-
Notifications
You must be signed in to change notification settings - Fork 0
Retire EnvLock and the env-mutation guards from test_support (#494) #583
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
leynos
merged 64 commits into
main
from
issue-494-retire-envlock-and-the-env-mutation-guards-from-test-support
Aug 31, 2026
Merged
Changes from all commits
Commits
Show all changes
64 commits
Select commit
Hold shift + click to select a range
bc7eb4b
Document Locize terminology and translation style
f10ab76
Rename Locize documents for localization scope
5490297
Add per-locale terminology sections for all 34 shipped locales
leynos 3bd42af
Scope the MD060 exception to the localization glossary
leynos f1a0026
Remove BDD process-global state (#492)
leynos 1c99f6d
Thread an explicit base directory into glob expansion
leynos 21db401
Migrate manifest glob integration tests off process CWD mutation
leynos 87373e4
Fix clippy findings in the glob base seam
leynos 9d33041
Keep walk and manifest modules within the line limit
leynos 7832082
Delete env_lock and cwd_guard from test_support
leynos 6f015f8
Gate in-process environment mutation in the lint target
leynos 9a28e25
Anchor BDD glob fixtures at the manifest directory
leynos c336f29
Fix glob base anchoring for relative and symlinked bases
leynos caa6460
Harden the env-mutation gate and refresh retired-CWD comments
leynos 24386dd
Document retired env-mutation utilities and fix glob base shadowing
leynos ca42b51
Split glob base tests into a dedicated module
leynos 602a819
Introduce a Utf8Path glob seam and split glob preparation from matching
leynos 373bcd3
Keep explicit config selectors independent of -C/--directory
leynos b0312e4
Align documentation with explicit-selector independence from -C
leynos 1082dc9
Fix BDD selector scenarios and lint gates after rebase
leynos e83c61f
Align scenario state table columns after global_state_lock removal
leynos 2622ab3
Keep discovery module within the 400-line limit
leynos b589ab3
Add injected-glob-base property tests through the glob_paths boundary
leynos 9256ec8
Add clippy env-policy UI coverage for process-CWD mutation vs Command…
leynos d1c0b7a
Align explicit-selector docs and harden glob-base property tests for …
leynos 1caec02
Register the clippy env-policy fixture manifest with Dependabot
leynos 83f59e1
Document the base-directory seam and -C anchoring as ADR-014
leynos b69245f
chore: archive backup for session c6635e5f
8127f1e
Anchor relative explicit config selectors to -C/--directory
leynos 0a42e18
Extract config-selector resolution into discovery_selector module
leynos 37bd9c6
Port the env-mutation gate to Python and adopt the scripting standards
leynos 0f5fdde
Fix spelling-gate finding in the scripting-standards section
leynos 6e7ac3c
Drop the stale env_lock line from the test_support crate docs
leynos 553e692
Mark the 3.11.5 EnvLock retirement roadmap items complete
leynos bc3e926
Gate the Unix-only glob base test imports with cfg(unix)
leynos 5005124
Fix cross-platform compilation of the glob capability tests
leynos d53ebe0
chore: archive backup for session 0cee541e
47598fe
Harden manifest glob base expansion (#494)
leynos 451a2d8
Fix Windows glob base tests
leynos a6df24a
Cover legal glob bases on Windows
leynos ff7682d
Fix Windows canonical glob bases
leynos 92bbcee
Compare absolute glob paths canonically
leynos 94366ad
Keep explicit config selectors independent of -C (#494)
leynos de7c1f8
Apply review repairs to environment seams (#494)
leynos 2fc9e0d
Align explicit selector documentation (#494)
leynos 2c7fefb
Preserve Windows glob base prefixes (#494)
leynos 3568b47
Repair rebase integration for discovery modules (#494)
leynos 9d37e16
Use sentence case in ADR-014 heading (#494)
leynos 3033158
Harden environment mutation and glob review gates (#494)
leynos e817285
Split manifest glob base preparation (#494)
leynos 7d7a5b2
Harden rebase review repairs (#494)
leynos 119f3b9
Stage mutation gates before parallel checks (#494)
leynos 500e40e
Rely on Clippy for environment policy (#494)
leynos 9659061
Cover glob benchmark Make target (#494)
leynos c157539
Remove duplicate Whitaker guidance (#494)
leynos 70b47cd
Align rebase repairs with formatting policy (#494)
leynos d72a882
Preserve Markdown and benchmark targets after rebase (#494)
leynos d24c612
Harden formatting and seam documentation (#494)
leynos 19246a1
Align Python rules with the 3.14 baseline (#494)
leynos 44838e4
Instrument glob base cache and align tooling docs (#494)
leynos ce49b9f
Deduplicate glob cache canonicalization metrics (#494)
leynos cc5d0f3
Instrument manifest-template glob expansion (#494)
leynos 9745feb
Deduplicate injected glob diagnostics setup (#494)
leynos 714d95e
Instrument template glob failure outcomes (#494)
leynos File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| # Python 3.14 code style guidelines (with Ruff, Pyright, and pytest) | ||
|
|
||
| ## Naming Conventions | ||
|
|
||
| - **Directories:** Use *snake_case* for top-level features or modules (e.g., | ||
| `data_pipeline`, `user_auth`). | ||
| - **Files:** Use *snake_case.py*; name for contents (e.g., `http_client.py`, | ||
| `task_queue.py`). | ||
| - **Classes:** Use *PascalCase*. | ||
| - **Variables & Functions:** Use *snake_case*. | ||
| - **Constants:** Use *UPPER_SNAKE_CASE* for module-level constants. | ||
| - **Private/Internal:** Prefix with a single underscore (`_`) for non-exported | ||
| helpers or internal APIs. | ||
|
|
||
| ## Python Typing Practices | ||
|
|
||
| - **Use typing everywhere.** Enable and maintain full static type coverage. Use | ||
| Pyright for type-checking. | ||
| - **Use `TypedDict` or `Dataclass` for structured data where appropriate.** For | ||
| internal-only usage, prefer `@dataclass(slots=True)`. | ||
| - **Avoid `Any`.** Prefer concrete types, `object`, generics, or type variables. | ||
| Use a documented `cast()` or `Any` only when the boundary requires it. | ||
| - **Be explicit with returns.** Use `-> None`, `-> str`, etc., for all public | ||
| functions and class methods. | ||
| - **Favour immutability.** Prefer tuples to lists, and `frozendict` or | ||
| `types.MappingProxyType` where appropriate. | ||
|
|
||
| ## Tooling and Runtime Practices | ||
|
|
||
| - **Enable Ruff.** Use Ruff to lint for performance, security, consistency, and | ||
| style issues. Enable fixers and formatters. | ||
| - Use `pyproject.toml` to configure tools like Ruff, Pyright, and Pytest. | ||
| - **Enforce `strict` in Pyright.** Treat all Pyright warnings as CI errors. Use | ||
| `# pyright: ignore` sparingly and with explanation. | ||
| - **Avoid side effects at import time.** Modules should not modify global state | ||
| or perform actions on import. | ||
| - **Use `.env` or settings modules** for environment-specific configuration. | ||
| Never hardcode secrets. | ||
|
|
||
| ## Linting and Formatting | ||
|
|
||
| - **Use Ruff for linting** (replacing flake8, isort, pyflakes, etc.). | ||
| - **Use Ruff for formatting**. Let Ruff handle whitespace and formatting | ||
| entirely—don't fight it. | ||
|
|
||
| ## Documentation | ||
|
|
||
| - **Use docstrings.** Document public functions, classes, and modules using | ||
| NumPy format. For example: | ||
|
|
||
| ```python | ||
| def scale(values: list[float], factor: float) -> list[float]: | ||
| """ | ||
| Scale a list of numbers by a given factor. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| values : list of float | ||
| The list of numeric values to scale. | ||
| factor : float | ||
| The multiplier to apply to each value. | ||
|
|
||
| Returns | ||
| ------- | ||
| list of float | ||
| The scaled numeric values. | ||
| """ | ||
| return [v * factor for v in values] | ||
| ``` | ||
|
|
||
| - **Explain tricky code.** Use inline comments for non-obvious logic or | ||
| decisions. | ||
| - **Colocate documentation.** Keep README.md or `docs/` near reusable packages; | ||
| include usage examples. | ||
|
|
||
| ## Testing with pytest | ||
|
|
||
| - **Colocate unit tests with code** using an `unittests` subdirectory and a | ||
| `test_` prefix. This keeps logic and its tests together: | ||
|
|
||
| ```text | ||
| user_auth/ | ||
| models.py | ||
| login_flow.py | ||
| unittests/ | ||
| test_models.py | ||
| test_login_flow.py | ||
| ``` | ||
|
|
||
| - **Structure integration tests separately.** When tests span multiple | ||
| components, use `tests/integration/`: | ||
|
|
||
| ```text | ||
| tests/ | ||
| integration/ | ||
| test_login_flow.py | ||
| test_user_onboarding.py | ||
| ``` | ||
|
|
||
| - **Use `pytest` idioms.** Prefer fixtures over setup/teardown methods. | ||
| Parametrize broadly. Avoid unnecessary mocks. | ||
|
|
||
| - **Group related tests** using `class` with method names prefixed by `test_`. | ||
|
|
||
| - **Write tests from a user's perspective.** Test public behaviour, not | ||
| internals. | ||
|
|
||
| - **Avoid mocking too much.** Prefer test doubles only for external services or | ||
| non-deterministic behaviours. | ||
|
|
||
| ## Example | ||
|
|
||
| ```python | ||
| # login_flow.py | ||
| def login_user(username: str, password: str) -> bool: | ||
| """Return True if the user is authenticated.""" | ||
| ... | ||
|
|
||
|
|
||
| # login_flow_test.py | ||
| def test_login_success(): | ||
| assert login_user("alice", "correct-password") is True | ||
|
|
||
|
|
||
| def test_login_failure(): | ||
| assert not login_user("alice", "wrong-password") | ||
| ``` | ||
|
|
||
| ______________________________________________________________________ | ||
|
|
||
| This style guide aims to foster clean, consistent, and maintainable Python 3.14 | ||
| code with modern tooling. The priority is correctness, clarity, and developer | ||
| empathy. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| # Using Context Managers for Cleanup and Resource Management | ||
|
|
||
| Use context managers to encapsulate setup and teardown logic cleanly and | ||
| safely. This reduces the risk of forgetting to release resources (files, locks, | ||
| connections, etc.) and simplifies error handling. | ||
|
|
||
| Context managers can be written either with `contextlib.contextmanager` (for | ||
| simple procedural control flow) or by implementing `__enter__` and `__exit__` | ||
| in a class (for more complex or stateful use cases). | ||
|
|
||
| ## Why Use Context Managers? | ||
|
|
||
| - **Safety:** Ensures cleanup occurs even if an exception is raised. | ||
| - **Clarity:** Reduces boilerplate and visually scopes side effects. | ||
| - **Reuse:** Common setup/teardown logic becomes reusable and composable. | ||
|
|
||
| ______________________________________________________________________ | ||
|
|
||
| ## Example: Using `contextlib.contextmanager` | ||
|
|
||
| Use this for straightforward procedural setup/teardown: | ||
|
|
||
| ```python | ||
| from contextlib import contextmanager | ||
|
|
||
|
|
||
| @contextmanager | ||
| def managed_file(path: str, mode: str): | ||
| f = open(path, mode) | ||
| try: | ||
| yield f | ||
| finally: | ||
| f.close() | ||
|
|
||
|
|
||
| # Usage: | ||
| with managed_file("/tmp/data.txt", "w") as f: | ||
| f.write("hello") | ||
| ``` | ||
|
|
||
| This avoids repeating `try/finally` in every file access. | ||
|
|
||
| ______________________________________________________________________ | ||
|
|
||
| ## Example: Using a Class-Based Context Manager | ||
|
|
||
| Use this when state or lifecycle logic spans methods: | ||
|
|
||
| ```python | ||
| class Resource: | ||
| def __enter__(self): | ||
| self.conn = connect() | ||
| return self.conn | ||
|
|
||
| def __exit__(self, exc_type, exc_val, exc_tb): | ||
| self.conn.close() | ||
|
|
||
|
|
||
| # Usage: | ||
| with Resource() as conn: | ||
| conn.send("ping") | ||
| ``` | ||
|
|
||
| This keeps state encapsulated and makes testing easier. | ||
|
|
||
| ______________________________________________________________________ | ||
|
|
||
| ## When to Use Which | ||
|
|
||
| - Use `@contextmanager` when control flow is linear and no persistent state is | ||
| required. | ||
|
|
||
| - Use a class when: | ||
|
|
||
| - There is internal state or methods tied to the resource lifecycle. | ||
| - You need to support re-entry or more advanced context features. | ||
|
|
||
| ______________________________________________________________________ | ||
|
|
||
| ## Common Use Cases | ||
|
|
||
| - File or network resource handling | ||
| - Lock acquisition and release | ||
| - Temporary resources and isolated environment changes (e.g., `patch`, | ||
| `tempfile`) | ||
| - Logging scope control or tracing | ||
| - Transaction control in databases or services | ||
|
|
||
| ______________________________________________________________________ | ||
|
|
||
| ## Don't Do This | ||
|
|
||
| ```python | ||
| f = open("file.txt") | ||
| try: | ||
| process(f) | ||
| finally: | ||
| f.close() | ||
| ``` | ||
|
|
||
| ## Do This Instead | ||
|
|
||
| ```python | ||
| with open("file.txt") as f: | ||
| process(f) | ||
| ``` | ||
|
|
||
| Context managers make intent and error handling explicit. Prefer them over | ||
| manual `try/finally` for clearer, safer code. For directory-dependent work, | ||
| inject the directory explicitly or run a child process with its working | ||
| directory set; do not change the process working directory with `os.chdir`. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.