From 8239fd9508ccedd15a6e8c3a8183c7cff7e2e755 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 29 Nov 2025 16:42:54 +0100 Subject: [PATCH 01/59] 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 8013bf80..1e243175 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/59] 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 1e243175..08cc8f64 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/59] 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 7db748bf..6f57222a 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 0a52cb72..7277e2d6 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 24e72b70..554a88f7 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 d3dbca7a..b7968a72 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 fbfb72d3..c8c1d730 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 61ff9ddb..10ea7f78 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 edd5a94e..1719a14f 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 9594fafd..85c9d980 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 9aa40873..1f9dd191 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 fef3d12e..70ebb6c0 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 87be9621..cfb0bf59 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 5c03e5cf..ddfb4794 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 5fde20b4..9c827940 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 b0fe8da5..ffde3455 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 62091780..06a98a04 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 75a1a0ab..a0cb2559 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 9a0d1cbb..c7b525c9 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 6adcfb4e..ddc9e840 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 efb9818a..79b1851a 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 a7226fa6..bf16b1fc 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 55869f3c..4039ad3c 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 ca7f50c4..c4b78f9c 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 9caa656e..a30110d5 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 08e83a31..c806e83c 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 17f3bdfd..ff4b97a2 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 625d1dbb..e4345ba7 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 e33a1007..8630c15e 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 3b010a5d..4b3395c3 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 42ee96a8..8ae74620 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 54c452e3..f79f9256 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 74e44d05..4267786d 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 b3eb060c..10dccf38 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 0ba1d0db..2611b9c2 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 3b7f3531..76732f91 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 df1419cc..ae146795 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 89abf00d..2ca25220 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 f6720d4b..2bcc0142 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 20003780..ffe172dd 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 ea42941f..39a74357 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 367d906d..8033a7f5 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 c9fff7b4..2ac8a7b7 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 dd26177b..e6b34221 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 516d86eb..dfdb081f 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 2af3ca51..7b76c441 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 d3f1178c..a2f8d7d6 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 00000000..26726d5f --- /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 00000000..54cec7a6 --- /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 00000000..0374dbb7 --- /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 1f6c767f..708b8ac3 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 00000000..aba09f22 --- /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 00000000..e3db6aa8 --- /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 1ff89bfe..7eb5df5c 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 9cb26148..778fd75e 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 d726e9c0..657c752e 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 c194d07b..25b5cf1b 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 b6b6f445..349be63d 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 b63d4f9c..693a82a8 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 63941f82..89465b97 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 7cad06dd..f1a9e18f 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 787f57a7..9927855a 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 8f3ca86d..7f8ea269 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 59e98f08..46f4645d 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 ea582f91..e7643f29 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 42dd73b5..5924c892 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 545ea78d..ce444eb8 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 080b7f63..33550e50 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 bb91f600..f24ff1f7 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 743aa42f..f11fa5e7 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 4c67069b..5d2423cf 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 3f148dff..fca73bd8 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 4d104aa8..3b864f7a 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 702bc56a..512f2f83 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 08cc8f64..879bf23a 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 5e6fa7b0..100b858a 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 162cbbf6..d228c9d3 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 23bc3be2..b2e38ef6 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 47642c00..2ee41d42 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 b75b44ee..4144357c 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 b2a2d45b..ba9c6edd 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 6a7290fc..3e598a75 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 798ebf08..d95eaa1d 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 05d69414..b7455674 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 9cc60e17..fde780f6 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 957cc5c8..59400a51 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 91244705..1383bc7a 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 f33dc1fc..3a2fff8c 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 150eba04..a1fb98dc 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 a33860ef..7f84671a 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 c06aad3a..a48bb5aa 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 a9047c9b..3b5ca458 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 47613ddd..1ca06eae 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 0cd72b0a..cc6c0ad3 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 a71507a7..c500a3ac 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 366727ce..c37dfda5 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 0af072c6..0685fd73 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 344856e5..2cbe608c 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 90279e4d..738cf01a 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 7ca78dee..5f5caa7a 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 9b6d3407..c24c4622 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/59] 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/59] 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 26726d5f..7d4fe1dc 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 54cec7a6..b7c23fc1 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 0374dbb7..22d5b744 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 708b8ac3..b13154dc 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 aba09f22..3e608fcd 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 e3db6aa8..7e9f74d4 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 3e598a75..4a7d4577 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 3a2fff8c..67943ec8 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 a48bb5aa..6884c3c2 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/59] 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 7277e2d6..462ddcbc 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 00000000..4e283f85 --- /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 879bf23a..c51893ee 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 fde780f6..50a38814 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 6884c3c2..09ddc836 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 3b5ca458..30c64ab2 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 c500a3ac..fde01915 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 b8d3eeb4..93868819 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 c24c4622..d65c492f 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/59] 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 7d4fe1dc..69ab1f99 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 4e283f85..03d25ad8 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 3e608fcd..b01dfcde 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/59] 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 67943ec8..a044411e 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/59] 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 69ab1f99..6a9af0fc 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 a044411e..3bddfc0d 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/59] 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/59] 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 554a88f7..24e72b70 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 b7968a72..d3dbca7a 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 c8c1d730..fbfb72d3 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 10ea7f78..61ff9ddb 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 1719a14f..edd5a94e 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 62d2ff5f..0e6064a4 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 85c9d980..9594fafd 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 1f9dd191..9aa40873 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 70ebb6c0..fef3d12e 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 cfb0bf59..87be9621 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 ddfb4794..5c03e5cf 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 9c827940..5fde20b4 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 ffde3455..b0fe8da5 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 06a98a04..62091780 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 a0cb2559..75a1a0ab 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 c7b525c9..9a0d1cbb 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 ddc9e840..6adcfb4e 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 79b1851a..efb9818a 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 531dcab2..e0c69a8d 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 bf16b1fc..a7226fa6 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 4039ad3c..55869f3c 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 c4b78f9c..22442669 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 a30110d5..9caa656e 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 c806e83c..08e83a31 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 ff4b97a2..17f3bdfd 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 e4345ba7..625d1dbb 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 8630c15e..e33a1007 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 4b3395c3..3b010a5d 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 8ae74620..42ee96a8 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 f79f9256..54c452e3 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 00000000..7abc81fc --- /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 4267786d..74e44d05 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 10dccf38..b3eb060c 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 2611b9c2..0ba1d0db 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 76732f91..3b7f3531 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 ae146795..df1419cc 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 2ca25220..89abf00d 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 2bcc0142..f6720d4b 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 ffe172dd..20003780 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 39a74357..ea42941f 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 8033a7f5..367d906d 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 2ac8a7b7..c9fff7b4 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 e6b34221..dd26177b 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 dfdb081f..516d86eb 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 7b76c441..2af3ca51 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 b13154dc..a78a52fb 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 3bddfc0d..77f2bc30 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/59] 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 fbfb72d3..27b391e8 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 edd5a94e..3fc474e7 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 62091780..4bbd1c12 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 75a1a0ab..1d1c169f 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 3b010a5d..d91795c7 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/59] 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 0e6064a4..70fde110 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 22442669..ca7f50c4 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 7abc81fc..00000000 --- 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/59] 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 cc6c0ad3..0cd72b0a 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/59] 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 6a9af0fc..b9a6525f 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 b01dfcde..e445c11e 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/59] 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 e0c69a8d..fd61e9b1 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/59] 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 ca7f50c4..c977ebe2 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 08e83a31..8d4d2714 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/59] 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 a7226fa6..91d99cc8 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/59] 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 1d1c169f..d849cc4a 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 b3eb060c..10dccf38 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 7eb5df5c..4b460149 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 f1a9e18f..2771f148 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 46f4645d..2c658951 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 e7643f29..2de048df 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 fca73bd8..84f48fc9 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 512f2f83..c9df6bfe 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 b2e38ef6..9177a91b 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 2ee41d42..e8cca7ac 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 4144357c..b75b44ee 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 ba9c6edd..db723032 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 50a38814..cc1ac0e5 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 a1fb98dc..150eba04 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 0685fd73..0af072c6 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 2cbe608c..344856e5 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 738cf01a..90279e4d 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/59] 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 462ddcbc..5b180883 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 27b391e8..fbfb72d3 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 3fc474e7..28aa1cd8 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 4bbd1c12..62091780 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 d849cc4a..db3bc48c 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 91d99cc8..a7226fa6 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 c977ebe2..ca7f50c4 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 d91795c7..3b010a5d 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 10dccf38..b3eb060c 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 a2f8d7d6..d3f1178c 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 0ca19294..52e13013 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 a78a52fb..5bd46fcc 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 7e9f74d4..1a892c1f 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 30c64ab2..8d31f600 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 4b460149..1ff89bfe 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 778fd75e..9cb26148 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 657c752e..d726e9c0 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 25b5cf1b..c194d07b 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 349be63d..b6b6f445 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 693a82a8..b63d4f9c 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 89465b97..63941f82 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 2771f148..7cad06dd 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 9927855a..787f57a7 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 7f8ea269..5201db93 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 2c658951..59e98f08 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 2de048df..ea582f91 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 5924c892..42dd73b5 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 ce444eb8..545ea78d 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 33550e50..080b7f63 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 f24ff1f7..bb91f600 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 f11fa5e7..743aa42f 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 5d2423cf..4c67069b 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 84f48fc9..3f148dff 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 3b864f7a..4d104aa8 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 c9df6bfe..702bc56a 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 c51893ee..8013bf80 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 100b858a..5e6fa7b0 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 d228c9d3..162cbbf6 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 9177a91b..3960e147 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 e8cca7ac..47642c00 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 db723032..b2a2d45b 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 d95eaa1d..798ebf08 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 b7455674..05d69414 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 cc1ac0e5..9cc60e17 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 59400a51..957cc5c8 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 1383bc7a..91244705 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 7f84671a..85d07a00 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 09ddc836..00000000 --- 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 e69de29b..00000000 diff --git a/tests/helpers.py b/tests/helpers.py index 1ca06eae..47613ddd 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 fde01915..ae2d5b57 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 c37dfda5..366727ce 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 93868819..b8d3eeb4 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 5f5caa7a..7ca78dee 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 d65c492f..9b6d3407 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/59] 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 e445c11e..58b03c3b 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 77f2bc30..2eabbee5 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/59] 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 8d4d2714..c806e83c 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 d3f1178c..873f73c7 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 1a892c1f..da751a3d 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 8d31f600..e3bb8a89 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 3960e147..69c29da4 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 0cd72b0a..d74b6c2b 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 9b6d3407..26b6e81c 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/59] 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 6f57222a..728a0ebb 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/59] 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 5b180883..9cb74412 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/59] 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 db3bc48c..75a1a0ab 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/59] 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 0ba1d0db..afb2b220 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/59] 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 da751a3d..6a1f0d95 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/59] 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 6a1f0d95..eb446e27 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/59] 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 eb446e27..e6d84fc9 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 d74b6c2b..b0ef1b36 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/59] 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 e6d84fc9..3447acb5 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/59] 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 b0ef1b36..d02156b1 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/59] Update paths to inventories --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 52e13013..08da1383 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/59] 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 3447acb5..ab0c6e23 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/59] Fix inventory paths again --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 08da1383..2c856afd 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/59] 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 d02156b1..657c3d9e 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/59] 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 ab0c6e23..cbc9feb1 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 657c3d9e..0f3c3b9c 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/59] More descriptive duty names --- duties.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/duties.py b/duties.py index 873f73c7..ff244d2f 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/59] 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 cbc9feb1..fd8b8230 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 0f3c3b9c..6205a439 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/59] 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 6205a439..fb7a3b07 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/59] 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 fb7a3b07..571f7020 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/59] 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 fd8b8230..82e8fe29 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 571f7020..96da3d03 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/59] 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 96da3d03..08ff85f2 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/59] 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 08ff85f2..3568834c 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/59] 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 3568834c..0cf2201b 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/59] 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 b9a6525f..db53ef71 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 58b03c3b..ad9954b4 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/59] 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 4a7d4577..6a7290fc 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/59] 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 28aa1cd8..ab9d2883 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 fd61e9b1..28b439af 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/59] 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 69c29da4..b3b6bc7d 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/59] 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 ab9d2883..75847068 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 28b439af..062b265d 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 82e8fe29..eef5da28 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 b3b6bc7d..5132b35a 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/59] 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 5132b35a..0d270e4f 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/59] 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 db53ef71..7cb4066a 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 ad9954b4..67d9e169 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/59] 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 0d270e4f..951d299a 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/59] 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 5201db93..aaa07ac5 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, From ae5672b1b673c3d5cdc7d6418333f9c82413f483 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 1 Feb 2026 09:05:45 +0100 Subject: [PATCH 54/59] Remove hardcoded part from finder logic --- 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 951d299a..0d270e4f 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, "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 dc6a2704fbfb908f277495c5f377b10431e621c4 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 1 Feb 2026 09:10:36 +0100 Subject: [PATCH 55/59] Fix `test_meson_python_file_handling` --- tests/test_finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_finder.py b/tests/test_finder.py index 26b6e81c..c8849e6d 100644 --- a/tests/test_finder.py +++ b/tests/test_finder.py @@ -191,7 +191,7 @@ def test_meson_python_file_handling(tmp_path: Path) -> None: pth_file = tmp_path / "_whatever_editable_loader.py" pth_file.write_text( # The path in argument 2 suffixed with src must exist, so we pass `.`. - "hello=1\ninstall({'griffe', 'hello'}, '.', ['/tmp/ninja'], False)", + "hello=1\ninstall({'griffe', 'hello'}, 'packages/griffelib', ['/tmp/ninja'], False)", encoding="utf8", ) search_paths = _handle_editable_module(pth_file) From c08cc96cd18952be568f3920cc2abb16d3849e03 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 1 Feb 2026 09:13:19 +0100 Subject: [PATCH 56/59] Add more packages to debug info --- 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 aaa07ac5..ecd625b9 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", "griffe"] + packages = ["griffelib", "griffecli", "griffe"] variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("GRIFFE")]] return _Environment( interpreter_name=py_name, From fa3ed5c571e8be223762fe6c37f1cd758af0b96c Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 1 Feb 2026 09:36:34 +0100 Subject: [PATCH 57/59] Workaround UP007 --- config/ruff.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/ruff.toml b/config/ruff.toml index 9cb74412..02c9a73f 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -33,6 +33,7 @@ ignore = [ "TD002", # Missing author in TODO "TD003", # Missing issue link on the line following this TODO "TRY003", # Avoid specifying long messages outside the exception class + "UP007", # Use `X | Y` for type annotations ] logger-objects = ["griffe.logger"] From e46a7a06ebc3225cf7e247e20c10715b292249e1 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 1 Feb 2026 09:44:55 +0100 Subject: [PATCH 58/59] Workaround an unrelated typing problem --- scripts/gen_credits.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/gen_credits.py b/scripts/gen_credits.py index 7eb3fbab..cbfe0c17 100644 --- a/scripts/gen_credits.py +++ b/scripts/gen_credits.py @@ -55,7 +55,11 @@ def _extra_marker(req: Requirement) -> str | None: if not req.marker: return None try: - return next(marker[2].value for marker in req.marker._markers if getattr(marker[0], "value", None) == "extra") + return next( + marker[2].value # type: ignore[union-attr] + for marker in req.marker._markers + if getattr(marker[0], "value", None) == "extra" + ) except StopIteration: return None From 102affa32cfdb482d5b13f81047f5b2033d981a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Sun, 1 Feb 2026 21:53:38 +0100 Subject: [PATCH 59/59] Fix comment in test --- tests/test_finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_finder.py b/tests/test_finder.py index c8849e6d..c45ff0ce 100644 --- a/tests/test_finder.py +++ b/tests/test_finder.py @@ -190,7 +190,7 @@ def test_meson_python_file_handling(tmp_path: Path) -> None: """ pth_file = tmp_path / "_whatever_editable_loader.py" pth_file.write_text( - # The path in argument 2 suffixed with src must exist, so we pass `.`. + # The path in argument 2 suffixed with src must exist, so we pass `packages/griffelib`. "hello=1\ninstall({'griffe', 'hello'}, 'packages/griffelib', ['/tmp/ninja'], False)", encoding="utf8", )