Repository navigation
cli: reject init --force at the curriculum source #71
Description
Motivation
Running forced initialization from a source checkout can crash after Pythonlings resolves the destination to the same directory as its bundled curriculum. A contributor-facing command should reject that target before attempting any copy.
Current evidence
Deep QA on dev at e1d4dae37234b75124bd6a53f06734296ebbbdee reproduced this twice in disposable copies:
PYTHONPATH=<source-copy> python -m pythonlings init --path <source-copy> --force
shutil.SameFileError: <source-copy>/info.toml and <source-copy>/info.toml are the same fileThe command exits 1 with a traceback. init_workspace() starts copying before checking whether path equals source_root(). update_workspace() already rejects the equivalent source target.
Exact scope
Reject forced initialization when the resolved destination is the curriculum source, before any file is copied or removed. Return a concise pythonlings: error through the existing CLI error path.
Acceptance checklist
-
init --path <curriculum-source> --forceexits non-zero without a traceback. - The source checkout is unchanged after the rejected command.
- The error identifies that the curriculum source cannot be initialized in place.
- Forced initialization of a different existing workspace retains its current behavior.
- First initialization and repeated non-forced initialization retain their current behavior.
- Regression coverage exercises the resolved same-path case.
Explicit exclusions
Do not change update target precedence, overwrite semantics for a normal learner workspace, curriculum copy layout, or automatic workspace discovery.
Likely files
pythonlings/core/curriculum.pypythonlings/cli.pytests/unit/test_curriculum.pytests/integration/test_cli_workspace.py
Verification
python -m pytest tests/unit/test_curriculum.py tests/integration/test_cli_workspace.py -q
python -m pytest -q
pythonlings --root tests/fixtures/passing_curriculum verifyRepeat the same-path command against a disposable source copy and confirm its tree hash is unchanged.
Sprint coordination
See Discussion #37 and tracker #52. This issue is intentionally unassigned. A coordination comment is welcome, but it does not reserve the issue. The first pull request that satisfies every acceptance criterion and verification requirement is considered for merge.
Activity
coderabbitai commentedon Aug 18, 2026
🔗 Related PRs
#53 - fix: preserve workspace gitignore entries [merged]
#54 - fix: wrap malformed info.toml failures in ManifestError [merged]
#66 - release: promote v0.4.2 to main [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
Azaucifer commentedon Sep 16, 2026
I've submitted a fix for this in #147.
The change adds a same-path guard in
init_workspace()before any copy, mirroring the existing guard inupdate_workspace(). It also adds unit and integration regression tests for the resolved same-path case.All acceptance criteria are met, and I verified:
Closes #71