From e6a6443f3d4c0fd5fafb7396be9a569c2b603453 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Fri, 27 Feb 2026 23:06:24 +1000 Subject: [PATCH 1/3] docs(instructions): update python conventions and add pytest guide - Update python.instructions.md to match actual repo conventions: 100-char line length, modern type syntax, from __future__ import annotations, slots=True dataclasses, ruff tooling - Add pytest.instructions.md with project-specific testing patterns: fixture structure, disc analysis helpers, matrix test conventions, per-disc integration test patterns Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/instructions/pytest.instructions.md | 118 ++++++++++++++++++++ .github/instructions/python.instructions.md | 40 ++++--- 2 files changed, 142 insertions(+), 16 deletions(-) create mode 100644 .github/instructions/pytest.instructions.md diff --git a/.github/instructions/pytest.instructions.md b/.github/instructions/pytest.instructions.md new file mode 100644 index 0000000..fa3932b --- /dev/null +++ b/.github/instructions/pytest.instructions.md @@ -0,0 +1,118 @@ +--- +description: 'Pytest conventions and testing patterns for the bdpl project' +applyTo: 'tests/**/*.py' +--- + +# Pytest Conventions + +## Project Test Structure + +``` +tests/ +├── conftest.py # Shared fixtures (_fixture_path, _analyze_fixture, disc fixtures) +├── test_disc_matrix.py # Cross-disc parametrized tests (6 parametrizations) +├── test_disc{N}_scan.py # Per-disc integration tests +├── test_fixture_integrity.py # Fixture file validation +├── test_reader.py # BinaryReader unit tests +├── test_mpls_parse.py # MPLS parser tests +├── test_clpi_parse.py # CLPI parser tests +├── test_index_bdmv.py # index.bdmv parser tests +├── test_movieobject_bdmv.py # MovieObject parser tests +├── test_ig_stream.py # IG stream parser tests +├── test_cli.py # CLI subprocess tests +└── fixtures/disc{N}/ # Bundled BDMV metadata fixtures +``` + +## Fixture Patterns + +### Disc Analysis Fixtures (conftest.py) + +- Use `@pytest.fixture(scope="session")` for disc analysis — parsing is expensive. +- Helper `_fixture_path(name)` resolves fixture directories and validates structure. +- Helper `_analyze_fixture(path)` runs `scan_disc()` and returns `DiscAnalysis`. +- Each disc gets a fixture like `disc3(request)` that calls `_analyze_fixture`. + +```python +@pytest.fixture(scope="session") +def disc7(request): + """Disc with commentary audio and creditless extras.""" + path = _fixture_path("disc7") + if path is None: + pytest.skip("disc7 fixture not available") + return _analyze_fixture(path) +``` + +### Adding a New Disc Fixture + +1. Create `tests/fixtures/disc{N}/` with PLAYLIST/, CLIPINF/, index.bdmv, MovieObject.bdmv. +2. Files go directly under `disc{N}/` — NOT under `disc{N}/BDMV/`. +3. Add the fixture to `conftest.py` with a descriptive docstring. +4. Add to ALL 6 parametrizations in `test_disc_matrix.py`. +5. Create `test_disc{N}_scan.py` with per-disc assertions. + +## Test Patterns + +### Per-Disc Integration Tests + +Each disc test file follows a consistent structure: + +```python +def test_episode_count(disc7): + assert len(disc7.episodes) == 6 + +def test_special_features(disc7): + cats = Counter(sf.category for sf in disc7.special_features) + assert cats["commentary"] == 2 + assert cats["creditless_op"] == 1 +``` + +### Matrix Tests (test_disc_matrix.py) + +Cross-disc parametrized tests validate invariants across all fixtures: + +```python +@pytest.mark.parametrize("fixture_name,expected", [ + ("disc1", 6), + ("disc3", 5), + # ... all discs +]) +def test_episode_count(fixture_name, expected, request): + da = request.getfixturevalue(fixture_name) + assert len(da.episodes) == expected +``` + +When adding a disc, update ALL parametrizations: +- `test_episode_count` +- `test_special_feature_count` +- `test_episode_numbering` +- `test_no_warnings` (or expected warnings) +- `test_playlist_classification_coverage` +- `test_episode_confidence` + +### Unit Tests + +Use small, focused tests with inline binary data or minimal fixtures: + +```python +def test_read_u32(self): + r = BinaryReader(b"\x00\x01\x00\x02") + assert r.read_u32() == 0x00010002 +``` + +## Running Tests + +```bash +pytest tests/ -v # All tests +pytest tests/test_disc7_scan.py -v # Single disc +pytest tests/ -k "matrix" -v # Matrix tests only +pytest tests/ -x # Stop on first failure +``` + +## Conventions + +- Use `assert` statements directly — no `self.assertEqual`. +- Group related assertions in a single test when they share expensive setup. +- Use `Counter` from `collections` for category breakdowns. +- Test names follow `test_{what}` pattern (e.g., `test_episode_count`, `test_special_features`). +- Skip tests gracefully when fixtures are unavailable (`pytest.skip`). +- Never commit copyrighted media (m2ts streams) — fixtures contain only structural metadata. diff --git a/.github/instructions/python.instructions.md b/.github/instructions/python.instructions.md index a783f42..081746d 100644 --- a/.github/instructions/python.instructions.md +++ b/.github/instructions/python.instructions.md @@ -1,55 +1,63 @@ --- -description: 'Python coding conventions and guidelines' +description: 'Python coding conventions and guidelines for the bdpl project' applyTo: '**/*.py' --- # Python Coding Conventions +## Project-Specific Conventions + +- Python 3.10+ required; use `from __future__ import annotations` in all modules. +- Use `dataclasses` with `slots=True` for data models. +- Use the `struct` module for binary parsing — no external binary-parsing deps. +- Use `typer` for CLI commands and `rich` for terminal output. +- Line length limit is **100 characters** (configured in `pyproject.toml` via ruff). +- Use double quotes for strings (configured via ruff format). +- Import sorting follows isort-style rules (ruff `I` rule). + ## Python Instructions -- Write clear and concise comments for each function. - Ensure functions have descriptive names and include type hints. -- Provide docstrings following PEP 257 conventions. -- Use the `typing` module for type annotations (e.g., `List[str]`, `Dict[str, int]`). +- Provide docstrings following PEP 257 conventions for public functions. +- Use modern Python type syntax (`list[str]`, `dict[str, int]`, `X | None`) — no `typing.List`/`typing.Dict`/`typing.Optional`. - Break down complex functions into smaller, more manageable functions. +- Only comment code that needs clarification; avoid obvious comments. ## General Instructions - Always prioritize readability and clarity. - For algorithm-related code, include explanations of the approach used. -- Write code with good maintainability practices, including comments on why certain design decisions were made. - Handle edge cases and write clear exception handling. -- For libraries or external dependencies, mention their usage and purpose in comments. +- Parsers should be robust — never crash on malformed binary data. - Use consistent naming conventions and follow language-specific best practices. - Write concise, efficient, and idiomatic code that is also easily understandable. ## Code Style and Formatting -- Follow the **PEP 8** style guide for Python. -- Maintain proper indentation (use 4 spaces for each level of indentation). -- Ensure lines do not exceed 79 characters. +- Follow **PEP 8** with the project's 100-character line limit. +- Maintain proper indentation (4 spaces). - Place function and class docstrings immediately after the `def` or `class` keyword. - Use blank lines to separate functions, classes, and code blocks where appropriate. +- Run `ruff check .` and `ruff format .` before committing. ## Edge Cases and Testing - Always include test cases for critical paths of the application. - Account for common edge cases like empty inputs, invalid data types, and large datasets. -- Include comments for edge cases and the expected behavior in those cases. - Write unit tests for functions and document them with docstrings explaining the test cases. +- See `pytest.instructions.md` for project-specific testing patterns. ## Example of Proper Documentation ```python def calculate_area(radius: float) -> float: - """ - Calculate the area of a circle given the radius. - + """Calculate the area of a circle given the radius. + Parameters: - radius (float): The radius of the circle. - + radius: The radius of the circle. + Returns: - float: The area of the circle, calculated as π * radius^2. + The area of the circle, calculated as π * radius². """ import math return math.pi * radius ** 2 From e68932b70daf64f9ea475b9711c4279c4f90c32e Mon Sep 17 00:00:00 2001 From: Benjamin Date: Fri, 27 Feb 2026 23:44:36 +1000 Subject: [PATCH 2/3] docs: add instructions/skills provenance manifest Track which files came from github/awesome-copilot vs project-specific, and whether upstream copies have been customized. Aids future sync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/instructions/README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/instructions/README.md diff --git a/.github/instructions/README.md b/.github/instructions/README.md new file mode 100644 index 0000000..3ca961d --- /dev/null +++ b/.github/instructions/README.md @@ -0,0 +1,30 @@ +# Agent Instructions & Skills Manifest + +Provenance tracking for all Copilot instruction files and agent skills. + +## Instructions + +| File | Source | Notes | +|------|--------|-------| +| `python.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/python.instructions.md) → **customized** | Originally copied from awesome-copilot; updated to match bdpl conventions (100-char lines, modern type syntax, ruff, dataclasses, struct parsing) | +| `pytest.instructions.md` | **Project-specific** | Written for bdpl's fixture patterns, matrix tests, and disc analysis conventions. Nothing equivalent in awesome-copilot. | +| `code-review-generic.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/code-review-generic.instructions.md) | Identical to upstream | +| `security-and-owasp.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/security-and-owasp.instructions.md) | Identical to upstream | +| `agent-skills.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/agent-skills.instructions.md) | Identical to upstream | +| `instructions.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/instructions.instructions.md) | Identical to upstream | + +## Skills + +| Skill | Source | Notes | +|-------|--------|-------| +| `add-disc-fixture` | **Project-specific** | 10-step disc fixture workflow + analysis debugging guide | +| `gh-cli` | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/gh-cli) | GitHub CLI reference | +| `gh-commit` | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/gh-commit) | Conventional commit generation | +| `make-repo-contribution` | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/make-repo-contribution) | Contribution workflow | + +## Upstream Sync + +When updating from awesome-copilot, check the "Notes" column: +- **Identical to upstream** — safe to overwrite with newer version +- **Customized** — merge manually; review diffs to preserve project-specific changes +- **Project-specific** — no upstream equivalent; maintained independently From 01d15e578d4d88fa2e4b185d43ec47d1fefc5c92 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Fri, 27 Feb 2026 23:47:26 +1000 Subject: [PATCH 3/3] docs: add detailed local modifications changelog to manifest List every specific change made to python.instructions.md vs upstream, so future syncs know exactly what to preserve. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/instructions/README.md | 67 ++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/.github/instructions/README.md b/.github/instructions/README.md index 3ca961d..578c41e 100644 --- a/.github/instructions/README.md +++ b/.github/instructions/README.md @@ -2,29 +2,58 @@ Provenance tracking for all Copilot instruction files and agent skills. +Legend: **upstream** = copied from awesome-copilot as-is · **customized** = forked +from awesome-copilot with local changes · **project-specific** = written for bdpl, +no upstream equivalent. + ## Instructions -| File | Source | Notes | -|------|--------|-------| -| `python.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/python.instructions.md) → **customized** | Originally copied from awesome-copilot; updated to match bdpl conventions (100-char lines, modern type syntax, ruff, dataclasses, struct parsing) | -| `pytest.instructions.md` | **Project-specific** | Written for bdpl's fixture patterns, matrix tests, and disc analysis conventions. Nothing equivalent in awesome-copilot. | -| `code-review-generic.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/code-review-generic.instructions.md) | Identical to upstream | -| `security-and-owasp.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/security-and-owasp.instructions.md) | Identical to upstream | -| `agent-skills.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/agent-skills.instructions.md) | Identical to upstream | -| `instructions.instructions.md` | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/instructions.instructions.md) | Identical to upstream | +| File | Status | Source | +|------|--------|--------| +| `python.instructions.md` | **customized** | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/python.instructions.md) | +| `pytest.instructions.md` | **project-specific** | — | +| `code-review-generic.instructions.md` | **upstream** | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/code-review-generic.instructions.md) | +| `security-and-owasp.instructions.md` | **upstream** | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/security-and-owasp.instructions.md) | +| `agent-skills.instructions.md` | **upstream** | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/agent-skills.instructions.md) | +| `instructions.instructions.md` | **upstream** | [awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/instructions.instructions.md) | ## Skills -| Skill | Source | Notes | -|-------|--------|-------| -| `add-disc-fixture` | **Project-specific** | 10-step disc fixture workflow + analysis debugging guide | -| `gh-cli` | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/gh-cli) | GitHub CLI reference | -| `gh-commit` | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/gh-commit) | Conventional commit generation | -| `make-repo-contribution` | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/make-repo-contribution) | Contribution workflow | +| Skill | Status | Source | +|-------|--------|--------| +| `add-disc-fixture` | **project-specific** | — | +| `gh-cli` | **upstream** | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/gh-cli) | +| `gh-commit` | **upstream** | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/gh-commit) | +| `make-repo-contribution` | **upstream** | [awesome-copilot](https://github.com/github/awesome-copilot/tree/main/skills/make-repo-contribution) | + +## Local Modifications + +Changes made to files forked from awesome-copilot. Keep this up to date when +making further edits so upstream syncs can be done safely. + +### `python.instructions.md` + +Upstream version is a generic PEP 8 guide. Customized to match bdpl's actual +tooling and conventions: + +- **Line length**: 79 → 100 (matches `line-length = 100` in `pyproject.toml`) +- **Type hints**: Replaced `typing.List[str]` / `typing.Dict` / `typing.Optional` + guidance with modern syntax (`list[str]`, `dict[str, int]`, `X | None`) +- **Added project conventions section**: `from __future__ import annotations`, + `dataclasses` with `slots=True`, `struct` for binary parsing, `typer`/`rich` +- **String style**: Added double-quote preference (ruff format default) +- **Import sorting**: Added isort-style via ruff `I` rule +- **Tooling**: Added `ruff check .` and `ruff format .` as pre-commit steps +- **Comments**: Changed "write clear and concise comments for each function" to + "only comment code that needs clarification" (matches AGENTS.md style guide) +- **Docstring example**: Modernized to single-line summary style per PEP 257 +- **Removed**: Over-commenting guidance, `typing` module recommendation, + mention of external dependency comments + +## Upstream Sync Guide -## Upstream Sync +When pulling updates from awesome-copilot: -When updating from awesome-copilot, check the "Notes" column: -- **Identical to upstream** — safe to overwrite with newer version -- **Customized** — merge manually; review diffs to preserve project-specific changes -- **Project-specific** — no upstream equivalent; maintained independently +- **upstream** — safe to overwrite with newer version +- **customized** — merge manually; check "Local Modifications" above for what to preserve +- **project-specific** — no upstream equivalent; maintained independently