Skip to content

Commit 44e1357

Browse files
Ben DavisallRisc
authored andcommitted
πŸ€– Improve documentation
πŸ€– Fix documentation typos in manifest reference πŸ€– Fix inconsistent field naming: use 'index' instead of 'registry' πŸ€– Add comprehensive documentation for the 'flist' field Added detailed documentation for the previously undocumented 'flist' field in the [package] section of the manifest format reference: - Added 'flist' to the field list in the overview πŸ€– Add validation to reject empty package names Added field validator to Package class to reject empty and whitespace-only package names. This improves validation and prevents invalid manifests. πŸ€– Clarify that the 'description' field is optional πŸ€– Fix authors field documentation Updated the authors field documentation to reflect all accepted formats: - Single string with optional email - List of strings - Dictionary with name and email πŸ€– Clarify optional dependencies format equivalence
1 parent f361ca8 commit 44e1357

4 files changed

Lines changed: 177 additions & 36 deletions

File tree

β€Ždocs/source/manifest_reference/manifest_format.rstβ€Ž

Lines changed: 143 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ The Manifest Format
44
===================
55

66
The `proj.toml` file within a package is called its *manifest* file.
7-
It is generally written i8n the `TOML <https://toml.io>`__ format.
7+
It is generally written in the `TOML <https://toml.io>`__ format.
88
Specifically, it currently supports `TOML v1.0.0 <https://toml.io/en/v1.0.0>`__.
99
It contains the metadata needed for inclusion of the package into a HDL/RTL project.
1010

@@ -14,13 +14,14 @@ Every manifest contains some of the following:
1414

1515
- :ref:`name <name_field>` - The name of the package
1616
- :ref:`version <version_field>` - The version of the package
17-
- :ref:`description <description_field>` - The description of the package
18-
- :ref:`authors <authors_field>` - The authors of the package
17+
- :ref:`description <description_field>` - (Optional) The description of the package
18+
- :ref:`authors <authors_field>` - (Optional) The authors of the package
1919
- :ref:`readme <readme_field>` - The readme of the package
20+
- :ref:`flist <flist_field>` - The file list of the package
2021

2122
- :ref:`[dependencies] <dependencies_section>`
2223
- :ref:`[optional_dependencies] <optional_dependencies_section>`
23-
- :ref:`[regsistries] <registries_section>`
24+
- :ref:`[registries] <registries_section>`
2425

2526

2627
.. _package_section:
@@ -38,6 +39,9 @@ The ``name`` field
3839
The package name is a unique identifier used to refer to the package.
3940
It is used when listed as a dependency in other manifests and as the default inferred name for certain other fields.
4041

42+
The name field is required and must be a non-empty string.
43+
Empty strings and whitespace-only strings are not allowed and will result in a validation error.
44+
4145

4246
.. _version_field:
4347

@@ -57,21 +61,69 @@ The ``description`` field
5761
The ``description`` is a short summary of the package.
5862
This field is treated as a plain-text string.
5963

64+
This field is optional.
65+
If not specified, it defaults to an empty string.
66+
However, providing a description is strongly recommended as it helps users understand the purpose and functionality of the package.
67+
68+
Example TOML with description:
69+
70+
.. code-block:: TOML
71+
72+
[package]
73+
name = "my-package"
74+
version = "1.0.0"
75+
description = "A package for HDL design and verification"
76+
77+
Example TOML without description (uses default empty string):
78+
79+
.. code-block:: TOML
80+
81+
[package]
82+
name = "my-package"
83+
version = "1.0.0"
84+
6085
6186
.. _authors_field:
6287

6388
The ``authors`` field
6489
^^^^^^^^^^^^^^^^^^^^^^
6590

66-
The ``authors`` of the package.
67-
This field is optional.
68-
If not specified, it defaults to not including any author information.
69-
This field can either be an array of strings, or an array of dictionaries.
91+
The ``authors`` field specifies the authors of the package.
92+
This field is optional. If not specified, no author information is included.
93+
94+
The ``authors`` field accepts several formats:
7095

71-
If the ``authors`` field is an array of strings, it is treated as a list.
72-
It is permissible to include the authors email within angled brackets at the end of the authors string.
96+
**Single string** (with optional email in angle brackets):
7397

74-
If the ``authors`` field is an array of dictionaries, it is treated as a list of authors where the valid keys are ``name`` and ``email``.
98+
.. code-block:: TOML
99+
100+
[package]
101+
authors = "John Doe"
102+
103+
# Or with email:
104+
authors = "John Doe <john.doe@example.com>"
105+
106+
**List of strings**:
107+
108+
.. code-block:: TOML
109+
110+
[package]
111+
authors = [
112+
"John Doe <john.doe@example.com>",
113+
"Jane Smith <jane.smith@example.com>"
114+
]
115+
116+
**Dictionary with name and email**:
117+
118+
.. code-block:: TOML
119+
120+
[package]
121+
authors = {name = "John Doe", email = "john.doe@example.com"}
122+
123+
# Email is optional:
124+
authors = {name = "John Doe"}
125+
126+
Choose the format that best suits your needs. For multiple authors, the list format is most readable.
75127

76128

77129
.. _readme_field:
@@ -85,6 +137,42 @@ If not specified, it defaults to not including any readme information.
85137
This field is relative to the location of the manifest file.
86138

87139

140+
.. _flist_field:
141+
142+
The ``flist`` field
143+
^^^^^^^^^^^^^^^^^^^
144+
145+
The ``flist`` field points to the relative location of the file list for the package.
146+
A file list contains the paths to all source files that should be included when this package is used as a dependency in another project.
147+
148+
This field is optional.
149+
If not specified, it defaults to ``<package-name>.f`` in the same directory as the manifest file.
150+
For example, if the package name is ``my-package``, the default file list would be ``my-package.f``.
151+
This field is relative to the location of the manifest file.
152+
153+
Example TOML with explicit file list:
154+
155+
.. code-block:: TOML
156+
157+
[package]
158+
name = "my-package"
159+
version = "1.0.0"
160+
description = "A sample package"
161+
flist = "rtl/sources.f"
162+
163+
Example TOML using the default file list (``my-package.f``):
164+
165+
.. code-block:: TOML
166+
167+
[package]
168+
name = "my-package"
169+
version = "1.0.0"
170+
description = "A sample package"
171+
172+
When a ``fastsandpm`` compatible package is used as a dependency, the specified file list is automatically included in the dependent project.
173+
For projects that do not specify an ``flist`` field, FastSandPM will look for a file named ``<package-name>.f`` at the root of the dependency directory.
174+
175+
88176
.. _dependencies_section:
89177

90178
The ``[dependencies]`` section
@@ -100,9 +188,9 @@ The dependencies section contains a group of :ref:`dependency specifiers <specif
100188
These are always brought in to the project.
101189
Additionally, if these point to projects with a ``fastsandpm`` manifest, their dependencies will also be brought in.
102190

103-
Once the dpendencies are resolved a filelist will be created.
104-
For ``fastsandpm`` compatible projects these will be included by pointing to the ``filelist`` field of the ``[package]`` section.
105-
Any other project will point to a filelist at the top of the dependency's directory with the same name as the dependency.
191+
Once the dependencies are resolved a file list will be created.
192+
For ``fastsandpm`` compatible projects, the file list is automatically included by pointing to the :ref:`flist <flist_field>` field of the ``[package]`` section.
193+
Any other project will use a file list located at the top of the dependency's directory with the same name as the dependency.
106194

107195
For example:
108196

@@ -128,31 +216,61 @@ For example:
128216

129217
.. code-block:: TOML
130218
131-
[optional_dependencies]
219+
[optional_dependencies]
132220
133-
uvm = [
134-
{name="uvm_utils", version="^1.0.0"},
135-
{name="improved_uvm_ral", version=">0.1.0", git="DCC_UVM"},
136-
]
221+
uvm = [
222+
{name="uvm_utils", version="^1.0.0"},
223+
{name="improved_uvm_ral", version=">0.1.0", git="DCC_UVM"},
224+
]
137225
138226
The above creates a UVM dependency group that contains the ``uvm_utils`` and ``improved_uvm_ral`` packages.
139227

140228
An alternative but equally valid way to write this TOML would be:
141229

142230
.. code-block:: TOML
143231
144-
[optional_dependencies.uvm]
232+
[optional_dependencies.uvm]
145233
146-
uvm_utils = "^1.0.0"
147-
improved_uvm_ral = {version=">0.1.0", git="DCC_UVM"}
234+
uvm_utils = "^1.0.0"
235+
improved_uvm_ral = {version=">0.1.0", git="DCC_UVM"}
236+
237+
238+
Format Equivalence
239+
^^^^^^^^^^^^^^^^^^
240+
241+
The two formats shown above are completely equivalent. Both create the same dependency group structure.
242+
Choose the format that is most readable for your use case:
243+
244+
- **List format** (``[optional_dependencies]`` with array): Better when copying dependency specifications or when dependencies have complex configurations
245+
- **Table format** (``[optional_dependencies.group]``): More concise and readable for simple version specifications
246+
247+
The following two specifications are identical:
248+
249+
.. code-block:: TOML
250+
251+
# List format
252+
[optional_dependencies]
253+
dev = [
254+
{name = "pytest", version = "^7.0.0"},
255+
{name = "mypy", version = "^1.0.0"}
256+
]
257+
258+
.. code-block:: TOML
259+
260+
# Table format (recommended for simple cases)
261+
[optional_dependencies.dev]
262+
pytest = "^7.0.0"
263+
mypy = "^1.0.0"
264+
265+
Choose whichever format makes your manifest more readable and maintainable for your project's needs.
148266

149267

150268
.. _registries_section:
151269

152-
The ``[registeries]`` section
270+
The ``[registries]`` section
153271
-----------------------------
154272

155-
Additional registeries can be specified in the ``[registries]`` section.
156-
A regsitry type exists for each :ref:`dependency specifier <specifying_dependencies>` type.
273+
Additional registries can be specified in the ``[registries]`` section.
274+
A registry type exists for each :ref:`dependency specifier <specifying_dependencies>` type.
157275

158276

β€Ždocs/source/manifest_reference/specifying_dependencies.rstβ€Ž

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,21 @@ For example you can specify a dependency named ``time`` and version ``1.0.0`` as
3131
time = "1.0.0"
3232
3333
The version string is a known as a :ref:`version specifier <version_specifier>`.
34-
These specifiers can be used to set a range of valid versions used for resolving dpendencies.
34+
These specifiers can be used to set a range of valid versions used for resolving dependencies.
3535

3636

3737
Dependencies from Other Registries
3838
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3939

4040
It is also possible to point to a different index using the ``index`` key in the dependency.
41-
For example you can specify a dependency named ``time`` and version ``1.0.0`` as follows:
41+
For example you can specify a dependency named ``time`` and version ``1.0.0`` from a custom registry as follows:
4242

4343
.. code-block:: TOML
4444
4545
[dependencies]
46-
time = {registry = "my-registry", version = "1.0.0"}
46+
time = {index = "my-registry", version = "1.0.0"}
4747
48-
The value of ``registry`` points to a regsiter definition from the ``[registries]`` section. of the manifest.
48+
The value of ``index`` points to a registry definition from the ``[registries]`` section of the manifest.
4949
See the :ref:`registries section documentation <registries_section>` for more information.
5050

5151

@@ -77,7 +77,7 @@ By default the upstream default branch will be used.
7777
.. note::
7878

7979
If when the dependencies are updated the existing local copy is dirty an error will be raised.
80-
A user of the library can force the update by setting the ``force_update`` flag to ``true`` or ignore the error by settign ``ignore_dirty`` to ``true``.
80+
A user of the library can force the update by setting the ``force_update`` flag to ``true`` or ignore the error by setting ``ignore_dirty`` to ``true``.
8181

8282

8383
Git Commit & Tag Specifiers

β€Žsrc/fastsandpm/manifest.pyβ€Ž

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
RootModel,
5959
ValidationError,
6060
WithJsonSchema,
61+
field_validator,
6162
model_validator,
6263
)
6364

@@ -140,6 +141,24 @@ class Package(BaseModel):
140141
readme: pathlib.Path | None = None # TODO: Field(default_factory=_find_readme)
141142
"""Path to the README file relative to manifest."""
142143

144+
@field_validator("name")
145+
@classmethod
146+
def validate_name_not_empty(cls, v: str) -> str:
147+
"""Validate that package name is not empty.
148+
149+
Args:
150+
v: The package name to validate.
151+
152+
Returns:
153+
The validated package name.
154+
155+
Raises:
156+
ValueError: If the name is empty or contains only whitespace.
157+
"""
158+
if not v or not v.strip():
159+
raise ValueError("Package name cannot be empty or whitespace-only")
160+
return v
161+
143162

144163
class Dependencies(RootModel[list[ConcreteRequirement]]):
145164
"""A collection of package dependencies.

β€Žtests/manifest/test_manifest_package.pyβ€Ž

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,17 @@ def test_name_with_numbers(self) -> None:
6262
package = Package(name="package123", version="1.0.0", description="A test package")
6363
assert package.name == "package123"
6464

65-
def test_name_accepts_empty_string(self) -> None:
66-
"""Test that name currently accepts an empty string.
65+
def test_name_rejects_empty_string(self) -> None:
66+
"""Test that name field rejects empty strings."""
67+
with pytest.raises(ValidationError) as exc_info:
68+
Package(name="", version="1.0.0", description="A test package")
69+
assert "cannot be empty" in str(exc_info.value).lower()
6770

68-
Note: This documents current behavior. Future validation may reject empty names.
69-
"""
70-
package = Package(name="", version="1.0.0", description="A test package")
71-
assert package.name == ""
71+
def test_name_rejects_whitespace_only(self) -> None:
72+
"""Test that name field rejects whitespace-only strings."""
73+
with pytest.raises(ValidationError) as exc_info:
74+
Package(name=" ", version="1.0.0", description="A test package")
75+
assert "cannot be empty" in str(exc_info.value).lower()
7276

7377

7478
class TestPackageVersion:

0 commit comments

Comments
Β (0)