modern-python-guidance 0.1.0__py3-none-any.whl

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 (45) hide show
  1. modern_python_guidance/__init__.py +3 -0
  2. modern_python_guidance/__main__.py +5 -0
  3. modern_python_guidance/cli.py +202 -0
  4. modern_python_guidance/compat.py +22 -0
  5. modern_python_guidance/frontmatter.py +166 -0
  6. modern_python_guidance/guide_index.py +96 -0
  7. modern_python_guidance/retrieve.py +56 -0
  8. modern_python_guidance/search.py +149 -0
  9. modern_python_guidance/skills/modern-python-guidance/SKILL.md +104 -0
  10. modern_python_guidance/skills/modern-python-guidance/guides/async/async-timeout-context.md +65 -0
  11. modern_python_guidance/skills/modern-python-guidance/guides/async/exception-groups.md +70 -0
  12. modern_python_guidance/skills/modern-python-guidance/guides/async/taskgroup-over-gather.md +63 -0
  13. modern_python_guidance/skills/modern-python-guidance/guides/data-structures/dataclass-modern.md +73 -0
  14. modern_python_guidance/skills/modern-python-guidance/guides/data-structures/dict-merge-operator.md +63 -0
  15. modern_python_guidance/skills/modern-python-guidance/guides/data-structures/match-case-patterns.md +70 -0
  16. modern_python_guidance/skills/modern-python-guidance/guides/fastapi/fastapi-annotated-depends.md +80 -0
  17. modern_python_guidance/skills/modern-python-guidance/guides/fastapi/fastapi-lifespan.md +77 -0
  18. modern_python_guidance/skills/modern-python-guidance/guides/fastapi/fastapi-typed-state.md +76 -0
  19. modern_python_guidance/skills/modern-python-guidance/guides/httpx/httpx-async-client-reuse.md +70 -0
  20. modern_python_guidance/skills/modern-python-guidance/guides/httpx/httpx-streaming.md +66 -0
  21. modern_python_guidance/skills/modern-python-guidance/guides/pydantic/pydantic-v2-config.md +73 -0
  22. modern_python_guidance/skills/modern-python-guidance/guides/pydantic/pydantic-v2-model-api.md +79 -0
  23. modern_python_guidance/skills/modern-python-guidance/guides/pydantic/pydantic-v2-serialization.md +71 -0
  24. modern_python_guidance/skills/modern-python-guidance/guides/pydantic/pydantic-v2-validators.md +83 -0
  25. modern_python_guidance/skills/modern-python-guidance/guides/stdlib/datetime-utc.md +56 -0
  26. modern_python_guidance/skills/modern-python-guidance/guides/stdlib/pathlib-over-os-path.md +68 -0
  27. modern_python_guidance/skills/modern-python-guidance/guides/stdlib/removeprefix-removesuffix.md +64 -0
  28. modern_python_guidance/skills/modern-python-guidance/guides/stdlib/tomllib-builtin.md +59 -0
  29. modern_python_guidance/skills/modern-python-guidance/guides/toolchain/no-pickle.md +79 -0
  30. modern_python_guidance/skills/modern-python-guidance/guides/toolchain/pyproject-toml-over-setup.md +69 -0
  31. modern_python_guidance/skills/modern-python-guidance/guides/toolchain/ruff-over-flake8.md +90 -0
  32. modern_python_guidance/skills/modern-python-guidance/guides/toolchain/safe-subprocess.md +79 -0
  33. modern_python_guidance/skills/modern-python-guidance/guides/toolchain/uv-over-pip.md +68 -0
  34. modern_python_guidance/skills/modern-python-guidance/guides/typing/override-decorator.md +65 -0
  35. modern_python_guidance/skills/modern-python-guidance/guides/typing/paramspec-decorators.md +81 -0
  36. modern_python_guidance/skills/modern-python-guidance/guides/typing/type-parameter-syntax.md +66 -0
  37. modern_python_guidance/skills/modern-python-guidance/guides/typing/typeis-vs-typeguard.md +66 -0
  38. modern_python_guidance/skills/modern-python-guidance/guides/typing/union-syntax.md +59 -0
  39. modern_python_guidance/skills/modern-python-guidance/guides/typing/use-builtin-generics.md +61 -0
  40. modern_python_guidance/version_detect.py +136 -0
  41. modern_python_guidance-0.1.0.dist-info/METADATA +180 -0
  42. modern_python_guidance-0.1.0.dist-info/RECORD +45 -0
  43. modern_python_guidance-0.1.0.dist-info/WHEEL +4 -0
  44. modern_python_guidance-0.1.0.dist-info/entry_points.txt +3 -0
  45. modern_python_guidance-0.1.0.dist-info/licenses/LICENSE +190 -0
@@ -0,0 +1,66 @@
1
+ ---
2
+ id: typeis-vs-typeguard
3
+ title: Use TypeIs for Precise Type Narrowing
4
+ category: typing
5
+ layer: 1
6
+ tags:
7
+ - type-hints
8
+ - narrowing
9
+ - typeguard
10
+ aliases:
11
+ - TypeGuard
12
+ - typing.TypeGuard
13
+ - typing.TypeIs
14
+ python: ">=3.13"
15
+ frequency: low
16
+ pep: 742
17
+ ---
18
+
19
+ # Use TypeIs for Precise Type Narrowing
20
+
21
+ Since Python 3.13, use `TypeIs` instead of `TypeGuard` for type narrowing functions. `TypeIs` narrows in both branches (true and false), while `TypeGuard` only narrows in the true branch.
22
+
23
+ ## BAD
24
+
25
+ ```python
26
+ from typing import TypeGuard
27
+
28
+ def is_str(val: str | int) -> TypeGuard[str]:
29
+ return isinstance(val, str)
30
+
31
+ def process(val: str | int) -> None:
32
+ if is_str(val):
33
+ print(val.upper()) # OK: narrowed to str
34
+ else:
35
+ print(val + 1) # ERROR: still str | int, not narrowed to int
36
+ ```
37
+
38
+ ## GOOD
39
+
40
+ ```python
41
+ from typing import TypeIs
42
+
43
+ def is_str(val: str | int) -> TypeIs[str]:
44
+ return isinstance(val, str)
45
+
46
+ def process(val: str | int) -> None:
47
+ if is_str(val):
48
+ print(val.upper()) # OK: narrowed to str
49
+ else:
50
+ print(val + 1) # OK: narrowed to int
51
+ ```
52
+
53
+ ## Why
54
+
55
+ - `TypeIs` narrows both branches — the false branch gets the complement type
56
+ - `TypeGuard` was too permissive — it could widen types unsoundly
57
+ - Safer and more precise for runtime type checking functions
58
+
59
+ ## Version Notes
60
+
61
+ - 3.13+: `from typing import TypeIs`
62
+ - 3.10-3.12: `from typing_extensions import TypeIs`
63
+
64
+ ## References
65
+
66
+ - [PEP 742 — Narrowing types with TypeIs](https://peps.python.org/pep-0742/)
@@ -0,0 +1,59 @@
1
+ ---
2
+ id: union-syntax
3
+ title: Use X | Y Union Syntax Instead of Optional/Union
4
+ category: typing
5
+ layer: 1
6
+ tags:
7
+ - type-hints
8
+ - union
9
+ - optional
10
+ aliases:
11
+ - Optional
12
+ - typing.Union
13
+ - typing.Optional
14
+ python: ">=3.10"
15
+ frequency: high
16
+ pep: 604
17
+ ---
18
+
19
+ # Use X | Y Union Syntax
20
+
21
+ Since Python 3.10, use the `|` operator for union types instead of `Union` or `Optional` from `typing`.
22
+
23
+ ## BAD
24
+
25
+ ```python
26
+ from typing import Optional, Union
27
+
28
+ def find(name: str) -> Optional[int]:
29
+ ...
30
+
31
+ def parse(value: Union[str, int, float]) -> str:
32
+ ...
33
+ ```
34
+
35
+ ## GOOD
36
+
37
+ ```python
38
+ def find(name: str) -> int | None:
39
+ ...
40
+
41
+ def parse(value: str | int | float) -> str:
42
+ ...
43
+ ```
44
+
45
+ ## Why
46
+
47
+ - Shorter, more readable syntax
48
+ - `Optional[X]` is just `Union[X, None]` — the new syntax makes `None` explicit
49
+ - Works in `isinstance()` checks too: `isinstance(x, str | int)`
50
+ - `Union` and `Optional` are deprecated since 3.10
51
+
52
+ ## Version Notes
53
+
54
+ - 3.10+: `X | Y` in annotations and `isinstance()`/`issubclass()`
55
+ - 3.9: Use `from __future__ import annotations` for deferred evaluation only
56
+
57
+ ## References
58
+
59
+ - [PEP 604 — Allow writing union types as X | Y](https://peps.python.org/pep-0604/)
@@ -0,0 +1,61 @@
1
+ ---
2
+ id: use-builtin-generics
3
+ title: Use Built-in Generic Types Instead of typing Module
4
+ category: typing
5
+ layer: 1
6
+ tags:
7
+ - type-hints
8
+ - generics
9
+ - typing
10
+ aliases:
11
+ - typing.List
12
+ - typing.Dict
13
+ - typing.Optional
14
+ - typing.Tuple
15
+ - typing.Set
16
+ python: ">=3.9"
17
+ frequency: high
18
+ pep: 585
19
+ ---
20
+
21
+ # Use Built-in Generic Types
22
+
23
+ Since Python 3.9, built-in types support subscript syntax directly. The `typing` module aliases are deprecated.
24
+
25
+ ## BAD
26
+
27
+ ```python
28
+ from typing import Dict, List, Optional, Set, Tuple
29
+
30
+ def process(items: List[str]) -> Dict[str, int]:
31
+ seen: Set[str] = set()
32
+ pair: Tuple[str, int] = ("a", 1)
33
+ name: Optional[str] = None
34
+ return {}
35
+ ```
36
+
37
+ ## GOOD
38
+
39
+ ```python
40
+ def process(items: list[str]) -> dict[str, int]:
41
+ seen: set[str] = set()
42
+ pair: tuple[str, int] = ("a", 1)
43
+ name: str | None = None
44
+ return {}
45
+ ```
46
+
47
+ ## Why
48
+
49
+ - Fewer imports, cleaner code
50
+ - Same runtime types used in annotations
51
+ - `typing` aliases deprecated since 3.9, scheduled for removal in 3.14+
52
+
53
+ ## Version Notes
54
+
55
+ - 3.9+: `list[str]`, `dict[str, int]`, `tuple[str, int]`, `set[str]`
56
+ - 3.10+: `str | None` replaces `Optional[str]` (PEP 604)
57
+
58
+ ## References
59
+
60
+ - [PEP 585 — Type Hinting Generics In Standard Collections](https://peps.python.org/pep-0585/)
61
+ - [PEP 604 — Allow writing union types as X | Y](https://peps.python.org/pep-0604/)
@@ -0,0 +1,136 @@
1
+ """Detect the target Python version for a project.
2
+
3
+ Precedence chain:
4
+ 1. CLI --python-version flag (explicit override)
5
+ 2. pyproject.toml [project].requires-python (PEP 621)
6
+ 3. .python-version file (pyenv/asdf)
7
+ 4. Default: 3.11
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import logging
13
+ import re
14
+ import tomllib
15
+ from pathlib import Path
16
+
17
+ from packaging.specifiers import InvalidSpecifier, SpecifierSet
18
+ from packaging.version import Version
19
+
20
+ log = logging.getLogger(__name__)
21
+
22
+ DEFAULT_VERSION = "3.11"
23
+
24
+ _KNOWN_MINORS = [
25
+ Version(f"3.{minor}") for minor in range(7, 20)
26
+ ]
27
+
28
+ _POETRY_CARET_RE = re.compile(r"\^(\d+\.\d+)")
29
+
30
+
31
+ def detect_version(
32
+ *,
33
+ cli_version: str | None = None,
34
+ project_dir: Path | None = None,
35
+ ) -> str:
36
+ if cli_version is not None:
37
+ return _normalize(cli_version)
38
+
39
+ if project_dir is None:
40
+ project_dir = Path.cwd()
41
+
42
+ project_dir = project_dir.resolve()
43
+
44
+ pyproject = project_dir / "pyproject.toml"
45
+ if pyproject.is_file():
46
+ result = _from_pyproject(pyproject)
47
+ if result is not None:
48
+ return result
49
+
50
+ python_version_file = project_dir / ".python-version"
51
+ if python_version_file.is_file():
52
+ result = _from_python_version_file(python_version_file)
53
+ if result is not None:
54
+ return result
55
+
56
+ log.info("No version config found, using default %s", DEFAULT_VERSION)
57
+ return DEFAULT_VERSION
58
+
59
+
60
+ def _from_pyproject(path: Path) -> str | None:
61
+ try:
62
+ data = tomllib.loads(path.read_text(encoding="utf-8"))
63
+ except (OSError, tomllib.TOMLDecodeError) as e:
64
+ log.warning("Failed to parse %s: %s", path, e)
65
+ return None
66
+
67
+ requires_python = data.get("project", {}).get("requires-python")
68
+ if requires_python:
69
+ return _min_version_from_specifier(requires_python)
70
+
71
+ poetry_python = (
72
+ data.get("tool", {}).get("poetry", {}).get("dependencies", {}).get("python")
73
+ )
74
+ if poetry_python:
75
+ m = _POETRY_CARET_RE.search(str(poetry_python))
76
+ if m:
77
+ log.warning(
78
+ "Poetry caret version '%s' is not PEP 440 — cannot parse precisely. "
79
+ "Use --python-version or add [project].requires-python to pyproject.toml.",
80
+ poetry_python,
81
+ )
82
+ else:
83
+ log.warning(
84
+ "Poetry python constraint '%s' detected but not supported. "
85
+ "Use --python-version or add [project].requires-python.",
86
+ poetry_python,
87
+ )
88
+ return None
89
+
90
+ return None
91
+
92
+
93
+ def _from_python_version_file(path: Path) -> str | None:
94
+ try:
95
+ content = path.read_text(encoding="utf-8").strip()
96
+ except OSError as e:
97
+ log.warning("Failed to read %s: %s", path, e)
98
+ return None
99
+
100
+ if not content or content == "system":
101
+ return None
102
+
103
+ if content.startswith("pypy") or content.startswith("graalpy"):
104
+ log.info("Skipping non-CPython version: %s", content)
105
+ return None
106
+
107
+ match = re.match(r"(\d+\.\d+)", content)
108
+ if match:
109
+ return match.group(1)
110
+
111
+ return None
112
+
113
+
114
+ def _min_version_from_specifier(spec_str: str) -> str | None:
115
+ try:
116
+ spec = SpecifierSet(spec_str)
117
+ except InvalidSpecifier:
118
+ log.warning("Invalid version specifier: %s", spec_str)
119
+ return None
120
+
121
+ for v in _KNOWN_MINORS:
122
+ if v in spec:
123
+ return f"{v.major}.{v.minor}"
124
+ high_patch = Version(f"{v.major}.{v.minor}.99")
125
+ if high_patch in spec:
126
+ return f"{v.major}.{v.minor}"
127
+
128
+ log.warning("No known Python version matches specifier: %s", spec_str)
129
+ return None
130
+
131
+
132
+ def _normalize(version: str) -> str:
133
+ match = re.match(r"(\d+\.\d+)", version)
134
+ if match:
135
+ return match.group(1)
136
+ return version
@@ -0,0 +1,180 @@
1
+ Metadata-Version: 2.4
2
+ Name: modern-python-guidance
3
+ Version: 0.1.0
4
+ Summary: Version-aware BAD/GOOD pattern guides that help AI coding agents generate modern Python
5
+ Project-URL: Homepage, https://github.com/yottayoshida/modern-python-guidance
6
+ Project-URL: Repository, https://github.com/yottayoshida/modern-python-guidance
7
+ Project-URL: Issues, https://github.com/yottayoshida/modern-python-guidance/issues
8
+ Author-email: Iori Yoshida <i.yoshida@raksul.com>
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
11
+ Keywords: ai,coding-agent,guidance,linter,modernization,python
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: packaging>=23.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7.0; extra == 'dev'
27
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # modern-python-guidance
31
+
32
+ [![CI](https://github.com/yottayoshida/modern-python-guidance/actions/workflows/ci.yml/badge.svg)](https://github.com/yottayoshida/modern-python-guidance/actions/workflows/ci.yml)
33
+ [![PyPI version](https://img.shields.io/pypi/v/modern-python-guidance.svg)](https://pypi.org/project/modern-python-guidance/)
34
+ [![Python](https://img.shields.io/pypi/pyversions/modern-python-guidance.svg)](https://pypi.org/project/modern-python-guidance/)
35
+ [![License](https://img.shields.io/github/license/yottayoshida/modern-python-guidance.svg)](LICENSE)
36
+
37
+ LLMs often produce outdated Python — `typing.List` instead of `list`, `@validator` instead of `@field_validator`, `setup.py` instead of `pyproject.toml`. This tool provides 30 version-aware BAD/GOOD pattern guides that show the modern replacement, filtered by your project's Python version.
38
+
39
+ > **Note:** The tool itself requires Python 3.11+ to run. Guides cover patterns from Python 3.9 onward, and `--python-version` filters guides for your target environment.
40
+
41
+ ## Quick start
42
+
43
+ ```bash
44
+ # Install
45
+ pip install modern-python-guidance
46
+
47
+ # Search for a pattern
48
+ mpg search "typing list"
49
+ # use-builtin-generics score=18.0 [typing]
50
+
51
+ # Get the full guide
52
+ mpg retrieve use-builtin-generics
53
+ # --- use-builtin-generics (version match: YES) ---
54
+ # ## BAD
55
+ # from typing import List, Dict, Optional
56
+ # ...
57
+ # ## GOOD
58
+ # names: list[str] = []
59
+ # ...
60
+ ```
61
+
62
+ `mpg` is the short alias for `modern-python-guidance`. Both work.
63
+
64
+ ## CLI usage
65
+
66
+ ```bash
67
+ # Search guides by keyword
68
+ mpg search "pydantic validator"
69
+
70
+ # Retrieve a specific guide (full BAD/GOOD content)
71
+ mpg retrieve use-builtin-generics
72
+
73
+ # List all guides compatible with your Python version
74
+ mpg list --python-version 3.11
75
+
76
+ # Auto-detect project Python version from pyproject.toml / .python-version
77
+ mpg detect-version
78
+
79
+ # Filter by category
80
+ mpg search "timeout" --category async
81
+
82
+ # JSON output (default when piped, explicit with --format)
83
+ mpg search "typing" --format json | jq '.[0].id'
84
+ ```
85
+
86
+ ## Guide coverage
87
+
88
+ 30 guides across 3 layers:
89
+
90
+ | Layer | Categories | Count | Examples |
91
+ |-------|-----------|-------|---------|
92
+ | **1 — stdlib** | typing, async, stdlib, data-structures | 16 | `list` over `List`, `match`/`case`, `TaskGroup` |
93
+ | **2 — frameworks** | pydantic, fastapi, httpx | 9 | Pydantic V2 migration, `Annotated[Depends]`, `AsyncClient` |
94
+ | **3 — toolchain** | toolchain | 5 | `uv` over `pip`, `ruff` over flake8, `pickle` avoidance |
95
+
96
+ Run `mpg list` to see all 30 guides, or [browse them on GitHub](skills/modern-python-guidance/guides/).
97
+
98
+ ## Version-aware filtering
99
+
100
+ Guides specify their minimum Python version. The CLI auto-detects your project's version from (in order):
101
+
102
+ 1. `--python-version` flag
103
+ 2. `pyproject.toml` `requires-python`
104
+ 3. `.python-version` file
105
+ 4. Default: 3.11
106
+
107
+ ```bash
108
+ # Only shows guides compatible with Python 3.9
109
+ mpg list --python-version 3.9
110
+ # Excludes: TaskGroup (3.11+), match/case (3.10+), etc.
111
+ ```
112
+
113
+ ## Agent Skills integration
114
+
115
+ This project doubles as a [Claude Code Agent Skills](https://docs.anthropic.com/en/docs/claude-code) plugin. Install it into your project's `.claude/skills/` to give Claude automatic access to modern Python patterns when writing or reviewing code.
116
+
117
+ ```bash
118
+ # Find where the package is installed
119
+ SKILL_DIR=$(python -c "from pathlib import Path; import modern_python_guidance; print(Path(modern_python_guidance.__file__).parent / 'skills' / 'modern-python-guidance')")
120
+
121
+ # Symlink into your project
122
+ ln -s "$SKILL_DIR" your-project/.claude/skills/modern-python-guidance
123
+ ```
124
+
125
+ For other AI tools (Cursor, Copilot, etc.), use the CLI directly — pipe `mpg search` or `mpg retrieve` output into your workflow.
126
+
127
+ ## Development
128
+
129
+ ```bash
130
+ git clone https://github.com/yottayoshida/modern-python-guidance.git
131
+ cd modern-python-guidance
132
+ uv venv && source .venv/bin/activate
133
+ uv pip install -e ".[dev]"
134
+ pytest
135
+ ruff check src/ tests/
136
+ ```
137
+
138
+ ### Project structure
139
+
140
+ ```
141
+ src/modern_python_guidance/
142
+ ├── cli.py # Entry point (search, retrieve, list, detect-version)
143
+ ├── frontmatter.py # YAML-subset parser (no PyYAML dependency)
144
+ ├── guide_index.py # Guide discovery and indexing
145
+ ├── search.py # Weighted keyword search + fuzzy fallback
146
+ ├── retrieve.py # Guide retrieval and JSON rendering
147
+ ├── version_detect.py # Python version auto-detection
148
+ └── compat.py # Shared helpers
149
+
150
+ skills/modern-python-guidance/
151
+ ├── SKILL.md # Agent Skills plugin entry point
152
+ └── guides/ # 30 guide files by category
153
+ ```
154
+
155
+ See [docs/design.md](docs/design.md) for the full design document.
156
+
157
+ ## Contributing
158
+
159
+ Contributions welcome! To add a new guide:
160
+
161
+ 1. Create `skills/modern-python-guidance/guides/<category>/<id>.md`
162
+ 2. Include YAML frontmatter with these fields:
163
+
164
+ | Field | Type | Values |
165
+ |-------|------|--------|
166
+ | `id` | string | Unique kebab-case identifier (must match filename) |
167
+ | `title` | string | Short descriptive title |
168
+ | `category` | string | Must match parent directory name |
169
+ | `layer` | int | 1 (stdlib), 2 (frameworks), 3 (toolchain) |
170
+ | `tags` | list | Search keywords |
171
+ | `aliases` | list | Alternate names (old API names, etc.) |
172
+ | `python` | string | Minimum version, e.g. `">=3.11"` |
173
+ | `frequency` | string | `high` (LLMs do this often), `medium`, `low` |
174
+
175
+ 3. Write BAD/GOOD/Why/Version Notes sections
176
+ 4. Run `pytest` to verify the guide parses correctly
177
+
178
+ ## License
179
+
180
+ Apache-2.0 — see [LICENSE](LICENSE).
@@ -0,0 +1,45 @@
1
+ modern_python_guidance/skills/modern-python-guidance/SKILL.md,sha256=rvrHlSSS9MPOcdVKuhAp1v1aQjeRZsCgXUX17l9I7b0,5028
2
+ modern_python_guidance/skills/modern-python-guidance/guides/async/async-timeout-context.md,sha256=a0le-QAqt9csyd7tMT3TeN5cx_nEsDv2pUHdQrlr_Yc,1668
3
+ modern_python_guidance/skills/modern-python-guidance/guides/async/exception-groups.md,sha256=_K8E8I_8U5Wm2c8Ywvl93HRsB3vjijXlqL4shelo-DA,1684
4
+ modern_python_guidance/skills/modern-python-guidance/guides/async/taskgroup-over-gather.md,sha256=-gyHQwcdBw0UxNVAfk5dIujN1BfSJRzWBlWZIdlH2FI,1604
5
+ modern_python_guidance/skills/modern-python-guidance/guides/data-structures/dataclass-modern.md,sha256=ZzU5xh9CbV12eGTVYhZZ1y3A6gqrnUJmP_4KWZ8jEAk,1652
6
+ modern_python_guidance/skills/modern-python-guidance/guides/data-structures/dict-merge-operator.md,sha256=6rVL98bmyjz3MImJGxjZToLlv8UZiLApSImGpc6KRdc,1242
7
+ modern_python_guidance/skills/modern-python-guidance/guides/data-structures/match-case-patterns.md,sha256=qWgCIYFtFMRCv-9qKLiRBKw7LqMn9QPCRpGHkcG6yXo,1893
8
+ modern_python_guidance/skills/modern-python-guidance/guides/fastapi/fastapi-annotated-depends.md,sha256=VKqrqPv50f6ODOsmi5mjQWzMzaSoOsMjblZcvIRydWM,1759
9
+ modern_python_guidance/skills/modern-python-guidance/guides/fastapi/fastapi-lifespan.md,sha256=yf94C4AS1LfT9cYgzwi5ZFwxiKbLpON5nY2voixKRgQ,1619
10
+ modern_python_guidance/skills/modern-python-guidance/guides/fastapi/fastapi-typed-state.md,sha256=AqQVDLYNys7ILbuQbFxag5RJMqY1zz5aqwWng6IvupU,1769
11
+ modern_python_guidance/skills/modern-python-guidance/guides/httpx/httpx-async-client-reuse.md,sha256=zlA3TE4HR-PJE1gOveEEWcMk8GH9p1fqm-oNqXUH5LI,1865
12
+ modern_python_guidance/skills/modern-python-guidance/guides/httpx/httpx-streaming.md,sha256=hnDxLKXTJ65-jZj0fmCJUPqi6OW2lLuejRV2p8eHrQA,1769
13
+ modern_python_guidance/skills/modern-python-guidance/guides/pydantic/pydantic-v2-config.md,sha256=_e1gxOrlW-cIFSnJcRAEjmEResNRR7ZdGy-lcXb5vwQ,1819
14
+ modern_python_guidance/skills/modern-python-guidance/guides/pydantic/pydantic-v2-model-api.md,sha256=Ip4X_M5cnnXWRTC7UhqZ8LD_ZZs_9NgRZphk5u_rAiY,1733
15
+ modern_python_guidance/skills/modern-python-guidance/guides/pydantic/pydantic-v2-serialization.md,sha256=l8xJFOxobo3BSkyOIOjfoIA7u_CR0LOTtB1q8oroyo8,1632
16
+ modern_python_guidance/skills/modern-python-guidance/guides/pydantic/pydantic-v2-validators.md,sha256=EVatseVapfnv88omr733TCjTDtmDM_kqED7HbK_tanI,1969
17
+ modern_python_guidance/skills/modern-python-guidance/guides/stdlib/datetime-utc.md,sha256=sbGPNQ8TfY0PQwSyvz7zOokZlNujNb6_TPDENia-_hU,1330
18
+ modern_python_guidance/skills/modern-python-guidance/guides/stdlib/pathlib-over-os-path.md,sha256=mYhjm3BWHVLM83Cv1b8Dae_J3h0r5QDgwLVsm-EtCjQ,1581
19
+ modern_python_guidance/skills/modern-python-guidance/guides/stdlib/removeprefix-removesuffix.md,sha256=6E_nnA_31z2LkECO3NF1iFfjK6bIXzWLZdWu0ncm9Fk,1597
20
+ modern_python_guidance/skills/modern-python-guidance/guides/stdlib/tomllib-builtin.md,sha256=0vgz24ayYBS3UYSlZT81eOAM5BE5dM04hevZdjwufrs,1196
21
+ modern_python_guidance/skills/modern-python-guidance/guides/toolchain/no-pickle.md,sha256=2zQaYb2gQ0bhX2IVcigeMNn-QkyNrNFZtLOyHWcBLRM,1957
22
+ modern_python_guidance/skills/modern-python-guidance/guides/toolchain/pyproject-toml-over-setup.md,sha256=V9ENRTKpXtEKguQKXvaLXnthJd0j63-H1tb9lvVEqGQ,1435
23
+ modern_python_guidance/skills/modern-python-guidance/guides/toolchain/ruff-over-flake8.md,sha256=Y0geL7xJGuD9ocRYlcZWlM1_Q7T5qBD7NfnMO3z3z34,1703
24
+ modern_python_guidance/skills/modern-python-guidance/guides/toolchain/safe-subprocess.md,sha256=-B-DUJPzfWH8XO6ywTgPMjlVCD2ah6SyHsm6b0oWLxE,2199
25
+ modern_python_guidance/skills/modern-python-guidance/guides/toolchain/uv-over-pip.md,sha256=ExnUwbVttKkORPkhqEAAxERiWo1kjPKKnsPBMonXwUs,1412
26
+ modern_python_guidance/skills/modern-python-guidance/guides/typing/override-decorator.md,sha256=L4PjDCg2NlGr-WG747u6uvZxgTMBAvVuhKDFWCM0-y0,1351
27
+ modern_python_guidance/skills/modern-python-guidance/guides/typing/paramspec-decorators.md,sha256=0hY88AYPJUE5AzALhvgxFhP8OEBINqEjEIfszcZISsM,1949
28
+ modern_python_guidance/skills/modern-python-guidance/guides/typing/type-parameter-syntax.md,sha256=QnQiu2kDYCd1tXKyb07iOhdOpgjP34WxP26fGvbKG1M,1359
29
+ modern_python_guidance/skills/modern-python-guidance/guides/typing/typeis-vs-typeguard.md,sha256=-68eMjwdn2XmmoPsUOyhI-27L13idL7dDeD-MdPqKE0,1514
30
+ modern_python_guidance/skills/modern-python-guidance/guides/typing/union-syntax.md,sha256=_BhYvxWq6MpRwL1w8VD8kiRGI_T4eUHZXfuIe8qZA70,1169
31
+ modern_python_guidance/skills/modern-python-guidance/guides/typing/use-builtin-generics.md,sha256=qFqKUlcICRH1FDQ54GTb3Q24_TYuq9TBynOEx5zCgC0,1349
32
+ modern_python_guidance/__init__.py,sha256=KLQC9PrsroRzCtfjT-gsjLg4E81Wx_iwLDxf4Z97I-4,116
33
+ modern_python_guidance/__main__.py,sha256=85nXGivCWEBw00evsgIQg6bhuHnb7-r9AVMdXoMVuco,112
34
+ modern_python_guidance/cli.py,sha256=exS4himsrvOiBOwwPri-tAvx6v7H_Q72B36SPRNfpiw,6492
35
+ modern_python_guidance/compat.py,sha256=uwBN9UxSTkCUX3GXdy5CfsjdrosWafon8r2X2n-hAOg,537
36
+ modern_python_guidance/frontmatter.py,sha256=SMB2EpHQvFTqySyXWvbzzs8tnd4qfqrgMoBYsQkgU-g,5011
37
+ modern_python_guidance/guide_index.py,sha256=V3EGVtTdGS2keBLgi1KG2eREpYG02_mdGV-UZg894KU,2869
38
+ modern_python_guidance/retrieve.py,sha256=ufJjEhJ55co0fUqlbR2iSMOM7h9y9C3KRWTLVlGrgx4,1569
39
+ modern_python_guidance/search.py,sha256=bCWJqFLw_Ws6G6mqmKQwfZwVag2FByT9qlFxAtMHdSw,4193
40
+ modern_python_guidance/version_detect.py,sha256=lHV3_8WuvKQhSOZyLMD5JiVzcXHESdoBuNCg2VOMN1s,3772
41
+ modern_python_guidance-0.1.0.dist-info/METADATA,sha256=AbAm51k1hUsa--kASUUxcjwJu_Rd8DciEjMWr9SGfhg,6819
42
+ modern_python_guidance-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
43
+ modern_python_guidance-0.1.0.dist-info/entry_points.txt,sha256=IPgwIOIfxf7Pu-L5vMkZ1cKcR1h_BdckzCOtl_UXjTE,113
44
+ modern_python_guidance-0.1.0.dist-info/licenses/LICENSE,sha256=l0zB3WNmNAS1Kqgln4pHyO-u1I_PlHet06-UqZgfkNI,10763
45
+ modern_python_guidance-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ modern-python-guidance = modern_python_guidance.cli:main
3
+ mpg = modern_python_guidance.cli:main