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.
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/CHANGELOG.md +11 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/PKG-INFO +1 -1
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/docs/design.md +8 -4
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/pyproject.toml +1 -1
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/__init__.py +1 -1
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/mcp_server.py +29 -5
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_mcp_unit.py +15 -5
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/.github/workflows/check-python-release.yml +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/.github/workflows/ci.yml +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/.github/workflows/publish.yml +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/.gitignore +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/CONTRIBUTING.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/LICENSE +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/LICENSE-MIT +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/README.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/SECURITY.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/edge-cases/opus48_multiline.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/edge-cases/valid_alt_patterns.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/pyproject.toml +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/app.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/config.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/crawler.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/models.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/scanner.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/utils.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/pyproject.toml +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/setup.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/app.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/config.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/crawler.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/models.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/scanner.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/utils.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-modern/myapp/models.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-modern/myapp/views.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-outdated/myapp/models.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-outdated/myapp/views.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-c-modern/tests/test_calculator.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/fixtures/variant-c-outdated/tests/test_calculator.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/mcp-config.json +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v2.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v3-mcp.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v3.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v4-a.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v4-b.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt-v4-c.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompt.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-detailed.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-normal.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-terse.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-detailed.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-normal.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-terse.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-detailed.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-normal.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-terse.txt +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/run-mcp.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/run-v4.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/run-v5.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/run.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score-v2.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score-v3.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score-v4.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/score_v5.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/test-scorer.sh +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/docs/benchmark-evaluation.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/docs/benchmark-procedure.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/docs/benchmark-v5.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/rules/modern-python.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/SKILL.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/async-timeout-context.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/exception-groups.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/taskgroup-over-gather.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/data-structures/dataclass-modern.md +0 -0
- {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
- {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
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-async-views.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-check-constraints.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-json-field.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-annotated-depends.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-lifespan.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-typed-state.md +0 -0
- {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
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/httpx/httpx-streaming.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-config.md +0 -0
- {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
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-serialization.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-validators.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-parametrize.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-raises-match.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-tmp-path.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-2-style.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-async-session.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-mapped-column.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/datetime-utc.md +0 -0
- {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
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/removeprefix-removesuffix.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/template-strings.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/tomllib-builtin.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/no-pickle.md +0 -0
- {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
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/ruff-over-flake8.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/safe-subprocess.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/uv-over-pip.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/deferred-annotations.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/override-decorator.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/paramspec-decorators.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/type-parameter-syntax.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/typeis-vs-typeguard.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/union-syntax.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/use-builtin-generics.md +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/__main__.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/check.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/cli.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/compat.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/frontmatter.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/guide_index.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/retrieve.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/search.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/setup_cmd.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/uninstall_cmd.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/version_detect.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_check.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_cli_integration.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_cli_unit.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_compat.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_frontmatter.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_guide_index.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_guide_structure.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_mcp_server.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_retrieve.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_scorer_v5.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_search.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_setup.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_skill_sync.py +0 -0
- {modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/tests/test_uninstall.py +0 -0
- {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.
|
|
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 (
|
|
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 |
|
|
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.
|
|
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"
|
|
@@ -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
|
|
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
|
-
|
|
274
|
-
|
|
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":
|
|
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
|
|
221
|
-
|
|
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
|
|
226
|
-
|
|
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
|
|
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",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-detailed.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-detailed.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-detailed.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/__main__.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/check.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/cli.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/compat.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/retrieve.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.4 → modern_python_guidance-0.4.5}/src/modern_python_guidance/search.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|