diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index acbbfafb4..dcfefaf63 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,6 +27,9 @@ git commit --signoff Finally, make sure to sign your commits using a GPG key. See the instructions [here](https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key) for more information. A green `verified` label will appear next to your commit on GitHub if it is successfully signed. +### Style Guide + +See our [Macaron Style Guide](./docs/source/pages/developers_guide/style_guide.rst). ### Pull request process @@ -135,9 +138,9 @@ Ideally, the GitHub token must have **read** permissions for the repositories th After generating a GitHub personal-access token, please store its value in an environment variable called ``GITHUB_TOKEN``. This environment variable will be read by Macaron for its **analyze** command. -### Running checks and tests locally +## Running checks and tests locally -#### Git hooks +### Git hooks Using the pre-commit tool and its `.pre-commit-config.yaml` configuration, a number of [pre-commit hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_committing_workflow_hooks) ensure that your code is formatted correctly. @@ -156,7 +159,7 @@ make check runs _all_ installed git hooks over your code. For more control over the code checks, the Makefile also implements the `check-bandit`, `check-flake8`, `check-lint`, `check-mypy`, and `check-actionlint` goals. -#### Testing +### Testing This repository is set up to test either standalone or as a pre-push git hook. Tests are stored in the `tests/` folder, and you can run them manually like so: ```bash @@ -172,9 +175,9 @@ make integration-test Note that integration tests can take a long time to complete. Also the repositories that we clone for these tests will be stored under `output/` directory. If you do not remove/move this directory and run the pre-commit tool you might get errors. -#### Generating documentation +## Generating documentation -As mentioned above, all package code should make use of [Python docstrings](https://www.python.org/dev/peps/pep-0257/) in [reStructured text format](https://www.python.org/dev/peps/pep-0287/). Using these docstrings and the documentation template in the `docs/source/` folder, you can then generate proper documentation in different formats using the [Sphinx](https://github.com/sphinx-doc/sphinx/) tool: +As mentioned above, all package code should make use of [Python docstrings](https://www.python.org/dev/peps/pep-0257/) in [reStructured text format](https://www.python.org/dev/peps/pep-0287/) following [numpydoc style](https://numpydoc.readthedocs.io/en/latest/format.html) (with some exceptions - see our [style guide](https://oracle.github.io/pages/developers_guide/style_guide.html#docstrings)). Using these docstrings and the documentation template in the `docs/source/` folder, you can then generate proper documentation in different formats using the [Sphinx](https://github.com/sphinx-doc/sphinx/) tool: ```bash make docs diff --git a/Makefile b/Makefile index a0e13aad5..64393d76a 100644 --- a/Makefile +++ b/Makefile @@ -299,6 +299,15 @@ dist/$(PACKAGE_NAME)-$(PACKAGE_VERSION)-build-epoch.txt: docs: docs-clean $(MAKE) -C docs/ html +# Generate API reference pages in the documentation using `sphinx-apidoc`. +.PHONY: docs-api +docs-api: + sphinx-apidoc --no-toc --module-first --force --maxdepth 1 --output-dir docs/source/pages/developers_guide/apidoc/ src/ + +# Combine the two targets `docs-api` and `docs`: +# First generate API reference pages, then build the HTML documentation. +.PHONY: docs-full +docs-full: docs-api docs # Build the Docker image. The image name and tag are read from IMAGE_NAME and RELEASE_TAG # environment variables, respectively. By default "test" is used as the image tag. diff --git a/docs/README.md b/docs/README.md index aa224a250..640daa170 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,13 +16,26 @@ This command will build and generate the documentation into `docs/_build/html`. python3 -m http.server -d docs/_build/html ``` -## Extend the API reference. +## Extend the API reference -If you add a new module, make sure that it is added to the API reference. The API reference is generated using the [sphinx-apidoc](https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html) tool. +We use the [sphinx-apidoc](https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html) tool to generate API reference automatically from Python docstrings. See the [Docstring section in the Macaron Style Guide](https://oracle.github.io/pages/developers_guide/style_guide.html#docstrings) for how to write docstrings in Macaron. + +If you make a code change, make sure to regenerate the API reference by running (with the dev environment activated): + +``` +make docs-api +``` + +This command uses [sphinx-apidoc](https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html) to generate the API reference RST files into `docs/source/pages/developers_guide/apidoc/`. Make sure to check in these API reference RST files to the repository. + +You can then rebuild the whole HTML documentation with: -From within the root directory of Macaron, run (with the dev environment activated): ``` -sphinx-apidoc --no-toc --module-first --force --maxdepth 1 --output-dir docs/source/pages/apidoc/ src/ +make docs ``` -This command will generate the API reference RST files into `docs/source/pages/apidoc/`. Make sure to check in the changed source files to the repository. +In addition, instead of running `make docs-api` and `make docs` separately, you can combine the two commands by running: + +``` +make docs-full +``` diff --git a/docs/source/conf.py b/docs/source/conf.py index 8d08a2f03..99ade503a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -30,18 +30,21 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ - "sphinx.ext.napoleon", - "sphinx.ext.autodoc", - "sphinx.ext.autosectionlabel", - "sphinx_autodoc_typehints", - "numpydoc", - "sphinx_tabs.tabs", + "sphinx.ext.napoleon", # Support parsing numpydoc style docstrings + "sphinx.ext.autodoc", # Support generating API reference from docstrings + "sphinx.ext.autosectionlabel", # Support referencing sections using their titles + "sphinx.ext.intersphinx", # Support referencing external APIs + "sphinx_autodoc_typehints", # Resolve type annotations in docstrings + "numpydoc", # Support numpydoc style docstrings + "sphinx_tabs.tabs", # Support tabbed views in documentation ] autosectionlabel_prefix_document = True autosectionlabel_maxdepth = 2 autodoc_member_order = "bysource" numpydoc_show_class_members = False +intersphinx_mapping = {"python": ("https://docs.python.org/3", None)} + templates_path = ["_templates"] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".venv"] diff --git a/docs/source/index.rst b/docs/source/index.rst index 54cb5e964..87d1ea5c5 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -36,9 +36,9 @@ concrete rules that can be checked automatically. Macaron has a customizable che Getting started --------------- -To start with Macaron, see our :doc:`Installation ` and :doc:`Using ` pages. +To start with Macaron, see the :doc:`Installation ` and :doc:`Using ` pages. -For all services and technologies that Macaron supports, see our :doc:`Supported Technologies ` page. +For all services and technologies that Macaron supports, see the :doc:`Supported Technologies ` page. ------------------------- Current checks in Macaron @@ -106,4 +106,4 @@ intermediate representations as abstractions. Using such abstractions, Macaron i pages/output_files pages/cli_usage/index pages/supported_technologies/index - pages/apidoc/index + pages/developers_guide/index diff --git a/docs/source/pages/apidoc/index.rst b/docs/source/pages/developers_guide/apidoc/index.rst similarity index 77% rename from docs/source/pages/apidoc/index.rst rename to docs/source/pages/developers_guide/apidoc/index.rst index cd0a31db6..c20bc5064 100644 --- a/docs/source/pages/apidoc/index.rst +++ b/docs/source/pages/developers_guide/apidoc/index.rst @@ -1,9 +1,9 @@ .. Copyright (c) 2022 - 2023, Oracle and/or its affiliates. All rights reserved. .. Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. -=================== -Developer Reference -=================== +===================== +Macaron API Reference +===================== .. toctree:: :maxdepth: 1 diff --git a/docs/source/pages/apidoc/macaron.code_analyzer.rst b/docs/source/pages/developers_guide/apidoc/macaron.code_analyzer.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.code_analyzer.rst rename to docs/source/pages/developers_guide/apidoc/macaron.code_analyzer.rst diff --git a/docs/source/pages/apidoc/macaron.config.rst b/docs/source/pages/developers_guide/apidoc/macaron.config.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.config.rst rename to docs/source/pages/developers_guide/apidoc/macaron.config.rst diff --git a/docs/source/pages/apidoc/macaron.database.rst b/docs/source/pages/developers_guide/apidoc/macaron.database.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.database.rst rename to docs/source/pages/developers_guide/apidoc/macaron.database.rst diff --git a/docs/source/pages/apidoc/macaron.dependency_analyzer.rst b/docs/source/pages/developers_guide/apidoc/macaron.dependency_analyzer.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.dependency_analyzer.rst rename to docs/source/pages/developers_guide/apidoc/macaron.dependency_analyzer.rst diff --git a/docs/source/pages/apidoc/macaron.output_reporter.rst b/docs/source/pages/developers_guide/apidoc/macaron.output_reporter.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.output_reporter.rst rename to docs/source/pages/developers_guide/apidoc/macaron.output_reporter.rst diff --git a/docs/source/pages/apidoc/macaron.parsers.rst b/docs/source/pages/developers_guide/apidoc/macaron.parsers.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.parsers.rst rename to docs/source/pages/developers_guide/apidoc/macaron.parsers.rst diff --git a/docs/source/pages/apidoc/macaron.parsers.yaml.rst b/docs/source/pages/developers_guide/apidoc/macaron.parsers.yaml.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.parsers.yaml.rst rename to docs/source/pages/developers_guide/apidoc/macaron.parsers.yaml.rst diff --git a/docs/source/pages/apidoc/macaron.policy_engine.rst b/docs/source/pages/developers_guide/apidoc/macaron.policy_engine.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.policy_engine.rst rename to docs/source/pages/developers_guide/apidoc/macaron.policy_engine.rst diff --git a/docs/source/pages/apidoc/macaron.rst b/docs/source/pages/developers_guide/apidoc/macaron.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.rst rename to docs/source/pages/developers_guide/apidoc/macaron.rst diff --git a/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.asset.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.asset.rst new file mode 100644 index 000000000..507f0f5cf --- /dev/null +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.asset.rst @@ -0,0 +1,7 @@ +macaron.slsa\_analyzer.asset package +==================================== + +.. automodule:: macaron.slsa_analyzer.asset + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.build_tool.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.build_tool.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.build_tool.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.build_tool.rst diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.checks.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.checks.rst similarity index 90% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.checks.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.checks.rst index de52bdc4c..c059b397b 100644 --- a/docs/source/pages/apidoc/macaron.slsa_analyzer.checks.rst +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.checks.rst @@ -73,6 +73,14 @@ macaron.slsa\_analyzer.checks.provenance\_l3\_content\_check module :undoc-members: :show-inheritance: +macaron.slsa\_analyzer.checks.provenance\_witness\_l1\_check module +------------------------------------------------------------------- + +.. automodule:: macaron.slsa_analyzer.checks.provenance_witness_l1_check + :members: + :undoc-members: + :show-inheritance: + macaron.slsa\_analyzer.checks.trusted\_builder\_l3\_check module ---------------------------------------------------------------- diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.ci_service.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.ci_service.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.ci_service.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.ci_service.rst diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.git_service.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.git_service.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.git_service.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.git_service.rst diff --git a/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.package_registry.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.package_registry.rst new file mode 100644 index 000000000..86b11540b --- /dev/null +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.package_registry.rst @@ -0,0 +1,26 @@ +macaron.slsa\_analyzer.package\_registry package +================================================ + +.. automodule:: macaron.slsa_analyzer.package_registry + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +macaron.slsa\_analyzer.package\_registry.jfrog\_maven\_registry module +---------------------------------------------------------------------- + +.. automodule:: macaron.slsa_analyzer.package_registry.jfrog_maven_registry + :members: + :undoc-members: + :show-inheritance: + +macaron.slsa\_analyzer.package\_registry.package\_registry module +----------------------------------------------------------------- + +.. automodule:: macaron.slsa_analyzer.package_registry.package_registry + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.provenance.expectations.cue.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.expectations.cue.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.provenance.expectations.cue.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.expectations.cue.rst diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.provenance.expectations.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.expectations.rst similarity index 100% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.provenance.expectations.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.expectations.rst diff --git a/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.rst new file mode 100644 index 000000000..5f9e041a2 --- /dev/null +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.rst @@ -0,0 +1,27 @@ +macaron.slsa\_analyzer.provenance.intoto package +================================================ + +.. automodule:: macaron.slsa_analyzer.provenance.intoto + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 1 + + macaron.slsa_analyzer.provenance.intoto.v01 + macaron.slsa_analyzer.provenance.intoto.v1 + +Submodules +---------- + +macaron.slsa\_analyzer.provenance.intoto.errors module +------------------------------------------------------ + +.. automodule:: macaron.slsa_analyzer.provenance.intoto.errors + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.v01.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.v01.rst new file mode 100644 index 000000000..83a056c97 --- /dev/null +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.v01.rst @@ -0,0 +1,7 @@ +macaron.slsa\_analyzer.provenance.intoto.v01 package +==================================================== + +.. automodule:: macaron.slsa_analyzer.provenance.intoto.v01 + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.v1.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.v1.rst new file mode 100644 index 000000000..65f5f212a --- /dev/null +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.intoto.v1.rst @@ -0,0 +1,7 @@ +macaron.slsa\_analyzer.provenance.intoto.v1 package +=================================================== + +.. automodule:: macaron.slsa_analyzer.provenance.intoto.v1 + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.provenance.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.rst similarity index 63% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.provenance.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.rst index b7acbc0d3..d680bdb4e 100644 --- a/docs/source/pages/apidoc/macaron.slsa_analyzer.provenance.rst +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.rst @@ -13,6 +13,8 @@ Subpackages :maxdepth: 1 macaron.slsa_analyzer.provenance.expectations + macaron.slsa_analyzer.provenance.intoto + macaron.slsa_analyzer.provenance.witness Submodules ---------- @@ -24,3 +26,11 @@ macaron.slsa\_analyzer.provenance.loader module :members: :undoc-members: :show-inheritance: + +macaron.slsa\_analyzer.provenance.provenance module +--------------------------------------------------- + +.. automodule:: macaron.slsa_analyzer.provenance.provenance + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.witness.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.witness.rst new file mode 100644 index 000000000..5bb06f7c0 --- /dev/null +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.provenance.witness.rst @@ -0,0 +1,18 @@ +macaron.slsa\_analyzer.provenance.witness package +================================================= + +.. automodule:: macaron.slsa_analyzer.provenance.witness + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +macaron.slsa\_analyzer.provenance.witness.attestor module +--------------------------------------------------------- + +.. automodule:: macaron.slsa_analyzer.provenance.witness.attestor + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.rst similarity index 96% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.rst index 9abe3ebe2..36f0f88aa 100644 --- a/docs/source/pages/apidoc/macaron.slsa_analyzer.rst +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.rst @@ -12,10 +12,12 @@ Subpackages .. toctree:: :maxdepth: 1 + macaron.slsa_analyzer.asset macaron.slsa_analyzer.build_tool macaron.slsa_analyzer.checks macaron.slsa_analyzer.ci_service macaron.slsa_analyzer.git_service + macaron.slsa_analyzer.package_registry macaron.slsa_analyzer.provenance macaron.slsa_analyzer.specs diff --git a/docs/source/pages/apidoc/macaron.slsa_analyzer.specs.rst b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.specs.rst similarity index 77% rename from docs/source/pages/apidoc/macaron.slsa_analyzer.specs.rst rename to docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.specs.rst index d05ba5712..cb899e759 100644 --- a/docs/source/pages/apidoc/macaron.slsa_analyzer.specs.rst +++ b/docs/source/pages/developers_guide/apidoc/macaron.slsa_analyzer.specs.rst @@ -32,3 +32,11 @@ macaron.slsa\_analyzer.specs.inferred\_provenance module :members: :undoc-members: :show-inheritance: + +macaron.slsa\_analyzer.specs.package\_registry\_spec module +----------------------------------------------------------- + +.. automodule:: macaron.slsa_analyzer.specs.package_registry_spec + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pages/developers_guide/index.rst b/docs/source/pages/developers_guide/index.rst new file mode 100644 index 000000000..d82cebd88 --- /dev/null +++ b/docs/source/pages/developers_guide/index.rst @@ -0,0 +1,18 @@ +.. Copyright (c) 2023 - 2023, Oracle and/or its affiliates. All rights reserved. +.. Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. + +========================= +Macaron Developer's Guide +========================= + +To get started with contributing to Macaron, see the `CONTRIBUTING `_ page. + +To follow the project's code style, see the :doc:`Macaron Style Guide ` page. + +For API reference, see the :doc:`API Reference ` page. + +.. toctree:: + :maxdepth: 1 + + style_guide + apidoc/index diff --git a/docs/source/pages/developers_guide/style_guide.rst b/docs/source/pages/developers_guide/style_guide.rst new file mode 100644 index 000000000..1381f6ddb --- /dev/null +++ b/docs/source/pages/developers_guide/style_guide.rst @@ -0,0 +1,78 @@ +.. Copyright (c) 2023 - 2023, Oracle and/or its affiliates. All rights reserved. +.. Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. + +.. References/links +.. _sphinx-apidoc: https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html + +=================== +Macaron Style Guide +=================== + +Macaron makes use of different linters. These linters are managed using `pre-commit `_ hooks (see the `.pre-commit-config.yaml `_ file). Most styling issues should be caught by pre-commit hooks. However, there are some additional styling rules that we follow. + +-------------- +Python Modules +-------------- + +We ban the use of ``__all__`` in ``__init__.py`` files due to known issues with the `sphinx-apidoc`_ docstring generator. + +------ +Naming +------ + +We avoid using the same name for two or more classes in all cases (including cases where the two classes are in different modules), due to known issues with the `sphinx-apidoc`_ docstring generator. + + +---------- +Docstrings +---------- + +We use `sphinx-apidoc`_ to generate :doc:`API Reference ` automatically from `Python docstrings `_ written in the code. + +We follow the `numpydoc style `_ for Python docstrings (see `example `_) with some exceptions. + +'''''''''''''''''''''' +Docstrings for classes +'''''''''''''''''''''' + +Each class should have a docstring written in a triple-quoted block describing the purpose of the class. + +For variables of a class: we do not use the ``Attribute`` section as per the `numpydoc style for class docstring `_, due to some known issues with Sphinx. Instead, to document class variables, we follow the following convention: + +- For simple Python classes having an ``__init__`` constructor: We document the ``__init__`` constructor like any other regular method, i.e. all parameters should be documented. We do not document `instance variables `_ and consider them to be private to the class. To expose an instance variable of a class in the documentation, we use `Python property `_ and document the property methods (``getter``, ``setter``, and ``deleter`` methods) instead. Example: + + .. code-block:: python + + class Point2D: + """A point in the 2D coordinate system.""" + + def __init__(self, coordinate: tuple[float, float]) -> None: + """Construct a point in the 2D coordinate system. + + Parameters + ---------- + coordinate : tuple[float, float] + A pair of x and y coordinates. + """ + self._x = tuple[0] + self._y = tuple[1] + + @property + def x(self) -> float: + """Get the x coordinate of the point.""" + return self._x + +- For Python classes that declare instance variables in class attributes (e.g. :py:class:`typing.NamedTuple`, :py:func:`dataclasses.dataclass`, or `SQLAlchemy ORM Mapped classes `_): We document each instance variable with a comment above the variable prefixed with ``#:`` (if the comment spans more than one line, all lines must be prefixed with ``#:``). Example: + + .. code-block:: python + + from typing import NamedTuple + + + class Point2D(NamedTuple): + """A point in the 2D coordinate system.""" + + #: The x coordinate of the point. + x: float + #: The y coordinate of the point. + y: float diff --git a/src/macaron/slsa_analyzer/checks/provenance_l3_check.py b/src/macaron/slsa_analyzer/checks/provenance_l3_check.py index def379f0d..924c37e2a 100644 --- a/src/macaron/slsa_analyzer/checks/provenance_l3_check.py +++ b/src/macaron/slsa_analyzer/checks/provenance_l3_check.py @@ -225,7 +225,7 @@ def _validate_path_traversal(path: str) -> bool: def _find_asset( self, - subject: v01.InTotoSubject, + subject: v01.InTotoV01Subject, all_assets: list[dict[str, str]], temp_path: str, ci_service: BaseCIService, diff --git a/src/macaron/slsa_analyzer/checks/provenance_witness_l1_check.py b/src/macaron/slsa_analyzer/checks/provenance_witness_l1_check.py index 9dd7ec265..9aa29933c 100644 --- a/src/macaron/slsa_analyzer/checks/provenance_witness_l1_check.py +++ b/src/macaron/slsa_analyzer/checks/provenance_witness_l1_check.py @@ -13,7 +13,8 @@ from macaron.slsa_analyzer.analyze_context import AnalyzeContext from macaron.slsa_analyzer.checks.base_check import BaseCheck from macaron.slsa_analyzer.checks.check_result import CheckResult, CheckResultType -from macaron.slsa_analyzer.package_registry import JFrogMavenAsset, JFrogMavenRegistry +from macaron.slsa_analyzer.package_registry import JFrogMavenRegistry +from macaron.slsa_analyzer.package_registry.jfrog_maven_registry import JFrogMavenAsset from macaron.slsa_analyzer.provenance.witness import ( WitnessProvenanceSubject, extract_witness_provenance_subjects, diff --git a/src/macaron/slsa_analyzer/git_service/api_client.py b/src/macaron/slsa_analyzer/git_service/api_client.py index 65150ecbb..de90498b4 100644 --- a/src/macaron/slsa_analyzer/git_service/api_client.py +++ b/src/macaron/slsa_analyzer/git_service/api_client.py @@ -18,23 +18,15 @@ class GitHubReleaseAsset(NamedTuple): - """An asset published from a GitHub Release. - - Attributes - ---------- - name : str - The asset name. - url : str - The URL to the asset. - size_in_bytes : int - The size of the asset, in bytes. - api_client : GhAPIClient - The GitHub API client. - """ + """An asset published from a GitHub Release.""" + #: The asset name. name: str + #: The URL to the asset. url: str + #: The size of the asset, in bytes. size_in_bytes: int + #: The GitHub API client. api_client: GhAPIClient def download(self, dest: str) -> bool: diff --git a/src/macaron/slsa_analyzer/package_registry/__init__.py b/src/macaron/slsa_analyzer/package_registry/__init__.py index 070ae38bb..14dedf1a1 100644 --- a/src/macaron/slsa_analyzer/package_registry/__init__.py +++ b/src/macaron/slsa_analyzer/package_registry/__init__.py @@ -3,13 +3,7 @@ """This module defines the package registries.""" -from macaron.slsa_analyzer.package_registry.jfrog_maven_registry import JFrogMavenAsset, JFrogMavenRegistry +from macaron.slsa_analyzer.package_registry.jfrog_maven_registry import JFrogMavenRegistry from macaron.slsa_analyzer.package_registry.package_registry import PackageRegistry -__all__ = [ - "JFrogMavenAsset", - "JFrogMavenRegistry", - "PackageRegistry", -] - PACKAGE_REGISTRIES: list[PackageRegistry] = [JFrogMavenRegistry()] diff --git a/src/macaron/slsa_analyzer/package_registry/jfrog_maven_registry.py b/src/macaron/slsa_analyzer/package_registry/jfrog_maven_registry.py index a2009ac78..c00b69c02 100644 --- a/src/macaron/slsa_analyzer/package_registry/jfrog_maven_registry.py +++ b/src/macaron/slsa_analyzer/package_registry/jfrog_maven_registry.py @@ -24,29 +24,20 @@ class JFrogMavenAsset(NamedTuple): - """An asset hosted on a JFrog Artifactory repository with Maven layout. - - Attributes - ---------- - name : str - The name of the Maven asset. - group_id : str - The group id. - artifact_id : str - The artifact id. - version : str - The version of the Maven asset. - metadata : JFrogMavenAssetMetadata - The metadata of the JFrog Maven asset. - jfrog_maven_registry : JFrogMavenRegistry - The metadata of the JFrog Maven asset. - """ + """An asset hosted on a JFrog Artifactory repository with Maven layout.""" + #: The name of the Maven asset. name: str + #: The group id. group_id: str + #: The artifact id. artifact_id: str + #: The version of the Maven asset. version: str + #: The metadata of the JFrog Maven asset. metadata: JFrogMavenAssetMetadata + #: The JFrog repo that acts as a package registry following the + #: `Maven layout `_. jfrog_maven_registry: JFrogMavenRegistry @property @@ -85,20 +76,13 @@ def download(self, dest: str) -> bool: class JFrogMavenAssetMetadata(NamedTuple): - """Metadata of an asset on a JFrog Maven registry. - - Attributes - ---------- - size_in_bytes : int - The size of the asset (in bytes). - sha256_digest : str - The SHA256 digest of the asset. - download_uri : str - The download URI of the asset. - """ + """Metadata of an asset on a JFrog Maven registry.""" + #: The size of the asset (in bytes). size_in_bytes: int + #: The SHA256 digest of the asset. sha256_digest: str + #: The download URI of the asset. download_uri: str diff --git a/src/macaron/slsa_analyzer/provenance/intoto/__init__.py b/src/macaron/slsa_analyzer/provenance/intoto/__init__.py index d366a1351..bb1f196e6 100644 --- a/src/macaron/slsa_analyzer/provenance/intoto/__init__.py +++ b/src/macaron/slsa_analyzer/provenance/intoto/__init__.py @@ -13,11 +13,9 @@ from macaron.slsa_analyzer.provenance.intoto.errors import ValidateInTotoPayloadError from macaron.util import JsonType +# Type of an in-toto statement. +# This is currently either a v0.1 statement or v1 statement. StatementT = TypeVar("StatementT", bound=Mapping) -"""Type of an in-toto statement. - -This is currently either a v0.1 statement or v1 statement. -""" @dataclass(frozen=True) # objects of this class are immutable and hashable @@ -41,7 +39,7 @@ class InTotoPayload(Generic[StatementT]): statement: StatementT -class InTotoV01Payload(InTotoPayload[v01.InTotoStatement]): +class InTotoV01Payload(InTotoPayload[v01.InTotoV01Statement]): """The provenance payload following in-toto v0.1 schema. The payload is a field within a DSSE envelope, having the type "Statement". @@ -56,7 +54,7 @@ class InTotoV01Payload(InTotoPayload[v01.InTotoStatement]): """ -class InTotoV1Payload(InTotoPayload[v1.InTotoStatement]): +class InTotoV1Payload(InTotoPayload[v1.InTotoV1Statement]): """The provenance payload following in-toto v1 schema. The payload is a field within a DSSE envelope, having the type "Statement". diff --git a/src/macaron/slsa_analyzer/provenance/intoto/v01/__init__.py b/src/macaron/slsa_analyzer/provenance/intoto/v01/__init__.py index 11c9a961c..fc855e1da 100644 --- a/src/macaron/slsa_analyzer/provenance/intoto/v01/__init__.py +++ b/src/macaron/slsa_analyzer/provenance/intoto/v01/__init__.py @@ -11,7 +11,7 @@ from macaron.util import JsonType -class InTotoStatement(TypedDict): +class InTotoV01Statement(TypedDict): """An in-toto version 0.1 statement. This is the type of the payload in an in-toto version 0.1 attestation. @@ -19,12 +19,12 @@ class InTotoStatement(TypedDict): """ _type: str - subject: list[InTotoSubject] + subject: list[InTotoV01Subject] predicateType: str # noqa: N815 predicate: dict[str, JsonType] | None -class InTotoSubject(TypedDict): +class InTotoV01Subject(TypedDict): """An in-toto subject. Specification: https://github.com/in-toto/attestation/tree/main/spec/v0.1.0#statement. @@ -34,7 +34,7 @@ class InTotoSubject(TypedDict): digest: dict[str, str] -def validate_intoto_statement(payload: dict[str, JsonType]) -> TypeGuard[InTotoStatement]: +def validate_intoto_statement(payload: dict[str, JsonType]) -> TypeGuard[InTotoV01Statement]: """Validate the statement of an in-toto attestation. Specification: https://github.com/in-toto/attestation/tree/main/spec/v0.1.0#statement. @@ -102,7 +102,7 @@ def validate_intoto_statement(payload: dict[str, JsonType]) -> TypeGuard[InTotoS return True -def validate_intoto_subject(subject: JsonType) -> TypeGuard[InTotoSubject]: +def validate_intoto_subject(subject: JsonType) -> TypeGuard[InTotoV01Subject]: """Validate a single subject in the in-toto statement. See specification: https://github.com/in-toto/attestation/tree/main/spec/v0.1.0#statement. diff --git a/src/macaron/slsa_analyzer/provenance/intoto/v1/__init__.py b/src/macaron/slsa_analyzer/provenance/intoto/v1/__init__.py index 0ab4b9367..0f6d05eed 100644 --- a/src/macaron/slsa_analyzer/provenance/intoto/v1/__init__.py +++ b/src/macaron/slsa_analyzer/provenance/intoto/v1/__init__.py @@ -6,7 +6,7 @@ from typing import TypedDict -class InTotoStatement(TypedDict): +class InTotoV1Statement(TypedDict): """An in-toto version 1 statement. This is the type of the payload in a version 1 in-toto attestation. diff --git a/src/macaron/slsa_analyzer/provenance/witness/__init__.py b/src/macaron/slsa_analyzer/provenance/witness/__init__.py index 234d6f2a5..cbe1afe8e 100644 --- a/src/macaron/slsa_analyzer/provenance/witness/__init__.py +++ b/src/macaron/slsa_analyzer/provenance/witness/__init__.py @@ -15,34 +15,21 @@ class WitnessProvenanceData(NamedTuple): - """Data of a downloaded witness provenance. - - Attributes - ---------- - asset : AssetLocator - The provenance asset. - payload : InTotoPayload - The provenance payload. - """ + """Data of a downloaded witness provenance.""" + #: The provenance asset. asset: AssetLocator + #: The provenance payload. payload: InTotoPayload class WitnessVerifierConfig(NamedTuple): - """Configuration for verifying witness provenances. - - Attributes - ---------- - predicate_types : set[str] - A provenance payload is recognized by Macaron to be a witness provenance if its - ``predicateType`` value is present within this set. - artifact_extensions : set[str] - A set of artifact extensions to verify. Artifacts having an extension outside this list - are not verified. - """ + """Configuration for verifying witness provenances.""" + #: A provenance payload is recognized by Macaron to be a witness provenance if + #: its ``predicateType`` value is present within this set. predicate_types: set[str] + #: A set of artifact extensions to verify. Artifacts having an extension outside this list are not verified. artifact_extensions: set[str] @@ -95,17 +82,11 @@ def is_witness_provenance_payload( class WitnessProvenanceSubject(NamedTuple): - """A helper class to store elements of the ``subject`` list in the provenances. - - Attributes - ---------- - subject_name : str - The ``"name"`` field of each ``subject``. - sha256 : str - The SHA256 digest of the corresponding asset to the subject. - """ + """A helper class to store elements of the ``subject`` list in the provenances.""" + #: The ``"name"`` field of each ``subject``. subject_name: str + #: The SHA256 digest of the corresponding asset to the subject. sha256_digest: str @property diff --git a/src/macaron/slsa_analyzer/specs/inferred_provenance.py b/src/macaron/slsa_analyzer/specs/inferred_provenance.py index 7b0584c91..70baf5939 100644 --- a/src/macaron/slsa_analyzer/specs/inferred_provenance.py +++ b/src/macaron/slsa_analyzer/specs/inferred_provenance.py @@ -12,7 +12,7 @@ class Provenance: def __init__(self) -> None: """Initialize instance.""" - self.payload: v01.InTotoStatement = { + self.payload: v01.InTotoV01Statement = { "_type": "https://in-toto.io/Statement/v0.1", "subject": [], "predicateType": "https://slsa.dev/provenance/v0.2", diff --git a/src/macaron/slsa_analyzer/specs/package_registry_spec.py b/src/macaron/slsa_analyzer/specs/package_registry_spec.py index 770a6fb6a..110a02c3e 100644 --- a/src/macaron/slsa_analyzer/specs/package_registry_spec.py +++ b/src/macaron/slsa_analyzer/specs/package_registry_spec.py @@ -13,20 +13,11 @@ @dataclass class PackageRegistryInfo: - """This class contains data for one package registry that is matched against a repository. - - Attributes - ---------- - build_tool : BaseBuildTool - The build tool matched against the repository. - - package_registry : PackageRegistry - The package registry matched against the repository. This is dependent on the build tool detected. - - provenances : list[IsProvenance] - The provenances matched against the current repo. - """ + """This class contains data for one package registry that is matched against a repository.""" + #: The build tool matched against the repository. build_tool: BaseBuildTool + #: The package registry matched against the repository. This is dependent on the build tool detected. package_registry: PackageRegistry + #: The provenances matched against the current repo. provenances: list[DownloadedProvenanceData] = field(default_factory=list) diff --git a/tests/slsa_analyzer/provenance/test_witness_provenance.py b/tests/slsa_analyzer/provenance/test_witness_provenance.py index de718a482..901c8f1db 100644 --- a/tests/slsa_analyzer/provenance/test_witness_provenance.py +++ b/tests/slsa_analyzer/provenance/test_witness_provenance.py @@ -91,7 +91,7 @@ def test_load_witness_predicate_types( ], ) def test_is_witness_provenance_payload( - payload_json: v01.InTotoStatement, + payload_json: v01.InTotoV01Statement, predicate_types: set[str], expected_result: bool, ) -> None: @@ -172,7 +172,7 @@ def test_is_witness_provenance_payload( ], ) def test_extract_witness_provenances_subjects( - payload_json: v01.InTotoStatement, + payload_json: v01.InTotoV01Statement, expected_subjects: set[WitnessProvenanceSubject], ) -> None: """Test the ``extract_witness_provenance_subjects`` function."""