modern-python-guidance 0.4.4__tar.gz → 0.4.5__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 (138) hide show
  1. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/CHANGELOG.md +11 -0
  2. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/PKG-INFO +1 -1
  3. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/docs/design.md +8 -4
  4. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/pyproject.toml +1 -1
  5. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/__init__.py +1 -1
  6. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/mcp_server.py +29 -5
  7. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_mcp_unit.py +15 -5
  8. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/.github/workflows/check-python-release.yml +0 -0
  9. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/.github/workflows/ci.yml +0 -0
  10. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/.github/workflows/publish.yml +0 -0
  11. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/.gitignore +0 -0
  12. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/CONTRIBUTING.md +0 -0
  13. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/LICENSE +0 -0
  14. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/LICENSE-MIT +0 -0
  15. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/README.md +0 -0
  16. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/SECURITY.md +0 -0
  17. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/edge-cases/opus48_multiline.py +0 -0
  18. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/edge-cases/valid_alt_patterns.py +0 -0
  19. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/pyproject.toml +0 -0
  20. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/app.py +0 -0
  21. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/config.py +0 -0
  22. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/crawler.py +0 -0
  23. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/models.py +0 -0
  24. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/scanner.py +0 -0
  25. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/utils.py +0 -0
  26. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/pyproject.toml +0 -0
  27. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/setup.py +0 -0
  28. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/app.py +0 -0
  29. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/config.py +0 -0
  30. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/crawler.py +0 -0
  31. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/models.py +0 -0
  32. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/scanner.py +0 -0
  33. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/utils.py +0 -0
  34. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-modern/myapp/models.py +0 -0
  35. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-modern/myapp/views.py +0 -0
  36. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-outdated/myapp/models.py +0 -0
  37. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-outdated/myapp/views.py +0 -0
  38. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-c-modern/tests/test_calculator.py +0 -0
  39. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-c-outdated/tests/test_calculator.py +0 -0
  40. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/mcp-config.json +0 -0
  41. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v2.txt +0 -0
  42. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v3-mcp.txt +0 -0
  43. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v3.txt +0 -0
  44. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v4-a.txt +0 -0
  45. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v4-b.txt +0 -0
  46. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v4-c.txt +0 -0
  47. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt.txt +0 -0
  48. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-detailed.txt +0 -0
  49. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-normal.txt +0 -0
  50. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-terse.txt +0 -0
  51. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-detailed.txt +0 -0
  52. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-normal.txt +0 -0
  53. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-terse.txt +0 -0
  54. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-detailed.txt +0 -0
  55. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-normal.txt +0 -0
  56. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-terse.txt +0 -0
  57. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/run-mcp.sh +0 -0
  58. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/run-v4.sh +0 -0
  59. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/run-v5.sh +0 -0
  60. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/run.sh +0 -0
  61. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score-v2.sh +0 -0
  62. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score-v3.sh +0 -0
  63. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score-v4.sh +0 -0
  64. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score.sh +0 -0
  65. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score_v5.py +0 -0
  66. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/test-scorer.sh +0 -0
  67. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/docs/benchmark-evaluation.md +0 -0
  68. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/docs/benchmark-procedure.md +0 -0
  69. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/docs/benchmark-v5.md +0 -0
  70. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/rules/modern-python.md +0 -0
  71. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/SKILL.md +0 -0
  72. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/async-timeout-context.md +0 -0
  73. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/exception-groups.md +0 -0
  74. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/taskgroup-over-gather.md +0 -0
  75. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/data-structures/dataclass-modern.md +0 -0
  76. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/data-structures/dict-merge-operator.md +0 -0
  77. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/data-structures/match-case-patterns.md +0 -0
  78. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-async-views.md +0 -0
  79. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-check-constraints.md +0 -0
  80. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-json-field.md +0 -0
  81. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-annotated-depends.md +0 -0
  82. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-lifespan.md +0 -0
  83. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-typed-state.md +0 -0
  84. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/httpx/httpx-async-client-reuse.md +0 -0
  85. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/httpx/httpx-streaming.md +0 -0
  86. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-config.md +0 -0
  87. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-model-api.md +0 -0
  88. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-serialization.md +0 -0
  89. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-validators.md +0 -0
  90. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-parametrize.md +0 -0
  91. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-raises-match.md +0 -0
  92. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-tmp-path.md +0 -0
  93. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-2-style.md +0 -0
  94. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-async-session.md +0 -0
  95. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-mapped-column.md +0 -0
  96. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/datetime-utc.md +0 -0
  97. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/pathlib-over-os-path.md +0 -0
  98. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/removeprefix-removesuffix.md +0 -0
  99. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/template-strings.md +0 -0
  100. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/tomllib-builtin.md +0 -0
  101. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/no-pickle.md +0 -0
  102. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/pyproject-toml-over-setup.md +0 -0
  103. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/ruff-over-flake8.md +0 -0
  104. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/safe-subprocess.md +0 -0
  105. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/uv-over-pip.md +0 -0
  106. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/deferred-annotations.md +0 -0
  107. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/override-decorator.md +0 -0
  108. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/paramspec-decorators.md +0 -0
  109. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/type-parameter-syntax.md +0 -0
  110. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/typeis-vs-typeguard.md +0 -0
  111. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/union-syntax.md +0 -0
  112. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/use-builtin-generics.md +0 -0
  113. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/__main__.py +0 -0
  114. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/check.py +0 -0
  115. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/cli.py +0 -0
  116. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/compat.py +0 -0
  117. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/frontmatter.py +0 -0
  118. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/guide_index.py +0 -0
  119. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/retrieve.py +0 -0
  120. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/search.py +0 -0
  121. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/setup_cmd.py +0 -0
  122. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/uninstall_cmd.py +0 -0
  123. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/version_detect.py +0 -0
  124. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_check.py +0 -0
  125. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_cli_integration.py +0 -0
  126. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_cli_unit.py +0 -0
  127. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_compat.py +0 -0
  128. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_frontmatter.py +0 -0
  129. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_guide_index.py +0 -0
  130. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_guide_structure.py +0 -0
  131. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_mcp_server.py +0 -0
  132. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_retrieve.py +0 -0
  133. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_scorer_v5.py +0 -0
  134. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_search.py +0 -0
  135. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_setup.py +0 -0
  136. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_skill_sync.py +0 -0
  137. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_uninstall.py +0 -0
  138. {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_version_detect.py +0 -0
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.4.5] — 2026-06-06
6
+
7
+ ### Fixed
8
+
9
+ - MCP `retrieve_guides` maxItems hardcoded to 41: replaced with `_guide_limit()` that derives the limit from actual guide count at runtime. `_get_tools()` dynamically injects `maxItems` and description into the `tools/list` schema. Adding new guides no longer requires updating `mcp_server.py`. (closes #98)
10
+ - `docs/design.md` out of sync with v0.4.4 implementation: consolidated overlapping non-goals, added `check`/`setup`/`uninstall` to CLI architecture diagram, added `check.py`, `setup_cmd.py`, `uninstall_cmd.py`, `mcp_server.py` to module responsibility table, fixed Layer 1 guide count from 16 to 18. (closes #99)
11
+
12
+ ### Added
13
+
14
+ - 1 new test (1000 total).
15
+
5
16
  ## [0.4.4] — 2026-06-05
6
17
 
7
18
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modern-python-guidance
3
- Version: 0.4.4
3
+ Version: 0.4.5
4
4
  Summary: Version-aware BAD/GOOD pattern guides that help AI coding agents generate modern Python
5
5
  Project-URL: Homepage, https://github.com/yottayoshida/modern-python-guidance
6
6
  Project-URL: Repository, https://github.com/yottayoshida/modern-python-guidance
@@ -14,16 +14,16 @@ LLMs frequently generate outdated Python patterns: `typing.List` instead of `lis
14
14
 
15
15
  ## Non-goals
16
16
 
17
- - Automated code transformation (this is a reference tool, not a codemod)
17
+ - Automated code transformation / codemod (the `check` command scans for outdated patterns via regex + tokenize, but does not rewrite code)
18
18
  - Language Server Protocol integration
19
- - Pattern detection in source code (no AST analysis)
20
19
 
21
20
  ## Architecture
22
21
 
23
22
  ```
24
23
  ┌─────────────────────────────────────────────────────────┐
25
24
  │ CLI (cli.py) │
26
- │ search │ retrieve │ list │ detect-version
25
+ │ search │ retrieve │ list │ detect-version check │
26
+ │ setup │ uninstall │
27
27
  ├─────────┴──────────┴──────┴─────────────────────────────┤
28
28
  │ │
29
29
  │ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │
@@ -67,6 +67,10 @@ LLMs frequently generate outdated Python patterns: `typing.List` instead of `lis
67
67
  | `retrieve.py` | Renders guide content as JSON with version-match flag and token estimate |
68
68
  | `version_detect.py` | Detects target Python version from `--python-version` flag, `pyproject.toml` (`requires-python`), `.python-version` file, or default (3.11) |
69
69
  | `compat.py` | `version_compatible()` using `packaging.specifiers` and `token_estimate()` (chars / 4) |
70
+ | `check.py` | Scan a Python file for outdated patterns against guide definitions (regex + tokenize, not AST) |
71
+ | `setup_cmd.py` | Automate MCP server registration and Agent Skills symlink creation |
72
+ | `uninstall_cmd.py` | Reverse `mpg setup`: deregister the MCP server and remove the Skills symlink |
73
+ | `mcp_server.py` | MCP server — JSON-RPC 2.0 over stdio, zero external dependencies |
70
74
 
71
75
  ## Guide format
72
76
 
@@ -197,7 +201,7 @@ The CLI defaults to JSON when piped and human-readable when attached to a TTY. T
197
201
 
198
202
  | Layer | Scope | Categories | Count |
199
203
  |-------|-------|-----------|-------|
200
- | 1 — stdlib | Python standard library | typing, async, stdlib, data-structures | 16 |
204
+ | 1 — stdlib | Python standard library | typing, async, stdlib, data-structures | 18 |
201
205
  | 2 — frameworks | Third-party frameworks | pydantic, fastapi, httpx, django, sqlalchemy, pytest | 18 |
202
206
  | 3 — toolchain | Development tools | toolchain | 5 |
203
207
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "modern-python-guidance"
7
- version = "0.4.4"
7
+ version = "0.4.5"
8
8
  description = "Version-aware BAD/GOOD pattern guides that help AI coding agents generate modern Python"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0 OR MIT"
@@ -1,3 +1,3 @@
1
1
  """Modern Python Guidance — version-aware BAD/GOOD pattern guides for AI coding agents."""
2
2
 
3
- __version__ = "0.4.4"
3
+ __version__ = "0.4.5"
@@ -26,6 +26,30 @@ def _get_index() -> GuideIndex:
26
26
  return _index
27
27
 
28
28
 
29
+ def _guide_limit() -> int:
30
+ return len(_get_index())
31
+
32
+
33
+ def _get_tools() -> list[dict]:
34
+ n = _guide_limit()
35
+ tools = list(TOOLS)
36
+ tools[1] = {
37
+ **TOOLS[1],
38
+ "inputSchema": {
39
+ **TOOLS[1]["inputSchema"],
40
+ "properties": {
41
+ **TOOLS[1]["inputSchema"]["properties"],
42
+ "guide_ids": {
43
+ **TOOLS[1]["inputSchema"]["properties"]["guide_ids"],
44
+ "maxItems": n,
45
+ "description": f"Guide IDs to retrieve (max {n})",
46
+ },
47
+ },
48
+ },
49
+ }
50
+ return tools
51
+
52
+
29
53
  # --- JSON-RPC framing (newline-delimited JSON) ---
30
54
 
31
55
 
@@ -122,8 +146,7 @@ TOOLS = [
122
146
  "guide_ids": {
123
147
  "type": "array",
124
148
  "items": {"type": "string"},
125
- "description": "Guide IDs to retrieve (max 41)",
126
- "maxItems": 41,
149
+ "description": "Guide IDs to retrieve",
127
150
  },
128
151
  "python_version": {
129
152
  "type": "string",
@@ -270,8 +293,9 @@ def _tool_retrieve(arguments: dict) -> dict:
270
293
  guide_ids = arguments.get("guide_ids", [])
271
294
  if not guide_ids:
272
295
  return _tool_result("guide_ids is required and must not be empty", is_error=True)
273
- if len(guide_ids) > 41:
274
- return _tool_result("guide_ids exceeds maximum of 41", is_error=True)
296
+ limit = _guide_limit()
297
+ if len(guide_ids) > limit:
298
+ return _tool_result(f"guide_ids exceeds maximum of {limit}", is_error=True)
275
299
 
276
300
  pv = arguments.get("python_version")
277
301
  err = _validate_python_version(pv)
@@ -371,7 +395,7 @@ def _handle_request(msg: dict) -> dict | None:
371
395
  return None if is_notification else result
372
396
 
373
397
  if method == "tools/list":
374
- result = _result_response(req_id, {"tools": TOOLS})
398
+ result = _result_response(req_id, {"tools": _get_tools()})
375
399
  return None if is_notification else result
376
400
 
377
401
  if method == "tools/call":
@@ -217,16 +217,18 @@ class TestToolFunctions:
217
217
  assert data["results"][0]["id"] == "use-builtin-generics"
218
218
  assert data["not_found"][0]["id"] == "zzz-fake"
219
219
 
220
- def test_retrieve_exactly_41_allowed(self):
221
- ids = [f"fake-{i}" for i in range(41)]
220
+ def test_retrieve_at_limit_allowed(self):
221
+ limit = len(mcp._get_index())
222
+ ids = [f"fake-{i}" for i in range(limit)]
222
223
  r = mcp._tool_retrieve({"guide_ids": ids})
223
224
  assert r.get("isError") is not True
224
225
 
225
- def test_retrieve_42_rejected(self):
226
- ids = [f"fake-{i}" for i in range(42)]
226
+ def test_retrieve_over_limit_rejected(self):
227
+ limit = len(mcp._get_index())
228
+ ids = [f"fake-{i}" for i in range(limit + 1)]
227
229
  r = mcp._tool_retrieve({"guide_ids": ids})
228
230
  assert r["isError"] is True
229
- assert "41" in r["content"][0]["text"]
231
+ assert str(limit) in r["content"][0]["text"]
230
232
 
231
233
  def test_retrieve_invalid_version(self):
232
234
  r = mcp._tool_retrieve({"guide_ids": ["use-builtin-generics"], "python_version": "x"})
@@ -318,6 +320,14 @@ class TestHandleRequest:
318
320
  assert "tools" in resp["result"]
319
321
  assert len(resp["result"]["tools"]) == 4
320
322
 
323
+ def test_tools_list_dynamic_max_items(self):
324
+ expected = len(mcp._get_index())
325
+ tools = mcp._get_tools()
326
+ retrieve = tools[1]
327
+ schema = retrieve["inputSchema"]["properties"]["guide_ids"]
328
+ assert schema["maxItems"] == expected
329
+ assert str(expected) in schema["description"]
330
+
321
331
  def test_tools_call(self):
322
332
  msg = {
323
333
  "jsonrpc": "2.0",