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.
Files changed (153) hide show
  1. {griffe-2.0.2 → griffe-2.2.0}/CHANGELOG.md +35 -0
  2. {griffe-2.0.2 → griffe-2.2.0}/PKG-INFO +7 -9
  3. {griffe-2.0.2 → griffe-2.2.0}/README.md +2 -4
  4. {griffe-2.0.2 → griffe-2.2.0}/config/coverage.ini +4 -3
  5. {griffe-2.0.2 → griffe-2.2.0}/config/pytest.ini +2 -3
  6. {griffe-2.0.2 → griffe-2.2.0}/config/ruff.toml +6 -4
  7. griffe-2.2.0/config/ty.toml +9 -0
  8. {griffe-2.0.2 → griffe-2.2.0}/config/vscode/launch.json +1 -2
  9. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/built-in/dataclasses.md +1 -1
  10. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official.md +4 -4
  11. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors/architecture.md +2 -1
  12. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/checking.md +35 -0
  13. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/set-docstring-styles.md +1 -1
  14. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/support-decorators.md +3 -3
  15. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/navigating.md +3 -3
  16. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/recommendations/public-apis.md +16 -10
  17. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/docstrings.md +1 -1
  18. {griffe-2.0.2 → griffe-2.2.0}/duties.py +19 -4
  19. {griffe-2.0.2 → griffe-2.2.0}/pyproject.toml +1 -1
  20. {griffe-2.0.2 → griffe-2.2.0}/scripts/gen_credits.py +16 -0
  21. griffe-2.2.0/scripts/gen_griffe_json.py +25 -0
  22. {griffe-2.0.2 → griffe-2.2.0}/scripts/gen_structure_docs.py +18 -2
  23. {griffe-2.0.2 → griffe-2.2.0}/scripts/get_version.py +17 -1
  24. {griffe-2.0.2 → griffe-2.2.0}/scripts/make.py +16 -0
  25. griffe-2.0.2/config/ty.toml +0 -6
  26. griffe-2.0.2/scripts/gen_griffe_json.py +0 -9
  27. griffe-2.0.2/tests/__init__.py +0 -9
  28. griffe-2.0.2/tests/conftest.py +0 -17
  29. griffe-2.0.2/tests/fixtures/_repo/v0.1.0/my_module/__init__.py +0 -1
  30. griffe-2.0.2/tests/fixtures/_repo/v0.2.0/my_module/__init__.py +0 -1
  31. griffe-2.0.2/tests/helpers.py +0 -33
  32. griffe-2.0.2/tests/test_api.py +0 -227
  33. griffe-2.0.2/tests/test_cli.py +0 -57
  34. griffe-2.0.2/tests/test_diff.py +0 -213
  35. griffe-2.0.2/tests/test_docstrings/__init__.py +0 -1
  36. griffe-2.0.2/tests/test_docstrings/conftest.py +0 -43
  37. griffe-2.0.2/tests/test_docstrings/helpers.py +0 -73
  38. griffe-2.0.2/tests/test_docstrings/test_google.py +0 -1931
  39. griffe-2.0.2/tests/test_docstrings/test_numpy.py +0 -1373
  40. griffe-2.0.2/tests/test_docstrings/test_sphinx.py +0 -1313
  41. griffe-2.0.2/tests/test_docstrings/test_warnings.py +0 -25
  42. griffe-2.0.2/tests/test_encoders.py +0 -211
  43. griffe-2.0.2/tests/test_expressions.py +0 -243
  44. griffe-2.0.2/tests/test_extensions/__init__.py +0 -1
  45. griffe-2.0.2/tests/test_extensions/test_base.py +0 -292
  46. griffe-2.0.2/tests/test_extensions/test_dataclasses.py +0 -170
  47. griffe-2.0.2/tests/test_extensions/test_unpack_typeddict.py +0 -253
  48. griffe-2.0.2/tests/test_finder.py +0 -326
  49. griffe-2.0.2/tests/test_functions.py +0 -142
  50. griffe-2.0.2/tests/test_git.py +0 -104
  51. griffe-2.0.2/tests/test_inheritance.py +0 -180
  52. griffe-2.0.2/tests/test_inspector.py +0 -344
  53. griffe-2.0.2/tests/test_loader.py +0 -538
  54. griffe-2.0.2/tests/test_merger.py +0 -97
  55. griffe-2.0.2/tests/test_mixins.py +0 -13
  56. griffe-2.0.2/tests/test_models.py +0 -662
  57. griffe-2.0.2/tests/test_nodes.py +0 -281
  58. griffe-2.0.2/tests/test_public_api.py +0 -23
  59. griffe-2.0.2/tests/test_stdlib.py +0 -50
  60. griffe-2.0.2/tests/test_visitor.py +0 -499
  61. {griffe-2.0.2 → griffe-2.2.0}/.gitignore +0 -0
  62. {griffe-2.0.2 → griffe-2.2.0}/CODE_OF_CONDUCT.md +0 -0
  63. {griffe-2.0.2 → griffe-2.2.0}/CONTRIBUTING.md +0 -0
  64. {griffe-2.0.2 → griffe-2.2.0}/LICENSE +0 -0
  65. {griffe-2.0.2 → griffe-2.2.0}/config/git-changelog.toml +0 -0
  66. {griffe-2.0.2 → griffe-2.2.0}/config/vscode/settings.json +0 -0
  67. {griffe-2.0.2 → griffe-2.2.0}/config/vscode/tasks.json +0 -0
  68. {griffe-2.0.2 → griffe-2.2.0}/docs/.overrides/main.html +0 -0
  69. {griffe-2.0.2 → griffe-2.2.0}/docs/.overrides/partials/comments.html +0 -0
  70. {griffe-2.0.2 → griffe-2.2.0}/docs/.overrides/partials/path-item.html +0 -0
  71. {griffe-2.0.2 → griffe-2.2.0}/docs/alternatives.md +0 -0
  72. {griffe-2.0.2 → griffe-2.2.0}/docs/changelog.md +0 -0
  73. {griffe-2.0.2 → griffe-2.2.0}/docs/code-of-conduct.md +0 -0
  74. {griffe-2.0.2 → griffe-2.2.0}/docs/community.md +0 -0
  75. {griffe-2.0.2 → griffe-2.2.0}/docs/contributing.md +0 -0
  76. {griffe-2.0.2 → griffe-2.2.0}/docs/credits.md +0 -0
  77. {griffe-2.0.2 → griffe-2.2.0}/docs/css/custom.css +0 -0
  78. {griffe-2.0.2 → griffe-2.2.0}/docs/css/material.css +0 -0
  79. {griffe-2.0.2 → griffe-2.2.0}/docs/css/mkdocstrings.css +0 -0
  80. {griffe-2.0.2 → griffe-2.2.0}/docs/downstream-projects.md +0 -0
  81. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/built-in/unpack-typeddict.md +0 -0
  82. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/built-in.md +0 -0
  83. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/autodocstringstyle.md +0 -0
  84. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/inherited-docstrings.md +0 -0
  85. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/public-redundant-aliases.md +0 -0
  86. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/public-wildcard-imports.md +0 -0
  87. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/pydantic.md +0 -0
  88. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/runtime-objects.md +0 -0
  89. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/sphinx.md +0 -0
  90. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/typingdoc.md +0 -0
  91. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/official/warnings-deprecated.md +0 -0
  92. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/docstring-inheritance.md +0 -0
  93. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/fastapi.md +0 -0
  94. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/fieldz.md +0 -0
  95. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/generics.md +0 -0
  96. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/inherited-method-crossrefs.md +0 -0
  97. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party/modernized-annotations.md +0 -0
  98. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions/third-party.md +0 -0
  99. {griffe-2.0.2 → griffe-2.2.0}/docs/extensions.md +0 -0
  100. {griffe-2.0.2 → griffe-2.2.0}/docs/getting-help.md +0 -0
  101. {griffe-2.0.2 → griffe-2.2.0}/docs/getting-started.md +0 -0
  102. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors/commands.md +0 -0
  103. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors/setup.md +0 -0
  104. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors/workflow.md +0 -0
  105. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/contributors.md +0 -0
  106. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/extending.md +0 -0
  107. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/parse-docstrings.md +0 -0
  108. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/selectively-inspect.md +0 -0
  109. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/how-to/set-git-info.md +0 -0
  110. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/loading.md +0 -0
  111. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/recommendations/docstrings.md +0 -0
  112. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/recommendations/python-code.md +0 -0
  113. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users/serializing.md +0 -0
  114. {griffe-2.0.2 → griffe-2.2.0}/docs/guide/users.md +0 -0
  115. {griffe-2.0.2 → griffe-2.2.0}/docs/guide.md +0 -0
  116. {griffe-2.0.2 → griffe-2.2.0}/docs/img/favicon.ico +0 -0
  117. {griffe-2.0.2 → griffe-2.2.0}/docs/img/gha_annotations_1.png +0 -0
  118. {griffe-2.0.2 → griffe-2.2.0}/docs/img/gha_annotations_2.png +0 -0
  119. {griffe-2.0.2 → griffe-2.2.0}/docs/index.md +0 -0
  120. {griffe-2.0.2 → griffe-2.2.0}/docs/installation.md +0 -0
  121. {griffe-2.0.2 → griffe-2.2.0}/docs/introduction.md +0 -0
  122. {griffe-2.0.2 → griffe-2.2.0}/docs/js/feedback.js +0 -0
  123. {griffe-2.0.2 → griffe-2.2.0}/docs/license.md +0 -0
  124. {griffe-2.0.2 → griffe-2.2.0}/docs/logo.svg +0 -0
  125. {griffe-2.0.2 → griffe-2.2.0}/docs/playground.md +0 -0
  126. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/agents.md +0 -0
  127. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/checks.md +0 -0
  128. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/cli.md +0 -0
  129. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/docstrings/models.md +0 -0
  130. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/docstrings/parsers.md +0 -0
  131. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/docstrings.md +0 -0
  132. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/exceptions.md +0 -0
  133. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/expressions.md +0 -0
  134. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/extensions.md +0 -0
  135. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/finder.md +0 -0
  136. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/helpers.md +0 -0
  137. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/loaders.md +0 -0
  138. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/loggers.md +0 -0
  139. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/alias.md +0 -0
  140. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/attribute.md +0 -0
  141. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/class.md +0 -0
  142. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/function.md +0 -0
  143. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/module.md +0 -0
  144. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models/type_alias.md +0 -0
  145. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/models.md +0 -0
  146. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api/serializers.md +0 -0
  147. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/api.md +0 -0
  148. {griffe-2.0.2 → griffe-2.2.0}/docs/reference/cli.md +0 -0
  149. {griffe-2.0.2 → griffe-2.2.0}/docs/reference.md +0 -0
  150. {griffe-2.0.2 → griffe-2.2.0}/docs/schema-docstrings-options.json +0 -0
  151. {griffe-2.0.2 → griffe-2.2.0}/docs/schema.json +0 -0
  152. {griffe-2.0.2 → griffe-2.2.0}/mkdocs.yml +0 -0
  153. {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.4
1
+ Metadata-Version: 2.5
2
2
  Name: griffe
3
- Version: 2.0.2
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.2
34
- Requires-Dist: griffelib==2.0.2
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.2; extra == 'pypi'
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=642fc2bdcc9904089c62fe5aec4e03ace32da67d&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=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 7 more private sponsor(s).*
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=642fc2bdcc9904089c62fe5aec4e03ace32da67d&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=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 7 more private sponsor(s).*
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
@@ -1,11 +1,10 @@
1
1
  [pytest]
2
- python_files =
3
- test_*.py
4
2
  addopts =
5
3
  --cov
6
4
  --cov-config config/coverage.ini
5
+ --import-mode=importlib
7
6
  testpaths =
8
- tests
7
+ packages/*/tests
9
8
 
10
9
  # action:message_regex:warning_class:module_regex:line
11
10
  filterwarnings =
@@ -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
@@ -0,0 +1,9 @@
1
+ [src]
2
+ exclude = ["packages/*/tests/fixtures"]
3
+
4
+ [terminal]
5
+ error-on-warning = true
6
+ output-format = "concise"
7
+
8
+ [environment]
9
+ root = [".", "packages/griffelib/src", "packages/griffecli/src"]
@@ -41,7 +41,6 @@
41
41
  "-vvv",
42
42
  "--no-cov",
43
43
  "--dist=no",
44
- "tests",
45
44
  "-k=${input:tests_selection}"
46
45
  ]
47
46
  }
@@ -54,4 +53,4 @@
54
53
  "default": ""
55
54
  }
56
55
  ]
57
- }
56
+ }
@@ -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 explictly enable it to change its position in the list of extensions (it will run only once):
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
- [`inherited-docstrings`](official/inherited-docstrings.md) | Inherit docstrings from parent classes.
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
- [`pydantic`](official/pydantic.md) | Support for [Pydantic](https://docs.pydantic.dev/latest/) models.
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
- [`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".
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 easly as possible, so that other extensions can work without issue.
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 suport my decorator."""
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 suport my decorator."""
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 suport my decorator."""
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 everytime they are accessed.
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 everytime they are accessed.
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. 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.
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. However we do have official recommendations and a few conventions.
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
- There is another convention that lets you do the opposite: explicitly mark objects as public. This convention uses the `__all__` module-level attribute, which is a list of strings containing the names of the public objects.
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 another beneficial effect: 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).
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__` convention expects developers to list their submodules too. In the end it looks like submodules are only subject to the underscore prefix convention.
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 title="tests/test_cli.py"
453
+ ```python
448
454
  import pytest
449
455
  import griffe
450
456
 
@@ -737,7 +737,7 @@ See previous tips for types in docstrings.
737
737
 
738
738
  ## Numpydoc-style
739
739
 
740
- Numpydoc docstrings, see [Numpydoc's documentation][numpydoc]
740
+ Numpydoc docstrings, see [Numpydoc's documentation][numpydoc].
741
741
 
742
742
  ### Syntax {#numpydoc-syntax}
743
743
 
@@ -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/griffecli/src", "packages/griffelib/src", "tests", "duties.py", "scripts"))
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[invalid-argument-type]
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
- "tests",
478
+ rootdir=".",
464
479
  config_file="config/pytest.ini",
465
480
  color="yes",
466
481
  ).add_args("-n", "auto", *cli_args),
@@ -102,7 +102,7 @@ maintain = [
102
102
  ci = [
103
103
  "duty>=1.6",
104
104
  "griffe-inherited-docstrings>=1.1.2",
105
- "jsonschema>=4.17",
105
+ "jsonschema>=4.18",
106
106
  "pysource-codegen>=0.7",
107
107
  "pysource-minimize>=0.10",
108
108
  "pytest>=8.2",
@@ -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)