Skip to content
Merged
Show file tree
Hide file tree
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
Aug 20, 2026
f10ab76
Rename Locize documents for localization scope
Aug 20, 2026
5490297
Add per-locale terminology sections for all 34 shipped locales
leynos Aug 23, 2026
3bd42af
Scope the MD060 exception to the localization glossary
leynos Aug 30, 2026
f1a0026
Remove BDD process-global state (#492)
leynos Aug 22, 2026
1c99f6d
Thread an explicit base directory into glob expansion
leynos Aug 22, 2026
21db401
Migrate manifest glob integration tests off process CWD mutation
leynos Aug 22, 2026
87373e4
Fix clippy findings in the glob base seam
leynos Aug 22, 2026
9d33041
Keep walk and manifest modules within the line limit
leynos Aug 22, 2026
7832082
Delete env_lock and cwd_guard from test_support
leynos Aug 22, 2026
6f015f8
Gate in-process environment mutation in the lint target
leynos Aug 22, 2026
9a28e25
Anchor BDD glob fixtures at the manifest directory
leynos Aug 22, 2026
c336f29
Fix glob base anchoring for relative and symlinked bases
leynos Aug 24, 2026
caa6460
Harden the env-mutation gate and refresh retired-CWD comments
leynos Aug 24, 2026
24386dd
Document retired env-mutation utilities and fix glob base shadowing
leynos Aug 24, 2026
ca42b51
Split glob base tests into a dedicated module
leynos Aug 24, 2026
602a819
Introduce a Utf8Path glob seam and split glob preparation from matching
leynos Aug 25, 2026
373bcd3
Keep explicit config selectors independent of -C/--directory
leynos Aug 25, 2026
b0312e4
Align documentation with explicit-selector independence from -C
leynos Aug 26, 2026
1082dc9
Fix BDD selector scenarios and lint gates after rebase
leynos Aug 26, 2026
e83c61f
Align scenario state table columns after global_state_lock removal
leynos Aug 26, 2026
2622ab3
Keep discovery module within the 400-line limit
leynos Aug 27, 2026
b589ab3
Add injected-glob-base property tests through the glob_paths boundary
leynos Aug 27, 2026
9256ec8
Add clippy env-policy UI coverage for process-CWD mutation vs Command…
leynos Aug 27, 2026
d1c0b7a
Align explicit-selector docs and harden glob-base property tests for …
leynos Aug 27, 2026
1caec02
Register the clippy env-policy fixture manifest with Dependabot
leynos Aug 27, 2026
83f59e1
Document the base-directory seam and -C anchoring as ADR-014
leynos Aug 27, 2026
b69245f
chore: archive backup for session c6635e5f
Aug 27, 2026
8127f1e
Anchor relative explicit config selectors to -C/--directory
leynos Aug 28, 2026
0a42e18
Extract config-selector resolution into discovery_selector module
leynos Aug 28, 2026
37bd9c6
Port the env-mutation gate to Python and adopt the scripting standards
leynos Aug 28, 2026
0f5fdde
Fix spelling-gate finding in the scripting-standards section
leynos Aug 28, 2026
6e7ac3c
Drop the stale env_lock line from the test_support crate docs
leynos Aug 28, 2026
553e692
Mark the 3.11.5 EnvLock retirement roadmap items complete
leynos Aug 28, 2026
bc3e926
Gate the Unix-only glob base test imports with cfg(unix)
leynos Aug 28, 2026
5005124
Fix cross-platform compilation of the glob capability tests
leynos Aug 28, 2026
d53ebe0
chore: archive backup for session 0cee541e
Aug 28, 2026
47598fe
Harden manifest glob base expansion (#494)
leynos Aug 28, 2026
451a2d8
Fix Windows glob base tests
leynos Aug 29, 2026
a6df24a
Cover legal glob bases on Windows
leynos Aug 29, 2026
ff7682d
Fix Windows canonical glob bases
leynos Aug 29, 2026
92bbcee
Compare absolute glob paths canonically
leynos Aug 29, 2026
94366ad
Keep explicit config selectors independent of -C (#494)
leynos Aug 29, 2026
de7c1f8
Apply review repairs to environment seams (#494)
leynos Aug 29, 2026
2fc9e0d
Align explicit selector documentation (#494)
leynos Aug 29, 2026
2c7fefb
Preserve Windows glob base prefixes (#494)
leynos Aug 29, 2026
3568b47
Repair rebase integration for discovery modules (#494)
leynos Aug 29, 2026
9d37e16
Use sentence case in ADR-014 heading (#494)
leynos Aug 29, 2026
3033158
Harden environment mutation and glob review gates (#494)
leynos Aug 29, 2026
e817285
Split manifest glob base preparation (#494)
leynos Aug 29, 2026
7d7a5b2
Harden rebase review repairs (#494)
leynos Aug 30, 2026
119f3b9
Stage mutation gates before parallel checks (#494)
leynos Aug 30, 2026
500e40e
Rely on Clippy for environment policy (#494)
leynos Aug 30, 2026
9659061
Cover glob benchmark Make target (#494)
leynos Aug 30, 2026
c157539
Remove duplicate Whitaker guidance (#494)
leynos Aug 30, 2026
70b47cd
Align rebase repairs with formatting policy (#494)
leynos Aug 30, 2026
d72a882
Preserve Markdown and benchmark targets after rebase (#494)
leynos Aug 30, 2026
d24c612
Harden formatting and seam documentation (#494)
leynos Aug 30, 2026
19246a1
Align Python rules with the 3.14 baseline (#494)
leynos Aug 30, 2026
44838e4
Instrument glob base cache and align tooling docs (#494)
leynos Aug 30, 2026
ce49b9f
Deduplicate glob cache canonicalization metrics (#494)
leynos Aug 31, 2026
cc5d0f3
Instrument manifest-template glob expansion (#494)
leynos Aug 31, 2026
9745feb
Deduplicate injected glob diagnostics setup (#494)
leynos Aug 31, 2026
714d95e
Instrument template glob failure outcomes (#494)
leynos Aug 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions .rules/python-00.md
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.
Comment thread
leynos marked this conversation as resolved.
111 changes: 111 additions & 0 deletions .rules/python-context-managers.md
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`.
Loading
Loading