|
| 1 | +# libtmux Python Project Rules |
| 2 | + |
| 3 | +<project_stack> |
| 4 | +- uv - Python package management and virtual environments |
| 5 | +- ruff - Fast Python linter and formatter |
| 6 | +- py.test - Testing framework |
| 7 | + - pytest-watcher - Continuous test runner |
| 8 | +- mypy - Static type checking |
| 9 | +- doctest - Testing code examples in documentation |
| 10 | +</project_stack> |
| 11 | + |
| 12 | +<coding_style> |
| 13 | +- Use a consistent coding style throughout the project |
| 14 | +- Format code with ruff before committing |
| 15 | +- Run linting and type checking before finalizing changes |
| 16 | +- Verify tests pass after each significant change |
| 17 | +</coding_style> |
| 18 | + |
| 19 | +<python_docstrings> |
| 20 | +- Use reStructuredText format for all docstrings in src/**/*.py files |
| 21 | +- Keep the main description on the first line after the opening `"""` |
| 22 | +- Use NumPy docstyle for parameter and return value documentation |
| 23 | +- Format docstrings as follows: |
| 24 | + ```python |
| 25 | + """Short description of the function or class. |
| 26 | + |
| 27 | + Detailed description using reStructuredText format. |
| 28 | + |
| 29 | + Parameters |
| 30 | + ---------- |
| 31 | + param1 : type |
| 32 | + Description of param1 |
| 33 | + param2 : type |
| 34 | + Description of param2 |
| 35 | + |
| 36 | + Returns |
| 37 | + ------- |
| 38 | + type |
| 39 | + Description of return value |
| 40 | + """ |
| 41 | + ``` |
| 42 | +</python_docstrings> |
| 43 | + |
| 44 | +<python_doctests> |
| 45 | +- Use narrative descriptions for test sections rather than inline comments |
| 46 | +- Format doctests as follows: |
| 47 | + ```python |
| 48 | + """ |
| 49 | + Examples |
| 50 | + -------- |
| 51 | + Create an instance: |
| 52 | + |
| 53 | + >>> obj = ExampleClass() |
| 54 | + |
| 55 | + Verify a property: |
| 56 | + |
| 57 | + >>> obj.property |
| 58 | + 'expected value' |
| 59 | + """ |
| 60 | + ``` |
| 61 | +- Add blank lines between test sections for improved readability |
| 62 | +- Keep doctests simple and focused on demonstrating usage |
| 63 | +- Move complex examples to dedicated test files at tests/examples/<path_to_module>/test_<example>.py |
| 64 | +- Utilize pytest fixtures via doctest_namespace for complex scenarios |
| 65 | +</python_doctests> |
| 66 | + |
| 67 | +<testing_practices> |
| 68 | +- Run tests with `uv run py.test` before committing changes |
| 69 | +- Use pytest-watcher for continuous testing: `uv run ptw . --now --doctest-modules` |
| 70 | +- Fix any test failures before proceeding with additional changes |
| 71 | +</testing_practices> |
| 72 | + |
| 73 | +<git_workflow> |
| 74 | +- Make atomic commits with conventional commit messages |
| 75 | +- Start with an initial commit of functional changes |
| 76 | +- Follow with separate commits for formatting, linting, and type checking fixes |
| 77 | +</git_workflow> |
| 78 | + |
| 79 | +<git_commit_standards> |
| 80 | +- Use the following commit message format: |
| 81 | + ``` |
| 82 | + Component/File(commit-type[Subcomponent/method]): Concise description |
| 83 | + |
| 84 | + why: Explanation of necessity or impact. |
| 85 | + what: |
| 86 | + - Specific technical changes made |
| 87 | + - Focused on a single topic |
| 88 | + |
| 89 | + refs: #issue-number, breaking changes, or relevant links |
| 90 | + ``` |
| 91 | + |
| 92 | +- Common commit types: |
| 93 | + - **feat**: New features or enhancements |
| 94 | + - **fix**: Bug fixes |
| 95 | + - **refactor**: Code restructuring without functional change |
| 96 | + - **docs**: Documentation updates |
| 97 | + - **chore**: Maintenance (dependencies, tooling, config) |
| 98 | + - **test**: Test-related updates |
| 99 | + - **style**: Code style and formatting |
| 100 | + |
| 101 | +- Prefix Python package changes with: |
| 102 | + - `py(deps):` for standard packages |
| 103 | + - `py(deps[dev]):` for development packages |
| 104 | + - `py(deps[extra]):` for extras/sub-packages |
| 105 | + |
| 106 | +- General guidelines: |
| 107 | + - Subject line: Maximum 50 characters |
| 108 | + - Body lines: Maximum 72 characters |
| 109 | + - Use imperative mood (e.g., "Add", "Fix", not "Added", "Fixed") |
| 110 | + - Limit to one topic per commit |
| 111 | + - Separate subject from body with a blank line |
| 112 | + - Mark breaking changes clearly: `BREAKING:` |
| 113 | +</git_commit_standards> |
| 114 | + |
| 115 | +<pytest_testing_guidelines> |
| 116 | +- Use fixtures from conftest.py instead of monkeypatch and MagicMock when available |
| 117 | +- For instance, if using libtmux, use provided fixtures: server, session, window, and pane |
| 118 | +- Document in test docstrings why standard fixtures weren't used for exceptional cases |
| 119 | +- Use tmp_path (pathlib.Path) fixture over Python's tempfile |
| 120 | +- Use monkeypatch fixture over unittest.mock |
| 121 | +</pytest_testing_guidelines> |
| 122 | + |
| 123 | +<import_guidelines> |
| 124 | +- Prefer namespace imports over importing specific symbols |
| 125 | +- Import modules and access attributes through the namespace: |
| 126 | + - Use `import enum` and access `enum.Enum` instead of `from enum import Enum` |
| 127 | + - This applies to standard library modules like pathlib, os, and similar cases |
| 128 | +- For typing, use `import typing as t` and access via the namespace: |
| 129 | + - Access typing elements as `t.NamedTuple`, `t.TypedDict`, etc. |
| 130 | + - Note primitive types like unions can be done via `|` pipes |
| 131 | + - Primitive types like list and dict can be done via `list` and `dict` directly |
| 132 | +- Benefits of namespace imports: |
| 133 | + - Improves code readability by making the source of symbols clear |
| 134 | + - Reduces potential naming conflicts |
| 135 | + - Makes import statements more maintainable |
| 136 | +</import_guidelines> |
0 commit comments