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[architecture-plan]) Update for latest changes
  • Loading branch information
tony committed Apr 26, 2025
commit 729430d545420dfc731cdd7066ef2e05f1196a4e
97 changes: 52 additions & 45 deletions notes/2025-03-02-architecture-plan.md
8000
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ The module now implements a hierarchical snapshot system for tmux objects with t
1. A modular package structure:
```
src/libtmux/snapshot/
├── __init__.py # Module documentation only, no exports
├── base.py # Base classes with Sealable mixins
├── __init__.py # Module documentation and examples
├── base.py # Base classes with Sealable mixins and common methods
├── types.py # Type definitions, exports, and annotations
├── factory.py # Type-safe centralized factory functions
├── models/
│ ├── __init__.py # Package documentation only, no exports
│ ├── pane.py # PaneSnapshot implementation
Expand All @@ -29,24 +30,36 @@ The module now implements a hierarchical snapshot system for tmux objects with t

3. Each class inherits from both:
- The corresponding tmux class (Server, Session, etc.)
- A `Sealable` base class to provide immutability (defined in `base.py`)
- A `SnapshotBase` class (derived from `Sealable`) to provide immutability and common methods
- Specialized base classes (`SealablePaneBase`, `SealableWindowBase`, etc.) in `base.py`

4. Utility functions for:
4. Centralized factory functions in `factory.py`:
- Type-safe overloaded `create_snapshot()` function for all tmux object types
- `create_snapshot_active()` convenience function for active-only snapshots
- Clear return type annotations using overloads

5. Enhanced API with common methods in the `SnapshotBase` class:
- `to_dict()` for serialization
- `filter()` for transforming snapshots
- `active_only()` for creating active-only views

6. 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
7. Direct, explicit imports and clean API:
- User-friendly factory functions
- Clear documentation in docstrings with examples
- Consistent API patterns across all snapshot classes

## Typing Approach

The module makes excellent use of Python's modern typing features:

- Type variables with covariance (`PaneT = t.TypeVar("PaneT", bound=Pane, covariant=True)`)
- Proper return type annotations with Union types
- Overloaded functions for type-safe factories
- Union types with proper return type annotations
- Type checking guards (`if t.TYPE_CHECKING:`)
- Type casts for better type safety (`t.cast("ServerSnapshot", filtered)`)
- Centralized type definitions in `types.py`
Expand All @@ -71,20 +84,26 @@ All proposals and enhancements must adhere to these core design principles:
- `SessionSnapshot` inherits from `Session`
- `ServerSnapshot` inherits from `Server`

4. **Fluent API**: Provide a fluent, chainable API for working with snapshots.
- Methods like `filter()` and `to_dict()` on all snapshot classes
- Convenience methods that return new instances (maintaining immutability)
- Consistent method names and patterns across all snapshot types

## Strengths of Current Implementation

1. **Modular Structure**: Smaller, focused files with clear responsibilities
2. **Separation of Concerns**: Types, base classes, models, and utilities are now properly separated
2. **Separation of Concerns**: Types, base classes, models, utilities, and factories are 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
4. **Type Safety**: Strong typing throughout the codebase with overloaded functions for precise return types
5. **Centralized Factory**: Single entry point with `create_snapshot()` and `create_snapshot_active()` functions
6. **Common Base Class**: `SnapshotBase` provides shared functionality across all snapshot types
7. **User-Friendly API**: Clear, consistent methods with comprehensive docstrings and examples

## Remaining Areas for Improvement

While the modular structure has been implemented, there are still opportunities for enhancing the API:
While the architecture has been significantly improved, there are still opportunities for further enhancement:

1. **Complex Factory Methods**: The `from_X` methods contain complex logic for finding server references, with multiple fallback strategies:
1. **Complex Factory Methods**: The individual `from_X` methods in snapshot classes still contain complex logic for finding server references, with multiple fallback strategies:
```python
if source_server is None and window_snapshot is not None:
source_server = window_snapshot.server
Expand Down Expand Up @@ -541,50 +560,38 @@ def create_snapshot(

```python
# Simple usage with centralized factory function
from libtmux.snapshot import create_snapshot
from libtmux.snapshot.factory import create_snapshot, create_snapshot_active

# Create a snapshot of a server
server = Server()
snapshot = create_snapshot(server)

# Create a snapshot with content capture
snapshot_with_content = create_snapshot(server, capture_content=True)

# Use fluent methods for filtering and transformation
active_windows = (
create_snapshot(server)
.filter(lambda s: isinstance(s, WindowSnapshot) and s.active)
.to_dict()
)

# Use advanced configuration
from libtmux.snapshot.models.config import SnapshotConfig
# Create a snapshot of only active components
active_snapshot = create_snapshot_active(server)

config = SnapshotConfig(
capture_content=True,
max_content_lines=100,
include_active_only=True
)

snapshot = create_snapshot(server, config=config)

# Use context manager
from libtmux.snapshot import snapshot_context

with snapshot_context(server) as snapshot:
# Work with immutable snapshot
dev_session = snapshot.find_session("dev")
if dev_session:
print(f"Dev session has {len(dev_session.windows)} windows")
# Use fluent methods for filtering and transformation
dev_session = snapshot.filter(lambda s: isinstance(s, SessionSnapshot) and s.name == "dev")
session_data = dev_session.to_dict() if dev_session else None

# Find specific components
main_session = snapshot.find_session("main")
if main_session:
active_window = main_session.active_window
if active_window:
content = active_window.active_pane.content if active_window.active_pane else None
```

## Implementation Priority and Timeline

Based on the proposals above, the following implementation timeline is suggested:

1. **Phase 1: Enhanced Factory Functions and Basic Fluent API** (1-2 weeks)
- Implement the centralized factory in `factory.py`
- Add basic fluent methods to snapshot classes
- Update type definitions for better safety
- Implement the centralized factory in `factory.py`
- Add basic fluent methods to snapshot classes
- Update type definitions for better safety

2. **Phase 2: Advanced Type Safety with Protocol Classes** (1-2 weeks)
- Implement Protocol classes in `types.py`
Expand All @@ -598,7 +605,7 @@ Based on the proposals above, the following implementation timeline is suggested

4. **Phase 4: Complete API Refinement and Documentation** (1-2 weeks)
- Finalize the public API
- Add comprehensive docstrings with examples
- Add comprehensive docstrings with examples
- Provide usage examples in README

These proposals maintain the core design principles of inheritance, immutability, and type safety while significantly improving the API ergonomics, type checking, and user experience.
0