10000 snapshot(refactor[typing]): Improve type overrides with generics by tony · Pull Request #590 · tmux-python/libtmux · GitHub
[go: up one dir, main page]

Skip to content

snapshot(refactor[typing]): Improve type overrides with generics #590

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

Draft
wants to merge 44 commits into
base: snapshots
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
ea5b0c4
.tool-versions(uv,python) uv 0.6.12 -> 0.6.14, python 3.13.2 -> 3.13.3
tony Apr 12, 2025
88e62d8
py(deps[dev]) Bump dev packages
tony Apr 12, 2025
4c49754
py(deps[dev]) Bump dev packages
tony Apr 19, 2025
93f2e75
py(deps[dev]) Bump dev packages
tony Apr 26, 2025
b9a5cb7
pyproject(mypy) Add mypy override for frozen_dataclass method-assign
tony Feb 28, 2025
477e24b
pyproject(ruff) Ignore B010 set-attr-with-constant rule for frozen_da…
tony Feb 28, 2025
19a331c
pyproject(mypy) Add mypy override for `frozen_dataclass_sealable` `me…
tony Feb 28, 2025
e5be3f4
pyproject.toml(chore[mypy]): Exclude frozen_dataclass_sealable test f…
tony Mar 1, 2025
a929424
pyproject.toml(chore[lint,types]): Exclude frozen_dataclass_sealable …
tony Mar 1, 2025
7046533
frozen_dataclass(feat): Add `frozen_dataclass`
tony Feb 28, 2025
112709f
frozen_dataclass_sealable(feat): Add `frozen_dataclass_sealable`
tony Feb 28, 2025
b6d41dc
docs(frozen_dataclass) Add to `internals`
tony Feb 28, 2025
c244be5
docs(frozen_dataclass_sealable) Add to `internals`
tony Feb 28, 2025
50be574
WIP: Snapshot
tony Feb 28, 2025
7e75203
test(Snapshot): Replace MagicMock with pytest fixtures
tony Mar 1, 2025
d9a6d8a
docs(ServerSnapshot): Fix doctest examples in snapshot.py
tony Mar 1, 2025
df905f6
docs(Pane): Fix send_keys method doctest example
tony Mar 1, 2025
239d401
src/libtmux/snapshot.py uv run ruff check --select ALL src/libtmux/sn…
tony Mar 1, 2025
82deff8
test/test_snapshot.py: uv run ruff check --select ALL src/libtmux/sna…
tony Mar 1, 2025
9a940df
chore[mypy]: Add snapshot module override
tony Mar 1, 2025
e806d88
refactor(snapshot): Add explicit type ignores for seal methods
tony Mar 1, 2025
c8b202d
test(snapshot): Add type annotation to mock_filter function
tony Mar 1, 2025
f52f617
Revert "chore[mypy]: Add snapshot module override"
tony Mar 1, 2025
8997ba1
snapshot(refactor[Snapshot]): Fix dataclass field order and enhance s…
tony Mar 1, 2025
b42672b
mypy(config[snapshot]): Add override for property/field conflicts
tony Mar 1, 2025
13f7624
test(fix[PaneSnapshot]): Specify capture_content flag in tests
tony Mar 1, 2025
1eb0307
snapshot.py(style[exceptions]): Fix linting issues identified by ruff
tony Mar 1, 2025
b4f2db5
snapshot.py(refactor[performance]): Extract helper function for sessi…
tony Mar 1, 2025
00151d7
notes(2025-03-02) Add architecture notes
tony Mar 2, 2025
d6421c8
frozen_dataclass_sealable fix imports from `typing`
tony Mar 2, 2025
47aaec8
pyproject(mypy) Add mypy override for frozen_dataclass method-assign
tony Feb 28, 2025
83088eb
snapshot(refactor[typing]): Improve type overrides with generics
tony Mar 2, 2025
314a89e
docs: proposal for snapshot.py refactoring into package structure
tony Mar 2, 2025
a30f674
snapshot: New architecture, part 0: Remove old snapshot.py
tony Mar 2, 2025
0a6b46d
snapshot: New architecture, part 1: Add new architecture
tony Mar 2, 2025
2d12f0e
mypy(config[snapshot]): Update module pattern to include submodules
tony Mar 2, 2025
5237944
notes(2025-03-02) Updates to architecture notes
tony Mar 2, 2025
91b57f7
notes(2025-03-02[architecture-plan]) Update with typing ideas
tony Mar 2, 2025
ec6db9b
snapshot(factory): Implement type-safe factory and fluent API
tony Mar 2, 2025
729430d
notes(2025-03-02[architecture-plan]) Update for latest changes
tony Mar 2, 2025
2077a36
docs(snapshot[README]) Add README
tony Mar 2, 2025
fe23292
docs(snapshot[README]): add comprehensive doctest-based README for sn…
tony Mar 2, 2025
f6fde52
docs(snapshot/README): Comprehensive overhaul with doctest integration
tony Mar 2, 2025
ac85da4
docs(snapshot/README): Add Capabilities and Limitations table
tony Mar 2, 2025
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
Prev Previous commit
Next Next commit
notes(2025-03-02) Updates to architecture notes
  • Loading branch information
tony committed Apr 26, 2025
commit 52379447a623c72dc0e594c38b9193a9fb87f09d
129 changes: 56 additions & 73 deletions notes/2025-03-02-architecture-plan.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,46 @@
<think>Let me analyze the `snapshot.py` file for its architecture, typing, and implementation details, as well as identify any flaws or opportunities for improvement in its API.
# Analysis of Snapshot Architecture

First, let's understand what this module is doing:
This document provides an analysis of the `snapshot` module architecture, with updates based on the recent refactoring efforts.

1. This module implements a snapshot mechanism for tmux objects (Server, Session, Window, Pane)
2. It uses frozen_dataclass_sealable to create immutable snapshots of these objects
3. It provides utilities to filter snapshots, convert them to dictionaries, etc.
## Current Architecture

Key classes in this module:
- PaneSnapshot, WindowSnapshot, SessionSnapshot, ServerSnapshot - these create immutable snapshots of their respective tmux objects
- Each snapshot class inherits from both the respective tmux class (Pane, Window, etc.) and Sealable
- Each has a from_X factory method to create a snapshot from a live object
The module now implements a hierarchical snapshot system for tmux objects with these key components:

Let's identify any architectural or typing issues:

1. Type annotations: The module uses Python's typing system extensively, with TypeVars, Union types, etc.
2. Immutability pattern: It uses frozen_dataclass_sealable to implement immutability
3. Circular references: The snapshots can have circular references (e.g., a WindowSnapshot has SessionSnapshot which has the same WindowSnapshot)

Now, let's look for flaws or areas for improvement:

1. **Complex Inheritance**: Multiple inheritance from both tmux objects and Sealable might cause confusion
2. **Code Duplication**: The from_X factory methods have a lot of duplicated logic
3. **Excessive Type Annotations**: Some of the type annotations might be overly complex
4. **Error Handling**: There's a mix of error suppression and re-raising
5. **Memory Usage**: Snapshots might use a lot of memory, especially with capture_content=True

API simplification opportunities:

1. **Factory Method Consistency**: Consider simplifying the factory methods
2. **Context Manager**: Consider adding a context manager for creating and using snapshots
3. **Fluent Interface**: Consider making the filter and conversion methods chainable
4. **Simplify Type Annotations**: Make type annotations more consistent and simpler where possible
5. **Reduce Circular References**: Consider alternative designs to reduce circular references

Let's discuss each of these in detail in the response.</think># Analysis of Snapshot Architecture

After examining the `snapshot.py` module, I can provide an analysis of its architecture, typing approach, and potential areas for improvement.

## Overall Architecture

The module implements a hierarchical snapshot system for tmux objects with these key components:
1. A modular package structure:
```
src/libtmux/snapshot/
├── __init__.py # Module documentation only, no exports
├── base.py # Base classes with Sealable mixins
├── types.py # Type definitions, exports, and annotations
├── models/
│ ├── __init__.py # Package documentation only, no exports
│ ├── pane.py # PaneSnapshot implementation
│ ├── window.py # WindowSnapshot implementation
│ ├── session.py # SessionSnapshot implementation
│ └── server.py # ServerSnapshot implementation
└── utils.py # Utility functions (filter_snapshot, snapshot_to_dict, etc.)
```

1. Four snapshot classes that mirror the tmux object hierarchy:
- `ServerSnapshot`
- `SessionSnapshot`
- `WindowSnapshot`
- `PaneSnapshot`
2. Four snapshot classes that mirror the tmux object hierarchy:
- `ServerSnapshot` (in `models/server.py`)
- `SessionSnapshot` (in `models/session.py`)
- `WindowSnapshot` (in `models/window.py`)
- `PaneSnapshot` (in `models/pane.py`)

2. Each class inherits from both:
3. Each class inherits from both:
- The corresponding tmux class (Server, Session, etc.)
- A `Sealable` base class to provide immutability
- A `Sealable` base class to provide immutability (defined in `base.py`)

3. Utility functions for:
4. Utility functions for:
- Filtering snapshots (`filter_snapshot`)
- Converting to dictionaries (`snapshot_to_dict`)
- Creating active-only views (`snapshot_active_only`)

5. Direct imports approach:
- No re-exports from `__init__.py` files
- Users import directly from specific modules
- Clear and explicit dependencies between modules

## Typing Approach

The module makes excellent use of Python's modern typing features:
Expand All @@ -64,14 +49,20 @@ The module makes excellent use of Python's modern typing features:
- Proper return type annotations with Union types
- Type checking guards (`if t.TYPE_CHECKING:`)
- Type casts for better type safety (`t.cast("ServerSnapshot", filtered)`)
- Centralized type definitions in `types.py`

## Strengths
## Strengths of Current Implementation

1. **Immutability Pattern**: Using `frozen_dataclass_sealable` provides a robust way to create immutable snapshots
2. **Complete Object Graph**: Snapshots maintain the full hierarchy of relationships
3. **Type Safety**: Strong typing throughout the codebase
1. **Modular Structure**: Smaller, focused files with clear responsibilities
2. **Separation of Concerns**: Types, base classes, models, and utilities are now properly separated
3. **Immutability Pattern**: Using `frozen_dataclass_sealable` provides a robust way to create immutable snapshots
4. **Type Safety**: Strong typing throughout the codebase
5. **Direct Imports**: Explicit dependencies encourage better code organization
6. **Maintainability**: Easier to understand, test, and extend each component

## Potential Flaws
## Remaining Areas for Improvement

While the modular structure has been implemented, there are still opportunities for enhancing the API:

1. **Complex Factory Methods**: The `from_X` methods contain complex logic for finding server references, with multiple fallback strategies:
```python
Expand All @@ -82,25 +73,15 @@ The module makes excellent use of Python's modern typing features:

2. **Circular References**: The bi-directional references (window_snapshot -> session_snapshot -> window_snapshot) could create complexity for serialization and garbage collection.

3. **Error Handling Inconsistencies**: There's a mix of:
```python
with contextlib.suppress(Exception):
# silent failure
```
and explicit error raising:
```python
if source_server is None:
error_msg = "Cannot create snapshot..."
raise ValueError(error_msg)
```
3. **Error Handling Consistency**: There's a mix of suppressed exceptions and explicit error raising that could be standardized.

4. **Memory Overhead**: Snapshots duplicate a lot of data, especially with `capture_content=True`.
4. **Memory Optimization**: Snapshots duplicate a lot of data, especially with `capture_content=True`.

5. **Attribute Access Pattern**: The code uses direct attribute access in some places but property methods in others.
## Future API Enhancements

## API Simplification Opportunities
For the next phase of improvements, consider:

1. **Unified Factory Method**: Consider a single entry point for snapshot creation:
1. **Unified Factory Method**: A single entry point for snapshot creation:
```python
def create_snapshot(tmux_object, capture_content=False, depth=None):
"""Create a snapshot of a tmux object."""
Expand Down Expand Up @@ -129,9 +110,7 @@ The module makes excellent use of Python's modern typing features:
)
```

4. **Focused Snapshot Classes**: The snapshots try to maintain compatibility with their tmux counterparts but override behaviors. Consider a cleaner separation with composition instead of inheritance.

5. **More Targeted Snapshot Creation**: Allow for creating more targeted snapshots:
4. **More Targeted Snapshot Creation**: Allow for creating more targeted snapshots:
```python
# Only capturing active session/window/pane hierarchy
snapshot = create_snapshot(server, include='active')
Expand All @@ -140,10 +119,14 @@ The module makes excellent use of Python's modern typing features:
snapshot = create_snapshot(server, include_sessions=['dev', 'prod'])
```

## Type Safety Improvements
## Next Steps

1. The use of `type: ignore[override]` comments suggests there might be a better way to handle property overrides in the typing system. Consider using Protocol classes or structural typing.
With the modular structure in place, focus on:

2. The `filter_snapshot` function's return type is quite complex - it might be worth creating a generic type for this.
1. **Documentation Updates**: Ensure all modules have comprehensive docstrings
2. **API Consistency**: Review the public API for consistency and usability
3. **Performance Optimization**: Profile and optimize memory usage and performance
4. **Advanced Features**: Consider implementing some of the suggested API enhancements
5. **Further Type Safety**: Address any remaining type: ignore comments with proper typing solutions

Overall, the module is well-designed but could benefit from some API simplifications to make it more intuitive for users while maintaining its strong typing and immutability guarantees.
The refactoring has successfully addressed the core structural issues, creating a strong foundation for future enhancements while maintaining backward compatibility through direct imports.
0