modern-python-guidance 0.4.1__tar.gz → 0.4.2__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.1 → modern_python_guidance-0.4.2}/CHANGELOG.md +6 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/PKG-INFO +1 -1
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/pyproject.toml +1 -1
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/__init__.py +1 -1
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/setup_cmd.py +10 -11
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_setup.py +39 -3
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_uninstall.py +21 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/.github/workflows/check-python-release.yml +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/.github/workflows/ci.yml +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/.github/workflows/publish.yml +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/.gitignore +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/CONTRIBUTING.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/LICENSE +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/LICENSE-MIT +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/README.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/SECURITY.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/edge-cases/opus48_multiline.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/edge-cases/valid_alt_patterns.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-modern/pyproject.toml +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-modern/src/app.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-modern/src/config.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-modern/src/crawler.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-modern/src/models.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-modern/src/scanner.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-modern/src/utils.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-outdated/pyproject.toml +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-outdated/setup.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-outdated/src/app.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-outdated/src/config.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-outdated/src/crawler.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-outdated/src/models.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-outdated/src/scanner.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-a-outdated/src/utils.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-b-modern/myapp/models.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-b-modern/myapp/views.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-b-outdated/myapp/models.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-b-outdated/myapp/views.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-c-modern/tests/test_calculator.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/fixtures/variant-c-outdated/tests/test_calculator.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/mcp-config.json +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompt-v2.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompt-v3-mcp.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompt-v3.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompt-v4-a.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompt-v4-b.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompt-v4-c.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompt.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-a-detailed.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-a-normal.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-a-terse.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-b-detailed.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-b-normal.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-b-terse.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-c-detailed.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-c-normal.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-c-terse.txt +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/run-mcp.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/run-v4.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/run-v5.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/run.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/score-v2.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/score-v3.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/score-v4.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/score.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/score_v5.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/test-scorer.sh +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/docs/benchmark-evaluation.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/docs/benchmark-procedure.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/docs/benchmark-v5.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/docs/design.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/rules/modern-python.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/SKILL.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/async/async-timeout-context.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/async/exception-groups.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/async/taskgroup-over-gather.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/data-structures/dataclass-modern.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/data-structures/dict-merge-operator.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/data-structures/match-case-patterns.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/django/django-async-views.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/django/django-check-constraints.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/django/django-json-field.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/fastapi/fastapi-annotated-depends.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/fastapi/fastapi-lifespan.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/fastapi/fastapi-typed-state.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/httpx/httpx-async-client-reuse.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/httpx/httpx-streaming.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-config.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-model-api.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-serialization.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/pydantic/pydantic-v2-validators.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/pytest/pytest-parametrize.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/pytest/pytest-raises-match.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/pytest/pytest-tmp-path.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-2-style.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-async-session.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/sqlalchemy/sqlalchemy-mapped-column.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/stdlib/datetime-utc.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/stdlib/pathlib-over-os-path.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/stdlib/removeprefix-removesuffix.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/stdlib/template-strings.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/stdlib/tomllib-builtin.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/toolchain/no-pickle.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/toolchain/pyproject-toml-over-setup.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/toolchain/ruff-over-flake8.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/toolchain/safe-subprocess.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/toolchain/uv-over-pip.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/typing/deferred-annotations.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/typing/override-decorator.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/typing/paramspec-decorators.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/typing/type-parameter-syntax.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/typing/typeis-vs-typeguard.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/typing/union-syntax.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/skills/modern-python-guidance/guides/typing/use-builtin-generics.md +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/__main__.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/check.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/cli.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/compat.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/frontmatter.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/guide_index.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/mcp_server.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/retrieve.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/search.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/uninstall_cmd.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/version_detect.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_check.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_cli_integration.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_cli_unit.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_compat.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_frontmatter.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_guide_index.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_guide_structure.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_mcp_server.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_mcp_unit.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_retrieve.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_scorer_v5.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_search.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_skill_sync.py +0 -0
- {modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/tests/test_version_detect.py +0 -0
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.4.2] — 2026-06-04
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `_find_project_root()` escaping to `$HOME` when `~/.claude/` exists but the repo has no `.claude/` directory. Marker search is now per-level (nearest ancestor with any marker wins) instead of per-marker-type. If you previously ran `mpg setup` and have stale symlinks at `~/.claude/skills/modern-python-guidance` or `~/.claude/rules/modern-python.md`, remove them manually. (closes #90)
|
|
10
|
+
|
|
5
11
|
## [0.4.1] — 2026-06-03
|
|
6
12
|
|
|
7
13
|
### 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.2
|
|
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
|
|
@@ -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.2"
|
|
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"
|
|
@@ -61,20 +61,19 @@ def _find_rule_source() -> Path:
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def _find_project_root(start: Path | None = None) -> Path:
|
|
64
|
-
"""Walk upward
|
|
64
|
+
"""Walk upward; return the nearest ancestor containing any marker."""
|
|
65
65
|
current = (start or Path.cwd()).resolve()
|
|
66
|
-
markers = [".
|
|
66
|
+
markers = [".git", "pyproject.toml", ".claude"]
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if candidate.exists():
|
|
68
|
+
d = current
|
|
69
|
+
while True:
|
|
70
|
+
for marker in markers:
|
|
71
|
+
if (d / marker).exists():
|
|
73
72
|
return d
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
parent = d.parent
|
|
74
|
+
if parent == d:
|
|
75
|
+
break
|
|
76
|
+
d = parent
|
|
78
77
|
|
|
79
78
|
return current
|
|
80
79
|
|
|
@@ -59,13 +59,31 @@ class TestFindProjectRoot:
|
|
|
59
59
|
sub.mkdir(parents=True)
|
|
60
60
|
assert _find_project_root(sub) == tmp_path
|
|
61
61
|
|
|
62
|
-
def
|
|
63
|
-
"""
|
|
62
|
+
def test_nearest_marker_wins(self, tmp_path: Path):
|
|
63
|
+
"""Nearest ancestor with any marker wins over distant ancestor."""
|
|
64
64
|
(tmp_path / ".claude").mkdir()
|
|
65
65
|
child = tmp_path / "child"
|
|
66
66
|
child.mkdir()
|
|
67
67
|
(child / ".git").mkdir()
|
|
68
|
-
assert _find_project_root(child) ==
|
|
68
|
+
assert _find_project_root(child) == child
|
|
69
|
+
|
|
70
|
+
def test_bug_repro_home_claude_escapes(self, tmp_path: Path):
|
|
71
|
+
"""V-001: .claude at home + .git at repo -> repo wins, not home."""
|
|
72
|
+
home = tmp_path / "home"
|
|
73
|
+
(home / ".claude").mkdir(parents=True)
|
|
74
|
+
repo = home / "projects" / "repo"
|
|
75
|
+
repo.mkdir(parents=True)
|
|
76
|
+
(repo / ".git").mkdir()
|
|
77
|
+
src = repo / "src"
|
|
78
|
+
src.mkdir()
|
|
79
|
+
assert _find_project_root(src) == repo
|
|
80
|
+
|
|
81
|
+
def test_git_as_file(self, tmp_path: Path):
|
|
82
|
+
"""V-008: .git as a file (worktree/submodule) is detected."""
|
|
83
|
+
(tmp_path / ".git").write_text("gitdir: /some/other/path")
|
|
84
|
+
sub = tmp_path / "src"
|
|
85
|
+
sub.mkdir()
|
|
86
|
+
assert _find_project_root(sub) == tmp_path
|
|
69
87
|
|
|
70
88
|
def test_falls_back_to_cwd(self, tmp_path: Path):
|
|
71
89
|
bare = tmp_path / "empty"
|
|
@@ -308,6 +326,24 @@ class TestSetupSkills:
|
|
|
308
326
|
err = capsys.readouterr().err
|
|
309
327
|
assert "'" in err or '"' in err
|
|
310
328
|
|
|
329
|
+
def test_autodetect_avoids_home_escape(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
330
|
+
"""setup_skills auto-discovers repo root, not distant ~/.claude."""
|
|
331
|
+
source = self._make_source(tmp_path)
|
|
332
|
+
home = tmp_path / "home"
|
|
333
|
+
(home / ".claude").mkdir(parents=True)
|
|
334
|
+
repo = home / "projects" / "repo"
|
|
335
|
+
repo.mkdir(parents=True)
|
|
336
|
+
(repo / ".git").mkdir()
|
|
337
|
+
|
|
338
|
+
monkeypatch.chdir(repo)
|
|
339
|
+
with patch("modern_python_guidance.setup_cmd._find_skills_dir", return_value=source):
|
|
340
|
+
ok = setup_skills()
|
|
341
|
+
|
|
342
|
+
assert ok is True
|
|
343
|
+
link = repo / ".claude" / "skills" / "modern-python-guidance"
|
|
344
|
+
assert link.is_symlink()
|
|
345
|
+
assert not (home / ".claude" / "skills" / "modern-python-guidance").exists()
|
|
346
|
+
|
|
311
347
|
def test_dry_run(self, tmp_path: Path, capsys: pytest.CaptureFixture[str]):
|
|
312
348
|
"""V-010: dry-run does not create symlink."""
|
|
313
349
|
source = self._make_source(tmp_path)
|
|
@@ -248,6 +248,27 @@ class TestUninstallSkills:
|
|
|
248
248
|
assert link.is_symlink() # still there
|
|
249
249
|
assert "Would remove" in capsys.readouterr().out
|
|
250
250
|
|
|
251
|
+
def test_resolves_correct_root_not_distant_ancestor(
|
|
252
|
+
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
253
|
+
):
|
|
254
|
+
"""V-009: uninstall resolves nearest project root, not distant ancestor."""
|
|
255
|
+
home = tmp_path / "home"
|
|
256
|
+
(home / ".claude" / "skills" / "modern-python-guidance").mkdir(parents=True)
|
|
257
|
+
repo = home / "projects" / "repo"
|
|
258
|
+
repo.mkdir(parents=True)
|
|
259
|
+
(repo / ".git").mkdir()
|
|
260
|
+
link = repo / ".claude" / "skills" / "modern-python-guidance"
|
|
261
|
+
link.parent.mkdir(parents=True)
|
|
262
|
+
os.symlink(tmp_path / "pkg_skills", link)
|
|
263
|
+
|
|
264
|
+
monkeypatch.chdir(repo)
|
|
265
|
+
ok = uninstall_skills()
|
|
266
|
+
|
|
267
|
+
assert ok is True
|
|
268
|
+
assert not link.is_symlink()
|
|
269
|
+
# Home-level skills dir must be untouched
|
|
270
|
+
assert (home / ".claude" / "skills" / "modern-python-guidance").is_dir()
|
|
271
|
+
|
|
251
272
|
def test_non_symlink_path_quoted(self, tmp_path: Path, capsys):
|
|
252
273
|
"""V-028: rm hint uses shell-safe quoting for paths with spaces."""
|
|
253
274
|
project = tmp_path / "my project"
|
|
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.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-a-detailed.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/bench/prompts/v5-b-detailed.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/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
|
|
File without changes
|
{modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/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.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/__main__.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/check.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/cli.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/compat.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/src/modern_python_guidance/retrieve.py
RENAMED
|
File without changes
|
{modern_python_guidance-0.4.1 → modern_python_guidance-0.4.2}/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
|