griffe 2.0.2__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {griffe-2.0.2 → griffe-2.2.0}/CHANGELOG.md +35 -0
- {griffe-2.0.2 → griffe-2.2.0}/PKG-INFO +7 -9
- {griffe-2.0.2 → griffe-2.2.0}/README.md +2 -4
- {griffe-2.0.2 → griffe-2.2.0}/config/coverage.ini +4 -3
- {griffe-2.0.2 → griffe-2.2.0}/config/pytest.ini +2 -3
- {griffe-2.0.2 → griffe-2.2.0}/config/ruff.toml +6 -4
- griffe-2.2.0/config/ty.toml +9 -0
- {griffe-2.0.2 → griffe-2.2.0}/config/vscode/launch.json +1 -2
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/built-in/dataclasses.md +1 -1
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official.md +4 -4
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors/architecture.md +2 -1
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/checking.md +35 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/set-docstring-styles.md +1 -1
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/support-decorators.md +3 -3
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/navigating.md +3 -3
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/recommendations/public-apis.md +16 -10
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/docstrings.md +1 -1
- {griffe-2.0.2 → griffe-2.2.0}/duties.py +19 -4
- {griffe-2.0.2 → griffe-2.2.0}/pyproject.toml +1 -1
- {griffe-2.0.2 → griffe-2.2.0}/scripts/gen_credits.py +16 -0
- griffe-2.2.0/scripts/gen_griffe_json.py +25 -0
- {griffe-2.0.2 → griffe-2.2.0}/scripts/gen_structure_docs.py +18 -2
- {griffe-2.0.2 → griffe-2.2.0}/scripts/get_version.py +17 -1
- {griffe-2.0.2 → griffe-2.2.0}/scripts/make.py +16 -0
- griffe-2.0.2/config/ty.toml +0 -6
- griffe-2.0.2/scripts/gen_griffe_json.py +0 -9
- griffe-2.0.2/tests/__init__.py +0 -9
- griffe-2.0.2/tests/conftest.py +0 -17
- griffe-2.0.2/tests/fixtures/_repo/v0.1.0/my_module/__init__.py +0 -1
- griffe-2.0.2/tests/fixtures/_repo/v0.2.0/my_module/__init__.py +0 -1
- griffe-2.0.2/tests/helpers.py +0 -33
- griffe-2.0.2/tests/test_api.py +0 -227
- griffe-2.0.2/tests/test_cli.py +0 -57
- griffe-2.0.2/tests/test_diff.py +0 -213
- griffe-2.0.2/tests/test_docstrings/__init__.py +0 -1
- griffe-2.0.2/tests/test_docstrings/conftest.py +0 -43
- griffe-2.0.2/tests/test_docstrings/helpers.py +0 -73
- griffe-2.0.2/tests/test_docstrings/test_google.py +0 -1931
- griffe-2.0.2/tests/test_docstrings/test_numpy.py +0 -1373
- griffe-2.0.2/tests/test_docstrings/test_sphinx.py +0 -1313
- griffe-2.0.2/tests/test_docstrings/test_warnings.py +0 -25
- griffe-2.0.2/tests/test_encoders.py +0 -211
- griffe-2.0.2/tests/test_expressions.py +0 -243
- griffe-2.0.2/tests/test_extensions/__init__.py +0 -1
- griffe-2.0.2/tests/test_extensions/test_base.py +0 -292
- griffe-2.0.2/tests/test_extensions/test_dataclasses.py +0 -170
- griffe-2.0.2/tests/test_extensions/test_unpack_typeddict.py +0 -253
- griffe-2.0.2/tests/test_finder.py +0 -326
- griffe-2.0.2/tests/test_functions.py +0 -142
- griffe-2.0.2/tests/test_git.py +0 -104
- griffe-2.0.2/tests/test_inheritance.py +0 -180
- griffe-2.0.2/tests/test_inspector.py +0 -344
- griffe-2.0.2/tests/test_loader.py +0 -538
- griffe-2.0.2/tests/test_merger.py +0 -97
- griffe-2.0.2/tests/test_mixins.py +0 -13
- griffe-2.0.2/tests/test_models.py +0 -662
- griffe-2.0.2/tests/test_nodes.py +0 -281
- griffe-2.0.2/tests/test_public_api.py +0 -23
- griffe-2.0.2/tests/test_stdlib.py +0 -50
- griffe-2.0.2/tests/test_visitor.py +0 -499
- {griffe-2.0.2 → griffe-2.2.0}/.gitignore +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/CODE_OF_CONDUCT.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/CONTRIBUTING.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/LICENSE +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/config/git-changelog.toml +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/config/vscode/settings.json +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/config/vscode/tasks.json +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/.overrides/main.html +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/.overrides/partials/comments.html +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/.overrides/partials/path-item.html +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/alternatives.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/changelog.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/code-of-conduct.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/community.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/contributing.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/credits.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/css/custom.css +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/css/material.css +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/css/mkdocstrings.css +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/downstream-projects.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/built-in/unpack-typeddict.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/built-in.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/autodocstringstyle.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/inherited-docstrings.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/public-redundant-aliases.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/public-wildcard-imports.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/pydantic.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/runtime-objects.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/sphinx.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/typingdoc.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/warnings-deprecated.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/docstring-inheritance.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/fastapi.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/fieldz.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/generics.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/inherited-method-crossrefs.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/modernized-annotations.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/extensions.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/getting-help.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/getting-started.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors/commands.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors/setup.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors/workflow.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/extending.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/parse-docstrings.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/selectively-inspect.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/set-git-info.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/loading.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/recommendations/docstrings.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/recommendations/python-code.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/serializing.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/guide.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/img/favicon.ico +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/img/gha_annotations_1.png +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/img/gha_annotations_2.png +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/index.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/installation.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/introduction.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/js/feedback.js +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/license.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/logo.svg +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/playground.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/agents.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/checks.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/cli.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/docstrings/models.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/docstrings/parsers.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/docstrings.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/exceptions.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/expressions.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/extensions.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/finder.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/helpers.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/loaders.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/loggers.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/alias.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/attribute.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/class.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/function.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/module.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/type_alias.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/serializers.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference/cli.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/reference.md +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/schema-docstrings-options.json +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/docs/schema.json +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/mkdocs.yml +0 -0
- {griffe-2.0.2 → griffe-2.2.0}/scripts/make +0 -0
|
@@ -5,6 +5,41 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
7
|
<!-- insertion marker -->
|
|
8
|
+
## [2.2.0](https://github.com/mkdocstrings/griffe/releases/tag/2.2.0) - 2026-08-16
|
|
9
|
+
|
|
10
|
+
<small>[Compare with 2.1.0](https://github.com/mkdocstrings/griffe/compare/2.1.0...2.2.0)</small>
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- Support `await` expressions ([6b3caab](https://github.com/mkdocstrings/griffe/commit/6b3caab7ce4fdcb1c9386937dad17510d35a3321) by Vincent Gao). [PR-479](https://github.com/mkdocstrings/griffe/pull/479)
|
|
15
|
+
- Support unpacking in dict comprehensions ([2d39391](https://github.com/mkdocstrings/griffe/commit/2d39391cb135febadf339bdea91c1113b74da145) by mushitoriami). [PR-475](https://github.com/mkdocstrings/griffe/pull/475)
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
- Forward `warn_missing_types` to Sphinx return section reader ([a15e782](https://github.com/mkdocstrings/griffe/commit/a15e782ed0793e06d22105beb016c10cfe0ed4b0) by Timothée Mazzucotelli). [Issue-mkdocstrings-python-337](https://github.com/mkdocstrings/python/issues/337)
|
|
20
|
+
- Make stringified expressions valid and faithful Python ([eb85f0d](https://github.com/mkdocstrings/griffe/commit/eb85f0dd8bf49f4a2400bf03face646d8f533a7c) by Vincent Gao). [PR-478](https://github.com/mkdocstrings/griffe/pull/478)
|
|
21
|
+
- Empty tuples can never be implicit ([82e728d](https://github.com/mkdocstrings/griffe/commit/82e728dc758f9635d2e500c13caa795b48e36d8a) by Vincent Gao). [PR-474](https://github.com/mkdocstrings/griffe/pull/474), Co-authored-by: Timothée Mazzucotelli <dev@pawamoy.fr>
|
|
22
|
+
- Render f-strings and t-strings with correct quote delimiters ([90e28d4](https://github.com/mkdocstrings/griffe/commit/90e28d45ffc998434895c0f73af608cb12f0d6dd) by Bartosz Sławecki). [Issue-444](https://github.com/mkdocstrings/griffe/issues/444), [PR-455](https://github.com/mkdocstrings/griffe/pull/455)
|
|
23
|
+
- Detect basic admonitions 'example', 'note' and 'warning' in Google/Numpy docstrings when inferring style ([f30306f](https://github.com/mkdocstrings/griffe/commit/f30306fa703741f976fc49576ddf95cf29ba998b) by Timothée Mazzucotelli).
|
|
24
|
+
- Render dict `**`-unpacking as `**value` instead of `None: value` ([74ddbbf](https://github.com/mkdocstrings/griffe/commit/74ddbbf22f49e1fb789ac754e3fff41a0ac2f152) by Vincent Gao). [PR-467](https://github.com/mkdocstrings/griffe/pull/467)
|
|
25
|
+
|
|
26
|
+
## [2.1.0](https://github.com/mkdocstrings/griffe/releases/tag/2.1.0) - 2026-06-19
|
|
27
|
+
|
|
28
|
+
<small>[Compare with 2.0.2](https://github.com/mkdocstrings/griffe/compare/2.0.2...2.1.0)</small>
|
|
29
|
+
|
|
30
|
+
### Build
|
|
31
|
+
|
|
32
|
+
- Add tests to source distributions for `griffecli` and `griffelib` packages. [Issue-452](https://github.com/mkdocstrings/griffe/issues/452)
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
|
|
36
|
+
- Add logging format for Azure Devops ([82526e4](https://github.com/mkdocstrings/griffe/commit/82526e487946f838c2521e531ef8716dd12d4eea) by Carsten Igel). [PR-457](https://github.com/mkdocstrings/griffe/pull/457), Co-authored-by: Timothée Mazzucotelli <dev@pawamoy.fr>
|
|
37
|
+
|
|
38
|
+
### Bug Fixes
|
|
39
|
+
|
|
40
|
+
- Rename tests module to avoid exclusion by packagers ([5b3e392](https://github.com/mkdocstrings/griffe/commit/5b3e392006da98d5f23ba0e808393038be6014d8) by Timothée Mazzucotelli). [Issue-461](https://github.com/mkdocstrings/griffe/issues/461)
|
|
41
|
+
- Don't try merging overload annotations into non-function objects ([1b6b053](https://github.com/mkdocstrings/griffe/commit/1b6b053dc4cfdc4381a9dc4b0676b7946e55951e) by Timothée Mazzucotelli). [Issue-451](https://github.com/mkdocstrings/griffe/discussions/451)
|
|
42
|
+
|
|
8
43
|
## [2.0.2](https://github.com/mkdocstrings/griffe/releases/tag/2.0.2) - 2026-03-27
|
|
9
44
|
|
|
10
45
|
<small>[Compare with 2.0.1](https://github.com/mkdocstrings/griffe/compare/2.0.1...2.0.2)</small>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: griffe
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: 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.
|
|
5
5
|
Project-URL: Homepage, https://mkdocstrings.github.io/griffe
|
|
6
6
|
Project-URL: Documentation, https://mkdocstrings.github.io/griffe
|
|
@@ -30,10 +30,10 @@ Classifier: Topic :: Software Development :: Documentation
|
|
|
30
30
|
Classifier: Topic :: Utilities
|
|
31
31
|
Classifier: Typing :: Typed
|
|
32
32
|
Requires-Python: >=3.10
|
|
33
|
-
Requires-Dist: griffecli==2.0
|
|
34
|
-
Requires-Dist: griffelib==2.0
|
|
33
|
+
Requires-Dist: griffecli==2.2.0
|
|
34
|
+
Requires-Dist: griffelib==2.2.0
|
|
35
35
|
Provides-Extra: pypi
|
|
36
|
-
Requires-Dist: griffelib[pypi]==2.0
|
|
36
|
+
Requires-Dist: griffelib[pypi]==2.2.0; extra == 'pypi'
|
|
37
37
|
Description-Content-Type: text/markdown
|
|
38
38
|
|
|
39
39
|
# Griffe
|
|
@@ -181,7 +181,7 @@ See the [Loading chapter](https://mkdocstrings.github.io/griffe/guide/users/load
|
|
|
181
181
|
<a href="https://github.com/BenHammersley"><img alt="BenHammersley" src="https://avatars.githubusercontent.com/u/99436?u=4499a7b507541045222ee28ae122dbe3c8d08ab5&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
182
182
|
<a href="https://github.com/trevorWieland"><img alt="trevorWieland" src="https://avatars.githubusercontent.com/u/28811461?u=74cc0e3756c1d4e3d66b5c396e1d131ea8a10472&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
183
183
|
<a href="https://github.com/MarcoGorelli"><img alt="MarcoGorelli" src="https://avatars.githubusercontent.com/u/33491632?u=7de3a749cac76a60baca9777baf71d043a4f884d&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
184
|
-
<a href="https://github.com/analog-cbarber"><img alt="analog-cbarber" src="https://avatars.githubusercontent.com/u/7408243?u=
|
|
184
|
+
<a href="https://github.com/analog-cbarber"><img alt="analog-cbarber" src="https://avatars.githubusercontent.com/u/7408243?u=fe0e7bf2882d1c9c901a341c2502e1518466527a&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
185
185
|
<a href="https://github.com/OdinManiac"><img alt="OdinManiac" src="https://avatars.githubusercontent.com/u/22727172?u=36ab20970f7f52ae8e7eb67b7fcf491fee01ac22&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
186
186
|
<a href="https://github.com/rstudio-sponsorship"><img alt="rstudio-sponsorship" src="https://avatars.githubusercontent.com/u/58949051?u=0c471515dd18111be30dfb7669ed5e778970959b&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
187
187
|
<a href="https://github.com/schlich"><img alt="schlich" src="https://avatars.githubusercontent.com/u/21191435?u=6f1240adb68f21614d809ae52d66509f46b1e877&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
@@ -193,17 +193,15 @@ See the [Loading chapter](https://mkdocstrings.github.io/griffe/guide/users/load
|
|
|
193
193
|
<a href="https://github.com/activeloopai"><img alt="activeloopai" src="https://avatars.githubusercontent.com/u/34816118?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
194
194
|
<a href="https://github.com/roboflow"><img alt="roboflow" src="https://avatars.githubusercontent.com/u/53104118?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
195
195
|
<a href="https://github.com/cmclaughlin"><img alt="cmclaughlin" src="https://avatars.githubusercontent.com/u/1061109?u=ddf6eec0edd2d11c980f8c3aa96e3d044d4e0468&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
196
|
-
<a href="https://github.com/blaisep"><img alt="blaisep" src="https://avatars.githubusercontent.com/u/254456?u=97d584b7c0a6faf583aa59975df4f993f671d121&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
197
196
|
<a href="https://github.com/RapidataAI"><img alt="RapidataAI" src="https://avatars.githubusercontent.com/u/104209891?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
198
197
|
<a href="https://github.com/rodolphebarbanneau"><img alt="rodolphebarbanneau" src="https://avatars.githubusercontent.com/u/46493454?u=6c405452a40c231cdf0b68e97544e07ee956a733&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
199
198
|
<a href="https://github.com/theSymbolSyndicate"><img alt="theSymbolSyndicate" src="https://avatars.githubusercontent.com/u/111542255?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
200
199
|
<a href="https://github.com/blakeNaccarato"><img alt="blakeNaccarato" src="https://avatars.githubusercontent.com/u/20692450?u=bb919218be30cfa994514f4cf39bb2f7cf952df4&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
201
200
|
<a href="https://github.com/ChargeStorm"><img alt="ChargeStorm" src="https://avatars.githubusercontent.com/u/26000165?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
202
|
-
<a href="https://github.com/Alphadelta14"><img alt="Alphadelta14" src="https://avatars.githubusercontent.com/u/480845?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
203
201
|
<a href="https://github.com/Cusp-AI"><img alt="Cusp-AI" src="https://avatars.githubusercontent.com/u/178170649?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
204
202
|
</p></div>
|
|
205
203
|
|
|
206
204
|
|
|
207
|
-
*And
|
|
205
|
+
*And 4 more private sponsor(s).*
|
|
208
206
|
|
|
209
207
|
<!-- sponsors-end -->
|
|
@@ -143,7 +143,7 @@ See the [Loading chapter](https://mkdocstrings.github.io/griffe/guide/users/load
|
|
|
143
143
|
<a href="https://github.com/BenHammersley"><img alt="BenHammersley" src="https://avatars.githubusercontent.com/u/99436?u=4499a7b507541045222ee28ae122dbe3c8d08ab5&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
144
144
|
<a href="https://github.com/trevorWieland"><img alt="trevorWieland" src="https://avatars.githubusercontent.com/u/28811461?u=74cc0e3756c1d4e3d66b5c396e1d131ea8a10472&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
145
145
|
<a href="https://github.com/MarcoGorelli"><img alt="MarcoGorelli" src="https://avatars.githubusercontent.com/u/33491632?u=7de3a749cac76a60baca9777baf71d043a4f884d&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
146
|
-
<a href="https://github.com/analog-cbarber"><img alt="analog-cbarber" src="https://avatars.githubusercontent.com/u/7408243?u=
|
|
146
|
+
<a href="https://github.com/analog-cbarber"><img alt="analog-cbarber" src="https://avatars.githubusercontent.com/u/7408243?u=fe0e7bf2882d1c9c901a341c2502e1518466527a&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
147
147
|
<a href="https://github.com/OdinManiac"><img alt="OdinManiac" src="https://avatars.githubusercontent.com/u/22727172?u=36ab20970f7f52ae8e7eb67b7fcf491fee01ac22&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
148
148
|
<a href="https://github.com/rstudio-sponsorship"><img alt="rstudio-sponsorship" src="https://avatars.githubusercontent.com/u/58949051?u=0c471515dd18111be30dfb7669ed5e778970959b&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
149
149
|
<a href="https://github.com/schlich"><img alt="schlich" src="https://avatars.githubusercontent.com/u/21191435?u=6f1240adb68f21614d809ae52d66509f46b1e877&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
@@ -155,17 +155,15 @@ See the [Loading chapter](https://mkdocstrings.github.io/griffe/guide/users/load
|
|
|
155
155
|
<a href="https://github.com/activeloopai"><img alt="activeloopai" src="https://avatars.githubusercontent.com/u/34816118?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
156
156
|
<a href="https://github.com/roboflow"><img alt="roboflow" src="https://avatars.githubusercontent.com/u/53104118?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
157
157
|
<a href="https://github.com/cmclaughlin"><img alt="cmclaughlin" src="https://avatars.githubusercontent.com/u/1061109?u=ddf6eec0edd2d11c980f8c3aa96e3d044d4e0468&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
158
|
-
<a href="https://github.com/blaisep"><img alt="blaisep" src="https://avatars.githubusercontent.com/u/254456?u=97d584b7c0a6faf583aa59975df4f993f671d121&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
159
158
|
<a href="https://github.com/RapidataAI"><img alt="RapidataAI" src="https://avatars.githubusercontent.com/u/104209891?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
160
159
|
<a href="https://github.com/rodolphebarbanneau"><img alt="rodolphebarbanneau" src="https://avatars.githubusercontent.com/u/46493454?u=6c405452a40c231cdf0b68e97544e07ee956a733&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
161
160
|
<a href="https://github.com/theSymbolSyndicate"><img alt="theSymbolSyndicate" src="https://avatars.githubusercontent.com/u/111542255?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
162
161
|
<a href="https://github.com/blakeNaccarato"><img alt="blakeNaccarato" src="https://avatars.githubusercontent.com/u/20692450?u=bb919218be30cfa994514f4cf39bb2f7cf952df4&v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
163
162
|
<a href="https://github.com/ChargeStorm"><img alt="ChargeStorm" src="https://avatars.githubusercontent.com/u/26000165?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
164
|
-
<a href="https://github.com/Alphadelta14"><img alt="Alphadelta14" src="https://avatars.githubusercontent.com/u/480845?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
165
163
|
<a href="https://github.com/Cusp-AI"><img alt="Cusp-AI" src="https://avatars.githubusercontent.com/u/178170649?v=4" style="height: 32px; border-radius: 100%;"></a>
|
|
166
164
|
</p></div>
|
|
167
165
|
|
|
168
166
|
|
|
169
|
-
*And
|
|
167
|
+
*And 4 more private sponsor(s).*
|
|
170
168
|
|
|
171
169
|
<!-- sponsors-end -->
|
|
@@ -4,7 +4,8 @@ parallel = true
|
|
|
4
4
|
source =
|
|
5
5
|
packages/griffelib/src/griffe
|
|
6
6
|
packages/griffecli/src/griffecli
|
|
7
|
-
tests/
|
|
7
|
+
packages/griffecli/tests/
|
|
8
|
+
packages/griffelib/tests/
|
|
8
9
|
|
|
9
10
|
[coverage:paths]
|
|
10
11
|
equivalent =
|
|
@@ -17,8 +18,8 @@ precision = 2
|
|
|
17
18
|
omit =
|
|
18
19
|
src/*/__init__.py
|
|
19
20
|
src/*/__main__.py
|
|
20
|
-
tests/__init__.py
|
|
21
|
-
tests/tmp/*
|
|
21
|
+
packages/*/tests/__init__.py
|
|
22
|
+
packages/*/tests/tmp/*
|
|
22
23
|
exclude_lines =
|
|
23
24
|
pragma: no cover
|
|
24
25
|
if TYPE_CHECKING
|
|
@@ -4,7 +4,7 @@ output-format = "concise"
|
|
|
4
4
|
|
|
5
5
|
[lint]
|
|
6
6
|
exclude = [
|
|
7
|
-
"tests/fixtures/*.py",
|
|
7
|
+
"packages/*/tests/fixtures/*.py",
|
|
8
8
|
]
|
|
9
9
|
select = ["ALL"]
|
|
10
10
|
ignore = [
|
|
@@ -65,12 +65,14 @@ logger-objects = ["griffe.logger"]
|
|
|
65
65
|
"INP001", # File is part of an implicit namespace package
|
|
66
66
|
"T201", # Print statement
|
|
67
67
|
]
|
|
68
|
-
"tests/test_git.py" = [
|
|
68
|
+
"packages/griffelib/tests/test_git.py" = [
|
|
69
69
|
"S603", # `subprocess` call: check for execution of untrusted input
|
|
70
70
|
"S607", # Starting a process with a partial executable path
|
|
71
71
|
]
|
|
72
|
-
"tests/**.py" = [
|
|
72
|
+
"packages/*/tests/**.py" = [
|
|
73
73
|
"ARG005", # Unused lambda argument
|
|
74
|
+
"D100", # Missing module docstring
|
|
75
|
+
"D104", # Missing package docstring
|
|
74
76
|
"FBT001", # Boolean positional arg in function definition
|
|
75
77
|
"PLC1901", # a == "" can be simplified to not a
|
|
76
78
|
"PLR2004", # Magic value used in comparison
|
|
@@ -91,7 +93,7 @@ convention = "google"
|
|
|
91
93
|
|
|
92
94
|
[format]
|
|
93
95
|
exclude = [
|
|
94
|
-
"tests/fixtures/*.py",
|
|
96
|
+
"packages/*/tests/fixtures/*.py",
|
|
95
97
|
]
|
|
96
98
|
docstring-code-format = true
|
|
97
99
|
docstring-code-line-length = 80
|
|
@@ -25,7 +25,7 @@ def __init__(self, uid: int, name: str, capacity: int = 10, available: bool = Tr
|
|
|
25
25
|
|
|
26
26
|
Additional metadata like `ClassVar`, the `init` and `kw_only` parameters, or the `KW_ONLY` sentinel are also recognized and will update the `__init__` method signature accordingly.
|
|
27
27
|
|
|
28
|
-
**This extension is enabled by default.** It is always added last. If you need to give it a higher priority, you can
|
|
28
|
+
**This extension is enabled by default.** It is always added last. If you need to give it a higher priority, you can explicitly enable it to change its position in the list of extensions (it will run only once):
|
|
29
29
|
|
|
30
30
|
=== "CLI"
|
|
31
31
|
```console
|
|
@@ -5,11 +5,11 @@ Official extensions are developed and maintained within the mkdocstrings organiz
|
|
|
5
5
|
Extension | Description
|
|
6
6
|
--------- | -----------
|
|
7
7
|
[`autodocstringstyle`](official/autodocstringstyle.md) | Set docstring style to `auto` for external packages.
|
|
8
|
-
|
|
8
|
+
[`inherited-docstrings`](official/inherited-docstrings.md) | Inherit docstrings from parent classes.
|
|
9
9
|
[`public-redundant-aliases`](official/public-redundant-aliases.md) | Mark objects imported with redundant aliases as public.
|
|
10
10
|
[`public-wildcard-imports`](official/public-wildcard-imports.md) | Mark wildcard imported objects as public.
|
|
11
|
-
|
|
11
|
+
[`pydantic`](official/pydantic.md) | Support for [Pydantic](https://docs.pydantic.dev/latest/) models.
|
|
12
12
|
[`runtime-objects`](official/runtime-objects.md) | Access runtime objects corresponding to each loaded Griffe object through their `extra` attribute.
|
|
13
13
|
[`sphinx`](official/sphinx.md) | Parse [Sphinx](https://www.sphinx-doc.org/)-comments above attributes (`#:`) as docstrings.
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
[`typing-doc`](official/typingdoc.md) | Support for [PEP 727](https://peps.python.org/pep-0727/)'s [`typing.Doc`][typing_extensions.Doc], "Documentation in Annotated Metadata".
|
|
15
|
+
[`warnings-deprecated`](official/warnings-deprecated.md) | Support for [PEP 702](https://peps.python.org/pep-0702/)'s [`warnings.deprecated`][], "Marking deprecations using the type system".
|
|
@@ -24,7 +24,8 @@ descriptions = {
|
|
|
24
24
|
"src": "The source of our Python package(s). See [Sources](#sources) and [Program structure](#program-structure).",
|
|
25
25
|
"src/griffe": "Our public API, exposed to users. See [Program structure](#program-structure).",
|
|
26
26
|
"packages/griffelib/src/griffe/_internal": "Our internal API, hidden from users. See [Program structure](#program-structure).",
|
|
27
|
-
"tests": "Our test suite. See [Tests](#tests).",
|
|
27
|
+
"packages/griffecli/tests": "Our test suite. See [Tests](#tests).",
|
|
28
|
+
"packages/griffelib/tests": "Our test suite. See [Tests](#tests).",
|
|
28
29
|
".copier-answers.yml": "The answers file generated by [Copier](https://copier.readthedocs.io/en/stable/). See [Boilerplate](#boilerplate).",
|
|
29
30
|
"devdeps.txt": "Our development dependencies specification. See [`make setup`][command-setup] command.",
|
|
30
31
|
"duties.py": "Our project tasks, written with [duty](https://pawamoy.github.io/duty). See [Tasks][tasks].",
|
|
@@ -115,6 +115,30 @@ jobs:
|
|
|
115
115
|
|
|
116
116
|
The last step will fail the workflow if any breaking change is found.
|
|
117
117
|
|
|
118
|
+
### Azure Pipelines {#ci-azdo}
|
|
119
|
+
|
|
120
|
+
Here is a quick example on how to use Griffe in an Azure Pipeline. Griffe can format its output using Azure DevOps [task logging commands](https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?view=azure-devops&tabs=bash#task-commands), similar to GitHub Actions messages:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
jobs:
|
|
124
|
+
- name: check-api
|
|
125
|
+
pool:
|
|
126
|
+
vmImage: 'ubuntu-latest'
|
|
127
|
+
steps:
|
|
128
|
+
- checkout: self
|
|
129
|
+
fetchDepth: 0 # We the need the full Git history.
|
|
130
|
+
- task: CmdLine@2
|
|
131
|
+
inputs:
|
|
132
|
+
script: pip install --user griffe
|
|
133
|
+
- task: CmdLine@2
|
|
134
|
+
inputs:
|
|
135
|
+
# The following command will compare current changes to latest tag.
|
|
136
|
+
script: |
|
|
137
|
+
griffe check --search src --format azdo your_package_name
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The last step will fail the workflow if any breaking change is found.
|
|
141
|
+
|
|
118
142
|
## Detected breakages
|
|
119
143
|
|
|
120
144
|
In this section, we will describe the breakages that Griffe detects, giving some code examples and hints on how to properly communicate breakages with deprecation messages before actually releasing them.
|
|
@@ -720,6 +744,17 @@ When running `griffe check` in CI, you can enable GitHub's annotations thanks to
|
|
|
720
744
|
::warning file=src/griffe/finder.py,line=77,title=NamespacePackage.path::Attribute value was changed: `path` -> unset
|
|
721
745
|
```
|
|
722
746
|
|
|
747
|
+
[](){#format-azdo}
|
|
748
|
+
|
|
749
|
+
### Azure DevOps / Azure Pipelines
|
|
750
|
+
|
|
751
|
+
- **CLI**: `-f azdo`
|
|
752
|
+
- **API**: `check(..., style="azdo")` / `check(..., style=ExplanationStyle.AZURE_DEVOPS)`
|
|
753
|
+
|
|
754
|
+
Similarly to the GitHub workflow syntax, Griffe is capable of using the task logging command syntax used by Azure Pipelines as part of the Azure DevOps Services.
|
|
755
|
+
|
|
756
|
+
When running `griffe check` in CI, warnings are displayed in the warnings panel of your pipeline.
|
|
757
|
+
|
|
723
758
|
## Next steps
|
|
724
759
|
|
|
725
760
|
If you are using a third-party library to mark objects as public, or if you follow conventions different than the one Griffe understands, you might get false-positives, or breaking changes could go undetected. In that case, you might be interested in [extending](extending.md) how Griffe loads API data to support these third-party libraries or other conventions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Setting the right docstring style for every docstring
|
|
2
2
|
|
|
3
|
-
Griffe attaches the specified docstring style and parsing options to each object in the tree of the package(s) you load. If your package(s) use several docstring styles, some of these objects will have the wrong style attached to them. This is problematic because other Griffe extensions rely on this attached style to parse docstrings and modify them. We plan to alleviate this limitation in the future (see [issue-340](https://github.com/mkdocstrings/griffe/issues/340)), but the most robust thing you can do is to make sure each object has the *right style* attached, as
|
|
3
|
+
Griffe attaches the specified docstring style and parsing options to each object in the tree of the package(s) you load. If your package(s) use several docstring styles, some of these objects will have the wrong style attached to them. This is problematic because other Griffe extensions rely on this attached style to parse docstrings and modify them. We plan to alleviate this limitation in the future (see [issue-340](https://github.com/mkdocstrings/griffe/issues/340)), but the most robust thing you can do is to make sure each object has the *right style* attached, as easily as possible, so that other extensions can work without issue.
|
|
4
4
|
|
|
5
5
|
There are currently two ways to make sure objects have the right docstring style attached as early as possible:
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ import griffe
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class MyDecorator(griffe.Extension):
|
|
28
|
-
"""An extension to
|
|
28
|
+
"""An extension to support my decorator."""
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
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`.
|
|
@@ -37,7 +37,7 @@ import griffe
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class MyDecorator(griffe.Extension):
|
|
40
|
-
"""An extension to
|
|
40
|
+
"""An extension to support my decorator."""
|
|
41
41
|
|
|
42
42
|
def on_function_instance(self, *, func: griffe.Function, **kwargs) -> None:
|
|
43
43
|
...
|
|
@@ -50,7 +50,7 @@ import griffe
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
class MyDecorator(griffe.Extension):
|
|
53
|
-
"""An extension to
|
|
53
|
+
"""An extension to support my decorator."""
|
|
54
54
|
|
|
55
55
|
def on_function_instance(self, *, func: griffe.Function, **kwargs) -> None:
|
|
56
56
|
for decorator in func.decorators:
|
|
@@ -89,13 +89,13 @@ To access an object's members, there are a few options:
|
|
|
89
89
|
|
|
90
90
|
The same way members are accessed, they can also be set:
|
|
91
91
|
|
|
92
|
-
- Dictionary-like item assignment: `markdown["thing"] = ...`, also supporting dotted-paths and string tuples. This will (re)assign only regular members: inherited members (classes only) are re-computed
|
|
92
|
+
- Dictionary-like item assignment: `markdown["thing"] = ...`, also supporting dotted-paths and string tuples. This will (re)assign only regular members: inherited members (classes only) are re-computed every time they are accessed.
|
|
93
93
|
- Safer method for extensions: `markdown.set_member("thing", ...)`, also supporting dotted-paths and string tuples.
|
|
94
94
|
- Regular member assignment: `markdown.members["thing"] = ...`. **This is not recommended, as the assigned member's `parent` attribute will not be automatically updated.**
|
|
95
95
|
|
|
96
96
|
...and deleted:
|
|
97
97
|
|
|
98
|
-
- 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
|
|
98
|
+
- 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 every time they are accessed.
|
|
99
99
|
- Safer method for extensions: `markdown.del_member("thing")`, also supporting dotted-paths and string tuples.
|
|
100
100
|
- 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.**
|
|
101
101
|
|
|
@@ -103,7 +103,7 @@ The same way members are accessed, they can also be set:
|
|
|
103
103
|
|
|
104
104
|
Griffe supports class inheritance, both when visiting and inspecting modules.
|
|
105
105
|
|
|
106
|
-
To access members of a class that are inherited from base classes, use the [`inherited_members`][griffe.Object.inherited_members] attribute.
|
|
106
|
+
To access members of a class that are inherited from base classes, use the [`inherited_members`][griffe.Object.inherited_members] attribute. Every time 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 every time (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.
|
|
107
107
|
|
|
108
108
|
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.
|
|
109
109
|
|
|
@@ -39,7 +39,7 @@ Besides, logging and exception messages simply cannot allow deprecation periods
|
|
|
39
39
|
|
|
40
40
|
## Conventions
|
|
41
41
|
|
|
42
|
-
Python does not provide any standard way to declare public APIs
|
|
42
|
+
Python does not provide any way to *enforce* public APIs: users can always import and use internal objects if they really want to. However, Python *does* specify a standard way to *declare* public APIs: the `__all__` attribute (see below), which is complemented by official recommendations and a few conventions.
|
|
43
43
|
|
|
44
44
|
### Underscore prefix
|
|
45
45
|
|
|
@@ -61,12 +61,18 @@ from elsewhere import something
|
|
|
61
61
|
|
|
62
62
|
Even though `something` doesn't start with an underscore, it was imported so it is not considered public.
|
|
63
63
|
|
|
64
|
+
Note that this exception comes from [PEP 8](https://peps.python.org/pep-0008/#public-and-internal-interfaces) ("imported names should always be considered an implementation detail") and from the conventions used by type checkers, not from the language reference: the latter states that when `__all__` is not defined, the set of public names includes *all* names found in the module's namespace which do not begin with an underscore, imported ones included.
|
|
65
|
+
|
|
64
66
|
### `__all__` list
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
Python also provides a mechanism that lets you do the opposite: explicitly mark objects as public. This mechanism uses the `__all__` module-level attribute, which is a list of strings containing the names of the public objects.
|
|
69
|
+
|
|
70
|
+
Contrary to popular belief, `__all__` is not merely a convention, nor just a way to control wildcard imports: it is actually specified in [the Python language reference](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement) as *the* mechanism that determines the public names of a module:
|
|
71
|
+
|
|
72
|
+
> The public names defined by a module are determined by checking the module's namespace for a variable named `__all__`; if defined, it must be a sequence of strings which are names defined or imported by that module. [...] The names given in `__all__` are all considered public and are required to exist. If `__all__` is not defined, the set of public names includes all names found in the module's namespace which do not begin with an underscore character (`'_'`). `__all__` should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).
|
|
67
73
|
|
|
68
74
|
```python title="package/module.py"
|
|
69
|
-
__all__ [
|
|
75
|
+
__all__ = [
|
|
70
76
|
"this_function",
|
|
71
77
|
"ThisClass",
|
|
72
78
|
]
|
|
@@ -86,7 +92,7 @@ class ThisOtherClass:
|
|
|
86
92
|
|
|
87
93
|
Here, even though `this_other_function` and `ThisOtherClass` are *not* prefixed with underscores, they are not considered public, because we explicitly and only marked `this_function` and `ThisClass` as public.
|
|
88
94
|
|
|
89
|
-
Declaring `__all__` has
|
|
95
|
+
Declaring `__all__` has a beneficial side-effect, which is often mistaken for its primary purpose: it affects wildcard imports. When your users use wildcard imports to import things from one of your modules, Python will only import the objects that are listed in `__all__`. Without `__all__`, it would import all objects that are not prefixed with an underscore, *including objects already imported from elsewhere*. This can cause serious namespace pollution, and even slow down Python code when wildcard imports are chained. [We actually recommend avoiding wildcard imports](python-code.md#avoid-wildcard-imports).
|
|
90
96
|
|
|
91
97
|
By declaring `__all__`, your public API becomes explicit, and explicit is better than implicit. But `__all__` only works for module-level objects. Within classes, you will still have to rely on the underscore prefix convention to mark methods or attributes as internal/private.
|
|
92
98
|
|
|
@@ -126,7 +132,7 @@ Note that the wildcard imports logic stays the same, and imports either all obje
|
|
|
126
132
|
> GRIFFE: **Our recommendation — Use the underscore prefix and `__all__` conventions.**
|
|
127
133
|
> Use both the underscore prefix convention for consistent naming at module and class levels, and the `__all__` convention for declaring your public API. We do not recommend using the redundant aliases convention, because it doesn't provide any information at runtime. We do not recommend the wildcard import convention either, for the same reason and [for additional reasons mentioned here](python-code.md#avoid-wildcard-imports). We still provide the [`griffe-public-redundant-aliases`](https://mkdocstrings.github.io/griffe-public-redundant-aliases/) and [`griffe-public-wildcard-imports`](https://mkdocstrings.github.io/griffe-public-wildcard-imports/) extensions for those who would still like to rely on these conventions.
|
|
128
134
|
>
|
|
129
|
-
> Our recommendation matches [PEP 8](https://peps.python.org/pep-0008/#public-and-internal-interfaces):
|
|
135
|
+
> Our recommendation matches the language reference (quoted above) as well as [PEP 8](https://peps.python.org/pep-0008/#public-and-internal-interfaces):
|
|
130
136
|
>
|
|
131
137
|
> > To better support introspection, modules should explicitly declare the names in their public API using the `__all__` attribute. Setting `__all__` to an empty list indicates that the module has no public API.
|
|
132
138
|
>
|
|
@@ -202,7 +208,7 @@ Such changes sometimes go unnoticed before the breaking change is released, beca
|
|
|
202
208
|
|
|
203
209
|
What if we could make this easier?
|
|
204
210
|
|
|
205
|
-
By hiding your module layout from your public API, you're removing all these pain points at once. Any object can freely move around without ever impacting users. Maintainers do not need to set deprecation periods where old and new uses are supported, or bump the major part of their semantic version when they stop supporting the old use. Hiding the module layout also removes the ambiguity of whether a submodule is considered public or not: [PEP 8](https://peps.python.org/pep-0008/#public-and-internal-interfaces) doesn't mention anything about it, and it doesn't look like the `__all__`
|
|
211
|
+
By hiding your module layout from your public API, you're removing all these pain points at once. Any object can freely move around without ever impacting users. Maintainers do not need to set deprecation periods where old and new uses are supported, or bump the major part of their semantic version when they stop supporting the old use. Hiding the module layout also removes the ambiguity of whether a submodule is considered public or not: [PEP 8](https://peps.python.org/pep-0008/#public-and-internal-interfaces) doesn't mention anything about it, and it doesn't look like the `__all__` mechanism expects developers to list their submodules too. In the end it looks like submodules are only subject to the underscore prefix convention.
|
|
206
212
|
|
|
207
213
|
So, how do we hide the module layout from the public API?
|
|
208
214
|
|
|
@@ -223,7 +229,7 @@ from my_package._combat import Combat
|
|
|
223
229
|
from my_package._exploration import navigate
|
|
224
230
|
from my_package._sorcery import cast_spell
|
|
225
231
|
|
|
226
|
-
__all__ [
|
|
232
|
+
__all__ = [
|
|
227
233
|
"Combat",
|
|
228
234
|
"navigate",
|
|
229
235
|
"cast_spell",
|
|
@@ -303,7 +309,7 @@ my_package/
|
|
|
303
309
|
Here the `Hello` class is exposed in both `my_package.module` and `my_package`.
|
|
304
310
|
|
|
305
311
|
```python title="my_package/module.py"
|
|
306
|
-
__all__ ["Hello"]
|
|
312
|
+
__all__ = ["Hello"]
|
|
307
313
|
|
|
308
314
|
class Hello:
|
|
309
315
|
...
|
|
@@ -319,7 +325,7 @@ my_package/
|
|
|
319
325
|
Here the `Hello` class is only exposed in `my_package.module`.
|
|
320
326
|
|
|
321
327
|
```python title="my_package/module.py"
|
|
322
|
-
__all__ ["Hello"]
|
|
328
|
+
__all__ = ["Hello"]
|
|
323
329
|
|
|
324
330
|
class Hello:
|
|
325
331
|
...
|
|
@@ -444,7 +450,7 @@ In this script, we find our entrypoint, `griffe.main`, used programmatically.
|
|
|
444
450
|
|
|
445
451
|
The second user of your CLI as API is... you again. When you write tests for your CLI, you import your entrypoints and call them by passing CLI options and arguments, maybe asserting the exit code raised with a `SystemExit` or the standard output/error thanks to [pytest's capture fixtures](https://docs.pytest.org/en/6.2.x/capture.html). Some simplified examples from our own test suite:
|
|
446
452
|
|
|
447
|
-
```python
|
|
453
|
+
```python
|
|
448
454
|
import pytest
|
|
449
455
|
import griffe
|
|
450
456
|
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# SPDX-License-Identifier: ISC
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2021, Timothée Mazzucotelli and contributors
|
|
4
|
+
|
|
5
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
# purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
# copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
|
|
1
17
|
"""Development tasks."""
|
|
2
18
|
|
|
3
19
|
from __future__ import annotations
|
|
@@ -20,7 +36,7 @@ if TYPE_CHECKING:
|
|
|
20
36
|
from duty.context import Context
|
|
21
37
|
|
|
22
38
|
|
|
23
|
-
PY_SRC_PATHS = (Path(_) for _ in ("packages
|
|
39
|
+
PY_SRC_PATHS = (Path(_) for _ in ("packages", "duties.py", "scripts"))
|
|
24
40
|
PY_SRC_LIST = tuple(str(_) for _ in PY_SRC_PATHS)
|
|
25
41
|
PY_SRC = " ".join(PY_SRC_LIST)
|
|
26
42
|
CI = os.environ.get("CI", "0") in {"1", "true", "yes", ""}
|
|
@@ -41,7 +57,7 @@ def _pyprefix(title: str) -> str:
|
|
|
41
57
|
def _get_changelog_version() -> str:
|
|
42
58
|
changelog_version_re = re.compile(r"^## \[(\d+\.\d+\.\d+)\].*$")
|
|
43
59
|
with Path(__file__).parent.joinpath("CHANGELOG.md").open("r", encoding="utf8") as file:
|
|
44
|
-
return next(filter(bool, map(changelog_version_re.match, file))).group(1) # ty:ignore[
|
|
60
|
+
return next(filter(bool, map(changelog_version_re.match, file))).group(1) # ty:ignore[unresolved-attribute]
|
|
45
61
|
|
|
46
62
|
|
|
47
63
|
@duty
|
|
@@ -243,7 +259,6 @@ def check_types(ctx: Context) -> None:
|
|
|
243
259
|
✓ Checking types
|
|
244
260
|
```
|
|
245
261
|
"""
|
|
246
|
-
"""Check that the code is correctly typed."""
|
|
247
262
|
py = f"{sys.version_info.major}.{sys.version_info.minor}"
|
|
248
263
|
ctx.run(
|
|
249
264
|
tools.ty.check(
|
|
@@ -460,7 +475,7 @@ def test(ctx: Context, *cli_args: str) -> None:
|
|
|
460
475
|
os.environ["PYTHONWARNDEFAULTENCODING"] = "1"
|
|
461
476
|
ctx.run(
|
|
462
477
|
tools.pytest(
|
|
463
|
-
"
|
|
478
|
+
rootdir=".",
|
|
464
479
|
config_file="config/pytest.ini",
|
|
465
480
|
color="yes",
|
|
466
481
|
).add_args("-n", "auto", *cli_args),
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# SPDX-License-Identifier: ISC
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2021, Timothée Mazzucotelli and contributors
|
|
4
|
+
|
|
5
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
# purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
# copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
|
|
1
17
|
# Script to generate the project's credits.
|
|
2
18
|
|
|
3
19
|
from __future__ import annotations
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SPDX-License-Identifier: ISC
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2021, Timothée Mazzucotelli and contributors
|
|
4
|
+
|
|
5
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
# purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
# copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
|
|
17
|
+
# Generate the JSON API data file.
|
|
18
|
+
|
|
19
|
+
import mkdocs_gen_files
|
|
20
|
+
|
|
21
|
+
python_handler = mkdocs_gen_files.config.plugins["mkdocstrings"].get_handler("python")
|
|
22
|
+
data = python_handler.collect("griffe", options=python_handler.get_options({}))
|
|
23
|
+
|
|
24
|
+
with mkdocs_gen_files.open("griffe.json", "w") as fd:
|
|
25
|
+
print(data.as_json(full=True), file=fd)
|