From 8239fd9508ccedd15a6e8c3a8183c7cff7e2e755 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 29 Nov 2025 16:42:54 +0100 Subject: [PATCH 01/53] Fix NameError & reformat everything --- src/griffe/_internal/extensions/base.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/griffe/_internal/extensions/base.py b/src/griffe/_internal/extensions/base.py index 8013bf806..1e243175e 100644 --- a/src/griffe/_internal/extensions/base.py +++ b/src/griffe/_internal/extensions/base.py @@ -22,7 +22,15 @@ from griffe._internal.agents.nodes.runtime import ObjectNode from griffe._internal.agents.visitor import Visitor from griffe._internal.loader import GriffeLoader - from griffe._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias + from griffe._internal.models import ( + Alias, + Attribute, + Class, + Function, + Module, + Object, + TypeAlias, + ) class Extension: @@ -603,7 +611,9 @@ def load_extensions(*exts: LoadableExtensionType) -> Extensions: # TODO: Deprecate and remove at some point? # Always add our built-in dataclasses extension. - from griffe._internal.extensions.dataclasses import DataclassesExtension # noqa: PLC0415 + from griffe._internal.extensions.dataclasses import ( + DataclassesExtension, + ) for ext in extensions._extensions: if type(ext) is DataclassesExtension: From 272cd112b99ce9ae3c6bbb25b3f3171cf64ed10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Sun, 30 Nov 2025 17:58:34 +0100 Subject: [PATCH 02/53] Apply suggestions from code review --- src/griffe/_internal/extensions/base.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/griffe/_internal/extensions/base.py b/src/griffe/_internal/extensions/base.py index 1e243175e..08cc8f64a 100644 --- a/src/griffe/_internal/extensions/base.py +++ b/src/griffe/_internal/extensions/base.py @@ -22,15 +22,7 @@ from griffe._internal.agents.nodes.runtime import ObjectNode from griffe._internal.agents.visitor import Visitor from griffe._internal.loader import GriffeLoader - from griffe._internal.models import ( - Alias, - Attribute, - Class, - Function, - Module, - Object, - TypeAlias, - ) + from griffe._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias class Extension: @@ -611,9 +603,7 @@ def load_extensions(*exts: LoadableExtensionType) -> Extensions: # TODO: Deprecate and remove at some point? # Always add our built-in dataclasses extension. - from griffe._internal.extensions.dataclasses import ( - DataclassesExtension, - ) + from griffe._internal.extensions.dataclasses import DataclassesExtension # noqa: PLC0415 for ext in extensions._extensions: if type(ext) is DataclassesExtension: From e9510841d53d68ce88c7fe9cfb4db570cc1abe7c Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 30 Nov 2025 20:54:16 +0100 Subject: [PATCH 03/53] Run migration script --- config/coverage.ini | 2 +- config/ruff.toml | 14 +- docs/extensions/built-in/dataclasses.md | 4 +- docs/extensions/built-in/unpack-typeddict.md | 4 +- docs/extensions/official/runtime-objects.md | 4 +- .../official/warnings-deprecated.md | 2 +- docs/guide/contributors/architecture.md | 10 +- docs/guide/users/checking.md | 100 +-- docs/guide/users/extending.md | 160 ++--- docs/guide/users/how-to/parse-docstrings.md | 2 +- .../guide/users/how-to/selectively-inspect.md | 46 +- .../users/how-to/set-docstring-styles.md | 12 +- docs/guide/users/how-to/set-git-info.md | 20 +- docs/guide/users/how-to/support-decorators.md | 14 +- docs/guide/users/loading.md | 74 +-- docs/guide/users/navigating.md | 210 +++--- .../users/recommendations/public-apis.md | 14 +- docs/guide/users/serializing.md | 18 +- docs/index.md | 10 +- docs/introduction.md | 22 +- docs/playground.md | 2 +- docs/reference/api/agents.md | 60 +- docs/reference/api/checks.md | 32 +- docs/reference/api/cli.md | 8 +- docs/reference/api/docstrings/models.md | 72 +-- docs/reference/api/docstrings/parsers.md | 36 +- docs/reference/api/exceptions.md | 26 +- docs/reference/api/expressions.md | 86 +-- docs/reference/api/extensions.md | 14 +- docs/reference/api/finder.md | 10 +- docs/reference/api/helpers.md | 20 +- docs/reference/api/loaders.md | 16 +- docs/reference/api/loggers.md | 12 +- docs/reference/api/models.md | 36 +- docs/reference/api/models/alias.md | 2 +- docs/reference/api/models/attribute.md | 2 +- docs/reference/api/models/class.md | 4 +- docs/reference/api/models/function.md | 12 +- docs/reference/api/models/module.md | 2 +- docs/reference/api/models/type_alias.md | 2 +- docs/reference/api/serializers.md | 6 +- docs/reference/docstrings.md | 2 +- docs/schema-docstrings-options.json | 6 +- docs/schema.json | 152 ++--- duties.py | 2 +- packages/griffecli/pyproject.toml | 48 ++ packages/griffecli/src/griffecli/__init__.py | 1 + packages/griffecli/src/griffecli/__main__.py | 13 + .../griffecli/src/griffecli}/_internal/cli.py | 38 +- packages/griffelib/pyproject.toml | 48 ++ packages/griffelib/src/griffelib/__init__.py | 607 +++++++++++++++++ .../src/griffelib}/_internal/__init__.py | 0 .../griffelib}/_internal/agents/__init__.py | 0 .../griffelib}/_internal/agents/inspector.py | 28 +- .../_internal/agents/nodes/__init__.py | 0 .../_internal/agents/nodes/assignments.py | 0 .../griffelib}/_internal/agents/nodes/ast.py | 2 +- .../_internal/agents/nodes/docstrings.py | 0 .../_internal/agents/nodes/exports.py | 10 +- .../_internal/agents/nodes/imports.py | 2 +- .../_internal/agents/nodes/parameters.py | 2 +- .../_internal/agents/nodes/runtime.py | 4 +- .../_internal/agents/nodes/values.py | 2 +- .../griffelib}/_internal/agents/visitor.py | 34 +- .../src/griffelib}/_internal/c3linear.py | 0 .../src/griffelib}/_internal/collections.py | 4 +- .../src/griffelib}/_internal/debug.py | 8 +- .../src/griffelib}/_internal/diff.py | 20 +- .../_internal/docstrings/__init__.py | 0 .../griffelib}/_internal/docstrings/auto.py | 20 +- .../griffelib}/_internal/docstrings/google.py | 10 +- .../griffelib}/_internal/docstrings/models.py | 6 +- .../griffelib}/_internal/docstrings/numpy.py | 12 +- .../_internal/docstrings/parsers.py | 14 +- .../griffelib}/_internal/docstrings/sphinx.py | 8 +- .../griffelib}/_internal/docstrings/utils.py | 12 +- .../src/griffelib}/_internal/encoders.py | 16 +- .../src/griffelib}/_internal/enumerations.py | 0 .../src/griffelib}/_internal/exceptions.py | 2 +- .../src/griffelib}/_internal/expressions.py | 14 +- .../_internal/extensions/__init__.py | 0 .../griffelib}/_internal/extensions/base.py | 20 +- .../_internal/extensions/dataclasses.py | 10 +- .../_internal/extensions/unpack_typeddict.py | 10 +- .../src/griffelib}/_internal/finder.py | 26 +- .../griffelib/src/griffelib}/_internal/git.py | 10 +- .../src/griffelib}/_internal/importer.py | 2 +- .../src/griffelib}/_internal/loader.py | 72 +-- .../src/griffelib}/_internal/logger.py | 10 +- .../src/griffelib}/_internal/merger.py | 6 +- .../src/griffelib}/_internal/mixins.py | 12 +- .../src/griffelib}/_internal/models.py | 462 ++++++------- .../src/griffelib}/_internal/py.typed | 0 .../src/griffelib}/_internal/stats.py | 6 +- .../src/griffelib}/_internal/tests.py | 18 +- pyproject.toml | 2 +- scripts/gen_griffe_json.py | 2 +- scripts/gen_structure_docs.py | 2 +- src/griffe/__init__.py | 611 +----------------- src/griffe/__main__.py | 9 +- tests/helpers.py | 2 +- tests/test_api.py | 50 +- tests/test_cli.py | 2 +- tests/test_docstrings/conftest.py | 2 +- tests/test_docstrings/test_google.py | 2 +- tests/test_docstrings/test_numpy.py | 2 +- tests/test_docstrings/test_sphinx.py | 2 +- tests/test_extensions/test_base.py | 2 +- tests/test_finder.py | 6 +- 109 files changed, 1910 insertions(+), 1799 deletions(-) create mode 100644 packages/griffecli/pyproject.toml create mode 100644 packages/griffecli/src/griffecli/__init__.py create mode 100644 packages/griffecli/src/griffecli/__main__.py rename {src/griffe => packages/griffecli/src/griffecli}/_internal/cli.py (94%) create mode 100644 packages/griffelib/pyproject.toml create mode 100644 packages/griffelib/src/griffelib/__init__.py rename {src/griffe => packages/griffelib/src/griffelib}/_internal/__init__.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/__init__.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/inspector.py (96%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/__init__.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/assignments.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/ast.py (98%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/docstrings.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/exports.py (91%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/imports.py (95%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/parameters.py (97%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/runtime.py (99%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/nodes/values.py (96%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/agents/visitor.py (96%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/c3linear.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/collections.py (94%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/debug.py (93%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/diff.py (97%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/docstrings/__init__.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/docstrings/auto.py (90%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/docstrings/google.py (99%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/docstrings/models.py (98%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/docstrings/numpy.py (98%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/docstrings/parsers.py (72%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/docstrings/sphinx.py (98%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/docstrings/utils.py (88%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/encoders.py (96%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/enumerations.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/exceptions.py (98%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/expressions.py (99%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/extensions/__init__.py (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/extensions/base.py (96%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/extensions/dataclasses.py (96%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/extensions/unpack_typeddict.py (96%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/finder.py (94%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/git.py (97%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/importer.py (98%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/loader.py (95%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/logger.py (92%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/merger.py (95%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/mixins.py (97%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/models.py (86%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/py.typed (100%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/stats.py (97%) rename {src/griffe => packages/griffelib/src/griffelib}/_internal/tests.py (96%) diff --git a/config/coverage.ini b/config/coverage.ini index 7db748bfd..6f57222a8 100644 --- a/config/coverage.ini +++ b/config/coverage.ini @@ -2,7 +2,7 @@ branch = true parallel = true source = - src/griffe + packages/griffe/src/griffe tests/ [coverage:paths] diff --git a/config/ruff.toml b/config/ruff.toml index 0a52cb729..7277e2d6f 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -35,27 +35,27 @@ ignore = [ "TRY003", # Avoid specifying long messages outside the exception class ] -logger-objects = ["griffe.logger"] +logger-objects = ["griffelib.logger"] [lint.per-file-ignores] -"src/griffe/__main__.py" = [ +"packages/griffe/src/griffe/__main__.py" = [ "D100", # Missing module docstring ] -"src/griffe/_internal/cli.py" = [ +"packages/griffe/src/griffe/_internal/cli.py" = [ "T201", # Print statement ] -"src/griffe/_internal/git.py" = [ +"packages/griffe/src/griffe/_internal/git.py" = [ "S603", # `subprocess` call: check for execution of untrusted input "S607", # Starting a process with a partial executable path ] -"src/griffe/_internal/agents/nodes/*.py" = [ +"packages/griffe/src/griffe/_internal/agents/nodes/*.py" = [ "ARG001", # Unused function argument "N812", # Lowercase `keyword` imported as non-lowercase `NodeKeyword` ] -"src/griffe/_internal/debug.py" = [ +"packages/griffe/src/griffe/_internal/debug.py" = [ "T201", # Print statement ] -"src/griffe/_internal/**.py" = [ +"packages/griffe/src/griffe/_internal/**.py" = [ "D100", # Missing docstring in public module ] "scripts/*.py" = [ diff --git a/docs/extensions/built-in/dataclasses.md b/docs/extensions/built-in/dataclasses.md index 24e72b70b..554a88f79 100644 --- a/docs/extensions/built-in/dataclasses.md +++ b/docs/extensions/built-in/dataclasses.md @@ -29,14 +29,14 @@ Additional metadata like `ClassVar`, the `init` and `kw_only` parameters, or the === "CLI" ```console - $ griffe dump -e dataclasses,other my_package + $ griffecli dump -e dataclasses,other my_package ``` === "Python" ```python import griffe - my_package = griffe.load("my_package", extensions=griffe.load_extensions("dataclasses", "other")) + my_package = griffelib.load("my_package", extensions=griffelib.load_extensions("dataclasses", "other")) ``` === "mkdocstrings" diff --git a/docs/extensions/built-in/unpack-typeddict.md b/docs/extensions/built-in/unpack-typeddict.md index d3dbca7ab..b7968a72f 100644 --- a/docs/extensions/built-in/unpack-typeddict.md +++ b/docs/extensions/built-in/unpack-typeddict.md @@ -65,14 +65,14 @@ To enable the extension: === "CLI" ```console - $ griffe dump -e unpack_typeddict my_package + $ griffecli dump -e unpack_typeddict my_package ``` === "Python" ```python import griffe - my_package = griffe.load("my_package", extensions=griffe.load_extensions("unpack_typeddict")) + my_package = griffelib.load("my_package", extensions=griffelib.load_extensions("unpack_typeddict")) ``` === "mkdocstrings" diff --git a/docs/extensions/official/runtime-objects.md b/docs/extensions/official/runtime-objects.md index fbfb72d34..c8c1d730e 100644 --- a/docs/extensions/official/runtime-objects.md +++ b/docs/extensions/official/runtime-objects.md @@ -11,11 +11,11 @@ This extension stores runtime objects corresponding to each loaded Griffe object ```pycon >>> import griffe ->>> griffe_data = griffe.load("griffe", extensions=griffe.load_extensions("griffe_runtime_objects"), resolve_aliases=True) +>>> griffe_data = griffelib.load("griffe", extensions=griffelib.load_extensions("griffe_runtime_objects"), resolve_aliases=True) >>> griffe_data["parse"].extra defaultdict(, {'runtime-objects': {'object': }}) >>> griffe_data["Module"].extra -defaultdict(, {'runtime-objects': {'object': }}) +defaultdict(, {'runtime-objects': {'object': }}) ``` It can be useful in combination with mkdocstrings-python and custom templates, to iterate over object values or their attributes that couldn't be loaded by Griffe itself (for example, objects built dynamically and loaded as attributes won't have "members" to iterate over). diff --git a/docs/extensions/official/warnings-deprecated.md b/docs/extensions/official/warnings-deprecated.md index 61ff9ddb2..10ea7f78b 100644 --- a/docs/extensions/official/warnings-deprecated.md +++ b/docs/extensions/official/warnings-deprecated.md @@ -7,7 +7,7 @@ --- -This extension adds support for functions and classes decorated with [`@warnings.deprecated(...)`][warnings.deprecated], as implemented thanks to [PEP 702](https://peps.python.org/pep-0702/). The message provided in the decorator call will be stored in the corresponding Griffe object's [`deprecated`][griffe.Object.deprecated] attribute (usable by downstream rendering templates), and will also add an admonition to the object's docstring with the provided message as text. +This extension adds support for functions and classes decorated with [`@warnings.deprecated(...)`][warnings.deprecated], as implemented thanks to [PEP 702](https://peps.python.org/pep-0702/). The message provided in the decorator call will be stored in the corresponding Griffe object's [`deprecated`][griffelib.Object.deprecated] attribute (usable by downstream rendering templates), and will also add an admonition to the object's docstring with the provided message as text. ```python from warnings import deprecated diff --git a/docs/guide/contributors/architecture.md b/docs/guide/contributors/architecture.md index edd5a94ec..1719a14f9 100644 --- a/docs/guide/contributors/architecture.md +++ b/docs/guide/contributors/architecture.md @@ -22,8 +22,8 @@ descriptions = { "scripts": "Our different scripts. See [Scripts, configuration](#scripts-configuration).", "site": "Documentation site, built with `make run mkdocs build` (git-ignored).", "src": "The source of our Python package(s). See [Sources](#sources) and [Program structure](#program-structure).", - "src/griffe": "Our public API, exposed to users. See [Program structure](#program-structure).", - "src/griffe/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).", + "packages/griffe/src/griffe": "Our public API, exposed to users. See [Program structure](#program-structure).", + "packages/griffe/src/griffe/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).", "tests": "Our test suite. See [Tests](#tests).", ".copier-answers.yml": "The answers file generated by [Copier](https://copier.readthedocs.io/en/stable/). See [Boilerplate](#boilerplate).", "devdeps.txt": "Our development dependencies specification. See [`make setup`][command-setup] command.", @@ -104,11 +104,11 @@ Sources are located in the `src` folder, following the [src-layout](https://pack Our test suite is located in the `tests` folder. It is located outside of the sources as to not pollute distributions (it would be very wrong to publish a `tests` package as part of our distributions, since this name is extremely common), or worse, the public API. The `tests` folder is however included in our source distributions (`.tar.gz`), alongside most of our metadata and configuration files. Check out `pyproject.toml` to get the full list of files included in our source distributions. -The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffe._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. +The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffelib._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. ## Program structure -The internal API is contained within the `src/griffe/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from various submodules of `griffe._internal`. +The internal API is contained within the `packages/griffe/src/griffe/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from various submodules of `griffelib._internal`. Users then import `griffe` directly, or import objects from it. @@ -122,7 +122,7 @@ if os.getenv("DEPLOY") == "true": from pydeps.target import Target cli.verbose = cli._not_verbose - options = cli.parse_args(["src/griffe", "--noshow", "--reverse"]) + options = cli.parse_args(["packages/griffe/src/griffe", "--noshow", "--reverse"]) colors.START_COLOR = 128 target = Target(options["fname"]) with target.chdir_work(): diff --git a/docs/guide/users/checking.md b/docs/guide/users/checking.md index 9594fafd5..85c9d9800 100644 --- a/docs/guide/users/checking.md +++ b/docs/guide/users/checking.md @@ -9,13 +9,13 @@ Griffe is able to compare two snapshots of your project to detect API breakages By default, Griffe will compare the current code to the latest tag: ```console -$ griffe check mypackage +$ griffecli check mypackage ``` To specify another Git reference to check against, use the `--against` or `-a` option: ```console -$ griffe check mypackage -a 0.2.0 +$ griffecli check mypackage -a 0.2.0 ``` You can specify a Git tag, commit (hash), or even a branch: Griffe will create a worktree at this reference in a temporary directory, and clean it up after finishing. @@ -23,24 +23,24 @@ You can specify a Git tag, commit (hash), or even a branch: Griffe will create a If you want to also specify the *base* reference to use (instead of the current code), use the `--base` or `-b` option. Some examples: ```console -$ griffe check mypackage -b HEAD -a 2.0.0 -$ griffe check mypackage -b 2.0.0 -a 1.0.0 -$ griffe check mypackage -b fix-issue-90 -a 1.2.3 -$ griffe check mypackage -b 8afcfd6e +$ griffecli check mypackage -b HEAD -a 2.0.0 +$ griffecli check mypackage -b 2.0.0 -a 1.0.0 +$ griffecli check mypackage -b fix-issue-90 -a 1.2.3 +$ griffecli check mypackage -b 8afcfd6e ``` TIP: **Important:** Remember that the base is the most recent reference, and the one we compare it against is the oldest one. -The package name you pass to `griffe check` must be found relative to the repository root. For Griffe to find packages in subfolders, pass the parent subfolder to the `--search` or `-s` option. Example for `src`-layouts: +The package name you pass to `griffecli check` must be found relative to the repository root. For Griffe to find packages in subfolders, pass the parent subfolder to the `--search` or `-s` option. Example for `src`-layouts: ```console -$ griffe check -s src griffe +$ griffecli check -s src griffe ``` Example in a monorepo, within a deeper file tree: ```console -$ griffe check -s back/services/identity-provider/src identity_provider +$ griffecli check -s back/services/identity-provider/src identity_provider ``` ### Using PyPI @@ -54,39 +54,39 @@ $ pip install griffe[pypi] The command syntax is: ```console -$ griffe check package_name -b project-name==2.0 -a project-name==1.0 +$ griffecli check package_name -b project-name==2.0 -a project-name==1.0 ``` You can let Griffe guess the package name by passing an empty string: ```console -$ griffe check "" -b project-name==2.0 -a project-name==1.0 +$ griffecli check "" -b project-name==2.0 -a project-name==1.0 ``` [PEP 508 version specifiers](https://peps.python.org/pep-0508/) are supported (`<`, `<=`, `!=`, `==`, `>=`, `>`, `~=`). For example, to compare v2 against the version just before it: ```console -$ griffe check "" -b project-name==2.0 -a project-name<2.0 +$ griffecli check "" -b project-name==2.0 -a project-name<2.0 ``` Without a version specifier on the base reference, or without a base reference at all, Griffe will use the latest available version. The two following commands compare the latest version against v1: ```console -$ griffe check "" -b project-name -a project-name==1.0 -$ griffe check "" -a project-name==1.0 +$ griffecli check "" -b project-name -a project-name==1.0 +$ griffecli check "" -a project-name==1.0 ``` Griffe will actually install packages in a cache directory. It means a few things: source distributions are supported, and only packages that are compatible with your current environment can be checked. ## Python API -To programmatically check for API breaking changes, you have to load two snapshots of your code base, for example using our [`load_git()`][griffe.load_git] utility, and then passing them both to the [`find_breaking_changes()`][griffe.find_breaking_changes] function. This function will yield instances of [`Breakage`][griffe.Breakage]. It's up to you how you want to use these breakage instances. +To programmatically check for API breaking changes, you have to load two snapshots of your code base, for example using our [`load_git()`][griffelib.load_git] utility, and then passing them both to the [`find_breaking_changes()`][griffelib.find_breaking_changes] function. This function will yield instances of [`Breakage`][griffelib.Breakage]. It's up to you how you want to use these breakage instances. ```python import griffe -my_pkg_v1 = griffe.load_git("my_pkg", ref="v1") -my_pkg_v2 = griffe.load_git("my_pkg", ref="v2") +my_pkg_v1 = griffelib.load_git("my_pkg", ref="v1") +my_pkg_v2 = griffelib.load_git("my_pkg", ref="v2") for breaking_change in find_breaking_changes(my_pkg_v1, my_pkg_v2): print(breaking_change.explain()) @@ -110,7 +110,7 @@ jobs: fetch-depth: 0 # We the need the full Git history. - uses: astral-sh/setup-uv@v6 # The following command will compare current changes to latest tag. - - run: uvx griffe check --search src --format github your_package_name + - run: uvx griffecli check --search src --format github your_package_name ``` The last step will fail the workflow if any breaking change is found. @@ -643,9 +643,9 @@ Griffe supports writing detected breakages in multiple formats, or styles. This is the default format. Griffe will print each detected breakage on a single line: -```console exec="1" source="console" result="ansi" returncode="1" id="griffe-check-oneline" +```console exec="1" source="console" result="ansi" returncode="1" id="griffecli-check-oneline" $ export FORCE_COLOR=1 # markdown-exec: hide -$ griffe check griffe -ssrc -b0.46.0 -a0.45.0 +$ griffecli check griffe -ssrc -b0.46.0 -a0.45.0 ``` [](){#format-verbose} @@ -655,11 +655,11 @@ $ griffe check griffe -ssrc -b0.46.0 -a0.45.0 - **CLI**: `-f verbose` / `-v` - **API**: `check(..., style="verbose")` / `check(..., style=ExplanationStyle.VERBOSE)` / `check(..., verbose=True)` -Depending on the detected breakages, the lines might be hard to read (being too compact), so `griffe check` also accepts a `--verbose` or `-v` option to add some space to the output: +Depending on the detected breakages, the lines might be hard to read (being too compact), so `griffecli check` also accepts a `--verbose` or `-v` option to add some space to the output: -```console exec="1" source="console" result="ansi" returncode="1" id="griffe-check-verbose" +```console exec="1" source="console" result="ansi" returncode="1" id="griffecli-check-verbose" $ export FORCE_COLOR=1 # markdown-exec: hide -$ griffe check griffe -ssrc -b0.46.0 -a0.45.0 --verbose +$ griffecli check griffe -ssrc -b0.46.0 -a0.45.0 --verbose ``` [](){#format-markdown} @@ -672,26 +672,26 @@ $ griffe check griffe -ssrc -b0.46.0 -a0.45.0 --verbose The Markdown format is adapted for changelogs. It doesn't show the file and line number, and instead prints out the complete path of your API objects. With a bit of automation, you will be able to automatically insert a summary of breaking changes in your changelog entries. ```md exec="1" source="tabbed-left" tabs="Output|Result" -- `griffe.loader.GriffeLoader.resolve_aliases(only_exported)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.loader.GriffeLoader.resolve_aliases(only_exported)`: *Parameter default was changed*: `True` -> `None` -- `griffe.loader.GriffeLoader.resolve_aliases(only_known_modules)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.loader.GriffeLoader.resolve_aliases(only_known_modules)`: *Parameter default was changed*: `True` -> `None` -- `griffe.loader.GriffeLoader.resolve_aliases(max_iterations)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.loader.GriffeLoader.resolve_module_aliases(only_exported)`: *Parameter was removed* -- `griffe.loader.GriffeLoader.resolve_module_aliases(only_known_modules)`: *Parameter was removed* -- `griffe.git.tmp_worktree(commit)`: *Parameter was removed* -- `griffe.git.tmp_worktree(repo)`: *Positional parameter was moved*: position: from 2 to 1 (-1) -- `griffe.git.load_git(commit)`: *Parameter was removed* -- `griffe.git.load_git(repo)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.git.load_git(submodules)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.git.load_git(try_relative_path)`: *Parameter was removed* -- `griffe.git.load_git(extensions)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.git.load_git(search_paths)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.git.load_git(docstring_parser)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.git.load_git(docstring_options)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.git.load_git(lines_collection)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.git.load_git(modules_collection)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffe.git.load_git(allow_inspection)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.loader.GriffeLoader.resolve_aliases(only_exported)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.loader.GriffeLoader.resolve_aliases(only_exported)`: *Parameter default was changed*: `True` -> `None` +- `griffelib.loader.GriffeLoader.resolve_aliases(only_known_modules)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.loader.GriffeLoader.resolve_aliases(only_known_modules)`: *Parameter default was changed*: `True` -> `None` +- `griffelib.loader.GriffeLoader.resolve_aliases(max_iterations)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.loader.GriffeLoader.resolve_module_aliases(only_exported)`: *Parameter was removed* +- `griffelib.loader.GriffeLoader.resolve_module_aliases(only_known_modules)`: *Parameter was removed* +- `griffelib.git.tmp_worktree(commit)`: *Parameter was removed* +- `griffelib.git.tmp_worktree(repo)`: *Positional parameter was moved*: position: from 2 to 1 (-1) +- `griffelib.git.load_git(commit)`: *Parameter was removed* +- `griffelib.git.load_git(repo)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.git.load_git(submodules)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.git.load_git(try_relative_path)`: *Parameter was removed* +- `griffelib.git.load_git(extensions)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.git.load_git(search_paths)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.git.load_git(docstring_parser)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.git.load_git(docstring_options)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.git.load_git(lines_collection)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.git.load_git(modules_collection)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffelib.git.load_git(allow_inspection)`: *Parameter kind was changed*: positional or keyword -> keyword-only ``` [](){#format-github} @@ -701,7 +701,7 @@ The Markdown format is adapted for changelogs. It doesn't show the file and line - **CLI**: `-f github` - **API**: `check(..., style="github")` / `check(..., style=ExplanationStyle.GITHUB)` -When running `griffe check` in CI, you can enable GitHub's annotations thanks to the GitHub output style. Annotations are displayed on specific lines of code. They are visible in the Checks tab. When you create an annotation for a file that is part of the pull request, the annotations are also shown in the Files changed tab. +When running `griffecli check` in CI, you can enable GitHub's annotations thanks to the GitHub output style. Annotations are displayed on specific lines of code. They are visible in the Checks tab. When you create an annotation for a file that is part of the pull request, the annotations are also shown in the Files changed tab. /// tab | Files changed tab ![gha_annotations_2](../../img/gha_annotations_2.png) @@ -712,12 +712,12 @@ When running `griffe check` in CI, you can enable GitHub's annotations thanks to /// ```console -% python -m griffe check -fgithub -ssrc griffe -::warning file=src/griffe/finder.py,line=58,title=Package.name::Attribute value was changed: `name` -> unset -::warning file=src/griffe/finder.py,line=60,title=Package.path::Attribute value was changed: `path` -> unset -::warning file=src/griffe/finder.py,line=62,title=Package.stubs::Attribute value was changed: `stubs` -> `None` -::warning file=src/griffe/finder.py,line=75,title=NamespacePackage.name::Attribute value was changed: `name` -> unset -::warning file=src/griffe/finder.py,line=77,title=NamespacePackage.path::Attribute value was changed: `path` -> unset +% python -m griffecli check -fgithub -ssrc griffe +::warning file=packages/griffe/src/griffe/finder.py,line=58,title=Package.name::Attribute value was changed: `name` -> unset +::warning file=packages/griffe/src/griffe/finder.py,line=60,title=Package.path::Attribute value was changed: `path` -> unset +::warning file=packages/griffe/src/griffe/finder.py,line=62,title=Package.stubs::Attribute value was changed: `stubs` -> `None` +::warning file=packages/griffe/src/griffe/finder.py,line=75,title=NamespacePackage.name::Attribute value was changed: `name` -> unset +::warning file=packages/griffe/src/griffe/finder.py,line=77,title=NamespacePackage.path::Attribute value was changed: `path` -> unset ``` ## Next steps diff --git a/docs/guide/users/extending.md b/docs/guide/users/extending.md index 9aa408731..1f9dd1917 100644 --- a/docs/guide/users/extending.md +++ b/docs/guide/users/extending.md @@ -28,11 +28,11 @@ To specify options in the JSON form, use a dictionary instead of a string: the d Some examples: ```bash -griffe dump griffe -e pydantic,scripts/exts.py:DynamicDocstrings,griffe_attrs +griffecli dump griffe -e pydantic,scripts/exts.py:DynamicDocstrings,griffe_attrs ``` ```bash -griffe check --search src griffe -e '[ +griffecli check --search src griffe -e '[ {"pydantic": {"schema": true}}, { "scripts/exts.py:DynamicDocstrings": { @@ -47,9 +47,9 @@ In the above two examples, `pydantic` would be a built-in extension, `scripts/ex ### Programmatically -Within Python code, extensions can be specified with the `extensions` parameter of the [`GriffeLoader` class][griffe.GriffeLoader] or [`load` function][griffe.load]. +Within Python code, extensions can be specified with the `extensions` parameter of the [`GriffeLoader` class][griffelib.GriffeLoader] or [`load` function][griffelib.load]. -The parameter accepts an instance of the [`Extensions` class][griffe.Extensions]. Such an instance is created with the help of the [`load_extensions` function][griffe.load_extensions], which itself accepts a list of strings, dictionaries, extension classes and extension instances. +The parameter accepts an instance of the [`Extensions` class][griffelib.Extensions]. Such an instance is created with the help of the [`load_extensions` function][griffelib.load_extensions], which itself accepts a list of strings, dictionaries, extension classes and extension instances. Strings and dictionaries are used the same way as [on the command-line](#on-the-command-line). Extension instances are used as such, and extension classes are instantiated without any options. @@ -60,7 +60,7 @@ import griffe from mypackage.extensions import ThisExtension, ThisOtherExtension -extensions = griffe.load_extensions( +extensions = griffelib.load_extensions( {"pydantic": {"schema": true}}, {"scripts/exts.py:DynamicDocstrings": {"paths": ["mypkg.mymod.myobj"]}}, "griffe_attrs", @@ -68,7 +68,7 @@ extensions = griffe.load_extensions( ThisOtherExtension, ) -data = griffe.load("mypackage", extensions=extensions) +data = griffelib.load("mypackage", extensions=extensions) ``` ### In MkDocs @@ -88,7 +88,7 @@ plugins: - griffe_attrs ``` -The `extensions` key accepts a list that is passed to the [`load_extensions` function][griffe.load_extensions]. See [how to use extensions programmatically](#programmatically) to learn more. +The `extensions` key accepts a list that is passed to the [`load_extensions` function][griffelib.load_extensions]. See [how to use extensions programmatically](#programmatically) to learn more. ## Writing extensions @@ -100,9 +100,9 @@ To extract information from your Python sources, Griffe tries to build Abstract If the source code is not available (the modules are built-in or compiled), Griffe imports the modules and builds object trees instead. -Griffe then follows the [Visitor pattern](https://www.wikiwand.com/en/Visitor_pattern) to walk the tree and extract information. For ASTs, Griffe uses its [Visitor agent][griffe.Visitor] and for object trees, it uses its [Inspector agent][griffe.Inspector]. +Griffe then follows the [Visitor pattern](https://www.wikiwand.com/en/Visitor_pattern) to walk the tree and extract information. For ASTs, Griffe uses its [Visitor agent][griffelib.Visitor] and for object trees, it uses its [Inspector agent][griffelib.Inspector]. -Sometimes during the walk through the source or runtime objects, both the visitor and inspector agents will trigger events, called **analysis events**. These events can be hooked on by extensions to alter or enhance Griffe's behavior. Some hooks will be passed just the current node being visited, others will be passed both the node and an instance of an [Object][griffe.Object] subclass, such as a [Module][griffe.Module], a [Class][griffe.Class], a [Function][griffe.Function], an [Attribute][griffe.Attribute], or a [Type Alias][griffe.TypeAlias]. Extensions will therefore be able to modify these instances. +Sometimes during the walk through the source or runtime objects, both the visitor and inspector agents will trigger events, called **analysis events**. These events can be hooked on by extensions to alter or enhance Griffe's behavior. Some hooks will be passed just the current node being visited, others will be passed both the node and an instance of an [Object][griffelib.Object] subclass, such as a [Module][griffelib.Module], a [Class][griffelib.Class], a [Function][griffelib.Function], an [Attribute][griffelib.Attribute], or a [Type Alias][griffelib.TypeAlias]. Extensions will therefore be able to modify these instances. Once the Griffe tree for a given package has been fully constructed, Griffe will trigger a second set of events, called **load events**, by walking the tree again. **It is safer to use load events as they are triggered only once data is complete for a given package**, contrary to the analysis events which are triggered *while the Griffe tree is still being built*. @@ -114,7 +114,7 @@ M(Module definition) --- C(Class definition) & F(Function definition) C --- m(Function definition) & A(Variable assignment) ``` -The following flow chart shows an example of an object tree inspection. The tree is simplified as well: [many more types of objects are handled][griffe.ObjectKind]. +The following flow chart shows an example of an object tree inspection. The tree is simplified as well: [many more types of objects are handled][griffelib.ObjectKind]. ```mermaid flowchart TB @@ -125,9 +125,9 @@ C --- m(Method) & A(Attribute) For a more concrete example, let say that we visit (or inspect) an AST (or object tree) for a given module, and that this module contains a single class, which itself contains a single method: - the agent (visitor or inspector) will walk through the tree by starting with the module node -- it will instantiate a [Module][griffe.Module], then walk through its members, continuing with the class node -- it will instantiate a [Class][griffe.Class], then walk through its members, continuing with the function node -- it will instantiate a [Function][griffe.Function] +- it will instantiate a [Module][griffelib.Module], then walk through its members, continuing with the class node +- it will instantiate a [Class][griffelib.Class], then walk through its members, continuing with the function node +- it will instantiate a [Function][griffelib.Function] - then it will go back up and finish walking since there are no more nodes to walk through Every time the agent enters a node, creates an object instance, or finishes handling members of an object, it will trigger an event. @@ -137,21 +137,21 @@ The flow of events is drawn in the following flowchart: ```mermaid flowchart TB visit_mod{{enter module node}} -event_mod_node{{"on_node event
on_module_node event"}} +event_mod_node{{"on_node event
on_module_node event"}} create_mod{{create module instance}} -event_mod_instance{{"on_instance event
on_module_instance event"}} +event_mod_instance{{"on_instance event
on_module_instance event"}} visit_mod_members{{visit module members}} visit_cls{{enter class node}} -event_cls_node{{"on_node event
on_class_node event"}} +event_cls_node{{"on_node event
on_class_node event"}} create_cls{{create class instance}} -event_cls_instance{{"on_instance event
on_class_instance event"}} +event_cls_instance{{"on_instance event
on_class_instance event"}} visit_cls_members{{visit class members}} visit_func{{enter func node}} -event_func_node{{"on_node event
on_function_node event"}} +event_func_node{{"on_node event
on_function_node event"}} create_func{{create function instance}} -event_func_instance{{"on_instance event
on_function_instance event"}} -event_cls_members{{"on_members event
on_class_members event"}} -event_mod_members{{"on_members event
on_module_members event"}} +event_func_instance{{"on_instance event
on_function_instance event"}} +event_cls_members{{"on_members event
on_class_members event"}} +event_mod_members{{"on_members event
on_module_members event"}} start{start} --> visit_mod visit_mod --> event_mod_node @@ -198,17 +198,17 @@ There are two kinds of events in Griffe: [**load events**](#load-events) and [** There is 1 generic **load event**: -- [`on_object`][griffe.Extension.on_object]: The "on object" event is triggered on any kind of object (except for aliases and packages, so modules, classes, functions, attributes and type aliases), once the tree for the object's package has been fully constructed. +- [`on_object`][griffelib.Extension.on_object]: The "on object" event is triggered on any kind of object (except for aliases and packages, so modules, classes, functions, attributes and type aliases), once the tree for the object's package has been fully constructed. There are also specific **load events** for each object kind: -- [`on_module`][griffe.Extension.on_module]: The "on module" event is triggered on modules. -- [`on_class`][griffe.Extension.on_class]: The "on class" event is triggered on classes. -- [`on_function`][griffe.Extension.on_function]: The "on function" event is triggered on functions. -- [`on_attribute`][griffe.Extension.on_attribute]: The "on attribute" event is triggered on attributes. -- [`on_type_alias`][griffe.Extension.on_type_alias]: The "on type alias" event is triggered on type aliases. -- [`on_alias`][griffe.Extension.on_alias]: The "on alias" event is triggered on aliases (imported/inherited objects). -- [`on_package`][griffe.Extension.on_package]: The "on package" event is triggered on top-level modules (packages) only. +- [`on_module`][griffelib.Extension.on_module]: The "on module" event is triggered on modules. +- [`on_class`][griffelib.Extension.on_class]: The "on class" event is triggered on classes. +- [`on_function`][griffelib.Extension.on_function]: The "on function" event is triggered on functions. +- [`on_attribute`][griffelib.Extension.on_attribute]: The "on attribute" event is triggered on attributes. +- [`on_type_alias`][griffelib.Extension.on_type_alias]: The "on type alias" event is triggered on type aliases. +- [`on_alias`][griffelib.Extension.on_alias]: The "on alias" event is triggered on aliases (imported/inherited objects). +- [`on_package`][griffelib.Extension.on_package]: The "on package" event is triggered on top-level modules (packages) only. #### Analysis events @@ -216,46 +216,46 @@ There are also specific **load events** for each object kind: There are 3 generic **analysis events**: -- [`on_node`][griffe.Extension.on_node]: The "on node" events are triggered when the agent (visitor or inspector) starts handling a node in the tree (AST or object tree). -- [`on_instance`][griffe.Extension.on_instance]: The "on instance" events are triggered when the agent just created an instance of [Module][griffe.Module], [Class][griffe.Class], [Function][griffe.Function], [Attribute][griffe.Attribute], or [Type Alias][griffe.TypeAlias], and added it as a member of its parent. The "on instance" event is **not** triggered when an [Alias][griffe.Alias] is created. -- [`on_members`][griffe.Extension.on_members]: The "on members" events are triggered when the agent just finished handling all the members of an object. Functions, attributes and type aliases do not have members, so there are no "on members" events for these kinds. +- [`on_node`][griffelib.Extension.on_node]: The "on node" events are triggered when the agent (visitor or inspector) starts handling a node in the tree (AST or object tree). +- [`on_instance`][griffelib.Extension.on_instance]: The "on instance" events are triggered when the agent just created an instance of [Module][griffelib.Module], [Class][griffelib.Class], [Function][griffelib.Function], [Attribute][griffelib.Attribute], or [Type Alias][griffelib.TypeAlias], and added it as a member of its parent. The "on instance" event is **not** triggered when an [Alias][griffelib.Alias] is created. +- [`on_members`][griffelib.Extension.on_members]: The "on members" events are triggered when the agent just finished handling all the members of an object. Functions, attributes and type aliases do not have members, so there are no "on members" events for these kinds. There are also specific **analysis events** for each object kind: -- [`on_module_node`][griffe.Extension.on_module_node] -- [`on_module_instance`][griffe.Extension.on_module_instance] -- [`on_module_members`][griffe.Extension.on_module_members] -- [`on_class_node`][griffe.Extension.on_class_node] -- [`on_class_instance`][griffe.Extension.on_class_instance] -- [`on_class_members`][griffe.Extension.on_class_members] -- [`on_function_node`][griffe.Extension.on_function_node] -- [`on_function_instance`][griffe.Extension.on_function_instance] -- [`on_attribute_node`][griffe.Extension.on_attribute_node] -- [`on_attribute_instance`][griffe.Extension.on_attribute_instance] -- [`on_type_alias_node`][griffe.Extension.on_type_alias_node] -- [`on_type_alias_instance`][griffe.Extension.on_type_alias_instance] -- [`on_alias_instance`][griffe.Extension.on_alias_instance] +- [`on_module_node`][griffelib.Extension.on_module_node] +- [`on_module_instance`][griffelib.Extension.on_module_instance] +- [`on_module_members`][griffelib.Extension.on_module_members] +- [`on_class_node`][griffelib.Extension.on_class_node] +- [`on_class_instance`][griffelib.Extension.on_class_instance] +- [`on_class_members`][griffelib.Extension.on_class_members] +- [`on_function_node`][griffelib.Extension.on_function_node] +- [`on_function_instance`][griffelib.Extension.on_function_instance] +- [`on_attribute_node`][griffelib.Extension.on_attribute_node] +- [`on_attribute_instance`][griffelib.Extension.on_attribute_instance] +- [`on_type_alias_node`][griffelib.Extension.on_type_alias_node] +- [`on_type_alias_instance`][griffelib.Extension.on_type_alias_instance] +- [`on_alias_instance`][griffelib.Extension.on_alias_instance] #### Extensions and hooks -**Extensions** are classes that inherit from [Griffe's Extension base class][griffe.Extension] and define some hooks as methods: +**Extensions** are classes that inherit from [Griffe's Extension base class][griffelib.Extension] and define some hooks as methods: ```python import griffe -class MyExtension(griffe.Extension): +class MyExtension(griffelib.Extension): def on_object( self, *, - obj: griffe.Object, - loader: griffe.GriffeLoader, + obj: griffelib.Object, + loader: griffelib.GriffeLoader, **kwargs, ) -> None: """Do something with `obj`.""" ``` -Hooks are always defined as methods of a class inheriting from [Extension][griffe.Extension], never as standalone functions. IDEs should autocomplete the signature when you start typing `def` followed by a hook name. +Hooks are always defined as methods of a class inheriting from [Extension][griffelib.Extension], never as standalone functions. IDEs should autocomplete the signature when you start typing `def` followed by a hook name. Since hooks are declared in a class, feel free to also declare state variables (or any other variable) in the `__init__` method: @@ -273,8 +273,8 @@ class MyExtension(Extension): def on_object( self, *, - obj: griffe.Object, - loader: griffe.GriffeLoader, + obj: griffelib.Object, + loader: griffelib.GriffeLoader, **kwargs, ) -> None: """Do something with `obj`.""" @@ -292,8 +292,8 @@ To support static analysis, dynamic analysis, or both in your load events, you c import griffe -class MyExtension(griffe.Extension): - def on_object(self, *, obj: griffe.Object, **kwargs) -> None: +class MyExtension(griffelib.Extension): + def on_object(self, *, obj: griffelib.Object, **kwargs) -> None: """Do something with `obj`.""" if obj.analysis == "static": ... # Apply logic for static analysis. @@ -307,10 +307,10 @@ class MyExtension(griffe.Extension): Extensions provide basic functionality to help you visit trees during analysis of the code: -- [`visit`][griffe.Extension.visit]: call `self.visit(node)` to start visiting an abstract syntax tree. -- [`generic_visit`][griffe.Extension.generic_visit]: call `self.generic_visit(node)` to visit each subnode of a given node. -- [`inspect`][griffe.Extension.inspect]: call `self.inspect(node)` to start visiting an object tree. Nodes contain references to the runtime objects, see [`ObjectNode`][griffe.ObjectNode]. -- [`generic_inspect`][griffe.Extension.generic_inspect]: call `self.generic_inspect(node)` to visit each subnode of a given node. +- [`visit`][griffelib.Extension.visit]: call `self.visit(node)` to start visiting an abstract syntax tree. +- [`generic_visit`][griffelib.Extension.generic_visit]: call `self.generic_visit(node)` to visit each subnode of a given node. +- [`inspect`][griffelib.Extension.inspect]: call `self.inspect(node)` to start visiting an object tree. Nodes contain references to the runtime objects, see [`ObjectNode`][griffelib.ObjectNode]. +- [`generic_inspect`][griffelib.Extension.generic_inspect]: call `self.generic_inspect(node)` to visit each subnode of a given node. Calling `self.visit(node)` or `self.inspect(node)` will do nothing unless you actually implement methods that handle specific types of nodes: @@ -333,7 +333,7 @@ Calling `self.visit(node)` or `self.inspect(node)` will do nothing unless you ac See the [list of existing AST classes](#ast-nodes) to learn what method you can implement. -- for object trees, methods must be named `inspect_`, where `` is replaced with the string value of the node's kind. The different kinds are listed in the [`ObjectKind`][griffe.ObjectKind] enumeration. For example, to allow inspecting coroutine nodes, you must implement the `inspect_coroutine` method: +- for object trees, methods must be named `inspect_`, where `` is replaced with the string value of the node's kind. The different kinds are listed in the [`ObjectKind`][griffelib.ObjectKind] enumeration. For example, to allow inspecting coroutine nodes, you must implement the `inspect_coroutine` method: ```python from griffe import Extension, ObjectNode @@ -349,26 +349,26 @@ Calling `self.visit(node)` or `self.inspect(node)` will do nothing unless you ac ### Triggering other extensions -If your extension creates new objects, you might want to trigger the other enabled extensions on these object instances. To do this you can use [`agent.extensions.call`][griffe.Extensions.call]: +If your extension creates new objects, you might want to trigger the other enabled extensions on these object instances. To do this you can use [`agent.extensions.call`][griffelib.Extensions.call]: ```python import ast import griffe -class MyExtension(griffe.Extension): +class MyExtension(griffelib.Extension): # Example from within a load event: - def on_package(self, *, pkg: griffe.Module, loader: griffe.GriffeLoader, **kwargs) -> None: + def on_package(self, *, pkg: griffelib.Module, loader: griffelib.GriffeLoader, **kwargs) -> None: # New object created for whatever reason. - function = griffe.Function(...) + function = griffelib.Function(...) # Trigger other extensions. loader.extensions.call("on_function", func=function, loader=loader) # Example from within an analysis event: - def on_node(self, *, node: ast.AST | griffe.ObjectNode, agent: griffe.Visitor | griffe.Inspector, **kwargs) -> None: + def on_node(self, *, node: ast.AST | griffelib.ObjectNode, agent: griffelib.Visitor | griffelib.Inspector, **kwargs) -> None: # New object created for whatever reason. - function = griffe.Function(...) + function = griffelib.Function(...) # Trigger other extensions. agent.extensions.call("on_function_instance", node=node, agent=agent, func=function, **kwargs) @@ -384,8 +384,8 @@ import griffe self_namespace = "my_extension" -class MyExtension(griffe.Extension): - def on_object(self, obj: griffe.Object, **kwargs) -> None: +class MyExtension(griffelib.Extension): + def on_object(self, obj: griffelib.Object, **kwargs) -> None: obj.extra[self_namespace]["some_key"] = "some_value" ``` @@ -398,8 +398,8 @@ self_namespace = "my_extension" mkdocstrings_namespace = "mkdocstrings" -class MyExtension(griffe.Extension): - def on_class(self, cls: griffe.Class, **kwargs) -> None: +class MyExtension(griffelib.Extension): + def on_class(self, cls: griffelib.Class, **kwargs) -> None: cls.extra[mkdocstrings_namespace]["template"] = "my_custom_template" ``` @@ -413,13 +413,13 @@ Extensions can be made to support options. These options can then be passed from import griffe -class MyExtension(griffe.Extension): +class MyExtension(griffelib.Extension): def __init__(self, option1: str, option2: bool = False) -> None: super().__init__() self.option1 = option1 self.option2 = option2 - def on_attribute(self, attr: griffe.Attribute, **kwargs) -> None: + def on_attribute(self, attr: griffelib.Attribute, **kwargs) -> None: if self.option2: ... # Do something. ``` @@ -431,11 +431,11 @@ To better integrate with Griffe and other tools in the ecosystem (notably MkDocs ```python import griffe -logger = griffe.get_logger(__name__) +logger = griffelib.get_logger(__name__) -class MyExtension(griffe.Extension): - def on_module(self, mod: griffe.Module, **kwargs) -> None: +class MyExtension(griffelib.Extension): + def on_module(self, mod: griffelib.Module, **kwargs) -> None: logger.info("Doing some work on module %s", mod.path) ``` @@ -459,17 +459,17 @@ import ast import inspect import griffe -logger = griffe.get_logger(__name__) +logger = griffelib.get_logger(__name__) -class DynamicDocstrings(griffe.Extension): +class DynamicDocstrings(griffelib.Extension): def __init__(self, object_paths: list[str] | None = None) -> None: self.object_paths = object_paths def on_object( self, - obj: griffe.Object, - loader: griffe.GriffeLoader, + obj: griffelib.Object, + loader: griffelib.GriffeLoader, **kwargs, ) -> None: if obj.analysis == "dynamic": @@ -480,7 +480,7 @@ class DynamicDocstrings(griffe.Extension): # Import object to get its evaluated docstring. try: - runtime_obj = griffe.dynamic_import(obj.path) + runtime_obj = griffelib.dynamic_import(obj.path) docstring = runtime_obj.__doc__ except ImportError: logger.debug(f"Could not get dynamic docstring for {obj.path}") @@ -494,7 +494,7 @@ class DynamicDocstrings(griffe.Extension): if obj.docstring: obj.docstring.value = docstring else: - obj.docstring = griffe.Docstring( + obj.docstring = griffelib.Docstring( docstring, parent=obj, docstring_parser=loader.docstring_parser, diff --git a/docs/guide/users/how-to/parse-docstrings.md b/docs/guide/users/how-to/parse-docstrings.md index fef3d12ee..70ebb6c05 100644 --- a/docs/guide/users/how-to/parse-docstrings.md +++ b/docs/guide/users/how-to/parse-docstrings.md @@ -1,6 +1,6 @@ # Using Griffe as a docstring-parsing library -You can use Griffe to parse arbitrary docstrings. You don't have to load anything through the Griffe loader. You just need to import the [`Docstring`][griffe.Docstring] class. Then you can build a `Docstring` instance and call its `parse` method, choosing the parsing-style to use: +You can use Griffe to parse arbitrary docstrings. You don't have to load anything through the Griffe loader. You just need to import the [`Docstring`][griffelib.Docstring] class. Then you can build a `Docstring` instance and call its `parse` method, choosing the parsing-style to use: ```python from griffe import Docstring diff --git a/docs/guide/users/how-to/selectively-inspect.md b/docs/guide/users/how-to/selectively-inspect.md index 87be96210..cfb0bf594 100644 --- a/docs/guide/users/how-to/selectively-inspect.md +++ b/docs/guide/users/how-to/selectively-inspect.md @@ -26,7 +26,7 @@ Start by creating an extensions module (a simple Python file) somewhere in your import griffe -class InspectSpecificObjects(griffe.Extension): +class InspectSpecificObjects(griffelib.Extension): """An extension to inspect just a few specific objects.""" ``` @@ -36,7 +36,7 @@ Make it accept configuration options by declaring an `__init__` method: import griffe -class InspectSpecificObjects(griffe.Extension): +class InspectSpecificObjects(griffelib.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: @@ -53,17 +53,17 @@ Now that our extension accepts options, we implement its core functionality. We import griffe -class InspectSpecificObjects(griffe.Extension): +class InspectSpecificObjects(griffelib.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: ... ``` -Check out the [available hooks][griffe.Extension] to see if there more appropriate hooks for your needs. +Check out the [available hooks][griffelib.Extension] to see if there more appropriate hooks for your needs. Lets now use our configuration option to decide whether to do something or skip: @@ -71,13 +71,13 @@ Lets now use our configuration option to decide whether to do something or skip: import griffe -class InspectSpecificObjects(griffe.Extension): +class InspectSpecificObjects(griffelib.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: if obj.path not in self.objects: return ``` @@ -87,21 +87,21 @@ Now we know that only the objects we're interested in will be handled, so lets h ```python hl_lines="3 16-20" import griffe -logger = griffe.get_logger("griffe_inspect_specific_objects") # (1)! +logger = griffelib.get_logger("griffe_inspect_specific_objects") # (1)! -class InspectSpecificObjects(griffe.Extension): +class InspectSpecificObjects(griffelib.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: if obj.path not in self.objects: return try: - runtime_obj = griffe.dynamic_import(obj.path) + runtime_obj = griffelib.dynamic_import(obj.path) except ImportError as error: logger.warning(f"Could not import {obj.path}: {error}") # (2)! return @@ -117,21 +117,21 @@ For example, we could use the runtime object's `__doc__` attribute, which could ```python hl_lines="22-25" import griffe -logger = griffe.get_logger("griffe_inspect_specific_objects") +logger = griffelib.get_logger("griffe_inspect_specific_objects") -class InspectSpecificObjects(griffe.Extension): +class InspectSpecificObjects(griffelib.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: if obj.path not in self.objects: return try: - runtime_obj = griffe.dynamic_import(obj.path) + runtime_obj = griffelib.dynamic_import(obj.path) except ImportError as error: logger.warning(f"Could not import {obj.path}: {error}") return @@ -139,7 +139,7 @@ class InspectSpecificObjects(griffe.Extension): if obj.docstring: obj.docstring.value = runtime_obj.__doc__ else: - obj.docstring = griffe.Docstring(runtime_obj.__doc__) + obj.docstring = griffelib.Docstring(runtime_obj.__doc__) ``` Or we could alter the Griffe object parameters in case of functions, which could have been modified by a signature-changing decorator: @@ -148,21 +148,21 @@ Or we could alter the Griffe object parameters in case of functions, which could import inspect import griffe -logger = griffe.get_logger("griffe_inspect_specific_objects") +logger = griffelib.get_logger("griffe_inspect_specific_objects") -class InspectSpecificObjects(griffe.Extension): +class InspectSpecificObjects(griffelib.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: if obj.path not in self.objects: return try: - runtime_obj = griffe.dynamic_import(obj.path) + runtime_obj = griffelib.dynamic_import(obj.path) except ImportError as error: logger.warning(f"Could not import {obj.path}: {error}") return @@ -181,17 +181,17 @@ We could also entirely replace the Griffe object obtained from static analysis b import griffe -class InspectSpecificObjects(griffe.Extension): +class InspectSpecificObjects(griffelib.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: if obj.path not in self.objects: return - inspected_module = griffe.inspect(obj.module.path, filepath=obj.filepath) + inspected_module = griffelib.inspect(obj.module.path, filepath=obj.filepath) obj.parent.set_member(obj.name, inspected_module[obj.name]) # (1)! ``` diff --git a/docs/guide/users/how-to/set-docstring-styles.md b/docs/guide/users/how-to/set-docstring-styles.md index 5c03e5cfd..ddfb4794d 100644 --- a/docs/guide/users/how-to/set-docstring-styles.md +++ b/docs/guide/users/how-to/set-docstring-styles.md @@ -44,11 +44,11 @@ import re import griffe -class ApplyDocstringStyle(griffe.Extension): +class ApplyDocstringStyle(griffelib.Extension): def __init__(self, regex: str = "") -> None: self.regex = re.compile(regex) - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: if obj.docstring: if match := self.regex.search(obj.docstring.value): obj.docstring.parser = match.group(1) @@ -73,11 +73,11 @@ import re import griffe -class ApplyDocstringStyle(griffe.Extension): +class ApplyDocstringStyle(griffelib.Extension): def __init__(self, regex: str = ".*# style: (google|numpy|sphinx)$") -> None: self.regex = re.compile(regex) - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: if obj.docstring: if match := self.regex.search(obj.docstring.source): obj.docstring.parser = match.group(1) @@ -91,7 +91,7 @@ Finally, you could decide to map a list of objects to the docstring style they s import griffe from fnmatch import fnmatch -class ApplyDocstringStyle(griffe.Extension): +class ApplyDocstringStyle(griffelib.Extension): def __init__(self, config: dict[str, str]): self.instances = {} self.globs = {} @@ -101,7 +101,7 @@ class ApplyDocstringStyle(griffe.Extension): else: self.instances[key] = value - def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: if obj.path in self.instances: if obj.docstring: obj.docsring.parser = self.instances[obj.path] diff --git a/docs/guide/users/how-to/set-git-info.md b/docs/guide/users/how-to/set-git-info.md index 5fde20b4a..9c827940f 100644 --- a/docs/guide/users/how-to/set-git-info.md +++ b/docs/guide/users/how-to/set-git-info.md @@ -12,7 +12,7 @@ Start by creating an extensions module (a simple Python file) somewhere in your import griffe -class GitInfo(griffe.Extension): +class GitInfo(griffelib.Extension): """An extension to set the right Git information.""" ``` @@ -25,12 +25,12 @@ from typing import Any import griffe -class GitInfo(griffe.Extension): +class GitInfo(griffelib.Extension): """An extension to set the right Git information.""" - def on_package(self, *, pkg: griffe.Module, **kwargs: Any) -> None: + def on_package(self, *, pkg: griffelib.Module, **kwargs: Any) -> None: if pkg.name == "my_package_name": - pkg.git_info = griffe.GitInfo( + pkg.git_info = griffelib.GitInfo( repository=Path("/path/to/this/package/local/repository"), service="forgejo", remote_url="https://myhostedforge.mydomain.com/myaccount/myproject", @@ -51,7 +51,7 @@ We could also reuse properties that Griffe found: ```python # Here we reuse `repository` and `commit_hash` while overriding only `service` and `remote_url`. -pkg.git_info = griffe.GitInfo( +pkg.git_info = griffelib.GitInfo( repository=pkg.git_info.repository, service="forgejo", remote_url="https://myhostedforge.mydomain.com/myaccount/myproject", @@ -74,7 +74,7 @@ Start by creating an extensions module (a simple Python file) somewhere in your import griffe -class SourceLinks(griffe.Extension): +class SourceLinks(griffelib.Extension): """An extension to set the right source links.""" ``` @@ -87,10 +87,10 @@ from typing import Any import griffe -class SourceLinks(griffe.Extension): +class SourceLinks(griffelib.Extension): """An extension to set the right source links.""" - def on_object(self, *, obj: griffe.Object, **kwargs: Any) -> None: + def on_object(self, *, obj: griffelib.Object, **kwargs: Any) -> None: if obj.path == "my_package_name.my_function": obj.source_link = "https://myhostedforge.mydomain.com/myaccount/myproject/src/commit/77f928aeab857cb45564462a4f849c2df2cca99a/src/lib.rs#L35-L48" # Handle any other object you want. @@ -107,10 +107,10 @@ from typing import Any import griffe -class SourceLinks(griffe.Extension): +class SourceLinks(griffelib.Extension): """An extension to set the right source links.""" - def on_object(self, *, obj: griffe.Object, **kwargs: Any) -> None: + def on_object(self, *, obj: griffelib.Object, **kwargs: Any) -> None: if obj.path == "my_package_name.my_function": obj.source_link = obj.git_info.get_source_link( filepath="src/lib.rs", diff --git a/docs/guide/users/how-to/support-decorators.md b/docs/guide/users/how-to/support-decorators.md index b0fe8da5c..ffde3455e 100644 --- a/docs/guide/users/how-to/support-decorators.md +++ b/docs/guide/users/how-to/support-decorators.md @@ -24,11 +24,11 @@ Start by creating an extensions module (a simple Python file) somewhere in your import griffe -class MyDecorator(griffe.Extension): +class MyDecorator(griffelib.Extension): """An extension to suport my decorator.""" ``` -Now we can declare the [`on_instance`][griffe.Extension.on_instance] hook, which receives any kind of Griffe object ([`Module`][griffe.Module], [`Class`][griffe.Class], [`Function`][griffe.Function], [`Attribute`][griffe.Attribute], [`TypeAlias`][griffe.TypeAlias]), or we could use a kind-specific hook such as [`on_module_instance`][griffe.Extension.on_module_instance], [`on_class_instance`][griffe.Extension.on_class_instance], [`on_function_instance`][griffe.Extension.on_function_instance], [`on_attribute_instance`][griffe.Extension.on_attribute_instance] and [`on_type_alias_instance`][griffe.Extension.on_type_alias_instance]. For example, if you know your decorator is only ever used on class declarations, it would make sense to use `on_class_instance`. +Now we can declare the [`on_instance`][griffelib.Extension.on_instance] hook, which receives any kind of Griffe object ([`Module`][griffelib.Module], [`Class`][griffelib.Class], [`Function`][griffelib.Function], [`Attribute`][griffelib.Attribute], [`TypeAlias`][griffelib.TypeAlias]), or we could use a kind-specific hook such as [`on_module_instance`][griffelib.Extension.on_module_instance], [`on_class_instance`][griffelib.Extension.on_class_instance], [`on_function_instance`][griffelib.Extension.on_function_instance], [`on_attribute_instance`][griffelib.Extension.on_attribute_instance] and [`on_type_alias_instance`][griffelib.Extension.on_type_alias_instance]. For example, if you know your decorator is only ever used on class declarations, it would make sense to use `on_class_instance`. For the example, lets use the `on_function_instance` hook, which receives `Function` instances. @@ -36,10 +36,10 @@ For the example, lets use the `on_function_instance` hook, which receives `Funct import griffe -class MyDecorator(griffe.Extension): +class MyDecorator(griffelib.Extension): """An extension to suport my decorator.""" - def on_function_instance(self, *, func: griffe.Function, **kwargs) -> None: + def on_function_instance(self, *, func: griffelib.Function, **kwargs) -> None: ... ``` @@ -49,13 +49,13 @@ In this hook, we check if our function is decorated with our custom decorator: import griffe -class MyDecorator(griffe.Extension): +class MyDecorator(griffelib.Extension): """An extension to suport my decorator.""" - def on_function_instance(self, *, func: griffe.Function, **kwargs) -> None: + def on_function_instance(self, *, func: griffelib.Function, **kwargs) -> None: for decorator in func.decorators: if decorator.callable_path == "my_package.utils.enhance": ... # Update the function attributes. ``` -Now all that is left to do is to actually write the code that updates the function according to what the decorator is doing. We could update the function's docstring, or its return type, or its parameters: it all depends on your decorator and what it does to the objects it decorates. Check out the [API reference for function objects][griffe.Function] to see what data this object stores. +Now all that is left to do is to actually write the code that updates the function according to what the decorator is doing. We could update the function's docstring, or its return type, or its parameters: it all depends on your decorator and what it does to the objects it decorates. Check out the [API reference for function objects][griffelib.Function] to see what data this object stores. diff --git a/docs/guide/users/loading.md b/docs/guide/users/loading.md index 620917803..06a98a040 100644 --- a/docs/guide/users/loading.md +++ b/docs/guide/users/loading.md @@ -4,12 +4,12 @@ Griffe can load API data from both source code (static analysis) and objects at ## The `load` function -The main interface to load API data is Griffe's [`load`][griffe.load] function: +The main interface to load API data is Griffe's [`load`][griffelib.load] function: ```python import griffe -my_package = griffe.load("my_package") +my_package = griffelib.load("my_package") ``` You can ask to load a specific object rather than a package: @@ -17,7 +17,7 @@ You can ask to load a specific object rather than a package: ```python import griffe -my_method = griffe.load("my_package.MyClass.my_method") +my_method = griffelib.load("my_package.MyClass.my_method") ``` Griffe will load the whole package anyway, but return the specified object directly, so that you don't have to access it manually. To manually access the object representing the method called `my_method`, you would have used the `my_package` variable instantiated before, like this: @@ -33,8 +33,8 @@ Finally, you can even load packages or modules by passing absolute or relative f ```python import griffe -griffe.load("src/my_package") -griffe.load("some_script.py") +griffelib.load("src/my_package") +griffelib.load("some_script.py") ``` In case of ambiguity, you can instruct Griffe to ignore existing relative file paths with `try_relative_paths=False`. For example, when using [the flat layout (in contrast to the src-layout)](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/), your Python package is in the root of the repository. @@ -51,12 +51,12 @@ Here if you ask Griffe to load `my_package`, it will find it as a relative path, ```python import griffe -my_installed_package = griffe.load("my_package", try_relative_path=False) +my_installed_package = griffelib.load("my_package", try_relative_path=False) ``` ## The `GriffeLoader` class -The [`load`][griffe.load] function is a shortcut for instantiating the [`GriffeLoader`][griffe.GriffeLoader] class and calling its [`load`][griffe.GriffeLoader.load] method. Calling the [`load`][griffe.load] function multiple times will instantiate a new Griffe loader each time. If you care about efficiency, it is better to instantiate the loader yourself and use its `load` method: +The [`load`][griffelib.load] function is a shortcut for instantiating the [`GriffeLoader`][griffelib.GriffeLoader] class and calling its [`load`][griffelib.GriffeLoader.load] method. Calling the [`load`][griffelib.load] function multiple times will instantiate a new Griffe loader each time. If you care about efficiency, it is better to instantiate the loader yourself and use its `load` method: ```python import griffe @@ -72,13 +72,13 @@ Reusing the same loader will also help resolving aliases across different packag ## Search paths -To specify in which directories Griffe should search for packages and modules, you can use the `search_paths` parameter on both the [`load` function][griffe.load] and the [`GriffeLoader` class][griffe.GriffeLoader]. +To specify in which directories Griffe should search for packages and modules, you can use the `search_paths` parameter on both the [`load` function][griffelib.load] and the [`GriffeLoader` class][griffelib.GriffeLoader]. === "`load`" ```python import griffe - my_package = griffe.load("my_package", search_paths=["src"]) + my_package = griffelib.load("my_package", search_paths=["src"]) ``` === "`GriffeLoader`" @@ -100,7 +100,7 @@ Griffe always tries first to find sources for the specified object. Then, unless ```python import griffe -my_package = griffe.load("my_package", force_inspection=True) +my_package = griffelib.load("my_package", force_inspection=True) ``` [](){#forcing-dynamic-analysis-not-recommended} @@ -125,10 +125,10 @@ If you want to be careful about what gets executed in the current Python process import griffe # Here Griffe will fall back on dynamic analysis and import `itertools`. -griffe.load("itertools") +griffelib.load("itertools") # While here it will raise `ModuleNotFoundError`. -griffe.load("itertools", allow_inspection=False) +griffelib.load("itertools", allow_inspection=False) ``` ## Alias resolution @@ -138,7 +138,7 @@ griffe.load("itertools", allow_inspection=False) > > The name "alias" comes from the fact that imported objects can be aliased under a different name: `from X import A as B`. In the case of inherited members, this doesn't really apply, but we reuse the concept for conciseness. > -> An [`Alias`][griffe.Alias] instance is therefore a pointer to another object. It has its own name, parent, line numbers, and stores the path to the target object. Thanks to this path, we can access the actual target object and all its metadata, such as name, parent, line numbers, docstring, etc.. Obtaining a reference to the target object is what we call "alias resolution". +> An [`Alias`][griffelib.Alias] instance is therefore a pointer to another object. It has its own name, parent, line numbers, and stores the path to the target object. Thanks to this path, we can access the actual target object and all its metadata, such as name, parent, line numbers, docstring, etc.. Obtaining a reference to the target object is what we call "alias resolution". > > **To summarize, alias resolution is a post-process task that resolves imports after loading everything.** @@ -171,14 +171,14 @@ When loading this package, `my_package.my_function` will be an alias pointing at ```python import griffe -my_package = griffe.load("my_package") +my_package = griffelib.load("my_package") my_package["my_function"].resolved # False ``` ```python import griffe -my_package = griffe.load("my_package", resolve_aliases=True) +my_package = griffelib.load("my_package", resolve_aliases=True) my_package["my_function"].resolved # True my_package["my_function"].target is my_package["my_module.my_function"] # True ``` @@ -207,7 +207,7 @@ from package1 import X ```pycon >>> import griffe ->>> package2 = griffe.load("package2", resolve_aliases=True) +>>> package2 = griffelib.load("package2", resolve_aliases=True) >>> package2["X"].target_path 'package1.X' >>> package2["X"].resolved @@ -232,17 +232,17 @@ Traceback (most recent call last): self._resolve_target() File "griffe/_internal/dataclasses.py", line 1377, in _resolve_target raise AliasResolutionError(self) from error -griffe._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) +griffelib._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) ``` -As you can see in the interpreter session above, Griffe did not resolve the `X` alias. When we tried to access its target object anyway, it failed with a `KeyError`, which was raised again as an [`AliasResolutionError`][griffe.AliasResolutionError]. +As you can see in the interpreter session above, Griffe did not resolve the `X` alias. When we tried to access its target object anyway, it failed with a `KeyError`, which was raised again as an [`AliasResolutionError`][griffelib.AliasResolutionError]. Lets try again, but this time by loading both packages. ```pycon >>> import griffe ->>> package1 = griffe.load("package1") # nothing to resolve ->>> package2 = griffe.load("package2", resolve_aliases=True) +>>> package1 = griffelib.load("package1") # nothing to resolve +>>> package2 = griffelib.load("package2", resolve_aliases=True) >>> package2["X"].target_path 'package1.X' >>> package2["X"].resolved @@ -250,27 +250,27 @@ False # Hmm? >>> package2["X"].target Traceback (most recent call last): ... -griffe._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) +griffelib._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) ``` The same exception again? What happened here? We loaded both packages, but Griffe still failed to resolve the alias. That is expected; here is the explanation. If you look closely at the first exception traceback, you will see that Griffe searched the target path in `self.modules_collection`. So what is this modules collection? -Each instance of [`GriffeLoader`][griffe.GriffeLoader] holds a reference to an instance of [`ModulesCollection`][griffe.ModulesCollection]. If you don't create such a collection manually to pass it to the loader, it will instantiate one itself. All objects loaded with this loader are added to this very modules collection, and gain a reference to it. +Each instance of [`GriffeLoader`][griffelib.GriffeLoader] holds a reference to an instance of [`ModulesCollection`][griffelib.ModulesCollection]. If you don't create such a collection manually to pass it to the loader, it will instantiate one itself. All objects loaded with this loader are added to this very modules collection, and gain a reference to it. -Since the [`load` function][griffe.load] is just a shortcut for creating a loader and calling its [`load` method][griffe.GriffeLoader.load], when we called `griffe.load(...)` twice, it actually created two distinct collections of modules. When Griffe tried to resolve aliases of `package2`, it looked for `package1` in `package2`'s collection, and couldn't find it. Indeed, `package1` was in another modules collection. +Since the [`load` function][griffelib.load] is just a shortcut for creating a loader and calling its [`load` method][griffelib.GriffeLoader.load], when we called `griffelib.load(...)` twice, it actually created two distinct collections of modules. When Griffe tried to resolve aliases of `package2`, it looked for `package1` in `package2`'s collection, and couldn't find it. Indeed, `package1` was in another modules collection. Therefore, to resolve aliases *across different packages*, these packages must be loaded within the same modules collection. In order to do that, you have a few options: - instantiate a single loader, and use it to load both packages -- create your own modules collection, and pass it to the [`load` function][griffe.load] each time you call it -- create your own modules collection, and pass it to the different instances of [`GriffeLoader`][griffe.GriffeLoader] you create +- create your own modules collection, and pass it to the [`load` function][griffelib.load] each time you call it +- create your own modules collection, and pass it to the different instances of [`GriffeLoader`][griffelib.GriffeLoader] you create === "Same loader" ```pycon >>> import griffe - >>> loader = griffe.GriffeLoader() + >>> loader = griffelib.GriffeLoader() >>> package1 = loader.load("package1") >>> package2 = loader.load("package2") >>> loader.resolve_aliases() @@ -283,9 +283,9 @@ Therefore, to resolve aliases *across different packages*, these packages must b === "Same collection with `load`" ```pycon >>> import griffe - >>> collection = griffe.ModulesCollection() - >>> package1 = griffe.load("package1", modules_collection=collection) - >>> package2 = griffe.load("package2", modules_collection=collection, resolve_aliases=True) + >>> collection = griffelib.ModulesCollection() + >>> package1 = griffelib.load("package1", modules_collection=collection) + >>> package2 = griffelib.load("package2", modules_collection=collection, resolve_aliases=True) >>> package2["X"].resolved True >>> package2["X"].target @@ -295,10 +295,10 @@ Therefore, to resolve aliases *across different packages*, these packages must b === "Same collection, different loaders" ```pycon >>> import griffe - >>> collection = griffe.ModulesCollection() - >>> loader1 = griffe.GriffeLoader(modules_collection=collection, ...) + >>> collection = griffelib.ModulesCollection() + >>> loader1 = griffelib.GriffeLoader(modules_collection=collection, ...) >>> package1 = loader1.load("package1") - >>> loader2 = griffe.GriffeLoader(modules_collection=collection, ...) # different parameters + >>> loader2 = griffelib.GriffeLoader(modules_collection=collection, ...) # different parameters >>> package2 = loader2.load("package2") >>> package2["X"].resolved True @@ -315,7 +315,7 @@ By default, when resolving aliases, Griffe loaders will not be able to resolve a ```python import griffe -package2 = griffe.load("package2", resolve_aliases=True, resolve_external=True) +package2 = griffelib.load("package2", resolve_aliases=True, resolve_external=True) print(package2["X"].target.name) # X ``` @@ -334,7 +334,7 @@ By default, Griffe runs some Git commands to find the following information abou - what service it corresponds to (GitHub, etc.) - the current commit hash -It then assigns this information to each package it loads, in the [`git_info`][griffe.Object.git_info] attribute. This attribute can be reassigned on any object, if necessary. Each object who has it set to `None` will look into its parents. +It then assigns this information to each package it loads, in the [`git_info`][griffelib.Object.git_info] attribute. This attribute can be reassigned on any object, if necessary. Each object who has it set to `None` will look into its parents. In the following cases, the information will not be set: @@ -343,15 +343,15 @@ In the following cases, the information will not be set: - Griffe cannot identify a known, supported service from the remote URL - any Git command failed -Griffe supports the services listed in the [`KnownGitService`][griffe.KnownGitService] symbol. Please open a feature request if you would like to add support for other services. +Griffe supports the services listed in the [`KnownGitService`][griffelib.KnownGitService] symbol. Please open a feature request if you would like to add support for other services. -Thanks to this source information, Griffe can then compute [source links][griffe.Object.source_link] for each objects, by combining the information with the object's filepath and line numbers. +Thanks to this source information, Griffe can then compute [source links][griffelib.Object.source_link] for each objects, by combining the information with the object's filepath and line numbers. You can globally change how Griffe obtains the source information with the following environment variables: - `GRIFFE_GIT_REMOTE_URL`: It is the repository remote URL, as an HTTPS link that readers of your documentation can access to see the repository online, on the service it is hosted on. Example: `GRIFFE_GIT_REMOTE_URL=https://app.radicle.at/nodes/seed.radicle.at/rad:z4M5XTPDD4Wh1sm8iPCenF85J3z8Z`. - `GRIFFE_GIT_REMOTE`: You can also let Griffe obtain the remote URL by getting it from the Git local configuration. The Git remote defaults to `origin`. This environment variable lets you change it to something else. Example: `GRIFFE_GIT_REMOTE=upstream`. -- `GRIFFE_GIT_SERVICE`: Griffe infers the service by looking at the remote URL. If the remote URL contains a [known service name][griffe.KnownGitService], Griffe will use it as service. You can otherwise explicitly set the service using this environment variable. Example: `GRIFFE_GIT_SERVICE=codeberg`. +- `GRIFFE_GIT_SERVICE`: Griffe infers the service by looking at the remote URL. If the remote URL contains a [known service name][griffelib.KnownGitService], Griffe will use it as service. You can otherwise explicitly set the service using this environment variable. Example: `GRIFFE_GIT_SERVICE=codeberg`. - `GRIFFE_GIT_COMMIT_HASH`: Griffe gets the commit hash by running a Git command. If you prefer using another commit hash, you can set it using this environment variable. Example: `GRIFFE_GIT_COMMIT_HASH=77f928aeab857cb45564462a4f849c2df2cca99a`. For more complex cases, see [How to programmatically set the correct Git information or source link on objects](how-to/set-git-info.md). diff --git a/docs/guide/users/navigating.md b/docs/guide/users/navigating.md index 75a1a0ab3..a0cb2559e 100644 --- a/docs/guide/users/navigating.md +++ b/docs/guide/users/navigating.md @@ -2,59 +2,59 @@ Griffe loads API data into data models. These models provide various attributes and methods to access or update specific fields. The different models are: -- [`Module`][griffe.Module], representing Python modules; -- [`Class`][griffe.Class], representing Python classes; -- [`Function`][griffe.Function], representing Python functions and class methods; -- [`Attribute`][griffe.Attribute], representing object attributes that weren't identified as modules, classes or functions; -- [`Type Alias`][griffe.TypeAlias], representing Python type aliases; -- [`Alias`][griffe.Alias], representing indirections such as imported objects or class members inherited from parent classes. +- [`Module`][griffelib.Module], representing Python modules; +- [`Class`][griffelib.Class], representing Python classes; +- [`Function`][griffelib.Function], representing Python functions and class methods; +- [`Attribute`][griffelib.Attribute], representing object attributes that weren't identified as modules, classes or functions; +- [`Type Alias`][griffelib.TypeAlias], representing Python type aliases; +- [`Alias`][griffelib.Alias], representing indirections such as imported objects or class members inherited from parent classes. When [loading an object](loading.md), Griffe will give you back an instance of one of these models. A few examples: ```python >>> import griffe ->>> type(griffe.load("markdown")) - ->>> type(griffe.load("markdown.core.Markdown")) - ->>> type(griffe.load("markdown.Markdown")) - ->>> type(griffe.load("markdown.core.markdown")) - ->>> type(griffe.load("markdown.markdown")) - ->>> type(griffe.load("markdown.Markdown.references")) - +>>> type(griffelib.load("markdown")) + +>>> type(griffelib.load("markdown.core.Markdown")) + +>>> type(griffelib.load("markdown.Markdown")) + +>>> type(griffelib.load("markdown.core.markdown")) + +>>> type(griffelib.load("markdown.markdown")) + +>>> type(griffelib.load("markdown.Markdown.references")) + ``` However deep the object is, Griffe loads the entire package. It means that in all the cases above, Griffe loaded the whole `markdown` package. The model instance Griffe gives you back is therefore part of a tree that you can navigate. ## Moving up: parents -Each object holds a reference to its [`parent`][griffe.Object.parent] (except for the top-level module, for which the parent is `None`). Shortcuts are provided to climb up directly to the parent [`module`][griffe.Object.module], or the top-level [`package`][griffe.Object.package]. As we have seen in the [Loading chapter](loading.md), Griffe stores all loaded modules in a modules collection; this collection can be accessed too, through the [`modules_collection`][griffe.Object.modules_collection] attribute. +Each object holds a reference to its [`parent`][griffelib.Object.parent] (except for the top-level module, for which the parent is `None`). Shortcuts are provided to climb up directly to the parent [`module`][griffelib.Object.module], or the top-level [`package`][griffelib.Object.package]. As we have seen in the [Loading chapter](loading.md), Griffe stores all loaded modules in a modules collection; this collection can be accessed too, through the [`modules_collection`][griffelib.Object.modules_collection] attribute. ## Moving down: members To access an object's members, there are a few options: -- Access to regular members through the [`members`][griffe.Object.members] attribute, which is a dictionary. The keys are member names, the values are Griffe models. +- Access to regular members through the [`members`][griffelib.Object.members] attribute, which is a dictionary. The keys are member names, the values are Griffe models. ```pycon >>> import griffe - >>> markdown = griffe.load("markdown") + >>> markdown = griffelib.load("markdown") >>> markdown.members["Markdown"] Alias('Markdown', 'markdown.core.Markdown') >>> markdown.members["core"].members["Markdown"] Class('Markdown', 46, 451) ``` -- Access to both regular and inherited members through the [`all_members`][griffe.Object.all_members] attribute, which is a dictionary again. See [Inherited members](#inherited-members). +- Access to both regular and inherited members through the [`all_members`][griffelib.Object.all_members] attribute, which is a dictionary again. See [Inherited members](#inherited-members). - Convenient dictionary-like item access, thanks to the subscript syntax `[]`. With this syntax, you will not only be able to chain accesses, but also merge them into a single access by using dot-separated paths to objects: ```pycon >>> import griffe - >>> markdown = griffe.load("markdown") + >>> markdown = griffelib.load("markdown") >>> markdown["core"]["Markdown"] # chained access Class('Markdown', 46, 451) >>> markdown["core.Markdown"] # merged access @@ -65,7 +65,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffe.load("markdown") + >>> markdown = griffelib.load("markdown") >>> markdown[("core", "Markdown")] # tuple access Class('Markdown', 46, 451) >>> # Due to the nature of the subscript syntax, @@ -74,18 +74,18 @@ To access an object's members, there are a few options: Class('Markdown', 46, 451) ``` -- Less convenient, but safer access to members while the object tree is being built (while a package is still being loaded), using the [`get_member()`][griffe.GetMembersMixin.get_member] method. +- Less convenient, but safer access to members while the object tree is being built (while a package is still being loaded), using the [`get_member()`][griffelib.GetMembersMixin.get_member] method. ```pycon >>> import griffe - >>> markdown = griffe.load("markdown") + >>> markdown = griffelib.load("markdown") >>> markdown.get_member("core.Markdown") Class('Markdown', 46, 451) ``` In particular, Griffe extensions should always use `get_member` instead of the subscript syntax `[]`. The `get_member` method only looks into regular members, while the subscript syntax looks into inherited members too (for classes), which cannot be correctly computed until a package is fully loaded (which is generally not the case when an extension is running). -- In addition to this, models provide the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes, which return only members of the corresponding kind. These attributes are computed dynamically each time (they are Python properties). +- In addition to this, models provide the [`attributes`][griffelib.Object.attributes], [`functions`][griffelib.Object.functions], [`classes`][griffelib.Object.classes], [`type_aliases`][griffelib.Object.type_aliases] or [`modules`][griffelib.Object.modules] attributes, which return only members of the corresponding kind. These attributes are computed dynamically each time (they are Python properties). The same way members are accessed, they can also be set: @@ -97,22 +97,22 @@ The same way members are accessed, they can also be set: - Dictionary-like item deletion: `del markdown["thing"]`, also supporting dotted-paths and string tuples. This will delete only regular members: inherited members (classes only) are re-computed everytime they are accessed. - Safer method for extensions: `markdown.del_member("thing")`, also supporting dotted-paths and string tuples. -- Regular member deletion: `del markdown.members["thing"]`. **This is not recommended, as the [`aliases`][griffe.Object.aliases] attribute of other objects in the tree will not be automatically updated.** +- Regular member deletion: `del markdown.members["thing"]`. **This is not recommended, as the [`aliases`][griffelib.Object.aliases] attribute of other objects in the tree will not be automatically updated.** ### Inherited members Griffe supports class inheritance, both when visiting and inspecting modules. -To access members of a class that are inherited from base classes, use the [`inherited_members`][griffe.Object.inherited_members] attribute. Everytime you access inherited members, the base classes of the given class will be resolved, then the MRO (Method Resolution Order) will be computed for these base classes, and a dictionary of inherited members will be built. Make sure to store the result in a variable to avoid re-computing it everytime (you are responsible for the caching part). Also make sure to only access `inherited_members` once everything is loaded by Griffe, to avoid computing things too early. Don't try to access inherited members in extensions, while visiting or inspecting modules. +To access members of a class that are inherited from base classes, use the [`inherited_members`][griffelib.Object.inherited_members] attribute. Everytime you access inherited members, the base classes of the given class will be resolved, then the MRO (Method Resolution Order) will be computed for these base classes, and a dictionary of inherited members will be built. Make sure to store the result in a variable to avoid re-computing it everytime (you are responsible for the caching part). Also make sure to only access `inherited_members` once everything is loaded by Griffe, to avoid computing things too early. Don't try to access inherited members in extensions, while visiting or inspecting modules. -Inherited members are aliases that point at the corresponding members in parent classes. These aliases will have their [`inherited`][griffe.Alias.inherited] attribute set to true. +Inherited members are aliases that point at the corresponding members in parent classes. These aliases will have their [`inherited`][griffelib.Alias.inherited] attribute set to true. **Important:** only classes from already loaded packages will be used when computing inherited members. This gives users control over how deep into inheritance to go, by pre-loading packages from which you want to inherit members. For example, if `package_c.ClassC` inherits from `package_b.ClassB`, itself inheriting from `package_a.ClassA`, and you want to load `ClassB` members only: ```python import griffe -loader = griffe.GriffeLoader() +loader = griffelib.GriffeLoader() # note that we don't load package_a loader.load("package_b") loader.load("package_c") @@ -120,9 +120,9 @@ loader.load("package_c") If a base class cannot be resolved during computation of inherited members, Griffe logs a DEBUG message. -If you want to access all members at once (both declared and inherited), use the [`all_members`][griffe.Object.all_members] attribute. If you want to access only declared members, use the [`members`][griffe.Object] attribute. +If you want to access all members at once (both declared and inherited), use the [`all_members`][griffelib.Object.all_members] attribute. If you want to access only declared members, use the [`members`][griffelib.Object] attribute. -Accessing the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by Griffe. Don't try to access inherited members in extensions, while visiting or inspecting modules. +Accessing the [`attributes`][griffelib.Object.attributes], [`functions`][griffelib.Object.functions], [`classes`][griffelib.Object.classes], [`type_aliases`][griffelib.Object.type_aliases] or [`modules`][griffelib.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by Griffe. Don't try to access inherited members in extensions, while visiting or inspecting modules. #### Limitations @@ -174,46 +174,46 @@ We will try to lift these limitations in the future. ## Aliases -Aliases represent indirections, such as objects imported from elsewhere, attributes, or methods inherited from parent classes. They are pointers to the object they represent. The path of the object they represent is stored in their [`target_path`][griffe.Alias.target_path] attribute. Once they are resolved, the target object can be accessed through their [`target`][griffe.Alias.target] attribute. +Aliases represent indirections, such as objects imported from elsewhere, attributes, or methods inherited from parent classes. They are pointers to the object they represent. The path of the object they represent is stored in their [`target_path`][griffelib.Alias.target_path] attribute. Once they are resolved, the target object can be accessed through their [`target`][griffelib.Alias.target] attribute. -Aliases can be found in objects' members. Each object can also access its own aliases (the aliases pointing at it) through its [`aliases`][griffe.Object.aliases] attribute. This attribute is a dictionary whose keys are the aliases paths and values are the aliases themselves. +Aliases can be found in objects' members. Each object can also access its own aliases (the aliases pointing at it) through its [`aliases`][griffelib.Object.aliases] attribute. This attribute is a dictionary whose keys are the aliases paths and values are the aliases themselves. Most of the time, aliases simply act as proxies to their target objects. For example, accessing the `docstring` of an alias will simply return the docstring of the object it targets. -Accessing fields on aliases will trigger their resolution. If they are already resolved (their `target` attribute is set to the target object), the field is returned. If they are not resolved, their target path will be looked up in the modules collection, and if it is found, the object at this location will be assigned to the alias' `target` attribute. If it isn't found, an [`AliasResolutionError`][griffe.AliasResolutionError] exception will be raised. +Accessing fields on aliases will trigger their resolution. If they are already resolved (their `target` attribute is set to the target object), the field is returned. If they are not resolved, their target path will be looked up in the modules collection, and if it is found, the object at this location will be assigned to the alias' `target` attribute. If it isn't found, an [`AliasResolutionError`][griffelib.AliasResolutionError] exception will be raised. Since merely accessing an alias field can raise an exception, it is often useful to check if an object is an alias before accessing its fields. There are multiple ways to check if an object is an alias: -- using the `is_alias` boolean ([`Object.is_alias`][griffe.Object.is_alias], [`Alias.is_alias`][griffe.Alias.is_alias]), which won't trigger resolution -- using `isinstance` to check if the object is an instance of [`Alias`][griffe.Alias] +- using the `is_alias` boolean ([`Object.is_alias`][griffelib.Object.is_alias], [`Alias.is_alias`][griffelib.Alias.is_alias]), which won't trigger resolution +- using `isinstance` to check if the object is an instance of [`Alias`][griffelib.Alias] ```pycon >>> import griffe ->>> load = griffe.load("griffe.load") +>>> load = griffelib.load("griffelib.load") >>> load.is_alias True ->>> isinstance(load, griffe.Alias) +>>> isinstance(load, griffelib.Alias) True ``` -The [`kind`][griffe.Alias.kind] of an alias will only return [`ALIAS`][griffe.Kind.ALIAS] if the alias is not resolved and cannot be resolved within the current modules collection. +The [`kind`][griffelib.Alias.kind] of an alias will only return [`ALIAS`][griffelib.Kind.ALIAS] if the alias is not resolved and cannot be resolved within the current modules collection. You can of course also catch any raised exception with a regular try/except block: ```python try: print(obj.source) -except griffe.AliasResolutionError: +except griffelib.AliasResolutionError: pass ``` -To check if an alias is already resolved, you can use its [`resolved`][griffe.Alias.resolved] attribute. +To check if an alias is already resolved, you can use its [`resolved`][griffelib.Alias.resolved] attribute. ### Alias chains -Aliases can be chained. For example, if module `a` imports `X` from module `b`, which itself imports `X` from module `c`, then `a.X` is an alias to `b.X` which is an alias to `c.X`: `a.X` -> `b.X` -> `c.X`. To access the final target directly, you can use the [`final_target`][griffe.Alias.final_target] attribute. Most alias properties that act like proxies actually fetch the final target rather than the next one to return the final field. +Aliases can be chained. For example, if module `a` imports `X` from module `b`, which itself imports `X` from module `c`, then `a.X` is an alias to `b.X` which is an alias to `c.X`: `a.X` -> `b.X` -> `c.X`. To access the final target directly, you can use the [`final_target`][griffelib.Alias.final_target] attribute. Most alias properties that act like proxies actually fetch the final target rather than the next one to return the final field. -Sometimes, when a package makes use of complicated imports (wildcard imports from parents and submodules), or when runtime objects are hard to inspect, it is possible to end up with a cyclic chain of aliases. You could for example end up with a chain like `a.X` -> `b.X` -> `c.X` -> `a.X`. In this case, the alias *cannot* be resolved, since the chain goes in a loop. Griffe will raise a [`CyclicAliasError`][griffe.CyclicAliasError] when trying to resolve such cyclic chains. +Sometimes, when a package makes use of complicated imports (wildcard imports from parents and submodules), or when runtime objects are hard to inspect, it is possible to end up with a cyclic chain of aliases. You could for example end up with a chain like `a.X` -> `b.X` -> `c.X` -> `a.X`. In this case, the alias *cannot* be resolved, since the chain goes in a loop. Griffe will raise a [`CyclicAliasError`][griffelib.CyclicAliasError] when trying to resolve such cyclic chains. Aliases chains are never partially resolved: either they are resolved down to their final target, or none of their links are resolved. @@ -221,9 +221,9 @@ Aliases chains are never partially resolved: either they are resolved down to th The kind of an object (module, class, function, attribute, type alias or alias) can be obtained in several ways. -- With the [`kind`][griffe.Object.kind] attribute and the [`Kind`][griffe.Kind] enumeration: `obj.kind is Kind.MODULE`. +- With the [`kind`][griffelib.Object.kind] attribute and the [`Kind`][griffelib.Kind] enumeration: `obj.kind is Kind.MODULE`. -- With the [`is_kind()`][griffe.Object.is_kind] method: +- With the [`is_kind()`][griffelib.Object.is_kind] method: - `obj.is_kind(Kind.MODULE)` - `obj.is_kind("class")` @@ -231,21 +231,21 @@ The kind of an object (module, class, function, attribute, type alias or alias) When given a set of kinds, the method returns true if the object is of one of the given kinds. -- With the [`is_module`][griffe.Object.is_module], [`is_class`][griffe.Object.is_class], [`is_function`][griffe.Object.is_function], [`is_attribute`][griffe.Object.is_attribute], [`is_type_alias`][griffe.Object.is_type_alias], and [`is_alias`][griffe.Object.is_alias] attributes. +- With the [`is_module`][griffelib.Object.is_module], [`is_class`][griffelib.Object.is_class], [`is_function`][griffelib.Object.is_function], [`is_attribute`][griffelib.Object.is_attribute], [`is_type_alias`][griffelib.Object.is_type_alias], and [`is_alias`][griffelib.Object.is_alias] attributes. Additionally, it is possible to check if an object is a sub-kind of module, with the following attributes: -- [`is_init_module`][griffe.Object.is_init_module], for `__init__.py` modules -- [`is_package`][griffe.Object.is_package], for top-level packages -- [`is_subpackage`][griffe.Object.is_subpackage], for non-top-level packages -- [`is_namespace_package`][griffe.Object.is_namespace_package], for top-level [namespace packages](https://packaging.python.org/en/latest/guides/packaging-namespace-packages/) -- [`is_namespace_subpackage`][griffe.Object.is_namespace_subpackage], for non-top-level namespace packages +- [`is_init_module`][griffelib.Object.is_init_module], for `__init__.py` modules +- [`is_package`][griffelib.Object.is_package], for top-level packages +- [`is_subpackage`][griffelib.Object.is_subpackage], for non-top-level packages +- [`is_namespace_package`][griffelib.Object.is_namespace_package], for top-level [namespace packages](https://packaging.python.org/en/latest/guides/packaging-namespace-packages/) +- [`is_namespace_subpackage`][griffelib.Object.is_namespace_subpackage], for non-top-level namespace packages -Finally, additional [`labels`][griffe.Object.labels] are attached to objects to further specify their kind. The [`has_labels()`][griffe.Object.has_labels] method can be used to check if an object has several specific labels. +Finally, additional [`labels`][griffelib.Object.labels] are attached to objects to further specify their kind. The [`has_labels()`][griffelib.Object.has_labels] method can be used to check if an object has several specific labels. ## Object location -An object is identified by its [`path`][griffe.Object.path], which is its location in the object tree. The path is composed of all the parent names and the object name, separated by dots, for example `mod.Class.meth`. This `path` is the [`canonical_path`][griffe.Object.canonical_path] on regular objects. For aliases however, the `path` is *where they are imported* while the canonical path is *where they come from*. Example: +An object is identified by its [`path`][griffelib.Object.path], which is its location in the object tree. The path is composed of all the parent names and the object name, separated by dots, for example `mod.Class.meth`. This `path` is the [`canonical_path`][griffelib.Object.canonical_path] on regular objects. For aliases however, the `path` is *where they are imported* while the canonical path is *where they come from*. Example: ```python # pkg1.py @@ -254,7 +254,7 @@ from pkg2 import A as B ```pycon >>> import griffe ->>> B = griffe.load("pkg1.B") +>>> B = griffelib.load("pkg1.B") >>> B.path 'pkg1.B' >>> B.canonical_path @@ -265,20 +265,20 @@ from pkg2 import A as B Information on the actual source code of objects is available through the following attributes: -- [`filepath`][griffe.Object.filepath], the absolute path to the module the object appears in, for example `~/project/src/pkg/mod.py` -- [`relative_filepath`][griffe.Object.relative_filepath], the relative path to the module, compared to the current working directory, for example `src/pkg/mod.py` -- [`relative_package_filepath`][griffe.Object.relative_package_filepath], the relative path to the module, compared to the parent of the top-level package, for example `pkg/mod.py` -- [`lineno`][griffe.Object.lineno] and [`endlineno`][griffe.Object.endlineno], the starting and ending line numbers of the object in the source -- [`lines`][griffe.Object.lines], the lines of code defining the object (or importing the alias) -- [`source`][griffe.Object.source], the source lines concatenated as a single multiline string +- [`filepath`][griffelib.Object.filepath], the absolute path to the module the object appears in, for example `~/project/src/pkg/mod.py` +- [`relative_filepath`][griffelib.Object.relative_filepath], the relative path to the module, compared to the current working directory, for example `src/pkg/mod.py` +- [`relative_package_filepath`][griffelib.Object.relative_package_filepath], the relative path to the module, compared to the parent of the top-level package, for example `pkg/mod.py` +- [`lineno`][griffelib.Object.lineno] and [`endlineno`][griffelib.Object.endlineno], the starting and ending line numbers of the object in the source +- [`lines`][griffelib.Object.lines], the lines of code defining the object (or importing the alias) +- [`source`][griffelib.Object.source], the source lines concatenated as a single multiline string -Each object holds a reference to a [`lines_collection`][griffe.Object.lines_collection]. Similar to the modules collection, this lines collection is a dictionary whose keys are module file-paths and values are their contents as list of lines. The lines collection is populated by the loader. +Each object holds a reference to a [`lines_collection`][griffelib.Object.lines_collection]. Similar to the modules collection, this lines collection is a dictionary whose keys are module file-paths and values are their contents as list of lines. The lines collection is populated by the loader. ## Object visibility Each object has fields that are related to their visibility within the API. -- [`is_public`][griffe.Object.is_public]: whether this object is public (destined to be consumed by your users). For module-level objects, Griffe considers that the object is public if: +- [`is_public`][griffelib.Object.is_public]: whether this object is public (destined to be consumed by your users). For module-level objects, Griffe considers that the object is public if: - it is listed in its parent module's `__all__` attribute - or if its parent module does not declare `__all__`, and the object doesn't have a private name, and the object is not imported from elsewhere @@ -312,47 +312,47 @@ Each object has fields that are related to their visibility within the API. ... ``` -- [`is_deprecated`][griffe.Object.is_deprecated]: whether this object is deprecated and shouldn't be used. +- [`is_deprecated`][griffelib.Object.is_deprecated]: whether this object is deprecated and shouldn't be used. -- [`is_special`][griffe.Object.is_special]: whether this object has a special name like `__special__` +- [`is_special`][griffelib.Object.is_special]: whether this object has a special name like `__special__` -- [`is_private`][griffe.Object.is_private]: whether this object has a private name like `_private` or `__private`, but not `__special__` +- [`is_private`][griffelib.Object.is_private]: whether this object has a private name like `_private` or `__private`, but not `__special__` -- [`is_class_private`][griffe.Object.is_class_private]: whether this object has a class-private name like `__private` and is a member of a class +- [`is_class_private`][griffelib.Object.is_class_private]: whether this object has a class-private name like `__private` and is a member of a class Since `is_private` only checks the name of the object, it is not mutually exclusive with `is_public`. It means an object can return true for both `is_public` and `is_private`. We invite Griffe users to mostly rely on `is_public` and `not is_public`. -It is possible to force `is_public` and `is_deprecated` to return true or false by setting the [`public`][griffe.Object.public] and [`deprecated`][griffe.Object.deprecated] fields respectively. These fields are typically set by extensions that support new ways of marking objects as public or deprecated. +It is possible to force `is_public` and `is_deprecated` to return true or false by setting the [`public`][griffelib.Object.public] and [`deprecated`][griffelib.Object.deprecated] fields respectively. These fields are typically set by extensions that support new ways of marking objects as public or deprecated. ## Imports/exports -Modules and classes populate their [`imports`][griffe.Object.imports] field with names that were imported from other modules. Similarly, modules populate their [`exports`][griffe.Object.exports] field with names that were exported by being listed into the module's `__all__` attribute. Each object then provides then [`is_imported`][griffe.Object.is_imported] and [`is_exported`][griffe.Object.is_exported] fields, which tell if an object was imported or exported respectively. Additionally, objects also provide an [`is_wildcard_exposed`][griffe.Object.is_wildcard_exposed] field that tells if an object is exposed to wildcard imports, i.e. will be imported when another module does `from this_module import *`. +Modules and classes populate their [`imports`][griffelib.Object.imports] field with names that were imported from other modules. Similarly, modules populate their [`exports`][griffelib.Object.exports] field with names that were exported by being listed into the module's `__all__` attribute. Each object then provides then [`is_imported`][griffelib.Object.is_imported] and [`is_exported`][griffelib.Object.is_exported] fields, which tell if an object was imported or exported respectively. Additionally, objects also provide an [`is_wildcard_exposed`][griffelib.Object.is_wildcard_exposed] field that tells if an object is exposed to wildcard imports, i.e. will be imported when another module does `from this_module import *`. ## Docstrings -Each object has an optional [`docstring`][griffe.Object.docstring] attached to it. To check whether it has one without comparing against `None`, the two following fields can be used: +Each object has an optional [`docstring`][griffelib.Object.docstring] attached to it. To check whether it has one without comparing against `None`, the two following fields can be used: -- [`has_docstring`][griffe.Object.has_docstring]: whether this object has a docstring (even empty) -- [`has_docstrings`][griffe.Object.has_docstrings]: same thing, but recursive; whether this object or any of its members has a docstring (even empty) +- [`has_docstring`][griffelib.Object.has_docstring]: whether this object has a docstring (even empty) +- [`has_docstrings`][griffelib.Object.has_docstrings]: same thing, but recursive; whether this object or any of its members has a docstring (even empty) -[Docstrings][griffe.Docstring] provide their cleaned-up [`value`][griffe.Docstring.value] (de-indented string, stripped from leading and trailing newlines), as well as their starting and ending line numbers with [`lineno`][griffe.Docstring.lineno] and [`endlineno`][griffe.Docstring.endlineno]. +[Docstrings][griffelib.Docstring] provide their cleaned-up [`value`][griffelib.Docstring.value] (de-indented string, stripped from leading and trailing newlines), as well as their starting and ending line numbers with [`lineno`][griffelib.Docstring.lineno] and [`endlineno`][griffelib.Docstring.endlineno]. Docstrings can be parsed against several [docstring-styles](../../reference/docstrings.md), which are micro-formats that allow documenting things such as parameters, returned values, raised exceptions, etc.. -When loading a package, it is possible to specify the docstring style to attach to every docstring (see the `docstring_parser` parameter of [`griffe.load`][griffe.load]). Accessing the [`parsed`][griffe.Docstring.parsed] field of a docstring will use this style to parse the docstring and return a list of [docstring sections][advanced-api-sections]. Each section has a `value` whose shape depends on the section kind. For example, parameter sections have a list of parameter representations as value, while a text section only has a string as value. +When loading a package, it is possible to specify the docstring style to attach to every docstring (see the `docstring_parser` parameter of [`griffelib.load`][griffelib.load]). Accessing the [`parsed`][griffelib.Docstring.parsed] field of a docstring will use this style to parse the docstring and return a list of [docstring sections][advanced-api-sections]. Each section has a `value` whose shape depends on the section kind. For example, parameter sections have a list of parameter representations as value, while a text section only has a string as value. -After a package is loaded, it is still possible to change the style used for specific docstrings by either overriding their [`parser`][griffe.Docstring.parser] and [`parser_options`][griffe.Docstring.parser_options] attributes, or by calling their [`parse()`][griffe.Docstring.parse] method with a different style: +After a package is loaded, it is still possible to change the style used for specific docstrings by either overriding their [`parser`][griffelib.Docstring.parser] and [`parser_options`][griffelib.Docstring.parser_options] attributes, or by calling their [`parse()`][griffelib.Docstring.parse] method with a different style: ```pycon >>> import griffe ->>> markdown = griffe.load("markdown", docstring_parser="google") +>>> markdown = griffelib.load("markdown", docstring_parser="google") >>> markdown["Markdown"].docstring.parse("numpy") [...] ``` Do note, however, that the `parsed` attribute is cached, and won't be reset when overriding the `parser` or `parser_options` values. -Docstrings have a [`parent`][griffe.Docstring.parent] field too, that is a reference to their respective module, class, function, attribute or type alias. +Docstrings have a [`parent`][griffelib.Docstring.parent] field too, that is a reference to their respective module, class, function, attribute or type alias. ## Model-specific fields @@ -360,46 +360,46 @@ Models have most fields in common, but also have specific fields. ### Modules -- [`imports_future_annotations`][griffe.Module.imports_future_annotations]: Whether the module imports [future annotations](https://peps.python.org/pep-0563/), which changes the way we parse type annotations. -- [`overloads`][griffe.Module.overloads]: A dictionary to store overloads for module-level functions. +- [`imports_future_annotations`][griffelib.Module.imports_future_annotations]: Whether the module imports [future annotations](https://peps.python.org/pep-0563/), which changes the way we parse type annotations. +- [`overloads`][griffelib.Module.overloads]: A dictionary to store overloads for module-level functions. ### Classes -- [`bases`][griffe.Class.bases]: A list of class bases in the form of [expressions][griffe.Expr]. -- [`resolved_bases`][griffe.Class.resolved_bases]: A list of class bases, in the form of [Class][griffe.Class] objects. Only the bases that were loaded are returned, the others are discarded. -- [`mro()`][griffe.Class.mro]: A method to compute the Method Resolution Order in the form of a list of [Class][griffe.Class] objects. -- [`overloads`][griffe.Class.overloads]: A dictionary to store overloads for class-level methods. -- [`decorators`][griffe.Class.decorators]: The [decorators][griffe.Decorator] applied to the class. -- [`parameters`][griffe.Class.parameters]: The [parameters][griffe.Parameters] of the class' `__init__` method, if any. -- [`type_parameters`][griffe.Class.type_parameters]: The [type parameters][griffe.TypeParameters] of the class. +- [`bases`][griffelib.Class.bases]: A list of class bases in the form of [expressions][griffelib.Expr]. +- [`resolved_bases`][griffelib.Class.resolved_bases]: A list of class bases, in the form of [Class][griffelib.Class] objects. Only the bases that were loaded are returned, the others are discarded. +- [`mro()`][griffelib.Class.mro]: A method to compute the Method Resolution Order in the form of a list of [Class][griffelib.Class] objects. +- [`overloads`][griffelib.Class.overloads]: A dictionary to store overloads for class-level methods. +- [`decorators`][griffelib.Class.decorators]: The [decorators][griffelib.Decorator] applied to the class. +- [`parameters`][griffelib.Class.parameters]: The [parameters][griffelib.Parameters] of the class' `__init__` method, if any. +- [`type_parameters`][griffelib.Class.type_parameters]: The [type parameters][griffelib.TypeParameters] of the class. ### Functions -- [`decorators`][griffe.Function.decorators]: The [decorators][griffe.Decorator] applied to the function. -- [`overloads`][griffe.Function.overloads]: The overloaded signatures of the function. -- [`parameters`][griffe.Function.parameters]: The [parameters][griffe.Parameters] of the function. -- [`returns`][griffe.Function.returns]: The type annotation of the returned value, in the form of an [expression][griffe.Expr]. The `annotation` field can also be used, for compatibility with attributes. -- [`type_parameters`][griffe.Function.type_parameters]: The [type parameters][griffe.TypeParameters] of the function. +- [`decorators`][griffelib.Function.decorators]: The [decorators][griffelib.Decorator] applied to the function. +- [`overloads`][griffelib.Function.overloads]: The overloaded signatures of the function. +- [`parameters`][griffelib.Function.parameters]: The [parameters][griffelib.Parameters] of the function. +- [`returns`][griffelib.Function.returns]: The type annotation of the returned value, in the form of an [expression][griffelib.Expr]. The `annotation` field can also be used, for compatibility with attributes. +- [`type_parameters`][griffelib.Function.type_parameters]: The [type parameters][griffelib.TypeParameters] of the function. ### Attributes -- [`annotation`][griffe.Attribute.annotation]: The type annotation of the attribute, in the form of an [expression][griffe.Expr]. -- [`value`][griffe.Attribute.value]: The value of the attribute, in the form of an [expression][griffe.Expr]. -- [`deleter`][griffe.Attribute.deleter]: The property deleter. -- [`setter`][griffe.Attribute.setter]: The property setter. +- [`annotation`][griffelib.Attribute.annotation]: The type annotation of the attribute, in the form of an [expression][griffelib.Expr]. +- [`value`][griffelib.Attribute.value]: The value of the attribute, in the form of an [expression][griffelib.Expr]. +- [`deleter`][griffelib.Attribute.deleter]: The property deleter. +- [`setter`][griffelib.Attribute.setter]: The property setter. ### Type aliases -- [`value`][griffe.TypeAlias.value]: The value of the type alias, in the form of an [expression][griffe.Expr]. -- [`type_parameters`][griffe.TypeAlias.type_parameters]: The [type parameters][griffe.TypeParameters] of the type alias. +- [`value`][griffelib.TypeAlias.value]: The value of the type alias, in the form of an [expression][griffelib.Expr]. +- [`type_parameters`][griffelib.TypeAlias.type_parameters]: The [type parameters][griffelib.TypeParameters] of the type alias. ### Alias -- [`alias_lineno`][griffe.Alias.alias_lineno]: The alias line number (where the object is imported). -- [`alias_endlineno`][griffe.Alias.alias_endlineno]: The alias ending line number (where the object is imported). -- [`target`][griffe.Alias.target]: The alias target (a module, class, function or attribute). -- [`target_path`][griffe.Alias.target_path]: The path of the alias target, as a string. -- [`wildcard`][griffe.Alias.wildcard]: Whether this alias represents a wildcard import, and if so from which module. -- [`resolve_target()`][griffe.Alias.resolve_target]: A method that resolves the target when called. +- [`alias_lineno`][griffelib.Alias.alias_lineno]: The alias line number (where the object is imported). +- [`alias_endlineno`][griffelib.Alias.alias_endlineno]: The alias ending line number (where the object is imported). +- [`target`][griffelib.Alias.target]: The alias target (a module, class, function or attribute). +- [`target_path`][griffelib.Alias.target_path]: The path of the alias target, as a string. +- [`wildcard`][griffelib.Alias.wildcard]: Whether this alias represents a wildcard import, and if so from which module. +- [`resolve_target()`][griffelib.Alias.resolve_target]: A method that resolves the target when called. ## Expressions @@ -444,7 +444,7 @@ The Python language keeps evolving, and often library developers must continue s Yet this doesn't mean they can't enjoy latest features in their own docs: Griffe allows to "modernize" expressions, for example by replacing `typing.Union` with PEP 604 type unions `|`. Thanks to this, downstream tools like [mkdocstrings][mkdocstrings-python] can automatically transform type annotations into their modern equivalent. This improves consistency in your docs, and shows users how to use your code with the latest features of the language. -To modernize an expression, simply call its [`modernize()`][griffe.Expr.modernize] method. It returns a new, modernized expression. Some parts of the expression might be left unchanged, so be careful if you decide to mutate them. +To modernize an expression, simply call its [`modernize()`][griffelib.Expr.modernize] method. It returns a new, modernized expression. Some parts of the expression might be left unchanged, so be careful if you decide to mutate them. Modernizations applied: diff --git a/docs/guide/users/recommendations/public-apis.md b/docs/guide/users/recommendations/public-apis.md index 9a0d1cbbd..c7b525c95 100644 --- a/docs/guide/users/recommendations/public-apis.md +++ b/docs/guide/users/recommendations/public-apis.md @@ -287,7 +287,7 @@ Start hiding your module layout early! It is much easier to (partially) expose t ## Unique names and public locations -Whether or not you are planning to hide your module layout, as recommended in the previous section, one thing that will help both you and your users is making sure your object names are unique across your code base. Having unique names ensures that you can expose everything at the top-level module of your package without having to alias objects (using `from ... import x as y`). It will also ensure that your users don't end up importing multiple different objects with the same name, again having to alias them. Finally, it forces you to use meaningful names for your objects, names that don't need the context of the above namespaces (generally modules) to understand what they mean. For example, in Griffe we previously exposed `griffe.docstrings.utils.warning`. Exposing `warning` at the top-level made it very vague: what does it do? So we renamed it `docstring_warning`, which is much clearer. +Whether or not you are planning to hide your module layout, as recommended in the previous section, one thing that will help both you and your users is making sure your object names are unique across your code base. Having unique names ensures that you can expose everything at the top-level module of your package without having to alias objects (using `from ... import x as y`). It will also ensure that your users don't end up importing multiple different objects with the same name, again having to alias them. Finally, it forces you to use meaningful names for your objects, names that don't need the context of the above namespaces (generally modules) to understand what they mean. For example, in Griffe we previously exposed `griffelib.docstrings.utils.warning`. Exposing `warning` at the top-level made it very vague: what does it do? So we renamed it `docstring_warning`, which is much clearer. Ensuring unique names across a code base is sometimes not feasible, or not desirable; in this case, try to use namespacing while still hiding the module layout the best you can. @@ -422,7 +422,7 @@ The first user of your CLI as API is... you. When you declare your project's CLI ```toml [project.scripts] -griffe = "griffe:main" +griffe = "griffecli:main" ``` ...this entrypoint ends up as a Python script in the `bin` directory of your virtual environment: @@ -438,7 +438,7 @@ if __name__ == "__main__": sys.exit(main()) ``` -In this script, we find our entrypoint, `griffe.main`, used programmatically. +In this script, we find our entrypoint, `griffecli.main`, used programmatically. --- @@ -450,21 +450,21 @@ import griffe def test_main() -> None: - assert griffe.main(["dump", "griffe", "-s", "src", "-o/dev/null"]) == 0 + assert griffecli.main(["dump", "griffe", "-s", "src", "-o/dev/null"]) == 0 def test_show_help(capsys: pytest.CaptureFixture) -> None: with pytest.raises(SystemExit): - griffe.main(["-h"]) + griffecli.main(["-h"]) captured = capsys.readouterr() assert "griffe" in captured.out def test_show_version(capsys: pytest.CaptureFixture) -> None: with pytest.raises(SystemExit): - griffe.main(["-V"]) + griffecli.main(["-V"]) captured = capsys.readouterr() - assert griffe.get_version() in captured.out + assert griffelib.get_version() in captured.out ``` Now, when you start testing the logic of your CLI subcommands, such as our `dump` subcommand above, you might feel like passing again and again through the command-line arguments parser (here `argparse`) is wasteful and redundant. It is important to test that your arguments are parsed correctly (as you expect them to be parsed), but they shouldn't *have* to be parsed when you are testing the underlying logic. diff --git a/docs/guide/users/serializing.md b/docs/guide/users/serializing.md index 6adcfb4e6..ddc9e840b 100644 --- a/docs/guide/users/serializing.md +++ b/docs/guide/users/serializing.md @@ -7,7 +7,7 @@ Griffe can be used to load API data and output it as JSON on standard output or The easiest way to load and serialize API data is to use the command-line tool: ```console -$ griffe dump httpx fastapi +$ griffecli dump httpx fastapi { "httpx": { "name": "httpx", @@ -25,7 +25,7 @@ It will output a JSON-serialized version of the package's API data. Try it out on Griffe itself: ```console -$ griffe dump griffe +$ griffecli dump griffe { "griffe": { "name": "griffe", @@ -37,13 +37,13 @@ $ griffe dump griffe To output in a file instead of standard output, use the `-o`, `--output` option: ```console -$ griffe dump griffe -o griffe.json +$ griffecli dump griffe -o griffelib.json ``` If you load multiple packages' signatures, you can dump each in its own file with a templated filepath: ```console -$ griffe dump griffe -o './dumps/{package}.json' +$ griffecli dump griffe -o './dumps/{package}.json' ``` By default, Griffe will search in `sys.path`, so if you installed it through *pipx*, there are few chances it will find your packages. To explicitly specify search paths, use the `-s, --search ` option. You can use it multiple times. You can also add the search paths to the `PYTHONPATH` environment variable. If Griffe can't find the packages, it will fail with a `ModuleNotFoundError`. @@ -54,14 +54,14 @@ See all the options for the `dump` command in the [CLI reference](../../referenc If you have read through the [Navigating](navigating.md) chapter, you know about our six data models for modules, classes, functions, attributes, type aliases and aliases. Each one of these model provide the two following methods: -- [`as_json`][griffe.Object.as_json], which allows to serialize an object into JSON, -- [`from_json`][griffe.Object.from_json], which allows loading JSON back into a model instance. +- [`as_json`][griffelib.Object.as_json], which allows to serialize an object into JSON, +- [`from_json`][griffelib.Object.from_json], which allows loading JSON back into a model instance. -These two methods are convenient wrappers around our [JSON encoder][griffe.JSONEncoder] and [JSON decoder][griffe.json_decoder]. The JSON encoder and decoder will give you finer-grain control over what you serialize or load, as the methods above are only available on data models, and not on sub-structures like decorators or parameters. +These two methods are convenient wrappers around our [JSON encoder][griffelib.JSONEncoder] and [JSON decoder][griffelib.json_decoder]. The JSON encoder and decoder will give you finer-grain control over what you serialize or load, as the methods above are only available on data models, and not on sub-structures like decorators or parameters. -Under the hood, `as_json` just calls [`as_dict`][griffe.Object.as_dict], which converts the model instance into a dictionary, and then serializes this dictionary to JSON. +Under the hood, `as_json` just calls [`as_dict`][griffelib.Object.as_dict], which converts the model instance into a dictionary, and then serializes this dictionary to JSON. -When serializing an object, by default the JSON will only contain the fields required to load it back to a Griffe model instance. If you are not planning on loading back the data into our data models, or if you want to load them in a different implementation which is not able to infer back all the other fields, you can choose to serialize every possible field. We call this a full dump, and it is enabled with the `full` option of the [encoder][griffe.JSONEncoder] or the [`as_json`][griffe.Object.as_json] method. +When serializing an object, by default the JSON will only contain the fields required to load it back to a Griffe model instance. If you are not planning on loading back the data into our data models, or if you want to load them in a different implementation which is not able to infer back all the other fields, you can choose to serialize every possible field. We call this a full dump, and it is enabled with the `full` option of the [encoder][griffelib.JSONEncoder] or the [`as_json`][griffelib.Object.as_json] method. ## Schema diff --git a/docs/index.md b/docs/index.md index efb9818a1..79b1851ae 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,7 +10,7 @@ hide: Griffe logo, created by François Rozet <francois.rozet@outlook.com> -> Griffe, pronounced "grif" (`/ɡʁif/`), is a french word that means "claw", but also "signature" in a familiar way. "On reconnaît bien là sa griffe." +> Griffe, pronounced "grif" (`/ɡʁif/`), is a french word that means "claw", but also "signature" in a familiar way. "On reconnaît bien là sa griffelib."
@@ -41,17 +41,17 @@ Griffe can be used as a Python library. For example, the [Python handler](https:
-```console exec="1" source="console" result="json" title="Serializing as JSON" id="griffe-dump" +```console exec="1" source="console" result="json" title="Serializing as JSON" id="griffecli-dump" $ export FORCE_COLOR=1 # markdown-exec: hide -$ griffe dump griffe -ssrc -r 2>/dev/null | head -n29 +$ griffecli dump griffe -ssrc -r 2>/dev/null | head -n29 ```
-```console exec="1" source="console" result="ansi" returncode="1" title="Checking for API breaking changes" id="griffe-check" +```console exec="1" source="console" result="ansi" returncode="1" title="Checking for API breaking changes" id="griffecli-check" $ export FORCE_COLOR=1 # markdown-exec: hide -$ griffe check griffe -ssrc -b0.46.0 -a0.45.0 --verbose +$ griffecli check griffe -ssrc -b0.46.0 -a0.45.0 --verbose ```
diff --git a/docs/introduction.md b/docs/introduction.md index a7226fa6e..bf16b1fc5 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -9,13 +9,13 @@ Griffe is both a command line tool and a Python library. The command line tool o ```bash # Load API of `my_package`, serialize it to JSON, # print it to standard output. -griffe dump my_package +griffecli dump my_package ``` ```bash # Check for API breaking changes # between current version and version 1.0 (Git reference). -griffe check my_package --against 1.0 +griffecli check my_package --against 1.0 ``` Both commands accept a `-h`, `--help` argument to show all the available options. For a complete reference of the command line interface, see [Reference / Command line interface](reference/cli.md). @@ -27,31 +27,31 @@ As a library, Griffe exposes all its public API directly in the top-level module ```python import griffe -griffe.load(...) -griffe.find_breaking_changes(...) -griffe.main(...) -griffe.visit(...) -griffe.inspect(...) +griffelib.load(...) +griffelib.find_breaking_changes(...) +griffecli.main(...) +griffelib.visit(...) +griffelib.inspect(...) ``` -To start exploring your API within Griffe data models, use the [`load`][griffe.load] function to load your package and access its various objects: +To start exploring your API within Griffe data models, use the [`load`][griffelib.load] function to load your package and access its various objects: ```python import griffe -my_package = griffe.load("my_package") +my_package = griffelib.load("my_package") some_method = my_package["some_module.SomeClass.some_method"] print(some_method.docstring.value) print(f"Is `some_method` public? {'yes' if some_method.is_public else 'no'}") ``` -Use the [`load_git`][griffe.load_git] function to load your API at a particular moment in time, specified with a Git reference (commit hash, branch name, tag name): +Use the [`load_git`][griffelib.load_git] function to load your API at a particular moment in time, specified with a Git reference (commit hash, branch name, tag name): ```python import griffe -my_package_v2_1 = griffe.load_git("my_package", ref="2.1") +my_package_v2_1 = griffelib.load_git("my_package", ref="2.1") ``` For more advanced usage, see our guide on [loading and navigating data](guide/users/loading.md). diff --git a/docs/playground.md b/docs/playground.md index 55869f3c0..4039ad3ce 100644 --- a/docs/playground.md +++ b/docs/playground.md @@ -16,6 +16,6 @@ import griffe, micropip await micropip.install("cowsay") # And load it with Griffe! -cowsay = griffe.load("cowsay") +cowsay = griffelib.load("cowsay") cowsay.as_json(indent=2)[:1000] ``` diff --git a/docs/reference/api/agents.md b/docs/reference/api/agents.md index ca7f50c4d..c4b78f9c9 100644 --- a/docs/reference/api/agents.md +++ b/docs/reference/api/agents.md @@ -4,70 +4,70 @@ Griffe is able to analyze code both statically and dynamically. ## **Main API** -::: griffe.visit +::: griffelib.visit -::: griffe.inspect +::: griffelib.inspect ## **Advanced API** -::: griffe.Visitor +::: griffelib.Visitor -::: griffe.Inspector +::: griffelib.Inspector ## **Dynamic analysis helpers** -::: griffe.sys_path +::: griffelib.sys_path -::: griffe.dynamic_import +::: griffelib.dynamic_import -::: griffe.ObjectNode +::: griffelib.ObjectNode -::: griffe.ObjectKind +::: griffelib.ObjectKind ## **Static analysis helpers** -::: griffe.builtin_decorators +::: griffelib.builtin_decorators -::: griffe.stdlib_decorators +::: griffelib.stdlib_decorators -::: griffe.typing_overload +::: griffelib.typing_overload -::: griffe.ast_kind +::: griffelib.ast_kind -::: griffe.ast_children +::: griffelib.ast_children -::: griffe.ast_previous_siblings +::: griffelib.ast_previous_siblings -::: griffe.ast_next_siblings +::: griffelib.ast_next_siblings -::: griffe.ast_siblings +::: griffelib.ast_siblings -::: griffe.ast_previous +::: griffelib.ast_previous -::: griffe.ast_next +::: griffelib.ast_next -::: griffe.ast_first_child +::: griffelib.ast_first_child -::: griffe.ast_last_child +::: griffelib.ast_last_child -::: griffe.get_docstring +::: griffelib.get_docstring -::: griffe.get_name +::: griffelib.get_name -::: griffe.get_names +::: griffelib.get_names -::: griffe.get_instance_names +::: griffelib.get_instance_names -::: griffe.get__all__ +::: griffelib.get__all__ -::: griffe.safe_get__all__ +::: griffelib.safe_get__all__ -::: griffe.relative_to_absolute +::: griffelib.relative_to_absolute -::: griffe.get_parameters +::: griffelib.get_parameters -::: griffe.get_value +::: griffelib.get_value -::: griffe.safe_get_value +::: griffelib.safe_get_value diff --git a/docs/reference/api/checks.md b/docs/reference/api/checks.md index 9caa656e5..a30110d55 100644 --- a/docs/reference/api/checks.md +++ b/docs/reference/api/checks.md @@ -1,33 +1,33 @@ # API checks -::: griffe.find_breaking_changes +::: griffelib.find_breaking_changes -::: griffe.ExplanationStyle +::: griffelib.ExplanationStyle -::: griffe.Breakage +::: griffelib.Breakage -::: griffe.BreakageKind +::: griffelib.BreakageKind -::: griffe.AttributeChangedTypeBreakage +::: griffelib.AttributeChangedTypeBreakage -::: griffe.AttributeChangedValueBreakage +::: griffelib.AttributeChangedValueBreakage -::: griffe.ClassRemovedBaseBreakage +::: griffelib.ClassRemovedBaseBreakage -::: griffe.ObjectChangedKindBreakage +::: griffelib.ObjectChangedKindBreakage -::: griffe.ObjectRemovedBreakage +::: griffelib.ObjectRemovedBreakage -::: griffe.ParameterAddedRequiredBreakage +::: griffelib.ParameterAddedRequiredBreakage -::: griffe.ParameterChangedDefaultBreakage +::: griffelib.ParameterChangedDefaultBreakage -::: griffe.ParameterChangedKindBreakage +::: griffelib.ParameterChangedKindBreakage -::: griffe.ParameterChangedRequiredBreakage +::: griffelib.ParameterChangedRequiredBreakage -::: griffe.ParameterMovedBreakage +::: griffelib.ParameterMovedBreakage -::: griffe.ParameterRemovedBreakage +::: griffelib.ParameterRemovedBreakage -::: griffe.ReturnChangedTypeBreakage +::: griffelib.ReturnChangedTypeBreakage diff --git a/docs/reference/api/cli.md b/docs/reference/api/cli.md index 08e83a31a..c806e83cf 100644 --- a/docs/reference/api/cli.md +++ b/docs/reference/api/cli.md @@ -2,12 +2,12 @@ ## **Main API** -::: griffe.main +::: griffecli.main -::: griffe.check +::: griffecli.check -::: griffe.dump +::: griffecli.dump ## **Advanced API** -::: griffe.get_parser +::: griffecli.get_parser diff --git a/docs/reference/api/docstrings/models.md b/docs/reference/api/docstrings/models.md index 17f3bdfd9..ff4b97a25 100644 --- a/docs/reference/api/docstrings/models.md +++ b/docs/reference/api/docstrings/models.md @@ -2,80 +2,80 @@ ## **Main API** -::: griffe.Docstring +::: griffelib.Docstring ## **Advanced API: Sections** -::: griffe.DocstringSectionKind +::: griffelib.DocstringSectionKind -::: griffe.DocstringSectionText +::: griffelib.DocstringSectionText -::: griffe.DocstringSectionParameters +::: griffelib.DocstringSectionParameters -::: griffe.DocstringSectionOtherParameters +::: griffelib.DocstringSectionOtherParameters -::: griffe.DocstringSectionTypeParameters +::: griffelib.DocstringSectionTypeParameters -::: griffe.DocstringSectionRaises +::: griffelib.DocstringSectionRaises -::: griffe.DocstringSectionWarns +::: griffelib.DocstringSectionWarns -::: griffe.DocstringSectionReturns +::: griffelib.DocstringSectionReturns -::: griffe.DocstringSectionYields +::: griffelib.DocstringSectionYields -::: griffe.DocstringSectionReceives +::: griffelib.DocstringSectionReceives -::: griffe.DocstringSectionExamples +::: griffelib.DocstringSectionExamples -::: griffe.DocstringSectionAttributes +::: griffelib.DocstringSectionAttributes -::: griffe.DocstringSectionFunctions +::: griffelib.DocstringSectionFunctions -::: griffe.DocstringSectionClasses +::: griffelib.DocstringSectionClasses -::: griffe.DocstringSectionTypeAliases +::: griffelib.DocstringSectionTypeAliases -::: griffe.DocstringSectionModules +::: griffelib.DocstringSectionModules -::: griffe.DocstringSectionDeprecated +::: griffelib.DocstringSectionDeprecated -::: griffe.DocstringSectionAdmonition +::: griffelib.DocstringSectionAdmonition ## **Advanced API: Section items** -::: griffe.DocstringAdmonition +::: griffelib.DocstringAdmonition -::: griffe.DocstringDeprecated +::: griffelib.DocstringDeprecated -::: griffe.DocstringRaise +::: griffelib.DocstringRaise -::: griffe.DocstringWarn +::: griffelib.DocstringWarn -::: griffe.DocstringReturn +::: griffelib.DocstringReturn -::: griffe.DocstringYield +::: griffelib.DocstringYield -::: griffe.DocstringReceive +::: griffelib.DocstringReceive -::: griffe.DocstringParameter +::: griffelib.DocstringParameter -::: griffe.DocstringTypeParameter +::: griffelib.DocstringTypeParameter -::: griffe.DocstringAttribute +::: griffelib.DocstringAttribute -::: griffe.DocstringFunction +::: griffelib.DocstringFunction -::: griffe.DocstringClass +::: griffelib.DocstringClass -::: griffe.DocstringTypeAlias +::: griffelib.DocstringTypeAlias -::: griffe.DocstringModule +::: griffelib.DocstringModule ## **Models base classes** -::: griffe.DocstringElement +::: griffelib.DocstringElement -::: griffe.DocstringNamedElement +::: griffelib.DocstringNamedElement -::: griffe.DocstringSection +::: griffelib.DocstringSection diff --git a/docs/reference/api/docstrings/parsers.md b/docs/reference/api/docstrings/parsers.md index 625d1dbb0..e4345ba77 100644 --- a/docs/reference/api/docstrings/parsers.md +++ b/docs/reference/api/docstrings/parsers.md @@ -2,42 +2,42 @@ ## **Main API** -::: griffe.parse +::: griffelib.parse -::: griffe.parse_auto +::: griffelib.parse_auto -::: griffe.parse_google +::: griffelib.parse_google -::: griffe.parse_numpy +::: griffelib.parse_numpy -::: griffe.parse_sphinx +::: griffelib.parse_sphinx -::: griffe.DocstringStyle +::: griffelib.DocstringStyle ## **Parser options** -::: griffe.DocstringOptions +::: griffelib.DocstringOptions -::: griffe.GoogleOptions +::: griffelib.GoogleOptions -::: griffe.NumpyOptions +::: griffelib.NumpyOptions -::: griffe.SphinxOptions +::: griffelib.SphinxOptions -::: griffe.AutoOptions +::: griffelib.AutoOptions -::: griffe.PerStyleOptions +::: griffelib.PerStyleOptions ## **Advanced API** -::: griffe.Parser +::: griffelib.Parser -::: griffe.parsers +::: griffelib.parsers -::: griffe.parse_docstring_annotation +::: griffelib.parse_docstring_annotation -::: griffe.docstring_warning +::: griffelib.docstring_warning -::: griffe.DocstringDetectionMethod +::: griffelib.DocstringDetectionMethod -::: griffe.infer_docstring_style +::: griffelib.infer_docstring_style diff --git a/docs/reference/api/exceptions.md b/docs/reference/api/exceptions.md index e33a10071..8630c15ec 100644 --- a/docs/reference/api/exceptions.md +++ b/docs/reference/api/exceptions.md @@ -1,27 +1,27 @@ # Exceptions -::: griffe.GriffeError +::: griffelib.GriffeError -::: griffe.LoadingError +::: griffelib.LoadingError -::: griffe.NameResolutionError +::: griffelib.NameResolutionError -::: griffe.UnhandledEditableModuleError +::: griffelib.UnhandledEditableModuleError -::: griffe.UnimportableModuleError +::: griffelib.UnimportableModuleError -::: griffe.AliasResolutionError +::: griffelib.AliasResolutionError -::: griffe.CyclicAliasError +::: griffelib.CyclicAliasError -::: griffe.LastNodeError +::: griffelib.LastNodeError -::: griffe.RootNodeError +::: griffelib.RootNodeError -::: griffe.BuiltinModuleError +::: griffelib.BuiltinModuleError -::: griffe.ExtensionError +::: griffelib.ExtensionError -::: griffe.ExtensionNotLoadedError +::: griffelib.ExtensionNotLoadedError -::: griffe.GitError +::: griffelib.GitError diff --git a/docs/reference/api/expressions.md b/docs/reference/api/expressions.md index 3b010a5d0..4b3395c39 100644 --- a/docs/reference/api/expressions.md +++ b/docs/reference/api/expressions.md @@ -1,6 +1,6 @@ # Expressions -::: griffe._internal.expressions +::: griffelib._internal.expressions options: members: false show_root_heading: false @@ -10,88 +10,88 @@ ## **Helpers** -::: griffe.get_annotation +::: griffelib.get_annotation -::: griffe.get_base_class +::: griffelib.get_base_class -::: griffe.get_class_keyword +::: griffelib.get_class_keyword -::: griffe.get_condition +::: griffelib.get_condition -::: griffe.get_expression +::: griffelib.get_expression -::: griffe.safe_get_annotation +::: griffelib.safe_get_annotation -::: griffe.safe_get_base_class +::: griffelib.safe_get_base_class -::: griffe.safe_get_class_keyword +::: griffelib.safe_get_class_keyword -::: griffe.safe_get_condition +::: griffelib.safe_get_condition -::: griffe.safe_get_expression +::: griffelib.safe_get_expression ## **Expression nodes** -::: griffe.Expr +::: griffelib.Expr -::: griffe.ExprAttribute +::: griffelib.ExprAttribute -::: griffe.ExprBinOp +::: griffelib.ExprBinOp -::: griffe.ExprBoolOp +::: griffelib.ExprBoolOp -::: griffe.ExprCall +::: griffelib.ExprCall -::: griffe.ExprCompare +::: griffelib.ExprCompare -::: griffe.ExprComprehension +::: griffelib.ExprComprehension -::: griffe.ExprConstant +::: griffelib.ExprConstant -::: griffe.ExprDict +::: griffelib.ExprDict -::: griffe.ExprDictComp +::: griffelib.ExprDictComp -::: griffe.ExprExtSlice +::: griffelib.ExprExtSlice -::: griffe.ExprFormatted +::: griffelib.ExprFormatted -::: griffe.ExprGeneratorExp +::: griffelib.ExprGeneratorExp -::: griffe.ExprIfExp +::: griffelib.ExprIfExp -::: griffe.ExprJoinedStr +::: griffelib.ExprJoinedStr -::: griffe.ExprKeyword +::: griffelib.ExprKeyword -::: griffe.ExprVarPositional +::: griffelib.ExprVarPositional -::: griffe.ExprVarKeyword +::: griffelib.ExprVarKeyword -::: griffe.ExprLambda +::: griffelib.ExprLambda -::: griffe.ExprList +::: griffelib.ExprList -::: griffe.ExprListComp +::: griffelib.ExprListComp -::: griffe.ExprName +::: griffelib.ExprName -::: griffe.ExprNamedExpr +::: griffelib.ExprNamedExpr -::: griffe.ExprParameter +::: griffelib.ExprParameter -::: griffe.ExprSet +::: griffelib.ExprSet -::: griffe.ExprSetComp +::: griffelib.ExprSetComp -::: griffe.ExprSlice +::: griffelib.ExprSlice -::: griffe.ExprSubscript +::: griffelib.ExprSubscript -::: griffe.ExprTuple +::: griffelib.ExprTuple -::: griffe.ExprUnaryOp +::: griffelib.ExprUnaryOp -::: griffe.ExprYield +::: griffelib.ExprYield -::: griffe.ExprYieldFrom +::: griffelib.ExprYieldFrom diff --git a/docs/reference/api/extensions.md b/docs/reference/api/extensions.md index 42ee96a80..8ae746205 100644 --- a/docs/reference/api/extensions.md +++ b/docs/reference/api/extensions.md @@ -2,26 +2,26 @@ ## **Main API** -::: griffe.load_extensions +::: griffelib.load_extensions -::: griffe.Extension +::: griffelib.Extension ## **Advanced API** -::: griffe.Extensions +::: griffelib.Extensions ## **Types** -::: griffe.LoadableExtensionType +::: griffelib.LoadableExtensionType ## **Builtin extensions** -::: griffe.builtin_extensions +::: griffelib.builtin_extensions -::: griffe.DataclassesExtension +::: griffelib.DataclassesExtension options: inherited_members: false -::: griffe.UnpackTypedDictExtension +::: griffelib.UnpackTypedDictExtension options: inherited_members: false diff --git a/docs/reference/api/finder.md b/docs/reference/api/finder.md index 54c452e31..f79f92565 100644 --- a/docs/reference/api/finder.md +++ b/docs/reference/api/finder.md @@ -2,14 +2,14 @@ ## **Advanced API** -::: griffe.ModuleFinder +::: griffelib.ModuleFinder -::: griffe.Package +::: griffelib.Package -::: griffe.NamespacePackage +::: griffelib.NamespacePackage ## **Types** -::: griffe.NamePartsType +::: griffelib.NamePartsType -::: griffe.NamePartsAndPathType +::: griffelib.NamePartsAndPathType diff --git a/docs/reference/api/helpers.md b/docs/reference/api/helpers.md index 74e44d05a..4267786da 100644 --- a/docs/reference/api/helpers.md +++ b/docs/reference/api/helpers.md @@ -1,21 +1,21 @@ # Helpers -::: griffe.TmpPackage +::: griffelib.TmpPackage -::: griffe.temporary_pyfile +::: griffelib.temporary_pyfile -::: griffe.temporary_pypackage +::: griffelib.temporary_pypackage -::: griffe.temporary_visited_module +::: griffelib.temporary_visited_module -::: griffe.temporary_visited_package +::: griffelib.temporary_visited_package -::: griffe.temporary_inspected_module +::: griffelib.temporary_inspected_module -::: griffe.temporary_inspected_package +::: griffelib.temporary_inspected_package -::: griffe.vtree +::: griffelib.vtree -::: griffe.htree +::: griffelib.htree -::: griffe.module_vtree +::: griffelib.module_vtree diff --git a/docs/reference/api/loaders.md b/docs/reference/api/loaders.md index b3eb060c9..10dccf38c 100644 --- a/docs/reference/api/loaders.md +++ b/docs/reference/api/loaders.md @@ -2,22 +2,22 @@ ## **Main API** -::: griffe.load +::: griffelib.load -::: griffe.load_git +::: griffelib.load_git -::: griffe.load_pypi +::: griffelib.load_pypi ## **Advanced API** -::: griffe.GriffeLoader +::: griffelib.GriffeLoader -::: griffe.ModulesCollection +::: griffelib.ModulesCollection -::: griffe.LinesCollection +::: griffelib.LinesCollection ## **Additional API** -::: griffe.Stats +::: griffelib.Stats -::: griffe.merge_stubs +::: griffelib.merge_stubs diff --git a/docs/reference/api/loggers.md b/docs/reference/api/loggers.md index 0ba1d0dbd..2611b9c2e 100644 --- a/docs/reference/api/loggers.md +++ b/docs/reference/api/loggers.md @@ -2,18 +2,18 @@ ## **Main API** -::: griffe.logger +::: griffelib.logger -::: griffe.get_logger +::: griffelib.get_logger -::: griffe.Logger +::: griffelib.Logger -::: griffe.LogLevel +::: griffelib.LogLevel -::: griffe.DEFAULT_LOG_LEVEL +::: griffecli.DEFAULT_LOG_LEVEL options: annotations_path: full ## **Advanced API** -::: griffe.patch_loggers +::: griffelib.patch_loggers diff --git a/docs/reference/api/models.md b/docs/reference/api/models.md index 3b7f35316..76732f917 100644 --- a/docs/reference/api/models.md +++ b/docs/reference/api/models.md @@ -10,41 +10,41 @@ Indirections to objects declared in other modules are represented as "aliases". The 6 models: -- [`Module`][griffe.Module] -- [`Class`][griffe.Class] -- [`Function`][griffe.Function] -- [`Attribute`][griffe.Attribute] -- [`Alias`][griffe.Alias] -- [`TypeAlias`][griffe.TypeAlias] +- [`Module`][griffelib.Module] +- [`Class`][griffelib.Class] +- [`Function`][griffelib.Function] +- [`Attribute`][griffelib.Attribute] +- [`Alias`][griffelib.Alias] +- [`TypeAlias`][griffelib.TypeAlias] ## **Model kind enumeration** -::: griffe.Kind +::: griffelib.Kind ## **Model base classes** -::: griffe.GetMembersMixin +::: griffelib.GetMembersMixin -::: griffe.SetMembersMixin +::: griffelib.SetMembersMixin -::: griffe.DelMembersMixin +::: griffelib.DelMembersMixin -::: griffe.SerializationMixin +::: griffelib.SerializationMixin -::: griffe.ObjectAliasMixin +::: griffelib.ObjectAliasMixin -::: griffe.Object +::: griffelib.Object ## **Type parameters** -::: griffe.TypeParameters +::: griffelib.TypeParameters -::: griffe.TypeParameter +::: griffelib.TypeParameter -::: griffe.TypeParameterKind +::: griffelib.TypeParameterKind ## **Git information** -::: griffe.KnownGitService +::: griffelib.KnownGitService -::: griffe.GitInfo +::: griffelib.GitInfo diff --git a/docs/reference/api/models/alias.md b/docs/reference/api/models/alias.md index df1419cc3..ae146795d 100644 --- a/docs/reference/api/models/alias.md +++ b/docs/reference/api/models/alias.md @@ -1 +1 @@ -# ::: griffe.Alias +# ::: griffelib.Alias diff --git a/docs/reference/api/models/attribute.md b/docs/reference/api/models/attribute.md index 89abf00d6..2ca25220b 100644 --- a/docs/reference/api/models/attribute.md +++ b/docs/reference/api/models/attribute.md @@ -1 +1 @@ -# ::: griffe.Attribute +# ::: griffelib.Attribute diff --git a/docs/reference/api/models/class.md b/docs/reference/api/models/class.md index f6720d4b8..2bcc01425 100644 --- a/docs/reference/api/models/class.md +++ b/docs/reference/api/models/class.md @@ -1,5 +1,5 @@ -# ::: griffe.Class +# ::: griffelib.Class ## **Utilities** -::: griffe.c3linear_merge +::: griffelib.c3linear_merge diff --git a/docs/reference/api/models/function.md b/docs/reference/api/models/function.md index 20003780b..ffe172ddc 100644 --- a/docs/reference/api/models/function.md +++ b/docs/reference/api/models/function.md @@ -1,11 +1,11 @@ -# ::: griffe.Function +# ::: griffelib.Function -::: griffe.Parameters +::: griffelib.Parameters -::: griffe.Parameter +::: griffelib.Parameter -::: griffe.ParameterKind +::: griffelib.ParameterKind -::: griffe.ParametersType +::: griffelib.ParametersType -::: griffe.Decorator +::: griffelib.Decorator diff --git a/docs/reference/api/models/module.md b/docs/reference/api/models/module.md index ea42941f9..39a74357f 100644 --- a/docs/reference/api/models/module.md +++ b/docs/reference/api/models/module.md @@ -1 +1 @@ -# ::: griffe.Module +# ::: griffelib.Module diff --git a/docs/reference/api/models/type_alias.md b/docs/reference/api/models/type_alias.md index 367d906d5..8033a7f5b 100644 --- a/docs/reference/api/models/type_alias.md +++ b/docs/reference/api/models/type_alias.md @@ -1,3 +1,3 @@ # Type Alias -::: griffe.TypeAlias +::: griffelib.TypeAlias diff --git a/docs/reference/api/serializers.md b/docs/reference/api/serializers.md index c9fff7b4e..2ac8a7b76 100644 --- a/docs/reference/api/serializers.md +++ b/docs/reference/api/serializers.md @@ -2,10 +2,10 @@ ## **Main API** -See the [`as_json()`][griffe.Object.as_json] and [`from_json()`][griffe.Object.from_json] methods of objects. +See the [`as_json()`][griffelib.Object.as_json] and [`from_json()`][griffelib.Object.from_json] methods of objects. ## **Advanced API** -::: griffe.JSONEncoder +::: griffelib.JSONEncoder -::: griffe.json_decoder +::: griffelib.json_decoder diff --git a/docs/reference/docstrings.md b/docs/reference/docstrings.md index dd26177b0..e6b342212 100644 --- a/docs/reference/docstrings.md +++ b/docs/reference/docstrings.md @@ -68,7 +68,7 @@ Note: Find out possibly invalid section syntax by grepping for "reasons" in Griffe debug logs: ```bash -griffe dump -Ldebug -o/dev/null -fdgoogle your_package 2>&1 | grep reasons +griffecli dump -Ldebug -o/dev/null -fdgoogle your_package 2>&1 | grep reasons ``` Some sections support documenting multiple items (attributes, parameters, etc.). When multiple items are supported, each item description can use multiple lines, and continuation lines must be indented once more so that the parser is able to differentiate items. diff --git a/docs/schema-docstrings-options.json b/docs/schema-docstrings-options.json index 516d86eb7..dfdb081fe 100644 --- a/docs/schema-docstrings-options.json +++ b/docs/schema-docstrings-options.json @@ -5,19 +5,19 @@ "properties": { "ignore_init_summary": { "title": "Whether to discard the summary line in `__init__` methods' docstrings.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffe.docstrings.google.parse", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffelib.docstrings.google.parse", "type": "boolean", "default": false }, "trim_doctest_flags": { "title": "Whether to remove doctest flags from Python example blocks.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffe.docstrings.google.parse", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffelib.docstrings.google.parse", "type": "boolean", "default": true }, "returns_multiple_items": { "title": "Whether the `Returns` section has multiple items.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffe.docstrings.google.parse", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffelib.docstrings.google.parse", "type": "boolean", "default": true } diff --git a/docs/schema.json b/docs/schema.json index 2af3ca516..7b76c4412 100644 --- a/docs/schema.json +++ b/docs/schema.json @@ -7,32 +7,32 @@ "properties": { "name": { "title": "The name of the alias.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.name", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.name", "type": "string" }, "kind": { "title": "The 'alias' kind.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.kind", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.kind", "const": "alias" }, "path": { "title": "The alias path.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.path", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.path", "type": "string" }, "target_path": { "title": "For aliases, the Python path of their target.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.target_path", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.target_path", "type": "string" }, "lineno": { "title": "For aliases, the import starting line number in their own module.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.lineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.lineno", "type": "integer" }, "endlineno": { "title": "For aliases, the import ending line number in their own module.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.endlineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.endlineno", "type": [ "integer", "null" @@ -40,17 +40,17 @@ }, "inherited": { "title": "Whether the alias is the member of another alias.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.inherited", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.inherited", "type": "boolean" }, "runtime": { "title": "Whether the alias exists at runtime.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.runtime", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.runtime", "type": "boolean" }, "public": { "title": "Whether the alias is public.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.public", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.public", "type": [ "null", "boolean" @@ -58,7 +58,7 @@ }, "deprecated": { "title": "Whether the alias is explicitly marked as deprecated.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.deprecated", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.deprecated", "type": [ "null", "boolean", @@ -67,7 +67,7 @@ }, "analysis": { "title": "The type of analysis used to load this alias.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.analysis", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.analysis", "type": [ "null", "string" @@ -80,42 +80,42 @@ }, "is_public": { "title": "Whether the alias is public.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_public", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_public", "type": "boolean" }, "is_deprecated": { "title": "Whether the alias is deprecated.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_deprecated", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_deprecated", "type": "boolean" }, "is_private": { "title": "Whether the alias is private.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_private", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_private", "type": "boolean" }, "is_class_private": { "title": "Whether the alias is class-private.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_class_private", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_class_private", "type": "boolean" }, "is_special": { "title": "Whether the alias is special.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_special", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_special", "type": "boolean" }, "is_imported": { "title": "Whether the alias is imported.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_imported", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_imported", "type": "boolean" }, "is_exported": { "title": "Whether the alias is exported.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_exported", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_exported", "type": "boolean" }, "is_wildcard_exposed": { "title": "Whether the alias is wildcard-exposed.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_wildcard_exposed", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_wildcard_exposed", "type": "boolean" } }, @@ -133,12 +133,12 @@ "properties": { "name": { "title": "The name of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.name", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.name", "type": "string" }, "kind": { "title": "The kind of object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.kind", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.kind", "enum": [ "module", "class", @@ -149,32 +149,32 @@ }, "path": { "title": "The path of the object (dot-separated Python path).", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.path", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.path", "type": "string" }, "filepath": { "title": "The file path of the object's parent module.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.filepath", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.filepath", "type": "string" }, "relative_filepath": { "title": "The file path of the object's parent module, relative to the (at the time) current working directory.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.relative_filepath", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.relative_filepath", "type": "string" }, "relative_package_filepath": { "title": "The file path of the object's package, as found in the explored directories of the Python paths.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.relative_package_filepath", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.relative_package_filepath", "type": "string" }, "git_info": { "title": "The Git information associated to this object's package.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Object.git_info", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Object.git_info", "$ref": "#/$defs/GitInfo" }, "source_link": { "title": "The source link of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.source_link", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.source_link", "type": [ "string", "null" @@ -182,7 +182,7 @@ }, "public": { "title": "Whether the object was explicitly marked as public.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.public", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.public", "type": [ "null", "boolean" @@ -190,7 +190,7 @@ }, "exports": { "title": "The exports of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.exports", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.exports", "type": [ "null", "array" @@ -201,17 +201,17 @@ }, "imports": { "title": "The imports of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.imports", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.imports", "type": "object" }, "runtime": { "title": "Whether this object exists at runtime.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.runtime", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.runtime", "type": "boolean" }, "deprecated": { "title": "Whether the object was explicitly marked as deprecated.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.deprecated", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.deprecated", "type": [ "null", "string", @@ -220,7 +220,7 @@ }, "analysis": { "title": "The type of analysis used to load this object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Object.analysis", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Object.analysis", "type": [ "null", "string" @@ -233,27 +233,27 @@ }, "labels": { "title": "The labels of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.labels", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.labels", "type": "array" }, "docstring": { "title": "The docstring of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring", "type": "object", "properties": { "value": { "title": "The actual string.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.value", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.value", "type": "string" }, "lineno": { "title": "The docstring starting line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.lineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.lineno", "type": "integer" }, "endlineno": { "title": "The docstring ending line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.endlineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.endlineno", "type": [ "integer", "null" @@ -261,7 +261,7 @@ }, "parsed": { "title": "The parsed docstring (list of docstring sections).", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.parsed", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.parsed", "type": "array", "items": { "type": "object", @@ -312,12 +312,12 @@ }, "lineno": { "title": "The docstring starting line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.lineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.lineno", "type": "integer" }, "endlineno": { "title": "The docstring ending line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.endlineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.endlineno", "type": [ "integer", "null" @@ -325,42 +325,42 @@ }, "is_public": { "title": "Whether the object is public.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_public", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_public", "type": "boolean" }, "is_deprecated": { "title": "Whether the object is deprecated.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_deprecated", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_deprecated", "type": "boolean" }, "is_private": { "title": "Whether the object is private.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_private", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_private", "type": "boolean" }, "is_class_private": { "title": "Whether the object is class-private.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_class_private", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_class_private", "type": "boolean" }, "is_special": { "title": "Whether the object is special.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_special", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_special", "type": "boolean" }, "is_imported": { "title": "Whether the object is imported.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_imported", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_imported", "type": "boolean" }, "is_exported": { "title": "Whether the object is exported.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_exported", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_exported", "type": "boolean" }, "is_wildcard_exposed": { "title": "Whether the object is wildcard-exposed.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_wildcard_exposed", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_wildcard_exposed", "type": "boolean" }, "bases": true, @@ -390,7 +390,7 @@ "properties": { "bases": { "title": "For classes, their bases classes.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffe.Class.bases", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffelib.Class.bases", "type": "array", "items": { "$ref": "#/$defs/annotation" @@ -398,24 +398,24 @@ }, "decorators": { "title": "For classes, their decorators.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffe.Class.decorators", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffelib.Class.decorators", "type": "array", "items": { "type": "object", "properties": { "value": { "title": "The decorator value (string, name or expression).", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Decorator.value", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Decorator.value", "$ref": "#/$defs/annotation" }, "lineno": { "title": "The decorator starting line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Decorator.lineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Decorator.lineno", "type": "integer" }, "endlineno": { "title": "The decorator ending line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Decorator.endlineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Decorator.endlineno", "type": [ "integer", "null" @@ -432,7 +432,7 @@ }, "type_parameters": { "title": "For classes, their type parameters.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffe.Class.type_parameters", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffelib.Class.type_parameters", "type": "array", "items": { "$ref": "#/$defs/type_parameter" @@ -457,29 +457,29 @@ "properties": { "parameters": { "title": "For functions, their parameters.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Function.parameters", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Function.parameters", "type": "array", "items": { "type": "object", "properties": { "name": { "title": "The name of the parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Parameter.name", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Parameter.name", "type": "string" }, "annotation": { "title": "The annotation of the parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Parameter.annotation", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Parameter.annotation", "$ref": "#/$defs/annotation" }, "kind": { "title": "The kind of parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Parameter.kind", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Parameter.kind", "type": "string" }, "default": { "title": "The default value of the parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Parameter.default", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Parameter.default", "$ref": "#/$defs/annotation" } }, @@ -491,12 +491,12 @@ }, "returns": { "title": "For functions, their return annotation.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Function.returns", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Function.returns", "$ref": "#/$defs/annotation" }, "type_parameters": { "title": "For functions, their type parameters.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Function.type_parameters", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Function.type_parameters", "type": "array", "items": { "$ref": "#/$defs/type_parameter" @@ -521,12 +521,12 @@ "properties": { "value": { "title": "For attributes, their value.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/attribute/#griffe.Attribute.value", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/attribute/#griffelib.Attribute.value", "$ref": "#/$defs/annotation" }, "annotation": { "title": "For attributes, their type annotation.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/attribute/#griffe.Attribute.annotation", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/attribute/#griffelib.Attribute.annotation", "$ref": "#/$defs/annotation" } } @@ -544,12 +544,12 @@ "properties": { "value": { "title": "For type aliases, their value.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/type_alias/#griffe.TypeAlias.value", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/type_alias/#griffelib.TypeAlias.value", "$ref": "#/$defs/annotation" }, "type_parameters": { "title": "For type aliases, their type parameters.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/type_alias/#griffe.TypeAlias.type_parameters", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/type_alias/#griffelib.TypeAlias.type_parameters", "type": "array", "items": { "$ref": "#/$defs/type_parameter" @@ -584,17 +584,17 @@ }, "type_parameter": { "title": "Type Parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter", "type": "object", "properties": { "name": { "title": "The type parameter name.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter.name", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter.name", "type": "string" }, "kind": { "title": "The type parameter kind.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter.kind", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter.kind", "enum": [ "type-var", "type-var-tuple", @@ -603,12 +603,12 @@ }, "annotation": { "title": "The type parameter bound or constraints.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter.annotation", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter.annotation", "$ref": "#/$defs/annotation" }, "default": { "title": "The type parameter default.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter.default", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter.default", "$ref": "#/$defs/annotation" } }, @@ -622,19 +622,19 @@ }, "GitInfo": { "title": "Git information.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo", "type": "object", "properties": { "repository": { "title": "The repository local path.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo.repository", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo.repository", "type": [ "string" ] }, "service": { "title": "The Git service (e.g., 'github', 'gitlab', 'bitbucket').", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo.service", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo.service", "type": [ "string" ], @@ -651,14 +651,14 @@ }, "remote_url": { "title": "The remote URL.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo.remote_url", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo.remote_url", "type": [ "string" ] }, "commit_hash": { "title": "The commit hash.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo.commit_hash", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo.commit_hash", "type": [ "string" ] diff --git a/duties.py b/duties.py index d3f1178cd..a2f8d7d61 100644 --- a/duties.py +++ b/duties.py @@ -285,7 +285,7 @@ def check_api(ctx: Context, *cli_args: str) -> None: *cli_args: Additional Griffe CLI arguments. """ ctx.run( - tools.griffe.check( + tools.griffecli.check( "griffe", search=["src"], color=True, diff --git a/packages/griffecli/pyproject.toml b/packages/griffecli/pyproject.toml new file mode 100644 index 000000000..26726d5fa --- /dev/null +++ b/packages/griffecli/pyproject.toml @@ -0,0 +1,48 @@ +[build-system] +# pdm-backend is left here as a dependency of the version discovery script currently in use. +# It may be removed in the future. See mkdocstrings/griffe#430 +requires = ["hatchling", "pdm-backend", "uv-dynamic-versioning>=0.7.0"] +build-backend = "hatchling.build" + +[tool.hatch.version] +source = "code" +path = "../../scripts/get_version.py" +expression = "get_version()" + +[project] +name = "griffecli" +description = "The griffe CLI" +authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}] +license = "ISC" +license-files = ["LICENSE"] +requires-python = ">=3.10" +keywords = ["api", "signature", "breaking-changes", "static-analysis", "dynamic-analysis"] +dynamic = ["version", "dependencies", "optional-dependencies"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + # YORE: EOL 3.10: Remove line. + "Programming Language :: Python :: 3.10", + # YORE: EOL 3.11: Remove line. + "Programming Language :: Python :: 3.11", + # YORE: EOL 3.12: Remove line. + "Programming Language :: Python :: 3.12", + # YORE: EOL 3.13: Remove line. + "Programming Language :: Python :: 3.13", + # YORE: EOL 3.14: Remove line. + "Programming Language :: Python :: 3.14", + "Topic :: Documentation", + "Topic :: Software Development", + "Topic :: Software Development :: Documentation", + "Topic :: Utilities", + "Typing :: Typed", +] + +[tool.hatch.metadata.hooks.uv-dynamic-versioning] + +[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] + +[tool.hatch.build.targets.sdist] diff --git a/packages/griffecli/src/griffecli/__init__.py b/packages/griffecli/src/griffecli/__init__.py new file mode 100644 index 000000000..54cec7a60 --- /dev/null +++ b/packages/griffecli/src/griffecli/__init__.py @@ -0,0 +1 @@ +# TODO: Cut proper imports from griffelib `__init__.py` module diff --git a/packages/griffecli/src/griffecli/__main__.py b/packages/griffecli/src/griffecli/__main__.py new file mode 100644 index 000000000..0374dbb77 --- /dev/null +++ b/packages/griffecli/src/griffecli/__main__.py @@ -0,0 +1,13 @@ +# Entry-point module, in case you use `python -m griffelib`. +# +# Why does this file exist, and why `__main__`? For more info, read: +# +# - https://www.python.org/dev/peps/pep-0338/ +# - https://docs.python.org/3/using/cmdline.html#cmdoption-m + +import sys + +from griffecli._internal.cli import main + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/src/griffe/_internal/cli.py b/packages/griffecli/src/griffecli/_internal/cli.py similarity index 94% rename from src/griffe/_internal/cli.py rename to packages/griffecli/src/griffecli/_internal/cli.py index 1f6c767f5..708b8ac33 100644 --- a/src/griffe/_internal/cli.py +++ b/packages/griffecli/src/griffecli/_internal/cli.py @@ -4,11 +4,11 @@ # We might be tempted to import things from `__main__` later, # but that will cause problems; the code will get executed twice: # -# - When we run `python -m griffe`, Python will execute +# - When we run `python -m griffelib`, Python will execute # `__main__.py` as a script. That means there won't be any -# `griffe.__main__` in `sys.modules`. +# `griffelib.__main__` in `sys.modules`. # - When you import `__main__` it will get executed again (as a module) because -# there's no `griffe.__main__` in `sys.modules`. +# there's no `griffelib.__main__` in `sys.modules`. from __future__ import annotations @@ -24,21 +24,21 @@ import colorama -from griffe._internal import debug -from griffe._internal.diff import find_breaking_changes -from griffe._internal.encoders import JSONEncoder -from griffe._internal.enumerations import ExplanationStyle, Parser -from griffe._internal.exceptions import ExtensionError, GitError -from griffe._internal.extensions.base import load_extensions -from griffe._internal.git import _get_latest_tag, _get_repo_root -from griffe._internal.loader import GriffeLoader, load, load_git, load_pypi -from griffe._internal.logger import logger +from griffelib._internal import debug +from griffelib._internal.diff import find_breaking_changes +from griffelib._internal.encoders import JSONEncoder +from griffelib._internal.enumerations import ExplanationStyle, Parser +from griffelib._internal.exceptions import ExtensionError, GitError +from griffelib._internal.extensions.base import load_extensions +from griffelib._internal.git import _get_latest_tag, _get_repo_root +from griffelib._internal.loader import GriffeLoader, load, load_git, load_pypi +from griffelib._internal.logger import logger if TYPE_CHECKING: from collections.abc import Sequence - from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffe._internal.extensions.base import Extension, Extensions + from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffelib._internal.extensions.base import Extension, Extensions DEFAULT_LOG_LEVEL = os.getenv("GRIFFE_LOG_LEVEL", "INFO").upper() @@ -138,7 +138,7 @@ def get_parser() -> argparse.ArgumentParser: description = "Signatures for entire Python programs. " "Extract the structure, the frame, the skeleton of your project, " "to generate API documentation or find breaking changes in your API." - parser = argparse.ArgumentParser(add_help=False, usage=usage, description=description, prog="griffe") + parser = argparse.ArgumentParser(add_help=False, usage=usage, description=description, prog="griffelib") main_help = "Show this help message and exit. Commands also accept the -h/--help option." subcommand_help = "Show this help message and exit." @@ -215,7 +215,7 @@ def add_common_options(subparser: argparse.ArgumentParser) -> None: dest="subcommand", title="Commands", metavar="COMMAND", - prog="griffe", + prog="griffelib", required=True, ) @@ -511,7 +511,7 @@ def check( against = against or _get_latest_tag(package) repository = _get_repo_root(against_path) except GitError as error: - print(f"griffe: error: {error}", file=sys.stderr) + print(f"griffelib: error: {error}", file=sys.stderr) return 2 # Load old and new version of the package. @@ -577,7 +577,7 @@ def check( def main(args: list[str] | None = None) -> int: """Run the main program. - This function is executed when you type `griffe` or `python -m griffe`. + This function is executed when you type `griffelib` or `python -m griffelib`. Parameters: args: Arguments passed from the command line. @@ -599,7 +599,7 @@ def main(args: list[str] | None = None) -> int: except AttributeError: choices = "', '".join(_level_choices) print( - f"griffe: error: invalid log level '{log_level}' (choose from '{choices}')", + f"griffelib: error: invalid log level '{log_level}' (choose from '{choices}')", file=sys.stderr, ) return 1 diff --git a/packages/griffelib/pyproject.toml b/packages/griffelib/pyproject.toml new file mode 100644 index 000000000..aba09f221 --- /dev/null +++ b/packages/griffelib/pyproject.toml @@ -0,0 +1,48 @@ +[build-system] +# pdm-backend is left here as a dependency of the version discovery script currently in use. +# It may be removed in the future. See mkdocstrings/griffe#430 +requires = ["hatchling", "pdm-backend", "uv-dynamic-versioning>=0.7.0"] +build-backend = "hatchling.build" + +[tool.hatch.version] +source = "code" +path = "../../scripts/get_version.py" +expression = "get_version()" + +[project] +name = "griffelib" +description = "The griffe library" +authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}] +license = "ISC" +license-files = ["LICENSE"] +requires-python = ">=3.10" +keywords = ["api", "signature", "breaking-changes", "static-analysis", "dynamic-analysis"] +dynamic = ["version", "dependencies", "optional-dependencies"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + # YORE: EOL 3.10: Remove line. + "Programming Language :: Python :: 3.10", + # YORE: EOL 3.11: Remove line. + "Programming Language :: Python :: 3.11", + # YORE: EOL 3.12: Remove line. + "Programming Language :: Python :: 3.12", + # YORE: EOL 3.13: Remove line. + "Programming Language :: Python :: 3.13", + # YORE: EOL 3.14: Remove line. + "Programming Language :: Python :: 3.14", + "Topic :: Documentation", + "Topic :: Software Development", + "Topic :: Software Development :: Documentation", + "Topic :: Utilities", + "Typing :: Typed", +] + +[tool.hatch.metadata.hooks.uv-dynamic-versioning] + +[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] + +[tool.hatch.build.targets.sdist] diff --git a/packages/griffelib/src/griffelib/__init__.py b/packages/griffelib/src/griffelib/__init__.py new file mode 100644 index 000000000..e3db6aa85 --- /dev/null +++ b/packages/griffelib/src/griffelib/__init__.py @@ -0,0 +1,607 @@ +# This top-level module imports all public names from the package, +# and exposes them as public objects. We have tests to make sure +# no object is forgotten in this list. + +"""Griffe package. + +Signatures for entire Python programs. +Extract the structure, the frame, the skeleton of your project, +to generate API documentation or find breaking changes in your API. + +The entirety of the public API is exposed here, in the top-level `griffelib` module. + +All messages written to standard output or error are logged using the `logging` module. +Our logger's name is set to `"griffelib"` and is public (you can rely on it). +You can obtain the logger from the standard `logging` module: `logging.getLogger("griffelib")`. +Actual logging messages are not part of the public API (they might change without notice). + +Raised exceptions throughout the package are part of the public API (you can rely on them). +Their actual messages are not part of the public API (they might change without notice). + +The following paragraphs will help you discover the package's content. + +## CLI entrypoints + +Griffe provides a command-line interface (CLI) to interact with the package. The CLI entrypoints can be called from Python code. + +- [`griffecli.main`][]: Run the main program. +- [`griffecli.check`][]: Check for API breaking changes in two versions of the same package. +- [`griffecli.dump`][]: Load packages data and dump it as JSON. + +## Loaders + +To load API data, Griffe provides several high-level functions. + +- [`griffelib.load`][]: Load and return a Griffe object. +- [`griffelib.load_git`][]: Load and return a module from a specific Git reference. +- [`griffelib.load_pypi`][]: Load and return a module from a specific package version downloaded using pip. + +## Models + +The data loaded by Griffe is represented by several classes. + +- [`griffelib.Module`][]: The class representing a Python module. +- [`griffelib.Class`][]: The class representing a Python class. +- [`griffelib.Function`][]: The class representing a Python function or method. +- [`griffelib.Attribute`][]: The class representing a Python attribute. +- [`griffelib.Alias`][]: This class represents an alias, or indirection, to an object declared in another module. + +Additional classes are available to represent other concepts. + +- [`griffelib.Decorator`][]: This class represents a decorator. +- [`griffelib.Parameters`][]: This class is a container for parameters. +- [`griffelib.Parameter`][]: This class represent a function parameter. + +## Agents + +Griffe is able to analyze code both statically and dynamically, using the following "agents". +However most of the time you will only need to use the loaders above. + +- [`griffelib.visit`][]: Parse and visit a module file. +- [`griffelib.inspect`][]: Inspect a module. + +## Serializers + +Griffe can serizalize data to dictionary and JSON. + +- [`griffelib.Object.as_json`][griffelib.Object.as_json] +- [`griffelib.Object.from_json`][griffelib.Object.from_json] +- [`griffelib.JSONEncoder`][]: JSON encoder for Griffe objects. +- [`griffelib.json_decoder`][]: JSON decoder for Griffe objects. + +## API checks + +Griffe can compare two versions of the same package to find breaking changes. + +- [`griffelib.find_breaking_changes`][]: Find breaking changes between two versions of the same API. +- [`griffelib.Breakage`][]: Breakage classes can explain what broke from a version to another. + +## Extensions + +Griffe supports extensions. You can create your own extension by subclassing the `griffelib.Extension` class. + +- [`griffelib.load_extensions`][]: Load configured extensions. +- [`griffelib.Extension`][]: Base class for Griffe extensions. + +## Docstrings + +Griffe can parse docstrings into structured data. + +Main class: + +- [`griffelib.Docstring`][]: This class represents docstrings. + +Docstring section and element classes all start with `Docstring`. + +Docstring parsers: + +- [`griffelib.parse`][]: Parse the docstring. +- [`griffelib.parse_auto`][]: Parse a docstring by automatically detecting the style it uses. +- [`griffelib.parse_google`][]: Parse a Google-style docstring. +- [`griffelib.parse_numpy`][]: Parse a Numpydoc-style docstring. +- [`griffelib.parse_sphinx`][]: Parse a Sphinx-style docstring. + +## Exceptions + +Griffe uses several exceptions to signal errors. + +- [`griffelib.GriffeError`][]: The base exception for all Griffe errors. +- [`griffelib.LoadingError`][]: Exception for loading errors. +- [`griffelib.NameResolutionError`][]: Exception for names that cannot be resolved in a object scope. +- [`griffelib.UnhandledEditableModuleError`][]: Exception for unhandled editables modules, when searching modules. +- [`griffelib.UnimportableModuleError`][]: Exception for modules that cannot be imported. +- [`griffelib.AliasResolutionError`][]: Exception for aliases that cannot be resolved. +- [`griffelib.CyclicAliasError`][]: Exception raised when a cycle is detected in aliases. +- [`griffelib.LastNodeError`][]: Exception raised when trying to access a next or previous node. +- [`griffelib.RootNodeError`][]: Exception raised when trying to use siblings properties on a root node. +- [`griffelib.BuiltinModuleError`][]: Exception raised when trying to access the filepath of a builtin module. +- [`griffelib.ExtensionError`][]: Base class for errors raised by extensions. +- [`griffelib.ExtensionNotLoadedError`][]: Exception raised when an extension could not be loaded. +- [`griffelib.GitError`][]: Exception raised for errors related to Git. + +# Expressions + +Griffe stores snippets of code (attribute values, decorators, base class, type annotations) as expressions. +Expressions are basically abstract syntax trees (AST) with a few differences compared to the nodes returned by [`ast`][]. +Griffe provides a few helpers to extract expressions from regular AST nodes. + +- [`griffelib.get_annotation`][]: Get a type annotation as expression. +- [`griffelib.get_base_class`][]: Get a base class as expression. +- [`griffelib.get_class_keyword`][]: Get a class keyword as expression. +- [`griffelib.get_condition`][]: Get a condition as expression. +- [`griffelib.get_expression`][]: Get an expression from an AST node. +- [`griffelib.safe_get_annotation`][]: Get a type annotation as expression, safely (returns `None` on error). +- [`griffelib.safe_get_base_class`][]: Get a base class as expression, safely (returns `None` on error). +- [`griffelib.safe_get_class_keyword`][]: Get a class keyword as expression, safely (returns `None` on error). +- [`griffelib.safe_get_condition`][]: Get a condition as expression, safely (returns `None` on error). +- [`griffelib.safe_get_expression`][]: Get an expression from an AST node, safely (returns `None` on error). + +The base class for expressions. + +- [`griffelib.Expr`][] + +Expression classes all start with `Expr`. + +# Loggers + +If you want to log messages from extensions, get a logger with `get_logger`. +The `logger` attribute is used by Griffe itself. You can use it to temporarily disable Griffe logging. + +- [`griffelib.logger`][]: Our global logger, used throughout the library. +- [`griffelib.get_logger`][]: Create and return a new logger instance. + +# Helpers + +To test your Griffe extensions, or to load API data from code in memory, Griffe provides the following helpers. + +- [`griffelib.temporary_pyfile`][]: Create a Python file containing the given code in a temporary directory. +- [`griffelib.temporary_pypackage`][]: Create a package containing the given modules in a temporary directory. +- [`griffelib.temporary_visited_module`][]: Create and visit a temporary module with the given code. +- [`griffelib.temporary_visited_package`][]: Create and visit a temporary package. +- [`griffelib.temporary_inspected_module`][]: Create and inspect a temporary module with the given code. +- [`griffelib.temporary_inspected_package`][]: Create and inspect a temporary package. +""" + +from __future__ import annotations + +from griffelib._internal.agents.inspector import Inspector, inspect +from griffelib._internal.agents.nodes.assignments import get_instance_names, get_name, get_names +from griffelib._internal.agents.nodes.ast import ( + ast_children, + ast_first_child, + ast_kind, + ast_last_child, + ast_next, + ast_next_siblings, + ast_previous, + ast_previous_siblings, + ast_siblings, +) +from griffelib._internal.agents.nodes.docstrings import get_docstring +from griffelib._internal.agents.nodes.exports import get__all__, safe_get__all__ +from griffelib._internal.agents.nodes.imports import relative_to_absolute +from griffelib._internal.agents.nodes.parameters import ParametersType, get_parameters +from griffelib._internal.agents.nodes.runtime import ObjectNode +from griffelib._internal.agents.nodes.values import get_value, safe_get_value +from griffelib._internal.agents.visitor import Visitor, builtin_decorators, stdlib_decorators, typing_overload, visit +from griffelib._internal.c3linear import c3linear_merge +from griffecli._internal.cli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main +from griffelib._internal.collections import LinesCollection, ModulesCollection +from griffelib._internal.diff import ( + AttributeChangedTypeBreakage, + AttributeChangedValueBreakage, + Breakage, + ClassRemovedBaseBreakage, + ObjectChangedKindBreakage, + ObjectRemovedBreakage, + ParameterAddedRequiredBreakage, + ParameterChangedDefaultBreakage, + ParameterChangedKindBreakage, + ParameterChangedRequiredBreakage, + ParameterMovedBreakage, + ParameterRemovedBreakage, + ReturnChangedTypeBreakage, + find_breaking_changes, +) +from griffelib._internal.docstrings.auto import ( + AutoOptions, + DocstringDetectionMethod, + PerStyleOptions, + infer_docstring_style, + parse_auto, +) +from griffelib._internal.docstrings.google import GoogleOptions, parse_google +from griffelib._internal.docstrings.models import ( + DocstringAdmonition, + DocstringAttribute, + DocstringClass, + DocstringDeprecated, + DocstringElement, + DocstringFunction, + DocstringModule, + DocstringNamedElement, + DocstringParameter, + DocstringRaise, + DocstringReceive, + DocstringReturn, + DocstringSection, + DocstringSectionAdmonition, + DocstringSectionAttributes, + DocstringSectionClasses, + DocstringSectionDeprecated, + DocstringSectionExamples, + DocstringSectionFunctions, + DocstringSectionModules, + DocstringSectionOtherParameters, + DocstringSectionParameters, + DocstringSectionRaises, + DocstringSectionReceives, + DocstringSectionReturns, + DocstringSectionText, + DocstringSectionTypeAliases, + DocstringSectionTypeParameters, + DocstringSectionWarns, + DocstringSectionYields, + DocstringTypeAlias, + DocstringTypeParameter, + DocstringWarn, + DocstringYield, +) +from griffelib._internal.docstrings.numpy import NumpyOptions, parse_numpy +from griffelib._internal.docstrings.parsers import ( + DocstringOptions, + DocstringStyle, + parse, + parsers, +) +from griffelib._internal.docstrings.sphinx import SphinxOptions, parse_sphinx +from griffelib._internal.docstrings.utils import docstring_warning, parse_docstring_annotation +from griffelib._internal.encoders import JSONEncoder, json_decoder +from griffelib._internal.enumerations import ( + BreakageKind, + DocstringSectionKind, + ExplanationStyle, + Kind, + LogLevel, + ObjectKind, + ParameterKind, + Parser, + TypeParameterKind, +) +from griffelib._internal.exceptions import ( + AliasResolutionError, + BuiltinModuleError, + CyclicAliasError, + ExtensionError, + ExtensionNotLoadedError, + GitError, + GriffeError, + LastNodeError, + LoadingError, + NameResolutionError, + RootNodeError, + UnhandledEditableModuleError, + UnimportableModuleError, +) +from griffelib._internal.expressions import ( + Expr, + ExprAttribute, + ExprBinOp, + ExprBoolOp, + ExprCall, + ExprCompare, + ExprComprehension, + ExprConstant, + ExprDict, + ExprDictComp, + ExprExtSlice, + ExprFormatted, + ExprGeneratorExp, + ExprIfExp, + ExprJoinedStr, + ExprKeyword, + ExprLambda, + ExprList, + ExprListComp, + ExprName, + ExprNamedExpr, + ExprParameter, + ExprSet, + ExprSetComp, + ExprSlice, + ExprSubscript, + ExprTuple, + ExprUnaryOp, + ExprVarKeyword, + ExprVarPositional, + ExprYield, + ExprYieldFrom, + get_annotation, + get_base_class, + get_class_keyword, + get_condition, + get_expression, + safe_get_annotation, + safe_get_base_class, + safe_get_class_keyword, + safe_get_condition, + safe_get_expression, +) +from griffelib._internal.extensions.base import ( + Extension, + Extensions, + LoadableExtensionType, + builtin_extensions, + load_extensions, +) +from griffelib._internal.extensions.dataclasses import DataclassesExtension +from griffelib._internal.extensions.unpack_typeddict import UnpackTypedDictExtension +from griffelib._internal.finder import ModuleFinder, NamePartsAndPathType, NamePartsType, NamespacePackage, Package +from griffelib._internal.git import GitInfo, KnownGitService +from griffelib._internal.importer import dynamic_import, sys_path +from griffelib._internal.loader import GriffeLoader, load, load_git, load_pypi +from griffelib._internal.logger import Logger, get_logger, logger, patch_loggers +from griffelib._internal.merger import merge_stubs +from griffelib._internal.mixins import ( + DelMembersMixin, + GetMembersMixin, + ObjectAliasMixin, + SerializationMixin, + SetMembersMixin, +) +from griffelib._internal.models import ( + Alias, + Attribute, + Class, + Decorator, + Docstring, + Function, + Module, + Object, + Parameter, + Parameters, + TypeAlias, + TypeParameter, + TypeParameters, +) +from griffelib._internal.stats import Stats +from griffelib._internal.tests import ( + TmpPackage, + htree, + module_vtree, + temporary_inspected_module, + temporary_inspected_package, + temporary_pyfile, + temporary_pypackage, + temporary_visited_module, + temporary_visited_package, + vtree, +) + +# Regenerate this list with the following Python snippet: +# import griffelib +# names = sorted(n for n in dir(griffelib) if not n.startswith("_") and n not in ("annotations",)) +# print('__all__ = [\n "' + '",\n "'.join(names) + '",\n]') +__all__ = [ + "DEFAULT_LOG_LEVEL", + "Alias", + "AliasResolutionError", + "Attribute", + "AttributeChangedTypeBreakage", + "AttributeChangedValueBreakage", + "AutoOptions", + "Breakage", + "BreakageKind", + "BuiltinModuleError", + "Class", + "ClassRemovedBaseBreakage", + "CyclicAliasError", + "DataclassesExtension", + "Decorator", + "DelMembersMixin", + "Docstring", + "DocstringAdmonition", + "DocstringAttribute", + "DocstringClass", + "DocstringDeprecated", + "DocstringDetectionMethod", + "DocstringElement", + "DocstringFunction", + "DocstringModule", + "DocstringNamedElement", + "DocstringOptions", + "DocstringParameter", + "DocstringRaise", + "DocstringReceive", + "DocstringReturn", + "DocstringSection", + "DocstringSectionAdmonition", + "DocstringSectionAttributes", + "DocstringSectionClasses", + "DocstringSectionDeprecated", + "DocstringSectionExamples", + "DocstringSectionFunctions", + "DocstringSectionKind", + "DocstringSectionModules", + "DocstringSectionOtherParameters", + "DocstringSectionParameters", + "DocstringSectionRaises", + "DocstringSectionReceives", + "DocstringSectionReturns", + "DocstringSectionText", + "DocstringSectionTypeAliases", + "DocstringSectionTypeParameters", + "DocstringSectionWarns", + "DocstringSectionYields", + "DocstringStyle", + "DocstringTypeAlias", + "DocstringTypeParameter", + "DocstringWarn", + "DocstringYield", + "ExplanationStyle", + "Expr", + "ExprAttribute", + "ExprBinOp", + "ExprBoolOp", + "ExprCall", + "ExprCompare", + "ExprComprehension", + "ExprConstant", + "ExprDict", + "ExprDictComp", + "ExprExtSlice", + "ExprFormatted", + "ExprGeneratorExp", + "ExprIfExp", + "ExprJoinedStr", + "ExprKeyword", + "ExprLambda", + "ExprList", + "ExprListComp", + "ExprName", + "ExprNamedExpr", + "ExprParameter", + "ExprSet", + "ExprSetComp", + "ExprSlice", + "ExprSubscript", + "ExprTuple", + "ExprUnaryOp", + "ExprVarKeyword", + "ExprVarPositional", + "ExprYield", + "ExprYieldFrom", + "Extension", + "ExtensionError", + "ExtensionNotLoadedError", + "Extensions", + "Function", + "GetMembersMixin", + "GitError", + "GitInfo", + "GoogleOptions", + "GriffeError", + "GriffeLoader", + "Inspector", + "JSONEncoder", + "Kind", + "KnownGitService", + "LastNodeError", + "LinesCollection", + "LoadableExtensionType", + "LoadingError", + "LogLevel", + "Logger", + "Module", + "ModuleFinder", + "ModulesCollection", + "NamePartsAndPathType", + "NamePartsType", + "NameResolutionError", + "NamespacePackage", + "NumpyOptions", + "Object", + "ObjectAliasMixin", + "ObjectChangedKindBreakage", + "ObjectKind", + "ObjectNode", + "ObjectRemovedBreakage", + "Package", + "Parameter", + "ParameterAddedRequiredBreakage", + "ParameterChangedDefaultBreakage", + "ParameterChangedKindBreakage", + "ParameterChangedRequiredBreakage", + "ParameterKind", + "ParameterMovedBreakage", + "ParameterRemovedBreakage", + "Parameters", + "ParametersType", + "Parser", + "PerStyleOptions", + "ReturnChangedTypeBreakage", + "RootNodeError", + "SerializationMixin", + "SetMembersMixin", + "SphinxOptions", + "Stats", + "TmpPackage", + "TypeAlias", + "TypeParameter", + "TypeParameterKind", + "TypeParameters", + "UnhandledEditableModuleError", + "UnimportableModuleError", + "UnpackTypedDictExtension", + "Visitor", + "ast_children", + "ast_first_child", + "ast_kind", + "ast_last_child", + "ast_next", + "ast_next_siblings", + "ast_previous", + "ast_previous_siblings", + "ast_siblings", + "builtin_decorators", + "builtin_extensions", + "c3linear_merge", + "check", + "docstring_warning", + "dump", + "dynamic_import", + "find_breaking_changes", + "get__all__", + "get_annotation", + "get_base_class", + "get_class_keyword", + "get_condition", + "get_docstring", + "get_expression", + "get_instance_names", + "get_logger", + "get_name", + "get_names", + "get_parameters", + "get_parser", + "get_value", + "htree", + "infer_docstring_style", + "inspect", + "json_decoder", + "load", + "load_extensions", + "load_git", + "load_pypi", + "logger", + "main", + "merge_stubs", + "module_vtree", + "parse", + "parse_auto", + "parse_docstring_annotation", + "parse_google", + "parse_numpy", + "parse_sphinx", + "parsers", + "patch_loggers", + "relative_to_absolute", + "safe_get__all__", + "safe_get_annotation", + "safe_get_base_class", + "safe_get_class_keyword", + "safe_get_condition", + "safe_get_expression", + "safe_get_value", + "stdlib_decorators", + "sys_path", + "temporary_inspected_module", + "temporary_inspected_package", + "temporary_pyfile", + "temporary_pypackage", + "temporary_visited_module", + "temporary_visited_package", + "typing_overload", + "visit", + "vtree", +] diff --git a/src/griffe/_internal/__init__.py b/packages/griffelib/src/griffelib/_internal/__init__.py similarity index 100% rename from src/griffe/_internal/__init__.py rename to packages/griffelib/src/griffelib/_internal/__init__.py diff --git a/src/griffe/_internal/agents/__init__.py b/packages/griffelib/src/griffelib/_internal/agents/__init__.py similarity index 100% rename from src/griffe/_internal/agents/__init__.py rename to packages/griffelib/src/griffelib/_internal/agents/__init__.py diff --git a/src/griffe/_internal/agents/inspector.py b/packages/griffelib/src/griffelib/_internal/agents/inspector.py similarity index 96% rename from src/griffe/_internal/agents/inspector.py rename to packages/griffelib/src/griffelib/_internal/agents/inspector.py index 1ff89bfe6..7eb5df5c2 100644 --- a/src/griffe/_internal/agents/inspector.py +++ b/packages/griffelib/src/griffelib/_internal/agents/inspector.py @@ -12,14 +12,14 @@ from inspect import signature as getsignature from typing import TYPE_CHECKING, Any -from griffe._internal.agents.nodes.runtime import ObjectNode -from griffe._internal.collections import LinesCollection, ModulesCollection -from griffe._internal.enumerations import Kind, ParameterKind, TypeParameterKind -from griffe._internal.expressions import Expr, ExprBinOp, ExprSubscript, ExprTuple, safe_get_annotation -from griffe._internal.extensions.base import Extensions, load_extensions -from griffe._internal.importer import dynamic_import -from griffe._internal.logger import logger -from griffe._internal.models import ( +from griffelib._internal.agents.nodes.runtime import ObjectNode +from griffelib._internal.collections import LinesCollection, ModulesCollection +from griffelib._internal.enumerations import Kind, ParameterKind, TypeParameterKind +from griffelib._internal.expressions import Expr, ExprBinOp, ExprSubscript, ExprTuple, safe_get_annotation +from griffelib._internal.extensions.base import Extensions, load_extensions +from griffelib._internal.importer import dynamic_import +from griffelib._internal.logger import logger +from griffelib._internal.models import ( Alias, Attribute, Class, @@ -37,8 +37,8 @@ from collections.abc import Sequence from pathlib import Path - from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffe._internal.enumerations import Parser + from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffelib._internal.enumerations import Parser _TYPING_MODULES: tuple[types.ModuleType, ...] try: @@ -75,16 +75,16 @@ def inspect( In this case, we load the module using introspection. Griffe therefore provides this function for dynamic analysis. - It uses a [`NodeVisitor`][ast.NodeVisitor]-like class, the [`Inspector`][griffe.Inspector], + It uses a [`NodeVisitor`][ast.NodeVisitor]-like class, the [`Inspector`][griffelib.Inspector], to inspect the module with [`inspect.getmembers()`][inspect.getmembers]. - The inspection agent works similarly to the regular [`Visitor`][griffe.Visitor] agent, + The inspection agent works similarly to the regular [`Visitor`][griffelib.Visitor] agent, in that it maintains a state with the current object being handled, and recursively handle its members. Important: This function is generally not used directly. - In most cases, users can rely on the [`GriffeLoader`][griffe.GriffeLoader] - and its accompanying [`load`][griffe.load] shortcut and their respective options + In most cases, users can rely on the [`GriffeLoader`][griffelib.GriffeLoader] + and its accompanying [`load`][griffelib.load] shortcut and their respective options to load modules using dynamic analysis. Parameters: diff --git a/src/griffe/_internal/agents/nodes/__init__.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/__init__.py similarity index 100% rename from src/griffe/_internal/agents/nodes/__init__.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/__init__.py diff --git a/src/griffe/_internal/agents/nodes/assignments.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/assignments.py similarity index 100% rename from src/griffe/_internal/agents/nodes/assignments.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/assignments.py diff --git a/src/griffe/_internal/agents/nodes/ast.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/ast.py similarity index 98% rename from src/griffe/_internal/agents/nodes/ast.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/ast.py index 9cb261486..778fd75ef 100644 --- a/src/griffe/_internal/agents/nodes/ast.py +++ b/packages/griffelib/src/griffelib/_internal/agents/nodes/ast.py @@ -5,7 +5,7 @@ from ast import AST from typing import TYPE_CHECKING -from griffe._internal.exceptions import LastNodeError +from griffelib._internal.exceptions import LastNodeError if TYPE_CHECKING: from collections.abc import Iterator diff --git a/src/griffe/_internal/agents/nodes/docstrings.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/docstrings.py similarity index 100% rename from src/griffe/_internal/agents/nodes/docstrings.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/docstrings.py diff --git a/src/griffe/_internal/agents/nodes/exports.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/exports.py similarity index 91% rename from src/griffe/_internal/agents/nodes/exports.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/exports.py index d726e9c03..657c752e0 100644 --- a/src/griffe/_internal/agents/nodes/exports.py +++ b/packages/griffelib/src/griffelib/_internal/agents/nodes/exports.py @@ -6,13 +6,13 @@ from contextlib import suppress from typing import TYPE_CHECKING, Any, Callable -from griffe._internal.agents.nodes.values import get_value -from griffe._internal.enumerations import LogLevel -from griffe._internal.expressions import ExprName -from griffe._internal.logger import logger +from griffelib._internal.agents.nodes.values import get_value +from griffelib._internal.enumerations import LogLevel +from griffelib._internal.expressions import ExprName +from griffelib._internal.logger import logger if TYPE_CHECKING: - from griffe._internal.models import Module + from griffelib._internal.models import Module def _extract_attribute(node: ast.Attribute, parent: Module) -> list[str | ExprName]: diff --git a/src/griffe/_internal/agents/nodes/imports.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/imports.py similarity index 95% rename from src/griffe/_internal/agents/nodes/imports.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/imports.py index c194d07bc..25b5cf1b6 100644 --- a/src/griffe/_internal/agents/nodes/imports.py +++ b/packages/griffelib/src/griffelib/_internal/agents/nodes/imports.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: import ast - from griffe._internal.models import Module + from griffelib._internal.models import Module def relative_to_absolute(node: ast.ImportFrom, name: ast.alias, current_module: Module) -> str: diff --git a/src/griffe/_internal/agents/nodes/parameters.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/parameters.py similarity index 97% rename from src/griffe/_internal/agents/nodes/parameters.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/parameters.py index b6b6f445d..349be63d1 100644 --- a/src/griffe/_internal/agents/nodes/parameters.py +++ b/packages/griffelib/src/griffelib/_internal/agents/nodes/parameters.py @@ -6,7 +6,7 @@ from itertools import zip_longest from typing import TYPE_CHECKING, Optional, Union -from griffe._internal.enumerations import ParameterKind +from griffelib._internal.enumerations import ParameterKind if TYPE_CHECKING: from collections.abc import Iterable diff --git a/src/griffe/_internal/agents/nodes/runtime.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/runtime.py similarity index 99% rename from src/griffe/_internal/agents/nodes/runtime.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/runtime.py index b63d4f9c9..693a82a8f 100644 --- a/src/griffe/_internal/agents/nodes/runtime.py +++ b/packages/griffelib/src/griffelib/_internal/agents/nodes/runtime.py @@ -9,8 +9,8 @@ from types import GetSetDescriptorType, ModuleType from typing import TYPE_CHECKING, Any, ClassVar -from griffe._internal.enumerations import ObjectKind -from griffe._internal.logger import logger +from griffelib._internal.enumerations import ObjectKind +from griffelib._internal.logger import logger if TYPE_CHECKING: import types diff --git a/src/griffe/_internal/agents/nodes/values.py b/packages/griffelib/src/griffelib/_internal/agents/nodes/values.py similarity index 96% rename from src/griffe/_internal/agents/nodes/values.py rename to packages/griffelib/src/griffelib/_internal/agents/nodes/values.py index 63941f823..89465b97d 100644 --- a/src/griffe/_internal/agents/nodes/values.py +++ b/packages/griffelib/src/griffelib/_internal/agents/nodes/values.py @@ -6,7 +6,7 @@ from ast import unparse from typing import TYPE_CHECKING -from griffe._internal.logger import logger +from griffelib._internal.logger import logger if TYPE_CHECKING: from pathlib import Path diff --git a/src/griffe/_internal/agents/visitor.py b/packages/griffelib/src/griffelib/_internal/agents/visitor.py similarity index 96% rename from src/griffe/_internal/agents/visitor.py rename to packages/griffelib/src/griffelib/_internal/agents/visitor.py index 7cad06dde..f1a9e18ff 100644 --- a/src/griffe/_internal/agents/visitor.py +++ b/packages/griffelib/src/griffelib/_internal/agents/visitor.py @@ -8,20 +8,20 @@ from contextlib import suppress from typing import TYPE_CHECKING, Final -from griffe._internal.agents.nodes.assignments import get_instance_names, get_names -from griffe._internal.agents.nodes.ast import ( +from griffelib._internal.agents.nodes.assignments import get_instance_names, get_names +from griffelib._internal.agents.nodes.ast import ( ast_children, ast_kind, ast_next, ) -from griffe._internal.agents.nodes.docstrings import get_docstring -from griffe._internal.agents.nodes.exports import safe_get__all__ -from griffe._internal.agents.nodes.imports import relative_to_absolute -from griffe._internal.agents.nodes.parameters import get_parameters -from griffe._internal.collections import LinesCollection, ModulesCollection -from griffe._internal.enumerations import Kind, TypeParameterKind -from griffe._internal.exceptions import AliasResolutionError, CyclicAliasError, LastNodeError -from griffe._internal.expressions import ( +from griffelib._internal.agents.nodes.docstrings import get_docstring +from griffelib._internal.agents.nodes.exports import safe_get__all__ +from griffelib._internal.agents.nodes.imports import relative_to_absolute +from griffelib._internal.agents.nodes.parameters import get_parameters +from griffelib._internal.collections import LinesCollection, ModulesCollection +from griffelib._internal.enumerations import Kind, TypeParameterKind +from griffelib._internal.exceptions import AliasResolutionError, CyclicAliasError, LastNodeError +from griffelib._internal.expressions import ( Expr, ExprName, safe_get_annotation, @@ -30,8 +30,8 @@ safe_get_condition, safe_get_expression, ) -from griffe._internal.extensions.base import Extensions, load_extensions -from griffe._internal.models import ( +from griffelib._internal.extensions.base import Extensions, load_extensions +from griffelib._internal.models import ( Alias, Attribute, Class, @@ -49,8 +49,8 @@ if TYPE_CHECKING: from pathlib import Path - from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffe._internal.enumerations import Parser + from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffelib._internal.enumerations import Parser builtin_decorators = { @@ -92,13 +92,13 @@ def visit( """Parse and visit a module file. We provide this function for static analysis. It uses a [`NodeVisitor`][ast.NodeVisitor]-like class, - the [`Visitor`][griffe.Visitor], to compile and parse code (using [`compile`][]) + the [`Visitor`][griffelib.Visitor], to compile and parse code (using [`compile`][]) then visit the resulting AST (Abstract Syntax Tree). Important: This function is generally not used directly. - In most cases, users can rely on the [`GriffeLoader`][griffe.GriffeLoader] - and its accompanying [`load`][griffe.load] shortcut and their respective options + In most cases, users can rely on the [`GriffeLoader`][griffelib.GriffeLoader] + and its accompanying [`load`][griffelib.load] shortcut and their respective options to load modules using static analysis. Parameters: diff --git a/src/griffe/_internal/c3linear.py b/packages/griffelib/src/griffelib/_internal/c3linear.py similarity index 100% rename from src/griffe/_internal/c3linear.py rename to packages/griffelib/src/griffelib/_internal/c3linear.py diff --git a/src/griffe/_internal/collections.py b/packages/griffelib/src/griffelib/_internal/collections.py similarity index 94% rename from src/griffe/_internal/collections.py rename to packages/griffelib/src/griffelib/_internal/collections.py index 787f57a73..9927855a2 100644 --- a/src/griffe/_internal/collections.py +++ b/packages/griffelib/src/griffelib/_internal/collections.py @@ -5,13 +5,13 @@ from typing import TYPE_CHECKING, Any -from griffe._internal.mixins import DelMembersMixin, GetMembersMixin, SetMembersMixin +from griffelib._internal.mixins import DelMembersMixin, GetMembersMixin, SetMembersMixin if TYPE_CHECKING: from collections.abc import ItemsView, KeysView, ValuesView from pathlib import Path - from griffe._internal.models import Module + from griffelib._internal.models import Module class LinesCollection: diff --git a/src/griffe/_internal/debug.py b/packages/griffelib/src/griffelib/_internal/debug.py similarity index 93% rename from src/griffe/_internal/debug.py rename to packages/griffelib/src/griffelib/_internal/debug.py index 8f3ca86d3..7f8ea2698 100644 --- a/src/griffe/_internal/debug.py +++ b/packages/griffelib/src/griffelib/_internal/debug.py @@ -1,7 +1,7 @@ # This module is here to help users report bugs. # It provides a function to print environment information, -# which is called from the public `griffe.debug` module -# (when called with `python -m griffe.debug`) +# which is called from the public `griffelib.debug` module +# (when called with `python -m griffelib.debug`) # or thanks to the `--debug-info` CLI flag. from __future__ import annotations @@ -62,7 +62,7 @@ def _interpreter_name_version() -> tuple[str, str]: return "", "0.0.0" -def _get_version(dist: str = "griffe") -> str: +def _get_version(dist: str = "griffelib") -> str: """Get version of the given distribution. Parameters: @@ -84,7 +84,7 @@ def _get_debug_info() -> _Environment: Environment information. """ py_name, py_version = _interpreter_name_version() - packages = ["griffe"] + packages = ["griffelib"] variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("GRIFFE")]] return _Environment( interpreter_name=py_name, diff --git a/src/griffe/_internal/diff.py b/packages/griffelib/src/griffelib/_internal/diff.py similarity index 97% rename from src/griffe/_internal/diff.py rename to packages/griffelib/src/griffelib/_internal/diff.py index 59e98f08f..46f4645d1 100644 --- a/src/griffe/_internal/diff.py +++ b/packages/griffelib/src/griffelib/_internal/diff.py @@ -12,15 +12,15 @@ from pathlib import Path from typing import TYPE_CHECKING, Any -from griffe._internal.enumerations import BreakageKind, ExplanationStyle, ParameterKind -from griffe._internal.exceptions import AliasResolutionError -from griffe._internal.git import _WORKTREE_PREFIX -from griffe._internal.logger import logger +from griffelib._internal.enumerations import BreakageKind, ExplanationStyle, ParameterKind +from griffelib._internal.exceptions import AliasResolutionError +from griffelib._internal.git import _WORKTREE_PREFIX +from griffelib._internal.logger import logger if TYPE_CHECKING: from collections.abc import Iterable, Iterator - from griffe._internal.models import Alias, Attribute, Class, Function, Object + from griffelib._internal.models import Alias, Attribute, Class, Function, Object _POSITIONAL = frozenset((ParameterKind.positional_only, ParameterKind.positional_or_keyword)) _KEYWORD = frozenset((ParameterKind.keyword_only, ParameterKind.positional_or_keyword)) @@ -150,7 +150,7 @@ def _relative_package_filepath(self) -> Path: def _location(self) -> Path: # Absolute file path probably means temporary worktree. # We use our worktree prefix to remove some components - # of the path on the left (`/tmp/griffe-worktree-*/griffe_*/repo`). + # of the path on the left (`/tmp/griffelib-worktree-*/griffe_*/repo`). if self._relative_filepath.is_absolute(): parts = self._relative_filepath.parts for index, part in enumerate(parts): @@ -674,10 +674,10 @@ def find_breaking_changes( Breaking changes. Examples: - >>> import sys, griffe - >>> new = griffe.load("pkg") - >>> old = griffe.load_git("pkg", "1.2.3") - >>> for breakage in griffe.find_breaking_changes(old, new) + >>> import sys, griffelib + >>> new = griffelib.load("pkg") + >>> old = griffelib.load_git("pkg", "1.2.3") + >>> for breakage in griffelib.find_breaking_changes(old, new) ... print(breakage.explain(style=style), file=sys.stderr) """ yield from _member_incompatibilities(old_obj, new_obj) diff --git a/src/griffe/_internal/docstrings/__init__.py b/packages/griffelib/src/griffelib/_internal/docstrings/__init__.py similarity index 100% rename from src/griffe/_internal/docstrings/__init__.py rename to packages/griffelib/src/griffelib/_internal/docstrings/__init__.py diff --git a/src/griffe/_internal/docstrings/auto.py b/packages/griffelib/src/griffelib/_internal/docstrings/auto.py similarity index 90% rename from src/griffe/_internal/docstrings/auto.py rename to packages/griffelib/src/griffelib/_internal/docstrings/auto.py index ea582f91d..e7643f29c 100644 --- a/src/griffe/_internal/docstrings/auto.py +++ b/packages/griffelib/src/griffelib/_internal/docstrings/auto.py @@ -5,15 +5,15 @@ import re from typing import TYPE_CHECKING, Literal, TypedDict -from griffe._internal.enumerations import Parser +from griffelib._internal.enumerations import Parser if TYPE_CHECKING: - from griffe._internal.docstrings.google import GoogleOptions - from griffe._internal.docstrings.models import DocstringSection - from griffe._internal.docstrings.numpy import NumpyOptions - from griffe._internal.docstrings.parsers import DocstringStyle - from griffe._internal.docstrings.sphinx import SphinxOptions - from griffe._internal.models import Docstring + from griffelib._internal.docstrings.google import GoogleOptions + from griffelib._internal.docstrings.models import DocstringSection + from griffelib._internal.docstrings.numpy import NumpyOptions + from griffelib._internal.docstrings.parsers import DocstringStyle + from griffelib._internal.docstrings.sphinx import SphinxOptions + from griffelib._internal.models import Docstring # This is not our preferred order, but the safest order for proper detection @@ -143,7 +143,7 @@ def infer_docstring_style( Returns: The inferred parser, and optionally parsed sections (when method is 'max_sections'). """ - from griffe._internal.docstrings.parsers import parsers # noqa: PLC0415 + from griffelib._internal.docstrings.parsers import parsers # noqa: PLC0415 per_style_options = per_style_options or {} @@ -195,7 +195,7 @@ def parse_auto( ) -> list[DocstringSection]: """Parse a docstring by automatically detecting the style it uses. - See [`infer_docstring_style`][griffe.infer_docstring_style] for more information + See [`infer_docstring_style`][griffelib.infer_docstring_style] for more information on the available parameters. Parameters: @@ -208,7 +208,7 @@ def parse_auto( Returns: A list of docstring sections. """ - from griffe._internal.docstrings.parsers import parse # noqa: PLC0415 + from griffelib._internal.docstrings.parsers import parse # noqa: PLC0415 per_style_options = per_style_options or {} diff --git a/src/griffe/_internal/docstrings/google.py b/packages/griffelib/src/griffelib/_internal/docstrings/google.py similarity index 99% rename from src/griffe/_internal/docstrings/google.py rename to packages/griffelib/src/griffelib/_internal/docstrings/google.py index 42dd73b54..5924c892c 100644 --- a/src/griffe/_internal/docstrings/google.py +++ b/packages/griffelib/src/griffelib/_internal/docstrings/google.py @@ -6,7 +6,7 @@ from contextlib import suppress from typing import TYPE_CHECKING, TypedDict -from griffe._internal.docstrings.models import ( +from griffelib._internal.docstrings.models import ( DocstringAttribute, DocstringClass, DocstringFunction, @@ -37,15 +37,15 @@ DocstringWarn, DocstringYield, ) -from griffe._internal.docstrings.utils import docstring_warning, parse_docstring_annotation -from griffe._internal.enumerations import DocstringSectionKind, LogLevel +from griffelib._internal.docstrings.utils import docstring_warning, parse_docstring_annotation +from griffelib._internal.enumerations import DocstringSectionKind, LogLevel if TYPE_CHECKING: from re import Pattern from typing import Any, Literal - from griffe._internal.expressions import Expr - from griffe._internal.models import Docstring + from griffelib._internal.expressions import Expr + from griffelib._internal.models import Docstring _section_kind = { diff --git a/src/griffe/_internal/docstrings/models.py b/packages/griffelib/src/griffelib/_internal/docstrings/models.py similarity index 98% rename from src/griffe/_internal/docstrings/models.py rename to packages/griffelib/src/griffelib/_internal/docstrings/models.py index 545ea78d1..ce444eb80 100644 --- a/src/griffe/_internal/docstrings/models.py +++ b/packages/griffelib/src/griffelib/_internal/docstrings/models.py @@ -4,14 +4,14 @@ from typing import TYPE_CHECKING -from griffe._internal.enumerations import DocstringSectionKind -from griffe._internal.expressions import ExprTuple +from griffelib._internal.enumerations import DocstringSectionKind +from griffelib._internal.expressions import ExprTuple if TYPE_CHECKING: from collections.abc import Sequence from typing import Any, Literal - from griffe._internal.expressions import Expr + from griffelib._internal.expressions import Expr # Elements ----------------------------------------------- diff --git a/src/griffe/_internal/docstrings/numpy.py b/packages/griffelib/src/griffelib/_internal/docstrings/numpy.py similarity index 98% rename from src/griffe/_internal/docstrings/numpy.py rename to packages/griffelib/src/griffelib/_internal/docstrings/numpy.py index 080b7f63e..33550e502 100644 --- a/src/griffe/_internal/docstrings/numpy.py +++ b/packages/griffelib/src/griffelib/_internal/docstrings/numpy.py @@ -24,7 +24,7 @@ from textwrap import dedent from typing import TYPE_CHECKING, TypedDict -from griffe._internal.docstrings.models import ( +from griffelib._internal.docstrings.models import ( DocstringAttribute, DocstringClass, DocstringFunction, @@ -56,16 +56,16 @@ DocstringWarn, DocstringYield, ) -from griffe._internal.docstrings.utils import docstring_warning, parse_docstring_annotation -from griffe._internal.enumerations import DocstringSectionKind, LogLevel -from griffe._internal.expressions import ExprName +from griffelib._internal.docstrings.utils import docstring_warning, parse_docstring_annotation +from griffelib._internal.enumerations import DocstringSectionKind, LogLevel +from griffelib._internal.expressions import ExprName if TYPE_CHECKING: from re import Pattern from typing import Any, Literal - from griffe._internal.expressions import Expr - from griffe._internal.models import Docstring + from griffelib._internal.expressions import Expr + from griffelib._internal.models import Docstring _section_kind = { diff --git a/src/griffe/_internal/docstrings/parsers.py b/packages/griffelib/src/griffelib/_internal/docstrings/parsers.py similarity index 72% rename from src/griffe/_internal/docstrings/parsers.py rename to packages/griffelib/src/griffelib/_internal/docstrings/parsers.py index bb91f600a..f24ff1f7d 100644 --- a/src/griffe/_internal/docstrings/parsers.py +++ b/packages/griffelib/src/griffelib/_internal/docstrings/parsers.py @@ -5,15 +5,15 @@ from typing import TYPE_CHECKING, Any, Callable, Literal, Union -from griffe._internal.docstrings.auto import AutoOptions, parse_auto -from griffe._internal.docstrings.google import GoogleOptions, parse_google -from griffe._internal.docstrings.models import DocstringSection, DocstringSectionText -from griffe._internal.docstrings.numpy import NumpyOptions, parse_numpy -from griffe._internal.docstrings.sphinx import SphinxOptions, parse_sphinx -from griffe._internal.enumerations import Parser +from griffelib._internal.docstrings.auto import AutoOptions, parse_auto +from griffelib._internal.docstrings.google import GoogleOptions, parse_google +from griffelib._internal.docstrings.models import DocstringSection, DocstringSectionText +from griffelib._internal.docstrings.numpy import NumpyOptions, parse_numpy +from griffelib._internal.docstrings.sphinx import SphinxOptions, parse_sphinx +from griffelib._internal.enumerations import Parser if TYPE_CHECKING: - from griffe._internal.models import Docstring + from griffelib._internal.models import Docstring DocstringStyle = Literal["google", "numpy", "sphinx", "auto"] diff --git a/src/griffe/_internal/docstrings/sphinx.py b/packages/griffelib/src/griffelib/_internal/docstrings/sphinx.py similarity index 98% rename from src/griffe/_internal/docstrings/sphinx.py rename to packages/griffelib/src/griffelib/_internal/docstrings/sphinx.py index 743aa42f2..f11fa5e7e 100644 --- a/src/griffe/_internal/docstrings/sphinx.py +++ b/packages/griffelib/src/griffelib/_internal/docstrings/sphinx.py @@ -11,7 +11,7 @@ from inspect import cleandoc from typing import TYPE_CHECKING, Any, Callable, TypedDict -from griffe._internal.docstrings.models import ( +from griffelib._internal.docstrings.models import ( DocstringAttribute, DocstringParameter, DocstringRaise, @@ -23,11 +23,11 @@ DocstringSectionReturns, DocstringSectionText, ) -from griffe._internal.docstrings.utils import docstring_warning, parse_docstring_annotation +from griffelib._internal.docstrings.utils import docstring_warning, parse_docstring_annotation if TYPE_CHECKING: - from griffe._internal.expressions import Expr - from griffe._internal.models import Docstring + from griffelib._internal.expressions import Expr + from griffelib._internal.models import Docstring # TODO: Examples: from the documentation, we're not sure there is a standard format for examples diff --git a/src/griffe/_internal/docstrings/utils.py b/packages/griffelib/src/griffelib/_internal/docstrings/utils.py similarity index 88% rename from src/griffe/_internal/docstrings/utils.py rename to packages/griffelib/src/griffelib/_internal/docstrings/utils.py index 4c67069b0..5d2423cf7 100644 --- a/src/griffe/_internal/docstrings/utils.py +++ b/packages/griffelib/src/griffelib/_internal/docstrings/utils.py @@ -6,14 +6,14 @@ from contextlib import suppress from typing import TYPE_CHECKING -from griffe._internal.enumerations import LogLevel -from griffe._internal.exceptions import BuiltinModuleError -from griffe._internal.expressions import safe_get_annotation -from griffe._internal.logger import logger +from griffelib._internal.enumerations import LogLevel +from griffelib._internal.exceptions import BuiltinModuleError +from griffelib._internal.expressions import safe_get_annotation +from griffelib._internal.logger import logger if TYPE_CHECKING: - from griffe._internal.expressions import Expr - from griffe._internal.models import Docstring + from griffelib._internal.expressions import Expr + from griffelib._internal.models import Docstring def docstring_warning( diff --git a/src/griffe/_internal/encoders.py b/packages/griffelib/src/griffelib/_internal/encoders.py similarity index 96% rename from src/griffe/_internal/encoders.py rename to packages/griffelib/src/griffelib/_internal/encoders.py index 3f148dff4..fca73bd8e 100644 --- a/src/griffe/_internal/encoders.py +++ b/packages/griffelib/src/griffelib/_internal/encoders.py @@ -7,10 +7,10 @@ from pathlib import Path, PosixPath, WindowsPath from typing import Any, Callable -from griffe._internal import expressions -from griffe._internal.enumerations import Kind, ParameterKind, TypeParameterKind -from griffe._internal.git import GitInfo -from griffe._internal.models import ( +from griffelib._internal import expressions +from griffelib._internal.enumerations import Kind, ParameterKind, TypeParameterKind +from griffelib._internal.git import GitInfo +from griffelib._internal.models import ( Alias, Attribute, Class, @@ -41,11 +41,11 @@ class JSONEncoder(json.JSONEncoder): the [`json.dump`][] or [`json.dumps`][] methods. Examples: - >>> from griffe import JSONEncoder + >>> from griffelib import JSONEncoder >>> JSONEncoder(full=True).encode(..., **kwargs) >>> import json - >>> from griffe import JSONEncoder + >>> from griffelib import JSONEncoder >>> json.dumps(..., cls=JSONEncoder, full=True, **kwargs) """ @@ -61,7 +61,7 @@ def __init__( *args: See [`json.JSONEncoder`][]. full: Whether to dump full data or base data. If you plan to reload the data in Python memory - using the [`json_decoder`][griffe.json_decoder], + using the [`json_decoder`][griffelib.json_decoder], you don't need the full data as it can be inferred again using the base data. If you want to feed a non-Python tool instead, dump the full data. @@ -342,7 +342,7 @@ def json_decoder( Examples: >>> import json - >>> from griffe import json_decoder + >>> from griffelib import json_decoder >>> json.loads(..., object_hook=json_decoder) Parameters: diff --git a/src/griffe/_internal/enumerations.py b/packages/griffelib/src/griffelib/_internal/enumerations.py similarity index 100% rename from src/griffe/_internal/enumerations.py rename to packages/griffelib/src/griffelib/_internal/enumerations.py diff --git a/src/griffe/_internal/exceptions.py b/packages/griffelib/src/griffelib/_internal/exceptions.py similarity index 98% rename from src/griffe/_internal/exceptions.py rename to packages/griffelib/src/griffelib/_internal/exceptions.py index 4d104aa8e..3b864f7ad 100644 --- a/src/griffe/_internal/exceptions.py +++ b/packages/griffelib/src/griffelib/_internal/exceptions.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from griffe._internal.models import Alias + from griffelib._internal.models import Alias class GriffeError(Exception): diff --git a/src/griffe/_internal/expressions.py b/packages/griffelib/src/griffelib/_internal/expressions.py similarity index 99% rename from src/griffe/_internal/expressions.py rename to packages/griffelib/src/griffelib/_internal/expressions.py index 702bc56aa..512f2f830 100644 --- a/src/griffe/_internal/expressions.py +++ b/packages/griffelib/src/griffelib/_internal/expressions.py @@ -13,16 +13,16 @@ from functools import partial from typing import TYPE_CHECKING, Any, Protocol -from griffe._internal.agents.nodes.parameters import get_parameters -from griffe._internal.enumerations import LogLevel, ParameterKind -from griffe._internal.exceptions import NameResolutionError -from griffe._internal.logger import logger +from griffelib._internal.agents.nodes.parameters import get_parameters +from griffelib._internal.enumerations import LogLevel, ParameterKind +from griffelib._internal.exceptions import NameResolutionError +from griffelib._internal.logger import logger if TYPE_CHECKING: from collections.abc import Iterable, Iterator, Sequence from pathlib import Path - from griffe._internal.models import Class, Function, Module + from griffelib._internal.models import Class, Function, Module class _OperatorPrecedence(IntEnum): @@ -180,7 +180,7 @@ def iterate(self, *, flat: bool = True) -> Iterator[str | Expr]: # noqa: ARG002 without them getting rendered as strings. On the contrary, when flat is true, the whole tree is flattened as a sequence - of strings and instances of [Names][griffe.ExprName]. + of strings and instances of [Names][griffelib.ExprName]. Yields: Strings and names when flat, strings and expressions otherwise. @@ -227,7 +227,7 @@ def canonical_path(self) -> str: @property def canonical_name(self) -> str: """Name of the expressed name/attribute/parameter.""" - # We must handle things like `griffe.Visitor` and `griffe.Visitor(code)`. + # We must handle things like `griffelib.Visitor` and `griffelib.Visitor(code)`. return self.canonical_path.rsplit(".", 1)[-1].split("(", 1)[-1].removesuffix(")") @property diff --git a/src/griffe/_internal/extensions/__init__.py b/packages/griffelib/src/griffelib/_internal/extensions/__init__.py similarity index 100% rename from src/griffe/_internal/extensions/__init__.py rename to packages/griffelib/src/griffelib/_internal/extensions/__init__.py diff --git a/src/griffe/_internal/extensions/base.py b/packages/griffelib/src/griffelib/_internal/extensions/base.py similarity index 96% rename from src/griffe/_internal/extensions/base.py rename to packages/griffelib/src/griffelib/_internal/extensions/base.py index 08cc8f64a..879bf23af 100644 --- a/src/griffe/_internal/extensions/base.py +++ b/packages/griffelib/src/griffelib/_internal/extensions/base.py @@ -10,19 +10,19 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Union -from griffe._internal.agents.nodes.ast import ast_children, ast_kind -from griffe._internal.exceptions import ExtensionNotLoadedError -from griffe._internal.importer import dynamic_import +from griffelib._internal.agents.nodes.ast import ast_children, ast_kind +from griffelib._internal.exceptions import ExtensionNotLoadedError +from griffelib._internal.importer import dynamic_import if TYPE_CHECKING: import ast from types import ModuleType - from griffe._internal.agents.inspector import Inspector - from griffe._internal.agents.nodes.runtime import ObjectNode - from griffe._internal.agents.visitor import Visitor - from griffe._internal.loader import GriffeLoader - from griffe._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias + from griffelib._internal.agents.inspector import Inspector + from griffelib._internal.agents.nodes.runtime import ObjectNode + from griffelib._internal.agents.visitor import Visitor + from griffelib._internal.loader import GriffeLoader + from griffelib._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias class Extension: @@ -543,7 +543,7 @@ def _load_extension( # If the import path corresponds to a built-in extension, expand it. if import_path in builtin_extensions: - import_path = f"griffe._internal.extensions.{import_path}" + import_path = f"griffelib._internal.extensions.{import_path}" # If the import path is a path to an existing file, load it. elif os.path.exists(import_path): # noqa: PTH110 try: @@ -603,7 +603,7 @@ def load_extensions(*exts: LoadableExtensionType) -> Extensions: # TODO: Deprecate and remove at some point? # Always add our built-in dataclasses extension. - from griffe._internal.extensions.dataclasses import DataclassesExtension # noqa: PLC0415 + from griffelib._internal.extensions.dataclasses import DataclassesExtension # noqa: PLC0415 for ext in extensions._extensions: if type(ext) is DataclassesExtension: diff --git a/src/griffe/_internal/extensions/dataclasses.py b/packages/griffelib/src/griffelib/_internal/extensions/dataclasses.py similarity index 96% rename from src/griffe/_internal/extensions/dataclasses.py rename to packages/griffelib/src/griffelib/_internal/extensions/dataclasses.py index 5e6fa7b01..100b858ad 100644 --- a/src/griffe/_internal/extensions/dataclasses.py +++ b/packages/griffelib/src/griffelib/_internal/extensions/dataclasses.py @@ -10,16 +10,16 @@ from functools import cache from typing import Any, cast -from griffe._internal.enumerations import ParameterKind -from griffe._internal.expressions import ( +from griffelib._internal.enumerations import ParameterKind +from griffelib._internal.expressions import ( Expr, ExprAttribute, ExprCall, ExprDict, ) -from griffe._internal.extensions.base import Extension -from griffe._internal.logger import logger -from griffe._internal.models import Attribute, Class, Decorator, Function, Module, Parameter, Parameters +from griffelib._internal.extensions.base import Extension +from griffelib._internal.logger import logger +from griffelib._internal.models import Attribute, Class, Decorator, Function, Module, Parameter, Parameters def _dataclass_decorator(decorators: list[Decorator]) -> Expr | None: diff --git a/src/griffe/_internal/extensions/unpack_typeddict.py b/packages/griffelib/src/griffelib/_internal/extensions/unpack_typeddict.py similarity index 96% rename from src/griffe/_internal/extensions/unpack_typeddict.py rename to packages/griffelib/src/griffelib/_internal/extensions/unpack_typeddict.py index 162cbbf69..d228c9d3c 100644 --- a/src/griffe/_internal/extensions/unpack_typeddict.py +++ b/packages/griffelib/src/griffelib/_internal/extensions/unpack_typeddict.py @@ -7,14 +7,14 @@ from itertools import chain from typing import TYPE_CHECKING, Any, TypedDict -from griffe._internal.docstrings.models import ( +from griffelib._internal.docstrings.models import ( DocstringParameter, DocstringSectionParameters, ) -from griffe._internal.enumerations import DocstringSectionKind, ParameterKind -from griffe._internal.expressions import Expr, ExprSubscript -from griffe._internal.extensions.base import Extension -from griffe._internal.models import Class, Docstring, Function, Parameter, Parameters +from griffelib._internal.enumerations import DocstringSectionKind, ParameterKind +from griffelib._internal.expressions import Expr, ExprSubscript +from griffelib._internal.extensions.base import Extension +from griffelib._internal.models import Class, Docstring, Function, Parameter, Parameters if TYPE_CHECKING: from collections.abc import Iterable, Iterator diff --git a/src/griffe/_internal/finder.py b/packages/griffelib/src/griffelib/_internal/finder.py similarity index 94% rename from src/griffe/_internal/finder.py rename to packages/griffelib/src/griffelib/_internal/finder.py index 23bc3be29..b2e38ef66 100644 --- a/src/griffe/_internal/finder.py +++ b/packages/griffelib/src/griffelib/_internal/finder.py @@ -5,12 +5,12 @@ # # ```pycon # >>> from importlib.util import _find_spec -# >>> _find_spec("griffe.agents", _find_spec("griffe", None).submodule_search_locations) +# >>> _find_spec("griffelib.agents", _find_spec("griffelib", None).submodule_search_locations) # ModuleSpec( -# name='griffe.agents', +# name='griffelib.agents', # loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fa5f34e8110>, -# origin='/media/data/dev/griffe/src/griffe/agents/__init__.py', -# submodule_search_locations=['/media/data/dev/griffe/src/griffe/agents'], +# origin='/media/data/dev/griffelib/packages/griffelib/src/griffelib/agents/__init__.py', +# submodule_search_locations=['/media/data/dev/griffelib/packages/griffelib/src/griffelib/agents'], # ) # ``` @@ -27,14 +27,14 @@ from pathlib import Path from typing import TYPE_CHECKING, ClassVar -from griffe._internal.exceptions import UnhandledEditableModuleError -from griffe._internal.logger import logger +from griffelib._internal.exceptions import UnhandledEditableModuleError +from griffelib._internal.logger import logger if TYPE_CHECKING: from collections.abc import Iterator, Sequence from re import Pattern - from griffe._internal.models import Module + from griffelib._internal.models import Module _editable_editables_patterns = [re.compile(pat) for pat in (r"^__editables_\w+\.py$", r"^_editable_impl_\w+\.py$")] @@ -89,9 +89,9 @@ class ModuleFinder: """The Griffe finder, allowing to find modules on the file system. The module finder is generally not used directly. - Each [`GriffeLoader`][griffe.GriffeLoader] instance creates its own module finder instance. + Each [`GriffeLoader`][griffelib.GriffeLoader] instance creates its own module finder instance. The finder can be configured when instantiating the loader - thanks to the [loader][griffe.GriffeLoader]'s `search_paths` parameter. + thanks to the [loader][griffelib.GriffeLoader]'s `search_paths` parameter. """ accepted_py_module_extensions: ClassVar[list[str]] = [".py", ".pyc", ".pyo", ".pyd", ".pyi", ".so"] @@ -470,9 +470,9 @@ def _handle_pth_file(path: Path) -> list[_SP]: def _handle_editable_module(path: Path) -> list[_SP]: if _match_pattern(path.name, (*_editable_editables_patterns, *_editable_scikit_build_core_patterns)): # Support for how 'editables' write these files: - # example line: `F.map_module('griffe', '/media/data/dev/griffe/src/griffe/__init__.py')`. + # example line: `F.map_module('griffelib', '/media/data/dev/griffelib/packages/griffelib/src/griffelib/__init__.py')`. # And how 'scikit-build-core' writes these files: - # example line: `install({'griffe': '/media/data/dev/griffe/src/griffe/__init__.py'}, {'cmake_example': ...}, None, False, True)`. + # example line: `install({'griffelib': '/media/data/dev/griffelib/packages/griffelib/src/griffelib/__init__.py'}, {'cmake_example': ...}, None, False, True)`. try: editable_lines = path.read_text(encoding="utf-8-sig").strip().splitlines(keepends=False) except FileNotFoundError as error: @@ -483,7 +483,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: return [_SP(new_path)] if _match_pattern(path.name, _editable_setuptools_patterns): # Support for how 'setuptools' writes these files: - # example line: `MAPPING = {'griffe': '/media/data/dev/griffe/src/griffe', 'briffe': '/media/data/dev/griffe/src/briffe'}`. + # example line: `MAPPING = {'griffelib': '/media/data/dev/griffelib/packages/griffelib/src/griffelib', 'briffe': '/media/data/dev/griffelib/src/briffe'}`. # with annotation: `MAPPING: dict[str, str] = {...}`. parsed_module = ast.parse(path.read_text(encoding="utf8")) for node in parsed_module.body: @@ -497,7 +497,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: return [_SP(Path(cst.value).parent) for cst in node.value.values if isinstance(cst, ast.Constant)] # type: ignore[arg-type] if _match_pattern(path.name, _editable_meson_python_patterns): # Support for how 'meson-python' writes these files: - # example line: `install({'package', 'module1'}, '/media/data/dev/griffe/build/cp311', ["path"], False)`. + # example line: `install({'package', 'module1'}, '/media/data/dev/griffelib/build/cp311', ["path"], False)`. # Compiled modules then found in the cp311 folder, under src/package. parsed_module = ast.parse(path.read_text(encoding="utf8")) for node in parsed_module.body: diff --git a/src/griffe/_internal/git.py b/packages/griffelib/src/griffelib/_internal/git.py similarity index 97% rename from src/griffe/_internal/git.py rename to packages/griffelib/src/griffelib/_internal/git.py index 47642c009..2ee41d424 100644 --- a/src/griffe/_internal/git.py +++ b/packages/griffelib/src/griffelib/_internal/git.py @@ -1,4 +1,4 @@ -# This module contains Git utilities, used by our [`load_git`][griffe.load_git] function, +# This module contains Git utilities, used by our [`load_git`][griffelib.load_git] function, # which in turn is used to load the API for different snapshots of a Git repository # and find breaking changes between them. @@ -16,15 +16,15 @@ from typing import TYPE_CHECKING, Literal from urllib.parse import urlsplit, urlunsplit -from griffe._internal.exceptions import BuiltinModuleError, GitError +from griffelib._internal.exceptions import BuiltinModuleError, GitError if TYPE_CHECKING: from collections.abc import Iterator - from griffe._internal.models import Module + from griffelib._internal.models import Module -_WORKTREE_PREFIX = "griffe-worktree-" +_WORKTREE_PREFIX = "griffelib-worktree-" def _normalize(value: str) -> str: @@ -120,7 +120,7 @@ def _tmp_worktree(repo: str | Path = ".", ref: str = "HEAD") -> Iterator[Path]: normref = _normalize(ref) # Branch names can contain slashes. with TemporaryDirectory(prefix=f"{_WORKTREE_PREFIX}{repo_name}-{normref}-") as tmp_dir: location = os.path.join(tmp_dir, normref) # noqa: PTH118 - tmp_branch = f"griffe-{normref}" # Temporary branch name must not already exist. + tmp_branch = f"griffelib-{normref}" # Temporary branch name must not already exist. try: _git("-C", str(repo), "worktree", "add", "-b", tmp_branch, location, ref) except GitError as error: diff --git a/src/griffe/_internal/importer.py b/packages/griffelib/src/griffelib/_internal/importer.py similarity index 98% rename from src/griffe/_internal/importer.py rename to packages/griffelib/src/griffelib/_internal/importer.py index b75b44ee2..4144357c3 100644 --- a/src/griffe/_internal/importer.py +++ b/packages/griffelib/src/griffelib/_internal/importer.py @@ -1,5 +1,5 @@ # This module contains utilities to dynamically import objects. -# These utilities are used by our [`Inspector`][griffe.Inspector] to dynamically import objects +# These utilities are used by our [`Inspector`][griffelib.Inspector] to dynamically import objects # specified as Python paths, like `package.module.Class.method`. from __future__ import annotations diff --git a/src/griffe/_internal/loader.py b/packages/griffelib/src/griffelib/_internal/loader.py similarity index 95% rename from src/griffe/_internal/loader.py rename to packages/griffelib/src/griffelib/_internal/loader.py index b2a2d45b5..ba9c6eddb 100644 --- a/src/griffe/_internal/loader.py +++ b/packages/griffelib/src/griffelib/_internal/loader.py @@ -14,31 +14,31 @@ from pathlib import Path from typing import TYPE_CHECKING, ClassVar, cast -from griffe._internal.agents.inspector import inspect -from griffe._internal.agents.visitor import visit -from griffe._internal.collections import LinesCollection, ModulesCollection -from griffe._internal.enumerations import Kind -from griffe._internal.exceptions import ( +from griffelib._internal.agents.inspector import inspect +from griffelib._internal.agents.visitor import visit +from griffelib._internal.collections import LinesCollection, ModulesCollection +from griffelib._internal.enumerations import Kind +from griffelib._internal.exceptions import ( AliasResolutionError, CyclicAliasError, LoadingError, UnimportableModuleError, ) -from griffe._internal.expressions import ExprName -from griffe._internal.extensions.base import Extensions, load_extensions -from griffe._internal.finder import ModuleFinder, NamespacePackage, Package -from griffe._internal.git import GitInfo, _tmp_worktree -from griffe._internal.importer import dynamic_import -from griffe._internal.logger import logger -from griffe._internal.merger import merge_stubs -from griffe._internal.models import Alias, Module, Object -from griffe._internal.stats import Stats +from griffelib._internal.expressions import ExprName +from griffelib._internal.extensions.base import Extensions, load_extensions +from griffelib._internal.finder import ModuleFinder, NamespacePackage, Package +from griffelib._internal.git import GitInfo, _tmp_worktree +from griffelib._internal.importer import dynamic_import +from griffelib._internal.logger import logger +from griffelib._internal.merger import merge_stubs +from griffelib._internal.models import Alias, Module, Object +from griffelib._internal.stats import Stats if TYPE_CHECKING: from collections.abc import Sequence - from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffe._internal.enumerations import Parser + from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffelib._internal.enumerations import Parser class GriffeLoader: @@ -119,8 +119,8 @@ def load( with regular methods and properties (`parent`, `members`, etc.). Examples: - >>> loader.load("griffe.Module") - Alias("Module", "griffe._internal.models.Module") + >>> loader.load("griffelib.Module") + Alias("Module", "griffelib._internal.models.Module") Parameters: objspec: The Python path of an object, or file path to a module. @@ -293,7 +293,7 @@ def resolve_aliases( def expand_exports(self, module: Module, seen: set | None = None) -> None: """Expand exports: try to recursively expand all module exports (`__all__` values). - See also: [`Module.exports`][griffe.Module.exports]. + See also: [`Module.exports`][griffelib.Module.exports]. Parameters: module: The module to recurse on. @@ -340,7 +340,7 @@ def expand_wildcards( ) -> None: """Expand wildcards: try to recursively expand all found wildcards. - See also: [`Alias.wildcard`][griffe.Alias.wildcard]. + See also: [`Alias.wildcard`][griffelib.Alias.wildcard]. Parameters: obj: The object and its members to recurse on. @@ -645,7 +645,7 @@ def _load_submodule(self, module: Module, subparts: tuple[str, ...], subpath: Pa logger.debug( "Submodule '%s' is shadowing the member at the same path. " "We recommend renaming the member or the submodule (for example prefixing it with `_`), " - "see https://mkdocstrings.github.io/griffe/best_practices/#avoid-member-submodule-name-shadowing.", + "see https://mkdocstrings.github.io/griffelib/best_practices/#avoid-member-submodule-name-shadowing.", submodule.path, ) parent_module.set_member(submodule_name, submodule) @@ -769,37 +769,37 @@ def load( In Griffe's context, loading means: - searching for a package, and finding it on the file system or as a builtin module - (see the [`ModuleFinder`][griffe.ModuleFinder] class for more information) + (see the [`ModuleFinder`][griffelib.ModuleFinder] class for more information) - extracting information from each of its (sub)modules, by either parsing - the source code (see the [`visit`][griffe.visit] function) - or inspecting the module at runtime (see the [`inspect`][griffe.inspect] function) + the source code (see the [`visit`][griffelib.visit] function) + or inspecting the module at runtime (see the [`inspect`][griffelib.inspect] function) The extracted information is stored in a collection of modules, which can be queried later. Each collected module is a tree of objects, representing the structure of the module. - See the [`Module`][griffe.Module], [`Class`][griffe.Class], - [`Function`][griffe.Function], [`Attribute`][griffe.Attribute], and - [`TypeAlias`][griffe.TypeAlias] classes for more information. + See the [`Module`][griffelib.Module], [`Class`][griffelib.Class], + [`Function`][griffelib.Function], [`Attribute`][griffelib.Attribute], and + [`TypeAlias`][griffelib.TypeAlias] classes for more information. - The main class used to load modules is [`GriffeLoader`][griffe.GriffeLoader]. - Convenience functions like this one and [`load_git`][griffe.load_git] are also available. + The main class used to load modules is [`GriffeLoader`][griffelib.GriffeLoader]. + Convenience functions like this one and [`load_git`][griffelib.load_git] are also available. Example: ```python - import griffe + import griffelib - module = griffe.load(...) + module = griffelib.load(...) ``` This is a shortcut for: ```python - from griffe import GriffeLoader + from griffelib import GriffeLoader loader = GriffeLoader(...) module = loader.load(...) ``` - See the documentation for the loader: [`GriffeLoader`][griffe.GriffeLoader]. + See the documentation for the loader: [`GriffeLoader`][griffelib.GriffeLoader]. Parameters: objspec: The Python path of an object, or file path to a module. @@ -873,13 +873,13 @@ def load_git( This function will create a temporary [git worktree](https://git-scm.com/docs/git-worktree) at the requested reference - before loading `module` with [`griffe.load`][griffe.load]. + before loading `module` with [`griffelib.load`][griffelib.load]. This function requires that the `git` executable is installed. Examples: ```python - from griffe import load_git + from griffelib import load_git old_api = load_git("my_module", ref="v0.1.0", repo="path/to/repo") ``` @@ -983,7 +983,7 @@ def load_pypi( import platformdirs # noqa: PLC0415 - pypi_cache_dir = Path(platformdirs.user_cache_dir("griffe")) + pypi_cache_dir = Path(platformdirs.user_cache_dir("griffelib")) install_dir = pypi_cache_dir / f"{distribution}{version_spec}" if install_dir.exists(): logger.debug("Using cached %s%s", distribution, version_spec) diff --git a/src/griffe/_internal/logger.py b/packages/griffelib/src/griffelib/_internal/logger.py similarity index 92% rename from src/griffe/_internal/logger.py rename to packages/griffelib/src/griffelib/_internal/logger.py index 6a7290fc3..3e598a758 100644 --- a/src/griffe/_internal/logger.py +++ b/packages/griffelib/src/griffelib/_internal/logger.py @@ -4,7 +4,7 @@ # For example, mkdocstrings-python patches the logger to relocate it as a child # of `mkdocs.plugins` so that it fits in the MkDocs logging configuration. # -# We use a single, global logger because our public API is exposed in a single module, `griffe`. +# We use a single, global logger because our public API is exposed in a single module, `griffelib`. # Extensions however should use their own logger, which is why we provide the `get_logger` function. from __future__ import annotations @@ -40,7 +40,7 @@ def disable(self) -> Iterator[None]: self._logger.setLevel(old_level) @classmethod - def _get(cls, name: str = "griffe") -> Logger: + def _get(cls, name: str = "griffelib") -> Logger: if name not in cls._instances: cls._instances[name] = cls(name) return cls._instances[name] @@ -60,7 +60,7 @@ def _patch_loggers(cls, get_logger_func: Callable) -> None: Griffe's output and error messages are logging messages. -Griffe provides the [`patch_loggers`][griffe.patch_loggers] +Griffe provides the [`patch_loggers`][griffelib.patch_loggers] function so dependent libraries can patch Griffe loggers as they see fit. For example, to fit in the MkDocs logging configuration @@ -68,7 +68,7 @@ def _patch_loggers(cls, get_logger_func: Callable) -> None: ```python import logging -from griffe import patch_loggers +from griffelib import patch_loggers class LoggerAdapter(logging.LoggerAdapter): @@ -90,7 +90,7 @@ def get_logger(name): """ -def get_logger(name: str = "griffe") -> Logger: +def get_logger(name: str = "griffelib") -> Logger: """Create and return a new logger instance. Parameters: diff --git a/src/griffe/_internal/merger.py b/packages/griffelib/src/griffelib/_internal/merger.py similarity index 95% rename from src/griffe/_internal/merger.py rename to packages/griffelib/src/griffelib/_internal/merger.py index 798ebf08e..d95eaa1d2 100644 --- a/src/griffe/_internal/merger.py +++ b/packages/griffelib/src/griffelib/_internal/merger.py @@ -5,11 +5,11 @@ from contextlib import suppress from typing import TYPE_CHECKING -from griffe._internal.exceptions import AliasResolutionError, CyclicAliasError -from griffe._internal.logger import logger +from griffelib._internal.exceptions import AliasResolutionError, CyclicAliasError +from griffelib._internal.logger import logger if TYPE_CHECKING: - from griffe._internal.models import Attribute, Class, Function, Module, Object, TypeAlias + from griffelib._internal.models import Attribute, Class, Function, Module, Object, TypeAlias def _merge_module_stubs(module: Module, stubs: Module) -> None: diff --git a/src/griffe/_internal/mixins.py b/packages/griffelib/src/griffelib/_internal/mixins.py similarity index 97% rename from src/griffe/_internal/mixins.py rename to packages/griffelib/src/griffelib/_internal/mixins.py index 05d69414c..b7455674c 100644 --- a/src/griffe/_internal/mixins.py +++ b/packages/griffelib/src/griffelib/_internal/mixins.py @@ -7,14 +7,14 @@ from contextlib import suppress from typing import TYPE_CHECKING, Any, TypeVar -from griffe._internal.enumerations import Kind -from griffe._internal.exceptions import AliasResolutionError, BuiltinModuleError, CyclicAliasError -from griffe._internal.merger import merge_stubs +from griffelib._internal.enumerations import Kind +from griffelib._internal.exceptions import AliasResolutionError, BuiltinModuleError, CyclicAliasError +from griffelib._internal.merger import merge_stubs if TYPE_CHECKING: from collections.abc import Sequence - from griffe._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias + from griffelib._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias _ObjType = TypeVar("_ObjType") @@ -222,7 +222,7 @@ def as_json(self, *, full: bool = False, **kwargs: Any) -> str: Returns: A JSON string. """ - from griffe._internal.encoders import JSONEncoder # Avoid circular import. # noqa: PLC0415 + from griffelib._internal.encoders import JSONEncoder # Avoid circular import. # noqa: PLC0415 return json.dumps(self, cls=JSONEncoder, full=full, **kwargs) @@ -241,7 +241,7 @@ def from_json(cls: type[_ObjType], json_string: str, **kwargs: Any) -> _ObjType: TypeError: When the json_string does not represent and object of the class from which this classmethod has been called. """ - from griffe._internal.encoders import json_decoder # Avoid circular import. # noqa: PLC0415 + from griffelib._internal.encoders import json_decoder # Avoid circular import. # noqa: PLC0415 kwargs.setdefault("object_hook", json_decoder) obj = json.loads(json_string, **kwargs) diff --git a/src/griffe/_internal/models.py b/packages/griffelib/src/griffelib/_internal/models.py similarity index 86% rename from src/griffe/_internal/models.py rename to packages/griffelib/src/griffelib/_internal/models.py index 9cc60e17f..fde780f6e 100644 --- a/src/griffe/_internal/models.py +++ b/packages/griffelib/src/griffelib/_internal/models.py @@ -11,21 +11,21 @@ from textwrap import dedent from typing import TYPE_CHECKING, Any, Callable, Literal, Union, cast -from griffe._internal.c3linear import c3linear_merge -from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle, parse -from griffe._internal.enumerations import Kind, ParameterKind, Parser, TypeParameterKind -from griffe._internal.exceptions import AliasResolutionError, BuiltinModuleError, CyclicAliasError, NameResolutionError -from griffe._internal.expressions import ExprCall, ExprName, ExprTuple -from griffe._internal.logger import logger -from griffe._internal.mixins import ObjectAliasMixin +from griffelib._internal.c3linear import c3linear_merge +from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle, parse +from griffelib._internal.enumerations import Kind, ParameterKind, Parser, TypeParameterKind +from griffelib._internal.exceptions import AliasResolutionError, BuiltinModuleError, CyclicAliasError, NameResolutionError +from griffelib._internal.expressions import ExprCall, ExprName, ExprTuple +from griffelib._internal.logger import logger +from griffelib._internal.mixins import ObjectAliasMixin if TYPE_CHECKING: from collections.abc import Sequence - from griffe._internal.collections import LinesCollection, ModulesCollection - from griffe._internal.docstrings.models import DocstringSection - from griffe._internal.expressions import Expr - from griffe._internal.git import GitInfo + from griffelib._internal.collections import LinesCollection, ModulesCollection + from griffelib._internal.docstrings.models import DocstringSection + from griffelib._internal.expressions import Expr + from griffelib._internal.git import GitInfo from functools import cached_property @@ -97,18 +97,18 @@ def __init__( self.value: str = inspect.cleandoc(value.rstrip()) """The original value of the docstring, cleaned by `inspect.cleandoc`. - See also: [`source`][griffe.Docstring.source]. + See also: [`source`][griffelib.Docstring.source]. """ self.lineno: int | None = lineno """The starting line number of the docstring. - See also: [`endlineno`][griffe.Docstring.endlineno].""" + See also: [`endlineno`][griffelib.Docstring.endlineno].""" self.endlineno: int | None = endlineno """The ending line number of the docstring. - See also: [`lineno`][griffe.Docstring.lineno].""" + See also: [`lineno`][griffelib.Docstring.lineno].""" self.parent: Object | None = parent """The object this docstring is attached to.""" @@ -116,22 +116,22 @@ def __init__( self.parser: DocstringStyle | Parser | None = parser """The selected docstring parser. - See also: [`parser_options`][griffe.Docstring.parser_options], - [`parse`][griffe.Docstring.parse]. + See also: [`parser_options`][griffelib.Docstring.parser_options], + [`parse`][griffelib.Docstring.parse]. """ self.parser_options: DocstringOptions = parser_options or {} """The configured parsing options. - See also: [`parser`][griffe.Docstring.parser], - [`parse`][griffe.Docstring.parse]. + See also: [`parser`][griffelib.Docstring.parser], + [`parse`][griffelib.Docstring.parse]. """ @property def lines(self) -> list[str]: """The lines of the docstring. - See also: [`source`][griffe.Docstring.source]. + See also: [`source`][griffelib.Docstring.source]. """ return self.value.split("\n") @@ -147,7 +147,7 @@ def source(self) -> str: ValueError: If the original docstring cannot be retrieved (no parent, no line numbers, or attached to namespace package). - See also: [`value`][griffe.Docstring.value]. + See also: [`value`][griffelib.Docstring.value]. """ if self.parent is None: raise ValueError("Cannot get original docstring without parent object") @@ -169,8 +169,8 @@ def parse( ) -> list[DocstringSection]: """Parse the docstring into structured data. - See also: [`parser`][griffe.Docstring.parser], - [`parser_options`][griffe.Docstring.parser_options]. + See also: [`parser`][griffelib.Docstring.parser], + [`parser_options`][griffelib.Docstring.parser_options]. Parameters: parser: The docstring parser to use. @@ -210,7 +210,7 @@ def as_dict( class Parameter: # noqa: PLW1641 """This class represent a function parameter. - See also: [`Parameters`][griffe.Parameters]. + See also: [`Parameters`][griffelib.Parameters]. """ def __init__( @@ -302,7 +302,7 @@ class Parameters: True ``` - See also: [`Parameter`][griffe.Parameter]. + See also: [`Parameter`][griffelib.Parameter]. """ def __init__(self, *parameters: Parameter) -> None: @@ -613,20 +613,20 @@ def __init__( self.lineno: int | None = lineno """The starting line number of the object. - See also: [`endlineno`][griffe.Object.endlineno]. + See also: [`endlineno`][griffelib.Object.endlineno]. """ self.endlineno: int | None = endlineno """The ending line number of the object. - See also: [`lineno`][griffe.Object.lineno]. + See also: [`lineno`][griffelib.Object.lineno]. """ self.docstring: Docstring | None = docstring """The object docstring. - See also: [`has_docstring`][griffe.Object.has_docstring], - [`has_docstrings`][griffe.Object.has_docstrings]. + See also: [`has_docstring`][griffelib.Object.has_docstring], + [`has_docstrings`][griffelib.Object.has_docstrings]. """ # TODO: Maybe move these into `Class` and `Function`. @@ -641,16 +641,16 @@ def __init__( self.members: dict[str, Object | Alias] = {} """The object members (modules, classes, functions, attributes, type aliases). - See also: [`inherited_members`][griffe.Object.inherited_members], - [`get_member`][griffe.Object.get_member], - [`set_member`][griffe.Object.set_member], - [`filter_members`][griffe.Object.filter_members]. + See also: [`inherited_members`][griffelib.Object.inherited_members], + [`get_member`][griffelib.Object.get_member], + [`set_member`][griffelib.Object.set_member], + [`filter_members`][griffelib.Object.filter_members]. """ self.labels: set[str] = set() """The object labels (`property`, `dataclass`, etc.). - See also: [`has_labels`][griffe.Object.has_labels].""" + See also: [`has_labels`][griffelib.Object.has_labels].""" self.imports: dict[str, str] = {} """The other objects imported by this object. @@ -673,7 +673,7 @@ def __init__( Exports get expanded by the loader before it expands wildcards and resolves aliases. - See also: [`GriffeLoader.expand_exports`][griffe.GriffeLoader.expand_exports]. + See also: [`GriffeLoader.expand_exports`][griffelib.GriffeLoader.expand_exports]. """ self.aliases: dict[str, Alias] = {} @@ -757,8 +757,8 @@ def source_link(self, value: str | None) -> None: def has_docstring(self) -> bool: """Whether this object has a docstring (empty or not). - See also: [`docstring`][griffe.Object.docstring], - [`has_docstrings`][griffe.Object.has_docstrings]. + See also: [`docstring`][griffelib.Object.docstring], + [`has_docstrings`][griffelib.Object.has_docstrings]. """ return bool(self.docstring) @@ -777,8 +777,8 @@ def has_docstrings(self) -> bool: Inherited members are not considered. Imported members are not considered, unless they are also public. - See also: [`docstring`][griffe.Object.docstring], - [`has_docstring`][griffe.Object.has_docstring]. + See also: [`docstring`][griffelib.Object.docstring], + [`has_docstring`][griffelib.Object.has_docstring]. """ if self.has_docstring: return True @@ -793,12 +793,12 @@ def has_docstrings(self) -> bool: def is_kind(self, kind: str | Kind | set[str | Kind]) -> bool: """Tell if this object is of the given kind. - See also: [`is_module`][griffe.Object.is_module], - [`is_class`][griffe.Object.is_class], - [`is_function`][griffe.Object.is_function], - [`is_attribute`][griffe.Object.is_attribute], - [`is_type_alias`][griffe.Object.is_type_alias], - [`is_alias`][griffe.Object.is_alias]. + See also: [`is_module`][griffelib.Object.is_module], + [`is_class`][griffelib.Object.is_class], + [`is_function`][griffelib.Object.is_function], + [`is_attribute`][griffelib.Object.is_attribute], + [`is_type_alias`][griffelib.Object.is_type_alias], + [`is_alias`][griffelib.Object.is_alias]. Parameters: kind: An instance or set of kinds (strings or enumerations). @@ -824,7 +824,7 @@ def inherited_members(self) -> dict[str, Alias]: This method is part of the consumer API: do not use when producing Griffe trees! - See also: [`members`][griffe.Object.members]. + See also: [`members`][griffelib.Object.members]. """ if not isinstance(self, Class): return {} @@ -844,13 +844,13 @@ def inherited_members(self) -> dict[str, Alias]: def is_module(self) -> bool: """Whether this object is a module. - See also: [`is_init_module`][griffe.Object.is_init_module]. - [`is_class`][griffe.Object.is_class], - [`is_function`][griffe.Object.is_function], - [`is_attribute`][griffe.Object.is_attribute], - [`is_type_alias`][griffe.Object.is_type_alias], - [`is_alias`][griffe.Object.is_alias], - [`is_kind`][griffe.Object.is_kind]. + See also: [`is_init_module`][griffelib.Object.is_init_module]. + [`is_class`][griffelib.Object.is_class], + [`is_function`][griffelib.Object.is_function], + [`is_attribute`][griffelib.Object.is_attribute], + [`is_type_alias`][griffelib.Object.is_type_alias], + [`is_alias`][griffelib.Object.is_alias], + [`is_kind`][griffelib.Object.is_kind]. """ return self.kind is Kind.MODULE @@ -858,12 +858,12 @@ def is_module(self) -> bool: def is_class(self) -> bool: """Whether this object is a class. - See also: [`is_module`][griffe.Object.is_module]. - [`is_function`][griffe.Object.is_function], - [`is_attribute`][griffe.Object.is_attribute], - [`is_type_alias`][griffe.Object.is_type_alias], - [`is_alias`][griffe.Object.is_alias], - [`is_kind`][griffe.Object.is_kind]. + See also: [`is_module`][griffelib.Object.is_module]. + [`is_function`][griffelib.Object.is_function], + [`is_attribute`][griffelib.Object.is_attribute], + [`is_type_alias`][griffelib.Object.is_type_alias], + [`is_alias`][griffelib.Object.is_alias], + [`is_kind`][griffelib.Object.is_kind]. """ return self.kind is Kind.CLASS @@ -871,12 +871,12 @@ def is_class(self) -> bool: def is_function(self) -> bool: """Whether this object is a function. - See also: [`is_module`][griffe.Object.is_module]. - [`is_class`][griffe.Object.is_class], - [`is_attribute`][griffe.Object.is_attribute], - [`is_type_alias`][griffe.Object.is_type_alias], - [`is_alias`][griffe.Object.is_alias], - [`is_kind`][griffe.Object.is_kind]. + See also: [`is_module`][griffelib.Object.is_module]. + [`is_class`][griffelib.Object.is_class], + [`is_attribute`][griffelib.Object.is_attribute], + [`is_type_alias`][griffelib.Object.is_type_alias], + [`is_alias`][griffelib.Object.is_alias], + [`is_kind`][griffelib.Object.is_kind]. """ return self.kind is Kind.FUNCTION @@ -884,12 +884,12 @@ def is_function(self) -> bool: def is_attribute(self) -> bool: """Whether this object is an attribute. - See also: [`is_module`][griffe.Object.is_module]. - [`is_class`][griffe.Object.is_class], - [`is_function`][griffe.Object.is_function], - [`is_type_alias`][griffe.Object.is_type_alias], - [`is_alias`][griffe.Object.is_alias], - [`is_kind`][griffe.Object.is_kind]. + See also: [`is_module`][griffelib.Object.is_module]. + [`is_class`][griffelib.Object.is_class], + [`is_function`][griffelib.Object.is_function], + [`is_type_alias`][griffelib.Object.is_type_alias], + [`is_alias`][griffelib.Object.is_alias], + [`is_kind`][griffelib.Object.is_kind]. """ return self.kind is Kind.ATTRIBUTE @@ -897,12 +897,12 @@ def is_attribute(self) -> bool: def is_type_alias(self) -> bool: """Whether this object is a type alias. - See also: [`is_module`][griffe.Object.is_module]. - [`is_class`][griffe.Object.is_class], - [`is_function`][griffe.Object.is_function], - [`is_attribute`][griffe.Object.is_attribute], - [`is_alias`][griffe.Object.is_alias], - [`is_kind`][griffe.Object.is_kind]. + See also: [`is_module`][griffelib.Object.is_module]. + [`is_class`][griffelib.Object.is_class], + [`is_function`][griffelib.Object.is_function], + [`is_attribute`][griffelib.Object.is_attribute], + [`is_alias`][griffelib.Object.is_alias], + [`is_kind`][griffelib.Object.is_kind]. """ return self.kind is Kind.TYPE_ALIAS @@ -915,7 +915,7 @@ def is_init_method(self) -> bool: def is_init_module(self) -> bool: """Whether this object is an `__init__.py` module. - See also: [`is_module`][griffe.Object.is_module]. + See also: [`is_module`][griffelib.Object.is_module]. """ return False @@ -923,7 +923,7 @@ def is_init_module(self) -> bool: def is_package(self) -> bool: """Whether this object is a package (top module). - See also: [`is_subpackage`][griffe.Object.is_subpackage]. + See also: [`is_subpackage`][griffelib.Object.is_subpackage]. """ return False @@ -931,7 +931,7 @@ def is_package(self) -> bool: def is_subpackage(self) -> bool: """Whether this object is a subpackage. - See also: [`is_package`][griffe.Object.is_package]. + See also: [`is_package`][griffelib.Object.is_package]. """ return False @@ -939,7 +939,7 @@ def is_subpackage(self) -> bool: def is_namespace_package(self) -> bool: """Whether this object is a namespace package (top folder, no `__init__.py`). - See also: [`is_namespace_subpackage`][griffe.Object.is_namespace_subpackage]. + See also: [`is_namespace_subpackage`][griffelib.Object.is_namespace_subpackage]. """ return False @@ -947,14 +947,14 @@ def is_namespace_package(self) -> bool: def is_namespace_subpackage(self) -> bool: """Whether this object is a namespace subpackage. - See also: [`is_namespace_package`][griffe.Object.is_namespace_package]. + See also: [`is_namespace_package`][griffelib.Object.is_namespace_package]. """ return False def has_labels(self, *labels: str) -> bool: """Tell if this object has all the given labels. - See also: [`labels`][griffe.Object.labels]. + See also: [`labels`][griffelib.Object.labels]. Parameters: *labels: Labels that must be present. @@ -967,7 +967,7 @@ def has_labels(self, *labels: str) -> bool: def filter_members(self, *predicates: Callable[[Object | Alias], bool]) -> dict[str, Object | Alias]: """Filter and return members based on predicates. - See also: [`members`][griffe.Object.members]. + See also: [`members`][griffelib.Object.members]. Parameters: *predicates: A list of predicates, i.e. callables accepting a member as argument and returning a boolean. @@ -986,11 +986,11 @@ def filter_members(self, *predicates: Callable[[Object | Alias], bool]) -> dict[ def module(self) -> Module: """The parent module of this object. - See also: [`package`][griffe.Object.package]. + See also: [`package`][griffelib.Object.package]. Examples: - >>> import griffe - >>> markdown = griffe.load("markdown") + >>> import griffelib + >>> markdown = griffelib.load("markdown") >>> markdown["core.Markdown.references"].module Module(PosixPath('~/project/.venv/lib/python3.11/site-packages/markdown/core.py')) >>> # The `module` of a module is itself. @@ -1010,11 +1010,11 @@ def module(self) -> Module: def package(self) -> Module: """The absolute top module (the package) of this object. - See also: [`module`][griffe.Object.module]. + See also: [`module`][griffelib.Object.module]. Examples: - >>> import griffe - >>> markdown = griffe.load("markdown") + >>> import griffelib + >>> markdown = griffelib.load("markdown") >>> markdown["core.Markdown.references"].package Module(PosixPath('~/project/.venv/lib/python3.11/site-packages/markdown/__init__.py')) """ @@ -1027,12 +1027,12 @@ def package(self) -> Module: def filepath(self) -> Path | list[Path]: """The file path (or directory list for namespace packages) where this object was defined. - See also: [`relative_filepath`][griffe.Object.relative_filepath], - [`relative_package_filepath`][griffe.Object.relative_package_filepath]. + See also: [`relative_filepath`][griffelib.Object.relative_filepath], + [`relative_package_filepath`][griffelib.Object.relative_package_filepath]. Examples: - >>> import griffe - >>> markdown = griffe.load("markdown") + >>> import griffelib + >>> markdown = griffelib.load("markdown") >>> markdown.filepath PosixPath('~/project/.venv/lib/python3.11/site-packages/markdown/__init__.py') """ @@ -1042,8 +1042,8 @@ def filepath(self) -> Path | list[Path]: def relative_package_filepath(self) -> Path: """The file path where this object was defined, relative to the top module path. - See also: [`filepath`][griffe.Object.filepath], - [`relative_filepath`][griffe.Object.relative_filepath]. + See also: [`filepath`][griffelib.Object.filepath], + [`relative_filepath`][griffelib.Object.relative_filepath]. Raises: ValueError: When the relative path could not be computed. @@ -1088,8 +1088,8 @@ def relative_filepath(self) -> Path: If this object's file path is not relative to the current working directory, return its absolute path. - See also: [`filepath`][griffe.Object.filepath], - [`relative_package_filepath`][griffe.Object.relative_package_filepath]. + See also: [`filepath`][griffelib.Object.filepath], + [`relative_package_filepath`][griffelib.Object.relative_package_filepath]. Raises: ValueError: When the relative path could not be computed. @@ -1111,11 +1111,11 @@ def path(self) -> str: On regular objects (not aliases), the path is the canonical path. - See also: [`canonical_path`][griffe.Object.canonical_path]. + See also: [`canonical_path`][griffelib.Object.canonical_path]. Examples: - >>> import griffe - >>> markdown = griffe.load("markdown") + >>> import griffelib + >>> markdown = griffelib.load("markdown") >>> markdown["core.Markdown.references"].path 'markdown.core.Markdown.references' """ @@ -1127,7 +1127,7 @@ def canonical_path(self) -> str: The canonical path is the path where the object was defined (not imported). - See also: [`path`][griffe.Object.path]. + See also: [`path`][griffelib.Object.path]. """ if self.parent is None: return self.name @@ -1150,8 +1150,8 @@ def modules_collection(self) -> ModulesCollection: def lines_collection(self) -> LinesCollection: """The lines collection attached to this object or its parents. - See also: [`lines`][griffe.Object.lines], - [`source`][griffe.Object.source]. + See also: [`lines`][griffelib.Object.lines], + [`source`][griffelib.Object.source]. Raises: ValueError: When no modules collection can be found in the object or its parents. @@ -1166,8 +1166,8 @@ def lines_collection(self) -> LinesCollection: def lines(self) -> list[str]: """The lines containing the source of this object. - See also: [`lines_collection`][griffe.Object.lines_collection], - [`source`][griffe.Object.source]. + See also: [`lines_collection`][griffelib.Object.lines_collection], + [`source`][griffelib.Object.source]. """ try: filepath = self.filepath @@ -1189,8 +1189,8 @@ def lines(self) -> list[str]: def source(self) -> str: """The source code of this object. - See also: [`lines`][griffe.Object.lines], - [`lines_collection`][griffe.Object.lines_collection]. + See also: [`lines`][griffelib.Object.lines], + [`lines_collection`][griffelib.Object.lines_collection]. """ return dedent("\n".join(self.lines)) @@ -1240,7 +1240,7 @@ def resolve(self, name: str) -> str: def as_dict(self, *, full: bool = False, **kwargs: Any) -> dict[str, Any]: """Return this object's data as a dictionary. - See also: [`as_json`][griffe.Object.as_json]. + See also: [`as_json`][griffelib.Object.as_json]. Parameters: full: Whether to return full info, or just base info. @@ -1336,7 +1336,7 @@ class Alias(ObjectAliasMixin): - the path is the alias path, not the canonical one - the name can be different from the target's - if the target can be resolved, the kind is the target's kind - - if the target cannot be resolved, the kind becomes [Kind.ALIAS][griffe.Kind] + - if the target cannot be resolved, the kind becomes [Kind.ALIAS][griffelib.Kind] """ is_alias: bool = True @@ -1344,7 +1344,7 @@ class Alias(ObjectAliasMixin): is_collection: bool = False """Always false for aliases. - See also: [`ModulesCollection`][griffe.ModulesCollection]. + See also: [`ModulesCollection`][griffelib.ModulesCollection]. """ def __init__( @@ -1439,7 +1439,7 @@ def __len__(self) -> int: def kind(self) -> Kind: """The target's kind, or `Kind.ALIAS` if the target cannot be resolved. - See also: [`is_kind`][griffe.Alias.is_kind]. + See also: [`is_kind`][griffelib.Alias.is_kind]. """ # custom behavior to avoid raising exceptions try: @@ -1451,8 +1451,8 @@ def kind(self) -> Kind: def has_docstring(self) -> bool: """Whether this alias' target has a non-empty docstring. - See also: [`has_docstrings`][griffe.Alias.has_docstrings], - [`docstring`][griffe.Alias.docstring]. + See also: [`has_docstrings`][griffelib.Alias.has_docstrings], + [`docstring`][griffelib.Alias.docstring]. """ try: return self.final_target.has_docstring @@ -1463,8 +1463,8 @@ def has_docstring(self) -> bool: def has_docstrings(self) -> bool: """Whether this alias' target or any of its members has a non-empty docstring. - See also: [`has_docstring`][griffe.Alias.has_docstring], - [`docstring`][griffe.Alias.docstring]. + See also: [`has_docstring`][griffelib.Alias.has_docstring], + [`docstring`][griffelib.Alias.docstring]. """ try: return self.final_target.has_docstrings @@ -1485,7 +1485,7 @@ def parent(self, value: Module | Class | Alias) -> None: def path(self) -> str: """The dotted path / import path of this object. - See also: [`canonical_path`][griffe.Alias.canonical_path]. + See also: [`canonical_path`][griffelib.Alias.canonical_path]. """ return f"{self.parent.path}.{self.name}" # type: ignore[union-attr] @@ -1499,10 +1499,10 @@ def modules_collection(self) -> ModulesCollection: def members(self) -> dict[str, Object | Alias]: """The target's members (modules, classes, functions, attributes, type aliases). - See also: [`inherited_members`][griffe.Alias.inherited_members], - [`get_member`][griffe.Alias.get_member], - [`set_member`][griffe.Alias.set_member], - [`filter_members`][griffe.Alias.filter_members]. + See also: [`inherited_members`][griffelib.Alias.inherited_members], + [`get_member`][griffelib.Alias.get_member], + [`set_member`][griffelib.Alias.set_member], + [`filter_members`][griffelib.Alias.filter_members]. """ final_target = self.final_target @@ -1525,7 +1525,7 @@ def inherited_members(self) -> dict[str, Alias]: This method is part of the consumer API: do not use when producing Griffe trees! - See also: [`members`][griffe.Alias.members]. + See also: [`members`][griffelib.Alias.members]. """ final_target = self.final_target @@ -1541,7 +1541,7 @@ def inherited_members(self) -> dict[str, Alias]: def as_json(self, *, full: bool = False, **kwargs: Any) -> str: """Return this target's data as a JSON string. - See also: [`as_dict`][griffe.Alias.as_dict]. + See also: [`as_dict`][griffelib.Alias.as_dict]. Parameters: full: Whether to return full info, or just base info. @@ -1589,7 +1589,7 @@ def extra(self) -> dict: def lineno(self) -> int | None: """The starting line number of the target object. - See also: [`endlineno`][griffe.Alias.endlineno]. + See also: [`endlineno`][griffelib.Alias.endlineno]. """ return self.final_target.lineno @@ -1601,7 +1601,7 @@ def lineno(self, lineno: int | None) -> None: def endlineno(self) -> int | None: """The ending line number of the target object. - See also: [`lineno`][griffe.Alias.lineno]. + See also: [`lineno`][griffelib.Alias.lineno]. """ return self.final_target.endlineno @@ -1613,8 +1613,8 @@ def endlineno(self, endlineno: int | None) -> None: def docstring(self) -> Docstring | None: """The target docstring. - See also: [`has_docstring`][griffe.Alias.has_docstring], - [`has_docstrings`][griffe.Alias.has_docstrings]. + See also: [`has_docstring`][griffelib.Alias.has_docstring], + [`has_docstrings`][griffelib.Alias.has_docstrings]. """ return self.final_target.docstring @@ -1631,7 +1631,7 @@ def type_parameters(self) -> TypeParameters: def labels(self) -> set[str]: """The target labels (`property`, `dataclass`, etc.). - See also: [`has_labels`][griffe.Alias.has_labels]. + See also: [`has_labels`][griffelib.Alias.has_labels]. """ return self.final_target.labels @@ -1642,7 +1642,7 @@ def imports(self) -> dict[str, str]: Keys are the names within the object (`from ... import ... as AS_NAME`), while the values are the actual names of the objects (`from ... import REAL_NAME as ...`). - See also: [`is_imported`][griffe.Alias.is_imported]. + See also: [`is_imported`][griffelib.Alias.is_imported]. """ return self.final_target.imports @@ -1661,7 +1661,7 @@ def exports(self) -> list[str | ExprName] | None: Exports get expanded by the loader before it expands wildcards and resolves aliases. - See also: [`GriffeLoader.expand_exports`][griffe.GriffeLoader.expand_exports]. + See also: [`GriffeLoader.expand_exports`][griffelib.GriffeLoader.expand_exports]. """ return self.final_target.exports @@ -1673,12 +1673,12 @@ def aliases(self) -> dict[str, Alias]: def is_kind(self, kind: str | Kind | set[str | Kind]) -> bool: """Tell if this object is of the given kind. - See also: [`is_module`][griffe.Alias.is_module], - [`is_class`][griffe.Alias.is_class], - [`is_function`][griffe.Alias.is_function], - [`is_attribute`][griffe.Alias.is_attribute], - [`is_type_alias`][griffe.Alias.is_type_alias], - [`is_alias`][griffe.Alias.is_alias]. + See also: [`is_module`][griffelib.Alias.is_module], + [`is_class`][griffelib.Alias.is_class], + [`is_function`][griffelib.Alias.is_function], + [`is_attribute`][griffelib.Alias.is_attribute], + [`is_type_alias`][griffelib.Alias.is_type_alias], + [`is_alias`][griffelib.Alias.is_alias]. Parameters: kind: An instance or set of kinds (strings or enumerations). @@ -1695,13 +1695,13 @@ def is_kind(self, kind: str | Kind | set[str | Kind]) -> bool: def is_module(self) -> bool: """Whether this object is a module. - See also: [`is_init_module`][griffe.Alias.is_init_module]. - [`is_class`][griffe.Alias.is_class], - [`is_function`][griffe.Alias.is_function], - [`is_attribute`][griffe.Alias.is_attribute], - [`is_type_alias`][griffe.Alias.is_type_alias], - [`is_alias`][griffe.Alias.is_alias], - [`is_kind`][griffe.Alias.is_kind]. + See also: [`is_init_module`][griffelib.Alias.is_init_module]. + [`is_class`][griffelib.Alias.is_class], + [`is_function`][griffelib.Alias.is_function], + [`is_attribute`][griffelib.Alias.is_attribute], + [`is_type_alias`][griffelib.Alias.is_type_alias], + [`is_alias`][griffelib.Alias.is_alias], + [`is_kind`][griffelib.Alias.is_kind]. """ return self.final_target.is_module @@ -1709,12 +1709,12 @@ def is_module(self) -> bool: def is_class(self) -> bool: """Whether this object is a class. - See also: [`is_module`][griffe.Alias.is_module], - [`is_function`][griffe.Alias.is_function], - [`is_attribute`][griffe.Alias.is_attribute], - [`is_type_alias`][griffe.Alias.is_type_alias], - [`is_alias`][griffe.Alias.is_alias], - [`is_kind`][griffe.Alias.is_kind]. + See also: [`is_module`][griffelib.Alias.is_module], + [`is_function`][griffelib.Alias.is_function], + [`is_attribute`][griffelib.Alias.is_attribute], + [`is_type_alias`][griffelib.Alias.is_type_alias], + [`is_alias`][griffelib.Alias.is_alias], + [`is_kind`][griffelib.Alias.is_kind]. """ return self.final_target.is_class @@ -1722,12 +1722,12 @@ def is_class(self) -> bool: def is_function(self) -> bool: """Whether this object is a function. - See also: [`is_module`][griffe.Alias.is_module], - [`is_class`][griffe.Alias.is_class], - [`is_attribute`][griffe.Alias.is_attribute], - [`is_type_alias`][griffe.Alias.is_type_alias], - [`is_alias`][griffe.Alias.is_alias], - [`is_kind`][griffe.Alias.is_kind]. + See also: [`is_module`][griffelib.Alias.is_module], + [`is_class`][griffelib.Alias.is_class], + [`is_attribute`][griffelib.Alias.is_attribute], + [`is_type_alias`][griffelib.Alias.is_type_alias], + [`is_alias`][griffelib.Alias.is_alias], + [`is_kind`][griffelib.Alias.is_kind]. """ return self.final_target.is_function @@ -1735,12 +1735,12 @@ def is_function(self) -> bool: def is_attribute(self) -> bool: """Whether this object is an attribute. - See also: [`is_module`][griffe.Alias.is_module], - [`is_class`][griffe.Alias.is_class], - [`is_function`][griffe.Alias.is_function], - [`is_type_alias`][griffe.Alias.is_type_alias], - [`is_alias`][griffe.Alias.is_alias], - [`is_kind`][griffe.Alias.is_kind]. + See also: [`is_module`][griffelib.Alias.is_module], + [`is_class`][griffelib.Alias.is_class], + [`is_function`][griffelib.Alias.is_function], + [`is_type_alias`][griffelib.Alias.is_type_alias], + [`is_alias`][griffelib.Alias.is_alias], + [`is_kind`][griffelib.Alias.is_kind]. """ return self.final_target.is_attribute @@ -1748,19 +1748,19 @@ def is_attribute(self) -> bool: def is_type_alias(self) -> bool: """Whether this object is a type alias. - See also: [`is_module`][griffe.Alias.is_module], - [`is_class`][griffe.Alias.is_class], - [`is_function`][griffe.Alias.is_function], - [`is_attribute`][griffe.Alias.is_attribute], - [`is_alias`][griffe.Alias.is_alias], - [`is_kind`][griffe.Alias.is_kind]. + See also: [`is_module`][griffelib.Alias.is_module], + [`is_class`][griffelib.Alias.is_class], + [`is_function`][griffelib.Alias.is_function], + [`is_attribute`][griffelib.Alias.is_attribute], + [`is_alias`][griffelib.Alias.is_alias], + [`is_kind`][griffelib.Alias.is_kind]. """ return self.final_target.is_type_alias def has_labels(self, *labels: str) -> bool: """Tell if this object has all the given labels. - See also: [`labels`][griffe.Alias.labels]. + See also: [`labels`][griffelib.Alias.labels]. Parameters: *labels: Labels that must be present. @@ -1773,9 +1773,9 @@ def has_labels(self, *labels: str) -> bool: def filter_members(self, *predicates: Callable[[Object | Alias], bool]) -> dict[str, Object | Alias]: """Filter and return members based on predicates. - See also: [`members`][griffe.Alias.members], - [`get_member`][griffe.Alias.get_member], - [`set_member`][griffe.Alias.set_member]. + See also: [`members`][griffelib.Alias.members], + [`get_member`][griffelib.Alias.get_member], + [`set_member`][griffelib.Alias.set_member]. Parameters: *predicates: A list of predicates, i.e. callables accepting a member as argument and returning a boolean. @@ -1789,7 +1789,7 @@ def filter_members(self, *predicates: Callable[[Object | Alias], bool]) -> dict[ def module(self) -> Module: """The parent module of this object. - See also: [`package`][griffe.Alias.package]. + See also: [`package`][griffelib.Alias.package]. Raises: ValueError: When the object is not a module and does not have a parent. @@ -1800,7 +1800,7 @@ def module(self) -> Module: def package(self) -> Module: """The absolute top module (the package) of this object. - See also: [`module`][griffe.Alias.module]. + See also: [`module`][griffelib.Alias.module]. """ return self.final_target.package @@ -1808,8 +1808,8 @@ def package(self) -> Module: def filepath(self) -> Path | list[Path]: """The file path (or directory list for namespace packages) where this object was defined. - See also: [`relative_filepath`][griffe.Alias.relative_filepath], - [`relative_package_filepath`][griffe.Alias.relative_package_filepath]. + See also: [`relative_filepath`][griffelib.Alias.relative_filepath], + [`relative_package_filepath`][griffelib.Alias.relative_package_filepath]. """ return self.final_target.filepath @@ -1819,8 +1819,8 @@ def relative_filepath(self) -> Path: If this object's file path is not relative to the current working directory, return its absolute path. - See also: [`filepath`][griffe.Alias.filepath], - [`relative_package_filepath`][griffe.Alias.relative_package_filepath]. + See also: [`filepath`][griffelib.Alias.filepath], + [`relative_package_filepath`][griffelib.Alias.relative_package_filepath]. Raises: ValueError: When the relative path could not be computed. @@ -1831,8 +1831,8 @@ def relative_filepath(self) -> Path: def relative_package_filepath(self) -> Path: """The file path where this object was defined, relative to the top module path. - See also: [`filepath`][griffe.Alias.filepath], - [`relative_filepath`][griffe.Alias.relative_filepath]. + See also: [`filepath`][griffelib.Alias.filepath], + [`relative_filepath`][griffelib.Alias.relative_filepath]. Raises: ValueError: When the relative path could not be computed. @@ -1845,7 +1845,7 @@ def canonical_path(self) -> str: The canonical path is the path where the object was defined (not imported). - See also: [`path`][griffe.Alias.path]. + See also: [`path`][griffelib.Alias.path]. """ return self.final_target.canonical_path @@ -1853,8 +1853,8 @@ def canonical_path(self) -> str: def lines_collection(self) -> LinesCollection: """The lines collection attached to this object or its parents. - See also: [`lines`][griffe.Alias.lines], - [`source`][griffe.Alias.source]. + See also: [`lines`][griffelib.Alias.lines], + [`source`][griffelib.Alias.source]. Raises: ValueError: When no modules collection can be found in the object or its parents. @@ -1865,8 +1865,8 @@ def lines_collection(self) -> LinesCollection: def lines(self) -> list[str]: """The lines containing the source of this object. - See also: [`source`][griffe.Alias.source], - [`lines_collection`][griffe.Alias.lines_collection]. + See also: [`source`][griffelib.Alias.source], + [`lines_collection`][griffelib.Alias.lines_collection]. """ return self.final_target.lines @@ -1874,8 +1874,8 @@ def lines(self) -> list[str]: def source(self) -> str: """The source code of this object. - See also: [`lines`][griffe.Alias.lines], - [`lines_collection`][griffe.Alias.lines_collection]. + See also: [`lines`][griffelib.Alias.lines], + [`lines_collection`][griffelib.Alias.lines_collection]. """ return self.final_target.source @@ -1906,9 +1906,9 @@ def _filepath(self) -> Path | list[Path] | None: def bases(self) -> list[Expr | str]: """The class bases. - See also: [`Class`][griffe.Class], - [`resolved_bases`][griffe.Alias.resolved_bases], - [`mro`][griffe.Alias.mro]. + See also: [`Class`][griffelib.Class], + [`resolved_bases`][griffelib.Alias.resolved_bases], + [`mro`][griffelib.Alias.mro]. """ return cast("Class", self.final_target).bases @@ -1921,8 +1921,8 @@ def keywords(self) -> dict[str, Expr | str]: def decorators(self) -> list[Decorator]: """The class/function decorators. - See also: [`Function`][griffe.Function], - [`Class`][griffe.Class]. + See also: [`Function`][griffelib.Function], + [`Class`][griffelib.Class]. """ return cast("Union[Class, Function]", self.target).decorators @@ -1940,7 +1940,7 @@ def is_init_method(self) -> bool: def is_init_module(self) -> bool: """Whether this module is an `__init__.py` module. - See also: [`is_module`][griffe.Alias.is_module]. + See also: [`is_module`][griffelib.Alias.is_module]. """ return cast("Module", self.final_target).is_init_module @@ -1948,7 +1948,7 @@ def is_init_module(self) -> bool: def is_package(self) -> bool: """Whether this module is a package (top module). - See also: [`is_subpackage`][griffe.Alias.is_subpackage]. + See also: [`is_subpackage`][griffelib.Alias.is_subpackage]. """ return cast("Module", self.final_target).is_package @@ -1956,7 +1956,7 @@ def is_package(self) -> bool: def is_subpackage(self) -> bool: """Whether this module is a subpackage. - See also: [`is_package`][griffe.Alias.is_package]. + See also: [`is_package`][griffelib.Alias.is_package]. """ return cast("Module", self.final_target).is_subpackage @@ -1964,7 +1964,7 @@ def is_subpackage(self) -> bool: def is_namespace_package(self) -> bool: """Whether this module is a namespace package (top folder, no `__init__.py`). - See also: [`is_namespace_subpackage`][griffe.Alias.is_namespace_subpackage]. + See also: [`is_namespace_subpackage`][griffelib.Alias.is_namespace_subpackage]. """ return cast("Module", self.final_target).is_namespace_package @@ -1972,7 +1972,7 @@ def is_namespace_package(self) -> bool: def is_namespace_subpackage(self) -> bool: """Whether this module is a namespace subpackage. - See also: [`is_namespace_package`][griffe.Alias.is_namespace_package]. + See also: [`is_namespace_package`][griffelib.Alias.is_namespace_package]. """ return cast("Module", self.final_target).is_namespace_subpackage @@ -2068,9 +2068,9 @@ def target(self) -> Object | Alias: Upon accessing this property, if the target is not already resolved, a lookup is done using the modules collection to find the target. - See also: [`final_target`][griffe.Alias.final_target], - [`resolve_target`][griffe.Alias.resolve_target], - [`resolved`][griffe.Alias.resolved]. + See also: [`final_target`][griffelib.Alias.final_target], + [`resolve_target`][griffelib.Alias.resolve_target], + [`resolved`][griffelib.Alias.resolved]. """ if not self.resolved: self.resolve_target() @@ -2091,9 +2091,9 @@ def final_target(self) -> Object: This will iterate through the targets until a non-alias object is found. - See also: [`target`][griffe.Alias.target], - [`resolve_target`][griffe.Alias.resolve_target], - [`resolved`][griffe.Alias.resolved]. + See also: [`target`][griffelib.Alias.target], + [`resolve_target`][griffelib.Alias.resolve_target], + [`resolved`][griffelib.Alias.resolved]. """ # Here we quickly iterate on the alias chain, # remembering which path we've seen already to detect cycles. @@ -2114,9 +2114,9 @@ def final_target(self) -> Object: def resolve_target(self) -> None: """Resolve the target. - See also: [`target`][griffe.Alias.target], - [`final_target`][griffe.Alias.final_target], - [`resolved`][griffe.Alias.resolved]. + See also: [`target`][griffelib.Alias.target], + [`final_target`][griffelib.Alias.final_target], + [`resolved`][griffelib.Alias.resolved]. Raises: AliasResolutionError: When the target cannot be resolved. @@ -2173,7 +2173,7 @@ def resolved(self) -> bool: def wildcard(self) -> str | None: """The module on which the wildcard import is performed (if any). - See also: [`GriffeLoader.expand_wildcards`][griffe.GriffeLoader.expand_wildcards]. + See also: [`GriffeLoader.expand_wildcards`][griffelib.GriffeLoader.expand_wildcards]. """ if self.name.endswith("/*"): return self.target_path @@ -2182,7 +2182,7 @@ def wildcard(self) -> str | None: def as_dict(self, *, full: bool = False, **kwargs: Any) -> dict[str, Any]: # noqa: ARG002 """Return this alias' data as a dictionary. - See also: [`as_json`][griffe.Alias.as_json]. + See also: [`as_json`][griffelib.Alias.as_json]. Parameters: full: Whether to return full info, or just base info. @@ -2237,9 +2237,9 @@ def __init__(self, *args: Any, filepath: Path | list[Path] | None = None, **kwar """Initialize the module. Parameters: - *args: See [`griffe.Object`][]. + *args: See [`griffelib.Object`][]. filepath: The module file path (directory for namespace [sub]packages, none for builtin modules). - **kwargs: See [`griffe.Object`][]. + **kwargs: See [`griffelib.Object`][]. """ super().__init__(*args, **kwargs) self._filepath: Path | list[Path] | None = filepath @@ -2276,7 +2276,7 @@ def imports_future_annotations(self) -> bool: def is_init_module(self) -> bool: """Whether this module is an `__init__.py` module. - See also: [`is_module`][griffe.Module.is_module]. + See also: [`is_module`][griffelib.Module.is_module]. """ if isinstance(self.filepath, list): return False @@ -2289,7 +2289,7 @@ def is_init_module(self) -> bool: def is_package(self) -> bool: """Whether this module is a package (top module). - See also: [`is_subpackage`][griffe.Module.is_subpackage]. + See also: [`is_subpackage`][griffelib.Module.is_subpackage]. """ return not bool(self.parent) and self.is_init_module @@ -2297,7 +2297,7 @@ def is_package(self) -> bool: def is_subpackage(self) -> bool: """Whether this module is a subpackage. - See also: [`is_package`][griffe.Module.is_package]. + See also: [`is_package`][griffelib.Module.is_package]. """ return bool(self.parent) and self.is_init_module @@ -2305,7 +2305,7 @@ def is_subpackage(self) -> bool: def is_namespace_package(self) -> bool: """Whether this module is a namespace package (top folder, no `__init__.py`). - See also: [`is_namespace_subpackage`][griffe.Module.is_namespace_subpackage]. + See also: [`is_namespace_subpackage`][griffelib.Module.is_namespace_subpackage]. """ try: return self.parent is None and isinstance(self.filepath, list) @@ -2316,7 +2316,7 @@ def is_namespace_package(self) -> bool: def is_namespace_subpackage(self) -> bool: """Whether this module is a namespace subpackage. - See also: [`is_namespace_package`][griffe.Module.is_namespace_package]. + See also: [`is_namespace_package`][griffelib.Module.is_namespace_package]. """ try: return ( @@ -2333,7 +2333,7 @@ def is_namespace_subpackage(self) -> bool: def as_dict(self, **kwargs: Any) -> dict[str, Any]: """Return this module's data as a dictionary. - See also: [`as_json`][griffe.Module.as_json]. + See also: [`as_json`][griffelib.Module.as_json]. Parameters: **kwargs: Additional serialization options. @@ -2367,19 +2367,19 @@ def __init__( """Initialize the class. Parameters: - *args: See [`griffe.Object`][]. + *args: See [`griffelib.Object`][]. bases: The list of base classes, if any. decorators: The class decorators, if any. keywords: The class keywords arguments, if any. - **kwargs: See [`griffe.Object`][]. + **kwargs: See [`griffelib.Object`][]. """ super().__init__(*args, **kwargs) self.bases: list[Expr | str] = list(bases) if bases else [] """The class bases. - See also: [`resolved_bases`][griffe.Class.resolved_bases], - [`mro`][griffe.Class.mro]. + See also: [`resolved_bases`][griffelib.Class.resolved_bases], + [`mro`][griffelib.Class.mro]. """ self.decorators: list[Decorator] = decorators or [] @@ -2428,8 +2428,8 @@ def resolved_bases(self) -> list[Object]: This method is part of the consumer API: do not use when producing Griffe trees! - See also: [`bases`][griffe.Class.bases], - [`mro`][griffe.Class.mro]. + See also: [`bases`][griffelib.Class.bases], + [`mro`][griffelib.Class.mro]. """ resolved_bases = [] for base in self.bases: @@ -2458,15 +2458,15 @@ def _mro(self, seen: tuple[str, ...] = ()) -> list[Class]: def mro(self) -> list[Class]: """Return a list of classes in order corresponding to Python's MRO. - See also: [`bases`][griffe.Class.bases], - [`resolved_bases`][griffe.Class.resolved_bases]. + See also: [`bases`][griffelib.Class.bases], + [`resolved_bases`][griffelib.Class.resolved_bases]. """ return self._mro()[1:] # Remove self. def as_dict(self, **kwargs: Any) -> dict[str, Any]: """Return this class' data as a dictionary. - See also: [`as_json`][griffe.Class.as_json]. + See also: [`as_json`][griffelib.Class.as_json]. Parameters: **kwargs: Additional serialization options. @@ -2496,11 +2496,11 @@ def __init__( """Initialize the function. Parameters: - *args: See [`griffe.Object`][]. + *args: See [`griffelib.Object`][]. parameters: The function parameters. returns: The function return annotation. decorators: The function decorators, if any. - **kwargs: See [`griffe.Object`][]. + **kwargs: See [`griffelib.Object`][]. """ super().__init__(*args, **kwargs) self.parameters: Parameters = parameters or Parameters() @@ -2561,7 +2561,7 @@ def is_init_method(self) -> bool: def as_dict(self, **kwargs: Any) -> dict[str, Any]: """Return this function's data as a dictionary. - See also: [`as_json`][griffe.Function.as_json]. + See also: [`as_json`][griffelib.Function.as_json]. Parameters: **kwargs: Additional serialization options. @@ -2665,10 +2665,10 @@ def __init__( """Initialize the function. Parameters: - *args: See [`griffe.Object`][]. + *args: See [`griffelib.Object`][]. value: The attribute value, if any. annotation: The attribute annotation, if any. - **kwargs: See [`griffe.Object`][]. + **kwargs: See [`griffelib.Object`][]. """ super().__init__(*args, **kwargs) self.value: str | Expr | None = value @@ -2683,7 +2683,7 @@ def __init__( def as_dict(self, **kwargs: Any) -> dict[str, Any]: """Return this attribute's data as a dictionary. - See also: [`as_json`][griffe.Attribute.as_json]. + See also: [`as_json`][griffelib.Attribute.as_json]. Parameters: **kwargs: Additional serialization options. @@ -2713,9 +2713,9 @@ def __init__( """Initialize the function. Parameters: - *args: See [`griffe.Object`][]. + *args: See [`griffelib.Object`][]. value: The type alias value. - **kwargs: See [`griffe.Object`][]. + **kwargs: See [`griffelib.Object`][]. """ super().__init__(*args, **kwargs) self.value: str | Expr | None = value diff --git a/src/griffe/_internal/py.typed b/packages/griffelib/src/griffelib/_internal/py.typed similarity index 100% rename from src/griffe/_internal/py.typed rename to packages/griffelib/src/griffelib/_internal/py.typed diff --git a/src/griffe/_internal/stats.py b/packages/griffelib/src/griffelib/_internal/stats.py similarity index 97% rename from src/griffe/_internal/stats.py rename to packages/griffelib/src/griffelib/_internal/stats.py index 957cc5c89..59400a510 100644 --- a/src/griffe/_internal/stats.py +++ b/packages/griffelib/src/griffelib/_internal/stats.py @@ -7,11 +7,11 @@ from pathlib import Path from typing import TYPE_CHECKING -from griffe._internal.enumerations import Kind +from griffelib._internal.enumerations import Kind if TYPE_CHECKING: - from griffe._internal.loader import GriffeLoader - from griffe._internal.models import Alias, Object + from griffelib._internal.loader import GriffeLoader + from griffelib._internal.models import Alias, Object class Stats: diff --git a/src/griffe/_internal/tests.py b/packages/griffelib/src/griffelib/_internal/tests.py similarity index 96% rename from src/griffe/_internal/tests.py rename to packages/griffelib/src/griffelib/_internal/tests.py index 912447056..1383bc7aa 100644 --- a/src/griffe/_internal/tests.py +++ b/packages/griffelib/src/griffelib/_internal/tests.py @@ -13,19 +13,19 @@ from textwrap import dedent from typing import TYPE_CHECKING -from griffe._internal.agents.inspector import inspect -from griffe._internal.agents.visitor import visit -from griffe._internal.collections import LinesCollection -from griffe._internal.loader import load -from griffe._internal.models import Module, Object +from griffelib._internal.agents.inspector import inspect +from griffelib._internal.agents.visitor import visit +from griffelib._internal.collections import LinesCollection +from griffelib._internal.loader import load +from griffelib._internal.models import Module, Object if TYPE_CHECKING: from collections.abc import Iterator, Mapping, Sequence - from griffe._internal.collections import ModulesCollection - from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffe._internal.enumerations import Parser - from griffe._internal.extensions.base import Extensions + from griffelib._internal.collections import ModulesCollection + from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffelib._internal.enumerations import Parser + from griffelib._internal.extensions.base import Extensions _TMPDIR_PREFIX = "griffe_" diff --git a/pyproject.toml b/pyproject.toml index f33dc1fc7..3a2fff8cc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,7 @@ Gitter = "https://gitter.im/mkdocstrings/griffe" Funding = "https://github.com/sponsors/pawamoy" [project.scripts] -griffe = "griffe:main" +griffe = "griffecli:main" [tool.hatch.version] source = "code" diff --git a/scripts/gen_griffe_json.py b/scripts/gen_griffe_json.py index 150eba043..a1fb98dca 100644 --- a/scripts/gen_griffe_json.py +++ b/scripts/gen_griffe_json.py @@ -5,5 +5,5 @@ python_handler = mkdocs_gen_files.config.plugins["mkdocstrings"].get_handler("python") data = python_handler.collect("griffe", options=python_handler.get_options({})) -with mkdocs_gen_files.open("griffe.json", "w") as fd: +with mkdocs_gen_files.open("griffelib.json", "w") as fd: print(data.as_json(full=True), file=fd) diff --git a/scripts/gen_structure_docs.py b/scripts/gen_structure_docs.py index a33860efe..7f84671ae 100644 --- a/scripts/gen_structure_docs.py +++ b/scripts/gen_structure_docs.py @@ -96,5 +96,5 @@ def render_entrypoint(heading_level: int = 4) -> None: root = Path(os.environ["MKDOCS_CONFIG_DIR"]) src = root / "src" public_api = src / "griffe" - print(f"{'#' * heading_level} `griffe.__main__`\n") + print(f"{'#' * heading_level} `griffelib.__main__`\n") print(_comment_block(public_api / "__main__.py")) diff --git a/src/griffe/__init__.py b/src/griffe/__init__.py index c06aad3a3..a48bb5aa2 100644 --- a/src/griffe/__init__.py +++ b/src/griffe/__init__.py @@ -1,607 +1,8 @@ -# This top-level module imports all public names from the package, -# and exposes them as public objects. We have tests to make sure -# no object is forgotten in this list. +"""Griffe CLI package. Re-exports griffelib and griffecli.""" -"""Griffe package. +from griffecli import * +from griffecli import __all__ as __cli_all__ +from griffelib import * +from griffelib import __all__ as __lib_all__ -Signatures for entire Python programs. -Extract the structure, the frame, the skeleton of your project, -to generate API documentation or find breaking changes in your API. - -The entirety of the public API is exposed here, in the top-level `griffe` module. - -All messages written to standard output or error are logged using the `logging` module. -Our logger's name is set to `"griffe"` and is public (you can rely on it). -You can obtain the logger from the standard `logging` module: `logging.getLogger("griffe")`. -Actual logging messages are not part of the public API (they might change without notice). - -Raised exceptions throughout the package are part of the public API (you can rely on them). -Their actual messages are not part of the public API (they might change without notice). - -The following paragraphs will help you discover the package's content. - -## CLI entrypoints - -Griffe provides a command-line interface (CLI) to interact with the package. The CLI entrypoints can be called from Python code. - -- [`griffe.main`][]: Run the main program. -- [`griffe.check`][]: Check for API breaking changes in two versions of the same package. -- [`griffe.dump`][]: Load packages data and dump it as JSON. - -## Loaders - -To load API data, Griffe provides several high-level functions. - -- [`griffe.load`][]: Load and return a Griffe object. -- [`griffe.load_git`][]: Load and return a module from a specific Git reference. -- [`griffe.load_pypi`][]: Load and return a module from a specific package version downloaded using pip. - -## Models - -The data loaded by Griffe is represented by several classes. - -- [`griffe.Module`][]: The class representing a Python module. -- [`griffe.Class`][]: The class representing a Python class. -- [`griffe.Function`][]: The class representing a Python function or method. -- [`griffe.Attribute`][]: The class representing a Python attribute. -- [`griffe.Alias`][]: This class represents an alias, or indirection, to an object declared in another module. - -Additional classes are available to represent other concepts. - -- [`griffe.Decorator`][]: This class represents a decorator. -- [`griffe.Parameters`][]: This class is a container for parameters. -- [`griffe.Parameter`][]: This class represent a function parameter. - -## Agents - -Griffe is able to analyze code both statically and dynamically, using the following "agents". -However most of the time you will only need to use the loaders above. - -- [`griffe.visit`][]: Parse and visit a module file. -- [`griffe.inspect`][]: Inspect a module. - -## Serializers - -Griffe can serizalize data to dictionary and JSON. - -- [`griffe.Object.as_json`][griffe.Object.as_json] -- [`griffe.Object.from_json`][griffe.Object.from_json] -- [`griffe.JSONEncoder`][]: JSON encoder for Griffe objects. -- [`griffe.json_decoder`][]: JSON decoder for Griffe objects. - -## API checks - -Griffe can compare two versions of the same package to find breaking changes. - -- [`griffe.find_breaking_changes`][]: Find breaking changes between two versions of the same API. -- [`griffe.Breakage`][]: Breakage classes can explain what broke from a version to another. - -## Extensions - -Griffe supports extensions. You can create your own extension by subclassing the `griffe.Extension` class. - -- [`griffe.load_extensions`][]: Load configured extensions. -- [`griffe.Extension`][]: Base class for Griffe extensions. - -## Docstrings - -Griffe can parse docstrings into structured data. - -Main class: - -- [`griffe.Docstring`][]: This class represents docstrings. - -Docstring section and element classes all start with `Docstring`. - -Docstring parsers: - -- [`griffe.parse`][]: Parse the docstring. -- [`griffe.parse_auto`][]: Parse a docstring by automatically detecting the style it uses. -- [`griffe.parse_google`][]: Parse a Google-style docstring. -- [`griffe.parse_numpy`][]: Parse a Numpydoc-style docstring. -- [`griffe.parse_sphinx`][]: Parse a Sphinx-style docstring. - -## Exceptions - -Griffe uses several exceptions to signal errors. - -- [`griffe.GriffeError`][]: The base exception for all Griffe errors. -- [`griffe.LoadingError`][]: Exception for loading errors. -- [`griffe.NameResolutionError`][]: Exception for names that cannot be resolved in a object scope. -- [`griffe.UnhandledEditableModuleError`][]: Exception for unhandled editables modules, when searching modules. -- [`griffe.UnimportableModuleError`][]: Exception for modules that cannot be imported. -- [`griffe.AliasResolutionError`][]: Exception for aliases that cannot be resolved. -- [`griffe.CyclicAliasError`][]: Exception raised when a cycle is detected in aliases. -- [`griffe.LastNodeError`][]: Exception raised when trying to access a next or previous node. -- [`griffe.RootNodeError`][]: Exception raised when trying to use siblings properties on a root node. -- [`griffe.BuiltinModuleError`][]: Exception raised when trying to access the filepath of a builtin module. -- [`griffe.ExtensionError`][]: Base class for errors raised by extensions. -- [`griffe.ExtensionNotLoadedError`][]: Exception raised when an extension could not be loaded. -- [`griffe.GitError`][]: Exception raised for errors related to Git. - -# Expressions - -Griffe stores snippets of code (attribute values, decorators, base class, type annotations) as expressions. -Expressions are basically abstract syntax trees (AST) with a few differences compared to the nodes returned by [`ast`][]. -Griffe provides a few helpers to extract expressions from regular AST nodes. - -- [`griffe.get_annotation`][]: Get a type annotation as expression. -- [`griffe.get_base_class`][]: Get a base class as expression. -- [`griffe.get_class_keyword`][]: Get a class keyword as expression. -- [`griffe.get_condition`][]: Get a condition as expression. -- [`griffe.get_expression`][]: Get an expression from an AST node. -- [`griffe.safe_get_annotation`][]: Get a type annotation as expression, safely (returns `None` on error). -- [`griffe.safe_get_base_class`][]: Get a base class as expression, safely (returns `None` on error). -- [`griffe.safe_get_class_keyword`][]: Get a class keyword as expression, safely (returns `None` on error). -- [`griffe.safe_get_condition`][]: Get a condition as expression, safely (returns `None` on error). -- [`griffe.safe_get_expression`][]: Get an expression from an AST node, safely (returns `None` on error). - -The base class for expressions. - -- [`griffe.Expr`][] - -Expression classes all start with `Expr`. - -# Loggers - -If you want to log messages from extensions, get a logger with `get_logger`. -The `logger` attribute is used by Griffe itself. You can use it to temporarily disable Griffe logging. - -- [`griffe.logger`][]: Our global logger, used throughout the library. -- [`griffe.get_logger`][]: Create and return a new logger instance. - -# Helpers - -To test your Griffe extensions, or to load API data from code in memory, Griffe provides the following helpers. - -- [`griffe.temporary_pyfile`][]: Create a Python file containing the given code in a temporary directory. -- [`griffe.temporary_pypackage`][]: Create a package containing the given modules in a temporary directory. -- [`griffe.temporary_visited_module`][]: Create and visit a temporary module with the given code. -- [`griffe.temporary_visited_package`][]: Create and visit a temporary package. -- [`griffe.temporary_inspected_module`][]: Create and inspect a temporary module with the given code. -- [`griffe.temporary_inspected_package`][]: Create and inspect a temporary package. -""" - -from __future__ import annotations - -from griffe._internal.agents.inspector import Inspector, inspect -from griffe._internal.agents.nodes.assignments import get_instance_names, get_name, get_names -from griffe._internal.agents.nodes.ast import ( - ast_children, - ast_first_child, - ast_kind, - ast_last_child, - ast_next, - ast_next_siblings, - ast_previous, - ast_previous_siblings, - ast_siblings, -) -from griffe._internal.agents.nodes.docstrings import get_docstring -from griffe._internal.agents.nodes.exports import get__all__, safe_get__all__ -from griffe._internal.agents.nodes.imports import relative_to_absolute -from griffe._internal.agents.nodes.parameters import ParametersType, get_parameters -from griffe._internal.agents.nodes.runtime import ObjectNode -from griffe._internal.agents.nodes.values import get_value, safe_get_value -from griffe._internal.agents.visitor import Visitor, builtin_decorators, stdlib_decorators, typing_overload, visit -from griffe._internal.c3linear import c3linear_merge -from griffe._internal.cli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main -from griffe._internal.collections import LinesCollection, ModulesCollection -from griffe._internal.diff import ( - AttributeChangedTypeBreakage, - AttributeChangedValueBreakage, - Breakage, - ClassRemovedBaseBreakage, - ObjectChangedKindBreakage, - ObjectRemovedBreakage, - ParameterAddedRequiredBreakage, - ParameterChangedDefaultBreakage, - ParameterChangedKindBreakage, - ParameterChangedRequiredBreakage, - ParameterMovedBreakage, - ParameterRemovedBreakage, - ReturnChangedTypeBreakage, - find_breaking_changes, -) -from griffe._internal.docstrings.auto import ( - AutoOptions, - DocstringDetectionMethod, - PerStyleOptions, - infer_docstring_style, - parse_auto, -) -from griffe._internal.docstrings.google import GoogleOptions, parse_google -from griffe._internal.docstrings.models import ( - DocstringAdmonition, - DocstringAttribute, - DocstringClass, - DocstringDeprecated, - DocstringElement, - DocstringFunction, - DocstringModule, - DocstringNamedElement, - DocstringParameter, - DocstringRaise, - DocstringReceive, - DocstringReturn, - DocstringSection, - DocstringSectionAdmonition, - DocstringSectionAttributes, - DocstringSectionClasses, - DocstringSectionDeprecated, - DocstringSectionExamples, - DocstringSectionFunctions, - DocstringSectionModules, - DocstringSectionOtherParameters, - DocstringSectionParameters, - DocstringSectionRaises, - DocstringSectionReceives, - DocstringSectionReturns, - DocstringSectionText, - DocstringSectionTypeAliases, - DocstringSectionTypeParameters, - DocstringSectionWarns, - DocstringSectionYields, - DocstringTypeAlias, - DocstringTypeParameter, - DocstringWarn, - DocstringYield, -) -from griffe._internal.docstrings.numpy import NumpyOptions, parse_numpy -from griffe._internal.docstrings.parsers import ( - DocstringOptions, - DocstringStyle, - parse, - parsers, -) -from griffe._internal.docstrings.sphinx import SphinxOptions, parse_sphinx -from griffe._internal.docstrings.utils import docstring_warning, parse_docstring_annotation -from griffe._internal.encoders import JSONEncoder, json_decoder -from griffe._internal.enumerations import ( - BreakageKind, - DocstringSectionKind, - ExplanationStyle, - Kind, - LogLevel, - ObjectKind, - ParameterKind, - Parser, - TypeParameterKind, -) -from griffe._internal.exceptions import ( - AliasResolutionError, - BuiltinModuleError, - CyclicAliasError, - ExtensionError, - ExtensionNotLoadedError, - GitError, - GriffeError, - LastNodeError, - LoadingError, - NameResolutionError, - RootNodeError, - UnhandledEditableModuleError, - UnimportableModuleError, -) -from griffe._internal.expressions import ( - Expr, - ExprAttribute, - ExprBinOp, - ExprBoolOp, - ExprCall, - ExprCompare, - ExprComprehension, - ExprConstant, - ExprDict, - ExprDictComp, - ExprExtSlice, - ExprFormatted, - ExprGeneratorExp, - ExprIfExp, - ExprJoinedStr, - ExprKeyword, - ExprLambda, - ExprList, - ExprListComp, - ExprName, - ExprNamedExpr, - ExprParameter, - ExprSet, - ExprSetComp, - ExprSlice, - ExprSubscript, - ExprTuple, - ExprUnaryOp, - ExprVarKeyword, - ExprVarPositional, - ExprYield, - ExprYieldFrom, - get_annotation, - get_base_class, - get_class_keyword, - get_condition, - get_expression, - safe_get_annotation, - safe_get_base_class, - safe_get_class_keyword, - safe_get_condition, - safe_get_expression, -) -from griffe._internal.extensions.base import ( - Extension, - Extensions, - LoadableExtensionType, - builtin_extensions, - load_extensions, -) -from griffe._internal.extensions.dataclasses import DataclassesExtension -from griffe._internal.extensions.unpack_typeddict import UnpackTypedDictExtension -from griffe._internal.finder import ModuleFinder, NamePartsAndPathType, NamePartsType, NamespacePackage, Package -from griffe._internal.git import GitInfo, KnownGitService -from griffe._internal.importer import dynamic_import, sys_path -from griffe._internal.loader import GriffeLoader, load, load_git, load_pypi -from griffe._internal.logger import Logger, get_logger, logger, patch_loggers -from griffe._internal.merger import merge_stubs -from griffe._internal.mixins import ( - DelMembersMixin, - GetMembersMixin, - ObjectAliasMixin, - SerializationMixin, - SetMembersMixin, -) -from griffe._internal.models import ( - Alias, - Attribute, - Class, - Decorator, - Docstring, - Function, - Module, - Object, - Parameter, - Parameters, - TypeAlias, - TypeParameter, - TypeParameters, -) -from griffe._internal.stats import Stats -from griffe._internal.tests import ( - TmpPackage, - htree, - module_vtree, - temporary_inspected_module, - temporary_inspected_package, - temporary_pyfile, - temporary_pypackage, - temporary_visited_module, - temporary_visited_package, - vtree, -) - -# Regenerate this list with the following Python snippet: -# import griffe -# names = sorted(n for n in dir(griffe) if not n.startswith("_") and n not in ("annotations",)) -# print('__all__ = [\n "' + '",\n "'.join(names) + '",\n]') -__all__ = [ - "DEFAULT_LOG_LEVEL", - "Alias", - "AliasResolutionError", - "Attribute", - "AttributeChangedTypeBreakage", - "AttributeChangedValueBreakage", - "AutoOptions", - "Breakage", - "BreakageKind", - "BuiltinModuleError", - "Class", - "ClassRemovedBaseBreakage", - "CyclicAliasError", - "DataclassesExtension", - "Decorator", - "DelMembersMixin", - "Docstring", - "DocstringAdmonition", - "DocstringAttribute", - "DocstringClass", - "DocstringDeprecated", - "DocstringDetectionMethod", - "DocstringElement", - "DocstringFunction", - "DocstringModule", - "DocstringNamedElement", - "DocstringOptions", - "DocstringParameter", - "DocstringRaise", - "DocstringReceive", - "DocstringReturn", - "DocstringSection", - "DocstringSectionAdmonition", - "DocstringSectionAttributes", - "DocstringSectionClasses", - "DocstringSectionDeprecated", - "DocstringSectionExamples", - "DocstringSectionFunctions", - "DocstringSectionKind", - "DocstringSectionModules", - "DocstringSectionOtherParameters", - "DocstringSectionParameters", - "DocstringSectionRaises", - "DocstringSectionReceives", - "DocstringSectionReturns", - "DocstringSectionText", - "DocstringSectionTypeAliases", - "DocstringSectionTypeParameters", - "DocstringSectionWarns", - "DocstringSectionYields", - "DocstringStyle", - "DocstringTypeAlias", - "DocstringTypeParameter", - "DocstringWarn", - "DocstringYield", - "ExplanationStyle", - "Expr", - "ExprAttribute", - "ExprBinOp", - "ExprBoolOp", - "ExprCall", - "ExprCompare", - "ExprComprehension", - "ExprConstant", - "ExprDict", - "ExprDictComp", - "ExprExtSlice", - "ExprFormatted", - "ExprGeneratorExp", - "ExprIfExp", - "ExprJoinedStr", - "ExprKeyword", - "ExprLambda", - "ExprList", - "ExprListComp", - "ExprName", - "ExprNamedExpr", - "ExprParameter", - "ExprSet", - "ExprSetComp", - "ExprSlice", - "ExprSubscript", - "ExprTuple", - "ExprUnaryOp", - "ExprVarKeyword", - "ExprVarPositional", - "ExprYield", - "ExprYieldFrom", - "Extension", - "ExtensionError", - "ExtensionNotLoadedError", - "Extensions", - "Function", - "GetMembersMixin", - "GitError", - "GitInfo", - "GoogleOptions", - "GriffeError", - "GriffeLoader", - "Inspector", - "JSONEncoder", - "Kind", - "KnownGitService", - "LastNodeError", - "LinesCollection", - "LoadableExtensionType", - "LoadingError", - "LogLevel", - "Logger", - "Module", - "ModuleFinder", - "ModulesCollection", - "NamePartsAndPathType", - "NamePartsType", - "NameResolutionError", - "NamespacePackage", - "NumpyOptions", - "Object", - "ObjectAliasMixin", - "ObjectChangedKindBreakage", - "ObjectKind", - "ObjectNode", - "ObjectRemovedBreakage", - "Package", - "Parameter", - "ParameterAddedRequiredBreakage", - "ParameterChangedDefaultBreakage", - "ParameterChangedKindBreakage", - "ParameterChangedRequiredBreakage", - "ParameterKind", - "ParameterMovedBreakage", - "ParameterRemovedBreakage", - "Parameters", - "ParametersType", - "Parser", - "PerStyleOptions", - "ReturnChangedTypeBreakage", - "RootNodeError", - "SerializationMixin", - "SetMembersMixin", - "SphinxOptions", - "Stats", - "TmpPackage", - "TypeAlias", - "TypeParameter", - "TypeParameterKind", - "TypeParameters", - "UnhandledEditableModuleError", - "UnimportableModuleError", - "UnpackTypedDictExtension", - "Visitor", - "ast_children", - "ast_first_child", - "ast_kind", - "ast_last_child", - "ast_next", - "ast_next_siblings", - "ast_previous", - "ast_previous_siblings", - "ast_siblings", - "builtin_decorators", - "builtin_extensions", - "c3linear_merge", - "check", - "docstring_warning", - "dump", - "dynamic_import", - "find_breaking_changes", - "get__all__", - "get_annotation", - "get_base_class", - "get_class_keyword", - "get_condition", - "get_docstring", - "get_expression", - "get_instance_names", - "get_logger", - "get_name", - "get_names", - "get_parameters", - "get_parser", - "get_value", - "htree", - "infer_docstring_style", - "inspect", - "json_decoder", - "load", - "load_extensions", - "load_git", - "load_pypi", - "logger", - "main", - "merge_stubs", - "module_vtree", - "parse", - "parse_auto", - "parse_docstring_annotation", - "parse_google", - "parse_numpy", - "parse_sphinx", - "parsers", - "patch_loggers", - "relative_to_absolute", - "safe_get__all__", - "safe_get_annotation", - "safe_get_base_class", - "safe_get_class_keyword", - "safe_get_condition", - "safe_get_expression", - "safe_get_value", - "stdlib_decorators", - "sys_path", - "temporary_inspected_module", - "temporary_inspected_package", - "temporary_pyfile", - "temporary_pypackage", - "temporary_visited_module", - "temporary_visited_package", - "typing_overload", - "visit", - "vtree", -] +__all__ = [*__lib_all__, *__cli_all__] diff --git a/src/griffe/__main__.py b/src/griffe/__main__.py index a9047c9b9..3b5ca458b 100644 --- a/src/griffe/__main__.py +++ b/src/griffe/__main__.py @@ -1,13 +1,6 @@ -# Entry-point module, in case you use `python -m griffe`. -# -# Why does this file exist, and why `__main__`? For more info, read: -# -# - https://www.python.org/dev/peps/pep-0338/ -# - https://docs.python.org/3/using/cmdline.html#cmdoption-m - import sys -from griffe._internal.cli import main +from griffecli import main if __name__ == "__main__": sys.exit(main(sys.argv[1:])) diff --git a/tests/helpers.py b/tests/helpers.py index 47613ddd0..1ca06eaef 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -6,7 +6,7 @@ import sys from tempfile import gettempdir -from griffe._internal.tests import _TMPDIR_PREFIX +from griffelib._internal.tests import _TMPDIR_PREFIX def clear_sys_modules(name: str | None = None) -> None: diff --git a/tests/test_api.py b/tests/test_api.py index 0cd72b0a5..cc6c0ad34 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -17,9 +17,9 @@ @pytest.fixture(name="loader", scope="module") -def _fixture_loader() -> griffe.GriffeLoader: - loader = griffe.GriffeLoader( - extensions=griffe.load_extensions( +def _fixture_loader() -> griffelib.GriffeLoader: + loader = griffelib.GriffeLoader( + extensions=griffelib.load_extensions( "griffe_inherited_docstrings", "unpack_typeddict", ), @@ -30,23 +30,23 @@ def _fixture_loader() -> griffe.GriffeLoader: @pytest.fixture(name="internal_api", scope="module") -def _fixture_internal_api(loader: griffe.GriffeLoader) -> griffe.Module: - return loader.modules_collection["griffe._internal"] +def _fixture_internal_api(loader: griffelib.GriffeLoader) -> griffelib.Module: + return loader.modules_collection["griffelib._internal"] @pytest.fixture(name="public_api", scope="module") -def _fixture_public_api(loader: griffe.GriffeLoader) -> griffe.Module: +def _fixture_public_api(loader: griffelib.GriffeLoader) -> griffelib.Module: return loader.modules_collection["griffe"] def _yield_public_objects( - obj: griffe.Module | griffe.Class, + obj: griffelib.Module | griffelib.Class, *, modules: bool = False, modulelevel: bool = True, inherited: bool = False, special: bool = False, -) -> Iterator[griffe.Object | griffe.Alias]: +) -> Iterator[griffelib.Object | griffelib.Alias]: for member in obj.all_members.values() if inherited else obj.members.values(): try: if member.is_module: @@ -72,22 +72,22 @@ def _yield_public_objects( inherited=inherited, special=special, ) - except (griffe.AliasResolutionError, griffe.CyclicAliasError): + except (griffelib.AliasResolutionError, griffelib.CyclicAliasError): continue @pytest.fixture(name="modulelevel_internal_objects", scope="module") -def _fixture_modulelevel_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: +def _fixture_modulelevel_internal_objects(internal_api: griffelib.Module) -> list[griffelib.Object | griffelib.Alias]: return list(_yield_public_objects(internal_api, modulelevel=True)) @pytest.fixture(name="internal_objects", scope="module") -def _fixture_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: +def _fixture_internal_objects(internal_api: griffelib.Module) -> list[griffelib.Object | griffelib.Alias]: return list(_yield_public_objects(internal_api, modulelevel=False, special=True)) @pytest.fixture(name="public_objects", scope="module") -def _fixture_public_objects(public_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: +def _fixture_public_objects(public_api: griffelib.Module) -> list[griffelib.Object | griffelib.Alias]: return list(_yield_public_objects(public_api, modulelevel=False, inherited=True, special=True)) @@ -100,7 +100,7 @@ def _fixture_inventory() -> Inventory: return Inventory.parse_sphinx(file) -def test_alias_proxies(internal_api: griffe.Module) -> None: +def test_alias_proxies(internal_api: griffelib.Module) -> None: """The Alias class has all the necessary methods and properties.""" alias_members = set(internal_api["models.Alias"].all_members.keys()) for cls in ( @@ -114,17 +114,17 @@ def test_alias_proxies(internal_api: griffe.Module) -> None: assert name in alias_members -def test_exposed_objects(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None: +def test_exposed_objects(modulelevel_internal_objects: list[griffelib.Object | griffelib.Alias]) -> None: """All public objects in the internal API are exposed under `griffe`.""" not_exposed = [ obj.path for obj in modulelevel_internal_objects - if obj.name not in griffe.__all__ or not hasattr(griffe, obj.name) + if obj.name not in griffelib.__all__ or not hasattr(griffe, obj.name) ] assert not not_exposed, "Objects not exposed:\n" + "\n".join(sorted(not_exposed)) -def test_unique_names(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None: +def test_unique_names(modulelevel_internal_objects: list[griffelib.Object | griffelib.Alias]) -> None: """All internal objects have unique names.""" names_to_paths = defaultdict(list) for obj in modulelevel_internal_objects: @@ -133,14 +133,14 @@ def test_unique_names(modulelevel_internal_objects: list[griffe.Object | griffe. assert not non_unique, "Non-unique names:\n" + "\n".join(str(paths) for paths in non_unique) -def test_single_locations(public_api: griffe.Module) -> None: +def test_single_locations(public_api: griffelib.Module) -> None: """All objects have a single public location.""" - def _public_path(obj: griffe.Object | griffe.Alias) -> bool: + def _public_path(obj: griffelib.Object | griffelib.Alias) -> bool: return obj.is_public and (obj.parent is None or _public_path(obj.parent)) multiple_locations = {} - for obj_name in griffe.__all__: + for obj_name in griffelib.__all__: obj = public_api[obj_name] if obj.aliases and ( public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)] @@ -151,10 +151,10 @@ def _public_path(obj: griffe.Object | griffe.Alias) -> bool: ) -def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe.Object | griffe.Alias]) -> None: +def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffelib.Object | griffelib.Alias]) -> None: """All public objects are added to the inventory.""" ignore_names = {"__getattr__", "__init__", "__repr__", "__str__", "__post_init__"} - ignore_paths = {"griffe.DataclassesExtension.*", "griffe.UnpackTypedDictExtension.*"} + ignore_paths = {"griffelib.DataclassesExtension.*", "griffelib.UnpackTypedDictExtension.*"} not_in_inventory = [ f"{obj.relative_filepath}:{obj.lineno}: {obj.path}" for obj in public_objects @@ -170,8 +170,8 @@ def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe def test_inventory_matches_api( inventory: Inventory, - public_objects: list[griffe.Object | griffe.Alias], - loader: griffe.GriffeLoader, + public_objects: list[griffelib.Object | griffelib.Alias], + loader: griffelib.GriffeLoader, ) -> None: """The inventory doesn't contain any additional Python object.""" not_in_api = [] @@ -186,14 +186,14 @@ def test_inventory_matches_api( assert not not_in_api, msg.format(paths="\n".join(sorted(not_in_api))) -def test_no_module_docstrings_in_internal_api(internal_api: griffe.Module) -> None: +def test_no_module_docstrings_in_internal_api(internal_api: griffelib.Module) -> None: """No module docstrings should be written in our internal API. The reasoning is that docstrings are addressed to users of the public API, but internal modules are not exposed to users, so they should not have docstrings. """ - def _modules(obj: griffe.Module) -> Iterator[griffe.Module]: + def _modules(obj: griffelib.Module) -> Iterator[griffelib.Module]: for member in obj.modules.values(): yield member yield from _modules(member) diff --git a/tests/test_cli.py b/tests/test_cli.py index a71507a76..c500a3ac2 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,7 +6,7 @@ import pytest -from griffe._internal import cli, debug +from griffelib._internal import cli, debug def test_main() -> None: diff --git a/tests/test_docstrings/conftest.py b/tests/test_docstrings/conftest.py index 366727cee..c37dfda55 100644 --- a/tests/test_docstrings/conftest.py +++ b/tests/test_docstrings/conftest.py @@ -6,7 +6,7 @@ import pytest -from griffe._internal.docstrings import google, numpy, sphinx +from griffelib._internal.docstrings import google, numpy, sphinx from tests.test_docstrings.helpers import ParserType, parser if TYPE_CHECKING: diff --git a/tests/test_docstrings/test_google.py b/tests/test_docstrings/test_google.py index 0af072c6d..0685fd73d 100644 --- a/tests/test_docstrings/test_google.py +++ b/tests/test_docstrings/test_google.py @@ -1,4 +1,4 @@ -"""Tests for the [Google-style parser][griffe.docstrings.google].""" +"""Tests for the [Google-style parser][griffelib.docstrings.google].""" from __future__ import annotations diff --git a/tests/test_docstrings/test_numpy.py b/tests/test_docstrings/test_numpy.py index 344856e50..2cbe608c1 100644 --- a/tests/test_docstrings/test_numpy.py +++ b/tests/test_docstrings/test_numpy.py @@ -1,4 +1,4 @@ -"""Tests for the [Numpy-style parser][griffe.docstrings.numpy].""" +"""Tests for the [Numpy-style parser][griffelib.docstrings.numpy].""" from __future__ import annotations diff --git a/tests/test_docstrings/test_sphinx.py b/tests/test_docstrings/test_sphinx.py index 90279e4dd..738cf01a7 100644 --- a/tests/test_docstrings/test_sphinx.py +++ b/tests/test_docstrings/test_sphinx.py @@ -1,4 +1,4 @@ -"""Tests for the [Sphinx-style parser][griffe.docstrings.sphinx].""" +"""Tests for the [Sphinx-style parser][griffelib.docstrings.sphinx].""" from __future__ import annotations diff --git a/tests/test_extensions/test_base.py b/tests/test_extensions/test_base.py index 7ca78dee4..5f5caa7a1 100644 --- a/tests/test_extensions/test_base.py +++ b/tests/test_extensions/test_base.py @@ -17,7 +17,7 @@ temporary_visited_module, temporary_visited_package, ) -from griffe._internal.models import Attribute, Class, Function, Module, Object, TypeAlias +from griffelib._internal.models import Attribute, Class, Function, Module, Object, TypeAlias if TYPE_CHECKING: import ast diff --git a/tests/test_finder.py b/tests/test_finder.py index 9b6d34076..c24c4622d 100644 --- a/tests/test_finder.py +++ b/tests/test_finder.py @@ -9,7 +9,7 @@ import pytest from griffe import Module, ModuleFinder, NamespacePackage, Package, temporary_pypackage -from griffe._internal.finder import _handle_editable_module, _handle_pth_file +from griffelib._internal.finder import _handle_editable_module, _handle_pth_file @pytest.mark.parametrize( @@ -125,7 +125,7 @@ def test_editables_file_handling(tmp_path: Path, editable_file_name: str) -> Non tmp_path: Pytest fixture. """ pth_file = tmp_path / editable_file_name - pth_file.write_text("hello\nF.map_module('griffe', 'src/griffe/__init__.py')", encoding="utf8") + pth_file.write_text("hello\nF.map_module('griffe', 'packages/griffe/src/griffe/__init__.py')", encoding="utf8") paths = [sp.path for sp in _handle_editable_module(pth_file)] assert paths == [Path("src")] @@ -139,7 +139,7 @@ def test_setuptools_file_handling(tmp_path: Path, annotation: str) -> None: annotation: The type annotation of the MAPPING variable. """ pth_file = tmp_path / "__editable__whatever.py" - pth_file.write_text(f"hello\nMAPPING{annotation} = {{'griffe': 'src/griffe'}}", encoding="utf8") + pth_file.write_text(f"hello\nMAPPING{annotation} = {{'griffe': 'packages/griffe/src/griffe'}}", encoding="utf8") paths = [sp.path for sp in _handle_editable_module(pth_file)] assert paths == [Path("src")] From b2dad08053d624aa8bb42ae164a36da8ce108002 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 20:27:02 +0000 Subject: [PATCH 04/53] Initial plan From 72b1bbd57b2b7c62cd83613fc6c2f8e4f71bde7a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 20:41:21 +0000 Subject: [PATCH 05/53] Fix griffelib/griffecli separation and add proper exports Co-authored-by: johnslavik <64036239+johnslavik@users.noreply.github.com> --- packages/griffecli/pyproject.toml | 7 + packages/griffecli/src/griffecli/__init__.py | 28 +++- packages/griffecli/src/griffecli/__main__.py | 2 +- .../griffecli/src/griffecli/_internal/cli.py | 6 +- packages/griffelib/pyproject.toml | 4 + packages/griffelib/src/griffelib/__init__.py | 143 ++++++++---------- .../src/griffelib/_internal/logger.py | 11 +- pyproject.toml | 4 +- src/griffe/__init__.py | 22 ++- 9 files changed, 137 insertions(+), 90 deletions(-) diff --git a/packages/griffecli/pyproject.toml b/packages/griffecli/pyproject.toml index 26726d5fa..7d4fe1dcd 100644 --- a/packages/griffecli/pyproject.toml +++ b/packages/griffecli/pyproject.toml @@ -41,8 +41,15 @@ classifiers = [ "Typing :: Typed", ] +[project.scripts] +griffecli = "griffecli:main" + [tool.hatch.metadata.hooks.uv-dynamic-versioning] +dependencies = ["griffelib=={version}", "colorama>=0.4"] [tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] [tool.hatch.build.targets.sdist] + +[tool.hatch.build.targets.wheel] +sources = ["src/"] diff --git a/packages/griffecli/src/griffecli/__init__.py b/packages/griffecli/src/griffecli/__init__.py index 54cec7a60..b7c23fc12 100644 --- a/packages/griffecli/src/griffecli/__init__.py +++ b/packages/griffecli/src/griffecli/__init__.py @@ -1 +1,27 @@ -# TODO: Cut proper imports from griffelib `__init__.py` module +# This top-level module imports all public names from the CLI package, +# and exposes them as public objects. + +"""Griffe CLI package. + +The CLI (Command Line Interface) for the griffe library. +This package provides command-line tools for interacting with griffe. + +## CLI entrypoints + +- [`griffecli.main`][]: Run the main program. +- [`griffecli.check`][]: Check for API breaking changes in two versions of the same package. +- [`griffecli.dump`][]: Load packages data and dump it as JSON. +- [`griffecli.get_parser`][]: Get the argument parser for the CLI. +""" + +from __future__ import annotations + +from griffecli._internal.cli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main + +__all__ = [ + "DEFAULT_LOG_LEVEL", + "check", + "dump", + "get_parser", + "main", +] diff --git a/packages/griffecli/src/griffecli/__main__.py b/packages/griffecli/src/griffecli/__main__.py index 0374dbb77..22d5b7441 100644 --- a/packages/griffecli/src/griffecli/__main__.py +++ b/packages/griffecli/src/griffecli/__main__.py @@ -1,4 +1,4 @@ -# Entry-point module, in case you use `python -m griffelib`. +# Entry-point module, in case you use `python -m griffecli`. # # Why does this file exist, and why `__main__`? For more info, read: # diff --git a/packages/griffecli/src/griffecli/_internal/cli.py b/packages/griffecli/src/griffecli/_internal/cli.py index 708b8ac33..b13154dc9 100644 --- a/packages/griffecli/src/griffecli/_internal/cli.py +++ b/packages/griffecli/src/griffecli/_internal/cli.py @@ -4,11 +4,11 @@ # We might be tempted to import things from `__main__` later, # but that will cause problems; the code will get executed twice: # -# - When we run `python -m griffelib`, Python will execute +# - When we run `python -m griffecli`, Python will execute # `__main__.py` as a script. That means there won't be any -# `griffelib.__main__` in `sys.modules`. +# `griffecli.__main__` in `sys.modules`. # - When you import `__main__` it will get executed again (as a module) because -# there's no `griffelib.__main__` in `sys.modules`. +# there's no `griffecli.__main__` in `sys.modules`. from __future__ import annotations diff --git a/packages/griffelib/pyproject.toml b/packages/griffelib/pyproject.toml index aba09f221..3e608fcd6 100644 --- a/packages/griffelib/pyproject.toml +++ b/packages/griffelib/pyproject.toml @@ -44,5 +44,9 @@ classifiers = [ [tool.hatch.metadata.hooks.uv-dynamic-versioning] [tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] +pypi = ["pip>=24.0", "platformdirs>=4.2", "wheel>=0.42"] [tool.hatch.build.targets.sdist] + +[tool.hatch.build.targets.wheel] +sources = ["src/"] diff --git a/packages/griffelib/src/griffelib/__init__.py b/packages/griffelib/src/griffelib/__init__.py index e3db6aa85..7e9f74d4f 100644 --- a/packages/griffelib/src/griffelib/__init__.py +++ b/packages/griffelib/src/griffelib/__init__.py @@ -2,17 +2,18 @@ # and exposes them as public objects. We have tests to make sure # no object is forgotten in this list. -"""Griffe package. +"""Griffe library package. Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API. -The entirety of the public API is exposed here, in the top-level `griffelib` module. +The entirety of the library API is exposed here, in the top-level `griffelib` module. +For backward compatibility, you can also import from `griffe` which re-exports everything. All messages written to standard output or error are logged using the `logging` module. -Our logger's name is set to `"griffelib"` and is public (you can rely on it). -You can obtain the logger from the standard `logging` module: `logging.getLogger("griffelib")`. +Our logger's name is set to `"griffe"` and is public (you can rely on it). +You can obtain the logger from the standard `logging` module: `logging.getLogger("griffe")`. Actual logging messages are not part of the public API (they might change without notice). Raised exceptions throughout the package are part of the public API (you can rely on them). @@ -20,68 +21,60 @@ The following paragraphs will help you discover the package's content. -## CLI entrypoints - -Griffe provides a command-line interface (CLI) to interact with the package. The CLI entrypoints can be called from Python code. - -- [`griffecli.main`][]: Run the main program. -- [`griffecli.check`][]: Check for API breaking changes in two versions of the same package. -- [`griffecli.dump`][]: Load packages data and dump it as JSON. - ## Loaders To load API data, Griffe provides several high-level functions. -- [`griffelib.load`][]: Load and return a Griffe object. -- [`griffelib.load_git`][]: Load and return a module from a specific Git reference. -- [`griffelib.load_pypi`][]: Load and return a module from a specific package version downloaded using pip. +- [`griffe.load`][]: Load and return a Griffe object. +- [`griffe.load_git`][]: Load and return a module from a specific Git reference. +- [`griffe.load_pypi`][]: Load and return a module from a specific package version downloaded using pip. ## Models The data loaded by Griffe is represented by several classes. -- [`griffelib.Module`][]: The class representing a Python module. -- [`griffelib.Class`][]: The class representing a Python class. -- [`griffelib.Function`][]: The class representing a Python function or method. -- [`griffelib.Attribute`][]: The class representing a Python attribute. -- [`griffelib.Alias`][]: This class represents an alias, or indirection, to an object declared in another module. +- [`griffe.Module`][]: The class representing a Python module. +- [`griffe.Class`][]: The class representing a Python class. +- [`griffe.Function`][]: The class representing a Python function or method. +- [`griffe.Attribute`][]: The class representing a Python attribute. +- [`griffe.Alias`][]: This class represents an alias, or indirection, to an object declared in another module. Additional classes are available to represent other concepts. -- [`griffelib.Decorator`][]: This class represents a decorator. -- [`griffelib.Parameters`][]: This class is a container for parameters. -- [`griffelib.Parameter`][]: This class represent a function parameter. +- [`griffe.Decorator`][]: This class represents a decorator. +- [`griffe.Parameters`][]: This class is a container for parameters. +- [`griffe.Parameter`][]: This class represent a function parameter. ## Agents Griffe is able to analyze code both statically and dynamically, using the following "agents". However most of the time you will only need to use the loaders above. -- [`griffelib.visit`][]: Parse and visit a module file. -- [`griffelib.inspect`][]: Inspect a module. +- [`griffe.visit`][]: Parse and visit a module file. +- [`griffe.inspect`][]: Inspect a module. ## Serializers Griffe can serizalize data to dictionary and JSON. -- [`griffelib.Object.as_json`][griffelib.Object.as_json] -- [`griffelib.Object.from_json`][griffelib.Object.from_json] -- [`griffelib.JSONEncoder`][]: JSON encoder for Griffe objects. -- [`griffelib.json_decoder`][]: JSON decoder for Griffe objects. +- [`griffe.Object.as_json`][griffe.Object.as_json] +- [`griffe.Object.from_json`][griffe.Object.from_json] +- [`griffe.JSONEncoder`][]: JSON encoder for Griffe objects. +- [`griffe.json_decoder`][]: JSON decoder for Griffe objects. ## API checks Griffe can compare two versions of the same package to find breaking changes. -- [`griffelib.find_breaking_changes`][]: Find breaking changes between two versions of the same API. -- [`griffelib.Breakage`][]: Breakage classes can explain what broke from a version to another. +- [`griffe.find_breaking_changes`][]: Find breaking changes between two versions of the same API. +- [`griffe.Breakage`][]: Breakage classes can explain what broke from a version to another. ## Extensions -Griffe supports extensions. You can create your own extension by subclassing the `griffelib.Extension` class. +Griffe supports extensions. You can create your own extension by subclassing the `griffe.Extension` class. -- [`griffelib.load_extensions`][]: Load configured extensions. -- [`griffelib.Extension`][]: Base class for Griffe extensions. +- [`griffe.load_extensions`][]: Load configured extensions. +- [`griffe.Extension`][]: Base class for Griffe extensions. ## Docstrings @@ -89,35 +82,35 @@ Main class: -- [`griffelib.Docstring`][]: This class represents docstrings. +- [`griffe.Docstring`][]: This class represents docstrings. Docstring section and element classes all start with `Docstring`. Docstring parsers: -- [`griffelib.parse`][]: Parse the docstring. -- [`griffelib.parse_auto`][]: Parse a docstring by automatically detecting the style it uses. -- [`griffelib.parse_google`][]: Parse a Google-style docstring. -- [`griffelib.parse_numpy`][]: Parse a Numpydoc-style docstring. -- [`griffelib.parse_sphinx`][]: Parse a Sphinx-style docstring. +- [`griffe.parse`][]: Parse the docstring. +- [`griffe.parse_auto`][]: Parse a docstring by automatically detecting the style it uses. +- [`griffe.parse_google`][]: Parse a Google-style docstring. +- [`griffe.parse_numpy`][]: Parse a Numpydoc-style docstring. +- [`griffe.parse_sphinx`][]: Parse a Sphinx-style docstring. ## Exceptions Griffe uses several exceptions to signal errors. -- [`griffelib.GriffeError`][]: The base exception for all Griffe errors. -- [`griffelib.LoadingError`][]: Exception for loading errors. -- [`griffelib.NameResolutionError`][]: Exception for names that cannot be resolved in a object scope. -- [`griffelib.UnhandledEditableModuleError`][]: Exception for unhandled editables modules, when searching modules. -- [`griffelib.UnimportableModuleError`][]: Exception for modules that cannot be imported. -- [`griffelib.AliasResolutionError`][]: Exception for aliases that cannot be resolved. -- [`griffelib.CyclicAliasError`][]: Exception raised when a cycle is detected in aliases. -- [`griffelib.LastNodeError`][]: Exception raised when trying to access a next or previous node. -- [`griffelib.RootNodeError`][]: Exception raised when trying to use siblings properties on a root node. -- [`griffelib.BuiltinModuleError`][]: Exception raised when trying to access the filepath of a builtin module. -- [`griffelib.ExtensionError`][]: Base class for errors raised by extensions. -- [`griffelib.ExtensionNotLoadedError`][]: Exception raised when an extension could not be loaded. -- [`griffelib.GitError`][]: Exception raised for errors related to Git. +- [`griffe.GriffeError`][]: The base exception for all Griffe errors. +- [`griffe.LoadingError`][]: Exception for loading errors. +- [`griffe.NameResolutionError`][]: Exception for names that cannot be resolved in a object scope. +- [`griffe.UnhandledEditableModuleError`][]: Exception for unhandled editables modules, when searching modules. +- [`griffe.UnimportableModuleError`][]: Exception for modules that cannot be imported. +- [`griffe.AliasResolutionError`][]: Exception for aliases that cannot be resolved. +- [`griffe.CyclicAliasError`][]: Exception raised when a cycle is detected in aliases. +- [`griffe.LastNodeError`][]: Exception raised when trying to access a next or previous node. +- [`griffe.RootNodeError`][]: Exception raised when trying to use siblings properties on a root node. +- [`griffe.BuiltinModuleError`][]: Exception raised when trying to access the filepath of a builtin module. +- [`griffe.ExtensionError`][]: Base class for errors raised by extensions. +- [`griffe.ExtensionNotLoadedError`][]: Exception raised when an extension could not be loaded. +- [`griffe.GitError`][]: Exception raised for errors related to Git. # Expressions @@ -125,20 +118,20 @@ Expressions are basically abstract syntax trees (AST) with a few differences compared to the nodes returned by [`ast`][]. Griffe provides a few helpers to extract expressions from regular AST nodes. -- [`griffelib.get_annotation`][]: Get a type annotation as expression. -- [`griffelib.get_base_class`][]: Get a base class as expression. -- [`griffelib.get_class_keyword`][]: Get a class keyword as expression. -- [`griffelib.get_condition`][]: Get a condition as expression. -- [`griffelib.get_expression`][]: Get an expression from an AST node. -- [`griffelib.safe_get_annotation`][]: Get a type annotation as expression, safely (returns `None` on error). -- [`griffelib.safe_get_base_class`][]: Get a base class as expression, safely (returns `None` on error). -- [`griffelib.safe_get_class_keyword`][]: Get a class keyword as expression, safely (returns `None` on error). -- [`griffelib.safe_get_condition`][]: Get a condition as expression, safely (returns `None` on error). -- [`griffelib.safe_get_expression`][]: Get an expression from an AST node, safely (returns `None` on error). +- [`griffe.get_annotation`][]: Get a type annotation as expression. +- [`griffe.get_base_class`][]: Get a base class as expression. +- [`griffe.get_class_keyword`][]: Get a class keyword as expression. +- [`griffe.get_condition`][]: Get a condition as expression. +- [`griffe.get_expression`][]: Get an expression from an AST node. +- [`griffe.safe_get_annotation`][]: Get a type annotation as expression, safely (returns `None` on error). +- [`griffe.safe_get_base_class`][]: Get a base class as expression, safely (returns `None` on error). +- [`griffe.safe_get_class_keyword`][]: Get a class keyword as expression, safely (returns `None` on error). +- [`griffe.safe_get_condition`][]: Get a condition as expression, safely (returns `None` on error). +- [`griffe.safe_get_expression`][]: Get an expression from an AST node, safely (returns `None` on error). The base class for expressions. -- [`griffelib.Expr`][] +- [`griffe.Expr`][] Expression classes all start with `Expr`. @@ -147,19 +140,19 @@ If you want to log messages from extensions, get a logger with `get_logger`. The `logger` attribute is used by Griffe itself. You can use it to temporarily disable Griffe logging. -- [`griffelib.logger`][]: Our global logger, used throughout the library. -- [`griffelib.get_logger`][]: Create and return a new logger instance. +- [`griffe.logger`][]: Our global logger, used throughout the library. +- [`griffe.get_logger`][]: Create and return a new logger instance. # Helpers To test your Griffe extensions, or to load API data from code in memory, Griffe provides the following helpers. -- [`griffelib.temporary_pyfile`][]: Create a Python file containing the given code in a temporary directory. -- [`griffelib.temporary_pypackage`][]: Create a package containing the given modules in a temporary directory. -- [`griffelib.temporary_visited_module`][]: Create and visit a temporary module with the given code. -- [`griffelib.temporary_visited_package`][]: Create and visit a temporary package. -- [`griffelib.temporary_inspected_module`][]: Create and inspect a temporary module with the given code. -- [`griffelib.temporary_inspected_package`][]: Create and inspect a temporary package. +- [`griffe.temporary_pyfile`][]: Create a Python file containing the given code in a temporary directory. +- [`griffe.temporary_pypackage`][]: Create a package containing the given modules in a temporary directory. +- [`griffe.temporary_visited_module`][]: Create and visit a temporary module with the given code. +- [`griffe.temporary_visited_package`][]: Create and visit a temporary package. +- [`griffe.temporary_inspected_module`][]: Create and inspect a temporary module with the given code. +- [`griffe.temporary_inspected_package`][]: Create and inspect a temporary package. """ from __future__ import annotations @@ -185,7 +178,6 @@ from griffelib._internal.agents.nodes.values import get_value, safe_get_value from griffelib._internal.agents.visitor import Visitor, builtin_decorators, stdlib_decorators, typing_overload, visit from griffelib._internal.c3linear import c3linear_merge -from griffecli._internal.cli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main from griffelib._internal.collections import LinesCollection, ModulesCollection from griffelib._internal.diff import ( AttributeChangedTypeBreakage, @@ -383,7 +375,6 @@ # names = sorted(n for n in dir(griffelib) if not n.startswith("_") and n not in ("annotations",)) # print('__all__ = [\n "' + '",\n "'.join(names) + '",\n]') __all__ = [ - "DEFAULT_LOG_LEVEL", "Alias", "AliasResolutionError", "Attribute", @@ -546,9 +537,7 @@ "builtin_decorators", "builtin_extensions", "c3linear_merge", - "check", "docstring_warning", - "dump", "dynamic_import", "find_breaking_changes", "get__all__", @@ -563,7 +552,6 @@ "get_name", "get_names", "get_parameters", - "get_parser", "get_value", "htree", "infer_docstring_style", @@ -574,7 +562,6 @@ "load_git", "load_pypi", "logger", - "main", "merge_stubs", "module_vtree", "parse", diff --git a/packages/griffelib/src/griffelib/_internal/logger.py b/packages/griffelib/src/griffelib/_internal/logger.py index 3e598a758..4a7d45773 100644 --- a/packages/griffelib/src/griffelib/_internal/logger.py +++ b/packages/griffelib/src/griffelib/_internal/logger.py @@ -4,7 +4,8 @@ # For example, mkdocstrings-python patches the logger to relocate it as a child # of `mkdocs.plugins` so that it fits in the MkDocs logging configuration. # -# We use a single, global logger because our public API is exposed in a single module, `griffelib`. +# We use a single, global logger because our public API is exposed in a single module. +# The logger name is "griffe" for backward compatibility. # Extensions however should use their own logger, which is why we provide the `get_logger` function. from __future__ import annotations @@ -40,7 +41,7 @@ def disable(self) -> Iterator[None]: self._logger.setLevel(old_level) @classmethod - def _get(cls, name: str = "griffelib") -> Logger: + def _get(cls, name: str = "griffe") -> Logger: if name not in cls._instances: cls._instances[name] = cls(name) return cls._instances[name] @@ -60,7 +61,7 @@ def _patch_loggers(cls, get_logger_func: Callable) -> None: Griffe's output and error messages are logging messages. -Griffe provides the [`patch_loggers`][griffelib.patch_loggers] +Griffe provides the [`patch_loggers`][griffe.patch_loggers] function so dependent libraries can patch Griffe loggers as they see fit. For example, to fit in the MkDocs logging configuration @@ -68,7 +69,7 @@ def _patch_loggers(cls, get_logger_func: Callable) -> None: ```python import logging -from griffelib import patch_loggers +from griffe import patch_loggers class LoggerAdapter(logging.LoggerAdapter): @@ -90,7 +91,7 @@ def get_logger(name): """ -def get_logger(name: str = "griffelib") -> Logger: +def get_logger(name: str = "griffe") -> Logger: """Create and return a new logger instance. Parameters: diff --git a/pyproject.toml b/pyproject.toml index 3a2fff8cc..67943ec8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,8 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "colorama>=0.4", + "griffelib", + "griffecli", ] [project.optional-dependencies] @@ -136,3 +137,4 @@ ci = [ [tool.uv] default-groups = ["maintain", "ci", "docs"] +workspace = { members = ["packages/*"] } diff --git a/src/griffe/__init__.py b/src/griffe/__init__.py index a48bb5aa2..6884c3c23 100644 --- a/src/griffe/__init__.py +++ b/src/griffe/__init__.py @@ -1,4 +1,24 @@ -"""Griffe CLI package. Re-exports griffelib and griffecli.""" +"""Griffe package. + +Signatures for entire Python programs. +Extract the structure, the frame, the skeleton of your project, +to generate API documentation or find breaking changes in your API. + +This is a backward-compatible package that re-exports all public symbols from +both `griffelib` (the library) and `griffecli` (the CLI). + +The entirety of the public API is exposed here, in the top-level `griffe` module. + +All messages written to standard output or error are logged using the `logging` module. +Our logger's name is set to `"griffe"` and is public (you can rely on it). +You can obtain the logger from the standard `logging` module: `logging.getLogger("griffe")`. +Actual logging messages are not part of the public API (they might change without notice). + +Raised exceptions throughout the package are part of the public API (you can rely on them). +Their actual messages are not part of the public API (they might change without notice). + +See the `griffelib` and `griffecli` packages for detailed API documentation. +""" from griffecli import * from griffecli import __all__ as __cli_all__ From 6b829c8c9e859a8f29b915bcb760b64d59a71231 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 20:49:22 +0000 Subject: [PATCH 06/53] Fix test imports and paths for new package structure Co-authored-by: johnslavik <64036239+johnslavik@users.noreply.github.com> --- config/ruff.toml | 16 ++++++++-------- .../src/griffecli/_internal/__init__.py | 1 + .../src/griffelib/_internal/extensions/base.py | 2 +- .../griffelib/src/griffelib/_internal/models.py | 7 ++++++- src/griffe/__init__.py | 6 +++--- src/griffe/__main__.py | 8 ++++++++ tests/test_cli.py | 3 ++- tests/test_encoders.py | 2 +- tests/test_finder.py | 4 ++-- 9 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 packages/griffecli/src/griffecli/_internal/__init__.py diff --git a/config/ruff.toml b/config/ruff.toml index 7277e2d6f..462ddcbce 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -35,27 +35,27 @@ ignore = [ "TRY003", # Avoid specifying long messages outside the exception class ] -logger-objects = ["griffelib.logger"] +logger-objects = ["griffe.logger", "griffelib.logger"] [lint.per-file-ignores] -"packages/griffe/src/griffe/__main__.py" = [ +"packages/griffecli/src/griffecli/__main__.py" = [ "D100", # Missing module docstring ] -"packages/griffe/src/griffe/_internal/cli.py" = [ +"packages/griffecli/src/griffecli/_internal/cli.py" = [ "T201", # Print statement ] -"packages/griffe/src/griffe/_internal/git.py" = [ +"packages/griffelib/src/griffelib/_internal/git.py" = [ "S603", # `subprocess` call: check for execution of untrusted input "S607", # Starting a process with a partial executable path ] -"packages/griffe/src/griffe/_internal/agents/nodes/*.py" = [ +"packages/griffelib/src/griffelib/_internal/agents/nodes/*.py" = [ "ARG001", # Unused function argument "N812", # Lowercase `keyword` imported as non-lowercase `NodeKeyword` ] -"packages/griffe/src/griffe/_internal/debug.py" = [ +"packages/griffelib/src/griffelib/_internal/debug.py" = [ "T201", # Print statement ] -"packages/griffe/src/griffe/_internal/**.py" = [ +"packages/griffelib/src/griffelib/_internal/**.py" = [ "D100", # Missing docstring in public module ] "scripts/*.py" = [ @@ -84,7 +84,7 @@ docstring-quotes = "double" ban-relative-imports = "all" [lint.isort] -known-first-party = ["griffe"] +known-first-party = ["griffe", "griffelib", "griffecli"] [lint.pydocstyle] convention = "google" diff --git a/packages/griffecli/src/griffecli/_internal/__init__.py b/packages/griffecli/src/griffecli/_internal/__init__.py new file mode 100644 index 000000000..4e283f85f --- /dev/null +++ b/packages/griffecli/src/griffecli/_internal/__init__.py @@ -0,0 +1 @@ +# Internal module for griffecli. diff --git a/packages/griffelib/src/griffelib/_internal/extensions/base.py b/packages/griffelib/src/griffelib/_internal/extensions/base.py index 879bf23af..c51893ee8 100644 --- a/packages/griffelib/src/griffelib/_internal/extensions/base.py +++ b/packages/griffelib/src/griffelib/_internal/extensions/base.py @@ -603,7 +603,7 @@ def load_extensions(*exts: LoadableExtensionType) -> Extensions: # TODO: Deprecate and remove at some point? # Always add our built-in dataclasses extension. - from griffelib._internal.extensions.dataclasses import DataclassesExtension # noqa: PLC0415 + from griffelib._internal.extensions.dataclasses import DataclassesExtension # noqa: PLC0415 for ext in extensions._extensions: if type(ext) is DataclassesExtension: diff --git a/packages/griffelib/src/griffelib/_internal/models.py b/packages/griffelib/src/griffelib/_internal/models.py index fde780f6e..50a38814f 100644 --- a/packages/griffelib/src/griffelib/_internal/models.py +++ b/packages/griffelib/src/griffelib/_internal/models.py @@ -14,7 +14,12 @@ from griffelib._internal.c3linear import c3linear_merge from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle, parse from griffelib._internal.enumerations import Kind, ParameterKind, Parser, TypeParameterKind -from griffelib._internal.exceptions import AliasResolutionError, BuiltinModuleError, CyclicAliasError, NameResolutionError +from griffelib._internal.exceptions import ( + AliasResolutionError, + BuiltinModuleError, + CyclicAliasError, + NameResolutionError, +) from griffelib._internal.expressions import ExprCall, ExprName, ExprTuple from griffelib._internal.logger import logger from griffelib._internal.mixins import ObjectAliasMixin diff --git a/src/griffe/__init__.py b/src/griffe/__init__.py index 6884c3c23..09ddc836a 100644 --- a/src/griffe/__init__.py +++ b/src/griffe/__init__.py @@ -20,9 +20,9 @@ See the `griffelib` and `griffecli` packages for detailed API documentation. """ -from griffecli import * +from griffecli import * # noqa: F403 from griffecli import __all__ as __cli_all__ -from griffelib import * +from griffelib import * # noqa: F403 from griffelib import __all__ as __lib_all__ -__all__ = [*__lib_all__, *__cli_all__] +__all__ = [*__lib_all__, *__cli_all__] # noqa: PLE0604 diff --git a/src/griffe/__main__.py b/src/griffe/__main__.py index 3b5ca458b..30c64ab2b 100644 --- a/src/griffe/__main__.py +++ b/src/griffe/__main__.py @@ -1,3 +1,11 @@ +"""Entry-point module, in case you use `python -m griffe`. + +Why does this file exist, and why `__main__`? For more info, read: + +- https://www.python.org/dev/peps/pep-0338/ +- https://docs.python.org/3/using/cmdline.html#cmdoption-m +""" + import sys from griffecli import main diff --git a/tests/test_cli.py b/tests/test_cli.py index c500a3ac2..fde01915f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,7 +6,8 @@ import pytest -from griffelib._internal import cli, debug +from griffecli._internal import cli +from griffelib._internal import debug def test_main() -> None: diff --git a/tests/test_encoders.py b/tests/test_encoders.py index b8d3eeb47..938688194 100644 --- a/tests/test_encoders.py +++ b/tests/test_encoders.py @@ -73,7 +73,7 @@ def test_namespace_packages() -> None: def test_minimal_light_data_is_enough(symbol: str) -> None: """Test serialization and de-serialization.""" loader = GriffeLoader() - package = loader.load("griffe") + package = loader.load("griffelib") obj = package[symbol] dump_options = {"indent": 2, "sort_keys": True} minimal = obj.as_json(full=False, **dump_options) diff --git a/tests/test_finder.py b/tests/test_finder.py index c24c4622d..d65c492fc 100644 --- a/tests/test_finder.py +++ b/tests/test_finder.py @@ -125,7 +125,7 @@ def test_editables_file_handling(tmp_path: Path, editable_file_name: str) -> Non tmp_path: Pytest fixture. """ pth_file = tmp_path / editable_file_name - pth_file.write_text("hello\nF.map_module('griffe', 'packages/griffe/src/griffe/__init__.py')", encoding="utf8") + pth_file.write_text("hello\nF.map_module('griffe', 'src/griffe/__init__.py')", encoding="utf8") paths = [sp.path for sp in _handle_editable_module(pth_file)] assert paths == [Path("src")] @@ -139,7 +139,7 @@ def test_setuptools_file_handling(tmp_path: Path, annotation: str) -> None: annotation: The type annotation of the MAPPING variable. """ pth_file = tmp_path / "__editable__whatever.py" - pth_file.write_text(f"hello\nMAPPING{annotation} = {{'griffe': 'packages/griffe/src/griffe'}}", encoding="utf8") + pth_file.write_text(f"hello\nMAPPING{annotation} = {{'griffe': 'src/griffe'}}", encoding="utf8") paths = [sp.path for sp in _handle_editable_module(pth_file)] assert paths == [Path("src")] From bb98dcaf0bb9b104dec1a6ee51991d1e8564ae7c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 20:52:18 +0000 Subject: [PATCH 07/53] Address code review feedback on comments and documentation Co-authored-by: johnslavik <64036239+johnslavik@users.noreply.github.com> --- packages/griffecli/pyproject.toml | 2 ++ packages/griffecli/src/griffecli/_internal/__init__.py | 2 +- packages/griffelib/pyproject.toml | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/griffecli/pyproject.toml b/packages/griffecli/pyproject.toml index 7d4fe1dcd..69ab1f99d 100644 --- a/packages/griffecli/pyproject.toml +++ b/packages/griffecli/pyproject.toml @@ -45,9 +45,11 @@ classifiers = [ griffecli = "griffecli:main" [tool.hatch.metadata.hooks.uv-dynamic-versioning] +# Dependencies are dynamically versioned; {version} is substituted at build time. dependencies = ["griffelib=={version}", "colorama>=0.4"] [tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] +# No optional dependencies for the CLI package [tool.hatch.build.targets.sdist] diff --git a/packages/griffecli/src/griffecli/_internal/__init__.py b/packages/griffecli/src/griffecli/_internal/__init__.py index 4e283f85f..03d25ad8f 100644 --- a/packages/griffecli/src/griffecli/_internal/__init__.py +++ b/packages/griffecli/src/griffecli/_internal/__init__.py @@ -1 +1 @@ -# Internal module for griffecli. +# Internal modules for the griffecli package. diff --git a/packages/griffelib/pyproject.toml b/packages/griffelib/pyproject.toml index 3e608fcd6..b01dfcde7 100644 --- a/packages/griffelib/pyproject.toml +++ b/packages/griffelib/pyproject.toml @@ -42,8 +42,11 @@ classifiers = [ ] [tool.hatch.metadata.hooks.uv-dynamic-versioning] +# No base dependencies needed for griffelib [tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] +# The 'pypi' extra provides dependencies needed for the load_pypi functionality +# to download and inspect packages from PyPI. pypi = ["pip>=24.0", "platformdirs>=4.2", "wheel>=0.42"] [tool.hatch.build.targets.sdist] From 95c310e765c2e5b2af3e2d9a356884ec4b993926 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 21:00:00 +0000 Subject: [PATCH 08/53] Add version locking for griffe's dependencies on griffelib and griffecli Co-authored-by: johnslavik <64036239+johnslavik@users.noreply.github.com> --- pyproject.toml | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 67943ec8b..a044411e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [build-system] # pdm-backend is left here as a dependency of the version discovery script currently in use. # It may be removed in the future. See mkdocstrings/griffe#430 -requires = ["hatchling", "pdm-backend"] +requires = ["hatchling", "pdm-backend", "uv-dynamic-versioning>=0.7.0"] build-backend = "hatchling.build" [project] @@ -13,7 +13,7 @@ license-files = ["LICENSE"] readme = "README.md" requires-python = ">=3.10" keywords = ["api", "signature", "breaking-changes", "static-analysis", "dynamic-analysis"] -dynamic = ["version"] +dynamic = ["version", "dependencies", "optional-dependencies"] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -36,17 +36,6 @@ classifiers = [ "Topic :: Utilities", "Typing :: Typed", ] -dependencies = [ - "griffelib", - "griffecli", -] - -[project.optional-dependencies] -pypi = [ - "pip>=24.0", - "platformdirs>=4.2", - "wheel>=0.42", -] [project.urls] Homepage = "https://mkdocstrings.github.io/griffe" @@ -66,6 +55,16 @@ source = "code" path = "scripts/get_version.py" expression = "get_version()" +[tool.hatch.metadata.hooks.uv-dynamic-versioning] +# Dependencies are dynamically versioned; {version} is substituted at build time. +# This ensures griffe, griffelib, and griffecli versions are always 1:1. +dependencies = ["griffelib=={version}", "griffecli=={version}"] + +[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] +# The 'pypi' extra provides dependencies needed for the load_pypi functionality +# to download and inspect packages from PyPI. +pypi = ["pip>=24.0", "platformdirs>=4.2", "wheel>=0.42"] + [tool.hatch.build] # Include as much as possible in the source distribution, to help redistributors. ignore-vcs = true From 538c553cd9a6240dffeba9ef5f2453fac288f5bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 21:07:10 +0000 Subject: [PATCH 09/53] Use double brackets for version interpolation and re-export griffelib[pypi] Co-authored-by: johnslavik <64036239+johnslavik@users.noreply.github.com> --- packages/griffecli/pyproject.toml | 4 ++-- pyproject.toml | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/griffecli/pyproject.toml b/packages/griffecli/pyproject.toml index 69ab1f99d..6a9af0fc8 100644 --- a/packages/griffecli/pyproject.toml +++ b/packages/griffecli/pyproject.toml @@ -45,8 +45,8 @@ classifiers = [ griffecli = "griffecli:main" [tool.hatch.metadata.hooks.uv-dynamic-versioning] -# Dependencies are dynamically versioned; {version} is substituted at build time. -dependencies = ["griffelib=={version}", "colorama>=0.4"] +# Dependencies are dynamically versioned; {{version}} is substituted at build time. +dependencies = ["griffelib=={{version}}", "colorama>=0.4"] [tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] # No optional dependencies for the CLI package diff --git a/pyproject.toml b/pyproject.toml index a044411e1..3bddfc0db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,14 +56,13 @@ path = "scripts/get_version.py" expression = "get_version()" [tool.hatch.metadata.hooks.uv-dynamic-versioning] -# Dependencies are dynamically versioned; {version} is substituted at build time. +# Dependencies are dynamically versioned; {{version}} is substituted at build time. # This ensures griffe, griffelib, and griffecli versions are always 1:1. -dependencies = ["griffelib=={version}", "griffecli=={version}"] +dependencies = ["griffelib=={{version}}", "griffecli=={{version}}"] [tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] -# The 'pypi' extra provides dependencies needed for the load_pypi functionality -# to download and inspect packages from PyPI. -pypi = ["pip>=24.0", "platformdirs>=4.2", "wheel>=0.42"] +# The 'pypi' extra re-exports griffelib[pypi] for backward compatibility. +pypi = ["griffelib[pypi]=={{version}}"] [tool.hatch.build] # Include as much as possible in the source distribution, to help redistributors. From 3b28334a3de44c8e85555f48af73eb17a6356eaa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 21:15:01 +0000 Subject: [PATCH 10/53] Initial plan From e080e574c8b91d6d5f6a7af0b87d4dbd8c178224 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 21:25:46 +0000 Subject: [PATCH 11/53] Fix missing pyproject.toml config and CLI program name Co-authored-by: johnslavik <64036239+johnslavik@users.noreply.github.com> --- docs/extensions/built-in/dataclasses.md | 4 +- docs/extensions/built-in/unpack-typeddict.md | 4 +- docs/extensions/official/runtime-objects.md | 4 +- .../official/warnings-deprecated.md | 2 +- docs/guide/contributors/architecture.md | 10 +- docs/guide/contributors/workflow.md | 4 + docs/guide/users/checking.md | 100 ++++----- docs/guide/users/extending.md | 160 ++++++------- docs/guide/users/how-to/parse-docstrings.md | 2 +- .../guide/users/how-to/selectively-inspect.md | 46 ++-- .../users/how-to/set-docstring-styles.md | 12 +- docs/guide/users/how-to/set-git-info.md | 20 +- docs/guide/users/how-to/support-decorators.md | 14 +- docs/guide/users/loading.md | 74 +++--- docs/guide/users/navigating.md | 210 +++++++++--------- .../users/recommendations/public-apis.md | 14 +- docs/guide/users/serializing.md | 18 +- docs/index.md | 10 +- docs/installation.md | 17 ++ docs/introduction.md | 22 +- docs/playground.md | 2 +- docs/reference/api/agents.md | 64 +++--- docs/reference/api/checks.md | 32 +-- docs/reference/api/cli.md | 8 +- docs/reference/api/docstrings/models.md | 72 +++--- docs/reference/api/docstrings/parsers.md | 36 +-- docs/reference/api/exceptions.md | 26 +-- docs/reference/api/expressions.md | 86 +++---- docs/reference/api/extensions.md | 14 +- docs/reference/api/finder.md | 10 +- docs/reference/api/git.md | 13 ++ docs/reference/api/helpers.md | 20 +- docs/reference/api/loaders.md | 16 +- docs/reference/api/loggers.md | 12 +- docs/reference/api/models.md | 36 +-- docs/reference/api/models/alias.md | 2 +- docs/reference/api/models/attribute.md | 2 +- docs/reference/api/models/class.md | 4 +- docs/reference/api/models/function.md | 12 +- docs/reference/api/models/module.md | 2 +- docs/reference/api/models/type_alias.md | 2 +- docs/reference/api/serializers.md | 6 +- docs/reference/docstrings.md | 2 +- docs/schema-docstrings-options.json | 6 +- docs/schema.json | 152 ++++++------- .../griffecli/src/griffecli/_internal/cli.py | 10 +- pyproject.toml | 4 + 47 files changed, 720 insertions(+), 678 deletions(-) create mode 100644 docs/reference/api/git.md diff --git a/docs/extensions/built-in/dataclasses.md b/docs/extensions/built-in/dataclasses.md index 554a88f79..24e72b70b 100644 --- a/docs/extensions/built-in/dataclasses.md +++ b/docs/extensions/built-in/dataclasses.md @@ -29,14 +29,14 @@ Additional metadata like `ClassVar`, the `init` and `kw_only` parameters, or the === "CLI" ```console - $ griffecli dump -e dataclasses,other my_package + $ griffe dump -e dataclasses,other my_package ``` === "Python" ```python import griffe - my_package = griffelib.load("my_package", extensions=griffelib.load_extensions("dataclasses", "other")) + my_package = griffe.load("my_package", extensions=griffe.load_extensions("dataclasses", "other")) ``` === "mkdocstrings" diff --git a/docs/extensions/built-in/unpack-typeddict.md b/docs/extensions/built-in/unpack-typeddict.md index b7968a72f..d3dbca7ab 100644 --- a/docs/extensions/built-in/unpack-typeddict.md +++ b/docs/extensions/built-in/unpack-typeddict.md @@ -65,14 +65,14 @@ To enable the extension: === "CLI" ```console - $ griffecli dump -e unpack_typeddict my_package + $ griffe dump -e unpack_typeddict my_package ``` === "Python" ```python import griffe - my_package = griffelib.load("my_package", extensions=griffelib.load_extensions("unpack_typeddict")) + my_package = griffe.load("my_package", extensions=griffe.load_extensions("unpack_typeddict")) ``` === "mkdocstrings" diff --git a/docs/extensions/official/runtime-objects.md b/docs/extensions/official/runtime-objects.md index c8c1d730e..fbfb72d34 100644 --- a/docs/extensions/official/runtime-objects.md +++ b/docs/extensions/official/runtime-objects.md @@ -11,11 +11,11 @@ This extension stores runtime objects corresponding to each loaded Griffe object ```pycon >>> import griffe ->>> griffe_data = griffelib.load("griffe", extensions=griffelib.load_extensions("griffe_runtime_objects"), resolve_aliases=True) +>>> griffe_data = griffe.load("griffe", extensions=griffe.load_extensions("griffe_runtime_objects"), resolve_aliases=True) >>> griffe_data["parse"].extra defaultdict(, {'runtime-objects': {'object': }}) >>> griffe_data["Module"].extra -defaultdict(, {'runtime-objects': {'object': }}) +defaultdict(, {'runtime-objects': {'object': }}) ``` It can be useful in combination with mkdocstrings-python and custom templates, to iterate over object values or their attributes that couldn't be loaded by Griffe itself (for example, objects built dynamically and loaded as attributes won't have "members" to iterate over). diff --git a/docs/extensions/official/warnings-deprecated.md b/docs/extensions/official/warnings-deprecated.md index 10ea7f78b..61ff9ddb2 100644 --- a/docs/extensions/official/warnings-deprecated.md +++ b/docs/extensions/official/warnings-deprecated.md @@ -7,7 +7,7 @@ --- -This extension adds support for functions and classes decorated with [`@warnings.deprecated(...)`][warnings.deprecated], as implemented thanks to [PEP 702](https://peps.python.org/pep-0702/). The message provided in the decorator call will be stored in the corresponding Griffe object's [`deprecated`][griffelib.Object.deprecated] attribute (usable by downstream rendering templates), and will also add an admonition to the object's docstring with the provided message as text. +This extension adds support for functions and classes decorated with [`@warnings.deprecated(...)`][warnings.deprecated], as implemented thanks to [PEP 702](https://peps.python.org/pep-0702/). The message provided in the decorator call will be stored in the corresponding Griffe object's [`deprecated`][griffe.Object.deprecated] attribute (usable by downstream rendering templates), and will also add an admonition to the object's docstring with the provided message as text. ```python from warnings import deprecated diff --git a/docs/guide/contributors/architecture.md b/docs/guide/contributors/architecture.md index 1719a14f9..edd5a94ec 100644 --- a/docs/guide/contributors/architecture.md +++ b/docs/guide/contributors/architecture.md @@ -22,8 +22,8 @@ descriptions = { "scripts": "Our different scripts. See [Scripts, configuration](#scripts-configuration).", "site": "Documentation site, built with `make run mkdocs build` (git-ignored).", "src": "The source of our Python package(s). See [Sources](#sources) and [Program structure](#program-structure).", - "packages/griffe/src/griffe": "Our public API, exposed to users. See [Program structure](#program-structure).", - "packages/griffe/src/griffe/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).", + "src/griffe": "Our public API, exposed to users. See [Program structure](#program-structure).", + "src/griffe/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).", "tests": "Our test suite. See [Tests](#tests).", ".copier-answers.yml": "The answers file generated by [Copier](https://copier.readthedocs.io/en/stable/). See [Boilerplate](#boilerplate).", "devdeps.txt": "Our development dependencies specification. See [`make setup`][command-setup] command.", @@ -104,11 +104,11 @@ Sources are located in the `src` folder, following the [src-layout](https://pack Our test suite is located in the `tests` folder. It is located outside of the sources as to not pollute distributions (it would be very wrong to publish a `tests` package as part of our distributions, since this name is extremely common), or worse, the public API. The `tests` folder is however included in our source distributions (`.tar.gz`), alongside most of our metadata and configuration files. Check out `pyproject.toml` to get the full list of files included in our source distributions. -The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffelib._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. +The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffe._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. ## Program structure -The internal API is contained within the `packages/griffe/src/griffe/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from various submodules of `griffelib._internal`. +The internal API is contained within the `src/griffe/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from various submodules of `griffe._internal`. Users then import `griffe` directly, or import objects from it. @@ -122,7 +122,7 @@ if os.getenv("DEPLOY") == "true": from pydeps.target import Target cli.verbose = cli._not_verbose - options = cli.parse_args(["packages/griffe/src/griffe", "--noshow", "--reverse"]) + options = cli.parse_args(["src/griffe", "--noshow", "--reverse"]) colors.START_COLOR = 128 target = Target(options["fname"]) with target.chdir_work(): diff --git a/docs/guide/contributors/workflow.md b/docs/guide/contributors/workflow.md index 62d2ff5f4..0e6064a49 100644 --- a/docs/guide/contributors/workflow.md +++ b/docs/guide/contributors/workflow.md @@ -57,6 +57,10 @@ Deprecated code should also be marked as legacy code. We use [Yore](https://pawa Examples: ```python title="Remove function when we bump to 2.0" +# YORE: Bump 2: Remove block. +def deprecated_function(): + ... +``` ```python title="Simplify imports when Python 3.15 is EOL" # YORE: EOL 3.15: Replace block with line 4. diff --git a/docs/guide/users/checking.md b/docs/guide/users/checking.md index 85c9d9800..9594fafd5 100644 --- a/docs/guide/users/checking.md +++ b/docs/guide/users/checking.md @@ -9,13 +9,13 @@ Griffe is able to compare two snapshots of your project to detect API breakages By default, Griffe will compare the current code to the latest tag: ```console -$ griffecli check mypackage +$ griffe check mypackage ``` To specify another Git reference to check against, use the `--against` or `-a` option: ```console -$ griffecli check mypackage -a 0.2.0 +$ griffe check mypackage -a 0.2.0 ``` You can specify a Git tag, commit (hash), or even a branch: Griffe will create a worktree at this reference in a temporary directory, and clean it up after finishing. @@ -23,24 +23,24 @@ You can specify a Git tag, commit (hash), or even a branch: Griffe will create a If you want to also specify the *base* reference to use (instead of the current code), use the `--base` or `-b` option. Some examples: ```console -$ griffecli check mypackage -b HEAD -a 2.0.0 -$ griffecli check mypackage -b 2.0.0 -a 1.0.0 -$ griffecli check mypackage -b fix-issue-90 -a 1.2.3 -$ griffecli check mypackage -b 8afcfd6e +$ griffe check mypackage -b HEAD -a 2.0.0 +$ griffe check mypackage -b 2.0.0 -a 1.0.0 +$ griffe check mypackage -b fix-issue-90 -a 1.2.3 +$ griffe check mypackage -b 8afcfd6e ``` TIP: **Important:** Remember that the base is the most recent reference, and the one we compare it against is the oldest one. -The package name you pass to `griffecli check` must be found relative to the repository root. For Griffe to find packages in subfolders, pass the parent subfolder to the `--search` or `-s` option. Example for `src`-layouts: +The package name you pass to `griffe check` must be found relative to the repository root. For Griffe to find packages in subfolders, pass the parent subfolder to the `--search` or `-s` option. Example for `src`-layouts: ```console -$ griffecli check -s src griffe +$ griffe check -s src griffe ``` Example in a monorepo, within a deeper file tree: ```console -$ griffecli check -s back/services/identity-provider/src identity_provider +$ griffe check -s back/services/identity-provider/src identity_provider ``` ### Using PyPI @@ -54,39 +54,39 @@ $ pip install griffe[pypi] The command syntax is: ```console -$ griffecli check package_name -b project-name==2.0 -a project-name==1.0 +$ griffe check package_name -b project-name==2.0 -a project-name==1.0 ``` You can let Griffe guess the package name by passing an empty string: ```console -$ griffecli check "" -b project-name==2.0 -a project-name==1.0 +$ griffe check "" -b project-name==2.0 -a project-name==1.0 ``` [PEP 508 version specifiers](https://peps.python.org/pep-0508/) are supported (`<`, `<=`, `!=`, `==`, `>=`, `>`, `~=`). For example, to compare v2 against the version just before it: ```console -$ griffecli check "" -b project-name==2.0 -a project-name<2.0 +$ griffe check "" -b project-name==2.0 -a project-name<2.0 ``` Without a version specifier on the base reference, or without a base reference at all, Griffe will use the latest available version. The two following commands compare the latest version against v1: ```console -$ griffecli check "" -b project-name -a project-name==1.0 -$ griffecli check "" -a project-name==1.0 +$ griffe check "" -b project-name -a project-name==1.0 +$ griffe check "" -a project-name==1.0 ``` Griffe will actually install packages in a cache directory. It means a few things: source distributions are supported, and only packages that are compatible with your current environment can be checked. ## Python API -To programmatically check for API breaking changes, you have to load two snapshots of your code base, for example using our [`load_git()`][griffelib.load_git] utility, and then passing them both to the [`find_breaking_changes()`][griffelib.find_breaking_changes] function. This function will yield instances of [`Breakage`][griffelib.Breakage]. It's up to you how you want to use these breakage instances. +To programmatically check for API breaking changes, you have to load two snapshots of your code base, for example using our [`load_git()`][griffe.load_git] utility, and then passing them both to the [`find_breaking_changes()`][griffe.find_breaking_changes] function. This function will yield instances of [`Breakage`][griffe.Breakage]. It's up to you how you want to use these breakage instances. ```python import griffe -my_pkg_v1 = griffelib.load_git("my_pkg", ref="v1") -my_pkg_v2 = griffelib.load_git("my_pkg", ref="v2") +my_pkg_v1 = griffe.load_git("my_pkg", ref="v1") +my_pkg_v2 = griffe.load_git("my_pkg", ref="v2") for breaking_change in find_breaking_changes(my_pkg_v1, my_pkg_v2): print(breaking_change.explain()) @@ -110,7 +110,7 @@ jobs: fetch-depth: 0 # We the need the full Git history. - uses: astral-sh/setup-uv@v6 # The following command will compare current changes to latest tag. - - run: uvx griffecli check --search src --format github your_package_name + - run: uvx griffe check --search src --format github your_package_name ``` The last step will fail the workflow if any breaking change is found. @@ -643,9 +643,9 @@ Griffe supports writing detected breakages in multiple formats, or styles. This is the default format. Griffe will print each detected breakage on a single line: -```console exec="1" source="console" result="ansi" returncode="1" id="griffecli-check-oneline" +```console exec="1" source="console" result="ansi" returncode="1" id="griffe-check-oneline" $ export FORCE_COLOR=1 # markdown-exec: hide -$ griffecli check griffe -ssrc -b0.46.0 -a0.45.0 +$ griffe check griffe -ssrc -b0.46.0 -a0.45.0 ``` [](){#format-verbose} @@ -655,11 +655,11 @@ $ griffecli check griffe -ssrc -b0.46.0 -a0.45.0 - **CLI**: `-f verbose` / `-v` - **API**: `check(..., style="verbose")` / `check(..., style=ExplanationStyle.VERBOSE)` / `check(..., verbose=True)` -Depending on the detected breakages, the lines might be hard to read (being too compact), so `griffecli check` also accepts a `--verbose` or `-v` option to add some space to the output: +Depending on the detected breakages, the lines might be hard to read (being too compact), so `griffe check` also accepts a `--verbose` or `-v` option to add some space to the output: -```console exec="1" source="console" result="ansi" returncode="1" id="griffecli-check-verbose" +```console exec="1" source="console" result="ansi" returncode="1" id="griffe-check-verbose" $ export FORCE_COLOR=1 # markdown-exec: hide -$ griffecli check griffe -ssrc -b0.46.0 -a0.45.0 --verbose +$ griffe check griffe -ssrc -b0.46.0 -a0.45.0 --verbose ``` [](){#format-markdown} @@ -672,26 +672,26 @@ $ griffecli check griffe -ssrc -b0.46.0 -a0.45.0 --verbose The Markdown format is adapted for changelogs. It doesn't show the file and line number, and instead prints out the complete path of your API objects. With a bit of automation, you will be able to automatically insert a summary of breaking changes in your changelog entries. ```md exec="1" source="tabbed-left" tabs="Output|Result" -- `griffelib.loader.GriffeLoader.resolve_aliases(only_exported)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.loader.GriffeLoader.resolve_aliases(only_exported)`: *Parameter default was changed*: `True` -> `None` -- `griffelib.loader.GriffeLoader.resolve_aliases(only_known_modules)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.loader.GriffeLoader.resolve_aliases(only_known_modules)`: *Parameter default was changed*: `True` -> `None` -- `griffelib.loader.GriffeLoader.resolve_aliases(max_iterations)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.loader.GriffeLoader.resolve_module_aliases(only_exported)`: *Parameter was removed* -- `griffelib.loader.GriffeLoader.resolve_module_aliases(only_known_modules)`: *Parameter was removed* -- `griffelib.git.tmp_worktree(commit)`: *Parameter was removed* -- `griffelib.git.tmp_worktree(repo)`: *Positional parameter was moved*: position: from 2 to 1 (-1) -- `griffelib.git.load_git(commit)`: *Parameter was removed* -- `griffelib.git.load_git(repo)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.git.load_git(submodules)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.git.load_git(try_relative_path)`: *Parameter was removed* -- `griffelib.git.load_git(extensions)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.git.load_git(search_paths)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.git.load_git(docstring_parser)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.git.load_git(docstring_options)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.git.load_git(lines_collection)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.git.load_git(modules_collection)`: *Parameter kind was changed*: positional or keyword -> keyword-only -- `griffelib.git.load_git(allow_inspection)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.loader.GriffeLoader.resolve_aliases(only_exported)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.loader.GriffeLoader.resolve_aliases(only_exported)`: *Parameter default was changed*: `True` -> `None` +- `griffe.loader.GriffeLoader.resolve_aliases(only_known_modules)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.loader.GriffeLoader.resolve_aliases(only_known_modules)`: *Parameter default was changed*: `True` -> `None` +- `griffe.loader.GriffeLoader.resolve_aliases(max_iterations)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.loader.GriffeLoader.resolve_module_aliases(only_exported)`: *Parameter was removed* +- `griffe.loader.GriffeLoader.resolve_module_aliases(only_known_modules)`: *Parameter was removed* +- `griffe.git.tmp_worktree(commit)`: *Parameter was removed* +- `griffe.git.tmp_worktree(repo)`: *Positional parameter was moved*: position: from 2 to 1 (-1) +- `griffe.git.load_git(commit)`: *Parameter was removed* +- `griffe.git.load_git(repo)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.git.load_git(submodules)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.git.load_git(try_relative_path)`: *Parameter was removed* +- `griffe.git.load_git(extensions)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.git.load_git(search_paths)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.git.load_git(docstring_parser)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.git.load_git(docstring_options)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.git.load_git(lines_collection)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.git.load_git(modules_collection)`: *Parameter kind was changed*: positional or keyword -> keyword-only +- `griffe.git.load_git(allow_inspection)`: *Parameter kind was changed*: positional or keyword -> keyword-only ``` [](){#format-github} @@ -701,7 +701,7 @@ The Markdown format is adapted for changelogs. It doesn't show the file and line - **CLI**: `-f github` - **API**: `check(..., style="github")` / `check(..., style=ExplanationStyle.GITHUB)` -When running `griffecli check` in CI, you can enable GitHub's annotations thanks to the GitHub output style. Annotations are displayed on specific lines of code. They are visible in the Checks tab. When you create an annotation for a file that is part of the pull request, the annotations are also shown in the Files changed tab. +When running `griffe check` in CI, you can enable GitHub's annotations thanks to the GitHub output style. Annotations are displayed on specific lines of code. They are visible in the Checks tab. When you create an annotation for a file that is part of the pull request, the annotations are also shown in the Files changed tab. /// tab | Files changed tab ![gha_annotations_2](../../img/gha_annotations_2.png) @@ -712,12 +712,12 @@ When running `griffecli check` in CI, you can enable GitHub's annotations thanks /// ```console -% python -m griffecli check -fgithub -ssrc griffe -::warning file=packages/griffe/src/griffe/finder.py,line=58,title=Package.name::Attribute value was changed: `name` -> unset -::warning file=packages/griffe/src/griffe/finder.py,line=60,title=Package.path::Attribute value was changed: `path` -> unset -::warning file=packages/griffe/src/griffe/finder.py,line=62,title=Package.stubs::Attribute value was changed: `stubs` -> `None` -::warning file=packages/griffe/src/griffe/finder.py,line=75,title=NamespacePackage.name::Attribute value was changed: `name` -> unset -::warning file=packages/griffe/src/griffe/finder.py,line=77,title=NamespacePackage.path::Attribute value was changed: `path` -> unset +% python -m griffe check -fgithub -ssrc griffe +::warning file=src/griffe/finder.py,line=58,title=Package.name::Attribute value was changed: `name` -> unset +::warning file=src/griffe/finder.py,line=60,title=Package.path::Attribute value was changed: `path` -> unset +::warning file=src/griffe/finder.py,line=62,title=Package.stubs::Attribute value was changed: `stubs` -> `None` +::warning file=src/griffe/finder.py,line=75,title=NamespacePackage.name::Attribute value was changed: `name` -> unset +::warning file=src/griffe/finder.py,line=77,title=NamespacePackage.path::Attribute value was changed: `path` -> unset ``` ## Next steps diff --git a/docs/guide/users/extending.md b/docs/guide/users/extending.md index 1f9dd1917..9aa408731 100644 --- a/docs/guide/users/extending.md +++ b/docs/guide/users/extending.md @@ -28,11 +28,11 @@ To specify options in the JSON form, use a dictionary instead of a string: the d Some examples: ```bash -griffecli dump griffe -e pydantic,scripts/exts.py:DynamicDocstrings,griffe_attrs +griffe dump griffe -e pydantic,scripts/exts.py:DynamicDocstrings,griffe_attrs ``` ```bash -griffecli check --search src griffe -e '[ +griffe check --search src griffe -e '[ {"pydantic": {"schema": true}}, { "scripts/exts.py:DynamicDocstrings": { @@ -47,9 +47,9 @@ In the above two examples, `pydantic` would be a built-in extension, `scripts/ex ### Programmatically -Within Python code, extensions can be specified with the `extensions` parameter of the [`GriffeLoader` class][griffelib.GriffeLoader] or [`load` function][griffelib.load]. +Within Python code, extensions can be specified with the `extensions` parameter of the [`GriffeLoader` class][griffe.GriffeLoader] or [`load` function][griffe.load]. -The parameter accepts an instance of the [`Extensions` class][griffelib.Extensions]. Such an instance is created with the help of the [`load_extensions` function][griffelib.load_extensions], which itself accepts a list of strings, dictionaries, extension classes and extension instances. +The parameter accepts an instance of the [`Extensions` class][griffe.Extensions]. Such an instance is created with the help of the [`load_extensions` function][griffe.load_extensions], which itself accepts a list of strings, dictionaries, extension classes and extension instances. Strings and dictionaries are used the same way as [on the command-line](#on-the-command-line). Extension instances are used as such, and extension classes are instantiated without any options. @@ -60,7 +60,7 @@ import griffe from mypackage.extensions import ThisExtension, ThisOtherExtension -extensions = griffelib.load_extensions( +extensions = griffe.load_extensions( {"pydantic": {"schema": true}}, {"scripts/exts.py:DynamicDocstrings": {"paths": ["mypkg.mymod.myobj"]}}, "griffe_attrs", @@ -68,7 +68,7 @@ extensions = griffelib.load_extensions( ThisOtherExtension, ) -data = griffelib.load("mypackage", extensions=extensions) +data = griffe.load("mypackage", extensions=extensions) ``` ### In MkDocs @@ -88,7 +88,7 @@ plugins: - griffe_attrs ``` -The `extensions` key accepts a list that is passed to the [`load_extensions` function][griffelib.load_extensions]. See [how to use extensions programmatically](#programmatically) to learn more. +The `extensions` key accepts a list that is passed to the [`load_extensions` function][griffe.load_extensions]. See [how to use extensions programmatically](#programmatically) to learn more. ## Writing extensions @@ -100,9 +100,9 @@ To extract information from your Python sources, Griffe tries to build Abstract If the source code is not available (the modules are built-in or compiled), Griffe imports the modules and builds object trees instead. -Griffe then follows the [Visitor pattern](https://www.wikiwand.com/en/Visitor_pattern) to walk the tree and extract information. For ASTs, Griffe uses its [Visitor agent][griffelib.Visitor] and for object trees, it uses its [Inspector agent][griffelib.Inspector]. +Griffe then follows the [Visitor pattern](https://www.wikiwand.com/en/Visitor_pattern) to walk the tree and extract information. For ASTs, Griffe uses its [Visitor agent][griffe.Visitor] and for object trees, it uses its [Inspector agent][griffe.Inspector]. -Sometimes during the walk through the source or runtime objects, both the visitor and inspector agents will trigger events, called **analysis events**. These events can be hooked on by extensions to alter or enhance Griffe's behavior. Some hooks will be passed just the current node being visited, others will be passed both the node and an instance of an [Object][griffelib.Object] subclass, such as a [Module][griffelib.Module], a [Class][griffelib.Class], a [Function][griffelib.Function], an [Attribute][griffelib.Attribute], or a [Type Alias][griffelib.TypeAlias]. Extensions will therefore be able to modify these instances. +Sometimes during the walk through the source or runtime objects, both the visitor and inspector agents will trigger events, called **analysis events**. These events can be hooked on by extensions to alter or enhance Griffe's behavior. Some hooks will be passed just the current node being visited, others will be passed both the node and an instance of an [Object][griffe.Object] subclass, such as a [Module][griffe.Module], a [Class][griffe.Class], a [Function][griffe.Function], an [Attribute][griffe.Attribute], or a [Type Alias][griffe.TypeAlias]. Extensions will therefore be able to modify these instances. Once the Griffe tree for a given package has been fully constructed, Griffe will trigger a second set of events, called **load events**, by walking the tree again. **It is safer to use load events as they are triggered only once data is complete for a given package**, contrary to the analysis events which are triggered *while the Griffe tree is still being built*. @@ -114,7 +114,7 @@ M(Module definition) --- C(Class definition) & F(Function definition) C --- m(Function definition) & A(Variable assignment) ``` -The following flow chart shows an example of an object tree inspection. The tree is simplified as well: [many more types of objects are handled][griffelib.ObjectKind]. +The following flow chart shows an example of an object tree inspection. The tree is simplified as well: [many more types of objects are handled][griffe.ObjectKind]. ```mermaid flowchart TB @@ -125,9 +125,9 @@ C --- m(Method) & A(Attribute) For a more concrete example, let say that we visit (or inspect) an AST (or object tree) for a given module, and that this module contains a single class, which itself contains a single method: - the agent (visitor or inspector) will walk through the tree by starting with the module node -- it will instantiate a [Module][griffelib.Module], then walk through its members, continuing with the class node -- it will instantiate a [Class][griffelib.Class], then walk through its members, continuing with the function node -- it will instantiate a [Function][griffelib.Function] +- it will instantiate a [Module][griffe.Module], then walk through its members, continuing with the class node +- it will instantiate a [Class][griffe.Class], then walk through its members, continuing with the function node +- it will instantiate a [Function][griffe.Function] - then it will go back up and finish walking since there are no more nodes to walk through Every time the agent enters a node, creates an object instance, or finishes handling members of an object, it will trigger an event. @@ -137,21 +137,21 @@ The flow of events is drawn in the following flowchart: ```mermaid flowchart TB visit_mod{{enter module node}} -event_mod_node{{"on_node event
on_module_node event"}} +event_mod_node{{"on_node event
on_module_node event"}} create_mod{{create module instance}} -event_mod_instance{{"on_instance event
on_module_instance event"}} +event_mod_instance{{"on_instance event
on_module_instance event"}} visit_mod_members{{visit module members}} visit_cls{{enter class node}} -event_cls_node{{"on_node event
on_class_node event"}} +event_cls_node{{"on_node event
on_class_node event"}} create_cls{{create class instance}} -event_cls_instance{{"on_instance event
on_class_instance event"}} +event_cls_instance{{"on_instance event
on_class_instance event"}} visit_cls_members{{visit class members}} visit_func{{enter func node}} -event_func_node{{"on_node event
on_function_node event"}} +event_func_node{{"on_node event
on_function_node event"}} create_func{{create function instance}} -event_func_instance{{"on_instance event
on_function_instance event"}} -event_cls_members{{"on_members event
on_class_members event"}} -event_mod_members{{"on_members event
on_module_members event"}} +event_func_instance{{"on_instance event
on_function_instance event"}} +event_cls_members{{"on_members event
on_class_members event"}} +event_mod_members{{"on_members event
on_module_members event"}} start{start} --> visit_mod visit_mod --> event_mod_node @@ -198,17 +198,17 @@ There are two kinds of events in Griffe: [**load events**](#load-events) and [** There is 1 generic **load event**: -- [`on_object`][griffelib.Extension.on_object]: The "on object" event is triggered on any kind of object (except for aliases and packages, so modules, classes, functions, attributes and type aliases), once the tree for the object's package has been fully constructed. +- [`on_object`][griffe.Extension.on_object]: The "on object" event is triggered on any kind of object (except for aliases and packages, so modules, classes, functions, attributes and type aliases), once the tree for the object's package has been fully constructed. There are also specific **load events** for each object kind: -- [`on_module`][griffelib.Extension.on_module]: The "on module" event is triggered on modules. -- [`on_class`][griffelib.Extension.on_class]: The "on class" event is triggered on classes. -- [`on_function`][griffelib.Extension.on_function]: The "on function" event is triggered on functions. -- [`on_attribute`][griffelib.Extension.on_attribute]: The "on attribute" event is triggered on attributes. -- [`on_type_alias`][griffelib.Extension.on_type_alias]: The "on type alias" event is triggered on type aliases. -- [`on_alias`][griffelib.Extension.on_alias]: The "on alias" event is triggered on aliases (imported/inherited objects). -- [`on_package`][griffelib.Extension.on_package]: The "on package" event is triggered on top-level modules (packages) only. +- [`on_module`][griffe.Extension.on_module]: The "on module" event is triggered on modules. +- [`on_class`][griffe.Extension.on_class]: The "on class" event is triggered on classes. +- [`on_function`][griffe.Extension.on_function]: The "on function" event is triggered on functions. +- [`on_attribute`][griffe.Extension.on_attribute]: The "on attribute" event is triggered on attributes. +- [`on_type_alias`][griffe.Extension.on_type_alias]: The "on type alias" event is triggered on type aliases. +- [`on_alias`][griffe.Extension.on_alias]: The "on alias" event is triggered on aliases (imported/inherited objects). +- [`on_package`][griffe.Extension.on_package]: The "on package" event is triggered on top-level modules (packages) only. #### Analysis events @@ -216,46 +216,46 @@ There are also specific **load events** for each object kind: There are 3 generic **analysis events**: -- [`on_node`][griffelib.Extension.on_node]: The "on node" events are triggered when the agent (visitor or inspector) starts handling a node in the tree (AST or object tree). -- [`on_instance`][griffelib.Extension.on_instance]: The "on instance" events are triggered when the agent just created an instance of [Module][griffelib.Module], [Class][griffelib.Class], [Function][griffelib.Function], [Attribute][griffelib.Attribute], or [Type Alias][griffelib.TypeAlias], and added it as a member of its parent. The "on instance" event is **not** triggered when an [Alias][griffelib.Alias] is created. -- [`on_members`][griffelib.Extension.on_members]: The "on members" events are triggered when the agent just finished handling all the members of an object. Functions, attributes and type aliases do not have members, so there are no "on members" events for these kinds. +- [`on_node`][griffe.Extension.on_node]: The "on node" events are triggered when the agent (visitor or inspector) starts handling a node in the tree (AST or object tree). +- [`on_instance`][griffe.Extension.on_instance]: The "on instance" events are triggered when the agent just created an instance of [Module][griffe.Module], [Class][griffe.Class], [Function][griffe.Function], [Attribute][griffe.Attribute], or [Type Alias][griffe.TypeAlias], and added it as a member of its parent. The "on instance" event is **not** triggered when an [Alias][griffe.Alias] is created. +- [`on_members`][griffe.Extension.on_members]: The "on members" events are triggered when the agent just finished handling all the members of an object. Functions, attributes and type aliases do not have members, so there are no "on members" events for these kinds. There are also specific **analysis events** for each object kind: -- [`on_module_node`][griffelib.Extension.on_module_node] -- [`on_module_instance`][griffelib.Extension.on_module_instance] -- [`on_module_members`][griffelib.Extension.on_module_members] -- [`on_class_node`][griffelib.Extension.on_class_node] -- [`on_class_instance`][griffelib.Extension.on_class_instance] -- [`on_class_members`][griffelib.Extension.on_class_members] -- [`on_function_node`][griffelib.Extension.on_function_node] -- [`on_function_instance`][griffelib.Extension.on_function_instance] -- [`on_attribute_node`][griffelib.Extension.on_attribute_node] -- [`on_attribute_instance`][griffelib.Extension.on_attribute_instance] -- [`on_type_alias_node`][griffelib.Extension.on_type_alias_node] -- [`on_type_alias_instance`][griffelib.Extension.on_type_alias_instance] -- [`on_alias_instance`][griffelib.Extension.on_alias_instance] +- [`on_module_node`][griffe.Extension.on_module_node] +- [`on_module_instance`][griffe.Extension.on_module_instance] +- [`on_module_members`][griffe.Extension.on_module_members] +- [`on_class_node`][griffe.Extension.on_class_node] +- [`on_class_instance`][griffe.Extension.on_class_instance] +- [`on_class_members`][griffe.Extension.on_class_members] +- [`on_function_node`][griffe.Extension.on_function_node] +- [`on_function_instance`][griffe.Extension.on_function_instance] +- [`on_attribute_node`][griffe.Extension.on_attribute_node] +- [`on_attribute_instance`][griffe.Extension.on_attribute_instance] +- [`on_type_alias_node`][griffe.Extension.on_type_alias_node] +- [`on_type_alias_instance`][griffe.Extension.on_type_alias_instance] +- [`on_alias_instance`][griffe.Extension.on_alias_instance] #### Extensions and hooks -**Extensions** are classes that inherit from [Griffe's Extension base class][griffelib.Extension] and define some hooks as methods: +**Extensions** are classes that inherit from [Griffe's Extension base class][griffe.Extension] and define some hooks as methods: ```python import griffe -class MyExtension(griffelib.Extension): +class MyExtension(griffe.Extension): def on_object( self, *, - obj: griffelib.Object, - loader: griffelib.GriffeLoader, + obj: griffe.Object, + loader: griffe.GriffeLoader, **kwargs, ) -> None: """Do something with `obj`.""" ``` -Hooks are always defined as methods of a class inheriting from [Extension][griffelib.Extension], never as standalone functions. IDEs should autocomplete the signature when you start typing `def` followed by a hook name. +Hooks are always defined as methods of a class inheriting from [Extension][griffe.Extension], never as standalone functions. IDEs should autocomplete the signature when you start typing `def` followed by a hook name. Since hooks are declared in a class, feel free to also declare state variables (or any other variable) in the `__init__` method: @@ -273,8 +273,8 @@ class MyExtension(Extension): def on_object( self, *, - obj: griffelib.Object, - loader: griffelib.GriffeLoader, + obj: griffe.Object, + loader: griffe.GriffeLoader, **kwargs, ) -> None: """Do something with `obj`.""" @@ -292,8 +292,8 @@ To support static analysis, dynamic analysis, or both in your load events, you c import griffe -class MyExtension(griffelib.Extension): - def on_object(self, *, obj: griffelib.Object, **kwargs) -> None: +class MyExtension(griffe.Extension): + def on_object(self, *, obj: griffe.Object, **kwargs) -> None: """Do something with `obj`.""" if obj.analysis == "static": ... # Apply logic for static analysis. @@ -307,10 +307,10 @@ class MyExtension(griffelib.Extension): Extensions provide basic functionality to help you visit trees during analysis of the code: -- [`visit`][griffelib.Extension.visit]: call `self.visit(node)` to start visiting an abstract syntax tree. -- [`generic_visit`][griffelib.Extension.generic_visit]: call `self.generic_visit(node)` to visit each subnode of a given node. -- [`inspect`][griffelib.Extension.inspect]: call `self.inspect(node)` to start visiting an object tree. Nodes contain references to the runtime objects, see [`ObjectNode`][griffelib.ObjectNode]. -- [`generic_inspect`][griffelib.Extension.generic_inspect]: call `self.generic_inspect(node)` to visit each subnode of a given node. +- [`visit`][griffe.Extension.visit]: call `self.visit(node)` to start visiting an abstract syntax tree. +- [`generic_visit`][griffe.Extension.generic_visit]: call `self.generic_visit(node)` to visit each subnode of a given node. +- [`inspect`][griffe.Extension.inspect]: call `self.inspect(node)` to start visiting an object tree. Nodes contain references to the runtime objects, see [`ObjectNode`][griffe.ObjectNode]. +- [`generic_inspect`][griffe.Extension.generic_inspect]: call `self.generic_inspect(node)` to visit each subnode of a given node. Calling `self.visit(node)` or `self.inspect(node)` will do nothing unless you actually implement methods that handle specific types of nodes: @@ -333,7 +333,7 @@ Calling `self.visit(node)` or `self.inspect(node)` will do nothing unless you ac See the [list of existing AST classes](#ast-nodes) to learn what method you can implement. -- for object trees, methods must be named `inspect_`, where `` is replaced with the string value of the node's kind. The different kinds are listed in the [`ObjectKind`][griffelib.ObjectKind] enumeration. For example, to allow inspecting coroutine nodes, you must implement the `inspect_coroutine` method: +- for object trees, methods must be named `inspect_`, where `` is replaced with the string value of the node's kind. The different kinds are listed in the [`ObjectKind`][griffe.ObjectKind] enumeration. For example, to allow inspecting coroutine nodes, you must implement the `inspect_coroutine` method: ```python from griffe import Extension, ObjectNode @@ -349,26 +349,26 @@ Calling `self.visit(node)` or `self.inspect(node)` will do nothing unless you ac ### Triggering other extensions -If your extension creates new objects, you might want to trigger the other enabled extensions on these object instances. To do this you can use [`agent.extensions.call`][griffelib.Extensions.call]: +If your extension creates new objects, you might want to trigger the other enabled extensions on these object instances. To do this you can use [`agent.extensions.call`][griffe.Extensions.call]: ```python import ast import griffe -class MyExtension(griffelib.Extension): +class MyExtension(griffe.Extension): # Example from within a load event: - def on_package(self, *, pkg: griffelib.Module, loader: griffelib.GriffeLoader, **kwargs) -> None: + def on_package(self, *, pkg: griffe.Module, loader: griffe.GriffeLoader, **kwargs) -> None: # New object created for whatever reason. - function = griffelib.Function(...) + function = griffe.Function(...) # Trigger other extensions. loader.extensions.call("on_function", func=function, loader=loader) # Example from within an analysis event: - def on_node(self, *, node: ast.AST | griffelib.ObjectNode, agent: griffelib.Visitor | griffelib.Inspector, **kwargs) -> None: + def on_node(self, *, node: ast.AST | griffe.ObjectNode, agent: griffe.Visitor | griffe.Inspector, **kwargs) -> None: # New object created for whatever reason. - function = griffelib.Function(...) + function = griffe.Function(...) # Trigger other extensions. agent.extensions.call("on_function_instance", node=node, agent=agent, func=function, **kwargs) @@ -384,8 +384,8 @@ import griffe self_namespace = "my_extension" -class MyExtension(griffelib.Extension): - def on_object(self, obj: griffelib.Object, **kwargs) -> None: +class MyExtension(griffe.Extension): + def on_object(self, obj: griffe.Object, **kwargs) -> None: obj.extra[self_namespace]["some_key"] = "some_value" ``` @@ -398,8 +398,8 @@ self_namespace = "my_extension" mkdocstrings_namespace = "mkdocstrings" -class MyExtension(griffelib.Extension): - def on_class(self, cls: griffelib.Class, **kwargs) -> None: +class MyExtension(griffe.Extension): + def on_class(self, cls: griffe.Class, **kwargs) -> None: cls.extra[mkdocstrings_namespace]["template"] = "my_custom_template" ``` @@ -413,13 +413,13 @@ Extensions can be made to support options. These options can then be passed from import griffe -class MyExtension(griffelib.Extension): +class MyExtension(griffe.Extension): def __init__(self, option1: str, option2: bool = False) -> None: super().__init__() self.option1 = option1 self.option2 = option2 - def on_attribute(self, attr: griffelib.Attribute, **kwargs) -> None: + def on_attribute(self, attr: griffe.Attribute, **kwargs) -> None: if self.option2: ... # Do something. ``` @@ -431,11 +431,11 @@ To better integrate with Griffe and other tools in the ecosystem (notably MkDocs ```python import griffe -logger = griffelib.get_logger(__name__) +logger = griffe.get_logger(__name__) -class MyExtension(griffelib.Extension): - def on_module(self, mod: griffelib.Module, **kwargs) -> None: +class MyExtension(griffe.Extension): + def on_module(self, mod: griffe.Module, **kwargs) -> None: logger.info("Doing some work on module %s", mod.path) ``` @@ -459,17 +459,17 @@ import ast import inspect import griffe -logger = griffelib.get_logger(__name__) +logger = griffe.get_logger(__name__) -class DynamicDocstrings(griffelib.Extension): +class DynamicDocstrings(griffe.Extension): def __init__(self, object_paths: list[str] | None = None) -> None: self.object_paths = object_paths def on_object( self, - obj: griffelib.Object, - loader: griffelib.GriffeLoader, + obj: griffe.Object, + loader: griffe.GriffeLoader, **kwargs, ) -> None: if obj.analysis == "dynamic": @@ -480,7 +480,7 @@ class DynamicDocstrings(griffelib.Extension): # Import object to get its evaluated docstring. try: - runtime_obj = griffelib.dynamic_import(obj.path) + runtime_obj = griffe.dynamic_import(obj.path) docstring = runtime_obj.__doc__ except ImportError: logger.debug(f"Could not get dynamic docstring for {obj.path}") @@ -494,7 +494,7 @@ class DynamicDocstrings(griffelib.Extension): if obj.docstring: obj.docstring.value = docstring else: - obj.docstring = griffelib.Docstring( + obj.docstring = griffe.Docstring( docstring, parent=obj, docstring_parser=loader.docstring_parser, diff --git a/docs/guide/users/how-to/parse-docstrings.md b/docs/guide/users/how-to/parse-docstrings.md index 70ebb6c05..fef3d12ee 100644 --- a/docs/guide/users/how-to/parse-docstrings.md +++ b/docs/guide/users/how-to/parse-docstrings.md @@ -1,6 +1,6 @@ # Using Griffe as a docstring-parsing library -You can use Griffe to parse arbitrary docstrings. You don't have to load anything through the Griffe loader. You just need to import the [`Docstring`][griffelib.Docstring] class. Then you can build a `Docstring` instance and call its `parse` method, choosing the parsing-style to use: +You can use Griffe to parse arbitrary docstrings. You don't have to load anything through the Griffe loader. You just need to import the [`Docstring`][griffe.Docstring] class. Then you can build a `Docstring` instance and call its `parse` method, choosing the parsing-style to use: ```python from griffe import Docstring diff --git a/docs/guide/users/how-to/selectively-inspect.md b/docs/guide/users/how-to/selectively-inspect.md index cfb0bf594..87be96210 100644 --- a/docs/guide/users/how-to/selectively-inspect.md +++ b/docs/guide/users/how-to/selectively-inspect.md @@ -26,7 +26,7 @@ Start by creating an extensions module (a simple Python file) somewhere in your import griffe -class InspectSpecificObjects(griffelib.Extension): +class InspectSpecificObjects(griffe.Extension): """An extension to inspect just a few specific objects.""" ``` @@ -36,7 +36,7 @@ Make it accept configuration options by declaring an `__init__` method: import griffe -class InspectSpecificObjects(griffelib.Extension): +class InspectSpecificObjects(griffe.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: @@ -53,17 +53,17 @@ Now that our extension accepts options, we implement its core functionality. We import griffe -class InspectSpecificObjects(griffelib.Extension): +class InspectSpecificObjects(griffe.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: ... ``` -Check out the [available hooks][griffelib.Extension] to see if there more appropriate hooks for your needs. +Check out the [available hooks][griffe.Extension] to see if there more appropriate hooks for your needs. Lets now use our configuration option to decide whether to do something or skip: @@ -71,13 +71,13 @@ Lets now use our configuration option to decide whether to do something or skip: import griffe -class InspectSpecificObjects(griffelib.Extension): +class InspectSpecificObjects(griffe.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: if obj.path not in self.objects: return ``` @@ -87,21 +87,21 @@ Now we know that only the objects we're interested in will be handled, so lets h ```python hl_lines="3 16-20" import griffe -logger = griffelib.get_logger("griffe_inspect_specific_objects") # (1)! +logger = griffe.get_logger("griffe_inspect_specific_objects") # (1)! -class InspectSpecificObjects(griffelib.Extension): +class InspectSpecificObjects(griffe.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: if obj.path not in self.objects: return try: - runtime_obj = griffelib.dynamic_import(obj.path) + runtime_obj = griffe.dynamic_import(obj.path) except ImportError as error: logger.warning(f"Could not import {obj.path}: {error}") # (2)! return @@ -117,21 +117,21 @@ For example, we could use the runtime object's `__doc__` attribute, which could ```python hl_lines="22-25" import griffe -logger = griffelib.get_logger("griffe_inspect_specific_objects") +logger = griffe.get_logger("griffe_inspect_specific_objects") -class InspectSpecificObjects(griffelib.Extension): +class InspectSpecificObjects(griffe.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: if obj.path not in self.objects: return try: - runtime_obj = griffelib.dynamic_import(obj.path) + runtime_obj = griffe.dynamic_import(obj.path) except ImportError as error: logger.warning(f"Could not import {obj.path}: {error}") return @@ -139,7 +139,7 @@ class InspectSpecificObjects(griffelib.Extension): if obj.docstring: obj.docstring.value = runtime_obj.__doc__ else: - obj.docstring = griffelib.Docstring(runtime_obj.__doc__) + obj.docstring = griffe.Docstring(runtime_obj.__doc__) ``` Or we could alter the Griffe object parameters in case of functions, which could have been modified by a signature-changing decorator: @@ -148,21 +148,21 @@ Or we could alter the Griffe object parameters in case of functions, which could import inspect import griffe -logger = griffelib.get_logger("griffe_inspect_specific_objects") +logger = griffe.get_logger("griffe_inspect_specific_objects") -class InspectSpecificObjects(griffelib.Extension): +class InspectSpecificObjects(griffe.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: if obj.path not in self.objects: return try: - runtime_obj = griffelib.dynamic_import(obj.path) + runtime_obj = griffe.dynamic_import(obj.path) except ImportError as error: logger.warning(f"Could not import {obj.path}: {error}") return @@ -181,17 +181,17 @@ We could also entirely replace the Griffe object obtained from static analysis b import griffe -class InspectSpecificObjects(griffelib.Extension): +class InspectSpecificObjects(griffe.Extension): """An extension to inspect just a few specific objects.""" def __init__(self, objects: list[str]) -> None: self.objects = objects - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: if obj.path not in self.objects: return - inspected_module = griffelib.inspect(obj.module.path, filepath=obj.filepath) + inspected_module = griffe.inspect(obj.module.path, filepath=obj.filepath) obj.parent.set_member(obj.name, inspected_module[obj.name]) # (1)! ``` diff --git a/docs/guide/users/how-to/set-docstring-styles.md b/docs/guide/users/how-to/set-docstring-styles.md index ddfb4794d..5c03e5cfd 100644 --- a/docs/guide/users/how-to/set-docstring-styles.md +++ b/docs/guide/users/how-to/set-docstring-styles.md @@ -44,11 +44,11 @@ import re import griffe -class ApplyDocstringStyle(griffelib.Extension): +class ApplyDocstringStyle(griffe.Extension): def __init__(self, regex: str = "") -> None: self.regex = re.compile(regex) - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: if obj.docstring: if match := self.regex.search(obj.docstring.value): obj.docstring.parser = match.group(1) @@ -73,11 +73,11 @@ import re import griffe -class ApplyDocstringStyle(griffelib.Extension): +class ApplyDocstringStyle(griffe.Extension): def __init__(self, regex: str = ".*# style: (google|numpy|sphinx)$") -> None: self.regex = re.compile(regex) - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: if obj.docstring: if match := self.regex.search(obj.docstring.source): obj.docstring.parser = match.group(1) @@ -91,7 +91,7 @@ Finally, you could decide to map a list of objects to the docstring style they s import griffe from fnmatch import fnmatch -class ApplyDocstringStyle(griffelib.Extension): +class ApplyDocstringStyle(griffe.Extension): def __init__(self, config: dict[str, str]): self.instances = {} self.globs = {} @@ -101,7 +101,7 @@ class ApplyDocstringStyle(griffelib.Extension): else: self.instances[key] = value - def on_instance(self, *, obj: griffelib.Object, **kwargs) -> None: + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: if obj.path in self.instances: if obj.docstring: obj.docsring.parser = self.instances[obj.path] diff --git a/docs/guide/users/how-to/set-git-info.md b/docs/guide/users/how-to/set-git-info.md index 9c827940f..5fde20b4a 100644 --- a/docs/guide/users/how-to/set-git-info.md +++ b/docs/guide/users/how-to/set-git-info.md @@ -12,7 +12,7 @@ Start by creating an extensions module (a simple Python file) somewhere in your import griffe -class GitInfo(griffelib.Extension): +class GitInfo(griffe.Extension): """An extension to set the right Git information.""" ``` @@ -25,12 +25,12 @@ from typing import Any import griffe -class GitInfo(griffelib.Extension): +class GitInfo(griffe.Extension): """An extension to set the right Git information.""" - def on_package(self, *, pkg: griffelib.Module, **kwargs: Any) -> None: + def on_package(self, *, pkg: griffe.Module, **kwargs: Any) -> None: if pkg.name == "my_package_name": - pkg.git_info = griffelib.GitInfo( + pkg.git_info = griffe.GitInfo( repository=Path("/path/to/this/package/local/repository"), service="forgejo", remote_url="https://myhostedforge.mydomain.com/myaccount/myproject", @@ -51,7 +51,7 @@ We could also reuse properties that Griffe found: ```python # Here we reuse `repository` and `commit_hash` while overriding only `service` and `remote_url`. -pkg.git_info = griffelib.GitInfo( +pkg.git_info = griffe.GitInfo( repository=pkg.git_info.repository, service="forgejo", remote_url="https://myhostedforge.mydomain.com/myaccount/myproject", @@ -74,7 +74,7 @@ Start by creating an extensions module (a simple Python file) somewhere in your import griffe -class SourceLinks(griffelib.Extension): +class SourceLinks(griffe.Extension): """An extension to set the right source links.""" ``` @@ -87,10 +87,10 @@ from typing import Any import griffe -class SourceLinks(griffelib.Extension): +class SourceLinks(griffe.Extension): """An extension to set the right source links.""" - def on_object(self, *, obj: griffelib.Object, **kwargs: Any) -> None: + def on_object(self, *, obj: griffe.Object, **kwargs: Any) -> None: if obj.path == "my_package_name.my_function": obj.source_link = "https://myhostedforge.mydomain.com/myaccount/myproject/src/commit/77f928aeab857cb45564462a4f849c2df2cca99a/src/lib.rs#L35-L48" # Handle any other object you want. @@ -107,10 +107,10 @@ from typing import Any import griffe -class SourceLinks(griffelib.Extension): +class SourceLinks(griffe.Extension): """An extension to set the right source links.""" - def on_object(self, *, obj: griffelib.Object, **kwargs: Any) -> None: + def on_object(self, *, obj: griffe.Object, **kwargs: Any) -> None: if obj.path == "my_package_name.my_function": obj.source_link = obj.git_info.get_source_link( filepath="src/lib.rs", diff --git a/docs/guide/users/how-to/support-decorators.md b/docs/guide/users/how-to/support-decorators.md index ffde3455e..b0fe8da5c 100644 --- a/docs/guide/users/how-to/support-decorators.md +++ b/docs/guide/users/how-to/support-decorators.md @@ -24,11 +24,11 @@ Start by creating an extensions module (a simple Python file) somewhere in your import griffe -class MyDecorator(griffelib.Extension): +class MyDecorator(griffe.Extension): """An extension to suport my decorator.""" ``` -Now we can declare the [`on_instance`][griffelib.Extension.on_instance] hook, which receives any kind of Griffe object ([`Module`][griffelib.Module], [`Class`][griffelib.Class], [`Function`][griffelib.Function], [`Attribute`][griffelib.Attribute], [`TypeAlias`][griffelib.TypeAlias]), or we could use a kind-specific hook such as [`on_module_instance`][griffelib.Extension.on_module_instance], [`on_class_instance`][griffelib.Extension.on_class_instance], [`on_function_instance`][griffelib.Extension.on_function_instance], [`on_attribute_instance`][griffelib.Extension.on_attribute_instance] and [`on_type_alias_instance`][griffelib.Extension.on_type_alias_instance]. For example, if you know your decorator is only ever used on class declarations, it would make sense to use `on_class_instance`. +Now we can declare the [`on_instance`][griffe.Extension.on_instance] hook, which receives any kind of Griffe object ([`Module`][griffe.Module], [`Class`][griffe.Class], [`Function`][griffe.Function], [`Attribute`][griffe.Attribute], [`TypeAlias`][griffe.TypeAlias]), or we could use a kind-specific hook such as [`on_module_instance`][griffe.Extension.on_module_instance], [`on_class_instance`][griffe.Extension.on_class_instance], [`on_function_instance`][griffe.Extension.on_function_instance], [`on_attribute_instance`][griffe.Extension.on_attribute_instance] and [`on_type_alias_instance`][griffe.Extension.on_type_alias_instance]. For example, if you know your decorator is only ever used on class declarations, it would make sense to use `on_class_instance`. For the example, lets use the `on_function_instance` hook, which receives `Function` instances. @@ -36,10 +36,10 @@ For the example, lets use the `on_function_instance` hook, which receives `Funct import griffe -class MyDecorator(griffelib.Extension): +class MyDecorator(griffe.Extension): """An extension to suport my decorator.""" - def on_function_instance(self, *, func: griffelib.Function, **kwargs) -> None: + def on_function_instance(self, *, func: griffe.Function, **kwargs) -> None: ... ``` @@ -49,13 +49,13 @@ In this hook, we check if our function is decorated with our custom decorator: import griffe -class MyDecorator(griffelib.Extension): +class MyDecorator(griffe.Extension): """An extension to suport my decorator.""" - def on_function_instance(self, *, func: griffelib.Function, **kwargs) -> None: + def on_function_instance(self, *, func: griffe.Function, **kwargs) -> None: for decorator in func.decorators: if decorator.callable_path == "my_package.utils.enhance": ... # Update the function attributes. ``` -Now all that is left to do is to actually write the code that updates the function according to what the decorator is doing. We could update the function's docstring, or its return type, or its parameters: it all depends on your decorator and what it does to the objects it decorates. Check out the [API reference for function objects][griffelib.Function] to see what data this object stores. +Now all that is left to do is to actually write the code that updates the function according to what the decorator is doing. We could update the function's docstring, or its return type, or its parameters: it all depends on your decorator and what it does to the objects it decorates. Check out the [API reference for function objects][griffe.Function] to see what data this object stores. diff --git a/docs/guide/users/loading.md b/docs/guide/users/loading.md index 06a98a040..620917803 100644 --- a/docs/guide/users/loading.md +++ b/docs/guide/users/loading.md @@ -4,12 +4,12 @@ Griffe can load API data from both source code (static analysis) and objects at ## The `load` function -The main interface to load API data is Griffe's [`load`][griffelib.load] function: +The main interface to load API data is Griffe's [`load`][griffe.load] function: ```python import griffe -my_package = griffelib.load("my_package") +my_package = griffe.load("my_package") ``` You can ask to load a specific object rather than a package: @@ -17,7 +17,7 @@ You can ask to load a specific object rather than a package: ```python import griffe -my_method = griffelib.load("my_package.MyClass.my_method") +my_method = griffe.load("my_package.MyClass.my_method") ``` Griffe will load the whole package anyway, but return the specified object directly, so that you don't have to access it manually. To manually access the object representing the method called `my_method`, you would have used the `my_package` variable instantiated before, like this: @@ -33,8 +33,8 @@ Finally, you can even load packages or modules by passing absolute or relative f ```python import griffe -griffelib.load("src/my_package") -griffelib.load("some_script.py") +griffe.load("src/my_package") +griffe.load("some_script.py") ``` In case of ambiguity, you can instruct Griffe to ignore existing relative file paths with `try_relative_paths=False`. For example, when using [the flat layout (in contrast to the src-layout)](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/), your Python package is in the root of the repository. @@ -51,12 +51,12 @@ Here if you ask Griffe to load `my_package`, it will find it as a relative path, ```python import griffe -my_installed_package = griffelib.load("my_package", try_relative_path=False) +my_installed_package = griffe.load("my_package", try_relative_path=False) ``` ## The `GriffeLoader` class -The [`load`][griffelib.load] function is a shortcut for instantiating the [`GriffeLoader`][griffelib.GriffeLoader] class and calling its [`load`][griffelib.GriffeLoader.load] method. Calling the [`load`][griffelib.load] function multiple times will instantiate a new Griffe loader each time. If you care about efficiency, it is better to instantiate the loader yourself and use its `load` method: +The [`load`][griffe.load] function is a shortcut for instantiating the [`GriffeLoader`][griffe.GriffeLoader] class and calling its [`load`][griffe.GriffeLoader.load] method. Calling the [`load`][griffe.load] function multiple times will instantiate a new Griffe loader each time. If you care about efficiency, it is better to instantiate the loader yourself and use its `load` method: ```python import griffe @@ -72,13 +72,13 @@ Reusing the same loader will also help resolving aliases across different packag ## Search paths -To specify in which directories Griffe should search for packages and modules, you can use the `search_paths` parameter on both the [`load` function][griffelib.load] and the [`GriffeLoader` class][griffelib.GriffeLoader]. +To specify in which directories Griffe should search for packages and modules, you can use the `search_paths` parameter on both the [`load` function][griffe.load] and the [`GriffeLoader` class][griffe.GriffeLoader]. === "`load`" ```python import griffe - my_package = griffelib.load("my_package", search_paths=["src"]) + my_package = griffe.load("my_package", search_paths=["src"]) ``` === "`GriffeLoader`" @@ -100,7 +100,7 @@ Griffe always tries first to find sources for the specified object. Then, unless ```python import griffe -my_package = griffelib.load("my_package", force_inspection=True) +my_package = griffe.load("my_package", force_inspection=True) ``` [](){#forcing-dynamic-analysis-not-recommended} @@ -125,10 +125,10 @@ If you want to be careful about what gets executed in the current Python process import griffe # Here Griffe will fall back on dynamic analysis and import `itertools`. -griffelib.load("itertools") +griffe.load("itertools") # While here it will raise `ModuleNotFoundError`. -griffelib.load("itertools", allow_inspection=False) +griffe.load("itertools", allow_inspection=False) ``` ## Alias resolution @@ -138,7 +138,7 @@ griffelib.load("itertools", allow_inspection=False) > > The name "alias" comes from the fact that imported objects can be aliased under a different name: `from X import A as B`. In the case of inherited members, this doesn't really apply, but we reuse the concept for conciseness. > -> An [`Alias`][griffelib.Alias] instance is therefore a pointer to another object. It has its own name, parent, line numbers, and stores the path to the target object. Thanks to this path, we can access the actual target object and all its metadata, such as name, parent, line numbers, docstring, etc.. Obtaining a reference to the target object is what we call "alias resolution". +> An [`Alias`][griffe.Alias] instance is therefore a pointer to another object. It has its own name, parent, line numbers, and stores the path to the target object. Thanks to this path, we can access the actual target object and all its metadata, such as name, parent, line numbers, docstring, etc.. Obtaining a reference to the target object is what we call "alias resolution". > > **To summarize, alias resolution is a post-process task that resolves imports after loading everything.** @@ -171,14 +171,14 @@ When loading this package, `my_package.my_function` will be an alias pointing at ```python import griffe -my_package = griffelib.load("my_package") +my_package = griffe.load("my_package") my_package["my_function"].resolved # False ``` ```python import griffe -my_package = griffelib.load("my_package", resolve_aliases=True) +my_package = griffe.load("my_package", resolve_aliases=True) my_package["my_function"].resolved # True my_package["my_function"].target is my_package["my_module.my_function"] # True ``` @@ -207,7 +207,7 @@ from package1 import X ```pycon >>> import griffe ->>> package2 = griffelib.load("package2", resolve_aliases=True) +>>> package2 = griffe.load("package2", resolve_aliases=True) >>> package2["X"].target_path 'package1.X' >>> package2["X"].resolved @@ -232,17 +232,17 @@ Traceback (most recent call last): self._resolve_target() File "griffe/_internal/dataclasses.py", line 1377, in _resolve_target raise AliasResolutionError(self) from error -griffelib._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) +griffe._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) ``` -As you can see in the interpreter session above, Griffe did not resolve the `X` alias. When we tried to access its target object anyway, it failed with a `KeyError`, which was raised again as an [`AliasResolutionError`][griffelib.AliasResolutionError]. +As you can see in the interpreter session above, Griffe did not resolve the `X` alias. When we tried to access its target object anyway, it failed with a `KeyError`, which was raised again as an [`AliasResolutionError`][griffe.AliasResolutionError]. Lets try again, but this time by loading both packages. ```pycon >>> import griffe ->>> package1 = griffelib.load("package1") # nothing to resolve ->>> package2 = griffelib.load("package2", resolve_aliases=True) +>>> package1 = griffe.load("package1") # nothing to resolve +>>> package2 = griffe.load("package2", resolve_aliases=True) >>> package2["X"].target_path 'package1.X' >>> package2["X"].resolved @@ -250,27 +250,27 @@ False # Hmm? >>> package2["X"].target Traceback (most recent call last): ... -griffelib._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) +griffe._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) ``` The same exception again? What happened here? We loaded both packages, but Griffe still failed to resolve the alias. That is expected; here is the explanation. If you look closely at the first exception traceback, you will see that Griffe searched the target path in `self.modules_collection`. So what is this modules collection? -Each instance of [`GriffeLoader`][griffelib.GriffeLoader] holds a reference to an instance of [`ModulesCollection`][griffelib.ModulesCollection]. If you don't create such a collection manually to pass it to the loader, it will instantiate one itself. All objects loaded with this loader are added to this very modules collection, and gain a reference to it. +Each instance of [`GriffeLoader`][griffe.GriffeLoader] holds a reference to an instance of [`ModulesCollection`][griffe.ModulesCollection]. If you don't create such a collection manually to pass it to the loader, it will instantiate one itself. All objects loaded with this loader are added to this very modules collection, and gain a reference to it. -Since the [`load` function][griffelib.load] is just a shortcut for creating a loader and calling its [`load` method][griffelib.GriffeLoader.load], when we called `griffelib.load(...)` twice, it actually created two distinct collections of modules. When Griffe tried to resolve aliases of `package2`, it looked for `package1` in `package2`'s collection, and couldn't find it. Indeed, `package1` was in another modules collection. +Since the [`load` function][griffe.load] is just a shortcut for creating a loader and calling its [`load` method][griffe.GriffeLoader.load], when we called `griffe.load(...)` twice, it actually created two distinct collections of modules. When Griffe tried to resolve aliases of `package2`, it looked for `package1` in `package2`'s collection, and couldn't find it. Indeed, `package1` was in another modules collection. Therefore, to resolve aliases *across different packages*, these packages must be loaded within the same modules collection. In order to do that, you have a few options: - instantiate a single loader, and use it to load both packages -- create your own modules collection, and pass it to the [`load` function][griffelib.load] each time you call it -- create your own modules collection, and pass it to the different instances of [`GriffeLoader`][griffelib.GriffeLoader] you create +- create your own modules collection, and pass it to the [`load` function][griffe.load] each time you call it +- create your own modules collection, and pass it to the different instances of [`GriffeLoader`][griffe.GriffeLoader] you create === "Same loader" ```pycon >>> import griffe - >>> loader = griffelib.GriffeLoader() + >>> loader = griffe.GriffeLoader() >>> package1 = loader.load("package1") >>> package2 = loader.load("package2") >>> loader.resolve_aliases() @@ -283,9 +283,9 @@ Therefore, to resolve aliases *across different packages*, these packages must b === "Same collection with `load`" ```pycon >>> import griffe - >>> collection = griffelib.ModulesCollection() - >>> package1 = griffelib.load("package1", modules_collection=collection) - >>> package2 = griffelib.load("package2", modules_collection=collection, resolve_aliases=True) + >>> collection = griffe.ModulesCollection() + >>> package1 = griffe.load("package1", modules_collection=collection) + >>> package2 = griffe.load("package2", modules_collection=collection, resolve_aliases=True) >>> package2["X"].resolved True >>> package2["X"].target @@ -295,10 +295,10 @@ Therefore, to resolve aliases *across different packages*, these packages must b === "Same collection, different loaders" ```pycon >>> import griffe - >>> collection = griffelib.ModulesCollection() - >>> loader1 = griffelib.GriffeLoader(modules_collection=collection, ...) + >>> collection = griffe.ModulesCollection() + >>> loader1 = griffe.GriffeLoader(modules_collection=collection, ...) >>> package1 = loader1.load("package1") - >>> loader2 = griffelib.GriffeLoader(modules_collection=collection, ...) # different parameters + >>> loader2 = griffe.GriffeLoader(modules_collection=collection, ...) # different parameters >>> package2 = loader2.load("package2") >>> package2["X"].resolved True @@ -315,7 +315,7 @@ By default, when resolving aliases, Griffe loaders will not be able to resolve a ```python import griffe -package2 = griffelib.load("package2", resolve_aliases=True, resolve_external=True) +package2 = griffe.load("package2", resolve_aliases=True, resolve_external=True) print(package2["X"].target.name) # X ``` @@ -334,7 +334,7 @@ By default, Griffe runs some Git commands to find the following information abou - what service it corresponds to (GitHub, etc.) - the current commit hash -It then assigns this information to each package it loads, in the [`git_info`][griffelib.Object.git_info] attribute. This attribute can be reassigned on any object, if necessary. Each object who has it set to `None` will look into its parents. +It then assigns this information to each package it loads, in the [`git_info`][griffe.Object.git_info] attribute. This attribute can be reassigned on any object, if necessary. Each object who has it set to `None` will look into its parents. In the following cases, the information will not be set: @@ -343,15 +343,15 @@ In the following cases, the information will not be set: - Griffe cannot identify a known, supported service from the remote URL - any Git command failed -Griffe supports the services listed in the [`KnownGitService`][griffelib.KnownGitService] symbol. Please open a feature request if you would like to add support for other services. +Griffe supports the services listed in the [`KnownGitService`][griffe.KnownGitService] symbol. Please open a feature request if you would like to add support for other services. -Thanks to this source information, Griffe can then compute [source links][griffelib.Object.source_link] for each objects, by combining the information with the object's filepath and line numbers. +Thanks to this source information, Griffe can then compute [source links][griffe.Object.source_link] for each objects, by combining the information with the object's filepath and line numbers. You can globally change how Griffe obtains the source information with the following environment variables: - `GRIFFE_GIT_REMOTE_URL`: It is the repository remote URL, as an HTTPS link that readers of your documentation can access to see the repository online, on the service it is hosted on. Example: `GRIFFE_GIT_REMOTE_URL=https://app.radicle.at/nodes/seed.radicle.at/rad:z4M5XTPDD4Wh1sm8iPCenF85J3z8Z`. - `GRIFFE_GIT_REMOTE`: You can also let Griffe obtain the remote URL by getting it from the Git local configuration. The Git remote defaults to `origin`. This environment variable lets you change it to something else. Example: `GRIFFE_GIT_REMOTE=upstream`. -- `GRIFFE_GIT_SERVICE`: Griffe infers the service by looking at the remote URL. If the remote URL contains a [known service name][griffelib.KnownGitService], Griffe will use it as service. You can otherwise explicitly set the service using this environment variable. Example: `GRIFFE_GIT_SERVICE=codeberg`. +- `GRIFFE_GIT_SERVICE`: Griffe infers the service by looking at the remote URL. If the remote URL contains a [known service name][griffe.KnownGitService], Griffe will use it as service. You can otherwise explicitly set the service using this environment variable. Example: `GRIFFE_GIT_SERVICE=codeberg`. - `GRIFFE_GIT_COMMIT_HASH`: Griffe gets the commit hash by running a Git command. If you prefer using another commit hash, you can set it using this environment variable. Example: `GRIFFE_GIT_COMMIT_HASH=77f928aeab857cb45564462a4f849c2df2cca99a`. For more complex cases, see [How to programmatically set the correct Git information or source link on objects](how-to/set-git-info.md). diff --git a/docs/guide/users/navigating.md b/docs/guide/users/navigating.md index a0cb2559e..75a1a0ab3 100644 --- a/docs/guide/users/navigating.md +++ b/docs/guide/users/navigating.md @@ -2,59 +2,59 @@ Griffe loads API data into data models. These models provide various attributes and methods to access or update specific fields. The different models are: -- [`Module`][griffelib.Module], representing Python modules; -- [`Class`][griffelib.Class], representing Python classes; -- [`Function`][griffelib.Function], representing Python functions and class methods; -- [`Attribute`][griffelib.Attribute], representing object attributes that weren't identified as modules, classes or functions; -- [`Type Alias`][griffelib.TypeAlias], representing Python type aliases; -- [`Alias`][griffelib.Alias], representing indirections such as imported objects or class members inherited from parent classes. +- [`Module`][griffe.Module], representing Python modules; +- [`Class`][griffe.Class], representing Python classes; +- [`Function`][griffe.Function], representing Python functions and class methods; +- [`Attribute`][griffe.Attribute], representing object attributes that weren't identified as modules, classes or functions; +- [`Type Alias`][griffe.TypeAlias], representing Python type aliases; +- [`Alias`][griffe.Alias], representing indirections such as imported objects or class members inherited from parent classes. When [loading an object](loading.md), Griffe will give you back an instance of one of these models. A few examples: ```python >>> import griffe ->>> type(griffelib.load("markdown")) - ->>> type(griffelib.load("markdown.core.Markdown")) - ->>> type(griffelib.load("markdown.Markdown")) - ->>> type(griffelib.load("markdown.core.markdown")) - ->>> type(griffelib.load("markdown.markdown")) - ->>> type(griffelib.load("markdown.Markdown.references")) - +>>> type(griffe.load("markdown")) + +>>> type(griffe.load("markdown.core.Markdown")) + +>>> type(griffe.load("markdown.Markdown")) + +>>> type(griffe.load("markdown.core.markdown")) + +>>> type(griffe.load("markdown.markdown")) + +>>> type(griffe.load("markdown.Markdown.references")) + ``` However deep the object is, Griffe loads the entire package. It means that in all the cases above, Griffe loaded the whole `markdown` package. The model instance Griffe gives you back is therefore part of a tree that you can navigate. ## Moving up: parents -Each object holds a reference to its [`parent`][griffelib.Object.parent] (except for the top-level module, for which the parent is `None`). Shortcuts are provided to climb up directly to the parent [`module`][griffelib.Object.module], or the top-level [`package`][griffelib.Object.package]. As we have seen in the [Loading chapter](loading.md), Griffe stores all loaded modules in a modules collection; this collection can be accessed too, through the [`modules_collection`][griffelib.Object.modules_collection] attribute. +Each object holds a reference to its [`parent`][griffe.Object.parent] (except for the top-level module, for which the parent is `None`). Shortcuts are provided to climb up directly to the parent [`module`][griffe.Object.module], or the top-level [`package`][griffe.Object.package]. As we have seen in the [Loading chapter](loading.md), Griffe stores all loaded modules in a modules collection; this collection can be accessed too, through the [`modules_collection`][griffe.Object.modules_collection] attribute. ## Moving down: members To access an object's members, there are a few options: -- Access to regular members through the [`members`][griffelib.Object.members] attribute, which is a dictionary. The keys are member names, the values are Griffe models. +- Access to regular members through the [`members`][griffe.Object.members] attribute, which is a dictionary. The keys are member names, the values are Griffe models. ```pycon >>> import griffe - >>> markdown = griffelib.load("markdown") + >>> markdown = griffe.load("markdown") >>> markdown.members["Markdown"] Alias('Markdown', 'markdown.core.Markdown') >>> markdown.members["core"].members["Markdown"] Class('Markdown', 46, 451) ``` -- Access to both regular and inherited members through the [`all_members`][griffelib.Object.all_members] attribute, which is a dictionary again. See [Inherited members](#inherited-members). +- Access to both regular and inherited members through the [`all_members`][griffe.Object.all_members] attribute, which is a dictionary again. See [Inherited members](#inherited-members). - Convenient dictionary-like item access, thanks to the subscript syntax `[]`. With this syntax, you will not only be able to chain accesses, but also merge them into a single access by using dot-separated paths to objects: ```pycon >>> import griffe - >>> markdown = griffelib.load("markdown") + >>> markdown = griffe.load("markdown") >>> markdown["core"]["Markdown"] # chained access Class('Markdown', 46, 451) >>> markdown["core.Markdown"] # merged access @@ -65,7 +65,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffelib.load("markdown") + >>> markdown = griffe.load("markdown") >>> markdown[("core", "Markdown")] # tuple access Class('Markdown', 46, 451) >>> # Due to the nature of the subscript syntax, @@ -74,18 +74,18 @@ To access an object's members, there are a few options: Class('Markdown', 46, 451) ``` -- Less convenient, but safer access to members while the object tree is being built (while a package is still being loaded), using the [`get_member()`][griffelib.GetMembersMixin.get_member] method. +- Less convenient, but safer access to members while the object tree is being built (while a package is still being loaded), using the [`get_member()`][griffe.GetMembersMixin.get_member] method. ```pycon >>> import griffe - >>> markdown = griffelib.load("markdown") + >>> markdown = griffe.load("markdown") >>> markdown.get_member("core.Markdown") Class('Markdown', 46, 451) ``` In particular, Griffe extensions should always use `get_member` instead of the subscript syntax `[]`. The `get_member` method only looks into regular members, while the subscript syntax looks into inherited members too (for classes), which cannot be correctly computed until a package is fully loaded (which is generally not the case when an extension is running). -- In addition to this, models provide the [`attributes`][griffelib.Object.attributes], [`functions`][griffelib.Object.functions], [`classes`][griffelib.Object.classes], [`type_aliases`][griffelib.Object.type_aliases] or [`modules`][griffelib.Object.modules] attributes, which return only members of the corresponding kind. These attributes are computed dynamically each time (they are Python properties). +- In addition to this, models provide the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes, which return only members of the corresponding kind. These attributes are computed dynamically each time (they are Python properties). The same way members are accessed, they can also be set: @@ -97,22 +97,22 @@ The same way members are accessed, they can also be set: - Dictionary-like item deletion: `del markdown["thing"]`, also supporting dotted-paths and string tuples. This will delete only regular members: inherited members (classes only) are re-computed everytime they are accessed. - Safer method for extensions: `markdown.del_member("thing")`, also supporting dotted-paths and string tuples. -- Regular member deletion: `del markdown.members["thing"]`. **This is not recommended, as the [`aliases`][griffelib.Object.aliases] attribute of other objects in the tree will not be automatically updated.** +- Regular member deletion: `del markdown.members["thing"]`. **This is not recommended, as the [`aliases`][griffe.Object.aliases] attribute of other objects in the tree will not be automatically updated.** ### Inherited members Griffe supports class inheritance, both when visiting and inspecting modules. -To access members of a class that are inherited from base classes, use the [`inherited_members`][griffelib.Object.inherited_members] attribute. Everytime you access inherited members, the base classes of the given class will be resolved, then the MRO (Method Resolution Order) will be computed for these base classes, and a dictionary of inherited members will be built. Make sure to store the result in a variable to avoid re-computing it everytime (you are responsible for the caching part). Also make sure to only access `inherited_members` once everything is loaded by Griffe, to avoid computing things too early. Don't try to access inherited members in extensions, while visiting or inspecting modules. +To access members of a class that are inherited from base classes, use the [`inherited_members`][griffe.Object.inherited_members] attribute. Everytime you access inherited members, the base classes of the given class will be resolved, then the MRO (Method Resolution Order) will be computed for these base classes, and a dictionary of inherited members will be built. Make sure to store the result in a variable to avoid re-computing it everytime (you are responsible for the caching part). Also make sure to only access `inherited_members` once everything is loaded by Griffe, to avoid computing things too early. Don't try to access inherited members in extensions, while visiting or inspecting modules. -Inherited members are aliases that point at the corresponding members in parent classes. These aliases will have their [`inherited`][griffelib.Alias.inherited] attribute set to true. +Inherited members are aliases that point at the corresponding members in parent classes. These aliases will have their [`inherited`][griffe.Alias.inherited] attribute set to true. **Important:** only classes from already loaded packages will be used when computing inherited members. This gives users control over how deep into inheritance to go, by pre-loading packages from which you want to inherit members. For example, if `package_c.ClassC` inherits from `package_b.ClassB`, itself inheriting from `package_a.ClassA`, and you want to load `ClassB` members only: ```python import griffe -loader = griffelib.GriffeLoader() +loader = griffe.GriffeLoader() # note that we don't load package_a loader.load("package_b") loader.load("package_c") @@ -120,9 +120,9 @@ loader.load("package_c") If a base class cannot be resolved during computation of inherited members, Griffe logs a DEBUG message. -If you want to access all members at once (both declared and inherited), use the [`all_members`][griffelib.Object.all_members] attribute. If you want to access only declared members, use the [`members`][griffelib.Object] attribute. +If you want to access all members at once (both declared and inherited), use the [`all_members`][griffe.Object.all_members] attribute. If you want to access only declared members, use the [`members`][griffe.Object] attribute. -Accessing the [`attributes`][griffelib.Object.attributes], [`functions`][griffelib.Object.functions], [`classes`][griffelib.Object.classes], [`type_aliases`][griffelib.Object.type_aliases] or [`modules`][griffelib.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by Griffe. Don't try to access inherited members in extensions, while visiting or inspecting modules. +Accessing the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by Griffe. Don't try to access inherited members in extensions, while visiting or inspecting modules. #### Limitations @@ -174,46 +174,46 @@ We will try to lift these limitations in the future. ## Aliases -Aliases represent indirections, such as objects imported from elsewhere, attributes, or methods inherited from parent classes. They are pointers to the object they represent. The path of the object they represent is stored in their [`target_path`][griffelib.Alias.target_path] attribute. Once they are resolved, the target object can be accessed through their [`target`][griffelib.Alias.target] attribute. +Aliases represent indirections, such as objects imported from elsewhere, attributes, or methods inherited from parent classes. They are pointers to the object they represent. The path of the object they represent is stored in their [`target_path`][griffe.Alias.target_path] attribute. Once they are resolved, the target object can be accessed through their [`target`][griffe.Alias.target] attribute. -Aliases can be found in objects' members. Each object can also access its own aliases (the aliases pointing at it) through its [`aliases`][griffelib.Object.aliases] attribute. This attribute is a dictionary whose keys are the aliases paths and values are the aliases themselves. +Aliases can be found in objects' members. Each object can also access its own aliases (the aliases pointing at it) through its [`aliases`][griffe.Object.aliases] attribute. This attribute is a dictionary whose keys are the aliases paths and values are the aliases themselves. Most of the time, aliases simply act as proxies to their target objects. For example, accessing the `docstring` of an alias will simply return the docstring of the object it targets. -Accessing fields on aliases will trigger their resolution. If they are already resolved (their `target` attribute is set to the target object), the field is returned. If they are not resolved, their target path will be looked up in the modules collection, and if it is found, the object at this location will be assigned to the alias' `target` attribute. If it isn't found, an [`AliasResolutionError`][griffelib.AliasResolutionError] exception will be raised. +Accessing fields on aliases will trigger their resolution. If they are already resolved (their `target` attribute is set to the target object), the field is returned. If they are not resolved, their target path will be looked up in the modules collection, and if it is found, the object at this location will be assigned to the alias' `target` attribute. If it isn't found, an [`AliasResolutionError`][griffe.AliasResolutionError] exception will be raised. Since merely accessing an alias field can raise an exception, it is often useful to check if an object is an alias before accessing its fields. There are multiple ways to check if an object is an alias: -- using the `is_alias` boolean ([`Object.is_alias`][griffelib.Object.is_alias], [`Alias.is_alias`][griffelib.Alias.is_alias]), which won't trigger resolution -- using `isinstance` to check if the object is an instance of [`Alias`][griffelib.Alias] +- using the `is_alias` boolean ([`Object.is_alias`][griffe.Object.is_alias], [`Alias.is_alias`][griffe.Alias.is_alias]), which won't trigger resolution +- using `isinstance` to check if the object is an instance of [`Alias`][griffe.Alias] ```pycon >>> import griffe ->>> load = griffelib.load("griffelib.load") +>>> load = griffe.load("griffe.load") >>> load.is_alias True ->>> isinstance(load, griffelib.Alias) +>>> isinstance(load, griffe.Alias) True ``` -The [`kind`][griffelib.Alias.kind] of an alias will only return [`ALIAS`][griffelib.Kind.ALIAS] if the alias is not resolved and cannot be resolved within the current modules collection. +The [`kind`][griffe.Alias.kind] of an alias will only return [`ALIAS`][griffe.Kind.ALIAS] if the alias is not resolved and cannot be resolved within the current modules collection. You can of course also catch any raised exception with a regular try/except block: ```python try: print(obj.source) -except griffelib.AliasResolutionError: +except griffe.AliasResolutionError: pass ``` -To check if an alias is already resolved, you can use its [`resolved`][griffelib.Alias.resolved] attribute. +To check if an alias is already resolved, you can use its [`resolved`][griffe.Alias.resolved] attribute. ### Alias chains -Aliases can be chained. For example, if module `a` imports `X` from module `b`, which itself imports `X` from module `c`, then `a.X` is an alias to `b.X` which is an alias to `c.X`: `a.X` -> `b.X` -> `c.X`. To access the final target directly, you can use the [`final_target`][griffelib.Alias.final_target] attribute. Most alias properties that act like proxies actually fetch the final target rather than the next one to return the final field. +Aliases can be chained. For example, if module `a` imports `X` from module `b`, which itself imports `X` from module `c`, then `a.X` is an alias to `b.X` which is an alias to `c.X`: `a.X` -> `b.X` -> `c.X`. To access the final target directly, you can use the [`final_target`][griffe.Alias.final_target] attribute. Most alias properties that act like proxies actually fetch the final target rather than the next one to return the final field. -Sometimes, when a package makes use of complicated imports (wildcard imports from parents and submodules), or when runtime objects are hard to inspect, it is possible to end up with a cyclic chain of aliases. You could for example end up with a chain like `a.X` -> `b.X` -> `c.X` -> `a.X`. In this case, the alias *cannot* be resolved, since the chain goes in a loop. Griffe will raise a [`CyclicAliasError`][griffelib.CyclicAliasError] when trying to resolve such cyclic chains. +Sometimes, when a package makes use of complicated imports (wildcard imports from parents and submodules), or when runtime objects are hard to inspect, it is possible to end up with a cyclic chain of aliases. You could for example end up with a chain like `a.X` -> `b.X` -> `c.X` -> `a.X`. In this case, the alias *cannot* be resolved, since the chain goes in a loop. Griffe will raise a [`CyclicAliasError`][griffe.CyclicAliasError] when trying to resolve such cyclic chains. Aliases chains are never partially resolved: either they are resolved down to their final target, or none of their links are resolved. @@ -221,9 +221,9 @@ Aliases chains are never partially resolved: either they are resolved down to th The kind of an object (module, class, function, attribute, type alias or alias) can be obtained in several ways. -- With the [`kind`][griffelib.Object.kind] attribute and the [`Kind`][griffelib.Kind] enumeration: `obj.kind is Kind.MODULE`. +- With the [`kind`][griffe.Object.kind] attribute and the [`Kind`][griffe.Kind] enumeration: `obj.kind is Kind.MODULE`. -- With the [`is_kind()`][griffelib.Object.is_kind] method: +- With the [`is_kind()`][griffe.Object.is_kind] method: - `obj.is_kind(Kind.MODULE)` - `obj.is_kind("class")` @@ -231,21 +231,21 @@ The kind of an object (module, class, function, attribute, type alias or alias) When given a set of kinds, the method returns true if the object is of one of the given kinds. -- With the [`is_module`][griffelib.Object.is_module], [`is_class`][griffelib.Object.is_class], [`is_function`][griffelib.Object.is_function], [`is_attribute`][griffelib.Object.is_attribute], [`is_type_alias`][griffelib.Object.is_type_alias], and [`is_alias`][griffelib.Object.is_alias] attributes. +- With the [`is_module`][griffe.Object.is_module], [`is_class`][griffe.Object.is_class], [`is_function`][griffe.Object.is_function], [`is_attribute`][griffe.Object.is_attribute], [`is_type_alias`][griffe.Object.is_type_alias], and [`is_alias`][griffe.Object.is_alias] attributes. Additionally, it is possible to check if an object is a sub-kind of module, with the following attributes: -- [`is_init_module`][griffelib.Object.is_init_module], for `__init__.py` modules -- [`is_package`][griffelib.Object.is_package], for top-level packages -- [`is_subpackage`][griffelib.Object.is_subpackage], for non-top-level packages -- [`is_namespace_package`][griffelib.Object.is_namespace_package], for top-level [namespace packages](https://packaging.python.org/en/latest/guides/packaging-namespace-packages/) -- [`is_namespace_subpackage`][griffelib.Object.is_namespace_subpackage], for non-top-level namespace packages +- [`is_init_module`][griffe.Object.is_init_module], for `__init__.py` modules +- [`is_package`][griffe.Object.is_package], for top-level packages +- [`is_subpackage`][griffe.Object.is_subpackage], for non-top-level packages +- [`is_namespace_package`][griffe.Object.is_namespace_package], for top-level [namespace packages](https://packaging.python.org/en/latest/guides/packaging-namespace-packages/) +- [`is_namespace_subpackage`][griffe.Object.is_namespace_subpackage], for non-top-level namespace packages -Finally, additional [`labels`][griffelib.Object.labels] are attached to objects to further specify their kind. The [`has_labels()`][griffelib.Object.has_labels] method can be used to check if an object has several specific labels. +Finally, additional [`labels`][griffe.Object.labels] are attached to objects to further specify their kind. The [`has_labels()`][griffe.Object.has_labels] method can be used to check if an object has several specific labels. ## Object location -An object is identified by its [`path`][griffelib.Object.path], which is its location in the object tree. The path is composed of all the parent names and the object name, separated by dots, for example `mod.Class.meth`. This `path` is the [`canonical_path`][griffelib.Object.canonical_path] on regular objects. For aliases however, the `path` is *where they are imported* while the canonical path is *where they come from*. Example: +An object is identified by its [`path`][griffe.Object.path], which is its location in the object tree. The path is composed of all the parent names and the object name, separated by dots, for example `mod.Class.meth`. This `path` is the [`canonical_path`][griffe.Object.canonical_path] on regular objects. For aliases however, the `path` is *where they are imported* while the canonical path is *where they come from*. Example: ```python # pkg1.py @@ -254,7 +254,7 @@ from pkg2 import A as B ```pycon >>> import griffe ->>> B = griffelib.load("pkg1.B") +>>> B = griffe.load("pkg1.B") >>> B.path 'pkg1.B' >>> B.canonical_path @@ -265,20 +265,20 @@ from pkg2 import A as B Information on the actual source code of objects is available through the following attributes: -- [`filepath`][griffelib.Object.filepath], the absolute path to the module the object appears in, for example `~/project/src/pkg/mod.py` -- [`relative_filepath`][griffelib.Object.relative_filepath], the relative path to the module, compared to the current working directory, for example `src/pkg/mod.py` -- [`relative_package_filepath`][griffelib.Object.relative_package_filepath], the relative path to the module, compared to the parent of the top-level package, for example `pkg/mod.py` -- [`lineno`][griffelib.Object.lineno] and [`endlineno`][griffelib.Object.endlineno], the starting and ending line numbers of the object in the source -- [`lines`][griffelib.Object.lines], the lines of code defining the object (or importing the alias) -- [`source`][griffelib.Object.source], the source lines concatenated as a single multiline string +- [`filepath`][griffe.Object.filepath], the absolute path to the module the object appears in, for example `~/project/src/pkg/mod.py` +- [`relative_filepath`][griffe.Object.relative_filepath], the relative path to the module, compared to the current working directory, for example `src/pkg/mod.py` +- [`relative_package_filepath`][griffe.Object.relative_package_filepath], the relative path to the module, compared to the parent of the top-level package, for example `pkg/mod.py` +- [`lineno`][griffe.Object.lineno] and [`endlineno`][griffe.Object.endlineno], the starting and ending line numbers of the object in the source +- [`lines`][griffe.Object.lines], the lines of code defining the object (or importing the alias) +- [`source`][griffe.Object.source], the source lines concatenated as a single multiline string -Each object holds a reference to a [`lines_collection`][griffelib.Object.lines_collection]. Similar to the modules collection, this lines collection is a dictionary whose keys are module file-paths and values are their contents as list of lines. The lines collection is populated by the loader. +Each object holds a reference to a [`lines_collection`][griffe.Object.lines_collection]. Similar to the modules collection, this lines collection is a dictionary whose keys are module file-paths and values are their contents as list of lines. The lines collection is populated by the loader. ## Object visibility Each object has fields that are related to their visibility within the API. -- [`is_public`][griffelib.Object.is_public]: whether this object is public (destined to be consumed by your users). For module-level objects, Griffe considers that the object is public if: +- [`is_public`][griffe.Object.is_public]: whether this object is public (destined to be consumed by your users). For module-level objects, Griffe considers that the object is public if: - it is listed in its parent module's `__all__` attribute - or if its parent module does not declare `__all__`, and the object doesn't have a private name, and the object is not imported from elsewhere @@ -312,47 +312,47 @@ Each object has fields that are related to their visibility within the API. ... ``` -- [`is_deprecated`][griffelib.Object.is_deprecated]: whether this object is deprecated and shouldn't be used. +- [`is_deprecated`][griffe.Object.is_deprecated]: whether this object is deprecated and shouldn't be used. -- [`is_special`][griffelib.Object.is_special]: whether this object has a special name like `__special__` +- [`is_special`][griffe.Object.is_special]: whether this object has a special name like `__special__` -- [`is_private`][griffelib.Object.is_private]: whether this object has a private name like `_private` or `__private`, but not `__special__` +- [`is_private`][griffe.Object.is_private]: whether this object has a private name like `_private` or `__private`, but not `__special__` -- [`is_class_private`][griffelib.Object.is_class_private]: whether this object has a class-private name like `__private` and is a member of a class +- [`is_class_private`][griffe.Object.is_class_private]: whether this object has a class-private name like `__private` and is a member of a class Since `is_private` only checks the name of the object, it is not mutually exclusive with `is_public`. It means an object can return true for both `is_public` and `is_private`. We invite Griffe users to mostly rely on `is_public` and `not is_public`. -It is possible to force `is_public` and `is_deprecated` to return true or false by setting the [`public`][griffelib.Object.public] and [`deprecated`][griffelib.Object.deprecated] fields respectively. These fields are typically set by extensions that support new ways of marking objects as public or deprecated. +It is possible to force `is_public` and `is_deprecated` to return true or false by setting the [`public`][griffe.Object.public] and [`deprecated`][griffe.Object.deprecated] fields respectively. These fields are typically set by extensions that support new ways of marking objects as public or deprecated. ## Imports/exports -Modules and classes populate their [`imports`][griffelib.Object.imports] field with names that were imported from other modules. Similarly, modules populate their [`exports`][griffelib.Object.exports] field with names that were exported by being listed into the module's `__all__` attribute. Each object then provides then [`is_imported`][griffelib.Object.is_imported] and [`is_exported`][griffelib.Object.is_exported] fields, which tell if an object was imported or exported respectively. Additionally, objects also provide an [`is_wildcard_exposed`][griffelib.Object.is_wildcard_exposed] field that tells if an object is exposed to wildcard imports, i.e. will be imported when another module does `from this_module import *`. +Modules and classes populate their [`imports`][griffe.Object.imports] field with names that were imported from other modules. Similarly, modules populate their [`exports`][griffe.Object.exports] field with names that were exported by being listed into the module's `__all__` attribute. Each object then provides then [`is_imported`][griffe.Object.is_imported] and [`is_exported`][griffe.Object.is_exported] fields, which tell if an object was imported or exported respectively. Additionally, objects also provide an [`is_wildcard_exposed`][griffe.Object.is_wildcard_exposed] field that tells if an object is exposed to wildcard imports, i.e. will be imported when another module does `from this_module import *`. ## Docstrings -Each object has an optional [`docstring`][griffelib.Object.docstring] attached to it. To check whether it has one without comparing against `None`, the two following fields can be used: +Each object has an optional [`docstring`][griffe.Object.docstring] attached to it. To check whether it has one without comparing against `None`, the two following fields can be used: -- [`has_docstring`][griffelib.Object.has_docstring]: whether this object has a docstring (even empty) -- [`has_docstrings`][griffelib.Object.has_docstrings]: same thing, but recursive; whether this object or any of its members has a docstring (even empty) +- [`has_docstring`][griffe.Object.has_docstring]: whether this object has a docstring (even empty) +- [`has_docstrings`][griffe.Object.has_docstrings]: same thing, but recursive; whether this object or any of its members has a docstring (even empty) -[Docstrings][griffelib.Docstring] provide their cleaned-up [`value`][griffelib.Docstring.value] (de-indented string, stripped from leading and trailing newlines), as well as their starting and ending line numbers with [`lineno`][griffelib.Docstring.lineno] and [`endlineno`][griffelib.Docstring.endlineno]. +[Docstrings][griffe.Docstring] provide their cleaned-up [`value`][griffe.Docstring.value] (de-indented string, stripped from leading and trailing newlines), as well as their starting and ending line numbers with [`lineno`][griffe.Docstring.lineno] and [`endlineno`][griffe.Docstring.endlineno]. Docstrings can be parsed against several [docstring-styles](../../reference/docstrings.md), which are micro-formats that allow documenting things such as parameters, returned values, raised exceptions, etc.. -When loading a package, it is possible to specify the docstring style to attach to every docstring (see the `docstring_parser` parameter of [`griffelib.load`][griffelib.load]). Accessing the [`parsed`][griffelib.Docstring.parsed] field of a docstring will use this style to parse the docstring and return a list of [docstring sections][advanced-api-sections]. Each section has a `value` whose shape depends on the section kind. For example, parameter sections have a list of parameter representations as value, while a text section only has a string as value. +When loading a package, it is possible to specify the docstring style to attach to every docstring (see the `docstring_parser` parameter of [`griffe.load`][griffe.load]). Accessing the [`parsed`][griffe.Docstring.parsed] field of a docstring will use this style to parse the docstring and return a list of [docstring sections][advanced-api-sections]. Each section has a `value` whose shape depends on the section kind. For example, parameter sections have a list of parameter representations as value, while a text section only has a string as value. -After a package is loaded, it is still possible to change the style used for specific docstrings by either overriding their [`parser`][griffelib.Docstring.parser] and [`parser_options`][griffelib.Docstring.parser_options] attributes, or by calling their [`parse()`][griffelib.Docstring.parse] method with a different style: +After a package is loaded, it is still possible to change the style used for specific docstrings by either overriding their [`parser`][griffe.Docstring.parser] and [`parser_options`][griffe.Docstring.parser_options] attributes, or by calling their [`parse()`][griffe.Docstring.parse] method with a different style: ```pycon >>> import griffe ->>> markdown = griffelib.load("markdown", docstring_parser="google") +>>> markdown = griffe.load("markdown", docstring_parser="google") >>> markdown["Markdown"].docstring.parse("numpy") [...] ``` Do note, however, that the `parsed` attribute is cached, and won't be reset when overriding the `parser` or `parser_options` values. -Docstrings have a [`parent`][griffelib.Docstring.parent] field too, that is a reference to their respective module, class, function, attribute or type alias. +Docstrings have a [`parent`][griffe.Docstring.parent] field too, that is a reference to their respective module, class, function, attribute or type alias. ## Model-specific fields @@ -360,46 +360,46 @@ Models have most fields in common, but also have specific fields. ### Modules -- [`imports_future_annotations`][griffelib.Module.imports_future_annotations]: Whether the module imports [future annotations](https://peps.python.org/pep-0563/), which changes the way we parse type annotations. -- [`overloads`][griffelib.Module.overloads]: A dictionary to store overloads for module-level functions. +- [`imports_future_annotations`][griffe.Module.imports_future_annotations]: Whether the module imports [future annotations](https://peps.python.org/pep-0563/), which changes the way we parse type annotations. +- [`overloads`][griffe.Module.overloads]: A dictionary to store overloads for module-level functions. ### Classes -- [`bases`][griffelib.Class.bases]: A list of class bases in the form of [expressions][griffelib.Expr]. -- [`resolved_bases`][griffelib.Class.resolved_bases]: A list of class bases, in the form of [Class][griffelib.Class] objects. Only the bases that were loaded are returned, the others are discarded. -- [`mro()`][griffelib.Class.mro]: A method to compute the Method Resolution Order in the form of a list of [Class][griffelib.Class] objects. -- [`overloads`][griffelib.Class.overloads]: A dictionary to store overloads for class-level methods. -- [`decorators`][griffelib.Class.decorators]: The [decorators][griffelib.Decorator] applied to the class. -- [`parameters`][griffelib.Class.parameters]: The [parameters][griffelib.Parameters] of the class' `__init__` method, if any. -- [`type_parameters`][griffelib.Class.type_parameters]: The [type parameters][griffelib.TypeParameters] of the class. +- [`bases`][griffe.Class.bases]: A list of class bases in the form of [expressions][griffe.Expr]. +- [`resolved_bases`][griffe.Class.resolved_bases]: A list of class bases, in the form of [Class][griffe.Class] objects. Only the bases that were loaded are returned, the others are discarded. +- [`mro()`][griffe.Class.mro]: A method to compute the Method Resolution Order in the form of a list of [Class][griffe.Class] objects. +- [`overloads`][griffe.Class.overloads]: A dictionary to store overloads for class-level methods. +- [`decorators`][griffe.Class.decorators]: The [decorators][griffe.Decorator] applied to the class. +- [`parameters`][griffe.Class.parameters]: The [parameters][griffe.Parameters] of the class' `__init__` method, if any. +- [`type_parameters`][griffe.Class.type_parameters]: The [type parameters][griffe.TypeParameters] of the class. ### Functions -- [`decorators`][griffelib.Function.decorators]: The [decorators][griffelib.Decorator] applied to the function. -- [`overloads`][griffelib.Function.overloads]: The overloaded signatures of the function. -- [`parameters`][griffelib.Function.parameters]: The [parameters][griffelib.Parameters] of the function. -- [`returns`][griffelib.Function.returns]: The type annotation of the returned value, in the form of an [expression][griffelib.Expr]. The `annotation` field can also be used, for compatibility with attributes. -- [`type_parameters`][griffelib.Function.type_parameters]: The [type parameters][griffelib.TypeParameters] of the function. +- [`decorators`][griffe.Function.decorators]: The [decorators][griffe.Decorator] applied to the function. +- [`overloads`][griffe.Function.overloads]: The overloaded signatures of the function. +- [`parameters`][griffe.Function.parameters]: The [parameters][griffe.Parameters] of the function. +- [`returns`][griffe.Function.returns]: The type annotation of the returned value, in the form of an [expression][griffe.Expr]. The `annotation` field can also be used, for compatibility with attributes. +- [`type_parameters`][griffe.Function.type_parameters]: The [type parameters][griffe.TypeParameters] of the function. ### Attributes -- [`annotation`][griffelib.Attribute.annotation]: The type annotation of the attribute, in the form of an [expression][griffelib.Expr]. -- [`value`][griffelib.Attribute.value]: The value of the attribute, in the form of an [expression][griffelib.Expr]. -- [`deleter`][griffelib.Attribute.deleter]: The property deleter. -- [`setter`][griffelib.Attribute.setter]: The property setter. +- [`annotation`][griffe.Attribute.annotation]: The type annotation of the attribute, in the form of an [expression][griffe.Expr]. +- [`value`][griffe.Attribute.value]: The value of the attribute, in the form of an [expression][griffe.Expr]. +- [`deleter`][griffe.Attribute.deleter]: The property deleter. +- [`setter`][griffe.Attribute.setter]: The property setter. ### Type aliases -- [`value`][griffelib.TypeAlias.value]: The value of the type alias, in the form of an [expression][griffelib.Expr]. -- [`type_parameters`][griffelib.TypeAlias.type_parameters]: The [type parameters][griffelib.TypeParameters] of the type alias. +- [`value`][griffe.TypeAlias.value]: The value of the type alias, in the form of an [expression][griffe.Expr]. +- [`type_parameters`][griffe.TypeAlias.type_parameters]: The [type parameters][griffe.TypeParameters] of the type alias. ### Alias -- [`alias_lineno`][griffelib.Alias.alias_lineno]: The alias line number (where the object is imported). -- [`alias_endlineno`][griffelib.Alias.alias_endlineno]: The alias ending line number (where the object is imported). -- [`target`][griffelib.Alias.target]: The alias target (a module, class, function or attribute). -- [`target_path`][griffelib.Alias.target_path]: The path of the alias target, as a string. -- [`wildcard`][griffelib.Alias.wildcard]: Whether this alias represents a wildcard import, and if so from which module. -- [`resolve_target()`][griffelib.Alias.resolve_target]: A method that resolves the target when called. +- [`alias_lineno`][griffe.Alias.alias_lineno]: The alias line number (where the object is imported). +- [`alias_endlineno`][griffe.Alias.alias_endlineno]: The alias ending line number (where the object is imported). +- [`target`][griffe.Alias.target]: The alias target (a module, class, function or attribute). +- [`target_path`][griffe.Alias.target_path]: The path of the alias target, as a string. +- [`wildcard`][griffe.Alias.wildcard]: Whether this alias represents a wildcard import, and if so from which module. +- [`resolve_target()`][griffe.Alias.resolve_target]: A method that resolves the target when called. ## Expressions @@ -444,7 +444,7 @@ The Python language keeps evolving, and often library developers must continue s Yet this doesn't mean they can't enjoy latest features in their own docs: Griffe allows to "modernize" expressions, for example by replacing `typing.Union` with PEP 604 type unions `|`. Thanks to this, downstream tools like [mkdocstrings][mkdocstrings-python] can automatically transform type annotations into their modern equivalent. This improves consistency in your docs, and shows users how to use your code with the latest features of the language. -To modernize an expression, simply call its [`modernize()`][griffelib.Expr.modernize] method. It returns a new, modernized expression. Some parts of the expression might be left unchanged, so be careful if you decide to mutate them. +To modernize an expression, simply call its [`modernize()`][griffe.Expr.modernize] method. It returns a new, modernized expression. Some parts of the expression might be left unchanged, so be careful if you decide to mutate them. Modernizations applied: diff --git a/docs/guide/users/recommendations/public-apis.md b/docs/guide/users/recommendations/public-apis.md index c7b525c95..9a0d1cbbd 100644 --- a/docs/guide/users/recommendations/public-apis.md +++ b/docs/guide/users/recommendations/public-apis.md @@ -287,7 +287,7 @@ Start hiding your module layout early! It is much easier to (partially) expose t ## Unique names and public locations -Whether or not you are planning to hide your module layout, as recommended in the previous section, one thing that will help both you and your users is making sure your object names are unique across your code base. Having unique names ensures that you can expose everything at the top-level module of your package without having to alias objects (using `from ... import x as y`). It will also ensure that your users don't end up importing multiple different objects with the same name, again having to alias them. Finally, it forces you to use meaningful names for your objects, names that don't need the context of the above namespaces (generally modules) to understand what they mean. For example, in Griffe we previously exposed `griffelib.docstrings.utils.warning`. Exposing `warning` at the top-level made it very vague: what does it do? So we renamed it `docstring_warning`, which is much clearer. +Whether or not you are planning to hide your module layout, as recommended in the previous section, one thing that will help both you and your users is making sure your object names are unique across your code base. Having unique names ensures that you can expose everything at the top-level module of your package without having to alias objects (using `from ... import x as y`). It will also ensure that your users don't end up importing multiple different objects with the same name, again having to alias them. Finally, it forces you to use meaningful names for your objects, names that don't need the context of the above namespaces (generally modules) to understand what they mean. For example, in Griffe we previously exposed `griffe.docstrings.utils.warning`. Exposing `warning` at the top-level made it very vague: what does it do? So we renamed it `docstring_warning`, which is much clearer. Ensuring unique names across a code base is sometimes not feasible, or not desirable; in this case, try to use namespacing while still hiding the module layout the best you can. @@ -422,7 +422,7 @@ The first user of your CLI as API is... you. When you declare your project's CLI ```toml [project.scripts] -griffe = "griffecli:main" +griffe = "griffe:main" ``` ...this entrypoint ends up as a Python script in the `bin` directory of your virtual environment: @@ -438,7 +438,7 @@ if __name__ == "__main__": sys.exit(main()) ``` -In this script, we find our entrypoint, `griffecli.main`, used programmatically. +In this script, we find our entrypoint, `griffe.main`, used programmatically. --- @@ -450,21 +450,21 @@ import griffe def test_main() -> None: - assert griffecli.main(["dump", "griffe", "-s", "src", "-o/dev/null"]) == 0 + assert griffe.main(["dump", "griffe", "-s", "src", "-o/dev/null"]) == 0 def test_show_help(capsys: pytest.CaptureFixture) -> None: with pytest.raises(SystemExit): - griffecli.main(["-h"]) + griffe.main(["-h"]) captured = capsys.readouterr() assert "griffe" in captured.out def test_show_version(capsys: pytest.CaptureFixture) -> None: with pytest.raises(SystemExit): - griffecli.main(["-V"]) + griffe.main(["-V"]) captured = capsys.readouterr() - assert griffelib.get_version() in captured.out + assert griffe.get_version() in captured.out ``` Now, when you start testing the logic of your CLI subcommands, such as our `dump` subcommand above, you might feel like passing again and again through the command-line arguments parser (here `argparse`) is wasteful and redundant. It is important to test that your arguments are parsed correctly (as you expect them to be parsed), but they shouldn't *have* to be parsed when you are testing the underlying logic. diff --git a/docs/guide/users/serializing.md b/docs/guide/users/serializing.md index ddc9e840b..6adcfb4e6 100644 --- a/docs/guide/users/serializing.md +++ b/docs/guide/users/serializing.md @@ -7,7 +7,7 @@ Griffe can be used to load API data and output it as JSON on standard output or The easiest way to load and serialize API data is to use the command-line tool: ```console -$ griffecli dump httpx fastapi +$ griffe dump httpx fastapi { "httpx": { "name": "httpx", @@ -25,7 +25,7 @@ It will output a JSON-serialized version of the package's API data. Try it out on Griffe itself: ```console -$ griffecli dump griffe +$ griffe dump griffe { "griffe": { "name": "griffe", @@ -37,13 +37,13 @@ $ griffecli dump griffe To output in a file instead of standard output, use the `-o`, `--output` option: ```console -$ griffecli dump griffe -o griffelib.json +$ griffe dump griffe -o griffe.json ``` If you load multiple packages' signatures, you can dump each in its own file with a templated filepath: ```console -$ griffecli dump griffe -o './dumps/{package}.json' +$ griffe dump griffe -o './dumps/{package}.json' ``` By default, Griffe will search in `sys.path`, so if you installed it through *pipx*, there are few chances it will find your packages. To explicitly specify search paths, use the `-s, --search ` option. You can use it multiple times. You can also add the search paths to the `PYTHONPATH` environment variable. If Griffe can't find the packages, it will fail with a `ModuleNotFoundError`. @@ -54,14 +54,14 @@ See all the options for the `dump` command in the [CLI reference](../../referenc If you have read through the [Navigating](navigating.md) chapter, you know about our six data models for modules, classes, functions, attributes, type aliases and aliases. Each one of these model provide the two following methods: -- [`as_json`][griffelib.Object.as_json], which allows to serialize an object into JSON, -- [`from_json`][griffelib.Object.from_json], which allows loading JSON back into a model instance. +- [`as_json`][griffe.Object.as_json], which allows to serialize an object into JSON, +- [`from_json`][griffe.Object.from_json], which allows loading JSON back into a model instance. -These two methods are convenient wrappers around our [JSON encoder][griffelib.JSONEncoder] and [JSON decoder][griffelib.json_decoder]. The JSON encoder and decoder will give you finer-grain control over what you serialize or load, as the methods above are only available on data models, and not on sub-structures like decorators or parameters. +These two methods are convenient wrappers around our [JSON encoder][griffe.JSONEncoder] and [JSON decoder][griffe.json_decoder]. The JSON encoder and decoder will give you finer-grain control over what you serialize or load, as the methods above are only available on data models, and not on sub-structures like decorators or parameters. -Under the hood, `as_json` just calls [`as_dict`][griffelib.Object.as_dict], which converts the model instance into a dictionary, and then serializes this dictionary to JSON. +Under the hood, `as_json` just calls [`as_dict`][griffe.Object.as_dict], which converts the model instance into a dictionary, and then serializes this dictionary to JSON. -When serializing an object, by default the JSON will only contain the fields required to load it back to a Griffe model instance. If you are not planning on loading back the data into our data models, or if you want to load them in a different implementation which is not able to infer back all the other fields, you can choose to serialize every possible field. We call this a full dump, and it is enabled with the `full` option of the [encoder][griffelib.JSONEncoder] or the [`as_json`][griffelib.Object.as_json] method. +When serializing an object, by default the JSON will only contain the fields required to load it back to a Griffe model instance. If you are not planning on loading back the data into our data models, or if you want to load them in a different implementation which is not able to infer back all the other fields, you can choose to serialize every possible field. We call this a full dump, and it is enabled with the `full` option of the [encoder][griffe.JSONEncoder] or the [`as_json`][griffe.Object.as_json] method. ## Schema diff --git a/docs/index.md b/docs/index.md index 79b1851ae..efb9818a1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,7 +10,7 @@ hide: Griffe logo, created by François Rozet <francois.rozet@outlook.com> -> Griffe, pronounced "grif" (`/ɡʁif/`), is a french word that means "claw", but also "signature" in a familiar way. "On reconnaît bien là sa griffelib." +> Griffe, pronounced "grif" (`/ɡʁif/`), is a french word that means "claw", but also "signature" in a familiar way. "On reconnaît bien là sa griffe."
@@ -41,17 +41,17 @@ Griffe can be used as a Python library. For example, the [Python handler](https:
-```console exec="1" source="console" result="json" title="Serializing as JSON" id="griffecli-dump" +```console exec="1" source="console" result="json" title="Serializing as JSON" id="griffe-dump" $ export FORCE_COLOR=1 # markdown-exec: hide -$ griffecli dump griffe -ssrc -r 2>/dev/null | head -n29 +$ griffe dump griffe -ssrc -r 2>/dev/null | head -n29 ```
-```console exec="1" source="console" result="ansi" returncode="1" title="Checking for API breaking changes" id="griffecli-check" +```console exec="1" source="console" result="ansi" returncode="1" title="Checking for API breaking changes" id="griffe-check" $ export FORCE_COLOR=1 # markdown-exec: hide -$ griffecli check griffe -ssrc -b0.46.0 -a0.45.0 --verbose +$ griffe check griffe -ssrc -b0.46.0 -a0.45.0 --verbose ```
diff --git a/docs/installation.md b/docs/installation.md index 531dcab22..e0c69a8df 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -104,3 +104,20 @@ Griffe is a Python package, so you can install it with your favorite Python pack [uv](https://docs.astral.sh/uv/) is an extremely fast Python package and project manager, written in Rust.
+ +## Running Griffe + +Once installed, you can run Griffe using the `griffe` command: + +```console +$ griffe check mypackage +``` + +Or as a Python module: + +```console +$ python -m griffe check mypackage +``` + +TIP: **Alternative CLI Package** +If you need to run Griffe without the full library, you can also use `python -m griffecli` instead of `python -m griffe`. This runs the CLI directly from the `griffecli` package. diff --git a/docs/introduction.md b/docs/introduction.md index bf16b1fc5..a7226fa6e 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -9,13 +9,13 @@ Griffe is both a command line tool and a Python library. The command line tool o ```bash # Load API of `my_package`, serialize it to JSON, # print it to standard output. -griffecli dump my_package +griffe dump my_package ``` ```bash # Check for API breaking changes # between current version and version 1.0 (Git reference). -griffecli check my_package --against 1.0 +griffe check my_package --against 1.0 ``` Both commands accept a `-h`, `--help` argument to show all the available options. For a complete reference of the command line interface, see [Reference / Command line interface](reference/cli.md). @@ -27,31 +27,31 @@ As a library, Griffe exposes all its public API directly in the top-level module ```python import griffe -griffelib.load(...) -griffelib.find_breaking_changes(...) -griffecli.main(...) -griffelib.visit(...) -griffelib.inspect(...) +griffe.load(...) +griffe.find_breaking_changes(...) +griffe.main(...) +griffe.visit(...) +griffe.inspect(...) ``` -To start exploring your API within Griffe data models, use the [`load`][griffelib.load] function to load your package and access its various objects: +To start exploring your API within Griffe data models, use the [`load`][griffe.load] function to load your package and access its various objects: ```python import griffe -my_package = griffelib.load("my_package") +my_package = griffe.load("my_package") some_method = my_package["some_module.SomeClass.some_method"] print(some_method.docstring.value) print(f"Is `some_method` public? {'yes' if some_method.is_public else 'no'}") ``` -Use the [`load_git`][griffelib.load_git] function to load your API at a particular moment in time, specified with a Git reference (commit hash, branch name, tag name): +Use the [`load_git`][griffe.load_git] function to load your API at a particular moment in time, specified with a Git reference (commit hash, branch name, tag name): ```python import griffe -my_package_v2_1 = griffelib.load_git("my_package", ref="2.1") +my_package_v2_1 = griffe.load_git("my_package", ref="2.1") ``` For more advanced usage, see our guide on [loading and navigating data](guide/users/loading.md). diff --git a/docs/playground.md b/docs/playground.md index 4039ad3ce..55869f3c0 100644 --- a/docs/playground.md +++ b/docs/playground.md @@ -16,6 +16,6 @@ import griffe, micropip await micropip.install("cowsay") # And load it with Griffe! -cowsay = griffelib.load("cowsay") +cowsay = griffe.load("cowsay") cowsay.as_json(indent=2)[:1000] ``` diff --git a/docs/reference/api/agents.md b/docs/reference/api/agents.md index c4b78f9c9..224426697 100644 --- a/docs/reference/api/agents.md +++ b/docs/reference/api/agents.md @@ -4,70 +4,74 @@ Griffe is able to analyze code both statically and dynamically. ## **Main API** -::: griffelib.visit +::: griffe.visit -::: griffelib.inspect +::: griffe.inspect ## **Advanced API** -::: griffelib.Visitor +::: griffe.Visitor -::: griffelib.Inspector +::: griffe.Inspector ## **Dynamic analysis helpers** -::: griffelib.sys_path +::: griffe.sys_path -::: griffelib.dynamic_import +::: griffe.dynamic_import -::: griffelib.ObjectNode +::: griffe.ObjectNode -::: griffelib.ObjectKind +::: griffe.ObjectKind ## **Static analysis helpers** -::: griffelib.builtin_decorators +::: griffe.builtin_decorators -::: griffelib.stdlib_decorators +::: griffe.stdlib_decorators -::: griffelib.typing_overload +::: griffe.typing_overload -::: griffelib.ast_kind +::: griffe.ast_kind -::: griffelib.ast_children +::: griffe.ast_children -::: griffelib.ast_previous_siblings +::: griffe.ast_previous_siblings -::: griffelib.ast_next_siblings +::: griffe.ast_next_siblings -::: griffelib.ast_siblings +::: griffe.ast_siblings -::: griffelib.ast_previous +::: griffe.ast_previous -::: griffelib.ast_next +::: griffe.ast_next -::: griffelib.ast_first_child +::: griffe.ast_first_child -::: griffelib.ast_last_child +::: griffe.ast_last_child -::: griffelib.get_docstring +::: griffe.get_docstring -::: griffelib.get_name +::: griffe.get_name -::: griffelib.get_names +::: griffe.get_names -::: griffelib.get_instance_names +::: griffe.get_instance_names -::: griffelib.get__all__ +::: griffe.get__all__ -::: griffelib.safe_get__all__ +::: griffe.safe_get__all__ -::: griffelib.relative_to_absolute +::: griffe.relative_to_absolute -::: griffelib.get_parameters +::: griffe.get_parameters -::: griffelib.get_value +::: griffe.get_value -::: griffelib.safe_get_value +::: griffe.safe_get_value + +## **Deprecated API** + +::: griffe.ExportedName diff --git a/docs/reference/api/checks.md b/docs/reference/api/checks.md index a30110d55..9caa656e5 100644 --- a/docs/reference/api/checks.md +++ b/docs/reference/api/checks.md @@ -1,33 +1,33 @@ # API checks -::: griffelib.find_breaking_changes +::: griffe.find_breaking_changes -::: griffelib.ExplanationStyle +::: griffe.ExplanationStyle -::: griffelib.Breakage +::: griffe.Breakage -::: griffelib.BreakageKind +::: griffe.BreakageKind -::: griffelib.AttributeChangedTypeBreakage +::: griffe.AttributeChangedTypeBreakage -::: griffelib.AttributeChangedValueBreakage +::: griffe.AttributeChangedValueBreakage -::: griffelib.ClassRemovedBaseBreakage +::: griffe.ClassRemovedBaseBreakage -::: griffelib.ObjectChangedKindBreakage +::: griffe.ObjectChangedKindBreakage -::: griffelib.ObjectRemovedBreakage +::: griffe.ObjectRemovedBreakage -::: griffelib.ParameterAddedRequiredBreakage +::: griffe.ParameterAddedRequiredBreakage -::: griffelib.ParameterChangedDefaultBreakage +::: griffe.ParameterChangedDefaultBreakage -::: griffelib.ParameterChangedKindBreakage +::: griffe.ParameterChangedKindBreakage -::: griffelib.ParameterChangedRequiredBreakage +::: griffe.ParameterChangedRequiredBreakage -::: griffelib.ParameterMovedBreakage +::: griffe.ParameterMovedBreakage -::: griffelib.ParameterRemovedBreakage +::: griffe.ParameterRemovedBreakage -::: griffelib.ReturnChangedTypeBreakage +::: griffe.ReturnChangedTypeBreakage diff --git a/docs/reference/api/cli.md b/docs/reference/api/cli.md index c806e83cf..08e83a31a 100644 --- a/docs/reference/api/cli.md +++ b/docs/reference/api/cli.md @@ -2,12 +2,12 @@ ## **Main API** -::: griffecli.main +::: griffe.main -::: griffecli.check +::: griffe.check -::: griffecli.dump +::: griffe.dump ## **Advanced API** -::: griffecli.get_parser +::: griffe.get_parser diff --git a/docs/reference/api/docstrings/models.md b/docs/reference/api/docstrings/models.md index ff4b97a25..17f3bdfd9 100644 --- a/docs/reference/api/docstrings/models.md +++ b/docs/reference/api/docstrings/models.md @@ -2,80 +2,80 @@ ## **Main API** -::: griffelib.Docstring +::: griffe.Docstring ## **Advanced API: Sections** -::: griffelib.DocstringSectionKind +::: griffe.DocstringSectionKind -::: griffelib.DocstringSectionText +::: griffe.DocstringSectionText -::: griffelib.DocstringSectionParameters +::: griffe.DocstringSectionParameters -::: griffelib.DocstringSectionOtherParameters +::: griffe.DocstringSectionOtherParameters -::: griffelib.DocstringSectionTypeParameters +::: griffe.DocstringSectionTypeParameters -::: griffelib.DocstringSectionRaises +::: griffe.DocstringSectionRaises -::: griffelib.DocstringSectionWarns +::: griffe.DocstringSectionWarns -::: griffelib.DocstringSectionReturns +::: griffe.DocstringSectionReturns -::: griffelib.DocstringSectionYields +::: griffe.DocstringSectionYields -::: griffelib.DocstringSectionReceives +::: griffe.DocstringSectionReceives -::: griffelib.DocstringSectionExamples +::: griffe.DocstringSectionExamples -::: griffelib.DocstringSectionAttributes +::: griffe.DocstringSectionAttributes -::: griffelib.DocstringSectionFunctions +::: griffe.DocstringSectionFunctions -::: griffelib.DocstringSectionClasses +::: griffe.DocstringSectionClasses -::: griffelib.DocstringSectionTypeAliases +::: griffe.DocstringSectionTypeAliases -::: griffelib.DocstringSectionModules +::: griffe.DocstringSectionModules -::: griffelib.DocstringSectionDeprecated +::: griffe.DocstringSectionDeprecated -::: griffelib.DocstringSectionAdmonition +::: griffe.DocstringSectionAdmonition ## **Advanced API: Section items** -::: griffelib.DocstringAdmonition +::: griffe.DocstringAdmonition -::: griffelib.DocstringDeprecated +::: griffe.DocstringDeprecated -::: griffelib.DocstringRaise +::: griffe.DocstringRaise -::: griffelib.DocstringWarn +::: griffe.DocstringWarn -::: griffelib.DocstringReturn +::: griffe.DocstringReturn -::: griffelib.DocstringYield +::: griffe.DocstringYield -::: griffelib.DocstringReceive +::: griffe.DocstringReceive -::: griffelib.DocstringParameter +::: griffe.DocstringParameter -::: griffelib.DocstringTypeParameter +::: griffe.DocstringTypeParameter -::: griffelib.DocstringAttribute +::: griffe.DocstringAttribute -::: griffelib.DocstringFunction +::: griffe.DocstringFunction -::: griffelib.DocstringClass +::: griffe.DocstringClass -::: griffelib.DocstringTypeAlias +::: griffe.DocstringTypeAlias -::: griffelib.DocstringModule +::: griffe.DocstringModule ## **Models base classes** -::: griffelib.DocstringElement +::: griffe.DocstringElement -::: griffelib.DocstringNamedElement +::: griffe.DocstringNamedElement -::: griffelib.DocstringSection +::: griffe.DocstringSection diff --git a/docs/reference/api/docstrings/parsers.md b/docs/reference/api/docstrings/parsers.md index e4345ba77..625d1dbb0 100644 --- a/docs/reference/api/docstrings/parsers.md +++ b/docs/reference/api/docstrings/parsers.md @@ -2,42 +2,42 @@ ## **Main API** -::: griffelib.parse +::: griffe.parse -::: griffelib.parse_auto +::: griffe.parse_auto -::: griffelib.parse_google +::: griffe.parse_google -::: griffelib.parse_numpy +::: griffe.parse_numpy -::: griffelib.parse_sphinx +::: griffe.parse_sphinx -::: griffelib.DocstringStyle +::: griffe.DocstringStyle ## **Parser options** -::: griffelib.DocstringOptions +::: griffe.DocstringOptions -::: griffelib.GoogleOptions +::: griffe.GoogleOptions -::: griffelib.NumpyOptions +::: griffe.NumpyOptions -::: griffelib.SphinxOptions +::: griffe.SphinxOptions -::: griffelib.AutoOptions +::: griffe.AutoOptions -::: griffelib.PerStyleOptions +::: griffe.PerStyleOptions ## **Advanced API** -::: griffelib.Parser +::: griffe.Parser -::: griffelib.parsers +::: griffe.parsers -::: griffelib.parse_docstring_annotation +::: griffe.parse_docstring_annotation -::: griffelib.docstring_warning +::: griffe.docstring_warning -::: griffelib.DocstringDetectionMethod +::: griffe.DocstringDetectionMethod -::: griffelib.infer_docstring_style +::: griffe.infer_docstring_style diff --git a/docs/reference/api/exceptions.md b/docs/reference/api/exceptions.md index 8630c15ec..e33a10071 100644 --- a/docs/reference/api/exceptions.md +++ b/docs/reference/api/exceptions.md @@ -1,27 +1,27 @@ # Exceptions -::: griffelib.GriffeError +::: griffe.GriffeError -::: griffelib.LoadingError +::: griffe.LoadingError -::: griffelib.NameResolutionError +::: griffe.NameResolutionError -::: griffelib.UnhandledEditableModuleError +::: griffe.UnhandledEditableModuleError -::: griffelib.UnimportableModuleError +::: griffe.UnimportableModuleError -::: griffelib.AliasResolutionError +::: griffe.AliasResolutionError -::: griffelib.CyclicAliasError +::: griffe.CyclicAliasError -::: griffelib.LastNodeError +::: griffe.LastNodeError -::: griffelib.RootNodeError +::: griffe.RootNodeError -::: griffelib.BuiltinModuleError +::: griffe.BuiltinModuleError -::: griffelib.ExtensionError +::: griffe.ExtensionError -::: griffelib.ExtensionNotLoadedError +::: griffe.ExtensionNotLoadedError -::: griffelib.GitError +::: griffe.GitError diff --git a/docs/reference/api/expressions.md b/docs/reference/api/expressions.md index 4b3395c39..3b010a5d0 100644 --- a/docs/reference/api/expressions.md +++ b/docs/reference/api/expressions.md @@ -1,6 +1,6 @@ # Expressions -::: griffelib._internal.expressions +::: griffe._internal.expressions options: members: false show_root_heading: false @@ -10,88 +10,88 @@ ## **Helpers** -::: griffelib.get_annotation +::: griffe.get_annotation -::: griffelib.get_base_class +::: griffe.get_base_class -::: griffelib.get_class_keyword +::: griffe.get_class_keyword -::: griffelib.get_condition +::: griffe.get_condition -::: griffelib.get_expression +::: griffe.get_expression -::: griffelib.safe_get_annotation +::: griffe.safe_get_annotation -::: griffelib.safe_get_base_class +::: griffe.safe_get_base_class -::: griffelib.safe_get_class_keyword +::: griffe.safe_get_class_keyword -::: griffelib.safe_get_condition +::: griffe.safe_get_condition -::: griffelib.safe_get_expression +::: griffe.safe_get_expression ## **Expression nodes** -::: griffelib.Expr +::: griffe.Expr -::: griffelib.ExprAttribute +::: griffe.ExprAttribute -::: griffelib.ExprBinOp +::: griffe.ExprBinOp -::: griffelib.ExprBoolOp +::: griffe.ExprBoolOp -::: griffelib.ExprCall +::: griffe.ExprCall -::: griffelib.ExprCompare +::: griffe.ExprCompare -::: griffelib.ExprComprehension +::: griffe.ExprComprehension -::: griffelib.ExprConstant +::: griffe.ExprConstant -::: griffelib.ExprDict +::: griffe.ExprDict -::: griffelib.ExprDictComp +::: griffe.ExprDictComp -::: griffelib.ExprExtSlice +::: griffe.ExprExtSlice -::: griffelib.ExprFormatted +::: griffe.ExprFormatted -::: griffelib.ExprGeneratorExp +::: griffe.ExprGeneratorExp -::: griffelib.ExprIfExp +::: griffe.ExprIfExp -::: griffelib.ExprJoinedStr +::: griffe.ExprJoinedStr -::: griffelib.ExprKeyword +::: griffe.ExprKeyword -::: griffelib.ExprVarPositional +::: griffe.ExprVarPositional -::: griffelib.ExprVarKeyword +::: griffe.ExprVarKeyword -::: griffelib.ExprLambda +::: griffe.ExprLambda -::: griffelib.ExprList +::: griffe.ExprList -::: griffelib.ExprListComp +::: griffe.ExprListComp -::: griffelib.ExprName +::: griffe.ExprName -::: griffelib.ExprNamedExpr +::: griffe.ExprNamedExpr -::: griffelib.ExprParameter +::: griffe.ExprParameter -::: griffelib.ExprSet +::: griffe.ExprSet -::: griffelib.ExprSetComp +::: griffe.ExprSetComp -::: griffelib.ExprSlice +::: griffe.ExprSlice -::: griffelib.ExprSubscript +::: griffe.ExprSubscript -::: griffelib.ExprTuple +::: griffe.ExprTuple -::: griffelib.ExprUnaryOp +::: griffe.ExprUnaryOp -::: griffelib.ExprYield +::: griffe.ExprYield -::: griffelib.ExprYieldFrom +::: griffe.ExprYieldFrom diff --git a/docs/reference/api/extensions.md b/docs/reference/api/extensions.md index 8ae746205..42ee96a80 100644 --- a/docs/reference/api/extensions.md +++ b/docs/reference/api/extensions.md @@ -2,26 +2,26 @@ ## **Main API** -::: griffelib.load_extensions +::: griffe.load_extensions -::: griffelib.Extension +::: griffe.Extension ## **Advanced API** -::: griffelib.Extensions +::: griffe.Extensions ## **Types** -::: griffelib.LoadableExtensionType +::: griffe.LoadableExtensionType ## **Builtin extensions** -::: griffelib.builtin_extensions +::: griffe.builtin_extensions -::: griffelib.DataclassesExtension +::: griffe.DataclassesExtension options: inherited_members: false -::: griffelib.UnpackTypedDictExtension +::: griffe.UnpackTypedDictExtension options: inherited_members: false diff --git a/docs/reference/api/finder.md b/docs/reference/api/finder.md index f79f92565..54c452e31 100644 --- a/docs/reference/api/finder.md +++ b/docs/reference/api/finder.md @@ -2,14 +2,14 @@ ## **Advanced API** -::: griffelib.ModuleFinder +::: griffe.ModuleFinder -::: griffelib.Package +::: griffe.Package -::: griffelib.NamespacePackage +::: griffe.NamespacePackage ## **Types** -::: griffelib.NamePartsType +::: griffe.NamePartsType -::: griffelib.NamePartsAndPathType +::: griffe.NamePartsAndPathType diff --git a/docs/reference/api/git.md b/docs/reference/api/git.md new file mode 100644 index 000000000..7abc81fcf --- /dev/null +++ b/docs/reference/api/git.md @@ -0,0 +1,13 @@ +# Git utilities + + + +DANGER: **Deprecated utilities.** We have decided to stop exposing Git-related utilities as it's not a core part of the library's functionality. The functions documented on this page will become unavailable in the next major version. + +::: griffe.assert_git_repo + +::: griffe.get_latest_tag + +::: griffe.get_repo_root + +::: griffe.tmp_worktree diff --git a/docs/reference/api/helpers.md b/docs/reference/api/helpers.md index 4267786da..74e44d05a 100644 --- a/docs/reference/api/helpers.md +++ b/docs/reference/api/helpers.md @@ -1,21 +1,21 @@ # Helpers -::: griffelib.TmpPackage +::: griffe.TmpPackage -::: griffelib.temporary_pyfile +::: griffe.temporary_pyfile -::: griffelib.temporary_pypackage +::: griffe.temporary_pypackage -::: griffelib.temporary_visited_module +::: griffe.temporary_visited_module -::: griffelib.temporary_visited_package +::: griffe.temporary_visited_package -::: griffelib.temporary_inspected_module +::: griffe.temporary_inspected_module -::: griffelib.temporary_inspected_package +::: griffe.temporary_inspected_package -::: griffelib.vtree +::: griffe.vtree -::: griffelib.htree +::: griffe.htree -::: griffelib.module_vtree +::: griffe.module_vtree diff --git a/docs/reference/api/loaders.md b/docs/reference/api/loaders.md index 10dccf38c..b3eb060c9 100644 --- a/docs/reference/api/loaders.md +++ b/docs/reference/api/loaders.md @@ -2,22 +2,22 @@ ## **Main API** -::: griffelib.load +::: griffe.load -::: griffelib.load_git +::: griffe.load_git -::: griffelib.load_pypi +::: griffe.load_pypi ## **Advanced API** -::: griffelib.GriffeLoader +::: griffe.GriffeLoader -::: griffelib.ModulesCollection +::: griffe.ModulesCollection -::: griffelib.LinesCollection +::: griffe.LinesCollection ## **Additional API** -::: griffelib.Stats +::: griffe.Stats -::: griffelib.merge_stubs +::: griffe.merge_stubs diff --git a/docs/reference/api/loggers.md b/docs/reference/api/loggers.md index 2611b9c2e..0ba1d0dbd 100644 --- a/docs/reference/api/loggers.md +++ b/docs/reference/api/loggers.md @@ -2,18 +2,18 @@ ## **Main API** -::: griffelib.logger +::: griffe.logger -::: griffelib.get_logger +::: griffe.get_logger -::: griffelib.Logger +::: griffe.Logger -::: griffelib.LogLevel +::: griffe.LogLevel -::: griffecli.DEFAULT_LOG_LEVEL +::: griffe.DEFAULT_LOG_LEVEL options: annotations_path: full ## **Advanced API** -::: griffelib.patch_loggers +::: griffe.patch_loggers diff --git a/docs/reference/api/models.md b/docs/reference/api/models.md index 76732f917..3b7f35316 100644 --- a/docs/reference/api/models.md +++ b/docs/reference/api/models.md @@ -10,41 +10,41 @@ Indirections to objects declared in other modules are represented as "aliases". The 6 models: -- [`Module`][griffelib.Module] -- [`Class`][griffelib.Class] -- [`Function`][griffelib.Function] -- [`Attribute`][griffelib.Attribute] -- [`Alias`][griffelib.Alias] -- [`TypeAlias`][griffelib.TypeAlias] +- [`Module`][griffe.Module] +- [`Class`][griffe.Class] +- [`Function`][griffe.Function] +- [`Attribute`][griffe.Attribute] +- [`Alias`][griffe.Alias] +- [`TypeAlias`][griffe.TypeAlias] ## **Model kind enumeration** -::: griffelib.Kind +::: griffe.Kind ## **Model base classes** -::: griffelib.GetMembersMixin +::: griffe.GetMembersMixin -::: griffelib.SetMembersMixin +::: griffe.SetMembersMixin -::: griffelib.DelMembersMixin +::: griffe.DelMembersMixin -::: griffelib.SerializationMixin +::: griffe.SerializationMixin -::: griffelib.ObjectAliasMixin +::: griffe.ObjectAliasMixin -::: griffelib.Object +::: griffe.Object ## **Type parameters** -::: griffelib.TypeParameters +::: griffe.TypeParameters -::: griffelib.TypeParameter +::: griffe.TypeParameter -::: griffelib.TypeParameterKind +::: griffe.TypeParameterKind ## **Git information** -::: griffelib.KnownGitService +::: griffe.KnownGitService -::: griffelib.GitInfo +::: griffe.GitInfo diff --git a/docs/reference/api/models/alias.md b/docs/reference/api/models/alias.md index ae146795d..df1419cc3 100644 --- a/docs/reference/api/models/alias.md +++ b/docs/reference/api/models/alias.md @@ -1 +1 @@ -# ::: griffelib.Alias +# ::: griffe.Alias diff --git a/docs/reference/api/models/attribute.md b/docs/reference/api/models/attribute.md index 2ca25220b..89abf00d6 100644 --- a/docs/reference/api/models/attribute.md +++ b/docs/reference/api/models/attribute.md @@ -1 +1 @@ -# ::: griffelib.Attribute +# ::: griffe.Attribute diff --git a/docs/reference/api/models/class.md b/docs/reference/api/models/class.md index 2bcc01425..f6720d4b8 100644 --- a/docs/reference/api/models/class.md +++ b/docs/reference/api/models/class.md @@ -1,5 +1,5 @@ -# ::: griffelib.Class +# ::: griffe.Class ## **Utilities** -::: griffelib.c3linear_merge +::: griffe.c3linear_merge diff --git a/docs/reference/api/models/function.md b/docs/reference/api/models/function.md index ffe172ddc..20003780b 100644 --- a/docs/reference/api/models/function.md +++ b/docs/reference/api/models/function.md @@ -1,11 +1,11 @@ -# ::: griffelib.Function +# ::: griffe.Function -::: griffelib.Parameters +::: griffe.Parameters -::: griffelib.Parameter +::: griffe.Parameter -::: griffelib.ParameterKind +::: griffe.ParameterKind -::: griffelib.ParametersType +::: griffe.ParametersType -::: griffelib.Decorator +::: griffe.Decorator diff --git a/docs/reference/api/models/module.md b/docs/reference/api/models/module.md index 39a74357f..ea42941f9 100644 --- a/docs/reference/api/models/module.md +++ b/docs/reference/api/models/module.md @@ -1 +1 @@ -# ::: griffelib.Module +# ::: griffe.Module diff --git a/docs/reference/api/models/type_alias.md b/docs/reference/api/models/type_alias.md index 8033a7f5b..367d906d5 100644 --- a/docs/reference/api/models/type_alias.md +++ b/docs/reference/api/models/type_alias.md @@ -1,3 +1,3 @@ # Type Alias -::: griffelib.TypeAlias +::: griffe.TypeAlias diff --git a/docs/reference/api/serializers.md b/docs/reference/api/serializers.md index 2ac8a7b76..c9fff7b4e 100644 --- a/docs/reference/api/serializers.md +++ b/docs/reference/api/serializers.md @@ -2,10 +2,10 @@ ## **Main API** -See the [`as_json()`][griffelib.Object.as_json] and [`from_json()`][griffelib.Object.from_json] methods of objects. +See the [`as_json()`][griffe.Object.as_json] and [`from_json()`][griffe.Object.from_json] methods of objects. ## **Advanced API** -::: griffelib.JSONEncoder +::: griffe.JSONEncoder -::: griffelib.json_decoder +::: griffe.json_decoder diff --git a/docs/reference/docstrings.md b/docs/reference/docstrings.md index e6b342212..dd26177b0 100644 --- a/docs/reference/docstrings.md +++ b/docs/reference/docstrings.md @@ -68,7 +68,7 @@ Note: Find out possibly invalid section syntax by grepping for "reasons" in Griffe debug logs: ```bash -griffecli dump -Ldebug -o/dev/null -fdgoogle your_package 2>&1 | grep reasons +griffe dump -Ldebug -o/dev/null -fdgoogle your_package 2>&1 | grep reasons ``` Some sections support documenting multiple items (attributes, parameters, etc.). When multiple items are supported, each item description can use multiple lines, and continuation lines must be indented once more so that the parser is able to differentiate items. diff --git a/docs/schema-docstrings-options.json b/docs/schema-docstrings-options.json index dfdb081fe..516d86eb7 100644 --- a/docs/schema-docstrings-options.json +++ b/docs/schema-docstrings-options.json @@ -5,19 +5,19 @@ "properties": { "ignore_init_summary": { "title": "Whether to discard the summary line in `__init__` methods' docstrings.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffelib.docstrings.google.parse", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffe.docstrings.google.parse", "type": "boolean", "default": false }, "trim_doctest_flags": { "title": "Whether to remove doctest flags from Python example blocks.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffelib.docstrings.google.parse", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffe.docstrings.google.parse", "type": "boolean", "default": true }, "returns_multiple_items": { "title": "Whether the `Returns` section has multiple items.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffelib.docstrings.google.parse", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/griffe/docstrings/google/#griffe.docstrings.google.parse", "type": "boolean", "default": true } diff --git a/docs/schema.json b/docs/schema.json index 7b76c4412..2af3ca516 100644 --- a/docs/schema.json +++ b/docs/schema.json @@ -7,32 +7,32 @@ "properties": { "name": { "title": "The name of the alias.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.name", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.name", "type": "string" }, "kind": { "title": "The 'alias' kind.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.kind", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.kind", "const": "alias" }, "path": { "title": "The alias path.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.path", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.path", "type": "string" }, "target_path": { "title": "For aliases, the Python path of their target.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.target_path", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.target_path", "type": "string" }, "lineno": { "title": "For aliases, the import starting line number in their own module.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.lineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.lineno", "type": "integer" }, "endlineno": { "title": "For aliases, the import ending line number in their own module.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.endlineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.endlineno", "type": [ "integer", "null" @@ -40,17 +40,17 @@ }, "inherited": { "title": "Whether the alias is the member of another alias.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.inherited", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.inherited", "type": "boolean" }, "runtime": { "title": "Whether the alias exists at runtime.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.runtime", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.runtime", "type": "boolean" }, "public": { "title": "Whether the alias is public.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.public", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.public", "type": [ "null", "boolean" @@ -58,7 +58,7 @@ }, "deprecated": { "title": "Whether the alias is explicitly marked as deprecated.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.deprecated", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.deprecated", "type": [ "null", "boolean", @@ -67,7 +67,7 @@ }, "analysis": { "title": "The type of analysis used to load this alias.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.analysis", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.analysis", "type": [ "null", "string" @@ -80,42 +80,42 @@ }, "is_public": { "title": "Whether the alias is public.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_public", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_public", "type": "boolean" }, "is_deprecated": { "title": "Whether the alias is deprecated.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_deprecated", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_deprecated", "type": "boolean" }, "is_private": { "title": "Whether the alias is private.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_private", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_private", "type": "boolean" }, "is_class_private": { "title": "Whether the alias is class-private.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_class_private", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_class_private", "type": "boolean" }, "is_special": { "title": "Whether the alias is special.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_special", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_special", "type": "boolean" }, "is_imported": { "title": "Whether the alias is imported.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_imported", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_imported", "type": "boolean" }, "is_exported": { "title": "Whether the alias is exported.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_exported", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_exported", "type": "boolean" }, "is_wildcard_exposed": { "title": "Whether the alias is wildcard-exposed.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Alias.is_wildcard_exposed", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Alias.is_wildcard_exposed", "type": "boolean" } }, @@ -133,12 +133,12 @@ "properties": { "name": { "title": "The name of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.name", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.name", "type": "string" }, "kind": { "title": "The kind of object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.kind", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.kind", "enum": [ "module", "class", @@ -149,32 +149,32 @@ }, "path": { "title": "The path of the object (dot-separated Python path).", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.path", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.path", "type": "string" }, "filepath": { "title": "The file path of the object's parent module.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.filepath", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.filepath", "type": "string" }, "relative_filepath": { "title": "The file path of the object's parent module, relative to the (at the time) current working directory.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.relative_filepath", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.relative_filepath", "type": "string" }, "relative_package_filepath": { "title": "The file path of the object's package, as found in the explored directories of the Python paths.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.relative_package_filepath", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.relative_package_filepath", "type": "string" }, "git_info": { "title": "The Git information associated to this object's package.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Object.git_info", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Object.git_info", "$ref": "#/$defs/GitInfo" }, "source_link": { "title": "The source link of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.source_link", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.source_link", "type": [ "string", "null" @@ -182,7 +182,7 @@ }, "public": { "title": "Whether the object was explicitly marked as public.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.public", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.public", "type": [ "null", "boolean" @@ -190,7 +190,7 @@ }, "exports": { "title": "The exports of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.exports", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.exports", "type": [ "null", "array" @@ -201,17 +201,17 @@ }, "imports": { "title": "The imports of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.imports", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.imports", "type": "object" }, "runtime": { "title": "Whether this object exists at runtime.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.runtime", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.runtime", "type": "boolean" }, "deprecated": { "title": "Whether the object was explicitly marked as deprecated.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.deprecated", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.deprecated", "type": [ "null", "string", @@ -220,7 +220,7 @@ }, "analysis": { "title": "The type of analysis used to load this object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffelib.Object.analysis", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/alias/#griffe.Object.analysis", "type": [ "null", "string" @@ -233,27 +233,27 @@ }, "labels": { "title": "The labels of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.labels", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.labels", "type": "array" }, "docstring": { "title": "The docstring of the object.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring", "type": "object", "properties": { "value": { "title": "The actual string.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.value", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.value", "type": "string" }, "lineno": { "title": "The docstring starting line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.lineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.lineno", "type": "integer" }, "endlineno": { "title": "The docstring ending line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.endlineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.endlineno", "type": [ "integer", "null" @@ -261,7 +261,7 @@ }, "parsed": { "title": "The parsed docstring (list of docstring sections).", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.parsed", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.parsed", "type": "array", "items": { "type": "object", @@ -312,12 +312,12 @@ }, "lineno": { "title": "The docstring starting line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.lineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.lineno", "type": "integer" }, "endlineno": { "title": "The docstring ending line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffelib.Docstring.endlineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/docstrings/models/#griffe.Docstring.endlineno", "type": [ "integer", "null" @@ -325,42 +325,42 @@ }, "is_public": { "title": "Whether the object is public.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_public", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_public", "type": "boolean" }, "is_deprecated": { "title": "Whether the object is deprecated.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_deprecated", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_deprecated", "type": "boolean" }, "is_private": { "title": "Whether the object is private.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_private", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_private", "type": "boolean" }, "is_class_private": { "title": "Whether the object is class-private.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_class_private", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_class_private", "type": "boolean" }, "is_special": { "title": "Whether the object is special.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_special", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_special", "type": "boolean" }, "is_imported": { "title": "Whether the object is imported.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_imported", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_imported", "type": "boolean" }, "is_exported": { "title": "Whether the object is exported.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_exported", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_exported", "type": "boolean" }, "is_wildcard_exposed": { "title": "Whether the object is wildcard-exposed.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.Object.is_wildcard_exposed", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.Object.is_wildcard_exposed", "type": "boolean" }, "bases": true, @@ -390,7 +390,7 @@ "properties": { "bases": { "title": "For classes, their bases classes.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffelib.Class.bases", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffe.Class.bases", "type": "array", "items": { "$ref": "#/$defs/annotation" @@ -398,24 +398,24 @@ }, "decorators": { "title": "For classes, their decorators.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffelib.Class.decorators", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffe.Class.decorators", "type": "array", "items": { "type": "object", "properties": { "value": { "title": "The decorator value (string, name or expression).", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Decorator.value", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Decorator.value", "$ref": "#/$defs/annotation" }, "lineno": { "title": "The decorator starting line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Decorator.lineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Decorator.lineno", "type": "integer" }, "endlineno": { "title": "The decorator ending line number.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Decorator.endlineno", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Decorator.endlineno", "type": [ "integer", "null" @@ -432,7 +432,7 @@ }, "type_parameters": { "title": "For classes, their type parameters.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffelib.Class.type_parameters", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/class/#griffe.Class.type_parameters", "type": "array", "items": { "$ref": "#/$defs/type_parameter" @@ -457,29 +457,29 @@ "properties": { "parameters": { "title": "For functions, their parameters.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Function.parameters", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Function.parameters", "type": "array", "items": { "type": "object", "properties": { "name": { "title": "The name of the parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Parameter.name", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Parameter.name", "type": "string" }, "annotation": { "title": "The annotation of the parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Parameter.annotation", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Parameter.annotation", "$ref": "#/$defs/annotation" }, "kind": { "title": "The kind of parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Parameter.kind", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Parameter.kind", "type": "string" }, "default": { "title": "The default value of the parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Parameter.default", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Parameter.default", "$ref": "#/$defs/annotation" } }, @@ -491,12 +491,12 @@ }, "returns": { "title": "For functions, their return annotation.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Function.returns", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Function.returns", "$ref": "#/$defs/annotation" }, "type_parameters": { "title": "For functions, their type parameters.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffelib.Function.type_parameters", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/function/#griffe.Function.type_parameters", "type": "array", "items": { "$ref": "#/$defs/type_parameter" @@ -521,12 +521,12 @@ "properties": { "value": { "title": "For attributes, their value.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/attribute/#griffelib.Attribute.value", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/attribute/#griffe.Attribute.value", "$ref": "#/$defs/annotation" }, "annotation": { "title": "For attributes, their type annotation.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/attribute/#griffelib.Attribute.annotation", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/attribute/#griffe.Attribute.annotation", "$ref": "#/$defs/annotation" } } @@ -544,12 +544,12 @@ "properties": { "value": { "title": "For type aliases, their value.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/type_alias/#griffelib.TypeAlias.value", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/type_alias/#griffe.TypeAlias.value", "$ref": "#/$defs/annotation" }, "type_parameters": { "title": "For type aliases, their type parameters.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/type_alias/#griffelib.TypeAlias.type_parameters", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/type_alias/#griffe.TypeAlias.type_parameters", "type": "array", "items": { "$ref": "#/$defs/type_parameter" @@ -584,17 +584,17 @@ }, "type_parameter": { "title": "Type Parameter.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter", "type": "object", "properties": { "name": { "title": "The type parameter name.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter.name", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter.name", "type": "string" }, "kind": { "title": "The type parameter kind.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter.kind", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter.kind", "enum": [ "type-var", "type-var-tuple", @@ -603,12 +603,12 @@ }, "annotation": { "title": "The type parameter bound or constraints.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter.annotation", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter.annotation", "$ref": "#/$defs/annotation" }, "default": { "title": "The type parameter default.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.TypeParameter.default", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.TypeParameter.default", "$ref": "#/$defs/annotation" } }, @@ -622,19 +622,19 @@ }, "GitInfo": { "title": "Git information.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo", "type": "object", "properties": { "repository": { "title": "The repository local path.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo.repository", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo.repository", "type": [ "string" ] }, "service": { "title": "The Git service (e.g., 'github', 'gitlab', 'bitbucket').", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo.service", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo.service", "type": [ "string" ], @@ -651,14 +651,14 @@ }, "remote_url": { "title": "The remote URL.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo.remote_url", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo.remote_url", "type": [ "string" ] }, "commit_hash": { "title": "The commit hash.", - "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffelib.GitInfo.commit_hash", + "markdownDescription": "https://mkdocstrings.github.io/griffe/reference/api/models/#griffe.GitInfo.commit_hash", "type": [ "string" ] diff --git a/packages/griffecli/src/griffecli/_internal/cli.py b/packages/griffecli/src/griffecli/_internal/cli.py index b13154dc9..a78a52fbe 100644 --- a/packages/griffecli/src/griffecli/_internal/cli.py +++ b/packages/griffecli/src/griffecli/_internal/cli.py @@ -138,7 +138,7 @@ def get_parser() -> argparse.ArgumentParser: description = "Signatures for entire Python programs. " "Extract the structure, the frame, the skeleton of your project, " "to generate API documentation or find breaking changes in your API." - parser = argparse.ArgumentParser(add_help=False, usage=usage, description=description, prog="griffelib") + parser = argparse.ArgumentParser(add_help=False, usage=usage, description=description, prog="griffe") main_help = "Show this help message and exit. Commands also accept the -h/--help option." subcommand_help = "Show this help message and exit." @@ -215,7 +215,7 @@ def add_common_options(subparser: argparse.ArgumentParser) -> None: dest="subcommand", title="Commands", metavar="COMMAND", - prog="griffelib", + prog="griffe", required=True, ) @@ -511,7 +511,7 @@ def check( against = against or _get_latest_tag(package) repository = _get_repo_root(against_path) except GitError as error: - print(f"griffelib: error: {error}", file=sys.stderr) + print(f"griffe: error: {error}", file=sys.stderr) return 2 # Load old and new version of the package. @@ -577,7 +577,7 @@ def check( def main(args: list[str] | None = None) -> int: """Run the main program. - This function is executed when you type `griffelib` or `python -m griffelib`. + This function is executed when you type `griffe` or `python -m griffe`. Parameters: args: Arguments passed from the command line. @@ -599,7 +599,7 @@ def main(args: list[str] | None = None) -> int: except AttributeError: choices = "', '".join(_level_choices) print( - f"griffelib: error: invalid log level '{log_level}' (choose from '{choices}')", + f"griffe: error: invalid log level '{log_level}' (choose from '{choices}')", file=sys.stderr, ) return 1 diff --git a/pyproject.toml b/pyproject.toml index 3bddfc0db..77f2bc30a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -136,3 +136,7 @@ ci = [ [tool.uv] default-groups = ["maintain", "ci", "docs"] workspace = { members = ["packages/*"] } + +[tool.uv.sources] +griffelib = { workspace = true } +griffecli = { workspace = true } From b310df2baebb08112a821c75181986a3f375d7df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 23:48:37 +0000 Subject: [PATCH 12/53] Fix griffe._internal references to griffelib._internal in docs Co-authored-by: johnslavik <64036239+johnslavik@users.noreply.github.com> --- docs/extensions/official/runtime-objects.md | 2 +- docs/guide/contributors/architecture.md | 8 ++++---- docs/guide/users/loading.md | 14 +++++++------- docs/guide/users/navigating.md | 12 ++++++------ docs/reference/api/expressions.md | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/extensions/official/runtime-objects.md b/docs/extensions/official/runtime-objects.md index fbfb72d34..27b391e8a 100644 --- a/docs/extensions/official/runtime-objects.md +++ b/docs/extensions/official/runtime-objects.md @@ -15,7 +15,7 @@ This extension stores runtime objects corresponding to each loaded Griffe object >>> griffe_data["parse"].extra defaultdict(, {'runtime-objects': {'object': }}) >>> griffe_data["Module"].extra -defaultdict(, {'runtime-objects': {'object': }}) +defaultdict(, {'runtime-objects': {'object': }}) ``` It can be useful in combination with mkdocstrings-python and custom templates, to iterate over object values or their attributes that couldn't be loaded by Griffe itself (for example, objects built dynamically and loaded as attributes won't have "members" to iterate over). diff --git a/docs/guide/contributors/architecture.md b/docs/guide/contributors/architecture.md index edd5a94ec..3fc474e75 100644 --- a/docs/guide/contributors/architecture.md +++ b/docs/guide/contributors/architecture.md @@ -23,7 +23,7 @@ descriptions = { "site": "Documentation site, built with `make run mkdocs build` (git-ignored).", "src": "The source of our Python package(s). See [Sources](#sources) and [Program structure](#program-structure).", "src/griffe": "Our public API, exposed to users. See [Program structure](#program-structure).", - "src/griffe/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).", + "packages/griffelib/src/griffelib/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).", "tests": "Our test suite. See [Tests](#tests).", ".copier-answers.yml": "The answers file generated by [Copier](https://copier.readthedocs.io/en/stable/). See [Boilerplate](#boilerplate).", "devdeps.txt": "Our development dependencies specification. See [`make setup`][command-setup] command.", @@ -104,11 +104,11 @@ Sources are located in the `src` folder, following the [src-layout](https://pack Our test suite is located in the `tests` folder. It is located outside of the sources as to not pollute distributions (it would be very wrong to publish a `tests` package as part of our distributions, since this name is extremely common), or worse, the public API. The `tests` folder is however included in our source distributions (`.tar.gz`), alongside most of our metadata and configuration files. Check out `pyproject.toml` to get the full list of files included in our source distributions. -The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffe._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. +The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffelib._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. ## Program structure -The internal API is contained within the `src/griffe/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from various submodules of `griffe._internal`. +The internal API is contained within the `packages/griffelib/src/griffelib/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from `griffelib`, which itself imports from various submodules of `griffelib._internal`. Users then import `griffe` directly, or import objects from it. @@ -122,7 +122,7 @@ if os.getenv("DEPLOY") == "true": from pydeps.target import Target cli.verbose = cli._not_verbose - options = cli.parse_args(["src/griffe", "--noshow", "--reverse"]) + options = cli.parse_args(["packages/griffelib/src/griffelib", "--noshow", "--reverse"]) colors.START_COLOR = 128 target = Target(options["fname"]) with target.chdir_work(): diff --git a/docs/guide/users/loading.md b/docs/guide/users/loading.md index 620917803..4bbd1c12a 100644 --- a/docs/guide/users/loading.md +++ b/docs/guide/users/loading.md @@ -214,10 +214,10 @@ from package1 import X False >>> package2["X"].target Traceback (most recent call last): - File "griffe/_internal/models.py", line 1375, in _resolve_target + File "griffelib/_internal/models.py", line 1375, in _resolve_target resolved = self.modules_collection.get_member(self.target_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "griffe/_internal/mixins.py", line 84, in get_member + File "griffelib/_internal/mixins.py", line 84, in get_member return self.members[parts[0]].get_member(parts[1:]) # type: ignore[attr-defined] ~~~~~~~~~~~~^^^^^^^^^^ KeyError: 'package1' @@ -226,13 +226,13 @@ The above exception was the direct cause of the following exception: Traceback (most recent call last): File "", line 1, in - File "griffe/_internal/dataclasses.py", line 1310, in target + File "griffelib/_internal/dataclasses.py", line 1310, in target self.resolve_target() - File "griffe/_internal/dataclasses.py", line 1369, in resolve_target + File "griffelib/_internal/dataclasses.py", line 1369, in resolve_target self._resolve_target() - File "griffe/_internal/dataclasses.py", line 1377, in _resolve_target + File "griffelib/_internal/dataclasses.py", line 1377, in _resolve_target raise AliasResolutionError(self) from error -griffe._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) +griffelib._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) ``` As you can see in the interpreter session above, Griffe did not resolve the `X` alias. When we tried to access its target object anyway, it failed with a `KeyError`, which was raised again as an [`AliasResolutionError`][griffe.AliasResolutionError]. @@ -250,7 +250,7 @@ False # Hmm? >>> package2["X"].target Traceback (most recent call last): ... -griffe._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) +griffelib._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) ``` The same exception again? What happened here? We loaded both packages, but Griffe still failed to resolve the alias. That is expected; here is the explanation. diff --git a/docs/guide/users/navigating.md b/docs/guide/users/navigating.md index 75a1a0ab3..1d1c169fe 100644 --- a/docs/guide/users/navigating.md +++ b/docs/guide/users/navigating.md @@ -14,17 +14,17 @@ When [loading an object](loading.md), Griffe will give you back an instance of o ```python >>> import griffe >>> type(griffe.load("markdown")) - + >>> type(griffe.load("markdown.core.Markdown")) - + >>> type(griffe.load("markdown.Markdown")) - + >>> type(griffe.load("markdown.core.markdown")) - + >>> type(griffe.load("markdown.markdown")) - + >>> type(griffe.load("markdown.Markdown.references")) - + ``` However deep the object is, Griffe loads the entire package. It means that in all the cases above, Griffe loaded the whole `markdown` package. The model instance Griffe gives you back is therefore part of a tree that you can navigate. diff --git a/docs/reference/api/expressions.md b/docs/reference/api/expressions.md index 3b010a5d0..d91795c79 100644 --- a/docs/reference/api/expressions.md +++ b/docs/reference/api/expressions.md @@ -1,6 +1,6 @@ # Expressions -::: griffe._internal.expressions +::: griffelib._internal.expressions options: members: false show_root_heading: false From e647fedd08c589fde50afd74e747e01336b509d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 2 Dec 2025 15:42:20 +0100 Subject: [PATCH 13/53] reapply yore fix -b2 --- docs/guide/contributors/workflow.md | 4 ++-- docs/reference/api/agents.md | 4 ---- docs/reference/api/git.md | 13 ------------- 3 files changed, 2 insertions(+), 19 deletions(-) delete mode 100644 docs/reference/api/git.md diff --git a/docs/guide/contributors/workflow.md b/docs/guide/contributors/workflow.md index 0e6064a49..70fde1107 100644 --- a/docs/guide/contributors/workflow.md +++ b/docs/guide/contributors/workflow.md @@ -56,8 +56,8 @@ Deprecated code should also be marked as legacy code. We use [Yore](https://pawa Examples: -```python title="Remove function when we bump to 2.0" -# YORE: Bump 2: Remove block. +```python title="Remove function when we bump to 5.0" +# YORE: Bump 5: Remove block. def deprecated_function(): ... ``` diff --git a/docs/reference/api/agents.md b/docs/reference/api/agents.md index 224426697..ca7f50c4d 100644 --- a/docs/reference/api/agents.md +++ b/docs/reference/api/agents.md @@ -70,8 +70,4 @@ Griffe is able to analyze code both statically and dynamically. ::: griffe.safe_get_value - -## **Deprecated API** - -::: griffe.ExportedName diff --git a/docs/reference/api/git.md b/docs/reference/api/git.md deleted file mode 100644 index 7abc81fcf..000000000 --- a/docs/reference/api/git.md +++ /dev/null @@ -1,13 +0,0 @@ -# Git utilities - - - -DANGER: **Deprecated utilities.** We have decided to stop exposing Git-related utilities as it's not a core part of the library's functionality. The functions documented on this page will become unavailable in the next major version. - -::: griffe.assert_git_repo - -::: griffe.get_latest_tag - -::: griffe.get_repo_root - -::: griffe.tmp_worktree From 7be978083507f330362a5a42c9e8390777cf82e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 2 Dec 2025 15:46:45 +0100 Subject: [PATCH 14/53] access members from griffe in tests --- tests/test_api.py | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index cc6c0ad34..0cd72b0a5 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -17,9 +17,9 @@ @pytest.fixture(name="loader", scope="module") -def _fixture_loader() -> griffelib.GriffeLoader: - loader = griffelib.GriffeLoader( - extensions=griffelib.load_extensions( +def _fixture_loader() -> griffe.GriffeLoader: + loader = griffe.GriffeLoader( + extensions=griffe.load_extensions( "griffe_inherited_docstrings", "unpack_typeddict", ), @@ -30,23 +30,23 @@ def _fixture_loader() -> griffelib.GriffeLoader: @pytest.fixture(name="internal_api", scope="module") -def _fixture_internal_api(loader: griffelib.GriffeLoader) -> griffelib.Module: - return loader.modules_collection["griffelib._internal"] +def _fixture_internal_api(loader: griffe.GriffeLoader) -> griffe.Module: + return loader.modules_collection["griffe._internal"] @pytest.fixture(name="public_api", scope="module") -def _fixture_public_api(loader: griffelib.GriffeLoader) -> griffelib.Module: +def _fixture_public_api(loader: griffe.GriffeLoader) -> griffe.Module: return loader.modules_collection["griffe"] def _yield_public_objects( - obj: griffelib.Module | griffelib.Class, + obj: griffe.Module | griffe.Class, *, modules: bool = False, modulelevel: bool = True, inherited: bool = False, special: bool = False, -) -> Iterator[griffelib.Object | griffelib.Alias]: +) -> Iterator[griffe.Object | griffe.Alias]: for member in obj.all_members.values() if inherited else obj.members.values(): try: if member.is_module: @@ -72,22 +72,22 @@ def _yield_public_objects( inherited=inherited, special=special, ) - except (griffelib.AliasResolutionError, griffelib.CyclicAliasError): + except (griffe.AliasResolutionError, griffe.CyclicAliasError): continue @pytest.fixture(name="modulelevel_internal_objects", scope="module") -def _fixture_modulelevel_internal_objects(internal_api: griffelib.Module) -> list[griffelib.Object | griffelib.Alias]: +def _fixture_modulelevel_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: return list(_yield_public_objects(internal_api, modulelevel=True)) @pytest.fixture(name="internal_objects", scope="module") -def _fixture_internal_objects(internal_api: griffelib.Module) -> list[griffelib.Object | griffelib.Alias]: +def _fixture_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: return list(_yield_public_objects(internal_api, modulelevel=False, special=True)) @pytest.fixture(name="public_objects", scope="module") -def _fixture_public_objects(public_api: griffelib.Module) -> list[griffelib.Object | griffelib.Alias]: +def _fixture_public_objects(public_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: return list(_yield_public_objects(public_api, modulelevel=False, inherited=True, special=True)) @@ -100,7 +100,7 @@ def _fixture_inventory() -> Inventory: return Inventory.parse_sphinx(file) -def test_alias_proxies(internal_api: griffelib.Module) -> None: +def test_alias_proxies(internal_api: griffe.Module) -> None: """The Alias class has all the necessary methods and properties.""" alias_members = set(internal_api["models.Alias"].all_members.keys()) for cls in ( @@ -114,17 +114,17 @@ def test_alias_proxies(internal_api: griffelib.Module) -> None: assert name in alias_members -def test_exposed_objects(modulelevel_internal_objects: list[griffelib.Object | griffelib.Alias]) -> None: +def test_exposed_objects(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None: """All public objects in the internal API are exposed under `griffe`.""" not_exposed = [ obj.path for obj in modulelevel_internal_objects - if obj.name not in griffelib.__all__ or not hasattr(griffe, obj.name) + if obj.name not in griffe.__all__ or not hasattr(griffe, obj.name) ] assert not not_exposed, "Objects not exposed:\n" + "\n".join(sorted(not_exposed)) -def test_unique_names(modulelevel_internal_objects: list[griffelib.Object | griffelib.Alias]) -> None: +def test_unique_names(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None: """All internal objects have unique names.""" names_to_paths = defaultdict(list) for obj in modulelevel_internal_objects: @@ -133,14 +133,14 @@ def test_unique_names(modulelevel_internal_objects: list[griffelib.Object | grif assert not non_unique, "Non-unique names:\n" + "\n".join(str(paths) for paths in non_unique) -def test_single_locations(public_api: griffelib.Module) -> None: +def test_single_locations(public_api: griffe.Module) -> None: """All objects have a single public location.""" - def _public_path(obj: griffelib.Object | griffelib.Alias) -> bool: + def _public_path(obj: griffe.Object | griffe.Alias) -> bool: return obj.is_public and (obj.parent is None or _public_path(obj.parent)) multiple_locations = {} - for obj_name in griffelib.__all__: + for obj_name in griffe.__all__: obj = public_api[obj_name] if obj.aliases and ( public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)] @@ -151,10 +151,10 @@ def _public_path(obj: griffelib.Object | griffelib.Alias) -> bool: ) -def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffelib.Object | griffelib.Alias]) -> None: +def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe.Object | griffe.Alias]) -> None: """All public objects are added to the inventory.""" ignore_names = {"__getattr__", "__init__", "__repr__", "__str__", "__post_init__"} - ignore_paths = {"griffelib.DataclassesExtension.*", "griffelib.UnpackTypedDictExtension.*"} + ignore_paths = {"griffe.DataclassesExtension.*", "griffe.UnpackTypedDictExtension.*"} not_in_inventory = [ f"{obj.relative_filepath}:{obj.lineno}: {obj.path}" for obj in public_objects @@ -170,8 +170,8 @@ def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe def test_inventory_matches_api( inventory: Inventory, - public_objects: list[griffelib.Object | griffelib.Alias], - loader: griffelib.GriffeLoader, + public_objects: list[griffe.Object | griffe.Alias], + loader: griffe.GriffeLoader, ) -> None: """The inventory doesn't contain any additional Python object.""" not_in_api = [] @@ -186,14 +186,14 @@ def test_inventory_matches_api( assert not not_in_api, msg.format(paths="\n".join(sorted(not_in_api))) -def test_no_module_docstrings_in_internal_api(internal_api: griffelib.Module) -> None: +def test_no_module_docstrings_in_internal_api(internal_api: griffe.Module) -> None: """No module docstrings should be written in our internal API. The reasoning is that docstrings are addressed to users of the public API, but internal modules are not exposed to users, so they should not have docstrings. """ - def _modules(obj: griffelib.Module) -> Iterator[griffelib.Module]: + def _modules(obj: griffe.Module) -> Iterator[griffe.Module]: for member in obj.modules.values(): yield member yield from _modules(member) From 697e2ea1142ee65b309ff8d1b2b8e22ae1ec5401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 2 Dec 2025 18:25:15 +0100 Subject: [PATCH 15/53] casing and order in pyproject.toml --- packages/griffecli/pyproject.toml | 12 ++++++------ packages/griffelib/pyproject.toml | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/griffecli/pyproject.toml b/packages/griffecli/pyproject.toml index 6a9af0fc8..b9a6525f8 100644 --- a/packages/griffecli/pyproject.toml +++ b/packages/griffecli/pyproject.toml @@ -4,14 +4,9 @@ requires = ["hatchling", "pdm-backend", "uv-dynamic-versioning>=0.7.0"] build-backend = "hatchling.build" -[tool.hatch.version] -source = "code" -path = "../../scripts/get_version.py" -expression = "get_version()" - [project] name = "griffecli" -description = "The griffe CLI" +description = "The Griffe CLI" authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}] license = "ISC" license-files = ["LICENSE"] @@ -44,6 +39,11 @@ classifiers = [ [project.scripts] griffecli = "griffecli:main" +[tool.hatch.version] +source = "code" +path = "../../scripts/get_version.py" +expression = "get_version()" + [tool.hatch.metadata.hooks.uv-dynamic-versioning] # Dependencies are dynamically versioned; {{version}} is substituted at build time. dependencies = ["griffelib=={{version}}", "colorama>=0.4"] diff --git a/packages/griffelib/pyproject.toml b/packages/griffelib/pyproject.toml index b01dfcde7..e445c11e2 100644 --- a/packages/griffelib/pyproject.toml +++ b/packages/griffelib/pyproject.toml @@ -4,14 +4,9 @@ requires = ["hatchling", "pdm-backend", "uv-dynamic-versioning>=0.7.0"] build-backend = "hatchling.build" -[tool.hatch.version] -source = "code" -path = "../../scripts/get_version.py" -expression = "get_version()" - [project] name = "griffelib" -description = "The griffe library" +description = "The Griffe library" authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}] license = "ISC" license-files = ["LICENSE"] @@ -41,6 +36,11 @@ classifiers = [ "Typing :: Typed", ] +[tool.hatch.version] +source = "code" +path = "../../scripts/get_version.py" +expression = "get_version()" + [tool.hatch.metadata.hooks.uv-dynamic-versioning] # No base dependencies needed for griffelib From e2bdab55d64b58c9e98bcd7845122933320c92e1 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Fri, 16 Jan 2026 15:20:08 +0100 Subject: [PATCH 16/53] Add info about griffelib to installation --- docs/installation.md | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index e0c69a8df..fd61e9b19 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -59,6 +59,65 @@ Griffe is a Python package, so you can install it with your favorite Python pack
+## Install as a library only + +If you only need the library for API introspection and analysis without the CLI tool, you can install just `griffelib`: + +=== ":simple-python: pip" + ```bash + pip install griffelib + ``` + +
+ + [pip](https://pip.pypa.io/en/stable/) is the main package installer for Python. + +
+ +=== ":simple-pdm: pdm" + ```bash + pdm add griffelib + ``` + +
+ + [PDM](https://pdm-project.org/en/latest/) is an all-in-one solution for Python project management. + +
+ +=== ":simple-poetry: poetry" + ```bash + poetry add griffelib + ``` + +
+ + [Poetry](https://python-poetry.org/) is an all-in-one solution for Python project management. + +
+ +=== ":simple-rye: rye" + ```bash + rye add griffelib + ``` + +
+ + [Rye](https://rye.astral.sh/) is an all-in-one solution for Python project management, written in Rust. + +
+ +=== ":simple-astral: uv" + ```bash + uv add griffelib + ``` + +
+ + [uv](https://docs.astral.sh/uv/) is an extremely fast Python package and project manager, written in Rust. + +
+ ## Install as a tool only === ":simple-python: pip" From bfdd1beb02f2e41d94acc3d864adf10d11f099e5 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Fri, 16 Jan 2026 15:26:27 +0100 Subject: [PATCH 17/53] Fix reference docs --- docs/reference/api/agents.md | 2 +- docs/reference/api/cli.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/api/agents.md b/docs/reference/api/agents.md index ca7f50c4d..c977ebe2b 100644 --- a/docs/reference/api/agents.md +++ b/docs/reference/api/agents.md @@ -4,7 +4,7 @@ Griffe is able to analyze code both statically and dynamically. ## **Main API** -::: griffe.visit +::: griffelib.visit ::: griffe.inspect diff --git a/docs/reference/api/cli.md b/docs/reference/api/cli.md index 08e83a31a..8d4d27143 100644 --- a/docs/reference/api/cli.md +++ b/docs/reference/api/cli.md @@ -2,7 +2,7 @@ ## **Main API** -::: griffe.main +::: griffecli.main ::: griffe.check From 2b39ee39aa12292475e8ee0301ef336a45ad4f79 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Fri, 16 Jan 2026 15:27:20 +0100 Subject: [PATCH 18/53] Add more info on griffelib --- docs/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/introduction.md b/docs/introduction.md index a7226fa6e..91d99cc8c 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -22,10 +22,10 @@ Both commands accept a `-h`, `--help` argument to show all the available options ## Python library -As a library, Griffe exposes all its public API directly in the top-level module. It means you can simply import `griffe` to access all its API. +As a library, Griffe exposes all its public API directly in the top-level module. It means you can simply import `griffe` or `griffelib` to access all its API. ```python -import griffe +import griffe # or griffelib griffe.load(...) griffe.find_breaking_changes(...) From 2814aa748ba615b3bf153a46875d658c76c414d8 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 12:55:37 +0100 Subject: [PATCH 19/53] Fix documention build warnings --- docs/guide/users/navigating.md | 16 +- docs/reference/api/loaders.md | 16 +- .../griffelib/_internal/agents/inspector.py | 16 +- .../src/griffelib/_internal/agents/visitor.py | 12 +- .../griffelib/src/griffelib/_internal/diff.py | 2 +- .../griffelib/_internal/docstrings/auto.py | 2 +- .../src/griffelib/_internal/encoders.py | 2 +- .../src/griffelib/_internal/expressions.py | 2 +- .../src/griffelib/_internal/finder.py | 4 +- .../griffelib/src/griffelib/_internal/git.py | 2 +- .../src/griffelib/_internal/importer.py | 2 +- .../src/griffelib/_internal/loader.py | 24 +- .../src/griffelib/_internal/models.py | 417 +++++++++--------- scripts/gen_griffe_json.py | 2 +- tests/test_docstrings/test_google.py | 2 +- tests/test_docstrings/test_numpy.py | 2 +- tests/test_docstrings/test_sphinx.py | 2 +- 17 files changed, 272 insertions(+), 253 deletions(-) diff --git a/docs/guide/users/navigating.md b/docs/guide/users/navigating.md index 1d1c169fe..d849cc4aa 100644 --- a/docs/guide/users/navigating.md +++ b/docs/guide/users/navigating.md @@ -41,7 +41,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffe.load("markdown") + >>> markdown = griffelib.load("markdown") >>> markdown.members["Markdown"] Alias('Markdown', 'markdown.core.Markdown') >>> markdown.members["core"].members["Markdown"] @@ -54,7 +54,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffe.load("markdown") + >>> markdown = griffelib.load("markdown") >>> markdown["core"]["Markdown"] # chained access Class('Markdown', 46, 451) >>> markdown["core.Markdown"] # merged access @@ -65,7 +65,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffe.load("markdown") + >>> markdown = griffelib.load("markdown") >>> markdown[("core", "Markdown")] # tuple access Class('Markdown', 46, 451) >>> # Due to the nature of the subscript syntax, @@ -78,7 +78,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffe.load("markdown") + >>> markdown = griffelib.load("markdown") >>> markdown.get_member("core.Markdown") Class('Markdown', 46, 451) ``` @@ -122,7 +122,7 @@ If a base class cannot be resolved during computation of inherited members, Grif If you want to access all members at once (both declared and inherited), use the [`all_members`][griffe.Object.all_members] attribute. If you want to access only declared members, use the [`members`][griffe.Object] attribute. -Accessing the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by Griffe. Don't try to access inherited members in extensions, while visiting or inspecting modules. +Accessing the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by griffelib. Don't try to access inherited members in extensions, while visiting or inspecting modules. #### Limitations @@ -254,7 +254,7 @@ from pkg2 import A as B ```pycon >>> import griffe ->>> B = griffe.load("pkg1.B") +>>> B = griffelib.load("pkg1.B") >>> B.path 'pkg1.B' >>> B.canonical_path @@ -339,13 +339,13 @@ Each object has an optional [`docstring`][griffe.Object.docstring] attached to i Docstrings can be parsed against several [docstring-styles](../../reference/docstrings.md), which are micro-formats that allow documenting things such as parameters, returned values, raised exceptions, etc.. -When loading a package, it is possible to specify the docstring style to attach to every docstring (see the `docstring_parser` parameter of [`griffe.load`][griffe.load]). Accessing the [`parsed`][griffe.Docstring.parsed] field of a docstring will use this style to parse the docstring and return a list of [docstring sections][advanced-api-sections]. Each section has a `value` whose shape depends on the section kind. For example, parameter sections have a list of parameter representations as value, while a text section only has a string as value. +When loading a package, it is possible to specify the docstring style to attach to every docstring (see the `docstring_parser` parameter of [`griffelib.load`][griffe.load]). Accessing the [`parsed`][griffe.Docstring.parsed] field of a docstring will use this style to parse the docstring and return a list of [docstring sections][advanced-api-sections]. Each section has a `value` whose shape depends on the section kind. For example, parameter sections have a list of parameter representations as value, while a text section only has a string as value. After a package is loaded, it is still possible to change the style used for specific docstrings by either overriding their [`parser`][griffe.Docstring.parser] and [`parser_options`][griffe.Docstring.parser_options] attributes, or by calling their [`parse()`][griffe.Docstring.parse] method with a different style: ```pycon >>> import griffe ->>> markdown = griffe.load("markdown", docstring_parser="google") +>>> markdown = griffelib.load("markdown", docstring_parser="google") >>> markdown["Markdown"].docstring.parse("numpy") [...] ``` diff --git a/docs/reference/api/loaders.md b/docs/reference/api/loaders.md index b3eb060c9..10dccf38c 100644 --- a/docs/reference/api/loaders.md +++ b/docs/reference/api/loaders.md @@ -2,22 +2,22 @@ ## **Main API** -::: griffe.load +::: griffelib.load -::: griffe.load_git +::: griffelib.load_git -::: griffe.load_pypi +::: griffelib.load_pypi ## **Advanced API** -::: griffe.GriffeLoader +::: griffelib.GriffeLoader -::: griffe.ModulesCollection +::: griffelib.ModulesCollection -::: griffe.LinesCollection +::: griffelib.LinesCollection ## **Additional API** -::: griffe.Stats +::: griffelib.Stats -::: griffe.merge_stubs +::: griffelib.merge_stubs diff --git a/packages/griffelib/src/griffelib/_internal/agents/inspector.py b/packages/griffelib/src/griffelib/_internal/agents/inspector.py index 7eb5df5c2..4b4601495 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/inspector.py +++ b/packages/griffelib/src/griffelib/_internal/agents/inspector.py @@ -15,7 +15,13 @@ from griffelib._internal.agents.nodes.runtime import ObjectNode from griffelib._internal.collections import LinesCollection, ModulesCollection from griffelib._internal.enumerations import Kind, ParameterKind, TypeParameterKind -from griffelib._internal.expressions import Expr, ExprBinOp, ExprSubscript, ExprTuple, safe_get_annotation +from griffelib._internal.expressions import ( + Expr, + ExprBinOp, + ExprSubscript, + ExprTuple, + safe_get_annotation, +) from griffelib._internal.extensions.base import Extensions, load_extensions from griffelib._internal.importer import dynamic_import from griffelib._internal.logger import logger @@ -75,16 +81,16 @@ def inspect( In this case, we load the module using introspection. Griffe therefore provides this function for dynamic analysis. - It uses a [`NodeVisitor`][ast.NodeVisitor]-like class, the [`Inspector`][griffelib.Inspector], + It uses a [`NodeVisitor`][ast.NodeVisitor]-like class, the [`Inspector`][griffe.Inspector], to inspect the module with [`inspect.getmembers()`][inspect.getmembers]. - The inspection agent works similarly to the regular [`Visitor`][griffelib.Visitor] agent, + The inspection agent works similarly to the regular [`Visitor`][griffe.Visitor] agent, in that it maintains a state with the current object being handled, and recursively handle its members. Important: This function is generally not used directly. - In most cases, users can rely on the [`GriffeLoader`][griffelib.GriffeLoader] - and its accompanying [`load`][griffelib.load] shortcut and their respective options + In most cases, users can rely on the [`GriffeLoader`][griffe.GriffeLoader] + and its accompanying [`load`][griffe.load] shortcut and their respective options to load modules using dynamic analysis. Parameters: diff --git a/packages/griffelib/src/griffelib/_internal/agents/visitor.py b/packages/griffelib/src/griffelib/_internal/agents/visitor.py index f1a9e18ff..2771f1483 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/visitor.py +++ b/packages/griffelib/src/griffelib/_internal/agents/visitor.py @@ -20,7 +20,11 @@ from griffelib._internal.agents.nodes.parameters import get_parameters from griffelib._internal.collections import LinesCollection, ModulesCollection from griffelib._internal.enumerations import Kind, TypeParameterKind -from griffelib._internal.exceptions import AliasResolutionError, CyclicAliasError, LastNodeError +from griffelib._internal.exceptions import ( + AliasResolutionError, + CyclicAliasError, + LastNodeError, +) from griffelib._internal.expressions import ( Expr, ExprName, @@ -92,13 +96,13 @@ def visit( """Parse and visit a module file. We provide this function for static analysis. It uses a [`NodeVisitor`][ast.NodeVisitor]-like class, - the [`Visitor`][griffelib.Visitor], to compile and parse code (using [`compile`][]) + the [`Visitor`][griffe.Visitor], to compile and parse code (using [`compile`][]) then visit the resulting AST (Abstract Syntax Tree). Important: This function is generally not used directly. - In most cases, users can rely on the [`GriffeLoader`][griffelib.GriffeLoader] - and its accompanying [`load`][griffelib.load] shortcut and their respective options + In most cases, users can rely on the [`GriffeLoader`][griffe.GriffeLoader] + and its accompanying [`load`][griffe.load] shortcut and their respective options to load modules using static analysis. Parameters: diff --git a/packages/griffelib/src/griffelib/_internal/diff.py b/packages/griffelib/src/griffelib/_internal/diff.py index 46f4645d1..2c6589515 100644 --- a/packages/griffelib/src/griffelib/_internal/diff.py +++ b/packages/griffelib/src/griffelib/_internal/diff.py @@ -150,7 +150,7 @@ def _relative_package_filepath(self) -> Path: def _location(self) -> Path: # Absolute file path probably means temporary worktree. # We use our worktree prefix to remove some components - # of the path on the left (`/tmp/griffelib-worktree-*/griffe_*/repo`). + # of the path on the left (`/tmp/griffe-worktree-*/griffe_*/repo`). if self._relative_filepath.is_absolute(): parts = self._relative_filepath.parts for index, part in enumerate(parts): diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/auto.py b/packages/griffelib/src/griffelib/_internal/docstrings/auto.py index e7643f29c..2de048df2 100644 --- a/packages/griffelib/src/griffelib/_internal/docstrings/auto.py +++ b/packages/griffelib/src/griffelib/_internal/docstrings/auto.py @@ -195,7 +195,7 @@ def parse_auto( ) -> list[DocstringSection]: """Parse a docstring by automatically detecting the style it uses. - See [`infer_docstring_style`][griffelib.infer_docstring_style] for more information + See [`infer_docstring_style`][griffe.infer_docstring_style] for more information on the available parameters. Parameters: diff --git a/packages/griffelib/src/griffelib/_internal/encoders.py b/packages/griffelib/src/griffelib/_internal/encoders.py index fca73bd8e..84f48fc93 100644 --- a/packages/griffelib/src/griffelib/_internal/encoders.py +++ b/packages/griffelib/src/griffelib/_internal/encoders.py @@ -61,7 +61,7 @@ def __init__( *args: See [`json.JSONEncoder`][]. full: Whether to dump full data or base data. If you plan to reload the data in Python memory - using the [`json_decoder`][griffelib.json_decoder], + using the [`json_decoder`][griffe.json_decoder], you don't need the full data as it can be inferred again using the base data. If you want to feed a non-Python tool instead, dump the full data. diff --git a/packages/griffelib/src/griffelib/_internal/expressions.py b/packages/griffelib/src/griffelib/_internal/expressions.py index 512f2f830..c9df6bfe7 100644 --- a/packages/griffelib/src/griffelib/_internal/expressions.py +++ b/packages/griffelib/src/griffelib/_internal/expressions.py @@ -180,7 +180,7 @@ def iterate(self, *, flat: bool = True) -> Iterator[str | Expr]: # noqa: ARG002 without them getting rendered as strings. On the contrary, when flat is true, the whole tree is flattened as a sequence - of strings and instances of [Names][griffelib.ExprName]. + of strings and instances of [Names][griffe.ExprName]. Yields: Strings and names when flat, strings and expressions otherwise. diff --git a/packages/griffelib/src/griffelib/_internal/finder.py b/packages/griffelib/src/griffelib/_internal/finder.py index b2e38ef66..9177a91b3 100644 --- a/packages/griffelib/src/griffelib/_internal/finder.py +++ b/packages/griffelib/src/griffelib/_internal/finder.py @@ -89,9 +89,9 @@ class ModuleFinder: """The Griffe finder, allowing to find modules on the file system. The module finder is generally not used directly. - Each [`GriffeLoader`][griffelib.GriffeLoader] instance creates its own module finder instance. + Each [`GriffeLoader`][griffe.GriffeLoader] instance creates its own module finder instance. The finder can be configured when instantiating the loader - thanks to the [loader][griffelib.GriffeLoader]'s `search_paths` parameter. + thanks to the [loader][griffe.GriffeLoader]'s `search_paths` parameter. """ accepted_py_module_extensions: ClassVar[list[str]] = [".py", ".pyc", ".pyo", ".pyd", ".pyi", ".so"] diff --git a/packages/griffelib/src/griffelib/_internal/git.py b/packages/griffelib/src/griffelib/_internal/git.py index 2ee41d424..e8cca7ac3 100644 --- a/packages/griffelib/src/griffelib/_internal/git.py +++ b/packages/griffelib/src/griffelib/_internal/git.py @@ -1,4 +1,4 @@ -# This module contains Git utilities, used by our [`load_git`][griffelib.load_git] function, +# This module contains Git utilities, used by our [`load_git`][griffe.load_git] function, # which in turn is used to load the API for different snapshots of a Git repository # and find breaking changes between them. diff --git a/packages/griffelib/src/griffelib/_internal/importer.py b/packages/griffelib/src/griffelib/_internal/importer.py index 4144357c3..b75b44ee2 100644 --- a/packages/griffelib/src/griffelib/_internal/importer.py +++ b/packages/griffelib/src/griffelib/_internal/importer.py @@ -1,5 +1,5 @@ # This module contains utilities to dynamically import objects. -# These utilities are used by our [`Inspector`][griffelib.Inspector] to dynamically import objects +# These utilities are used by our [`Inspector`][griffe.Inspector] to dynamically import objects # specified as Python paths, like `package.module.Class.method`. from __future__ import annotations diff --git a/packages/griffelib/src/griffelib/_internal/loader.py b/packages/griffelib/src/griffelib/_internal/loader.py index ba9c6eddb..db723032d 100644 --- a/packages/griffelib/src/griffelib/_internal/loader.py +++ b/packages/griffelib/src/griffelib/_internal/loader.py @@ -293,7 +293,7 @@ def resolve_aliases( def expand_exports(self, module: Module, seen: set | None = None) -> None: """Expand exports: try to recursively expand all module exports (`__all__` values). - See also: [`Module.exports`][griffelib.Module.exports]. + See also: [`Module.exports`][griffe.Module.exports]. Parameters: module: The module to recurse on. @@ -340,7 +340,7 @@ def expand_wildcards( ) -> None: """Expand wildcards: try to recursively expand all found wildcards. - See also: [`Alias.wildcard`][griffelib.Alias.wildcard]. + See also: [`Alias.wildcard`][griffe.Alias.wildcard]. Parameters: obj: The object and its members to recurse on. @@ -769,19 +769,19 @@ def load( In Griffe's context, loading means: - searching for a package, and finding it on the file system or as a builtin module - (see the [`ModuleFinder`][griffelib.ModuleFinder] class for more information) + (see the [`ModuleFinder`][griffe.ModuleFinder] class for more information) - extracting information from each of its (sub)modules, by either parsing - the source code (see the [`visit`][griffelib.visit] function) - or inspecting the module at runtime (see the [`inspect`][griffelib.inspect] function) + the source code (see the [`visit`][griffe.visit] function) + or inspecting the module at runtime (see the [`inspect`][griffe.inspect] function) The extracted information is stored in a collection of modules, which can be queried later. Each collected module is a tree of objects, representing the structure of the module. - See the [`Module`][griffelib.Module], [`Class`][griffelib.Class], - [`Function`][griffelib.Function], [`Attribute`][griffelib.Attribute], and - [`TypeAlias`][griffelib.TypeAlias] classes for more information. + See the [`Module`][griffe.Module], [`Class`][griffe.Class], + [`Function`][griffe.Function], [`Attribute`][griffe.Attribute], and + [`TypeAlias`][griffe.TypeAlias] classes for more information. - The main class used to load modules is [`GriffeLoader`][griffelib.GriffeLoader]. - Convenience functions like this one and [`load_git`][griffelib.load_git] are also available. + The main class used to load modules is [`GriffeLoader`][griffe.GriffeLoader]. + Convenience functions like this one and [`load_git`][griffe.load_git] are also available. Example: ```python @@ -799,7 +799,7 @@ def load( module = loader.load(...) ``` - See the documentation for the loader: [`GriffeLoader`][griffelib.GriffeLoader]. + See the documentation for the loader: [`GriffeLoader`][griffe.GriffeLoader]. Parameters: objspec: The Python path of an object, or file path to a module. @@ -873,7 +873,7 @@ def load_git( This function will create a temporary [git worktree](https://git-scm.com/docs/git-worktree) at the requested reference - before loading `module` with [`griffelib.load`][griffelib.load]. + before loading `module` with [`griffelib.load`][griffe.load]. This function requires that the `git` executable is installed. diff --git a/packages/griffelib/src/griffelib/_internal/models.py b/packages/griffelib/src/griffelib/_internal/models.py index 50a38814f..cc1ac0e51 100644 --- a/packages/griffelib/src/griffelib/_internal/models.py +++ b/packages/griffelib/src/griffelib/_internal/models.py @@ -12,8 +12,17 @@ from typing import TYPE_CHECKING, Any, Callable, Literal, Union, cast from griffelib._internal.c3linear import c3linear_merge -from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle, parse -from griffelib._internal.enumerations import Kind, ParameterKind, Parser, TypeParameterKind +from griffelib._internal.docstrings.parsers import ( + DocstringOptions, + DocstringStyle, + parse, +) +from griffelib._internal.enumerations import ( + Kind, + ParameterKind, + Parser, + TypeParameterKind, +) from griffelib._internal.exceptions import ( AliasResolutionError, BuiltinModuleError, @@ -102,18 +111,18 @@ def __init__( self.value: str = inspect.cleandoc(value.rstrip()) """The original value of the docstring, cleaned by `inspect.cleandoc`. - See also: [`source`][griffelib.Docstring.source]. + See also: [`source`][griffe.Docstring.source]. """ self.lineno: int | None = lineno """The starting line number of the docstring. - See also: [`endlineno`][griffelib.Docstring.endlineno].""" + See also: [`endlineno`][griffe.Docstring.endlineno].""" self.endlineno: int | None = endlineno """The ending line number of the docstring. - See also: [`lineno`][griffelib.Docstring.lineno].""" + See also: [`lineno`][griffe.Docstring.lineno].""" self.parent: Object | None = parent """The object this docstring is attached to.""" @@ -121,22 +130,22 @@ def __init__( self.parser: DocstringStyle | Parser | None = parser """The selected docstring parser. - See also: [`parser_options`][griffelib.Docstring.parser_options], - [`parse`][griffelib.Docstring.parse]. + See also: [`parser_options`][griffe.Docstring.parser_options], + [`parse`][griffe.Docstring.parse]. """ self.parser_options: DocstringOptions = parser_options or {} """The configured parsing options. - See also: [`parser`][griffelib.Docstring.parser], - [`parse`][griffelib.Docstring.parse]. + See also: [`parser`][griffe.Docstring.parser], + [`parse`][griffe.Docstring.parse]. """ @property def lines(self) -> list[str]: """The lines of the docstring. - See also: [`source`][griffelib.Docstring.source]. + See also: [`source`][griffe.Docstring.source]. """ return self.value.split("\n") @@ -152,7 +161,7 @@ def source(self) -> str: ValueError: If the original docstring cannot be retrieved (no parent, no line numbers, or attached to namespace package). - See also: [`value`][griffelib.Docstring.value]. + See also: [`value`][griffe.Docstring.value]. """ if self.parent is None: raise ValueError("Cannot get original docstring without parent object") @@ -174,8 +183,8 @@ def parse( ) -> list[DocstringSection]: """Parse the docstring into structured data. - See also: [`parser`][griffelib.Docstring.parser], - [`parser_options`][griffelib.Docstring.parser_options]. + See also: [`parser`][griffe.Docstring.parser], + [`parser_options`][griffe.Docstring.parser_options]. Parameters: parser: The docstring parser to use. @@ -215,7 +224,7 @@ def as_dict( class Parameter: # noqa: PLW1641 """This class represent a function parameter. - See also: [`Parameters`][griffelib.Parameters]. + See also: [`Parameters`][griffe.Parameters]. """ def __init__( @@ -307,7 +316,7 @@ class Parameters: True ``` - See also: [`Parameter`][griffelib.Parameter]. + See also: [`Parameter`][griffe.Parameter]. """ def __init__(self, *parameters: Parameter) -> None: @@ -618,20 +627,20 @@ def __init__( self.lineno: int | None = lineno """The starting line number of the object. - See also: [`endlineno`][griffelib.Object.endlineno]. + See also: [`endlineno`][griffe.Object.endlineno]. """ self.endlineno: int | None = endlineno """The ending line number of the object. - See also: [`lineno`][griffelib.Object.lineno]. + See also: [`lineno`][griffe.Object.lineno]. """ self.docstring: Docstring | None = docstring """The object docstring. - See also: [`has_docstring`][griffelib.Object.has_docstring], - [`has_docstrings`][griffelib.Object.has_docstrings]. + See also: [`has_docstring`][griffe.Object.has_docstring], + [`has_docstrings`][griffe.Object.has_docstrings]. """ # TODO: Maybe move these into `Class` and `Function`. @@ -646,16 +655,16 @@ def __init__( self.members: dict[str, Object | Alias] = {} """The object members (modules, classes, functions, attributes, type aliases). - See also: [`inherited_members`][griffelib.Object.inherited_members], - [`get_member`][griffelib.Object.get_member], - [`set_member`][griffelib.Object.set_member], - [`filter_members`][griffelib.Object.filter_members]. + See also: [`inherited_members`][griffe.Object.inherited_members], + [`get_member`][griffe.Object.get_member], + [`set_member`][griffe.Object.set_member], + [`filter_members`][griffe.Object.filter_members]. """ self.labels: set[str] = set() """The object labels (`property`, `dataclass`, etc.). - See also: [`has_labels`][griffelib.Object.has_labels].""" + See also: [`has_labels`][griffe.Object.has_labels].""" self.imports: dict[str, str] = {} """The other objects imported by this object. @@ -678,7 +687,7 @@ def __init__( Exports get expanded by the loader before it expands wildcards and resolves aliases. - See also: [`GriffeLoader.expand_exports`][griffelib.GriffeLoader.expand_exports]. + See also: [`GriffeLoader.expand_exports`][griffe.GriffeLoader.expand_exports]. """ self.aliases: dict[str, Alias] = {} @@ -762,8 +771,8 @@ def source_link(self, value: str | None) -> None: def has_docstring(self) -> bool: """Whether this object has a docstring (empty or not). - See also: [`docstring`][griffelib.Object.docstring], - [`has_docstrings`][griffelib.Object.has_docstrings]. + See also: [`docstring`][griffe.Object.docstring], + [`has_docstrings`][griffe.Object.has_docstrings]. """ return bool(self.docstring) @@ -782,8 +791,8 @@ def has_docstrings(self) -> bool: Inherited members are not considered. Imported members are not considered, unless they are also public. - See also: [`docstring`][griffelib.Object.docstring], - [`has_docstring`][griffelib.Object.has_docstring]. + See also: [`docstring`][griffe.Object.docstring], + [`has_docstring`][griffe.Object.has_docstring]. """ if self.has_docstring: return True @@ -798,12 +807,12 @@ def has_docstrings(self) -> bool: def is_kind(self, kind: str | Kind | set[str | Kind]) -> bool: """Tell if this object is of the given kind. - See also: [`is_module`][griffelib.Object.is_module], - [`is_class`][griffelib.Object.is_class], - [`is_function`][griffelib.Object.is_function], - [`is_attribute`][griffelib.Object.is_attribute], - [`is_type_alias`][griffelib.Object.is_type_alias], - [`is_alias`][griffelib.Object.is_alias]. + See also: [`is_module`][griffe.Object.is_module], + [`is_class`][griffe.Object.is_class], + [`is_function`][griffe.Object.is_function], + [`is_attribute`][griffe.Object.is_attribute], + [`is_type_alias`][griffe.Object.is_type_alias], + [`is_alias`][griffe.Object.is_alias]. Parameters: kind: An instance or set of kinds (strings or enumerations). @@ -829,7 +838,7 @@ def inherited_members(self) -> dict[str, Alias]: This method is part of the consumer API: do not use when producing Griffe trees! - See also: [`members`][griffelib.Object.members]. + See also: [`members`][griffe.Object.members]. """ if not isinstance(self, Class): return {} @@ -849,13 +858,13 @@ def inherited_members(self) -> dict[str, Alias]: def is_module(self) -> bool: """Whether this object is a module. - See also: [`is_init_module`][griffelib.Object.is_init_module]. - [`is_class`][griffelib.Object.is_class], - [`is_function`][griffelib.Object.is_function], - [`is_attribute`][griffelib.Object.is_attribute], - [`is_type_alias`][griffelib.Object.is_type_alias], - [`is_alias`][griffelib.Object.is_alias], - [`is_kind`][griffelib.Object.is_kind]. + See also: [`is_init_module`][griffe.Object.is_init_module]. + [`is_class`][griffe.Object.is_class], + [`is_function`][griffe.Object.is_function], + [`is_attribute`][griffe.Object.is_attribute], + [`is_type_alias`][griffe.Object.is_type_alias], + [`is_alias`][griffe.Object.is_alias], + [`is_kind`][griffe.Object.is_kind]. """ return self.kind is Kind.MODULE @@ -863,12 +872,12 @@ def is_module(self) -> bool: def is_class(self) -> bool: """Whether this object is a class. - See also: [`is_module`][griffelib.Object.is_module]. - [`is_function`][griffelib.Object.is_function], - [`is_attribute`][griffelib.Object.is_attribute], - [`is_type_alias`][griffelib.Object.is_type_alias], - [`is_alias`][griffelib.Object.is_alias], - [`is_kind`][griffelib.Object.is_kind]. + See also: [`is_module`][griffe.Object.is_module]. + [`is_function`][griffe.Object.is_function], + [`is_attribute`][griffe.Object.is_attribute], + [`is_type_alias`][griffe.Object.is_type_alias], + [`is_alias`][griffe.Object.is_alias], + [`is_kind`][griffe.Object.is_kind]. """ return self.kind is Kind.CLASS @@ -876,12 +885,12 @@ def is_class(self) -> bool: def is_function(self) -> bool: """Whether this object is a function. - See also: [`is_module`][griffelib.Object.is_module]. - [`is_class`][griffelib.Object.is_class], - [`is_attribute`][griffelib.Object.is_attribute], - [`is_type_alias`][griffelib.Object.is_type_alias], - [`is_alias`][griffelib.Object.is_alias], - [`is_kind`][griffelib.Object.is_kind]. + See also: [`is_module`][griffe.Object.is_module]. + [`is_class`][griffe.Object.is_class], + [`is_attribute`][griffe.Object.is_attribute], + [`is_type_alias`][griffe.Object.is_type_alias], + [`is_alias`][griffe.Object.is_alias], + [`is_kind`][griffe.Object.is_kind]. """ return self.kind is Kind.FUNCTION @@ -889,12 +898,12 @@ def is_function(self) -> bool: def is_attribute(self) -> bool: """Whether this object is an attribute. - See also: [`is_module`][griffelib.Object.is_module]. - [`is_class`][griffelib.Object.is_class], - [`is_function`][griffelib.Object.is_function], - [`is_type_alias`][griffelib.Object.is_type_alias], - [`is_alias`][griffelib.Object.is_alias], - [`is_kind`][griffelib.Object.is_kind]. + See also: [`is_module`][griffe.Object.is_module]. + [`is_class`][griffe.Object.is_class], + [`is_function`][griffe.Object.is_function], + [`is_type_alias`][griffe.Object.is_type_alias], + [`is_alias`][griffe.Object.is_alias], + [`is_kind`][griffe.Object.is_kind]. """ return self.kind is Kind.ATTRIBUTE @@ -902,12 +911,12 @@ def is_attribute(self) -> bool: def is_type_alias(self) -> bool: """Whether this object is a type alias. - See also: [`is_module`][griffelib.Object.is_module]. - [`is_class`][griffelib.Object.is_class], - [`is_function`][griffelib.Object.is_function], - [`is_attribute`][griffelib.Object.is_attribute], - [`is_alias`][griffelib.Object.is_alias], - [`is_kind`][griffelib.Object.is_kind]. + See also: [`is_module`][griffe.Object.is_module]. + [`is_class`][griffe.Object.is_class], + [`is_function`][griffe.Object.is_function], + [`is_attribute`][griffe.Object.is_attribute], + [`is_alias`][griffe.Object.is_alias], + [`is_kind`][griffe.Object.is_kind]. """ return self.kind is Kind.TYPE_ALIAS @@ -920,7 +929,7 @@ def is_init_method(self) -> bool: def is_init_module(self) -> bool: """Whether this object is an `__init__.py` module. - See also: [`is_module`][griffelib.Object.is_module]. + See also: [`is_module`][griffe.Object.is_module]. """ return False @@ -928,7 +937,7 @@ def is_init_module(self) -> bool: def is_package(self) -> bool: """Whether this object is a package (top module). - See also: [`is_subpackage`][griffelib.Object.is_subpackage]. + See also: [`is_subpackage`][griffe.Object.is_subpackage]. """ return False @@ -936,7 +945,7 @@ def is_package(self) -> bool: def is_subpackage(self) -> bool: """Whether this object is a subpackage. - See also: [`is_package`][griffelib.Object.is_package]. + See also: [`is_package`][griffe.Object.is_package]. """ return False @@ -944,7 +953,7 @@ def is_subpackage(self) -> bool: def is_namespace_package(self) -> bool: """Whether this object is a namespace package (top folder, no `__init__.py`). - See also: [`is_namespace_subpackage`][griffelib.Object.is_namespace_subpackage]. + See also: [`is_namespace_subpackage`][griffe.Object.is_namespace_subpackage]. """ return False @@ -952,14 +961,14 @@ def is_namespace_package(self) -> bool: def is_namespace_subpackage(self) -> bool: """Whether this object is a namespace subpackage. - See also: [`is_namespace_package`][griffelib.Object.is_namespace_package]. + See also: [`is_namespace_package`][griffe.Object.is_namespace_package]. """ return False def has_labels(self, *labels: str) -> bool: """Tell if this object has all the given labels. - See also: [`labels`][griffelib.Object.labels]. + See also: [`labels`][griffe.Object.labels]. Parameters: *labels: Labels that must be present. @@ -972,7 +981,7 @@ def has_labels(self, *labels: str) -> bool: def filter_members(self, *predicates: Callable[[Object | Alias], bool]) -> dict[str, Object | Alias]: """Filter and return members based on predicates. - See also: [`members`][griffelib.Object.members]. + See also: [`members`][griffe.Object.members]. Parameters: *predicates: A list of predicates, i.e. callables accepting a member as argument and returning a boolean. @@ -991,7 +1000,7 @@ def filter_members(self, *predicates: Callable[[Object | Alias], bool]) -> dict[ def module(self) -> Module: """The parent module of this object. - See also: [`package`][griffelib.Object.package]. + See also: [`package`][griffe.Object.package]. Examples: >>> import griffelib @@ -1015,7 +1024,7 @@ def module(self) -> Module: def package(self) -> Module: """The absolute top module (the package) of this object. - See also: [`module`][griffelib.Object.module]. + See also: [`module`][griffe.Object.module]. Examples: >>> import griffelib @@ -1032,8 +1041,8 @@ def package(self) -> Module: def filepath(self) -> Path | list[Path]: """The file path (or directory list for namespace packages) where this object was defined. - See also: [`relative_filepath`][griffelib.Object.relative_filepath], - [`relative_package_filepath`][griffelib.Object.relative_package_filepath]. + See also: [`relative_filepath`][griffe.Object.relative_filepath], + [`relative_package_filepath`][griffe.Object.relative_package_filepath]. Examples: >>> import griffelib @@ -1047,8 +1056,8 @@ def filepath(self) -> Path | list[Path]: def relative_package_filepath(self) -> Path: """The file path where this object was defined, relative to the top module path. - See also: [`filepath`][griffelib.Object.filepath], - [`relative_filepath`][griffelib.Object.relative_filepath]. + See also: [`filepath`][griffe.Object.filepath], + [`relative_filepath`][griffe.Object.relative_filepath]. Raises: ValueError: When the relative path could not be computed. @@ -1093,8 +1102,8 @@ def relative_filepath(self) -> Path: If this object's file path is not relative to the current working directory, return its absolute path. - See also: [`filepath`][griffelib.Object.filepath], - [`relative_package_filepath`][griffelib.Object.relative_package_filepath]. + See also: [`filepath`][griffe.Object.filepath], + [`relative_package_filepath`][griffe.Object.relative_package_filepath]. Raises: ValueError: When the relative path could not be computed. @@ -1116,7 +1125,7 @@ def path(self) -> str: On regular objects (not aliases), the path is the canonical path. - See also: [`canonical_path`][griffelib.Object.canonical_path]. + See also: [`canonical_path`][griffe.Object.canonical_path]. Examples: >>> import griffelib @@ -1132,7 +1141,7 @@ def canonical_path(self) -> str: The canonical path is the path where the object was defined (not imported). - See also: [`path`][griffelib.Object.path]. + See also: [`path`][griffe.Object.path]. """ if self.parent is None: return self.name @@ -1155,8 +1164,8 @@ def modules_collection(self) -> ModulesCollection: def lines_collection(self) -> LinesCollection: """The lines collection attached to this object or its parents. - See also: [`lines`][griffelib.Object.lines], - [`source`][griffelib.Object.source]. + See also: [`lines`][griffe.Object.lines], + [`source`][griffe.Object.source]. Raises: ValueError: When no modules collection can be found in the object or its parents. @@ -1171,8 +1180,8 @@ def lines_collection(self) -> LinesCollection: def lines(self) -> list[str]: """The lines containing the source of this object. - See also: [`lines_collection`][griffelib.Object.lines_collection], - [`source`][griffelib.Object.source]. + See also: [`lines_collection`][griffe.Object.lines_collection], + [`source`][griffe.Object.source]. """ try: filepath = self.filepath @@ -1194,8 +1203,8 @@ def lines(self) -> list[str]: def source(self) -> str: """The source code of this object. - See also: [`lines`][griffelib.Object.lines], - [`lines_collection`][griffelib.Object.lines_collection]. + See also: [`lines`][griffe.Object.lines], + [`lines_collection`][griffe.Object.lines_collection]. """ return dedent("\n".join(self.lines)) @@ -1245,7 +1254,7 @@ def resolve(self, name: str) -> str: def as_dict(self, *, full: bool = False, **kwargs: Any) -> dict[str, Any]: """Return this object's data as a dictionary. - See also: [`as_json`][griffelib.Object.as_json]. + See also: [`as_json`][griffe.Object.as_json]. Parameters: full: Whether to return full info, or just base info. @@ -1341,7 +1350,7 @@ class Alias(ObjectAliasMixin): - the path is the alias path, not the canonical one - the name can be different from the target's - if the target can be resolved, the kind is the target's kind - - if the target cannot be resolved, the kind becomes [Kind.ALIAS][griffelib.Kind] + - if the target cannot be resolved, the kind becomes [Kind.ALIAS][griffe.Kind] """ is_alias: bool = True @@ -1349,7 +1358,7 @@ class Alias(ObjectAliasMixin): is_collection: bool = False """Always false for aliases. - See also: [`ModulesCollection`][griffelib.ModulesCollection]. + See also: [`ModulesCollection`][griffe.ModulesCollection]. """ def __init__( @@ -1444,7 +1453,7 @@ def __len__(self) -> int: def kind(self) -> Kind: """The target's kind, or `Kind.ALIAS` if the target cannot be resolved. - See also: [`is_kind`][griffelib.Alias.is_kind]. + See also: [`is_kind`][griffe.Alias.is_kind]. """ # custom behavior to avoid raising exceptions try: @@ -1456,8 +1465,8 @@ def kind(self) -> Kind: def has_docstring(self) -> bool: """Whether this alias' target has a non-empty docstring. - See also: [`has_docstrings`][griffelib.Alias.has_docstrings], - [`docstring`][griffelib.Alias.docstring]. + See also: [`has_docstrings`][griffe.Alias.has_docstrings], + [`docstring`][griffe.Alias.docstring]. """ try: return self.final_target.has_docstring @@ -1468,8 +1477,8 @@ def has_docstring(self) -> bool: def has_docstrings(self) -> bool: """Whether this alias' target or any of its members has a non-empty docstring. - See also: [`has_docstring`][griffelib.Alias.has_docstring], - [`docstring`][griffelib.Alias.docstring]. + See also: [`has_docstring`][griffe.Alias.has_docstring], + [`docstring`][griffe.Alias.docstring]. """ try: return self.final_target.has_docstrings @@ -1490,7 +1499,7 @@ def parent(self, value: Module | Class | Alias) -> None: def path(self) -> str: """The dotted path / import path of this object. - See also: [`canonical_path`][griffelib.Alias.canonical_path]. + See also: [`canonical_path`][griffe.Alias.canonical_path]. """ return f"{self.parent.path}.{self.name}" # type: ignore[union-attr] @@ -1504,10 +1513,10 @@ def modules_collection(self) -> ModulesCollection: def members(self) -> dict[str, Object | Alias]: """The target's members (modules, classes, functions, attributes, type aliases). - See also: [`inherited_members`][griffelib.Alias.inherited_members], - [`get_member`][griffelib.Alias.get_member], - [`set_member`][griffelib.Alias.set_member], - [`filter_members`][griffelib.Alias.filter_members]. + See also: [`inherited_members`][griffe.Alias.inherited_members], + [`get_member`][griffe.Alias.get_member], + [`set_member`][griffe.Alias.set_member], + [`filter_members`][griffe.Alias.filter_members]. """ final_target = self.final_target @@ -1530,7 +1539,7 @@ def inherited_members(self) -> dict[str, Alias]: This method is part of the consumer API: do not use when producing Griffe trees! - See also: [`members`][griffelib.Alias.members]. + See also: [`members`][griffe.Alias.members]. """ final_target = self.final_target @@ -1546,7 +1555,7 @@ def inherited_members(self) -> dict[str, Alias]: def as_json(self, *, full: bool = False, **kwargs: Any) -> str: """Return this target's data as a JSON string. - See also: [`as_dict`][griffelib.Alias.as_dict]. + See also: [`as_dict`][griffe.Alias.as_dict]. Parameters: full: Whether to return full info, or just base info. @@ -1594,7 +1603,7 @@ def extra(self) -> dict: def lineno(self) -> int | None: """The starting line number of the target object. - See also: [`endlineno`][griffelib.Alias.endlineno]. + See also: [`endlineno`][griffe.Alias.endlineno]. """ return self.final_target.lineno @@ -1606,7 +1615,7 @@ def lineno(self, lineno: int | None) -> None: def endlineno(self) -> int | None: """The ending line number of the target object. - See also: [`lineno`][griffelib.Alias.lineno]. + See also: [`lineno`][griffe.Alias.lineno]. """ return self.final_target.endlineno @@ -1618,8 +1627,8 @@ def endlineno(self, endlineno: int | None) -> None: def docstring(self) -> Docstring | None: """The target docstring. - See also: [`has_docstring`][griffelib.Alias.has_docstring], - [`has_docstrings`][griffelib.Alias.has_docstrings]. + See also: [`has_docstring`][griffe.Alias.has_docstring], + [`has_docstrings`][griffe.Alias.has_docstrings]. """ return self.final_target.docstring @@ -1636,7 +1645,7 @@ def type_parameters(self) -> TypeParameters: def labels(self) -> set[str]: """The target labels (`property`, `dataclass`, etc.). - See also: [`has_labels`][griffelib.Alias.has_labels]. + See also: [`has_labels`][griffe.Alias.has_labels]. """ return self.final_target.labels @@ -1647,7 +1656,7 @@ def imports(self) -> dict[str, str]: Keys are the names within the object (`from ... import ... as AS_NAME`), while the values are the actual names of the objects (`from ... import REAL_NAME as ...`). - See also: [`is_imported`][griffelib.Alias.is_imported]. + See also: [`is_imported`][griffe.Alias.is_imported]. """ return self.final_target.imports @@ -1666,7 +1675,7 @@ def exports(self) -> list[str | ExprName] | None: Exports get expanded by the loader before it expands wildcards and resolves aliases. - See also: [`GriffeLoader.expand_exports`][griffelib.GriffeLoader.expand_exports]. + See also: [`GriffeLoader.expand_exports`][griffe.GriffeLoader.expand_exports]. """ return self.final_target.exports @@ -1678,12 +1687,12 @@ def aliases(self) -> dict[str, Alias]: def is_kind(self, kind: str | Kind | set[str | Kind]) -> bool: """Tell if this object is of the given kind. - See also: [`is_module`][griffelib.Alias.is_module], - [`is_class`][griffelib.Alias.is_class], - [`is_function`][griffelib.Alias.is_function], - [`is_attribute`][griffelib.Alias.is_attribute], - [`is_type_alias`][griffelib.Alias.is_type_alias], - [`is_alias`][griffelib.Alias.is_alias]. + See also: [`is_module`][griffe.Alias.is_module], + [`is_class`][griffe.Alias.is_class], + [`is_function`][griffe.Alias.is_function], + [`is_attribute`][griffe.Alias.is_attribute], + [`is_type_alias`][griffe.Alias.is_type_alias], + [`is_alias`][griffe.Alias.is_alias]. Parameters: kind: An instance or set of kinds (strings or enumerations). @@ -1700,13 +1709,13 @@ def is_kind(self, kind: str | Kind | set[str | Kind]) -> bool: def is_module(self) -> bool: """Whether this object is a module. - See also: [`is_init_module`][griffelib.Alias.is_init_module]. - [`is_class`][griffelib.Alias.is_class], - [`is_function`][griffelib.Alias.is_function], - [`is_attribute`][griffelib.Alias.is_attribute], - [`is_type_alias`][griffelib.Alias.is_type_alias], - [`is_alias`][griffelib.Alias.is_alias], - [`is_kind`][griffelib.Alias.is_kind]. + See also: [`is_init_module`][griffe.Alias.is_init_module]. + [`is_class`][griffe.Alias.is_class], + [`is_function`][griffe.Alias.is_function], + [`is_attribute`][griffe.Alias.is_attribute], + [`is_type_alias`][griffe.Alias.is_type_alias], + [`is_alias`][griffe.Alias.is_alias], + [`is_kind`][griffe.Alias.is_kind]. """ return self.final_target.is_module @@ -1714,12 +1723,12 @@ def is_module(self) -> bool: def is_class(self) -> bool: """Whether this object is a class. - See also: [`is_module`][griffelib.Alias.is_module], - [`is_function`][griffelib.Alias.is_function], - [`is_attribute`][griffelib.Alias.is_attribute], - [`is_type_alias`][griffelib.Alias.is_type_alias], - [`is_alias`][griffelib.Alias.is_alias], - [`is_kind`][griffelib.Alias.is_kind]. + See also: [`is_module`][griffe.Alias.is_module], + [`is_function`][griffe.Alias.is_function], + [`is_attribute`][griffe.Alias.is_attribute], + [`is_type_alias`][griffe.Alias.is_type_alias], + [`is_alias`][griffe.Alias.is_alias], + [`is_kind`][griffe.Alias.is_kind]. """ return self.final_target.is_class @@ -1727,12 +1736,12 @@ def is_class(self) -> bool: def is_function(self) -> bool: """Whether this object is a function. - See also: [`is_module`][griffelib.Alias.is_module], - [`is_class`][griffelib.Alias.is_class], - [`is_attribute`][griffelib.Alias.is_attribute], - [`is_type_alias`][griffelib.Alias.is_type_alias], - [`is_alias`][griffelib.Alias.is_alias], - [`is_kind`][griffelib.Alias.is_kind]. + See also: [`is_module`][griffe.Alias.is_module], + [`is_class`][griffe.Alias.is_class], + [`is_attribute`][griffe.Alias.is_attribute], + [`is_type_alias`][griffe.Alias.is_type_alias], + [`is_alias`][griffe.Alias.is_alias], + [`is_kind`][griffe.Alias.is_kind]. """ return self.final_target.is_function @@ -1740,12 +1749,12 @@ def is_function(self) -> bool: def is_attribute(self) -> bool: """Whether this object is an attribute. - See also: [`is_module`][griffelib.Alias.is_module], - [`is_class`][griffelib.Alias.is_class], - [`is_function`][griffelib.Alias.is_function], - [`is_type_alias`][griffelib.Alias.is_type_alias], - [`is_alias`][griffelib.Alias.is_alias], - [`is_kind`][griffelib.Alias.is_kind]. + See also: [`is_module`][griffe.Alias.is_module], + [`is_class`][griffe.Alias.is_class], + [`is_function`][griffe.Alias.is_function], + [`is_type_alias`][griffe.Alias.is_type_alias], + [`is_alias`][griffe.Alias.is_alias], + [`is_kind`][griffe.Alias.is_kind]. """ return self.final_target.is_attribute @@ -1753,19 +1762,19 @@ def is_attribute(self) -> bool: def is_type_alias(self) -> bool: """Whether this object is a type alias. - See also: [`is_module`][griffelib.Alias.is_module], - [`is_class`][griffelib.Alias.is_class], - [`is_function`][griffelib.Alias.is_function], - [`is_attribute`][griffelib.Alias.is_attribute], - [`is_alias`][griffelib.Alias.is_alias], - [`is_kind`][griffelib.Alias.is_kind]. + See also: [`is_module`][griffe.Alias.is_module], + [`is_class`][griffe.Alias.is_class], + [`is_function`][griffe.Alias.is_function], + [`is_attribute`][griffe.Alias.is_attribute], + [`is_alias`][griffe.Alias.is_alias], + [`is_kind`][griffe.Alias.is_kind]. """ return self.final_target.is_type_alias def has_labels(self, *labels: str) -> bool: """Tell if this object has all the given labels. - See also: [`labels`][griffelib.Alias.labels]. + See also: [`labels`][griffe.Alias.labels]. Parameters: *labels: Labels that must be present. @@ -1778,9 +1787,9 @@ def has_labels(self, *labels: str) -> bool: def filter_members(self, *predicates: Callable[[Object | Alias], bool]) -> dict[str, Object | Alias]: """Filter and return members based on predicates. - See also: [`members`][griffelib.Alias.members], - [`get_member`][griffelib.Alias.get_member], - [`set_member`][griffelib.Alias.set_member]. + See also: [`members`][griffe.Alias.members], + [`get_member`][griffe.Alias.get_member], + [`set_member`][griffe.Alias.set_member]. Parameters: *predicates: A list of predicates, i.e. callables accepting a member as argument and returning a boolean. @@ -1794,7 +1803,7 @@ def filter_members(self, *predicates: Callable[[Object | Alias], bool]) -> dict[ def module(self) -> Module: """The parent module of this object. - See also: [`package`][griffelib.Alias.package]. + See also: [`package`][griffe.Alias.package]. Raises: ValueError: When the object is not a module and does not have a parent. @@ -1805,7 +1814,7 @@ def module(self) -> Module: def package(self) -> Module: """The absolute top module (the package) of this object. - See also: [`module`][griffelib.Alias.module]. + See also: [`module`][griffe.Alias.module]. """ return self.final_target.package @@ -1813,8 +1822,8 @@ def package(self) -> Module: def filepath(self) -> Path | list[Path]: """The file path (or directory list for namespace packages) where this object was defined. - See also: [`relative_filepath`][griffelib.Alias.relative_filepath], - [`relative_package_filepath`][griffelib.Alias.relative_package_filepath]. + See also: [`relative_filepath`][griffe.Alias.relative_filepath], + [`relative_package_filepath`][griffe.Alias.relative_package_filepath]. """ return self.final_target.filepath @@ -1824,8 +1833,8 @@ def relative_filepath(self) -> Path: If this object's file path is not relative to the current working directory, return its absolute path. - See also: [`filepath`][griffelib.Alias.filepath], - [`relative_package_filepath`][griffelib.Alias.relative_package_filepath]. + See also: [`filepath`][griffe.Alias.filepath], + [`relative_package_filepath`][griffe.Alias.relative_package_filepath]. Raises: ValueError: When the relative path could not be computed. @@ -1836,8 +1845,8 @@ def relative_filepath(self) -> Path: def relative_package_filepath(self) -> Path: """The file path where this object was defined, relative to the top module path. - See also: [`filepath`][griffelib.Alias.filepath], - [`relative_filepath`][griffelib.Alias.relative_filepath]. + See also: [`filepath`][griffe.Alias.filepath], + [`relative_filepath`][griffe.Alias.relative_filepath]. Raises: ValueError: When the relative path could not be computed. @@ -1850,7 +1859,7 @@ def canonical_path(self) -> str: The canonical path is the path where the object was defined (not imported). - See also: [`path`][griffelib.Alias.path]. + See also: [`path`][griffe.Alias.path]. """ return self.final_target.canonical_path @@ -1858,8 +1867,8 @@ def canonical_path(self) -> str: def lines_collection(self) -> LinesCollection: """The lines collection attached to this object or its parents. - See also: [`lines`][griffelib.Alias.lines], - [`source`][griffelib.Alias.source]. + See also: [`lines`][griffe.Alias.lines], + [`source`][griffe.Alias.source]. Raises: ValueError: When no modules collection can be found in the object or its parents. @@ -1870,8 +1879,8 @@ def lines_collection(self) -> LinesCollection: def lines(self) -> list[str]: """The lines containing the source of this object. - See also: [`source`][griffelib.Alias.source], - [`lines_collection`][griffelib.Alias.lines_collection]. + See also: [`source`][griffe.Alias.source], + [`lines_collection`][griffe.Alias.lines_collection]. """ return self.final_target.lines @@ -1879,8 +1888,8 @@ def lines(self) -> list[str]: def source(self) -> str: """The source code of this object. - See also: [`lines`][griffelib.Alias.lines], - [`lines_collection`][griffelib.Alias.lines_collection]. + See also: [`lines`][griffe.Alias.lines], + [`lines_collection`][griffe.Alias.lines_collection]. """ return self.final_target.source @@ -1911,9 +1920,9 @@ def _filepath(self) -> Path | list[Path] | None: def bases(self) -> list[Expr | str]: """The class bases. - See also: [`Class`][griffelib.Class], - [`resolved_bases`][griffelib.Alias.resolved_bases], - [`mro`][griffelib.Alias.mro]. + See also: [`Class`][griffe.Class], + [`resolved_bases`][griffe.Alias.resolved_bases], + [`mro`][griffe.Alias.mro]. """ return cast("Class", self.final_target).bases @@ -1926,8 +1935,8 @@ def keywords(self) -> dict[str, Expr | str]: def decorators(self) -> list[Decorator]: """The class/function decorators. - See also: [`Function`][griffelib.Function], - [`Class`][griffelib.Class]. + See also: [`Function`][griffe.Function], + [`Class`][griffe.Class]. """ return cast("Union[Class, Function]", self.target).decorators @@ -1945,7 +1954,7 @@ def is_init_method(self) -> bool: def is_init_module(self) -> bool: """Whether this module is an `__init__.py` module. - See also: [`is_module`][griffelib.Alias.is_module]. + See also: [`is_module`][griffe.Alias.is_module]. """ return cast("Module", self.final_target).is_init_module @@ -1953,7 +1962,7 @@ def is_init_module(self) -> bool: def is_package(self) -> bool: """Whether this module is a package (top module). - See also: [`is_subpackage`][griffelib.Alias.is_subpackage]. + See also: [`is_subpackage`][griffe.Alias.is_subpackage]. """ return cast("Module", self.final_target).is_package @@ -1961,7 +1970,7 @@ def is_package(self) -> bool: def is_subpackage(self) -> bool: """Whether this module is a subpackage. - See also: [`is_package`][griffelib.Alias.is_package]. + See also: [`is_package`][griffe.Alias.is_package]. """ return cast("Module", self.final_target).is_subpackage @@ -1969,7 +1978,7 @@ def is_subpackage(self) -> bool: def is_namespace_package(self) -> bool: """Whether this module is a namespace package (top folder, no `__init__.py`). - See also: [`is_namespace_subpackage`][griffelib.Alias.is_namespace_subpackage]. + See also: [`is_namespace_subpackage`][griffe.Alias.is_namespace_subpackage]. """ return cast("Module", self.final_target).is_namespace_package @@ -1977,7 +1986,7 @@ def is_namespace_package(self) -> bool: def is_namespace_subpackage(self) -> bool: """Whether this module is a namespace subpackage. - See also: [`is_namespace_package`][griffelib.Alias.is_namespace_package]. + See also: [`is_namespace_package`][griffe.Alias.is_namespace_package]. """ return cast("Module", self.final_target).is_namespace_subpackage @@ -2073,9 +2082,9 @@ def target(self) -> Object | Alias: Upon accessing this property, if the target is not already resolved, a lookup is done using the modules collection to find the target. - See also: [`final_target`][griffelib.Alias.final_target], - [`resolve_target`][griffelib.Alias.resolve_target], - [`resolved`][griffelib.Alias.resolved]. + See also: [`final_target`][griffe.Alias.final_target], + [`resolve_target`][griffe.Alias.resolve_target], + [`resolved`][griffe.Alias.resolved]. """ if not self.resolved: self.resolve_target() @@ -2096,9 +2105,9 @@ def final_target(self) -> Object: This will iterate through the targets until a non-alias object is found. - See also: [`target`][griffelib.Alias.target], - [`resolve_target`][griffelib.Alias.resolve_target], - [`resolved`][griffelib.Alias.resolved]. + See also: [`target`][griffe.Alias.target], + [`resolve_target`][griffe.Alias.resolve_target], + [`resolved`][griffe.Alias.resolved]. """ # Here we quickly iterate on the alias chain, # remembering which path we've seen already to detect cycles. @@ -2119,9 +2128,9 @@ def final_target(self) -> Object: def resolve_target(self) -> None: """Resolve the target. - See also: [`target`][griffelib.Alias.target], - [`final_target`][griffelib.Alias.final_target], - [`resolved`][griffelib.Alias.resolved]. + See also: [`target`][griffe.Alias.target], + [`final_target`][griffe.Alias.final_target], + [`resolved`][griffe.Alias.resolved]. Raises: AliasResolutionError: When the target cannot be resolved. @@ -2178,7 +2187,7 @@ def resolved(self) -> bool: def wildcard(self) -> str | None: """The module on which the wildcard import is performed (if any). - See also: [`GriffeLoader.expand_wildcards`][griffelib.GriffeLoader.expand_wildcards]. + See also: [`GriffeLoader.expand_wildcards`][griffe.GriffeLoader.expand_wildcards]. """ if self.name.endswith("/*"): return self.target_path @@ -2187,7 +2196,7 @@ def wildcard(self) -> str | None: def as_dict(self, *, full: bool = False, **kwargs: Any) -> dict[str, Any]: # noqa: ARG002 """Return this alias' data as a dictionary. - See also: [`as_json`][griffelib.Alias.as_json]. + See also: [`as_json`][griffe.Alias.as_json]. Parameters: full: Whether to return full info, or just base info. @@ -2281,7 +2290,7 @@ def imports_future_annotations(self) -> bool: def is_init_module(self) -> bool: """Whether this module is an `__init__.py` module. - See also: [`is_module`][griffelib.Module.is_module]. + See also: [`is_module`][griffe.Module.is_module]. """ if isinstance(self.filepath, list): return False @@ -2294,7 +2303,7 @@ def is_init_module(self) -> bool: def is_package(self) -> bool: """Whether this module is a package (top module). - See also: [`is_subpackage`][griffelib.Module.is_subpackage]. + See also: [`is_subpackage`][griffe.Module.is_subpackage]. """ return not bool(self.parent) and self.is_init_module @@ -2302,7 +2311,7 @@ def is_package(self) -> bool: def is_subpackage(self) -> bool: """Whether this module is a subpackage. - See also: [`is_package`][griffelib.Module.is_package]. + See also: [`is_package`][griffe.Module.is_package]. """ return bool(self.parent) and self.is_init_module @@ -2310,7 +2319,7 @@ def is_subpackage(self) -> bool: def is_namespace_package(self) -> bool: """Whether this module is a namespace package (top folder, no `__init__.py`). - See also: [`is_namespace_subpackage`][griffelib.Module.is_namespace_subpackage]. + See also: [`is_namespace_subpackage`][griffe.Module.is_namespace_subpackage]. """ try: return self.parent is None and isinstance(self.filepath, list) @@ -2321,7 +2330,7 @@ def is_namespace_package(self) -> bool: def is_namespace_subpackage(self) -> bool: """Whether this module is a namespace subpackage. - See also: [`is_namespace_package`][griffelib.Module.is_namespace_package]. + See also: [`is_namespace_package`][griffe.Module.is_namespace_package]. """ try: return ( @@ -2338,7 +2347,7 @@ def is_namespace_subpackage(self) -> bool: def as_dict(self, **kwargs: Any) -> dict[str, Any]: """Return this module's data as a dictionary. - See also: [`as_json`][griffelib.Module.as_json]. + See also: [`as_json`][griffe.Module.as_json]. Parameters: **kwargs: Additional serialization options. @@ -2383,8 +2392,8 @@ def __init__( self.bases: list[Expr | str] = list(bases) if bases else [] """The class bases. - See also: [`resolved_bases`][griffelib.Class.resolved_bases], - [`mro`][griffelib.Class.mro]. + See also: [`resolved_bases`][griffe.Class.resolved_bases], + [`mro`][griffe.Class.mro]. """ self.decorators: list[Decorator] = decorators or [] @@ -2433,8 +2442,8 @@ def resolved_bases(self) -> list[Object]: This method is part of the consumer API: do not use when producing Griffe trees! - See also: [`bases`][griffelib.Class.bases], - [`mro`][griffelib.Class.mro]. + See also: [`bases`][griffe.Class.bases], + [`mro`][griffe.Class.mro]. """ resolved_bases = [] for base in self.bases: @@ -2463,15 +2472,15 @@ def _mro(self, seen: tuple[str, ...] = ()) -> list[Class]: def mro(self) -> list[Class]: """Return a list of classes in order corresponding to Python's MRO. - See also: [`bases`][griffelib.Class.bases], - [`resolved_bases`][griffelib.Class.resolved_bases]. + See also: [`bases`][griffe.Class.bases], + [`resolved_bases`][griffe.Class.resolved_bases]. """ return self._mro()[1:] # Remove self. def as_dict(self, **kwargs: Any) -> dict[str, Any]: """Return this class' data as a dictionary. - See also: [`as_json`][griffelib.Class.as_json]. + See also: [`as_json`][griffe.Class.as_json]. Parameters: **kwargs: Additional serialization options. @@ -2566,7 +2575,7 @@ def is_init_method(self) -> bool: def as_dict(self, **kwargs: Any) -> dict[str, Any]: """Return this function's data as a dictionary. - See also: [`as_json`][griffelib.Function.as_json]. + See also: [`as_json`][griffe.Function.as_json]. Parameters: **kwargs: Additional serialization options. @@ -2688,7 +2697,7 @@ def __init__( def as_dict(self, **kwargs: Any) -> dict[str, Any]: """Return this attribute's data as a dictionary. - See also: [`as_json`][griffelib.Attribute.as_json]. + See also: [`as_json`][griffe.Attribute.as_json]. Parameters: **kwargs: Additional serialization options. diff --git a/scripts/gen_griffe_json.py b/scripts/gen_griffe_json.py index a1fb98dca..150eba043 100644 --- a/scripts/gen_griffe_json.py +++ b/scripts/gen_griffe_json.py @@ -5,5 +5,5 @@ python_handler = mkdocs_gen_files.config.plugins["mkdocstrings"].get_handler("python") data = python_handler.collect("griffe", options=python_handler.get_options({})) -with mkdocs_gen_files.open("griffelib.json", "w") as fd: +with mkdocs_gen_files.open("griffe.json", "w") as fd: print(data.as_json(full=True), file=fd) diff --git a/tests/test_docstrings/test_google.py b/tests/test_docstrings/test_google.py index 0685fd73d..0af072c6d 100644 --- a/tests/test_docstrings/test_google.py +++ b/tests/test_docstrings/test_google.py @@ -1,4 +1,4 @@ -"""Tests for the [Google-style parser][griffelib.docstrings.google].""" +"""Tests for the [Google-style parser][griffe.docstrings.google].""" from __future__ import annotations diff --git a/tests/test_docstrings/test_numpy.py b/tests/test_docstrings/test_numpy.py index 2cbe608c1..344856e50 100644 --- a/tests/test_docstrings/test_numpy.py +++ b/tests/test_docstrings/test_numpy.py @@ -1,4 +1,4 @@ -"""Tests for the [Numpy-style parser][griffelib.docstrings.numpy].""" +"""Tests for the [Numpy-style parser][griffe.docstrings.numpy].""" from __future__ import annotations diff --git a/tests/test_docstrings/test_sphinx.py b/tests/test_docstrings/test_sphinx.py index 738cf01a7..90279e4dd 100644 --- a/tests/test_docstrings/test_sphinx.py +++ b/tests/test_docstrings/test_sphinx.py @@ -1,4 +1,4 @@ -"""Tests for the [Sphinx-style parser][griffelib.docstrings.sphinx].""" +"""Tests for the [Sphinx-style parser][griffe.docstrings.sphinx].""" from __future__ import annotations From b6bb973ca4cfefd22a8ee87a008a1af761c88f2b Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 13:15:19 +0100 Subject: [PATCH 20/53] Don't introduce the new `griffelib` namespace --- config/ruff.toml | 12 +-- docs/extensions/official/runtime-objects.md | 2 +- docs/guide/contributors/architecture.md | 8 +- docs/guide/users/loading.md | 14 +-- docs/guide/users/navigating.md | 28 +++--- docs/introduction.md | 4 +- docs/reference/api/agents.md | 2 +- docs/reference/api/expressions.md | 2 +- docs/reference/api/loaders.md | 16 +-- duties.py | 2 +- mkdocs.yml | 2 +- .../griffecli/src/griffecli/_internal/cli.py | 22 ++--- .../src/{griffelib => griffe}/__init__.py | 98 +++++++++++-------- .../griffelib/src}/griffe/__main__.py | 8 +- .../_internal/__init__.py | 0 .../_internal/agents/__init__.py | 0 .../_internal/agents/inspector.py | 26 ++--- .../_internal/agents/nodes/__init__.py | 0 .../_internal/agents/nodes/assignments.py | 0 .../_internal/agents/nodes/ast.py | 2 +- .../_internal/agents/nodes/docstrings.py | 0 .../_internal/agents/nodes/exports.py | 10 +- .../_internal/agents/nodes/imports.py | 2 +- .../_internal/agents/nodes/parameters.py | 2 +- .../_internal/agents/nodes/runtime.py | 4 +- .../_internal/agents/nodes/values.py | 2 +- .../_internal/agents/visitor.py | 32 +++--- .../_internal/c3linear.py | 0 .../_internal/collections.py | 4 +- .../{griffelib => griffe}/_internal/debug.py | 4 +- .../{griffelib => griffe}/_internal/diff.py | 18 ++-- .../_internal/docstrings/__init__.py | 0 .../_internal/docstrings/auto.py | 18 ++-- .../_internal/docstrings/google.py | 10 +- .../_internal/docstrings/models.py | 6 +- .../_internal/docstrings/numpy.py | 12 +-- .../_internal/docstrings/parsers.py | 14 +-- .../_internal/docstrings/sphinx.py | 8 +- .../_internal/docstrings/utils.py | 12 +-- .../_internal/encoders.py | 14 +-- .../_internal/enumerations.py | 0 .../_internal/exceptions.py | 2 +- .../_internal/expressions.py | 12 +-- .../_internal/extensions/__init__.py | 0 .../_internal/extensions/base.py | 20 ++-- .../_internal/extensions/dataclasses.py | 10 +- .../_internal/extensions/unpack_typeddict.py | 10 +- .../{griffelib => griffe}/_internal/finder.py | 20 ++-- .../{griffelib => griffe}/_internal/git.py | 8 +- .../_internal/importer.py | 0 .../{griffelib => griffe}/_internal/loader.py | 50 +++++----- .../{griffelib => griffe}/_internal/logger.py | 0 .../{griffelib => griffe}/_internal/merger.py | 6 +- .../{griffelib => griffe}/_internal/mixins.py | 12 +-- .../{griffelib => griffe}/_internal/models.py | 72 ++++++-------- .../{griffelib => griffe}/_internal/py.typed | 0 .../{griffelib => griffe}/_internal/stats.py | 6 +- .../{griffelib => griffe}/_internal/tests.py | 18 ++-- scripts/gen_structure_docs.py | 8 +- src/griffe/__init__.py | 28 ------ src/griffe/py.typed | 0 tests/helpers.py | 2 +- tests/test_cli.py | 2 +- tests/test_docstrings/conftest.py | 2 +- tests/test_encoders.py | 2 +- tests/test_extensions/test_base.py | 2 +- tests/test_finder.py | 2 +- 67 files changed, 344 insertions(+), 370 deletions(-) rename packages/griffelib/src/{griffelib => griffe}/__init__.py (84%) rename {src => packages/griffelib/src}/griffe/__main__.py (61%) rename packages/griffelib/src/{griffelib => griffe}/_internal/__init__.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/__init__.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/inspector.py (97%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/__init__.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/assignments.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/ast.py (98%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/docstrings.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/exports.py (91%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/imports.py (95%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/parameters.py (97%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/runtime.py (99%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/nodes/values.py (96%) rename packages/griffelib/src/{griffelib => griffe}/_internal/agents/visitor.py (96%) rename packages/griffelib/src/{griffelib => griffe}/_internal/c3linear.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/collections.py (94%) rename packages/griffelib/src/{griffelib => griffe}/_internal/debug.py (96%) rename packages/griffelib/src/{griffelib => griffe}/_internal/diff.py (97%) rename packages/griffelib/src/{griffelib => griffe}/_internal/docstrings/__init__.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/docstrings/auto.py (92%) rename packages/griffelib/src/{griffelib => griffe}/_internal/docstrings/google.py (99%) rename packages/griffelib/src/{griffelib => griffe}/_internal/docstrings/models.py (98%) rename packages/griffelib/src/{griffelib => griffe}/_internal/docstrings/numpy.py (98%) rename packages/griffelib/src/{griffelib => griffe}/_internal/docstrings/parsers.py (72%) rename packages/griffelib/src/{griffelib => griffe}/_internal/docstrings/sphinx.py (98%) rename packages/griffelib/src/{griffelib => griffe}/_internal/docstrings/utils.py (88%) rename packages/griffelib/src/{griffelib => griffe}/_internal/encoders.py (97%) rename packages/griffelib/src/{griffelib => griffe}/_internal/enumerations.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/exceptions.py (98%) rename packages/griffelib/src/{griffelib => griffe}/_internal/expressions.py (99%) rename packages/griffelib/src/{griffelib => griffe}/_internal/extensions/__init__.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/extensions/base.py (96%) rename packages/griffelib/src/{griffelib => griffe}/_internal/extensions/dataclasses.py (96%) rename packages/griffelib/src/{griffelib => griffe}/_internal/extensions/unpack_typeddict.py (96%) rename packages/griffelib/src/{griffelib => griffe}/_internal/finder.py (95%) rename packages/griffelib/src/{griffelib => griffe}/_internal/git.py (97%) rename packages/griffelib/src/{griffelib => griffe}/_internal/importer.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/loader.py (97%) rename packages/griffelib/src/{griffelib => griffe}/_internal/logger.py (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/merger.py (95%) rename packages/griffelib/src/{griffelib => griffe}/_internal/mixins.py (97%) rename packages/griffelib/src/{griffelib => griffe}/_internal/models.py (98%) rename packages/griffelib/src/{griffelib => griffe}/_internal/py.typed (100%) rename packages/griffelib/src/{griffelib => griffe}/_internal/stats.py (97%) rename packages/griffelib/src/{griffelib => griffe}/_internal/tests.py (96%) delete mode 100644 src/griffe/__init__.py delete mode 100644 src/griffe/py.typed diff --git a/config/ruff.toml b/config/ruff.toml index 462ddcbce..5b1808839 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -35,7 +35,7 @@ ignore = [ "TRY003", # Avoid specifying long messages outside the exception class ] -logger-objects = ["griffe.logger", "griffelib.logger"] +logger-objects = ["griffe.logger", "griffe.logger"] [lint.per-file-ignores] "packages/griffecli/src/griffecli/__main__.py" = [ @@ -44,18 +44,18 @@ logger-objects = ["griffe.logger", "griffelib.logger"] "packages/griffecli/src/griffecli/_internal/cli.py" = [ "T201", # Print statement ] -"packages/griffelib/src/griffelib/_internal/git.py" = [ +"packages/griffelib/src/griffe/_internal/git.py" = [ "S603", # `subprocess` call: check for execution of untrusted input "S607", # Starting a process with a partial executable path ] -"packages/griffelib/src/griffelib/_internal/agents/nodes/*.py" = [ +"packages/griffelib/src/griffe/_internal/agents/nodes/*.py" = [ "ARG001", # Unused function argument "N812", # Lowercase `keyword` imported as non-lowercase `NodeKeyword` ] -"packages/griffelib/src/griffelib/_internal/debug.py" = [ +"packages/griffelib/src/griffe/_internal/debug.py" = [ "T201", # Print statement ] -"packages/griffelib/src/griffelib/_internal/**.py" = [ +"packages/griffelib/src/griffe/_internal/**.py" = [ "D100", # Missing docstring in public module ] "scripts/*.py" = [ @@ -84,7 +84,7 @@ docstring-quotes = "double" ban-relative-imports = "all" [lint.isort] -known-first-party = ["griffe", "griffelib", "griffecli"] +known-first-party = ["griffe", "griffecli"] [lint.pydocstyle] convention = "google" diff --git a/docs/extensions/official/runtime-objects.md b/docs/extensions/official/runtime-objects.md index 27b391e8a..fbfb72d34 100644 --- a/docs/extensions/official/runtime-objects.md +++ b/docs/extensions/official/runtime-objects.md @@ -15,7 +15,7 @@ This extension stores runtime objects corresponding to each loaded Griffe object >>> griffe_data["parse"].extra defaultdict(, {'runtime-objects': {'object': }}) >>> griffe_data["Module"].extra -defaultdict(, {'runtime-objects': {'object': }}) +defaultdict(, {'runtime-objects': {'object': }}) ``` It can be useful in combination with mkdocstrings-python and custom templates, to iterate over object values or their attributes that couldn't be loaded by Griffe itself (for example, objects built dynamically and loaded as attributes won't have "members" to iterate over). diff --git a/docs/guide/contributors/architecture.md b/docs/guide/contributors/architecture.md index 3fc474e75..28aa1cd83 100644 --- a/docs/guide/contributors/architecture.md +++ b/docs/guide/contributors/architecture.md @@ -23,7 +23,7 @@ descriptions = { "site": "Documentation site, built with `make run mkdocs build` (git-ignored).", "src": "The source of our Python package(s). See [Sources](#sources) and [Program structure](#program-structure).", "src/griffe": "Our public API, exposed to users. See [Program structure](#program-structure).", - "packages/griffelib/src/griffelib/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).", + "packages/griffelib/src/griffe/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).", "tests": "Our test suite. See [Tests](#tests).", ".copier-answers.yml": "The answers file generated by [Copier](https://copier.readthedocs.io/en/stable/). See [Boilerplate](#boilerplate).", "devdeps.txt": "Our development dependencies specification. See [`make setup`][command-setup] command.", @@ -104,11 +104,11 @@ Sources are located in the `src` folder, following the [src-layout](https://pack Our test suite is located in the `tests` folder. It is located outside of the sources as to not pollute distributions (it would be very wrong to publish a `tests` package as part of our distributions, since this name is extremely common), or worse, the public API. The `tests` folder is however included in our source distributions (`.tar.gz`), alongside most of our metadata and configuration files. Check out `pyproject.toml` to get the full list of files included in our source distributions. -The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffelib._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. +The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffe._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. ## Program structure -The internal API is contained within the `packages/griffelib/src/griffelib/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from `griffelib`, which itself imports from various submodules of `griffelib._internal`. +The internal API is contained within the `packages/griffelib/src/griffe/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from various submodules of `griffe._internal`. Users then import `griffe` directly, or import objects from it. @@ -122,7 +122,7 @@ if os.getenv("DEPLOY") == "true": from pydeps.target import Target cli.verbose = cli._not_verbose - options = cli.parse_args(["packages/griffelib/src/griffelib", "--noshow", "--reverse"]) + options = cli.parse_args(["packages/griffelib/src/griffe", "--noshow", "--reverse"]) colors.START_COLOR = 128 target = Target(options["fname"]) with target.chdir_work(): diff --git a/docs/guide/users/loading.md b/docs/guide/users/loading.md index 4bbd1c12a..620917803 100644 --- a/docs/guide/users/loading.md +++ b/docs/guide/users/loading.md @@ -214,10 +214,10 @@ from package1 import X False >>> package2["X"].target Traceback (most recent call last): - File "griffelib/_internal/models.py", line 1375, in _resolve_target + File "griffe/_internal/models.py", line 1375, in _resolve_target resolved = self.modules_collection.get_member(self.target_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "griffelib/_internal/mixins.py", line 84, in get_member + File "griffe/_internal/mixins.py", line 84, in get_member return self.members[parts[0]].get_member(parts[1:]) # type: ignore[attr-defined] ~~~~~~~~~~~~^^^^^^^^^^ KeyError: 'package1' @@ -226,13 +226,13 @@ The above exception was the direct cause of the following exception: Traceback (most recent call last): File "", line 1, in - File "griffelib/_internal/dataclasses.py", line 1310, in target + File "griffe/_internal/dataclasses.py", line 1310, in target self.resolve_target() - File "griffelib/_internal/dataclasses.py", line 1369, in resolve_target + File "griffe/_internal/dataclasses.py", line 1369, in resolve_target self._resolve_target() - File "griffelib/_internal/dataclasses.py", line 1377, in _resolve_target + File "griffe/_internal/dataclasses.py", line 1377, in _resolve_target raise AliasResolutionError(self) from error -griffelib._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) +griffe._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) ``` As you can see in the interpreter session above, Griffe did not resolve the `X` alias. When we tried to access its target object anyway, it failed with a `KeyError`, which was raised again as an [`AliasResolutionError`][griffe.AliasResolutionError]. @@ -250,7 +250,7 @@ False # Hmm? >>> package2["X"].target Traceback (most recent call last): ... -griffelib._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) +griffe._internal.exceptions.AliasResolutionError: Could not resolve alias package2.X pointing at package1.X (in package2/__init__.py:1) ``` The same exception again? What happened here? We loaded both packages, but Griffe still failed to resolve the alias. That is expected; here is the explanation. diff --git a/docs/guide/users/navigating.md b/docs/guide/users/navigating.md index d849cc4aa..db3bc48c5 100644 --- a/docs/guide/users/navigating.md +++ b/docs/guide/users/navigating.md @@ -14,17 +14,17 @@ When [loading an object](loading.md), Griffe will give you back an instance of o ```python >>> import griffe >>> type(griffe.load("markdown")) - + >>> type(griffe.load("markdown.core.Markdown")) - + >>> type(griffe.load("markdown.Markdown")) - + >>> type(griffe.load("markdown.core.markdown")) - + >>> type(griffe.load("markdown.markdown")) - + >>> type(griffe.load("markdown.Markdown.references")) - + ``` However deep the object is, Griffe loads the entire package. It means that in all the cases above, Griffe loaded the whole `markdown` package. The model instance Griffe gives you back is therefore part of a tree that you can navigate. @@ -41,7 +41,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffelib.load("markdown") + >>> markdown = griffe.load("markdown") >>> markdown.members["Markdown"] Alias('Markdown', 'markdown.core.Markdown') >>> markdown.members["core"].members["Markdown"] @@ -54,7 +54,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffelib.load("markdown") + >>> markdown = griffe.load("markdown") >>> markdown["core"]["Markdown"] # chained access Class('Markdown', 46, 451) >>> markdown["core.Markdown"] # merged access @@ -65,7 +65,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffelib.load("markdown") + >>> markdown = griffe.load("markdown") >>> markdown[("core", "Markdown")] # tuple access Class('Markdown', 46, 451) >>> # Due to the nature of the subscript syntax, @@ -78,7 +78,7 @@ To access an object's members, there are a few options: ```pycon >>> import griffe - >>> markdown = griffelib.load("markdown") + >>> markdown = griffe.load("markdown") >>> markdown.get_member("core.Markdown") Class('Markdown', 46, 451) ``` @@ -122,7 +122,7 @@ If a base class cannot be resolved during computation of inherited members, Grif If you want to access all members at once (both declared and inherited), use the [`all_members`][griffe.Object.all_members] attribute. If you want to access only declared members, use the [`members`][griffe.Object] attribute. -Accessing the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by griffelib. Don't try to access inherited members in extensions, while visiting or inspecting modules. +Accessing the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by griffe. Don't try to access inherited members in extensions, while visiting or inspecting modules. #### Limitations @@ -254,7 +254,7 @@ from pkg2 import A as B ```pycon >>> import griffe ->>> B = griffelib.load("pkg1.B") +>>> B = griffe.load("pkg1.B") >>> B.path 'pkg1.B' >>> B.canonical_path @@ -339,13 +339,13 @@ Each object has an optional [`docstring`][griffe.Object.docstring] attached to i Docstrings can be parsed against several [docstring-styles](../../reference/docstrings.md), which are micro-formats that allow documenting things such as parameters, returned values, raised exceptions, etc.. -When loading a package, it is possible to specify the docstring style to attach to every docstring (see the `docstring_parser` parameter of [`griffelib.load`][griffe.load]). Accessing the [`parsed`][griffe.Docstring.parsed] field of a docstring will use this style to parse the docstring and return a list of [docstring sections][advanced-api-sections]. Each section has a `value` whose shape depends on the section kind. For example, parameter sections have a list of parameter representations as value, while a text section only has a string as value. +When loading a package, it is possible to specify the docstring style to attach to every docstring (see the `docstring_parser` parameter of [`griffe.load`][griffe.load]). Accessing the [`parsed`][griffe.Docstring.parsed] field of a docstring will use this style to parse the docstring and return a list of [docstring sections][advanced-api-sections]. Each section has a `value` whose shape depends on the section kind. For example, parameter sections have a list of parameter representations as value, while a text section only has a string as value. After a package is loaded, it is still possible to change the style used for specific docstrings by either overriding their [`parser`][griffe.Docstring.parser] and [`parser_options`][griffe.Docstring.parser_options] attributes, or by calling their [`parse()`][griffe.Docstring.parse] method with a different style: ```pycon >>> import griffe ->>> markdown = griffelib.load("markdown", docstring_parser="google") +>>> markdown = griffe.load("markdown", docstring_parser="google") >>> markdown["Markdown"].docstring.parse("numpy") [...] ``` diff --git a/docs/introduction.md b/docs/introduction.md index 91d99cc8c..a7226fa6e 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -22,10 +22,10 @@ Both commands accept a `-h`, `--help` argument to show all the available options ## Python library -As a library, Griffe exposes all its public API directly in the top-level module. It means you can simply import `griffe` or `griffelib` to access all its API. +As a library, Griffe exposes all its public API directly in the top-level module. It means you can simply import `griffe` to access all its API. ```python -import griffe # or griffelib +import griffe griffe.load(...) griffe.find_breaking_changes(...) diff --git a/docs/reference/api/agents.md b/docs/reference/api/agents.md index c977ebe2b..ca7f50c4d 100644 --- a/docs/reference/api/agents.md +++ b/docs/reference/api/agents.md @@ -4,7 +4,7 @@ Griffe is able to analyze code both statically and dynamically. ## **Main API** -::: griffelib.visit +::: griffe.visit ::: griffe.inspect diff --git a/docs/reference/api/expressions.md b/docs/reference/api/expressions.md index d91795c79..3b010a5d0 100644 --- a/docs/reference/api/expressions.md +++ b/docs/reference/api/expressions.md @@ -1,6 +1,6 @@ # Expressions -::: griffelib._internal.expressions +::: griffe._internal.expressions options: members: false show_root_heading: false diff --git a/docs/reference/api/loaders.md b/docs/reference/api/loaders.md index 10dccf38c..b3eb060c9 100644 --- a/docs/reference/api/loaders.md +++ b/docs/reference/api/loaders.md @@ -2,22 +2,22 @@ ## **Main API** -::: griffelib.load +::: griffe.load -::: griffelib.load_git +::: griffe.load_git -::: griffelib.load_pypi +::: griffe.load_pypi ## **Advanced API** -::: griffelib.GriffeLoader +::: griffe.GriffeLoader -::: griffelib.ModulesCollection +::: griffe.ModulesCollection -::: griffelib.LinesCollection +::: griffe.LinesCollection ## **Additional API** -::: griffelib.Stats +::: griffe.Stats -::: griffelib.merge_stubs +::: griffe.merge_stubs diff --git a/duties.py b/duties.py index a2f8d7d61..d3f1178cd 100644 --- a/duties.py +++ b/duties.py @@ -285,7 +285,7 @@ def check_api(ctx: Context, *cli_args: str) -> None: *cli_args: Additional Griffe CLI arguments. """ ctx.run( - tools.griffecli.check( + tools.griffe.check( "griffe", search=["src"], color=True, diff --git a/mkdocs.yml b/mkdocs.yml index 0ca192944..52e130130 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,7 +4,7 @@ site_url: "https://mkdocstrings.github.io/griffe" repo_url: "https://github.com/mkdocstrings/griffe" repo_name: "mkdocstrings/griffe" site_dir: "site" -watch: [mkdocs.yml, README.md, CONTRIBUTING.md, CHANGELOG.md, src] +watch: [mkdocs.yml, README.md, CONTRIBUTING.md, CHANGELOG.md, packages] copyright: Copyright © 2021 Timothée Mazzucotelli edit_uri: edit/main/docs/ diff --git a/packages/griffecli/src/griffecli/_internal/cli.py b/packages/griffecli/src/griffecli/_internal/cli.py index a78a52fbe..5bd46fcc9 100644 --- a/packages/griffecli/src/griffecli/_internal/cli.py +++ b/packages/griffecli/src/griffecli/_internal/cli.py @@ -24,21 +24,21 @@ import colorama -from griffelib._internal import debug -from griffelib._internal.diff import find_breaking_changes -from griffelib._internal.encoders import JSONEncoder -from griffelib._internal.enumerations import ExplanationStyle, Parser -from griffelib._internal.exceptions import ExtensionError, GitError -from griffelib._internal.extensions.base import load_extensions -from griffelib._internal.git import _get_latest_tag, _get_repo_root -from griffelib._internal.loader import GriffeLoader, load, load_git, load_pypi -from griffelib._internal.logger import logger +from griffe._internal import debug +from griffe._internal.diff import find_breaking_changes +from griffe._internal.encoders import JSONEncoder +from griffe._internal.enumerations import ExplanationStyle, Parser +from griffe._internal.exceptions import ExtensionError, GitError +from griffe._internal.extensions.base import load_extensions +from griffe._internal.git import _get_latest_tag, _get_repo_root +from griffe._internal.loader import GriffeLoader, load, load_git, load_pypi +from griffe._internal.logger import logger if TYPE_CHECKING: from collections.abc import Sequence - from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffelib._internal.extensions.base import Extension, Extensions + from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffe._internal.extensions.base import Extension, Extensions DEFAULT_LOG_LEVEL = os.getenv("GRIFFE_LOG_LEVEL", "INFO").upper() diff --git a/packages/griffelib/src/griffelib/__init__.py b/packages/griffelib/src/griffe/__init__.py similarity index 84% rename from packages/griffelib/src/griffelib/__init__.py rename to packages/griffelib/src/griffe/__init__.py index 7e9f74d4f..1a892c1f2 100644 --- a/packages/griffelib/src/griffelib/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -157,9 +157,9 @@ from __future__ import annotations -from griffelib._internal.agents.inspector import Inspector, inspect -from griffelib._internal.agents.nodes.assignments import get_instance_names, get_name, get_names -from griffelib._internal.agents.nodes.ast import ( +from griffe._internal.agents.inspector import Inspector, inspect +from griffe._internal.agents.nodes.assignments import get_instance_names, get_name, get_names +from griffe._internal.agents.nodes.ast import ( ast_children, ast_first_child, ast_kind, @@ -170,16 +170,16 @@ ast_previous_siblings, ast_siblings, ) -from griffelib._internal.agents.nodes.docstrings import get_docstring -from griffelib._internal.agents.nodes.exports import get__all__, safe_get__all__ -from griffelib._internal.agents.nodes.imports import relative_to_absolute -from griffelib._internal.agents.nodes.parameters import ParametersType, get_parameters -from griffelib._internal.agents.nodes.runtime import ObjectNode -from griffelib._internal.agents.nodes.values import get_value, safe_get_value -from griffelib._internal.agents.visitor import Visitor, builtin_decorators, stdlib_decorators, typing_overload, visit -from griffelib._internal.c3linear import c3linear_merge -from griffelib._internal.collections import LinesCollection, ModulesCollection -from griffelib._internal.diff import ( +from griffe._internal.agents.nodes.docstrings import get_docstring +from griffe._internal.agents.nodes.exports import get__all__, safe_get__all__ +from griffe._internal.agents.nodes.imports import relative_to_absolute +from griffe._internal.agents.nodes.parameters import ParametersType, get_parameters +from griffe._internal.agents.nodes.runtime import ObjectNode +from griffe._internal.agents.nodes.values import get_value, safe_get_value +from griffe._internal.agents.visitor import Visitor, builtin_decorators, stdlib_decorators, typing_overload, visit +from griffe._internal.c3linear import c3linear_merge +from griffe._internal.collections import LinesCollection, ModulesCollection +from griffe._internal.diff import ( AttributeChangedTypeBreakage, AttributeChangedValueBreakage, Breakage, @@ -195,15 +195,15 @@ ReturnChangedTypeBreakage, find_breaking_changes, ) -from griffelib._internal.docstrings.auto import ( +from griffe._internal.docstrings.auto import ( AutoOptions, DocstringDetectionMethod, PerStyleOptions, infer_docstring_style, parse_auto, ) -from griffelib._internal.docstrings.google import GoogleOptions, parse_google -from griffelib._internal.docstrings.models import ( +from griffe._internal.docstrings.google import GoogleOptions, parse_google +from griffe._internal.docstrings.models import ( DocstringAdmonition, DocstringAttribute, DocstringClass, @@ -239,17 +239,17 @@ DocstringWarn, DocstringYield, ) -from griffelib._internal.docstrings.numpy import NumpyOptions, parse_numpy -from griffelib._internal.docstrings.parsers import ( +from griffe._internal.docstrings.numpy import NumpyOptions, parse_numpy +from griffe._internal.docstrings.parsers import ( DocstringOptions, DocstringStyle, parse, parsers, ) -from griffelib._internal.docstrings.sphinx import SphinxOptions, parse_sphinx -from griffelib._internal.docstrings.utils import docstring_warning, parse_docstring_annotation -from griffelib._internal.encoders import JSONEncoder, json_decoder -from griffelib._internal.enumerations import ( +from griffe._internal.docstrings.sphinx import SphinxOptions, parse_sphinx +from griffe._internal.docstrings.utils import docstring_warning, parse_docstring_annotation +from griffe._internal.encoders import JSONEncoder, json_decoder +from griffe._internal.enumerations import ( BreakageKind, DocstringSectionKind, ExplanationStyle, @@ -260,7 +260,7 @@ Parser, TypeParameterKind, ) -from griffelib._internal.exceptions import ( +from griffe._internal.exceptions import ( AliasResolutionError, BuiltinModuleError, CyclicAliasError, @@ -275,7 +275,7 @@ UnhandledEditableModuleError, UnimportableModuleError, ) -from griffelib._internal.expressions import ( +from griffe._internal.expressions import ( Expr, ExprAttribute, ExprBinOp, @@ -319,29 +319,29 @@ safe_get_condition, safe_get_expression, ) -from griffelib._internal.extensions.base import ( +from griffe._internal.extensions.base import ( Extension, Extensions, LoadableExtensionType, builtin_extensions, load_extensions, ) -from griffelib._internal.extensions.dataclasses import DataclassesExtension -from griffelib._internal.extensions.unpack_typeddict import UnpackTypedDictExtension -from griffelib._internal.finder import ModuleFinder, NamePartsAndPathType, NamePartsType, NamespacePackage, Package -from griffelib._internal.git import GitInfo, KnownGitService -from griffelib._internal.importer import dynamic_import, sys_path -from griffelib._internal.loader import GriffeLoader, load, load_git, load_pypi -from griffelib._internal.logger import Logger, get_logger, logger, patch_loggers -from griffelib._internal.merger import merge_stubs -from griffelib._internal.mixins import ( +from griffe._internal.extensions.dataclasses import DataclassesExtension +from griffe._internal.extensions.unpack_typeddict import UnpackTypedDictExtension +from griffe._internal.finder import ModuleFinder, NamePartsAndPathType, NamePartsType, NamespacePackage, Package +from griffe._internal.git import GitInfo, KnownGitService +from griffe._internal.importer import dynamic_import, sys_path +from griffe._internal.loader import GriffeLoader, load, load_git, load_pypi +from griffe._internal.logger import Logger, get_logger, logger, patch_loggers +from griffe._internal.merger import merge_stubs +from griffe._internal.mixins import ( DelMembersMixin, GetMembersMixin, ObjectAliasMixin, SerializationMixin, SetMembersMixin, ) -from griffelib._internal.models import ( +from griffe._internal.models import ( Alias, Attribute, Class, @@ -356,8 +356,8 @@ TypeParameter, TypeParameters, ) -from griffelib._internal.stats import Stats -from griffelib._internal.tests import ( +from griffe._internal.stats import Stats +from griffe._internal.tests import ( TmpPackage, htree, module_vtree, @@ -371,8 +371,8 @@ ) # Regenerate this list with the following Python snippet: -# import griffelib -# names = sorted(n for n in dir(griffelib) if not n.startswith("_") and n not in ("annotations",)) +# import griffe +# names = sorted(n for n in dir(griffe) if not n.startswith("_") and n not in ("annotations",)) # print('__all__ = [\n "' + '",\n "'.join(names) + '",\n]') __all__ = [ "Alias", @@ -592,3 +592,23 @@ "visit", "vtree", ] + +__cli_all__ = [ + "DEFAULT_LOG_LEVEL", + "check", + "dump", + "get_parser", + "main", +] + +try: + from griffecli._internal.cli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main +except ImportError: + def __getattr__(attr: str) -> object: + if attr in __cli_all__: + import griffecli._internal.cli as griffecli_mod + return getattr(griffecli_mod, attr) + raise AttributeError(attr) + +else: + __all__.extend(__cli_all__) diff --git a/src/griffe/__main__.py b/packages/griffelib/src/griffe/__main__.py similarity index 61% rename from src/griffe/__main__.py rename to packages/griffelib/src/griffe/__main__.py index 30c64ab2b..8d31f600e 100644 --- a/src/griffe/__main__.py +++ b/packages/griffelib/src/griffe/__main__.py @@ -8,7 +8,13 @@ import sys -from griffecli import main +try: + from griffecli import main +except ModuleNotFoundError: + raise ImportError( + "`griffecli` is not installed. Install `griffecli` " + "to use `python -m griffe`." + ) if __name__ == "__main__": sys.exit(main(sys.argv[1:])) diff --git a/packages/griffelib/src/griffelib/_internal/__init__.py b/packages/griffelib/src/griffe/_internal/__init__.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/__init__.py rename to packages/griffelib/src/griffe/_internal/__init__.py diff --git a/packages/griffelib/src/griffelib/_internal/agents/__init__.py b/packages/griffelib/src/griffe/_internal/agents/__init__.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/agents/__init__.py rename to packages/griffelib/src/griffe/_internal/agents/__init__.py diff --git a/packages/griffelib/src/griffelib/_internal/agents/inspector.py b/packages/griffelib/src/griffe/_internal/agents/inspector.py similarity index 97% rename from packages/griffelib/src/griffelib/_internal/agents/inspector.py rename to packages/griffelib/src/griffe/_internal/agents/inspector.py index 4b4601495..1ff89bfe6 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/inspector.py +++ b/packages/griffelib/src/griffe/_internal/agents/inspector.py @@ -12,20 +12,14 @@ from inspect import signature as getsignature from typing import TYPE_CHECKING, Any -from griffelib._internal.agents.nodes.runtime import ObjectNode -from griffelib._internal.collections import LinesCollection, ModulesCollection -from griffelib._internal.enumerations import Kind, ParameterKind, TypeParameterKind -from griffelib._internal.expressions import ( - Expr, - ExprBinOp, - ExprSubscript, - ExprTuple, - safe_get_annotation, -) -from griffelib._internal.extensions.base import Extensions, load_extensions -from griffelib._internal.importer import dynamic_import -from griffelib._internal.logger import logger -from griffelib._internal.models import ( +from griffe._internal.agents.nodes.runtime import ObjectNode +from griffe._internal.collections import LinesCollection, ModulesCollection +from griffe._internal.enumerations import Kind, ParameterKind, TypeParameterKind +from griffe._internal.expressions import Expr, ExprBinOp, ExprSubscript, ExprTuple, safe_get_annotation +from griffe._internal.extensions.base import Extensions, load_extensions +from griffe._internal.importer import dynamic_import +from griffe._internal.logger import logger +from griffe._internal.models import ( Alias, Attribute, Class, @@ -43,8 +37,8 @@ from collections.abc import Sequence from pathlib import Path - from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffelib._internal.enumerations import Parser + from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffe._internal.enumerations import Parser _TYPING_MODULES: tuple[types.ModuleType, ...] try: diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/__init__.py b/packages/griffelib/src/griffe/_internal/agents/nodes/__init__.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/__init__.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/__init__.py diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/assignments.py b/packages/griffelib/src/griffe/_internal/agents/nodes/assignments.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/assignments.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/assignments.py diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/ast.py b/packages/griffelib/src/griffe/_internal/agents/nodes/ast.py similarity index 98% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/ast.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/ast.py index 778fd75ef..9cb261486 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/nodes/ast.py +++ b/packages/griffelib/src/griffe/_internal/agents/nodes/ast.py @@ -5,7 +5,7 @@ from ast import AST from typing import TYPE_CHECKING -from griffelib._internal.exceptions import LastNodeError +from griffe._internal.exceptions import LastNodeError if TYPE_CHECKING: from collections.abc import Iterator diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/docstrings.py b/packages/griffelib/src/griffe/_internal/agents/nodes/docstrings.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/docstrings.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/docstrings.py diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/exports.py b/packages/griffelib/src/griffe/_internal/agents/nodes/exports.py similarity index 91% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/exports.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/exports.py index 657c752e0..d726e9c03 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/nodes/exports.py +++ b/packages/griffelib/src/griffe/_internal/agents/nodes/exports.py @@ -6,13 +6,13 @@ from contextlib import suppress from typing import TYPE_CHECKING, Any, Callable -from griffelib._internal.agents.nodes.values import get_value -from griffelib._internal.enumerations import LogLevel -from griffelib._internal.expressions import ExprName -from griffelib._internal.logger import logger +from griffe._internal.agents.nodes.values import get_value +from griffe._internal.enumerations import LogLevel +from griffe._internal.expressions import ExprName +from griffe._internal.logger import logger if TYPE_CHECKING: - from griffelib._internal.models import Module + from griffe._internal.models import Module def _extract_attribute(node: ast.Attribute, parent: Module) -> list[str | ExprName]: diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/imports.py b/packages/griffelib/src/griffe/_internal/agents/nodes/imports.py similarity index 95% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/imports.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/imports.py index 25b5cf1b6..c194d07bc 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/nodes/imports.py +++ b/packages/griffelib/src/griffe/_internal/agents/nodes/imports.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: import ast - from griffelib._internal.models import Module + from griffe._internal.models import Module def relative_to_absolute(node: ast.ImportFrom, name: ast.alias, current_module: Module) -> str: diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/parameters.py b/packages/griffelib/src/griffe/_internal/agents/nodes/parameters.py similarity index 97% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/parameters.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/parameters.py index 349be63d1..b6b6f445d 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/nodes/parameters.py +++ b/packages/griffelib/src/griffe/_internal/agents/nodes/parameters.py @@ -6,7 +6,7 @@ from itertools import zip_longest from typing import TYPE_CHECKING, Optional, Union -from griffelib._internal.enumerations import ParameterKind +from griffe._internal.enumerations import ParameterKind if TYPE_CHECKING: from collections.abc import Iterable diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/runtime.py b/packages/griffelib/src/griffe/_internal/agents/nodes/runtime.py similarity index 99% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/runtime.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/runtime.py index 693a82a8f..b63d4f9c9 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/nodes/runtime.py +++ b/packages/griffelib/src/griffe/_internal/agents/nodes/runtime.py @@ -9,8 +9,8 @@ from types import GetSetDescriptorType, ModuleType from typing import TYPE_CHECKING, Any, ClassVar -from griffelib._internal.enumerations import ObjectKind -from griffelib._internal.logger import logger +from griffe._internal.enumerations import ObjectKind +from griffe._internal.logger import logger if TYPE_CHECKING: import types diff --git a/packages/griffelib/src/griffelib/_internal/agents/nodes/values.py b/packages/griffelib/src/griffe/_internal/agents/nodes/values.py similarity index 96% rename from packages/griffelib/src/griffelib/_internal/agents/nodes/values.py rename to packages/griffelib/src/griffe/_internal/agents/nodes/values.py index 89465b97d..63941f823 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/nodes/values.py +++ b/packages/griffelib/src/griffe/_internal/agents/nodes/values.py @@ -6,7 +6,7 @@ from ast import unparse from typing import TYPE_CHECKING -from griffelib._internal.logger import logger +from griffe._internal.logger import logger if TYPE_CHECKING: from pathlib import Path diff --git a/packages/griffelib/src/griffelib/_internal/agents/visitor.py b/packages/griffelib/src/griffe/_internal/agents/visitor.py similarity index 96% rename from packages/griffelib/src/griffelib/_internal/agents/visitor.py rename to packages/griffelib/src/griffe/_internal/agents/visitor.py index 2771f1483..7cad06dde 100644 --- a/packages/griffelib/src/griffelib/_internal/agents/visitor.py +++ b/packages/griffelib/src/griffe/_internal/agents/visitor.py @@ -8,24 +8,20 @@ from contextlib import suppress from typing import TYPE_CHECKING, Final -from griffelib._internal.agents.nodes.assignments import get_instance_names, get_names -from griffelib._internal.agents.nodes.ast import ( +from griffe._internal.agents.nodes.assignments import get_instance_names, get_names +from griffe._internal.agents.nodes.ast import ( ast_children, ast_kind, ast_next, ) -from griffelib._internal.agents.nodes.docstrings import get_docstring -from griffelib._internal.agents.nodes.exports import safe_get__all__ -from griffelib._internal.agents.nodes.imports import relative_to_absolute -from griffelib._internal.agents.nodes.parameters import get_parameters -from griffelib._internal.collections import LinesCollection, ModulesCollection -from griffelib._internal.enumerations import Kind, TypeParameterKind -from griffelib._internal.exceptions import ( - AliasResolutionError, - CyclicAliasError, - LastNodeError, -) -from griffelib._internal.expressions import ( +from griffe._internal.agents.nodes.docstrings import get_docstring +from griffe._internal.agents.nodes.exports import safe_get__all__ +from griffe._internal.agents.nodes.imports import relative_to_absolute +from griffe._internal.agents.nodes.parameters import get_parameters +from griffe._internal.collections import LinesCollection, ModulesCollection +from griffe._internal.enumerations import Kind, TypeParameterKind +from griffe._internal.exceptions import AliasResolutionError, CyclicAliasError, LastNodeError +from griffe._internal.expressions import ( Expr, ExprName, safe_get_annotation, @@ -34,8 +30,8 @@ safe_get_condition, safe_get_expression, ) -from griffelib._internal.extensions.base import Extensions, load_extensions -from griffelib._internal.models import ( +from griffe._internal.extensions.base import Extensions, load_extensions +from griffe._internal.models import ( Alias, Attribute, Class, @@ -53,8 +49,8 @@ if TYPE_CHECKING: from pathlib import Path - from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffelib._internal.enumerations import Parser + from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffe._internal.enumerations import Parser builtin_decorators = { diff --git a/packages/griffelib/src/griffelib/_internal/c3linear.py b/packages/griffelib/src/griffe/_internal/c3linear.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/c3linear.py rename to packages/griffelib/src/griffe/_internal/c3linear.py diff --git a/packages/griffelib/src/griffelib/_internal/collections.py b/packages/griffelib/src/griffe/_internal/collections.py similarity index 94% rename from packages/griffelib/src/griffelib/_internal/collections.py rename to packages/griffelib/src/griffe/_internal/collections.py index 9927855a2..787f57a73 100644 --- a/packages/griffelib/src/griffelib/_internal/collections.py +++ b/packages/griffelib/src/griffe/_internal/collections.py @@ -5,13 +5,13 @@ from typing import TYPE_CHECKING, Any -from griffelib._internal.mixins import DelMembersMixin, GetMembersMixin, SetMembersMixin +from griffe._internal.mixins import DelMembersMixin, GetMembersMixin, SetMembersMixin if TYPE_CHECKING: from collections.abc import ItemsView, KeysView, ValuesView from pathlib import Path - from griffelib._internal.models import Module + from griffe._internal.models import Module class LinesCollection: diff --git a/packages/griffelib/src/griffelib/_internal/debug.py b/packages/griffelib/src/griffe/_internal/debug.py similarity index 96% rename from packages/griffelib/src/griffelib/_internal/debug.py rename to packages/griffelib/src/griffe/_internal/debug.py index 7f8ea2698..5201db934 100644 --- a/packages/griffelib/src/griffelib/_internal/debug.py +++ b/packages/griffelib/src/griffe/_internal/debug.py @@ -1,7 +1,7 @@ # This module is here to help users report bugs. # It provides a function to print environment information, -# which is called from the public `griffelib.debug` module -# (when called with `python -m griffelib.debug`) +# which is called from the public `griffe.debug` module +# (when called with `python -m griffe.debug`) # or thanks to the `--debug-info` CLI flag. from __future__ import annotations diff --git a/packages/griffelib/src/griffelib/_internal/diff.py b/packages/griffelib/src/griffe/_internal/diff.py similarity index 97% rename from packages/griffelib/src/griffelib/_internal/diff.py rename to packages/griffelib/src/griffe/_internal/diff.py index 2c6589515..59e98f08f 100644 --- a/packages/griffelib/src/griffelib/_internal/diff.py +++ b/packages/griffelib/src/griffe/_internal/diff.py @@ -12,15 +12,15 @@ from pathlib import Path from typing import TYPE_CHECKING, Any -from griffelib._internal.enumerations import BreakageKind, ExplanationStyle, ParameterKind -from griffelib._internal.exceptions import AliasResolutionError -from griffelib._internal.git import _WORKTREE_PREFIX -from griffelib._internal.logger import logger +from griffe._internal.enumerations import BreakageKind, ExplanationStyle, ParameterKind +from griffe._internal.exceptions import AliasResolutionError +from griffe._internal.git import _WORKTREE_PREFIX +from griffe._internal.logger import logger if TYPE_CHECKING: from collections.abc import Iterable, Iterator - from griffelib._internal.models import Alias, Attribute, Class, Function, Object + from griffe._internal.models import Alias, Attribute, Class, Function, Object _POSITIONAL = frozenset((ParameterKind.positional_only, ParameterKind.positional_or_keyword)) _KEYWORD = frozenset((ParameterKind.keyword_only, ParameterKind.positional_or_keyword)) @@ -674,10 +674,10 @@ def find_breaking_changes( Breaking changes. Examples: - >>> import sys, griffelib - >>> new = griffelib.load("pkg") - >>> old = griffelib.load_git("pkg", "1.2.3") - >>> for breakage in griffelib.find_breaking_changes(old, new) + >>> import sys, griffe + >>> new = griffe.load("pkg") + >>> old = griffe.load_git("pkg", "1.2.3") + >>> for breakage in griffe.find_breaking_changes(old, new) ... print(breakage.explain(style=style), file=sys.stderr) """ yield from _member_incompatibilities(old_obj, new_obj) diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/__init__.py b/packages/griffelib/src/griffe/_internal/docstrings/__init__.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/docstrings/__init__.py rename to packages/griffelib/src/griffe/_internal/docstrings/__init__.py diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/auto.py b/packages/griffelib/src/griffe/_internal/docstrings/auto.py similarity index 92% rename from packages/griffelib/src/griffelib/_internal/docstrings/auto.py rename to packages/griffelib/src/griffe/_internal/docstrings/auto.py index 2de048df2..ea582f91d 100644 --- a/packages/griffelib/src/griffelib/_internal/docstrings/auto.py +++ b/packages/griffelib/src/griffe/_internal/docstrings/auto.py @@ -5,15 +5,15 @@ import re from typing import TYPE_CHECKING, Literal, TypedDict -from griffelib._internal.enumerations import Parser +from griffe._internal.enumerations import Parser if TYPE_CHECKING: - from griffelib._internal.docstrings.google import GoogleOptions - from griffelib._internal.docstrings.models import DocstringSection - from griffelib._internal.docstrings.numpy import NumpyOptions - from griffelib._internal.docstrings.parsers import DocstringStyle - from griffelib._internal.docstrings.sphinx import SphinxOptions - from griffelib._internal.models import Docstring + from griffe._internal.docstrings.google import GoogleOptions + from griffe._internal.docstrings.models import DocstringSection + from griffe._internal.docstrings.numpy import NumpyOptions + from griffe._internal.docstrings.parsers import DocstringStyle + from griffe._internal.docstrings.sphinx import SphinxOptions + from griffe._internal.models import Docstring # This is not our preferred order, but the safest order for proper detection @@ -143,7 +143,7 @@ def infer_docstring_style( Returns: The inferred parser, and optionally parsed sections (when method is 'max_sections'). """ - from griffelib._internal.docstrings.parsers import parsers # noqa: PLC0415 + from griffe._internal.docstrings.parsers import parsers # noqa: PLC0415 per_style_options = per_style_options or {} @@ -208,7 +208,7 @@ def parse_auto( Returns: A list of docstring sections. """ - from griffelib._internal.docstrings.parsers import parse # noqa: PLC0415 + from griffe._internal.docstrings.parsers import parse # noqa: PLC0415 per_style_options = per_style_options or {} diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/google.py b/packages/griffelib/src/griffe/_internal/docstrings/google.py similarity index 99% rename from packages/griffelib/src/griffelib/_internal/docstrings/google.py rename to packages/griffelib/src/griffe/_internal/docstrings/google.py index 5924c892c..42dd73b54 100644 --- a/packages/griffelib/src/griffelib/_internal/docstrings/google.py +++ b/packages/griffelib/src/griffe/_internal/docstrings/google.py @@ -6,7 +6,7 @@ from contextlib import suppress from typing import TYPE_CHECKING, TypedDict -from griffelib._internal.docstrings.models import ( +from griffe._internal.docstrings.models import ( DocstringAttribute, DocstringClass, DocstringFunction, @@ -37,15 +37,15 @@ DocstringWarn, DocstringYield, ) -from griffelib._internal.docstrings.utils import docstring_warning, parse_docstring_annotation -from griffelib._internal.enumerations import DocstringSectionKind, LogLevel +from griffe._internal.docstrings.utils import docstring_warning, parse_docstring_annotation +from griffe._internal.enumerations import DocstringSectionKind, LogLevel if TYPE_CHECKING: from re import Pattern from typing import Any, Literal - from griffelib._internal.expressions import Expr - from griffelib._internal.models import Docstring + from griffe._internal.expressions import Expr + from griffe._internal.models import Docstring _section_kind = { diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/models.py b/packages/griffelib/src/griffe/_internal/docstrings/models.py similarity index 98% rename from packages/griffelib/src/griffelib/_internal/docstrings/models.py rename to packages/griffelib/src/griffe/_internal/docstrings/models.py index ce444eb80..545ea78d1 100644 --- a/packages/griffelib/src/griffelib/_internal/docstrings/models.py +++ b/packages/griffelib/src/griffe/_internal/docstrings/models.py @@ -4,14 +4,14 @@ from typing import TYPE_CHECKING -from griffelib._internal.enumerations import DocstringSectionKind -from griffelib._internal.expressions import ExprTuple +from griffe._internal.enumerations import DocstringSectionKind +from griffe._internal.expressions import ExprTuple if TYPE_CHECKING: from collections.abc import Sequence from typing import Any, Literal - from griffelib._internal.expressions import Expr + from griffe._internal.expressions import Expr # Elements ----------------------------------------------- diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/numpy.py b/packages/griffelib/src/griffe/_internal/docstrings/numpy.py similarity index 98% rename from packages/griffelib/src/griffelib/_internal/docstrings/numpy.py rename to packages/griffelib/src/griffe/_internal/docstrings/numpy.py index 33550e502..080b7f63e 100644 --- a/packages/griffelib/src/griffelib/_internal/docstrings/numpy.py +++ b/packages/griffelib/src/griffe/_internal/docstrings/numpy.py @@ -24,7 +24,7 @@ from textwrap import dedent from typing import TYPE_CHECKING, TypedDict -from griffelib._internal.docstrings.models import ( +from griffe._internal.docstrings.models import ( DocstringAttribute, DocstringClass, DocstringFunction, @@ -56,16 +56,16 @@ DocstringWarn, DocstringYield, ) -from griffelib._internal.docstrings.utils import docstring_warning, parse_docstring_annotation -from griffelib._internal.enumerations import DocstringSectionKind, LogLevel -from griffelib._internal.expressions import ExprName +from griffe._internal.docstrings.utils import docstring_warning, parse_docstring_annotation +from griffe._internal.enumerations import DocstringSectionKind, LogLevel +from griffe._internal.expressions import ExprName if TYPE_CHECKING: from re import Pattern from typing import Any, Literal - from griffelib._internal.expressions import Expr - from griffelib._internal.models import Docstring + from griffe._internal.expressions import Expr + from griffe._internal.models import Docstring _section_kind = { diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/parsers.py b/packages/griffelib/src/griffe/_internal/docstrings/parsers.py similarity index 72% rename from packages/griffelib/src/griffelib/_internal/docstrings/parsers.py rename to packages/griffelib/src/griffe/_internal/docstrings/parsers.py index f24ff1f7d..bb91f600a 100644 --- a/packages/griffelib/src/griffelib/_internal/docstrings/parsers.py +++ b/packages/griffelib/src/griffe/_internal/docstrings/parsers.py @@ -5,15 +5,15 @@ from typing import TYPE_CHECKING, Any, Callable, Literal, Union -from griffelib._internal.docstrings.auto import AutoOptions, parse_auto -from griffelib._internal.docstrings.google import GoogleOptions, parse_google -from griffelib._internal.docstrings.models import DocstringSection, DocstringSectionText -from griffelib._internal.docstrings.numpy import NumpyOptions, parse_numpy -from griffelib._internal.docstrings.sphinx import SphinxOptions, parse_sphinx -from griffelib._internal.enumerations import Parser +from griffe._internal.docstrings.auto import AutoOptions, parse_auto +from griffe._internal.docstrings.google import GoogleOptions, parse_google +from griffe._internal.docstrings.models import DocstringSection, DocstringSectionText +from griffe._internal.docstrings.numpy import NumpyOptions, parse_numpy +from griffe._internal.docstrings.sphinx import SphinxOptions, parse_sphinx +from griffe._internal.enumerations import Parser if TYPE_CHECKING: - from griffelib._internal.models import Docstring + from griffe._internal.models import Docstring DocstringStyle = Literal["google", "numpy", "sphinx", "auto"] diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/sphinx.py b/packages/griffelib/src/griffe/_internal/docstrings/sphinx.py similarity index 98% rename from packages/griffelib/src/griffelib/_internal/docstrings/sphinx.py rename to packages/griffelib/src/griffe/_internal/docstrings/sphinx.py index f11fa5e7e..743aa42f2 100644 --- a/packages/griffelib/src/griffelib/_internal/docstrings/sphinx.py +++ b/packages/griffelib/src/griffe/_internal/docstrings/sphinx.py @@ -11,7 +11,7 @@ from inspect import cleandoc from typing import TYPE_CHECKING, Any, Callable, TypedDict -from griffelib._internal.docstrings.models import ( +from griffe._internal.docstrings.models import ( DocstringAttribute, DocstringParameter, DocstringRaise, @@ -23,11 +23,11 @@ DocstringSectionReturns, DocstringSectionText, ) -from griffelib._internal.docstrings.utils import docstring_warning, parse_docstring_annotation +from griffe._internal.docstrings.utils import docstring_warning, parse_docstring_annotation if TYPE_CHECKING: - from griffelib._internal.expressions import Expr - from griffelib._internal.models import Docstring + from griffe._internal.expressions import Expr + from griffe._internal.models import Docstring # TODO: Examples: from the documentation, we're not sure there is a standard format for examples diff --git a/packages/griffelib/src/griffelib/_internal/docstrings/utils.py b/packages/griffelib/src/griffe/_internal/docstrings/utils.py similarity index 88% rename from packages/griffelib/src/griffelib/_internal/docstrings/utils.py rename to packages/griffelib/src/griffe/_internal/docstrings/utils.py index 5d2423cf7..4c67069b0 100644 --- a/packages/griffelib/src/griffelib/_internal/docstrings/utils.py +++ b/packages/griffelib/src/griffe/_internal/docstrings/utils.py @@ -6,14 +6,14 @@ from contextlib import suppress from typing import TYPE_CHECKING -from griffelib._internal.enumerations import LogLevel -from griffelib._internal.exceptions import BuiltinModuleError -from griffelib._internal.expressions import safe_get_annotation -from griffelib._internal.logger import logger +from griffe._internal.enumerations import LogLevel +from griffe._internal.exceptions import BuiltinModuleError +from griffe._internal.expressions import safe_get_annotation +from griffe._internal.logger import logger if TYPE_CHECKING: - from griffelib._internal.expressions import Expr - from griffelib._internal.models import Docstring + from griffe._internal.expressions import Expr + from griffe._internal.models import Docstring def docstring_warning( diff --git a/packages/griffelib/src/griffelib/_internal/encoders.py b/packages/griffelib/src/griffe/_internal/encoders.py similarity index 97% rename from packages/griffelib/src/griffelib/_internal/encoders.py rename to packages/griffelib/src/griffe/_internal/encoders.py index 84f48fc93..3f148dff4 100644 --- a/packages/griffelib/src/griffelib/_internal/encoders.py +++ b/packages/griffelib/src/griffe/_internal/encoders.py @@ -7,10 +7,10 @@ from pathlib import Path, PosixPath, WindowsPath from typing import Any, Callable -from griffelib._internal import expressions -from griffelib._internal.enumerations import Kind, ParameterKind, TypeParameterKind -from griffelib._internal.git import GitInfo -from griffelib._internal.models import ( +from griffe._internal import expressions +from griffe._internal.enumerations import Kind, ParameterKind, TypeParameterKind +from griffe._internal.git import GitInfo +from griffe._internal.models import ( Alias, Attribute, Class, @@ -41,11 +41,11 @@ class JSONEncoder(json.JSONEncoder): the [`json.dump`][] or [`json.dumps`][] methods. Examples: - >>> from griffelib import JSONEncoder + >>> from griffe import JSONEncoder >>> JSONEncoder(full=True).encode(..., **kwargs) >>> import json - >>> from griffelib import JSONEncoder + >>> from griffe import JSONEncoder >>> json.dumps(..., cls=JSONEncoder, full=True, **kwargs) """ @@ -342,7 +342,7 @@ def json_decoder( Examples: >>> import json - >>> from griffelib import json_decoder + >>> from griffe import json_decoder >>> json.loads(..., object_hook=json_decoder) Parameters: diff --git a/packages/griffelib/src/griffelib/_internal/enumerations.py b/packages/griffelib/src/griffe/_internal/enumerations.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/enumerations.py rename to packages/griffelib/src/griffe/_internal/enumerations.py diff --git a/packages/griffelib/src/griffelib/_internal/exceptions.py b/packages/griffelib/src/griffe/_internal/exceptions.py similarity index 98% rename from packages/griffelib/src/griffelib/_internal/exceptions.py rename to packages/griffelib/src/griffe/_internal/exceptions.py index 3b864f7ad..4d104aa8e 100644 --- a/packages/griffelib/src/griffelib/_internal/exceptions.py +++ b/packages/griffelib/src/griffe/_internal/exceptions.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from griffelib._internal.models import Alias + from griffe._internal.models import Alias class GriffeError(Exception): diff --git a/packages/griffelib/src/griffelib/_internal/expressions.py b/packages/griffelib/src/griffe/_internal/expressions.py similarity index 99% rename from packages/griffelib/src/griffelib/_internal/expressions.py rename to packages/griffelib/src/griffe/_internal/expressions.py index c9df6bfe7..702bc56aa 100644 --- a/packages/griffelib/src/griffelib/_internal/expressions.py +++ b/packages/griffelib/src/griffe/_internal/expressions.py @@ -13,16 +13,16 @@ from functools import partial from typing import TYPE_CHECKING, Any, Protocol -from griffelib._internal.agents.nodes.parameters import get_parameters -from griffelib._internal.enumerations import LogLevel, ParameterKind -from griffelib._internal.exceptions import NameResolutionError -from griffelib._internal.logger import logger +from griffe._internal.agents.nodes.parameters import get_parameters +from griffe._internal.enumerations import LogLevel, ParameterKind +from griffe._internal.exceptions import NameResolutionError +from griffe._internal.logger import logger if TYPE_CHECKING: from collections.abc import Iterable, Iterator, Sequence from pathlib import Path - from griffelib._internal.models import Class, Function, Module + from griffe._internal.models import Class, Function, Module class _OperatorPrecedence(IntEnum): @@ -227,7 +227,7 @@ def canonical_path(self) -> str: @property def canonical_name(self) -> str: """Name of the expressed name/attribute/parameter.""" - # We must handle things like `griffelib.Visitor` and `griffelib.Visitor(code)`. + # We must handle things like `griffe.Visitor` and `griffe.Visitor(code)`. return self.canonical_path.rsplit(".", 1)[-1].split("(", 1)[-1].removesuffix(")") @property diff --git a/packages/griffelib/src/griffelib/_internal/extensions/__init__.py b/packages/griffelib/src/griffe/_internal/extensions/__init__.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/extensions/__init__.py rename to packages/griffelib/src/griffe/_internal/extensions/__init__.py diff --git a/packages/griffelib/src/griffelib/_internal/extensions/base.py b/packages/griffelib/src/griffe/_internal/extensions/base.py similarity index 96% rename from packages/griffelib/src/griffelib/_internal/extensions/base.py rename to packages/griffelib/src/griffe/_internal/extensions/base.py index c51893ee8..8013bf806 100644 --- a/packages/griffelib/src/griffelib/_internal/extensions/base.py +++ b/packages/griffelib/src/griffe/_internal/extensions/base.py @@ -10,19 +10,19 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Union -from griffelib._internal.agents.nodes.ast import ast_children, ast_kind -from griffelib._internal.exceptions import ExtensionNotLoadedError -from griffelib._internal.importer import dynamic_import +from griffe._internal.agents.nodes.ast import ast_children, ast_kind +from griffe._internal.exceptions import ExtensionNotLoadedError +from griffe._internal.importer import dynamic_import if TYPE_CHECKING: import ast from types import ModuleType - from griffelib._internal.agents.inspector import Inspector - from griffelib._internal.agents.nodes.runtime import ObjectNode - from griffelib._internal.agents.visitor import Visitor - from griffelib._internal.loader import GriffeLoader - from griffelib._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias + from griffe._internal.agents.inspector import Inspector + from griffe._internal.agents.nodes.runtime import ObjectNode + from griffe._internal.agents.visitor import Visitor + from griffe._internal.loader import GriffeLoader + from griffe._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias class Extension: @@ -543,7 +543,7 @@ def _load_extension( # If the import path corresponds to a built-in extension, expand it. if import_path in builtin_extensions: - import_path = f"griffelib._internal.extensions.{import_path}" + import_path = f"griffe._internal.extensions.{import_path}" # If the import path is a path to an existing file, load it. elif os.path.exists(import_path): # noqa: PTH110 try: @@ -603,7 +603,7 @@ def load_extensions(*exts: LoadableExtensionType) -> Extensions: # TODO: Deprecate and remove at some point? # Always add our built-in dataclasses extension. - from griffelib._internal.extensions.dataclasses import DataclassesExtension # noqa: PLC0415 + from griffe._internal.extensions.dataclasses import DataclassesExtension # noqa: PLC0415 for ext in extensions._extensions: if type(ext) is DataclassesExtension: diff --git a/packages/griffelib/src/griffelib/_internal/extensions/dataclasses.py b/packages/griffelib/src/griffe/_internal/extensions/dataclasses.py similarity index 96% rename from packages/griffelib/src/griffelib/_internal/extensions/dataclasses.py rename to packages/griffelib/src/griffe/_internal/extensions/dataclasses.py index 100b858ad..5e6fa7b01 100644 --- a/packages/griffelib/src/griffelib/_internal/extensions/dataclasses.py +++ b/packages/griffelib/src/griffe/_internal/extensions/dataclasses.py @@ -10,16 +10,16 @@ from functools import cache from typing import Any, cast -from griffelib._internal.enumerations import ParameterKind -from griffelib._internal.expressions import ( +from griffe._internal.enumerations import ParameterKind +from griffe._internal.expressions import ( Expr, ExprAttribute, ExprCall, ExprDict, ) -from griffelib._internal.extensions.base import Extension -from griffelib._internal.logger import logger -from griffelib._internal.models import Attribute, Class, Decorator, Function, Module, Parameter, Parameters +from griffe._internal.extensions.base import Extension +from griffe._internal.logger import logger +from griffe._internal.models import Attribute, Class, Decorator, Function, Module, Parameter, Parameters def _dataclass_decorator(decorators: list[Decorator]) -> Expr | None: diff --git a/packages/griffelib/src/griffelib/_internal/extensions/unpack_typeddict.py b/packages/griffelib/src/griffe/_internal/extensions/unpack_typeddict.py similarity index 96% rename from packages/griffelib/src/griffelib/_internal/extensions/unpack_typeddict.py rename to packages/griffelib/src/griffe/_internal/extensions/unpack_typeddict.py index d228c9d3c..162cbbf69 100644 --- a/packages/griffelib/src/griffelib/_internal/extensions/unpack_typeddict.py +++ b/packages/griffelib/src/griffe/_internal/extensions/unpack_typeddict.py @@ -7,14 +7,14 @@ from itertools import chain from typing import TYPE_CHECKING, Any, TypedDict -from griffelib._internal.docstrings.models import ( +from griffe._internal.docstrings.models import ( DocstringParameter, DocstringSectionParameters, ) -from griffelib._internal.enumerations import DocstringSectionKind, ParameterKind -from griffelib._internal.expressions import Expr, ExprSubscript -from griffelib._internal.extensions.base import Extension -from griffelib._internal.models import Class, Docstring, Function, Parameter, Parameters +from griffe._internal.enumerations import DocstringSectionKind, ParameterKind +from griffe._internal.expressions import Expr, ExprSubscript +from griffe._internal.extensions.base import Extension +from griffe._internal.models import Class, Docstring, Function, Parameter, Parameters if TYPE_CHECKING: from collections.abc import Iterable, Iterator diff --git a/packages/griffelib/src/griffelib/_internal/finder.py b/packages/griffelib/src/griffe/_internal/finder.py similarity index 95% rename from packages/griffelib/src/griffelib/_internal/finder.py rename to packages/griffelib/src/griffe/_internal/finder.py index 9177a91b3..3960e1470 100644 --- a/packages/griffelib/src/griffelib/_internal/finder.py +++ b/packages/griffelib/src/griffe/_internal/finder.py @@ -5,12 +5,12 @@ # # ```pycon # >>> from importlib.util import _find_spec -# >>> _find_spec("griffelib.agents", _find_spec("griffelib", None).submodule_search_locations) +# >>> _find_spec("griffe.agents", _find_spec("griffe", None).submodule_search_locations) # ModuleSpec( -# name='griffelib.agents', +# name='griffe.agents', # loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fa5f34e8110>, -# origin='/media/data/dev/griffelib/packages/griffelib/src/griffelib/agents/__init__.py', -# submodule_search_locations=['/media/data/dev/griffelib/packages/griffelib/src/griffelib/agents'], +# origin='/media/data/dev/griffelib/packages/griffe/src/griffe/agents/__init__.py', +# submodule_search_locations=['/media/data/dev/griffelib/packages/griffe/src/griffe/agents'], # ) # ``` @@ -27,14 +27,14 @@ from pathlib import Path from typing import TYPE_CHECKING, ClassVar -from griffelib._internal.exceptions import UnhandledEditableModuleError -from griffelib._internal.logger import logger +from griffe._internal.exceptions import UnhandledEditableModuleError +from griffe._internal.logger import logger if TYPE_CHECKING: from collections.abc import Iterator, Sequence from re import Pattern - from griffelib._internal.models import Module + from griffe._internal.models import Module _editable_editables_patterns = [re.compile(pat) for pat in (r"^__editables_\w+\.py$", r"^_editable_impl_\w+\.py$")] @@ -470,9 +470,9 @@ def _handle_pth_file(path: Path) -> list[_SP]: def _handle_editable_module(path: Path) -> list[_SP]: if _match_pattern(path.name, (*_editable_editables_patterns, *_editable_scikit_build_core_patterns)): # Support for how 'editables' write these files: - # example line: `F.map_module('griffelib', '/media/data/dev/griffelib/packages/griffelib/src/griffelib/__init__.py')`. + # example line: `F.map_module('griffe', '/media/data/dev/griffelib/packages/griffe/src/griffe/__init__.py')`. # And how 'scikit-build-core' writes these files: - # example line: `install({'griffelib': '/media/data/dev/griffelib/packages/griffelib/src/griffelib/__init__.py'}, {'cmake_example': ...}, None, False, True)`. + # example line: `install({'griffe': '/media/data/dev/griffelib/packages/griffe/src/griffe/__init__.py'}, {'cmake_example': ...}, None, False, True)`. try: editable_lines = path.read_text(encoding="utf-8-sig").strip().splitlines(keepends=False) except FileNotFoundError as error: @@ -483,7 +483,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: return [_SP(new_path)] if _match_pattern(path.name, _editable_setuptools_patterns): # Support for how 'setuptools' writes these files: - # example line: `MAPPING = {'griffelib': '/media/data/dev/griffelib/packages/griffelib/src/griffelib', 'briffe': '/media/data/dev/griffelib/src/briffe'}`. + # example line: `MAPPING = {'griffe': '/media/data/dev/griffelib/packages/griffe/src/griffe', 'briffe': '/media/data/dev/griffelib/src/briffe'}`. # with annotation: `MAPPING: dict[str, str] = {...}`. parsed_module = ast.parse(path.read_text(encoding="utf8")) for node in parsed_module.body: diff --git a/packages/griffelib/src/griffelib/_internal/git.py b/packages/griffelib/src/griffe/_internal/git.py similarity index 97% rename from packages/griffelib/src/griffelib/_internal/git.py rename to packages/griffelib/src/griffe/_internal/git.py index e8cca7ac3..47642c009 100644 --- a/packages/griffelib/src/griffelib/_internal/git.py +++ b/packages/griffelib/src/griffe/_internal/git.py @@ -16,15 +16,15 @@ from typing import TYPE_CHECKING, Literal from urllib.parse import urlsplit, urlunsplit -from griffelib._internal.exceptions import BuiltinModuleError, GitError +from griffe._internal.exceptions import BuiltinModuleError, GitError if TYPE_CHECKING: from collections.abc import Iterator - from griffelib._internal.models import Module + from griffe._internal.models import Module -_WORKTREE_PREFIX = "griffelib-worktree-" +_WORKTREE_PREFIX = "griffe-worktree-" def _normalize(value: str) -> str: @@ -120,7 +120,7 @@ def _tmp_worktree(repo: str | Path = ".", ref: str = "HEAD") -> Iterator[Path]: normref = _normalize(ref) # Branch names can contain slashes. with TemporaryDirectory(prefix=f"{_WORKTREE_PREFIX}{repo_name}-{normref}-") as tmp_dir: location = os.path.join(tmp_dir, normref) # noqa: PTH118 - tmp_branch = f"griffelib-{normref}" # Temporary branch name must not already exist. + tmp_branch = f"griffe-{normref}" # Temporary branch name must not already exist. try: _git("-C", str(repo), "worktree", "add", "-b", tmp_branch, location, ref) except GitError as error: diff --git a/packages/griffelib/src/griffelib/_internal/importer.py b/packages/griffelib/src/griffe/_internal/importer.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/importer.py rename to packages/griffelib/src/griffe/_internal/importer.py diff --git a/packages/griffelib/src/griffelib/_internal/loader.py b/packages/griffelib/src/griffe/_internal/loader.py similarity index 97% rename from packages/griffelib/src/griffelib/_internal/loader.py rename to packages/griffelib/src/griffe/_internal/loader.py index db723032d..b2a2d45b5 100644 --- a/packages/griffelib/src/griffelib/_internal/loader.py +++ b/packages/griffelib/src/griffe/_internal/loader.py @@ -14,31 +14,31 @@ from pathlib import Path from typing import TYPE_CHECKING, ClassVar, cast -from griffelib._internal.agents.inspector import inspect -from griffelib._internal.agents.visitor import visit -from griffelib._internal.collections import LinesCollection, ModulesCollection -from griffelib._internal.enumerations import Kind -from griffelib._internal.exceptions import ( +from griffe._internal.agents.inspector import inspect +from griffe._internal.agents.visitor import visit +from griffe._internal.collections import LinesCollection, ModulesCollection +from griffe._internal.enumerations import Kind +from griffe._internal.exceptions import ( AliasResolutionError, CyclicAliasError, LoadingError, UnimportableModuleError, ) -from griffelib._internal.expressions import ExprName -from griffelib._internal.extensions.base import Extensions, load_extensions -from griffelib._internal.finder import ModuleFinder, NamespacePackage, Package -from griffelib._internal.git import GitInfo, _tmp_worktree -from griffelib._internal.importer import dynamic_import -from griffelib._internal.logger import logger -from griffelib._internal.merger import merge_stubs -from griffelib._internal.models import Alias, Module, Object -from griffelib._internal.stats import Stats +from griffe._internal.expressions import ExprName +from griffe._internal.extensions.base import Extensions, load_extensions +from griffe._internal.finder import ModuleFinder, NamespacePackage, Package +from griffe._internal.git import GitInfo, _tmp_worktree +from griffe._internal.importer import dynamic_import +from griffe._internal.logger import logger +from griffe._internal.merger import merge_stubs +from griffe._internal.models import Alias, Module, Object +from griffe._internal.stats import Stats if TYPE_CHECKING: from collections.abc import Sequence - from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffelib._internal.enumerations import Parser + from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffe._internal.enumerations import Parser class GriffeLoader: @@ -119,8 +119,8 @@ def load( with regular methods and properties (`parent`, `members`, etc.). Examples: - >>> loader.load("griffelib.Module") - Alias("Module", "griffelib._internal.models.Module") + >>> loader.load("griffe.Module") + Alias("Module", "griffe._internal.models.Module") Parameters: objspec: The Python path of an object, or file path to a module. @@ -645,7 +645,7 @@ def _load_submodule(self, module: Module, subparts: tuple[str, ...], subpath: Pa logger.debug( "Submodule '%s' is shadowing the member at the same path. " "We recommend renaming the member or the submodule (for example prefixing it with `_`), " - "see https://mkdocstrings.github.io/griffelib/best_practices/#avoid-member-submodule-name-shadowing.", + "see https://mkdocstrings.github.io/griffe/best_practices/#avoid-member-submodule-name-shadowing.", submodule.path, ) parent_module.set_member(submodule_name, submodule) @@ -785,15 +785,15 @@ def load( Example: ```python - import griffelib + import griffe - module = griffelib.load(...) + module = griffe.load(...) ``` This is a shortcut for: ```python - from griffelib import GriffeLoader + from griffe import GriffeLoader loader = GriffeLoader(...) module = loader.load(...) @@ -873,13 +873,13 @@ def load_git( This function will create a temporary [git worktree](https://git-scm.com/docs/git-worktree) at the requested reference - before loading `module` with [`griffelib.load`][griffe.load]. + before loading `module` with [`griffe.load`][griffe.load]. This function requires that the `git` executable is installed. Examples: ```python - from griffelib import load_git + from griffe import load_git old_api = load_git("my_module", ref="v0.1.0", repo="path/to/repo") ``` @@ -983,7 +983,7 @@ def load_pypi( import platformdirs # noqa: PLC0415 - pypi_cache_dir = Path(platformdirs.user_cache_dir("griffelib")) + pypi_cache_dir = Path(platformdirs.user_cache_dir("griffe")) install_dir = pypi_cache_dir / f"{distribution}{version_spec}" if install_dir.exists(): logger.debug("Using cached %s%s", distribution, version_spec) diff --git a/packages/griffelib/src/griffelib/_internal/logger.py b/packages/griffelib/src/griffe/_internal/logger.py similarity index 100% rename from packages/griffelib/src/griffelib/_internal/logger.py rename to packages/griffelib/src/griffe/_internal/logger.py diff --git a/packages/griffelib/src/griffelib/_internal/merger.py b/packages/griffelib/src/griffe/_internal/merger.py similarity index 95% rename from packages/griffelib/src/griffelib/_internal/merger.py rename to packages/griffelib/src/griffe/_internal/merger.py index d95eaa1d2..798ebf08e 100644 --- a/packages/griffelib/src/griffelib/_internal/merger.py +++ b/packages/griffelib/src/griffe/_internal/merger.py @@ -5,11 +5,11 @@ from contextlib import suppress from typing import TYPE_CHECKING -from griffelib._internal.exceptions import AliasResolutionError, CyclicAliasError -from griffelib._internal.logger import logger +from griffe._internal.exceptions import AliasResolutionError, CyclicAliasError +from griffe._internal.logger import logger if TYPE_CHECKING: - from griffelib._internal.models import Attribute, Class, Function, Module, Object, TypeAlias + from griffe._internal.models import Attribute, Class, Function, Module, Object, TypeAlias def _merge_module_stubs(module: Module, stubs: Module) -> None: diff --git a/packages/griffelib/src/griffelib/_internal/mixins.py b/packages/griffelib/src/griffe/_internal/mixins.py similarity index 97% rename from packages/griffelib/src/griffelib/_internal/mixins.py rename to packages/griffelib/src/griffe/_internal/mixins.py index b7455674c..05d69414c 100644 --- a/packages/griffelib/src/griffelib/_internal/mixins.py +++ b/packages/griffelib/src/griffe/_internal/mixins.py @@ -7,14 +7,14 @@ from contextlib import suppress from typing import TYPE_CHECKING, Any, TypeVar -from griffelib._internal.enumerations import Kind -from griffelib._internal.exceptions import AliasResolutionError, BuiltinModuleError, CyclicAliasError -from griffelib._internal.merger import merge_stubs +from griffe._internal.enumerations import Kind +from griffe._internal.exceptions import AliasResolutionError, BuiltinModuleError, CyclicAliasError +from griffe._internal.merger import merge_stubs if TYPE_CHECKING: from collections.abc import Sequence - from griffelib._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias + from griffe._internal.models import Alias, Attribute, Class, Function, Module, Object, TypeAlias _ObjType = TypeVar("_ObjType") @@ -222,7 +222,7 @@ def as_json(self, *, full: bool = False, **kwargs: Any) -> str: Returns: A JSON string. """ - from griffelib._internal.encoders import JSONEncoder # Avoid circular import. # noqa: PLC0415 + from griffe._internal.encoders import JSONEncoder # Avoid circular import. # noqa: PLC0415 return json.dumps(self, cls=JSONEncoder, full=full, **kwargs) @@ -241,7 +241,7 @@ def from_json(cls: type[_ObjType], json_string: str, **kwargs: Any) -> _ObjType: TypeError: When the json_string does not represent and object of the class from which this classmethod has been called. """ - from griffelib._internal.encoders import json_decoder # Avoid circular import. # noqa: PLC0415 + from griffe._internal.encoders import json_decoder # Avoid circular import. # noqa: PLC0415 kwargs.setdefault("object_hook", json_decoder) obj = json.loads(json_string, **kwargs) diff --git a/packages/griffelib/src/griffelib/_internal/models.py b/packages/griffelib/src/griffe/_internal/models.py similarity index 98% rename from packages/griffelib/src/griffelib/_internal/models.py rename to packages/griffelib/src/griffe/_internal/models.py index cc1ac0e51..9cc60e17f 100644 --- a/packages/griffelib/src/griffelib/_internal/models.py +++ b/packages/griffelib/src/griffe/_internal/models.py @@ -11,35 +11,21 @@ from textwrap import dedent from typing import TYPE_CHECKING, Any, Callable, Literal, Union, cast -from griffelib._internal.c3linear import c3linear_merge -from griffelib._internal.docstrings.parsers import ( - DocstringOptions, - DocstringStyle, - parse, -) -from griffelib._internal.enumerations import ( - Kind, - ParameterKind, - Parser, - TypeParameterKind, -) -from griffelib._internal.exceptions import ( - AliasResolutionError, - BuiltinModuleError, - CyclicAliasError, - NameResolutionError, -) -from griffelib._internal.expressions import ExprCall, ExprName, ExprTuple -from griffelib._internal.logger import logger -from griffelib._internal.mixins import ObjectAliasMixin +from griffe._internal.c3linear import c3linear_merge +from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle, parse +from griffe._internal.enumerations import Kind, ParameterKind, Parser, TypeParameterKind +from griffe._internal.exceptions import AliasResolutionError, BuiltinModuleError, CyclicAliasError, NameResolutionError +from griffe._internal.expressions import ExprCall, ExprName, ExprTuple +from griffe._internal.logger import logger +from griffe._internal.mixins import ObjectAliasMixin if TYPE_CHECKING: from collections.abc import Sequence - from griffelib._internal.collections import LinesCollection, ModulesCollection - from griffelib._internal.docstrings.models import DocstringSection - from griffelib._internal.expressions import Expr - from griffelib._internal.git import GitInfo + from griffe._internal.collections import LinesCollection, ModulesCollection + from griffe._internal.docstrings.models import DocstringSection + from griffe._internal.expressions import Expr + from griffe._internal.git import GitInfo from functools import cached_property @@ -1003,8 +989,8 @@ def module(self) -> Module: See also: [`package`][griffe.Object.package]. Examples: - >>> import griffelib - >>> markdown = griffelib.load("markdown") + >>> import griffe + >>> markdown = griffe.load("markdown") >>> markdown["core.Markdown.references"].module Module(PosixPath('~/project/.venv/lib/python3.11/site-packages/markdown/core.py')) >>> # The `module` of a module is itself. @@ -1027,8 +1013,8 @@ def package(self) -> Module: See also: [`module`][griffe.Object.module]. Examples: - >>> import griffelib - >>> markdown = griffelib.load("markdown") + >>> import griffe + >>> markdown = griffe.load("markdown") >>> markdown["core.Markdown.references"].package Module(PosixPath('~/project/.venv/lib/python3.11/site-packages/markdown/__init__.py')) """ @@ -1045,8 +1031,8 @@ def filepath(self) -> Path | list[Path]: [`relative_package_filepath`][griffe.Object.relative_package_filepath]. Examples: - >>> import griffelib - >>> markdown = griffelib.load("markdown") + >>> import griffe + >>> markdown = griffe.load("markdown") >>> markdown.filepath PosixPath('~/project/.venv/lib/python3.11/site-packages/markdown/__init__.py') """ @@ -1128,8 +1114,8 @@ def path(self) -> str: See also: [`canonical_path`][griffe.Object.canonical_path]. Examples: - >>> import griffelib - >>> markdown = griffelib.load("markdown") + >>> import griffe + >>> markdown = griffe.load("markdown") >>> markdown["core.Markdown.references"].path 'markdown.core.Markdown.references' """ @@ -2251,9 +2237,9 @@ def __init__(self, *args: Any, filepath: Path | list[Path] | None = None, **kwar """Initialize the module. Parameters: - *args: See [`griffelib.Object`][]. + *args: See [`griffe.Object`][]. filepath: The module file path (directory for namespace [sub]packages, none for builtin modules). - **kwargs: See [`griffelib.Object`][]. + **kwargs: See [`griffe.Object`][]. """ super().__init__(*args, **kwargs) self._filepath: Path | list[Path] | None = filepath @@ -2381,11 +2367,11 @@ def __init__( """Initialize the class. Parameters: - *args: See [`griffelib.Object`][]. + *args: See [`griffe.Object`][]. bases: The list of base classes, if any. decorators: The class decorators, if any. keywords: The class keywords arguments, if any. - **kwargs: See [`griffelib.Object`][]. + **kwargs: See [`griffe.Object`][]. """ super().__init__(*args, **kwargs) @@ -2510,11 +2496,11 @@ def __init__( """Initialize the function. Parameters: - *args: See [`griffelib.Object`][]. + *args: See [`griffe.Object`][]. parameters: The function parameters. returns: The function return annotation. decorators: The function decorators, if any. - **kwargs: See [`griffelib.Object`][]. + **kwargs: See [`griffe.Object`][]. """ super().__init__(*args, **kwargs) self.parameters: Parameters = parameters or Parameters() @@ -2679,10 +2665,10 @@ def __init__( """Initialize the function. Parameters: - *args: See [`griffelib.Object`][]. + *args: See [`griffe.Object`][]. value: The attribute value, if any. annotation: The attribute annotation, if any. - **kwargs: See [`griffelib.Object`][]. + **kwargs: See [`griffe.Object`][]. """ super().__init__(*args, **kwargs) self.value: str | Expr | None = value @@ -2727,9 +2713,9 @@ def __init__( """Initialize the function. Parameters: - *args: See [`griffelib.Object`][]. + *args: See [`griffe.Object`][]. value: The type alias value. - **kwargs: See [`griffelib.Object`][]. + **kwargs: See [`griffe.Object`][]. """ super().__init__(*args, **kwargs) self.value: str | Expr | None = value diff --git a/packages/griffelib/src/griffelib/_internal/py.typed b/packages/griffelib/src/griffe/_internal/py.typed similarity index 100% rename from packages/griffelib/src/griffelib/_internal/py.typed rename to packages/griffelib/src/griffe/_internal/py.typed diff --git a/packages/griffelib/src/griffelib/_internal/stats.py b/packages/griffelib/src/griffe/_internal/stats.py similarity index 97% rename from packages/griffelib/src/griffelib/_internal/stats.py rename to packages/griffelib/src/griffe/_internal/stats.py index 59400a510..957cc5c89 100644 --- a/packages/griffelib/src/griffelib/_internal/stats.py +++ b/packages/griffelib/src/griffe/_internal/stats.py @@ -7,11 +7,11 @@ from pathlib import Path from typing import TYPE_CHECKING -from griffelib._internal.enumerations import Kind +from griffe._internal.enumerations import Kind if TYPE_CHECKING: - from griffelib._internal.loader import GriffeLoader - from griffelib._internal.models import Alias, Object + from griffe._internal.loader import GriffeLoader + from griffe._internal.models import Alias, Object class Stats: diff --git a/packages/griffelib/src/griffelib/_internal/tests.py b/packages/griffelib/src/griffe/_internal/tests.py similarity index 96% rename from packages/griffelib/src/griffelib/_internal/tests.py rename to packages/griffelib/src/griffe/_internal/tests.py index 1383bc7aa..912447056 100644 --- a/packages/griffelib/src/griffelib/_internal/tests.py +++ b/packages/griffelib/src/griffe/_internal/tests.py @@ -13,19 +13,19 @@ from textwrap import dedent from typing import TYPE_CHECKING -from griffelib._internal.agents.inspector import inspect -from griffelib._internal.agents.visitor import visit -from griffelib._internal.collections import LinesCollection -from griffelib._internal.loader import load -from griffelib._internal.models import Module, Object +from griffe._internal.agents.inspector import inspect +from griffe._internal.agents.visitor import visit +from griffe._internal.collections import LinesCollection +from griffe._internal.loader import load +from griffe._internal.models import Module, Object if TYPE_CHECKING: from collections.abc import Iterator, Mapping, Sequence - from griffelib._internal.collections import ModulesCollection - from griffelib._internal.docstrings.parsers import DocstringOptions, DocstringStyle - from griffelib._internal.enumerations import Parser - from griffelib._internal.extensions.base import Extensions + from griffe._internal.collections import ModulesCollection + from griffe._internal.docstrings.parsers import DocstringOptions, DocstringStyle + from griffe._internal.enumerations import Parser + from griffe._internal.extensions.base import Extensions _TMPDIR_PREFIX = "griffe_" diff --git a/scripts/gen_structure_docs.py b/scripts/gen_structure_docs.py index 7f84671ae..85d07a000 100644 --- a/scripts/gen_structure_docs.py +++ b/scripts/gen_structure_docs.py @@ -68,7 +68,7 @@ def render_internal_api(heading_level: int = 4) -> None: heading_level: The initial level of Markdown headings. """ root = Path(os.environ["MKDOCS_CONFIG_DIR"]) - src = root / "src" + src = root / "packages" / "griffelib" / "src" internal_api = src / "griffe" / "_internal" print(_comment_block(internal_api / "__init__.py")) _render_api(internal_api, internal_api, heading_level) @@ -81,7 +81,7 @@ def render_public_api(heading_level: int = 4) -> None: heading_level: The initial level of Markdown headings. """ root = Path(os.environ["MKDOCS_CONFIG_DIR"]) - src = root / "src" + src = root / "packages" / "griffelib" / "src" public_api = src / "griffe" print(f"{'#' * heading_level} `griffe`\n") print(_comment_block(public_api / "__init__.py")) @@ -94,7 +94,7 @@ def render_entrypoint(heading_level: int = 4) -> None: heading_level: The initial level of Markdown headings. """ root = Path(os.environ["MKDOCS_CONFIG_DIR"]) - src = root / "src" + src = root / "packages" / "griffelib" / "src" public_api = src / "griffe" - print(f"{'#' * heading_level} `griffelib.__main__`\n") + print(f"{'#' * heading_level} `griffe.__main__`\n") print(_comment_block(public_api / "__main__.py")) diff --git a/src/griffe/__init__.py b/src/griffe/__init__.py deleted file mode 100644 index 09ddc836a..000000000 --- a/src/griffe/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Griffe package. - -Signatures for entire Python programs. -Extract the structure, the frame, the skeleton of your project, -to generate API documentation or find breaking changes in your API. - -This is a backward-compatible package that re-exports all public symbols from -both `griffelib` (the library) and `griffecli` (the CLI). - -The entirety of the public API is exposed here, in the top-level `griffe` module. - -All messages written to standard output or error are logged using the `logging` module. -Our logger's name is set to `"griffe"` and is public (you can rely on it). -You can obtain the logger from the standard `logging` module: `logging.getLogger("griffe")`. -Actual logging messages are not part of the public API (they might change without notice). - -Raised exceptions throughout the package are part of the public API (you can rely on them). -Their actual messages are not part of the public API (they might change without notice). - -See the `griffelib` and `griffecli` packages for detailed API documentation. -""" - -from griffecli import * # noqa: F403 -from griffecli import __all__ as __cli_all__ -from griffelib import * # noqa: F403 -from griffelib import __all__ as __lib_all__ - -__all__ = [*__lib_all__, *__cli_all__] # noqa: PLE0604 diff --git a/src/griffe/py.typed b/src/griffe/py.typed deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/helpers.py b/tests/helpers.py index 1ca06eaef..47613ddd0 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -6,7 +6,7 @@ import sys from tempfile import gettempdir -from griffelib._internal.tests import _TMPDIR_PREFIX +from griffe._internal.tests import _TMPDIR_PREFIX def clear_sys_modules(name: str | None = None) -> None: diff --git a/tests/test_cli.py b/tests/test_cli.py index fde01915f..ae2d5b576 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,8 +6,8 @@ import pytest +from griffe._internal import debug from griffecli._internal import cli -from griffelib._internal import debug def test_main() -> None: diff --git a/tests/test_docstrings/conftest.py b/tests/test_docstrings/conftest.py index c37dfda55..366727cee 100644 --- a/tests/test_docstrings/conftest.py +++ b/tests/test_docstrings/conftest.py @@ -6,7 +6,7 @@ import pytest -from griffelib._internal.docstrings import google, numpy, sphinx +from griffe._internal.docstrings import google, numpy, sphinx from tests.test_docstrings.helpers import ParserType, parser if TYPE_CHECKING: diff --git a/tests/test_encoders.py b/tests/test_encoders.py index 938688194..b8d3eeb47 100644 --- a/tests/test_encoders.py +++ b/tests/test_encoders.py @@ -73,7 +73,7 @@ def test_namespace_packages() -> None: def test_minimal_light_data_is_enough(symbol: str) -> None: """Test serialization and de-serialization.""" loader = GriffeLoader() - package = loader.load("griffelib") + package = loader.load("griffe") obj = package[symbol] dump_options = {"indent": 2, "sort_keys": True} minimal = obj.as_json(full=False, **dump_options) diff --git a/tests/test_extensions/test_base.py b/tests/test_extensions/test_base.py index 5f5caa7a1..7ca78dee4 100644 --- a/tests/test_extensions/test_base.py +++ b/tests/test_extensions/test_base.py @@ -17,7 +17,7 @@ temporary_visited_module, temporary_visited_package, ) -from griffelib._internal.models import Attribute, Class, Function, Module, Object, TypeAlias +from griffe._internal.models import Attribute, Class, Function, Module, Object, TypeAlias if TYPE_CHECKING: import ast diff --git a/tests/test_finder.py b/tests/test_finder.py index d65c492fc..9b6d34076 100644 --- a/tests/test_finder.py +++ b/tests/test_finder.py @@ -9,7 +9,7 @@ import pytest from griffe import Module, ModuleFinder, NamespacePackage, Package, temporary_pypackage -from griffelib._internal.finder import _handle_editable_module, _handle_pth_file +from griffe._internal.finder import _handle_editable_module, _handle_pth_file @pytest.mark.parametrize( From c7d2fe94708a1f904de8f3502690777ad0d103ee Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 13:55:15 +0100 Subject: [PATCH 21/53] Fix packaging --- packages/griffelib/pyproject.toml | 2 +- pyproject.toml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/griffelib/pyproject.toml b/packages/griffelib/pyproject.toml index e445c11e2..58b03c3b5 100644 --- a/packages/griffelib/pyproject.toml +++ b/packages/griffelib/pyproject.toml @@ -52,4 +52,4 @@ pypi = ["pip>=24.0", "platformdirs>=4.2", "wheel>=0.42"] [tool.hatch.build.targets.sdist] [tool.hatch.build.targets.wheel] -sources = ["src/"] +packages = ["src/griffe"] diff --git a/pyproject.toml b/pyproject.toml index 77f2bc30a..2eabbee53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,7 +74,6 @@ include = [ "config", "docs", "scripts", - "src", "share", "tests", "duties.py", @@ -87,7 +86,7 @@ include = [ # Manual pages can be included in the wheel. # Depending on the installation tool, they will be accessible to users. # pipx supports it, uv does not yet, see https://github.com/astral-sh/uv/issues/4731. -sources = ["src/"] +bypass-selection = true artifacts = ["share/**/*"] [dependency-groups] From 8a6b14a8e798529a71a6171e1c82821f876d076e Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 13:59:42 +0100 Subject: [PATCH 22/53] Additional cleanups/fixes --- docs/reference/api/cli.md | 6 +++--- duties.py | 17 +++++++++++++++-- packages/griffelib/src/griffe/__init__.py | 17 ++++++----------- packages/griffelib/src/griffe/__main__.py | 10 +++++----- .../griffelib/src/griffe/_internal/finder.py | 2 +- tests/test_api.py | 2 +- tests/test_finder.py | 6 +++--- 7 files changed, 34 insertions(+), 26 deletions(-) diff --git a/docs/reference/api/cli.md b/docs/reference/api/cli.md index 8d4d27143..c806e83cf 100644 --- a/docs/reference/api/cli.md +++ b/docs/reference/api/cli.md @@ -4,10 +4,10 @@ ::: griffecli.main -::: griffe.check +::: griffecli.check -::: griffe.dump +::: griffecli.dump ## **Advanced API** -::: griffe.get_parser +::: griffecli.get_parser diff --git a/duties.py b/duties.py index d3f1178cd..873f73c78 100644 --- a/duties.py +++ b/duties.py @@ -24,7 +24,7 @@ from duty.context import Context -PY_SRC_PATHS = (Path(_) for _ in ("src", "tests", "duties.py", "scripts")) +PY_SRC_PATHS = (Path(_) for _ in ("packages/griffecli/src", "packages/griffelib/src", "tests", "duties.py", "scripts")) PY_SRC_LIST = tuple(str(_) for _ in PY_SRC_PATHS) PY_SRC = " ".join(PY_SRC_LIST) CI = os.environ.get("CI", "0") in {"1", "true", "yes", ""} @@ -287,7 +287,20 @@ def check_api(ctx: Context, *cli_args: str) -> None: ctx.run( tools.griffe.check( "griffe", - search=["src"], + search=["packages/griffelib/src"], + color=True, + extensions=[ + "griffe_inherited_docstrings", + "unpack_typeddict", + ], + ).add_args(*cli_args), + title="Checking for API breaking changes", + nofail=True, + ) + ctx.run( + tools.griffe.check( + "griffecli", + search=["packages/griffecli/src"], color=True, extensions=[ "griffe_inherited_docstrings", diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index 1a892c1f2..da751a3d2 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -601,14 +601,9 @@ "main", ] -try: - from griffecli._internal.cli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main -except ImportError: - def __getattr__(attr: str) -> object: - if attr in __cli_all__: - import griffecli._internal.cli as griffecli_mod - return getattr(griffecli_mod, attr) - raise AttributeError(attr) - -else: - __all__.extend(__cli_all__) +__all__ += __cli_all__ + +def __getattr__(attr: str) -> object: + if attr in __cli_all__: + raise ImportError(f'Install `griffecli` to use {"griffe." + attr!r}') + raise AttributeError(attr) diff --git a/packages/griffelib/src/griffe/__main__.py b/packages/griffelib/src/griffe/__main__.py index 8d31f600e..e3bb8a89f 100644 --- a/packages/griffelib/src/griffe/__main__.py +++ b/packages/griffelib/src/griffe/__main__.py @@ -10,11 +10,11 @@ try: from griffecli import main -except ModuleNotFoundError: - raise ImportError( - "`griffecli` is not installed. Install `griffecli` " - "to use `python -m griffe`." - ) +except ModuleNotFoundError as exc: + raise ModuleNotFoundError( + "`griffecli` or its dependencies are not installed. " + "Install `griffecli` to use `python -m griffe`.", + ) from exc if __name__ == "__main__": sys.exit(main(sys.argv[1:])) diff --git a/packages/griffelib/src/griffe/_internal/finder.py b/packages/griffelib/src/griffe/_internal/finder.py index 3960e1470..69c29da4d 100644 --- a/packages/griffelib/src/griffe/_internal/finder.py +++ b/packages/griffelib/src/griffe/_internal/finder.py @@ -508,7 +508,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: and node.value.func.id == "install" and isinstance(node.value.args[1], ast.Constant) ): - build_path = Path(node.value.args[1].value, "src") # type: ignore[arg-type] + build_path = Path(node.value.args[1].value, "packages/griffelib/src") # type: ignore[arg-type] # NOTE: What if there are multiple packages? pkg_name = next(build_path.iterdir()).name return [_SP(build_path, always_scan_for=pkg_name)] diff --git a/tests/test_api.py b/tests/test_api.py index 0cd72b0a5..d74b6c2b9 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -140,7 +140,7 @@ def _public_path(obj: griffe.Object | griffe.Alias) -> bool: return obj.is_public and (obj.parent is None or _public_path(obj.parent)) multiple_locations = {} - for obj_name in griffe.__all__: + for obj_name in set(griffe.__all__) - set(griffe.__cli_all__): obj = public_api[obj_name] if obj.aliases and ( public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)] diff --git a/tests/test_finder.py b/tests/test_finder.py index 9b6d34076..26b6e81c6 100644 --- a/tests/test_finder.py +++ b/tests/test_finder.py @@ -125,9 +125,9 @@ def test_editables_file_handling(tmp_path: Path, editable_file_name: str) -> Non tmp_path: Pytest fixture. """ pth_file = tmp_path / editable_file_name - pth_file.write_text("hello\nF.map_module('griffe', 'src/griffe/__init__.py')", encoding="utf8") + pth_file.write_text("hello\nF.map_module('griffe', 'packages/griffelib/src/griffe/__init__.py')", encoding="utf8") paths = [sp.path for sp in _handle_editable_module(pth_file)] - assert paths == [Path("src")] + assert paths == [Path("packages/griffelib/src")] @pytest.mark.parametrize("annotation", ["", ": dict[str, str]"]) @@ -197,7 +197,7 @@ def test_meson_python_file_handling(tmp_path: Path) -> None: search_paths = _handle_editable_module(pth_file) assert all(sp.always_scan_for == "griffe" for sp in search_paths) paths = [sp.path for sp in search_paths] - assert paths == [Path("src")] + assert paths == [Path("packages/griffelib/src")] @pytest.mark.parametrize( From 7dd30c341d8948925823096233f3e44cbd55285e Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 14:45:22 +0100 Subject: [PATCH 23/53] Fix coverage config --- config/coverage.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/coverage.ini b/config/coverage.ini index 6f57222a8..728a0ebb5 100644 --- a/config/coverage.ini +++ b/config/coverage.ini @@ -2,7 +2,8 @@ branch = true parallel = true source = - packages/griffe/src/griffe + packages/griffelib/src/griffe + packages/griffecli/src/griffecli tests/ [coverage:paths] From e2ea8b8b783f9f1967fc9b56256f3ff44a455d62 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 14:49:32 +0100 Subject: [PATCH 24/53] Remove pointless option in ruff config --- config/ruff.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/ruff.toml b/config/ruff.toml index 5b1808839..9cb744122 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -35,7 +35,7 @@ ignore = [ "TRY003", # Avoid specifying long messages outside the exception class ] -logger-objects = ["griffe.logger", "griffe.logger"] +logger-objects = ["griffe.logger"] [lint.per-file-ignores] "packages/griffecli/src/griffecli/__main__.py" = [ From 0571dda8c53a05f7cda6a8c31ff7787e683e691e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Sun, 18 Jan 2026 14:50:31 +0100 Subject: [PATCH 25/53] Remove unnecessary change --- docs/guide/users/navigating.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/users/navigating.md b/docs/guide/users/navigating.md index db3bc48c5..75a1a0ab3 100644 --- a/docs/guide/users/navigating.md +++ b/docs/guide/users/navigating.md @@ -122,7 +122,7 @@ If a base class cannot be resolved during computation of inherited members, Grif If you want to access all members at once (both declared and inherited), use the [`all_members`][griffe.Object.all_members] attribute. If you want to access only declared members, use the [`members`][griffe.Object] attribute. -Accessing the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by griffe. Don't try to access inherited members in extensions, while visiting or inspecting modules. +Accessing the [`attributes`][griffe.Object.attributes], [`functions`][griffe.Object.functions], [`classes`][griffe.Object.classes], [`type_aliases`][griffe.Object.type_aliases] or [`modules`][griffe.Object.modules] attributes will trigger inheritance computation, so make sure to only access them once everything is loaded by Griffe. Don't try to access inherited members in extensions, while visiting or inspecting modules. #### Limitations From 77b44fc9957b827439aea75784eb38376f90d3e6 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 14:56:00 +0100 Subject: [PATCH 26/53] Fix cross-ref --- docs/reference/api/loggers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/api/loggers.md b/docs/reference/api/loggers.md index 0ba1d0dbd..afb2b220a 100644 --- a/docs/reference/api/loggers.md +++ b/docs/reference/api/loggers.md @@ -10,7 +10,7 @@ ::: griffe.LogLevel -::: griffe.DEFAULT_LOG_LEVEL +::: griffecli.DEFAULT_LOG_LEVEL options: annotations_path: full From e0f3490dfb01b1082fcee2cad3536d6a94390f57 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 15:15:23 +0100 Subject: [PATCH 27/53] Fix warning --- packages/griffelib/src/griffe/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index da751a3d2..6a1f0d956 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -603,6 +603,11 @@ __all__ += __cli_all__ +try: + from griffecli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main +except ImportError: + pass + def __getattr__(attr: str) -> object: if attr in __cli_all__: raise ImportError(f'Install `griffecli` to use {"griffe." + attr!r}') From 4886bdbf6114bf188ceb13e86251c5c9aa7fbebe Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 15:23:32 +0100 Subject: [PATCH 28/53] Fix quality checks --- packages/griffelib/src/griffe/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index 6a1f0d956..eb446e27f 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -601,10 +601,10 @@ "main", ] -__all__ += __cli_all__ +__all__ += __cli_all__ # noqa: PLE0605 -try: - from griffecli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main +try: # noqa: SIM105 + from griffecli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main # noqa: F401 except ImportError: pass From ebca8583579e72548e41c12a4dd540863b735693 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 16:18:54 +0100 Subject: [PATCH 29/53] Fix CLI glue code --- packages/griffelib/src/griffe/__init__.py | 25 +++++++++++------------ tests/test_api.py | 1 + 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index eb446e27f..e6d84fc9c 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -593,22 +593,21 @@ "vtree", ] -__cli_all__ = [ - "DEFAULT_LOG_LEVEL", - "check", - "dump", - "get_parser", - "main", -] - -__all__ += __cli_all__ # noqa: PLE0605 - try: # noqa: SIM105 from griffecli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main # noqa: F401 except ImportError: - pass + _CLI_MISSING_FEATURES = { + "DEFAULT_LOG_LEVEL", + "check", + "dump", + "get_parser", + "main", + } +else: + _CLI_MISSING_FEATURES = set() + def __getattr__(attr: str) -> object: - if attr in __cli_all__: - raise ImportError(f'Install `griffecli` to use {"griffe." + attr!r}') + if attr in _CLI_MISSING_FEATURES: + raise ImportError(f'Please install `griffecli` to use {"griffe." + attr!r}') raise AttributeError(attr) diff --git a/tests/test_api.py b/tests/test_api.py index d74b6c2b9..b0ef1b36d 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -177,6 +177,7 @@ def test_inventory_matches_api( not_in_api = [] public_api_paths = {obj.path for obj in public_objects} public_api_paths.add("griffe") + public_api_paths.add("griffecli") for item in inventory.values(): if item.domain == "py" and "(" not in item.name: obj = loader.modules_collection[item.name] From 38abea4bc27001f2408d68c9ded39009e92e329f Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 16:21:11 +0100 Subject: [PATCH 30/53] Fix lint problems --- packages/griffelib/src/griffe/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index e6d84fc9c..3447acb51 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -593,7 +593,7 @@ "vtree", ] -try: # noqa: SIM105 +try: from griffecli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main # noqa: F401 except ImportError: _CLI_MISSING_FEATURES = { From 8a1e6556df1fcc7b12f77727d686d349dd7e0503 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 16:27:30 +0100 Subject: [PATCH 31/53] Fix typing problems --- tests/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api.py b/tests/test_api.py index b0ef1b36d..d02156b15 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -140,7 +140,7 @@ def _public_path(obj: griffe.Object | griffe.Alias) -> bool: return obj.is_public and (obj.parent is None or _public_path(obj.parent)) multiple_locations = {} - for obj_name in set(griffe.__all__) - set(griffe.__cli_all__): + for obj_name in set(griffe.__all__) - griffe._CLI_MISSING_FEATURES: obj = public_api[obj_name] if obj.aliases and ( public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)] From a02b3ede7595962c11a05591225f3c67faf0fdd0 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 16:33:22 +0100 Subject: [PATCH 32/53] Update paths to inventories --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 52e130130..08da13839 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -218,7 +218,7 @@ plugins: - url: https://docs.python.org/3/objects.inv domains: [std, py] - https://typing-extensions.readthedocs.io/en/latest/objects.inv - paths: [src, scripts, .] + paths: [packages/griffelib, packages/griffecli, scripts, .] options: backlinks: tree docstring_options: From 4e5307337d9b92ca618e84628483e7a27b7399e7 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 16:35:49 +0100 Subject: [PATCH 33/53] Use double quoted strings --- packages/griffelib/src/griffe/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index 3447acb51..ab0c6e230 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -609,5 +609,5 @@ def __getattr__(attr: str) -> object: if attr in _CLI_MISSING_FEATURES: - raise ImportError(f'Please install `griffecli` to use {"griffe." + attr!r}') + raise ImportError(f"Please install `griffecli` to use {'griffe.' + attr!r}") raise AttributeError(attr) From 09d08647ef452b73507de74c1755c22a001820d8 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 16:46:14 +0100 Subject: [PATCH 34/53] Fix inventory paths again --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 08da13839..2c856afd0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -218,7 +218,7 @@ plugins: - url: https://docs.python.org/3/objects.inv domains: [std, py] - https://typing-extensions.readthedocs.io/en/latest/objects.inv - paths: [packages/griffelib, packages/griffecli, scripts, .] + paths: [packages/griffelib/src, packages/griffecli/src, scripts, .] options: backlinks: tree docstring_options: From f50fd1848a6b9f1b3cb5d5335ffc8afe04b93643 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 18:34:00 +0100 Subject: [PATCH 35/53] Make API tests generic over packages --- tests/test_api.py | 69 ++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index d02156b15..657c3d9e6 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -5,38 +5,41 @@ from collections import defaultdict from fnmatch import fnmatch from pathlib import Path +from types import ModuleType from typing import TYPE_CHECKING import pytest from mkdocstrings import Inventory import griffe +import griffecli if TYPE_CHECKING: from collections.abc import Iterator -@pytest.fixture(name="loader", scope="module") -def _fixture_loader() -> griffe.GriffeLoader: +def _load_module(module: ModuleType) -> griffe.GriffeLoader: loader = griffe.GriffeLoader( extensions=griffe.load_extensions( "griffe_inherited_docstrings", "unpack_typeddict", ), ) - loader.load("griffe") + loader.load(module.__name__) loader.resolve_aliases() return loader -@pytest.fixture(name="internal_api", scope="module") -def _fixture_internal_api(loader: griffe.GriffeLoader) -> griffe.Module: - return loader.modules_collection["griffe._internal"] +def _get_internal_api(module: ModuleType, loader: griffe.GriffeLoader | None = None) -> griffe.Module: + if loader is None: + loader = _load_module(module) + return loader.modules_collection[module.__name__ + "._internal"] -@pytest.fixture(name="public_api", scope="module") -def _fixture_public_api(loader: griffe.GriffeLoader) -> griffe.Module: - return loader.modules_collection["griffe"] +def _get_public_api(module: ModuleType, loader: griffe.GriffeLoader | None = None) -> griffe.Module: + if loader is None: + loader = _load_module(module) + return loader.modules_collection[module.__name__] def _yield_public_objects( @@ -76,19 +79,12 @@ def _yield_public_objects( continue -@pytest.fixture(name="modulelevel_internal_objects", scope="module") -def _fixture_modulelevel_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: - return list(_yield_public_objects(internal_api, modulelevel=True)) +def _get_modulelevel_internal_objects(tested_module: ModuleType) -> list[griffe.Object | griffe.Alias]: + return list(_yield_public_objects(_get_internal_api(tested_module), modulelevel=True)) -@pytest.fixture(name="internal_objects", scope="module") -def _fixture_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: - return list(_yield_public_objects(internal_api, modulelevel=False, special=True)) - - -@pytest.fixture(name="public_objects", scope="module") -def _fixture_public_objects(public_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: - return list(_yield_public_objects(public_api, modulelevel=False, inherited=True, special=True)) +def _get_public_objects(tested_module: ModuleType) -> list[griffe.Object | griffe.Alias]: + return list(_yield_public_objects(_get_public_api(tested_module), modulelevel=False, inherited=True, special=True)) @pytest.fixture(name="inventory", scope="module") @@ -100,8 +96,9 @@ def _fixture_inventory() -> Inventory: return Inventory.parse_sphinx(file) -def test_alias_proxies(internal_api: griffe.Module) -> None: +def test_alias_proxies() -> None: """The Alias class has all the necessary methods and properties.""" + internal_api = _get_internal_api(griffe) alias_members = set(internal_api["models.Alias"].all_members.keys()) for cls in ( internal_api["models.Module"], @@ -114,18 +111,22 @@ def test_alias_proxies(internal_api: griffe.Module) -> None: assert name in alias_members -def test_exposed_objects(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None: +@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +def test_exposed_objects(tested_module: ModuleType) -> None: """All public objects in the internal API are exposed under `griffe`.""" + modulelevel_internal_objects = _get_modulelevel_internal_objects(tested_module) not_exposed = [ obj.path for obj in modulelevel_internal_objects - if obj.name not in griffe.__all__ or not hasattr(griffe, obj.name) + if obj.name not in tested_module.__all__ or not hasattr(tested_module, obj.name) ] assert not not_exposed, "Objects not exposed:\n" + "\n".join(sorted(not_exposed)) -def test_unique_names(modulelevel_internal_objects: list[griffe.Object | griffe.Alias]) -> None: +@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +def test_unique_names(tested_module: ModuleType) -> None: """All internal objects have unique names.""" + modulelevel_internal_objects = _get_modulelevel_internal_objects(tested_module) names_to_paths = defaultdict(list) for obj in modulelevel_internal_objects: names_to_paths[obj.name].append(obj.path) @@ -133,14 +134,16 @@ def test_unique_names(modulelevel_internal_objects: list[griffe.Object | griffe. assert not non_unique, "Non-unique names:\n" + "\n".join(str(paths) for paths in non_unique) -def test_single_locations(public_api: griffe.Module) -> None: +@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +def test_single_locations(tested_module: ModuleType) -> None: """All objects have a single public location.""" def _public_path(obj: griffe.Object | griffe.Alias) -> bool: return obj.is_public and (obj.parent is None or _public_path(obj.parent)) + public_api = _get_public_api(tested_module) multiple_locations = {} - for obj_name in set(griffe.__all__) - griffe._CLI_MISSING_FEATURES: + for obj_name in tested_module.__all__: obj = public_api[obj_name] if obj.aliases and ( public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)] @@ -168,16 +171,19 @@ def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe assert not not_in_inventory, msg.format(paths="\n".join(sorted(not_in_inventory))) +@pytest.mark.parametrize("tested_module", [griffe, griffecli]) def test_inventory_matches_api( inventory: Inventory, public_objects: list[griffe.Object | griffe.Alias], - loader: griffe.GriffeLoader, + tested_module: ModuleType, ) -> None: """The inventory doesn't contain any additional Python object.""" + loader = _load_module(tested_module) + public_api = _get_public_api(tested_module, loader=loader) + public_objects = _get_public_objects(public_api) not_in_api = [] public_api_paths = {obj.path for obj in public_objects} - public_api_paths.add("griffe") - public_api_paths.add("griffecli") + public_api_paths.add(tested_module.__name__) for item in inventory.values(): if item.domain == "py" and "(" not in item.name: obj = loader.modules_collection[item.name] @@ -187,13 +193,16 @@ def test_inventory_matches_api( assert not not_in_api, msg.format(paths="\n".join(sorted(not_in_api))) -def test_no_module_docstrings_in_internal_api(internal_api: griffe.Module) -> None: +@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +def test_no_module_docstrings_in_internal_api(tested_module: ModuleType) -> None: """No module docstrings should be written in our internal API. The reasoning is that docstrings are addressed to users of the public API, but internal modules are not exposed to users, so they should not have docstrings. """ + internal_api = _get_internal_api(tested_module) + def _modules(obj: griffe.Module) -> Iterator[griffe.Module]: for member in obj.modules.values(): yield member From a4ce6fbad689c6d3f6ce254dbcce5a41787db22a Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 18:43:29 +0100 Subject: [PATCH 36/53] Workaround single locations test --- packages/griffelib/src/griffe/__init__.py | 22 +++++++++++++--------- tests/test_api.py | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index ab0c6e230..cbc9feb12 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -593,21 +593,25 @@ "vtree", ] +# Re-export griffecli for backward compatibility. try: - from griffecli import DEFAULT_LOG_LEVEL, check, dump, get_parser, main # noqa: F401 + from griffecli import * + from griffecli import __all__ as __cli_all__ except ImportError: - _CLI_MISSING_FEATURES = { + # Keep this in sync with the exported members of griffecli. + _MISSING_FROM_GRIFFECLI = { "DEFAULT_LOG_LEVEL", "check", "dump", "get_parser", "main", } -else: - _CLI_MISSING_FEATURES = set() - -def __getattr__(attr: str) -> object: - if attr in _CLI_MISSING_FEATURES: - raise ImportError(f"Please install `griffecli` to use {'griffe.' + attr!r}") - raise AttributeError(attr) + def __getattr__(attr: str) -> object: + if attr in _MISSING_FROM_GRIFFECLI: + raise ImportError(f"Please install `griffecli` to use {'griffe.' + attr!r}") + raise AttributeError(attr) +else: + __all__ += __cli_all__ + # Ignore this namespace in internal API tests. + _SINGLE_LOCATIONS_IGNORE = set(__cli_all__) diff --git a/tests/test_api.py b/tests/test_api.py index 657c3d9e6..0f3c3b9ce 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -143,7 +143,7 @@ def _public_path(obj: griffe.Object | griffe.Alias) -> bool: public_api = _get_public_api(tested_module) multiple_locations = {} - for obj_name in tested_module.__all__: + for obj_name in set(tested_module.__all__) - getattr(tested_module, "_SINGLE_LOCATIONS_IGNORE", set()): obj = public_api[obj_name] if obj.aliases and ( public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)] From c71d03468c55247ef0a9f21dccb4ff02729a1aa7 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 18:46:00 +0100 Subject: [PATCH 37/53] More descriptive duty names --- duties.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/duties.py b/duties.py index 873f73c78..ff244d2f7 100644 --- a/duties.py +++ b/duties.py @@ -294,7 +294,7 @@ def check_api(ctx: Context, *cli_args: str) -> None: "unpack_typeddict", ], ).add_args(*cli_args), - title="Checking for API breaking changes", + title="Checking for API breaking changes in Griffe library", nofail=True, ) ctx.run( @@ -307,7 +307,7 @@ def check_api(ctx: Context, *cli_args: str) -> None: "unpack_typeddict", ], ).add_args(*cli_args), - title="Checking for API breaking changes", + title="Checking for API breaking changes in Griffe CLI", nofail=True, ) From f37ffdcdf8ccaaf0a5cd59c1f7774af07914d609 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 18:48:32 +0100 Subject: [PATCH 38/53] Fix lint problems --- packages/griffelib/src/griffe/__init__.py | 4 ++-- tests/test_api.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index cbc9feb12..fd8b82301 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -595,7 +595,7 @@ # Re-export griffecli for backward compatibility. try: - from griffecli import * + from griffecli import * # noqa: F403 from griffecli import __all__ as __cli_all__ except ImportError: # Keep this in sync with the exported members of griffecli. @@ -612,6 +612,6 @@ def __getattr__(attr: str) -> object: raise ImportError(f"Please install `griffecli` to use {'griffe.' + attr!r}") raise AttributeError(attr) else: - __all__ += __cli_all__ + __all__ += __cli_all__ # noqa: PLE0605 # Ignore this namespace in internal API tests. _SINGLE_LOCATIONS_IGNORE = set(__cli_all__) diff --git a/tests/test_api.py b/tests/test_api.py index 0f3c3b9ce..6205a4393 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -5,7 +5,6 @@ from collections import defaultdict from fnmatch import fnmatch from pathlib import Path -from types import ModuleType from typing import TYPE_CHECKING import pytest @@ -16,6 +15,7 @@ if TYPE_CHECKING: from collections.abc import Iterator + from types import ModuleType def _load_module(module: ModuleType) -> griffe.GriffeLoader: @@ -200,7 +200,6 @@ def test_no_module_docstrings_in_internal_api(tested_module: ModuleType) -> None The reasoning is that docstrings are addressed to users of the public API, but internal modules are not exposed to users, so they should not have docstrings. """ - internal_api = _get_internal_api(tested_module) def _modules(obj: griffe.Module) -> Iterator[griffe.Module]: From 0c5610c5611883125bccb3267ee7305d8be7ae3f Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 18:53:47 +0100 Subject: [PATCH 39/53] Fix test rewrite --- tests/test_api.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 6205a4393..fb7a3b079 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -79,12 +79,12 @@ def _yield_public_objects( continue -def _get_modulelevel_internal_objects(tested_module: ModuleType) -> list[griffe.Object | griffe.Alias]: - return list(_yield_public_objects(_get_internal_api(tested_module), modulelevel=True)) +def _get_modulelevel_internal_objects(internal_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: + return list(_yield_public_objects(internal_api, modulelevel=True)) -def _get_public_objects(tested_module: ModuleType) -> list[griffe.Object | griffe.Alias]: - return list(_yield_public_objects(_get_public_api(tested_module), modulelevel=False, inherited=True, special=True)) +def _get_public_objects(public_api: griffe.Module) -> list[griffe.Object | griffe.Alias]: + return list(_yield_public_objects(public_api, modulelevel=False, inherited=True, special=True)) @pytest.fixture(name="inventory", scope="module") @@ -114,7 +114,7 @@ def test_alias_proxies() -> None: @pytest.mark.parametrize("tested_module", [griffe, griffecli]) def test_exposed_objects(tested_module: ModuleType) -> None: """All public objects in the internal API are exposed under `griffe`.""" - modulelevel_internal_objects = _get_modulelevel_internal_objects(tested_module) + modulelevel_internal_objects = _get_modulelevel_internal_objects(_get_internal_api(tested_module)) not_exposed = [ obj.path for obj in modulelevel_internal_objects @@ -126,7 +126,7 @@ def test_exposed_objects(tested_module: ModuleType) -> None: @pytest.mark.parametrize("tested_module", [griffe, griffecli]) def test_unique_names(tested_module: ModuleType) -> None: """All internal objects have unique names.""" - modulelevel_internal_objects = _get_modulelevel_internal_objects(tested_module) + modulelevel_internal_objects = _get_modulelevel_internal_objects(_get_public_api(tested_module)) names_to_paths = defaultdict(list) for obj in modulelevel_internal_objects: names_to_paths[obj.name].append(obj.path) From 0b1ca264c5fe7e9ab1dfcf04206c1c45692e89ac Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 18:59:35 +0100 Subject: [PATCH 40/53] Remove `public_objects` fixture reference --- tests/test_api.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index fb7a3b079..571f70202 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -172,11 +172,7 @@ def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe @pytest.mark.parametrize("tested_module", [griffe, griffecli]) -def test_inventory_matches_api( - inventory: Inventory, - public_objects: list[griffe.Object | griffe.Alias], - tested_module: ModuleType, -) -> None: +def test_inventory_matches_api(inventory: Inventory, tested_module: ModuleType) -> None: """The inventory doesn't contain any additional Python object.""" loader = _load_module(tested_module) public_api = _get_public_api(tested_module, loader=loader) From 449ff541ef20e9606e3417dac3ba1b3f35e5f408 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 19:21:37 +0100 Subject: [PATCH 41/53] Fix tests to new layout --- packages/griffelib/src/griffe/__init__.py | 4 +-- tests/test_api.py | 44 ++++++++++++++++------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index fd8b82301..82e8fe297 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -613,5 +613,5 @@ def __getattr__(attr: str) -> object: raise AttributeError(attr) else: __all__ += __cli_all__ # noqa: PLE0605 - # Ignore this namespace in internal API tests. - _SINGLE_LOCATIONS_IGNORE = set(__cli_all__) + # Ignore any reexpected API in internal API tests. + _REEXPORTED_EXTERNAL_API = set(__cli_all__) diff --git a/tests/test_api.py b/tests/test_api.py index 571f70202..96da3d03c 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -3,6 +3,7 @@ from __future__ import annotations from collections import defaultdict +from collections.abc import Iterable from fnmatch import fnmatch from pathlib import Path from typing import TYPE_CHECKING @@ -18,27 +19,32 @@ from types import ModuleType -def _load_module(module: ModuleType) -> griffe.GriffeLoader: +def _load_modules(*modules: ModuleType) -> griffe.GriffeLoader: loader = griffe.GriffeLoader( extensions=griffe.load_extensions( "griffe_inherited_docstrings", "unpack_typeddict", ), ) - loader.load(module.__name__) + for module in modules: + loader.load(module.__name__) loader.resolve_aliases() return loader def _get_internal_api(module: ModuleType, loader: griffe.GriffeLoader | None = None) -> griffe.Module: if loader is None: - loader = _load_module(module) + loader = _load_modules(module) return loader.modules_collection[module.__name__ + "._internal"] +def _get_reexported_names(module: ModuleType) -> Iterable[str]: + return getattr(module, "_REEXPORTED_EXTERNAL_API", ()) + + def _get_public_api(module: ModuleType, loader: griffe.GriffeLoader | None = None) -> griffe.Module: if loader is None: - loader = _load_module(module) + loader = _load_modules(module) return loader.modules_collection[module.__name__] @@ -143,7 +149,7 @@ def _public_path(obj: griffe.Object | griffe.Alias) -> bool: public_api = _get_public_api(tested_module) multiple_locations = {} - for obj_name in set(tested_module.__all__) - getattr(tested_module, "_SINGLE_LOCATIONS_IGNORE", set()): + for obj_name in set(tested_module.__all__).difference(_get_reexported_names(tested_module)): obj = public_api[obj_name] if obj.aliases and ( public_aliases := [path for path, alias in obj.aliases.items() if path != obj.path and _public_path(alias)] @@ -154,10 +160,15 @@ def _public_path(obj: griffe.Object | griffe.Alias) -> bool: ) -def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe.Object | griffe.Alias]) -> None: +@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +def test_api_matches_inventory(inventory: Inventory, tested_module: ModuleType) -> None: """All public objects are added to the inventory.""" ignore_names = {"__getattr__", "__init__", "__repr__", "__str__", "__post_init__"} + ignore_names.update(_get_reexported_names(tested_module)) ignore_paths = {"griffe.DataclassesExtension.*", "griffe.UnpackTypedDictExtension.*"} + loader = _load_modules(tested_module) + public_api = _get_public_api(tested_module, loader=loader) + public_objects = _get_public_objects(public_api) not_in_inventory = [ f"{obj.relative_filepath}:{obj.lineno}: {obj.path}" for obj in public_objects @@ -171,20 +182,27 @@ def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe assert not not_in_inventory, msg.format(paths="\n".join(sorted(not_in_inventory))) -@pytest.mark.parametrize("tested_module", [griffe, griffecli]) -def test_inventory_matches_api(inventory: Inventory, tested_module: ModuleType) -> None: +def test_inventory_matches_api(inventory: Inventory) -> None: """The inventory doesn't contain any additional Python object.""" - loader = _load_module(tested_module) - public_api = _get_public_api(tested_module, loader=loader) - public_objects = _get_public_objects(public_api) + tested_modules = (griffe, griffecli) + loader = _load_modules(*tested_modules) not_in_api = [] - public_api_paths = {obj.path for obj in public_objects} - public_api_paths.add(tested_module.__name__) + public_objects = [] + public_api_paths = set() + + for tested_module in tested_modules: + public_api = _get_public_api(tested_module, loader=loader) + module_public_objects = _get_public_objects(public_api) + public_api_paths.add(tested_module.__name__) + public_api_paths.update({obj.path for obj in module_public_objects}) + public_objects.extend(module_public_objects) + for item in inventory.values(): if item.domain == "py" and "(" not in item.name: obj = loader.modules_collection[item.name] if obj.path not in public_api_paths and not any(path in public_api_paths for path in obj.aliases): not_in_api.append(item.name) + msg = "Inventory objects not in public API (try running `make run mkdocs build`):\n{paths}" assert not not_in_api, msg.format(paths="\n".join(sorted(not_in_api))) From e90f3c18f6d5c2331eae463c6c3793ca74aaa02d Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 19:22:03 +0100 Subject: [PATCH 42/53] Fix import --- tests/test_api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 96da3d03c..08ff85f27 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -3,7 +3,6 @@ from __future__ import annotations from collections import defaultdict -from collections.abc import Iterable from fnmatch import fnmatch from pathlib import Path from typing import TYPE_CHECKING @@ -15,7 +14,7 @@ import griffecli if TYPE_CHECKING: - from collections.abc import Iterator + from collections.abc import Iterable, Iterator from types import ModuleType From 01d4d7c27c0d979d1ff6d8f31b6722b1640e07d1 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 19:25:43 +0100 Subject: [PATCH 43/53] Improve test structure --- tests/test_api.py | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 08ff85f27..3568834cb 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -18,6 +18,19 @@ from types import ModuleType +TESTED_MODULES = (griffe, griffecli) +test_all_modules = pytest.mark.parametrize("tested_module", TESTED_MODULES) + + +@pytest.fixture(name="inventory", scope="module") +def _fixture_inventory() -> Inventory: + inventory_file = Path(__file__).parent.parent / "site" / "objects.inv" + if not inventory_file.exists(): + pytest.skip("The objects inventory is not available.") # ty: ignore[call-non-callable] + with inventory_file.open("rb") as file: + return Inventory.parse_sphinx(file) + + def _load_modules(*modules: ModuleType) -> griffe.GriffeLoader: loader = griffe.GriffeLoader( extensions=griffe.load_extensions( @@ -92,15 +105,6 @@ def _get_public_objects(public_api: griffe.Module) -> list[griffe.Object | griff return list(_yield_public_objects(public_api, modulelevel=False, inherited=True, special=True)) -@pytest.fixture(name="inventory", scope="module") -def _fixture_inventory() -> Inventory: - inventory_file = Path(__file__).parent.parent / "site" / "objects.inv" - if not inventory_file.exists(): - pytest.skip("The objects inventory is not available.") # ty: ignore[call-non-callable] - with inventory_file.open("rb") as file: - return Inventory.parse_sphinx(file) - - def test_alias_proxies() -> None: """The Alias class has all the necessary methods and properties.""" internal_api = _get_internal_api(griffe) @@ -116,7 +120,7 @@ def test_alias_proxies() -> None: assert name in alias_members -@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +@test_all_modules def test_exposed_objects(tested_module: ModuleType) -> None: """All public objects in the internal API are exposed under `griffe`.""" modulelevel_internal_objects = _get_modulelevel_internal_objects(_get_internal_api(tested_module)) @@ -128,7 +132,7 @@ def test_exposed_objects(tested_module: ModuleType) -> None: assert not not_exposed, "Objects not exposed:\n" + "\n".join(sorted(not_exposed)) -@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +@test_all_modules def test_unique_names(tested_module: ModuleType) -> None: """All internal objects have unique names.""" modulelevel_internal_objects = _get_modulelevel_internal_objects(_get_public_api(tested_module)) @@ -139,7 +143,7 @@ def test_unique_names(tested_module: ModuleType) -> None: assert not non_unique, "Non-unique names:\n" + "\n".join(str(paths) for paths in non_unique) -@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +@test_all_modules def test_single_locations(tested_module: ModuleType) -> None: """All objects have a single public location.""" @@ -159,7 +163,7 @@ def _public_path(obj: griffe.Object | griffe.Alias) -> bool: ) -@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +@test_all_modules def test_api_matches_inventory(inventory: Inventory, tested_module: ModuleType) -> None: """All public objects are added to the inventory.""" ignore_names = {"__getattr__", "__init__", "__repr__", "__str__", "__post_init__"} @@ -183,13 +187,12 @@ def test_api_matches_inventory(inventory: Inventory, tested_module: ModuleType) def test_inventory_matches_api(inventory: Inventory) -> None: """The inventory doesn't contain any additional Python object.""" - tested_modules = (griffe, griffecli) - loader = _load_modules(*tested_modules) + loader = _load_modules(*TESTED_MODULES) not_in_api = [] public_objects = [] public_api_paths = set() - for tested_module in tested_modules: + for tested_module in TESTED_MODULES: public_api = _get_public_api(tested_module, loader=loader) module_public_objects = _get_public_objects(public_api) public_api_paths.add(tested_module.__name__) @@ -206,7 +209,7 @@ def test_inventory_matches_api(inventory: Inventory) -> None: assert not not_in_api, msg.format(paths="\n".join(sorted(not_in_api))) -@pytest.mark.parametrize("tested_module", [griffe, griffecli]) +@test_all_modules def test_no_module_docstrings_in_internal_api(tested_module: ModuleType) -> None: """No module docstrings should be written in our internal API. From 8d919882f684357f8acb5542810b106a4a53cac6 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 19:31:35 +0100 Subject: [PATCH 44/53] Workaround pytest moodiness --- tests/test_api.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 3568834cb..0cf2201b8 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -19,7 +19,7 @@ TESTED_MODULES = (griffe, griffecli) -test_all_modules = pytest.mark.parametrize("tested_module", TESTED_MODULES) +_test_all_modules = pytest.mark.parametrize("tested_module", TESTED_MODULES) @pytest.fixture(name="inventory", scope="module") @@ -120,7 +120,7 @@ def test_alias_proxies() -> None: assert name in alias_members -@test_all_modules +@_test_all_modules def test_exposed_objects(tested_module: ModuleType) -> None: """All public objects in the internal API are exposed under `griffe`.""" modulelevel_internal_objects = _get_modulelevel_internal_objects(_get_internal_api(tested_module)) @@ -132,7 +132,7 @@ def test_exposed_objects(tested_module: ModuleType) -> None: assert not not_exposed, "Objects not exposed:\n" + "\n".join(sorted(not_exposed)) -@test_all_modules +@_test_all_modules def test_unique_names(tested_module: ModuleType) -> None: """All internal objects have unique names.""" modulelevel_internal_objects = _get_modulelevel_internal_objects(_get_public_api(tested_module)) @@ -143,7 +143,7 @@ def test_unique_names(tested_module: ModuleType) -> None: assert not non_unique, "Non-unique names:\n" + "\n".join(str(paths) for paths in non_unique) -@test_all_modules +@_test_all_modules def test_single_locations(tested_module: ModuleType) -> None: """All objects have a single public location.""" @@ -163,7 +163,7 @@ def _public_path(obj: griffe.Object | griffe.Alias) -> bool: ) -@test_all_modules +@_test_all_modules def test_api_matches_inventory(inventory: Inventory, tested_module: ModuleType) -> None: """All public objects are added to the inventory.""" ignore_names = {"__getattr__", "__init__", "__repr__", "__str__", "__post_init__"} @@ -209,7 +209,7 @@ def test_inventory_matches_api(inventory: Inventory) -> None: assert not not_in_api, msg.format(paths="\n".join(sorted(not_in_api))) -@test_all_modules +@_test_all_modules def test_no_module_docstrings_in_internal_api(tested_module: ModuleType) -> None: """No module docstrings should be written in our internal API. From 333a1b66f45e9d90521db512559907405f91e447 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 22:45:33 +0100 Subject: [PATCH 45/53] Fix problems with building `uv build --all` now works --- packages/griffecli/pyproject.toml | 17 ++++++++++------- packages/griffelib/pyproject.toml | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/griffecli/pyproject.toml b/packages/griffecli/pyproject.toml index b9a6525f8..db53ef713 100644 --- a/packages/griffecli/pyproject.toml +++ b/packages/griffecli/pyproject.toml @@ -12,7 +12,7 @@ license = "ISC" license-files = ["LICENSE"] requires-python = ">=3.10" keywords = ["api", "signature", "breaking-changes", "static-analysis", "dynamic-analysis"] -dynamic = ["version", "dependencies", "optional-dependencies"] +dynamic = ["version", "dependencies"] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -44,14 +44,17 @@ source = "code" path = "../../scripts/get_version.py" expression = "get_version()" +[tool.hatch.build.targets.sdist.force-include] +"../../CHANGELOG.md" = "CHANGELOG.md" +"../../LICENSE" = "LICENSE" +"../../README.md" = "README.md" + [tool.hatch.metadata.hooks.uv-dynamic-versioning] # Dependencies are dynamically versioned; {{version}} is substituted at build time. dependencies = ["griffelib=={{version}}", "colorama>=0.4"] -[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] -# No optional dependencies for the CLI package - -[tool.hatch.build.targets.sdist] - [tool.hatch.build.targets.wheel] -sources = ["src/"] +packages = ["src/griffecli"] + +[tool.uv.sources] +griffelib = { workspace = true } diff --git a/packages/griffelib/pyproject.toml b/packages/griffelib/pyproject.toml index 58b03c3b5..ad9954b44 100644 --- a/packages/griffelib/pyproject.toml +++ b/packages/griffelib/pyproject.toml @@ -12,7 +12,7 @@ license = "ISC" license-files = ["LICENSE"] requires-python = ">=3.10" keywords = ["api", "signature", "breaking-changes", "static-analysis", "dynamic-analysis"] -dynamic = ["version", "dependencies", "optional-dependencies"] +dynamic = ["version"] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -36,20 +36,20 @@ classifiers = [ "Typing :: Typed", ] +[project.optional-dependencies] +# The 'pypi' extra provides dependencies needed for the load_pypi functionality +# to download and inspect packages from PyPI. +pypi = ["pip>=24.0", "platformdirs>=4.2", "wheel>=0.42"] + [tool.hatch.version] source = "code" path = "../../scripts/get_version.py" expression = "get_version()" -[tool.hatch.metadata.hooks.uv-dynamic-versioning] -# No base dependencies needed for griffelib - -[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] -# The 'pypi' extra provides dependencies needed for the load_pypi functionality -# to download and inspect packages from PyPI. -pypi = ["pip>=24.0", "platformdirs>=4.2", "wheel>=0.42"] - -[tool.hatch.build.targets.sdist] +[tool.hatch.build.targets.sdist.force-include] +"../../CHANGELOG.md" = "CHANGELOG.md" +"../../LICENSE" = "LICENSE" +"../../README.md" = "README.md" [tool.hatch.build.targets.wheel] packages = ["src/griffe"] From b455adf49045785f37fbb2cc114bf30164c93450 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 23:01:25 +0100 Subject: [PATCH 46/53] Fix comment --- packages/griffelib/src/griffe/_internal/logger.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/griffelib/src/griffe/_internal/logger.py b/packages/griffelib/src/griffe/_internal/logger.py index 4a7d45773..6a7290fc3 100644 --- a/packages/griffelib/src/griffe/_internal/logger.py +++ b/packages/griffelib/src/griffe/_internal/logger.py @@ -4,8 +4,7 @@ # For example, mkdocstrings-python patches the logger to relocate it as a child # of `mkdocs.plugins` so that it fits in the MkDocs logging configuration. # -# We use a single, global logger because our public API is exposed in a single module. -# The logger name is "griffe" for backward compatibility. +# We use a single, global logger because our public API is exposed in a single module, `griffe`. # Extensions however should use their own logger, which is why we provide the `get_logger` function. from __future__ import annotations From e44a59558f654a35c13a15f0e6fbdf395cc2366b Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 18 Jan 2026 23:29:04 +0100 Subject: [PATCH 47/53] Update the documentation --- docs/guide/contributors/architecture.md | 19 +++++++++++++++---- docs/installation.md | 5 ++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/guide/contributors/architecture.md b/docs/guide/contributors/architecture.md index 28aa1cd83..ab9d28835 100644 --- a/docs/guide/contributors/architecture.md +++ b/docs/guide/contributors/architecture.md @@ -98,19 +98,30 @@ The tools used in tasks have their configuration files stored in the `config` fo ## Sources -Sources are located in the `src` folder, following the [src-layout](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/). We use [PDM-Backend](https://backend.pdm-project.org/) to build source and wheel distributions, and configure it in `pyproject.toml` to search for packages in the `src` folder. +Sources are located in the `packages/` subfolders, following the [src-layout](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/). +We use [Hatch](https://hatch.pypa.io/latest/) to build source and wheel distributions, and configure it in `pyproject.toml`. ## Tests -Our test suite is located in the `tests` folder. It is located outside of the sources as to not pollute distributions (it would be very wrong to publish a `tests` package as part of our distributions, since this name is extremely common), or worse, the public API. The `tests` folder is however included in our source distributions (`.tar.gz`), alongside most of our metadata and configuration files. Check out `pyproject.toml` to get the full list of files included in our source distributions. +Our test suite is located in the `tests` folder. It is located outside of the sources as to not pollute distributions (it would be very wrong to publish a `tests` package as part of our distributions, since this name is extremely common), or worse, the public API. The `tests` folder is however included in our source distributions (`.tar.gz`), alongside most of our metadata and configuration files. Check out our `pyproject.toml` files to get the full list of files included in our source distributions for every individual package within the `packages/` folder. The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test modules reflect our internal API structure, and except for a few test modules that test specific aspects of our API, each test module tests the logic from the corresponding module in the internal API. For example, `test_finder.py` tests code of the `griffe._internal.finder` internal module, while `test_functions` tests our ability to extract correct information from function signatures, statically. The general rule of thumb when writing new tests is to mirror the internal API. If a test touches to many aspects of the loading process, it can be added to the `test_loader` test module. ## Program structure -The internal API is contained within the `packages/griffelib/src/griffe/_internal` folder. The top-level `griffe/__init__.py` module exposes all the public API, by importing the internal objects from various submodules of `griffe._internal`. +Griffe is split into two pieces: the library and the CLI. -Users then import `griffe` directly, or import objects from it. +Each of them has an internal API contained within an `_internal` folder: +- `packages/griffelib/src/griffe/_internal` for the library, +- `packages/griffecli/src/griffecli/_internal` for the CLI. + +Griffe can be installed in library-only mode, which means that the CLI package from `packages/griffecli` is not present. +Library-only mode can be preferred if the user does not utilize the CLI functionality of Griffe and does not want to incorporate its dependencies. + +The top-level `packages/griffelib/src/griffe/__init__.py` module exposes all the public API available: it always re-exports internal objects from various submodules of `griffe._internal` and, if the CLI is installed, it re-exports the public API of `griffecli` as well. + +Users then import `griffe` directly, or import objects from it. If they don't have `griffecli` installed, they cannot import the CLI-related functionality, +such as [`griffecli.check`][]. We'll be honest: our code organization is not the most elegant, but it works :shrug: Have a look at the following module dependency graph, which will basically tell you nothing except that we have a lot of inter-module dependencies. Arrows read as "imports from". The code base is generally pleasant to work with though. diff --git a/docs/installation.md b/docs/installation.md index fd61e9b19..28b439af5 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -118,6 +118,8 @@ If you only need the library for API introspection and analysis without the CLI
+This installs the `griffe` package as usual, but without the CLI program, nor its API, nor its dependencies. + ## Install as a tool only === ":simple-python: pip" @@ -177,6 +179,3 @@ Or as a Python module: ```console $ python -m griffe check mypackage ``` - -TIP: **Alternative CLI Package** -If you need to run Griffe without the full library, you can also use `python -m griffecli` instead of `python -m griffe`. This runs the CLI directly from the `griffecli` package. From ce2c62eaffa214188ed93aa97bed7fc9a1934e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Sun, 18 Jan 2026 23:47:35 +0100 Subject: [PATCH 48/53] Apply suggestions from code review --- packages/griffelib/src/griffe/_internal/finder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/griffelib/src/griffe/_internal/finder.py b/packages/griffelib/src/griffe/_internal/finder.py index 69c29da4d..b3b6bc7dc 100644 --- a/packages/griffelib/src/griffe/_internal/finder.py +++ b/packages/griffelib/src/griffe/_internal/finder.py @@ -483,7 +483,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: return [_SP(new_path)] if _match_pattern(path.name, _editable_setuptools_patterns): # Support for how 'setuptools' writes these files: - # example line: `MAPPING = {'griffe': '/media/data/dev/griffelib/packages/griffe/src/griffe', 'briffe': '/media/data/dev/griffelib/src/briffe'}`. + # example line: `MAPPING = {'griffe': '/media/data/dev/griffe/packages/griffelib/src/griffe', 'briffe': '/media/data/dev/griffe/src/briffe'}`. # with annotation: `MAPPING: dict[str, str] = {...}`. parsed_module = ast.parse(path.read_text(encoding="utf8")) for node in parsed_module.body: @@ -497,7 +497,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: return [_SP(Path(cst.value).parent) for cst in node.value.values if isinstance(cst, ast.Constant)] # type: ignore[arg-type] if _match_pattern(path.name, _editable_meson_python_patterns): # Support for how 'meson-python' writes these files: - # example line: `install({'package', 'module1'}, '/media/data/dev/griffelib/build/cp311', ["path"], False)`. + # example line: `install({'package', 'module1'}, '/media/data/dev/griffe/build/cp311', ["path"], False)`. # Compiled modules then found in the cp311 folder, under src/package. parsed_module = ast.parse(path.read_text(encoding="utf8")) for node in parsed_module.body: From 87ce03f134e0fd81200d6603b447aa309e2ec561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Mon, 19 Jan 2026 16:01:46 +0100 Subject: [PATCH 49/53] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks! Co-authored-by: Timothée Mazzucotelli --- docs/guide/contributors/architecture.md | 1 + docs/installation.md | 4 ++-- packages/griffelib/src/griffe/__init__.py | 5 ++--- packages/griffelib/src/griffe/_internal/finder.py | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/guide/contributors/architecture.md b/docs/guide/contributors/architecture.md index ab9d28835..758470687 100644 --- a/docs/guide/contributors/architecture.md +++ b/docs/guide/contributors/architecture.md @@ -112,6 +112,7 @@ The test suite is based on [pytest](https://docs.pytest.org/en/8.2.x/). Test mod Griffe is split into two pieces: the library and the CLI. Each of them has an internal API contained within an `_internal` folder: + - `packages/griffelib/src/griffe/_internal` for the library, - `packages/griffecli/src/griffecli/_internal` for the CLI. diff --git a/docs/installation.md b/docs/installation.md index 28b439af5..062b265d1 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -61,7 +61,7 @@ Griffe is a Python package, so you can install it with your favorite Python pack ## Install as a library only -If you only need the library for API introspection and analysis without the CLI tool, you can install just `griffelib`: +If you only need the library for API introspection and analysis without the CLI tool, you can install `griffelib`: === ":simple-python: pip" ```bash @@ -118,7 +118,7 @@ If you only need the library for API introspection and analysis without the CLI
-This installs the `griffe` package as usual, but without the CLI program, nor its API, nor its dependencies. +This installs the `griffe` package as usual, but without the CLI program and its dependencies. ## Install as a tool only diff --git a/packages/griffelib/src/griffe/__init__.py b/packages/griffelib/src/griffe/__init__.py index 82e8fe297..eef5da28b 100644 --- a/packages/griffelib/src/griffe/__init__.py +++ b/packages/griffelib/src/griffe/__init__.py @@ -8,8 +8,7 @@ Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API. -The entirety of the library API is exposed here, in the top-level `griffelib` module. -For backward compatibility, you can also import from `griffe` which re-exports everything. +The entirety of the library API is exposed here, in the top-level `griffe` module. All messages written to standard output or error are logged using the `logging` module. Our logger's name is set to `"griffe"` and is public (you can rely on it). @@ -613,5 +612,5 @@ def __getattr__(attr: str) -> object: raise AttributeError(attr) else: __all__ += __cli_all__ # noqa: PLE0605 - # Ignore any reexpected API in internal API tests. + # Ignore any re-exported API in internal API tests. _REEXPORTED_EXTERNAL_API = set(__cli_all__) diff --git a/packages/griffelib/src/griffe/_internal/finder.py b/packages/griffelib/src/griffe/_internal/finder.py index b3b6bc7dc..5132b35a7 100644 --- a/packages/griffelib/src/griffe/_internal/finder.py +++ b/packages/griffelib/src/griffe/_internal/finder.py @@ -470,7 +470,7 @@ def _handle_pth_file(path: Path) -> list[_SP]: def _handle_editable_module(path: Path) -> list[_SP]: if _match_pattern(path.name, (*_editable_editables_patterns, *_editable_scikit_build_core_patterns)): # Support for how 'editables' write these files: - # example line: `F.map_module('griffe', '/media/data/dev/griffelib/packages/griffe/src/griffe/__init__.py')`. + # example line: `F.map_module('pkg', '/data/dev/pkg/src/pkg/__init__.py')`. # And how 'scikit-build-core' writes these files: # example line: `install({'griffe': '/media/data/dev/griffelib/packages/griffe/src/griffe/__init__.py'}, {'cmake_example': ...}, None, False, True)`. try: @@ -483,7 +483,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: return [_SP(new_path)] if _match_pattern(path.name, _editable_setuptools_patterns): # Support for how 'setuptools' writes these files: - # example line: `MAPPING = {'griffe': '/media/data/dev/griffe/packages/griffelib/src/griffe', 'briffe': '/media/data/dev/griffe/src/briffe'}`. + # example line: `MAPPING = {'pkg': '/data/dev/pkg/src/pkg', 'pkg2': '/data/dev/pkg/src/pkg2'}`. # with annotation: `MAPPING: dict[str, str] = {...}`. parsed_module = ast.parse(path.read_text(encoding="utf8")) for node in parsed_module.body: @@ -508,7 +508,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: and node.value.func.id == "install" and isinstance(node.value.args[1], ast.Constant) ): - build_path = Path(node.value.args[1].value, "packages/griffelib/src") # type: ignore[arg-type] + build_path = Path(node.value.args[1].value, "src") # type: ignore[arg-type] # NOTE: What if there are multiple packages? pkg_name = next(build_path.iterdir()).name return [_SP(build_path, always_scan_for=pkg_name)] From b5501021b9cd171ec1d3c216aa36fba0c9823947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Mon, 19 Jan 2026 16:02:43 +0100 Subject: [PATCH 50/53] Update example comment in Griffe finder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Timothée Mazzucotelli --- packages/griffelib/src/griffe/_internal/finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/griffelib/src/griffe/_internal/finder.py b/packages/griffelib/src/griffe/_internal/finder.py index 5132b35a7..0d270e4f7 100644 --- a/packages/griffelib/src/griffe/_internal/finder.py +++ b/packages/griffelib/src/griffe/_internal/finder.py @@ -472,7 +472,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: # Support for how 'editables' write these files: # example line: `F.map_module('pkg', '/data/dev/pkg/src/pkg/__init__.py')`. # And how 'scikit-build-core' writes these files: - # example line: `install({'griffe': '/media/data/dev/griffelib/packages/griffe/src/griffe/__init__.py'}, {'cmake_example': ...}, None, False, True)`. + # example line: `install({'pkg': '/data/dev/pkg/src/pkg/__init__.py'}, {'cmake_example': ...}, None, False, True)`. try: editable_lines = path.read_text(encoding="utf-8-sig").strip().splitlines(keepends=False) except FileNotFoundError as error: From 6f3b755d64fbeaf33a57f228bad1a8d0e687fe6c Mon Sep 17 00:00:00 2001 From: johnslavik Date: Mon, 19 Jan 2026 16:10:03 +0100 Subject: [PATCH 51/53] Keep original descriptions --- packages/griffecli/pyproject.toml | 2 +- packages/griffelib/pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/griffecli/pyproject.toml b/packages/griffecli/pyproject.toml index db53ef713..7cb4066ac 100644 --- a/packages/griffecli/pyproject.toml +++ b/packages/griffecli/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "hatchling.build" [project] name = "griffecli" -description = "The Griffe CLI" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}] license = "ISC" license-files = ["LICENSE"] diff --git a/packages/griffelib/pyproject.toml b/packages/griffelib/pyproject.toml index ad9954b44..67d9e1696 100644 --- a/packages/griffelib/pyproject.toml +++ b/packages/griffelib/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "hatchling.build" [project] name = "griffelib" -description = "The Griffe library" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." authors = [{name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}] license = "ISC" license-files = ["LICENSE"] From b3cf2f34d0a4043d5d3d2aeed591ac19e445f7ec Mon Sep 17 00:00:00 2001 From: johnslavik Date: Mon, 19 Jan 2026 16:44:20 +0100 Subject: [PATCH 52/53] Revert one suggestion --- packages/griffelib/src/griffe/_internal/finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/griffelib/src/griffe/_internal/finder.py b/packages/griffelib/src/griffe/_internal/finder.py index 0d270e4f7..951d299a8 100644 --- a/packages/griffelib/src/griffe/_internal/finder.py +++ b/packages/griffelib/src/griffe/_internal/finder.py @@ -508,7 +508,7 @@ def _handle_editable_module(path: Path) -> list[_SP]: and node.value.func.id == "install" and isinstance(node.value.args[1], ast.Constant) ): - build_path = Path(node.value.args[1].value, "src") # type: ignore[arg-type] + build_path = Path(node.value.args[1].value, "packages/griffelib/src") # type: ignore[arg-type] # NOTE: What if there are multiple packages? pkg_name = next(build_path.iterdir()).name return [_SP(build_path, always_scan_for=pkg_name)] From 524f534f2580f7cf3cb6c671acbb2557b2dd16bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Mon, 19 Jan 2026 22:48:47 +0100 Subject: [PATCH 53/53] Add `"griffe"` to version debug check candidates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Timothée Mazzucotelli --- packages/griffelib/src/griffe/_internal/debug.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/griffelib/src/griffe/_internal/debug.py b/packages/griffelib/src/griffe/_internal/debug.py index 5201db934..aaa07ac50 100644 --- a/packages/griffelib/src/griffe/_internal/debug.py +++ b/packages/griffelib/src/griffe/_internal/debug.py @@ -84,7 +84,7 @@ def _get_debug_info() -> _Environment: Environment information. """ py_name, py_version = _interpreter_name_version() - packages = ["griffelib"] + packages = ["griffelib", "griffe"] variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("GRIFFE")]] return _Environment( interpreter_name=py_name,