Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: tmux-python/libtmux
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.15.0a0
Choose a base ref
...
head repository: tmux-python/libtmux
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Loading
Showing with 17,785 additions and 6,282 deletions.
  1. +0 −15 .coveragerc
  2. +57 −0 .cursor/rules/avoid-debug-loops.mdc
  3. +187 −0 .cursor/rules/dev-loop.mdc
  4. +95 −0 .cursor/rules/git-commits.mdc
  5. +42 −0 .cursor/rules/notes-llms-txt.mdc
  6. +7 −0 .github/dependabot.yml
  7. +0 −70 .github/workflows/codeql-analysis.yml
  8. +15 −16 .github/workflows/docs.yml
  9. +58 −21 .github/workflows/tests.yml
  10. +6 −0 .gitignore
  11. +1 −1 .python-version
  12. +0 −3 .tmuxp-before-script.sh
  13. +3 −4 .tmuxp.yaml
  14. +2 −2 .tool-versions
  15. +19 −0 .vim/coc-settings.json
  16. +136 −0 .windsurfrules
  17. +1,177 −15 CHANGES
  18. +13 −0 CITATION.cff
  19. +0 −3 MANIFEST.in
  20. +213 −0 MIGRATION
  21. +16 −17 Makefile
  22. +117 −46 README.md
  23. +75 −0 conftest.py
  24. +3 −3 docs/Makefile
  25. +1 −0 docs/__init__.py
  26. +9 −9 docs/_static/img/libtmux.svg
  27. +1 −1 docs/_templates/book.html
  28. +25 −1 docs/_templates/sidebar/projects.html
  29. +13 −13 docs/about.md
  30. +1 −1 docs/{reference → api}/common.md
  31. +6 −0 docs/api/constants.md
  32. +1 −1 docs/{reference → api}/exceptions.md
  33. +2 −1 docs/{reference → api}/index.md
  34. +1 −1 docs/{reference → api}/panes.md
  35. +137 −0 docs/api/properties.md
  36. +2 −2 docs/{reference → api}/servers.md
  37. +1 −1 docs/{reference → api}/sessions.md
  38. +1 −1 docs/{reference → api}/windows.md
  39. +71 −84 docs/conf.py
  40. +137 −56 docs/developing.md
  41. +1 −1 docs/glossary.md
  42. +2 −0 docs/history.md
  43. +4 −3 docs/index.md
  44. +8 −0 docs/internals/dataclasses.md
  45. +4 −4 docs/internals/index.md
  46. +6 −0 docs/internals/query_list.md
  47. +0 −6 docs/internals/test.md
  48. +9 −0 docs/migration.md
  49. +149 −0 docs/pytest-plugin/index.md
  50. +95 −54 docs/quickstart.md
  51. +12 −1 docs/redirects.txt
  52. +0 −171 docs/reference/properties.md
  53. +13 −0 docs/test-helpers/constants.md
  54. +13 −0 docs/test-helpers/environment.md
  55. +18 −0 docs/test-helpers/index.md
  56. +13 −0 docs/test-helpers/random.md
  57. +15 −0 docs/test-helpers/retry.md
  58. +13 −0 docs/test-helpers/temporary.md
  59. +128 −0 docs/topics/context_managers.md
  60. +8 −1 docs/topics/index.md
  61. +116 −35 docs/topics/traversal.md
  62. +0 −15 libtmux/__init__.py
  63. +0 −33 libtmux/_compat.py
  64. +0 −771 libtmux/common.py
  65. +0 −117 libtmux/conftest.py
  66. +0 −56 libtmux/exc.py
  67. +0 −360 libtmux/pane.py
  68. +0 −622 libtmux/server.py
  69. +0 −551 libtmux/session.py
  70. +0 −314 libtmux/test.py
  71. +0 −591 libtmux/window.py
  72. +0 −1,577 poetry.lock
  73. +0 −2 poetry.toml
  74. +190 −63 pyproject.toml
  75. +0 −3 requirements/dev.txt
  76. +0 −4 requirements/doc.txt
  77. +0 −3 requirements/test.txt
  78. +0 −27 setup.cfg
  79. +5 −1 { → src}/libtmux/__about__.py
  80. +33 −0 src/libtmux/__init__.py
  81. +121 −0 src/libtmux/_compat.py
  82. 0 libtmux/py.typed → src/libtmux/_internal/__init__.py
  83. +92 −0 src/libtmux/_internal/dataclasses.py
  84. +569 −0 src/libtmux/_internal/query_list.py
  85. +19 −0 src/libtmux/_internal/types.py
  86. 0 src/libtmux/_vendor/__init__.py
  87. +63 −0 src/libtmux/_vendor/_structures.py
  88. +587 −0 src/libtmux/_vendor/version.py
  89. +499 −0 src/libtmux/common.py
  90. +53 −0 src/libtmux/constants.py
  91. +165 −0 src/libtmux/exc.py
  92. +6 −3 { → src}/libtmux/formats.py
  93. +264 −0 src/libtmux/neo.py
  94. +984 −0 src/libtmux/pane.py
  95. 0 src/libtmux/py.typed
  96. +315 −0 src/libtmux/pytest_plugin.py
  97. +882 −0 src/libtmux/server.py
  98. +1,022 −0 src/libtmux/session.py
  99. +1 −0 src/libtmux/test/__init__.py
  100. +18 −0 src/libtmux/test/constants.py
  101. +78 −0 src/libtmux/test/environment.py
  102. +132 −0 src/libtmux/test/random.py
  103. +71 −0 src/libtmux/test/retry.py
  104. +135 −0 src/libtmux/test/temporary.py
  105. +1,111 −0 src/libtmux/window.py
  106. +1 −0 tests/__init__.py
  107. 0 tests/_internal/__init__.py
  108. +293 −0 tests/_internal/test_query_list.py
  109. +0 −1 tests/conftest.py
  110. +1 −0 tests/legacy_api/__init__.py
  111. +243 −0 tests/legacy_api/test_common.py
  112. +98 −0 tests/legacy_api/test_pane.py
  113. +173 −0 tests/legacy_api/test_server.py
  114. +320 −0 tests/legacy_api/test_session.py
  115. +194 −0 tests/legacy_api/test_tmuxobject.py
  116. +89 −0 tests/legacy_api/test_version.py
  117. +444 −0 tests/legacy_api/test_window.py
  118. +51 −0 tests/test/test_constants.py
  119. +151 −0 tests/test/test_environment.py
  120. +602 −0 tests/test/test_random.py
  121. +105 −0 tests/test/test_retry.py
  122. +136 −0 tests/test/test_temporary.py
  123. +452 −165 tests/test_common.py
  124. +189 −0 tests/test_dataclasses.py
  125. +393 −34 tests/test_pane.py
  126. +158 −0 tests/test_pytest_plugin.py
  127. +313 −19 tests/test_server.py
  128. +328 −45 tests/test_session.py
  129. +0 −88 tests/test_test.py
  130. +69 −63 tests/test_tmuxobject.py
  131. +160 −0 tests/test_version.py
  132. +556 −90 tests/test_window.py
  133. +1,573 −0 uv.lock
15 changes: 0 additions & 15 deletions .coveragerc

This file was deleted.

57 changes: 57 additions & 0 deletions .cursor/rules/avoid-debug-loops.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
description: When stuck in debugging loops, break the cycle by minimizing to an MVP, removing debugging cruft, and documenting the issue completely for a fresh approach
globs: *.py
alwaysApply: true
---
# Avoid Debug Loops

When debugging becomes circular and unproductive, follow these steps:

## Detection
- You have made multiple unsuccessful attempts to fix the same issue
- You are adding increasingly complex code to address errors
- Each fix creates new errors in a cascading pattern
- You are uncertain about the root cause after 2-3 iterations

## Action Plan

1. **Pause and acknowledge the loop**
- Explicitly state that you are in a potential debug loop
- Review what approaches have been tried and failed

2. **Minimize to MVP**
- Remove all debugging cruft and experimental code
- Revert to the simplest version that demonstrates the issue
- Focus on isolating the core problem without added complexity

3. **Comprehensive Documentation**
- Provide a clear summary of the issue
- Include minimal but complete code examples that reproduce the problem
- Document exact error messages and unexpected behaviors
- Explain your current understanding of potential causes

4. **Format for Portability**
- Present the problem in quadruple backticks for easy copying:

````
# Problem Summary
[Concise explanation of the issue]

## Minimal Reproduction Code
```python
# Minimal code example that reproduces the issue
```

## Error/Unexpected Output
```
[Exact error messages or unexpected output]
```

## Failed Approaches
[Brief summary of approaches already tried]

## Suspected Cause
[Your current hypothesis about what might be causing the issue]
````

This format enables the user to easily copy the entire problem statement into a fresh conversation for a clean-slate approach.
187 changes: 187 additions & 0 deletions .cursor/rules/dev-loop.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
---
description: QA every edit
globs: *.py
alwaysApply: true
---

# Development Process

## Project Stack

The project uses the following tools and technologies:

- **uv** - Python package management and virtual environments
- **ruff** - Fast Python linter and formatter
- **py.test** - Testing framework
- **pytest-watcher** - Continuous test runner
- **mypy** - Static type checking
- **doctest** - Testing code examples in documentation

## 1. Start with Formatting

Format your code first:

```
uv run ruff format .
```

## 2. Run Tests

Verify that your changes pass the tests:

```
uv run py.test
```

For continuous testing during development, use pytest-watcher:

```
# Watch all tests
uv run ptw .

# Watch and run tests immediately, including doctests
uv run ptw . --now --doctest-modules

# Watch specific files or directories
uv run ptw . --now --doctest-modules src/libtmux/_internal/
```

## 3. Commit Initial Changes

Make an atomic commit for your changes using conventional commits.
Use `@git-commits.mdc` for assistance with commit message standards.

## 4. Run Linting and Type Checking

Check and fix linting issues:

```
uv run ruff check . --fix --show-fixes
```

Check typings:

```
uv run mypy
```

## 5. Verify Tests Again

Ensure tests still pass after linting and type fixes:

```
uv run py.test
```

## 6. Final Commit

Make a final commit with any linting/typing fixes.
Use `@git-commits.mdc` for assistance with commit message standards.

## Development Loop Guidelines

If there are any failures at any step due to your edits, fix them before proceeding to the next step.

## Python Code Standards

### Docstring Guidelines

For `src/**/*.py` files, follow these docstring guidelines:

1. **Use reStructuredText format** for all docstrings.
```python
"""Short description of the function or class.

Detailed description using reStructuredText format.

Parameters
----------
param1 : type
Description of param1
param2 : type
Description of param2

Returns
-------
type
Description of return value
"""
```

2. **Keep the main description on the first line** after the opening `"""`.

3. **Use NumPy docstyle** for parameter and return value documentation.

### Doctest Guidelines

For doctests in `src/**/*.py` files:

1. **Use narrative descriptions** for test sections rather than inline comments:
```python
"""Example function.

Examples
--------
Create an instance:

>>> obj = ExampleClass()

Verify a property:

>>> obj.property
'expected value'
"""
```

2. **Move complex examples** to dedicated test files at `tests/examples/<path_to_module>/test_<example>.py` if they require elaborate setup or multiple steps.

3. **Utilize pytest fixtures** via `doctest_namespace` for more complex test scenarios:
```python
"""Example with fixture.

Examples
--------
>>> # doctest_namespace contains all pytest fixtures from conftest.py
>>> example_fixture = getfixture('example_fixture')
>>> example_fixture.method()
'expected result'
"""
```

4. **Keep doctests simple and focused** on demonstrating usage rather than comprehensive testing.

5. **Add blank lines between test sections** for improved readability.

6. **Test your doctests continuously** using pytest-watcher during development:
```
# Watch specific modules for doctest changes
uv run ptw . --now --doctest-modules src/path/to/module.py
```

### Pytest Testing Guidelines

1. **Use existing fixtures over mocks**:
- Use fixtures from conftest.py instead of `monkeypatch` and `MagicMock` when available
- For instance, if using libtmux, use provided fixtures: `server`, `session`, `window`, and `pane`
- Document in test docstrings why standard fixtures weren't used for exceptional cases

2. **Preferred pytest patterns**:
- Use `tmp_path` (pathlib.Path) fixture over Python's `tempfile`
- Use `monkeypatch` fixture over `unittest.mock`

### Import Guidelines

1. **Prefer namespace imports**:
- Import modules and access attributes through the namespace instead of importing specific symbols
- Example: Use `import enum` and access `enum.Enum` instead of `from enum import Enum`
- This applies to standard library modules like `pathlib`, `os`, and similar cases

2. **Standard aliases**:
- For `typing` module, use `import typing as t`
- Access typing elements via the namespace: `t.NamedTuple`, `t.TypedDict`, etc.
- Note primitive types like unions can be done via `|` pipes and primitive types like list and dict can be done via `list` and `dict` directly.

3. **Benefits of namespace imports**:
- Improves code readability by making the source of symbols clear
- Reduces potential naming conflicts
- Makes import statements more maintainable
95 changes: 95 additions & 0 deletions .cursor/rules/git-commits.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
description: git-commits: Git commit message standards and AI assistance
globs: git-commits: Git commit message standards and AI assistance | *.git/* .gitignore .github/* CHANGELOG.md CHANGES.md
alwaysApply: true
---
# Optimized Git Commit Standards

## Commit Message Format
```
Component/File(commit-type[Subcomponent/method]): Concise description

why: Explanation of necessity or impact.
what:
- Specific technical changes made
- Focused on a single topic

refs: #issue-number, breaking changes, or relevant links
```

## Component Patterns
### General Code Changes
```
Component/File(feat[method]): Add feature
Component/File(fix[method]): Fix bug
Component/File(refactor[method]): Code restructure
```

### Packages and Dependencies
| Language | Standard Packages | Dev Packages | Extras / Sub-packages |
|------------|------------------------------------|-------------------------------|-----------------------------------------------|
| General | `lang(deps):` | `lang(deps[dev]):` | |
| Python | `py(deps):` | `py(deps[dev]):` | `py(deps[extra]):` |
| JavaScript | `js(deps):` | `js(deps[dev]):` | `js(deps[subpackage]):`, `js(deps[dev{subpackage}]):` |

#### Examples
- `py(deps[dev]): Update pytest to v8.1`
- `js(deps[ui-components]): Upgrade Button component package`
- `js(deps[dev{linting}]): Add ESLint plugin`

### Documentation Changes
Prefix with `docs:`
```
docs(Component/File[Subcomponent/method]): Update API usage guide
```

### Test Changes
Prefix with `tests:`
```
tests(Component/File[Subcomponent/method]): Add edge case tests
```

## Commit Types Summary
- **feat**: New features or enhancements
- **fix**: Bug fixes
- **refactor**: Code restructuring without functional change
- **docs**: Documentation updates
- **chore**: Maintenance (dependencies, tooling, config)
- **test**: Test-related updates
- **style**: Code style and formatting

## General Guidelines
- Subject line: Maximum 50 characters
- Body lines: Maximum 72 characters
- Use imperative mood (e.g., "Add", "Fix", not "Added", "Fixed")
- Limit to one topic per commit
- Separate subject from body with a blank line
- Mark breaking changes clearly: `BREAKING:`
- Use `See also:` to provide external references

## AI Assistance Workflow in Cursor
- Stage changes with `git add`
- Use `@commit` to generate initial commit message
- Review and refine generated message
- Ensure adherence to these standards

## Good Commit Example
```
Pane(feat[capture_pane]): Add screenshot capture support

why: Provide visual debugging capability
what:
- Implement capturePane method with image export
- Integrate with existing Pane component logic
- Document usage in Pane README

refs: #485
See also: https://example.com/docs/pane-capture
```

## Bad Commit Example
```
fixed stuff and improved some functions
```

These guidelines ensure clear, consistent commit histories, facilitating easier code review and maintenance.
Loading