modern-python-guidance 0.4.3__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.3 → modern_python_guidance-0.4.5}/.github/workflows/ci.yml +1 -1
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/CHANGELOG.md +19 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/PKG-INFO +4 -3
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/README.md +3 -2
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/docs/design.md +11 -8
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/pyproject.toml +1 -1
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/__init__.py +1 -1
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/mcp_server.py +29 -5
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/version_detect.py +50 -15
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_mcp_unit.py +15 -5
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_version_detect.py +86 -6
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/.github/workflows/check-python-release.yml +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/.github/workflows/publish.yml +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/.gitignore +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/CONTRIBUTING.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/LICENSE +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/LICENSE-MIT +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/SECURITY.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/edge-cases/opus48_multiline.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/edge-cases/valid_alt_patterns.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/pyproject.toml +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/app.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/config.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/crawler.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/models.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/scanner.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-modern/src/utils.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/pyproject.toml +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/setup.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/app.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/config.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/crawler.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/models.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/scanner.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-a-outdated/src/utils.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-modern/myapp/models.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-modern/myapp/views.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-outdated/myapp/models.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-b-outdated/myapp/views.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-c-modern/tests/test_calculator.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/fixtures/variant-c-outdated/tests/test_calculator.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/mcp-config.json +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompt-v2.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompt-v3-mcp.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompt-v3.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompt-v4-a.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompt-v4-b.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompt-v4-c.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompt.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-detailed.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-normal.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-a-terse.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-detailed.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-normal.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-b-terse.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-detailed.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-normal.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/prompts/v5-c-terse.txt +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/run-mcp.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/run-v4.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/run-v5.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/run.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/score-v2.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/score-v3.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/score-v4.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/score.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/score_v5.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/bench/test-scorer.sh +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/docs/benchmark-evaluation.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/docs/benchmark-procedure.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/docs/benchmark-v5.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/rules/modern-python.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/SKILL.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/async-timeout-context.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/exception-groups.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/async/taskgroup-over-gather.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/data-structures/dataclass-modern.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/data-structures/dict-merge-operator.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/data-structures/match-case-patterns.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-async-views.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-check-constraints.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/django/django-json-field.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-annotated-depends.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-lifespan.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/fastapi/fastapi-typed-state.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/httpx/httpx-async-client-reuse.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/httpx/httpx-streaming.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-config.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-model-api.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-serialization.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-validators.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-parametrize.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-raises-match.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/pytest/pytest-tmp-path.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-2-style.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-async-session.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-mapped-column.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/datetime-utc.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/pathlib-over-os-path.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/removeprefix-removesuffix.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/template-strings.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/stdlib/tomllib-builtin.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/no-pickle.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/pyproject-toml-over-setup.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/ruff-over-flake8.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/safe-subprocess.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/toolchain/uv-over-pip.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/deferred-annotations.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/override-decorator.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/paramspec-decorators.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/type-parameter-syntax.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/typeis-vs-typeguard.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/union-syntax.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/skills/modern-python-guidance/guides/typing/use-builtin-generics.md +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/__main__.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/check.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/cli.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/compat.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/frontmatter.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/guide_index.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/retrieve.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/search.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/setup_cmd.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/uninstall_cmd.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_check.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_cli_integration.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_cli_unit.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_compat.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_frontmatter.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_guide_index.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_guide_structure.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_mcp_server.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_retrieve.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_scorer_v5.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_search.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_setup.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_skill_sync.py +0 -0
- {modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/tests/test_uninstall.py +0 -0
|
@@ -2,6 +2,25 @@
|
|
|
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
|
+
|
|
16
|
+
## [0.4.4] — 2026-06-05
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Poetry constraint parsing: `detect_version()` now extracts the minimum Python version from `[tool.poetry.dependencies].python` instead of only logging a warning. Supported forms: caret (`^3.10`), tilde (`~3.11`), PEP 440 (`>=3.10,<3.14`), and dict-form (`{version = "^3.10"}`). Union operators (`||`) and unsupported formats warn and fall through to `.python-version` / default. (closes #95)
|
|
21
|
+
- Python 3.14 added to CI test matrix as a regular (non-allowed-failure) entry. Python 3.14 has been GA since 2025-10-07; pyproject.toml classifiers already declared support. (closes #94)
|
|
22
|
+
- 12 new tests (999 total).
|
|
23
|
+
|
|
5
24
|
## [0.4.3] — 2026-06-04
|
|
6
25
|
|
|
7
26
|
### Fixed
|
|
@@ -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
|
|
@@ -166,8 +166,9 @@ Guides specify their minimum Python version. The CLI auto-detects your project's
|
|
|
166
166
|
|
|
167
167
|
1. `--python-version` flag
|
|
168
168
|
2. `pyproject.toml` `requires-python`
|
|
169
|
-
3.
|
|
170
|
-
4.
|
|
169
|
+
3. `pyproject.toml` Poetry `python` constraint (`^3.10`, `~3.11`, `>=3.10,<3.14`)
|
|
170
|
+
4. `.python-version` file
|
|
171
|
+
5. Default: 3.11
|
|
171
172
|
|
|
172
173
|
```bash
|
|
173
174
|
# Only shows guides compatible with Python 3.9
|
|
@@ -134,8 +134,9 @@ Guides specify their minimum Python version. The CLI auto-detects your project's
|
|
|
134
134
|
|
|
135
135
|
1. `--python-version` flag
|
|
136
136
|
2. `pyproject.toml` `requires-python`
|
|
137
|
-
3.
|
|
138
|
-
4.
|
|
137
|
+
3. `pyproject.toml` Poetry `python` constraint (`^3.10`, `~3.11`, `>=3.10,<3.14`)
|
|
138
|
+
4. `.python-version` file
|
|
139
|
+
5. Default: 3.11
|
|
139
140
|
|
|
140
141
|
```bash
|
|
141
142
|
# Only shows guides compatible with Python 3.9
|
|
@@ -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
|
|
|
@@ -150,10 +154,9 @@ Fuzzy results are marked with `fuzzy: true` in the output.
|
|
|
150
154
|
|
|
151
155
|
1. `--python-version` CLI flag (explicit override)
|
|
152
156
|
2. `pyproject.toml` `[project].requires-python` (PEP 621)
|
|
153
|
-
3.
|
|
154
|
-
4.
|
|
155
|
-
|
|
156
|
-
Poetry's caret syntax (`^3.11`) is detected but not parsed — the tool logs a warning and suggests using `--python-version` or adding `[project].requires-python`.
|
|
157
|
+
3. `pyproject.toml` `[tool.poetry.dependencies].python` — caret (`^3.10`), tilde (`~3.11`), and PEP 440 (`>=3.10,<3.14`) constraints are parsed to extract the minimum version. Dict-form (`{version = "^3.10"}`) is also supported. Union operators (`||`) are not supported and fall through with a warning.
|
|
158
|
+
4. `.python-version` file (pyenv/asdf convention)
|
|
159
|
+
5. Default: `3.11`
|
|
157
160
|
|
|
158
161
|
## Output format
|
|
159
162
|
|
|
@@ -198,7 +201,7 @@ The CLI defaults to JSON when piped and human-readable when attached to a TTY. T
|
|
|
198
201
|
|
|
199
202
|
| Layer | Scope | Categories | Count |
|
|
200
203
|
|-------|-------|-----------|-------|
|
|
201
|
-
| 1 — stdlib | Python standard library | typing, async, stdlib, data-structures |
|
|
204
|
+
| 1 — stdlib | Python standard library | typing, async, stdlib, data-structures | 18 |
|
|
202
205
|
| 2 — frameworks | Third-party frameworks | pydantic, fastapi, httpx, django, sqlalchemy, pytest | 18 |
|
|
203
206
|
| 3 — toolchain | Development tools | toolchain | 5 |
|
|
204
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":
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
Precedence chain:
|
|
4
4
|
1. CLI --python-version flag (explicit override)
|
|
5
5
|
2. pyproject.toml [project].requires-python (PEP 621)
|
|
6
|
-
3. .python
|
|
7
|
-
4.
|
|
6
|
+
3. pyproject.toml [tool.poetry.dependencies].python (caret/tilde/PEP 440)
|
|
7
|
+
4. .python-version file (pyenv/asdf)
|
|
8
|
+
5. Default: 3.11
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
from __future__ import annotations
|
|
@@ -24,6 +25,7 @@ DEFAULT_VERSION = "3.11"
|
|
|
24
25
|
_KNOWN_MINORS = [Version(f"3.{minor}") for minor in range(7, 20)]
|
|
25
26
|
|
|
26
27
|
_POETRY_CARET_RE = re.compile(r"\^(\d+\.\d+)")
|
|
28
|
+
_POETRY_TILDE_RE = re.compile(r"~(\d+\.\d+)")
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
def detect_version(
|
|
@@ -68,21 +70,54 @@ def _from_pyproject(path: Path) -> str | None:
|
|
|
68
70
|
|
|
69
71
|
poetry_python = data.get("tool", {}).get("poetry", {}).get("dependencies", {}).get("python")
|
|
70
72
|
if poetry_python:
|
|
71
|
-
|
|
72
|
-
if
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
73
|
+
result = _parse_poetry_python(poetry_python)
|
|
74
|
+
if result is not None:
|
|
75
|
+
return result
|
|
76
|
+
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _parse_poetry_python(value: str | dict) -> str | None:
|
|
81
|
+
if isinstance(value, dict):
|
|
82
|
+
value = value.get("version")
|
|
83
|
+
if not value:
|
|
84
|
+
log.warning("Poetry python constraint has no 'version' key")
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
if not isinstance(value, str):
|
|
88
|
+
log.warning("Poetry python constraint has unexpected type %s", type(value).__name__)
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
poetry_str = value
|
|
92
|
+
|
|
93
|
+
if "||" in poetry_str:
|
|
94
|
+
log.warning(
|
|
95
|
+
"Poetry union constraint '%s' is not supported. "
|
|
96
|
+
"Use --python-version or add [project].requires-python.",
|
|
97
|
+
poetry_str,
|
|
98
|
+
)
|
|
84
99
|
return None
|
|
85
100
|
|
|
101
|
+
m = _POETRY_CARET_RE.search(poetry_str)
|
|
102
|
+
if m:
|
|
103
|
+
log.info("Parsed Poetry caret constraint '%s' → %s", poetry_str, m.group(1))
|
|
104
|
+
return m.group(1)
|
|
105
|
+
|
|
106
|
+
m = _POETRY_TILDE_RE.search(poetry_str)
|
|
107
|
+
if m:
|
|
108
|
+
log.info("Parsed Poetry tilde constraint '%s' → %s", poetry_str, m.group(1))
|
|
109
|
+
return m.group(1)
|
|
110
|
+
|
|
111
|
+
result = _min_version_from_specifier(poetry_str)
|
|
112
|
+
if result is not None:
|
|
113
|
+
log.info("Parsed Poetry PEP 440 constraint '%s' → %s", poetry_str, result)
|
|
114
|
+
return result
|
|
115
|
+
|
|
116
|
+
log.warning(
|
|
117
|
+
"Poetry python constraint '%s' detected but not supported. "
|
|
118
|
+
"Use --python-version or add [project].requires-python.",
|
|
119
|
+
poetry_str,
|
|
120
|
+
)
|
|
86
121
|
return None
|
|
87
122
|
|
|
88
123
|
|
|
@@ -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",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
5
6
|
import pytest
|
|
@@ -44,13 +45,87 @@ class TestPyprojectToml:
|
|
|
44
45
|
(tmp_project / "pyproject.toml").write_text('[project]\nrequires-python = ">=3.11.4"\n')
|
|
45
46
|
assert detect_version(project_dir=tmp_project) == "3.11"
|
|
46
47
|
|
|
47
|
-
def
|
|
48
|
+
def test_poetry_caret(self, tmp_project: Path, caplog):
|
|
48
49
|
(tmp_project / "pyproject.toml").write_text(
|
|
49
50
|
'[tool.poetry.dependencies]\npython = "^3.10"\n'
|
|
50
51
|
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
assert "Poetry caret
|
|
52
|
+
with caplog.at_level(logging.INFO):
|
|
53
|
+
assert detect_version(project_dir=tmp_project) == "3.10"
|
|
54
|
+
assert "Parsed Poetry caret" in caplog.text
|
|
55
|
+
|
|
56
|
+
def test_poetry_caret_with_patch(self, tmp_project: Path):
|
|
57
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
58
|
+
'[tool.poetry.dependencies]\npython = "^3.10.2"\n'
|
|
59
|
+
)
|
|
60
|
+
assert detect_version(project_dir=tmp_project) == "3.10"
|
|
61
|
+
|
|
62
|
+
def test_poetry_tilde(self, tmp_project: Path, caplog):
|
|
63
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
64
|
+
'[tool.poetry.dependencies]\npython = "~3.11"\n'
|
|
65
|
+
)
|
|
66
|
+
with caplog.at_level(logging.INFO):
|
|
67
|
+
assert detect_version(project_dir=tmp_project) == "3.11"
|
|
68
|
+
assert "Parsed Poetry tilde" in caplog.text
|
|
69
|
+
|
|
70
|
+
def test_poetry_tilde_with_patch(self, tmp_project: Path):
|
|
71
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
72
|
+
'[tool.poetry.dependencies]\npython = "~3.11.5"\n'
|
|
73
|
+
)
|
|
74
|
+
assert detect_version(project_dir=tmp_project) == "3.11"
|
|
75
|
+
|
|
76
|
+
def test_poetry_pep440_range(self, tmp_project: Path, caplog):
|
|
77
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
78
|
+
'[tool.poetry.dependencies]\npython = ">=3.10,<3.14"\n'
|
|
79
|
+
)
|
|
80
|
+
with caplog.at_level(logging.INFO):
|
|
81
|
+
assert detect_version(project_dir=tmp_project) == "3.10"
|
|
82
|
+
assert "Parsed Poetry PEP 440" in caplog.text
|
|
83
|
+
|
|
84
|
+
def test_poetry_pep440_compatible(self, tmp_project: Path, caplog):
|
|
85
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
86
|
+
'[tool.poetry.dependencies]\npython = "~=3.11"\n'
|
|
87
|
+
)
|
|
88
|
+
with caplog.at_level(logging.INFO):
|
|
89
|
+
assert detect_version(project_dir=tmp_project) == "3.11"
|
|
90
|
+
assert "Parsed Poetry PEP 440" in caplog.text
|
|
91
|
+
assert "Parsed Poetry tilde" not in caplog.text
|
|
92
|
+
|
|
93
|
+
def test_poetry_dict_form(self, tmp_project: Path):
|
|
94
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
95
|
+
'[tool.poetry.dependencies.python]\nversion = "^3.10"\n'
|
|
96
|
+
)
|
|
97
|
+
assert detect_version(project_dir=tmp_project) == "3.10"
|
|
98
|
+
|
|
99
|
+
def test_poetry_dict_no_version_key(self, tmp_project: Path, caplog):
|
|
100
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
101
|
+
"[tool.poetry.dependencies.python]\noptional = true\n"
|
|
102
|
+
)
|
|
103
|
+
assert detect_version(project_dir=tmp_project) == DEFAULT_VERSION
|
|
104
|
+
assert "no 'version' key" in caplog.text
|
|
105
|
+
|
|
106
|
+
def test_poetry_union_warns(self, tmp_project: Path, caplog):
|
|
107
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
108
|
+
'[tool.poetry.dependencies]\npython = "^3.10 || ^3.12"\n'
|
|
109
|
+
)
|
|
110
|
+
assert detect_version(project_dir=tmp_project) == DEFAULT_VERSION
|
|
111
|
+
assert "union constraint" in caplog.text
|
|
112
|
+
|
|
113
|
+
def test_poetry_unsupported_warns(self, tmp_project: Path, caplog):
|
|
114
|
+
(tmp_project / "pyproject.toml").write_text('[tool.poetry.dependencies]\npython = "*"\n')
|
|
115
|
+
assert detect_version(project_dir=tmp_project) == DEFAULT_VERSION
|
|
116
|
+
assert "not supported" in caplog.text
|
|
117
|
+
|
|
118
|
+
def test_poetry_major_only_warns(self, tmp_project: Path, caplog):
|
|
119
|
+
(tmp_project / "pyproject.toml").write_text('[tool.poetry.dependencies]\npython = "^3"\n')
|
|
120
|
+
assert detect_version(project_dir=tmp_project) == DEFAULT_VERSION
|
|
121
|
+
assert "not supported" in caplog.text
|
|
122
|
+
|
|
123
|
+
def test_poetry_list_type_warns(self, tmp_project: Path, caplog):
|
|
124
|
+
(tmp_project / "pyproject.toml").write_text(
|
|
125
|
+
'[tool.poetry.dependencies]\npython = ["^3.10", "^3.12"]\n'
|
|
126
|
+
)
|
|
127
|
+
assert detect_version(project_dir=tmp_project) == DEFAULT_VERSION
|
|
128
|
+
assert "unexpected type" in caplog.text
|
|
54
129
|
|
|
55
130
|
def test_malformed_toml(self, tmp_project: Path, caplog):
|
|
56
131
|
(tmp_project / "pyproject.toml").write_text("this is not valid toml [[[")
|
|
@@ -91,12 +166,17 @@ class TestPrecedence:
|
|
|
91
166
|
(tmp_project / ".python-version").write_text("3.10\n")
|
|
92
167
|
assert detect_version(project_dir=tmp_project) == "3.12"
|
|
93
168
|
|
|
94
|
-
def
|
|
169
|
+
def test_poetry_wins_over_python_version_file(self, tmp_project: Path):
|
|
95
170
|
(tmp_project / "pyproject.toml").write_text(
|
|
96
171
|
'[tool.poetry.dependencies]\npython = "^3.10"\n'
|
|
97
172
|
)
|
|
98
173
|
(tmp_project / ".python-version").write_text("3.11\n")
|
|
99
|
-
assert detect_version(project_dir=tmp_project) == "3.
|
|
174
|
+
assert detect_version(project_dir=tmp_project) == "3.10"
|
|
175
|
+
|
|
176
|
+
def test_poetry_unsupported_falls_to_python_version_file(self, tmp_project: Path):
|
|
177
|
+
(tmp_project / "pyproject.toml").write_text('[tool.poetry.dependencies]\npython = "*"\n')
|
|
178
|
+
(tmp_project / ".python-version").write_text("3.12\n")
|
|
179
|
+
assert detect_version(project_dir=tmp_project) == "3.12"
|
|
100
180
|
|
|
101
181
|
|
|
102
182
|
class TestDefault:
|
|
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.3 → 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.3 → 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.3 → 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.3 → 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.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/__main__.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/check.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/cli.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.3 → 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.3 → modern_python_guidance-0.4.5}/src/modern_python_guidance/retrieve.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.3 → 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
|