par-term-emu-core-rust 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- par_term_emu_core_rust-0.2.0/.claude/agents/rust-python-terminal-expert.md +129 -0
- par_term_emu_core_rust-0.2.0/.github/workflows/README.md +271 -0
- par_term_emu_core_rust-0.2.0/.github/workflows/ci.yml +125 -0
- par_term_emu_core_rust-0.2.0/.github/workflows/deployment.yml +230 -0
- par_term_emu_core_rust-0.2.0/.github/workflows/publish-testpypi.yml +187 -0
- par_term_emu_core_rust-0.2.0/.github/workflows/release.yml +184 -0
- par_term_emu_core_rust-0.2.0/.gitignore +37 -0
- par_term_emu_core_rust-0.2.0/.pre-commit-config.yaml +83 -0
- par_term_emu_core_rust-0.2.0/AGENTS.md +81 -0
- par_term_emu_core_rust-0.2.0/CLAUDE.md +60 -0
- par_term_emu_core_rust-0.2.0/Cargo.lock +1601 -0
- par_term_emu_core_rust-0.2.0/Cargo.toml +35 -0
- par_term_emu_core_rust-0.2.0/LICENSE +21 -0
- par_term_emu_core_rust-0.2.0/Makefile +284 -0
- par_term_emu_core_rust-0.2.0/PKG-INFO +1255 -0
- par_term_emu_core_rust-0.2.0/QUICKSTART.md +176 -0
- par_term_emu_core_rust-0.2.0/README.md +1219 -0
- par_term_emu_core_rust-0.2.0/debug/diagnose_corruption.py +133 -0
- par_term_emu_core_rust-0.2.0/debug/test_debug_features.py +291 -0
- par_term_emu_core_rust-0.2.0/debug/test_wide_chars.py +129 -0
- par_term_emu_core_rust-0.2.0/docs/ADVANCED_FEATURES.md +1313 -0
- par_term_emu_core_rust-0.2.0/docs/ARCHITECTURE.md +595 -0
- par_term_emu_core_rust-0.2.0/docs/BUILDING.md +374 -0
- par_term_emu_core_rust-0.2.0/docs/CONFIG_REFERENCE.md +482 -0
- par_term_emu_core_rust-0.2.0/docs/CROSS_PLATFORM.md +302 -0
- par_term_emu_core_rust-0.2.0/docs/DOCUMENTATION_STYLE_GUIDE.md +1054 -0
- par_term_emu_core_rust-0.2.0/docs/FONTS.md +236 -0
- par_term_emu_core_rust-0.2.0/docs/MATURIN_BEST_PRACTICES.md +380 -0
- par_term_emu_core_rust-0.2.0/docs/SECURITY.md +575 -0
- par_term_emu_core_rust-0.2.0/docs/VT_FEATURE_PARITY.md +990 -0
- par_term_emu_core_rust-0.2.0/examples/README.md +391 -0
- par_term_emu_core_rust-0.2.0/examples/alt_screen.py +115 -0
- par_term_emu_core_rust-0.2.0/examples/basic_usage_improved.py +128 -0
- par_term_emu_core_rust-0.2.0/examples/bracketed_paste.py +134 -0
- par_term_emu_core_rust-0.2.0/examples/colors_demo.py +67 -0
- par_term_emu_core_rust-0.2.0/examples/cursor_movement.py +58 -0
- par_term_emu_core_rust-0.2.0/examples/display_image_sixel.py +282 -0
- par_term_emu_core_rust-0.2.0/examples/feature_showcase.py +468 -0
- par_term_emu_core_rust-0.2.0/examples/hyperlink_demo.py +87 -0
- par_term_emu_core_rust-0.2.0/examples/mouse_tracking.py +136 -0
- par_term_emu_core_rust-0.2.0/examples/notifications.py +126 -0
- par_term_emu_core_rust-0.2.0/examples/pty_basic.py +92 -0
- par_term_emu_core_rust-0.2.0/examples/pty_custom_env.py +193 -0
- par_term_emu_core_rust-0.2.0/examples/pty_event_loop.py +191 -0
- par_term_emu_core_rust-0.2.0/examples/pty_mouse_events.py +193 -0
- par_term_emu_core_rust-0.2.0/examples/pty_multiple.py +182 -0
- par_term_emu_core_rust-0.2.0/examples/pty_resize.py +179 -0
- par_term_emu_core_rust-0.2.0/examples/pty_shell.py +116 -0
- par_term_emu_core_rust-0.2.0/examples/pty_with_par_term.py +138 -0
- par_term_emu_core_rust-0.2.0/examples/rectangle_operations.py +167 -0
- par_term_emu_core_rust-0.2.0/examples/render_utils.py +167 -0
- par_term_emu_core_rust-0.2.0/examples/screenshot_demo.py +272 -0
- par_term_emu_core_rust-0.2.0/examples/scrollback_demo.py +43 -0
- par_term_emu_core_rust-0.2.0/examples/shell_integration.py +187 -0
- par_term_emu_core_rust-0.2.0/examples/synchronized_updates.py +97 -0
- par_term_emu_core_rust-0.2.0/examples/test_kitty_keyboard.py +88 -0
- par_term_emu_core_rust-0.2.0/examples/test_osc52_clipboard.py +201 -0
- par_term_emu_core_rust-0.2.0/examples/test_sixel_display.py +188 -0
- par_term_emu_core_rust-0.2.0/examples/test_sixel_simple.py +145 -0
- par_term_emu_core_rust-0.2.0/examples/test_tui_clipboard.py +119 -0
- par_term_emu_core_rust-0.2.0/examples/test_underline_styles.py +295 -0
- par_term_emu_core_rust-0.2.0/examples/text_attributes.py +55 -0
- par_term_emu_core_rust-0.2.0/examples/unicode_emoji.py +85 -0
- par_term_emu_core_rust-0.2.0/pyproject.toml +101 -0
- par_term_emu_core_rust-0.2.0/pyrightconfig.json +19 -0
- par_term_emu_core_rust-0.2.0/python/par_term_emu_core_rust/__init__.py +41 -0
- par_term_emu_core_rust-0.2.0/python/par_term_emu_core_rust/debug.py +255 -0
- par_term_emu_core_rust-0.2.0/requirements-dev.txt +6 -0
- par_term_emu_core_rust-0.2.0/scripts/install_font.sh +42 -0
- par_term_emu_core_rust-0.2.0/shell_integration/README.md +290 -0
- par_term_emu_core_rust-0.2.0/shell_integration/install.sh +248 -0
- par_term_emu_core_rust-0.2.0/shell_integration/par_term_emu_core_rust_shell_integration.bash +325 -0
- par_term_emu_core_rust-0.2.0/shell_integration/par_term_emu_core_rust_shell_integration.fish +145 -0
- par_term_emu_core_rust-0.2.0/shell_integration/par_term_emu_core_rust_shell_integration.zsh +171 -0
- par_term_emu_core_rust-0.2.0/shell_integration/test_directory_tracking.sh +29 -0
- par_term_emu_core_rust-0.2.0/snake.tiff +0 -0
- par_term_emu_core_rust-0.2.0/src/ansi_utils.rs +263 -0
- par_term_emu_core_rust-0.2.0/src/cell.rs +291 -0
- par_term_emu_core_rust-0.2.0/src/color.rs +244 -0
- par_term_emu_core_rust-0.2.0/src/color_utils.rs +286 -0
- par_term_emu_core_rust-0.2.0/src/cursor.rs +155 -0
- par_term_emu_core_rust-0.2.0/src/debug.rs +445 -0
- par_term_emu_core_rust-0.2.0/src/grid.rs +1616 -0
- par_term_emu_core_rust-0.2.0/src/html_export.rs +184 -0
- par_term_emu_core_rust-0.2.0/src/lib.rs +102 -0
- par_term_emu_core_rust-0.2.0/src/mouse.rs +124 -0
- par_term_emu_core_rust-0.2.0/src/pty_error.rs +49 -0
- par_term_emu_core_rust-0.2.0/src/pty_session.rs +897 -0
- par_term_emu_core_rust-0.2.0/src/python_bindings/conversions.rs +22 -0
- par_term_emu_core_rust-0.2.0/src/python_bindings/enums.rs +68 -0
- par_term_emu_core_rust-0.2.0/src/python_bindings/mod.rs +20 -0
- par_term_emu_core_rust-0.2.0/src/python_bindings/pty.rs +2040 -0
- par_term_emu_core_rust-0.2.0/src/python_bindings/terminal.rs +1611 -0
- par_term_emu_core_rust-0.2.0/src/python_bindings/types.rs +253 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/JetBrainsMono-Regular.ttf +0 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/NotoEmoji-Regular.ttf +0 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/config.rs +173 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/error.rs +52 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/font_cache.rs +913 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/formats/bmp.rs +11 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/formats/jpeg.rs +25 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/formats/mod.rs +4 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/formats/png.rs +11 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/formats/svg.rs +216 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/mod.rs +234 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/renderer.rs +1016 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/shaper.rs +240 -0
- par_term_emu_core_rust-0.2.0/src/screenshot/utils.rs +262 -0
- par_term_emu_core_rust-0.2.0/src/shell_integration.rs +145 -0
- par_term_emu_core_rust-0.2.0/src/sixel.rs +423 -0
- par_term_emu_core_rust-0.2.0/src/terminal/colors.rs +205 -0
- par_term_emu_core_rust-0.2.0/src/terminal/graphics.rs +126 -0
- par_term_emu_core_rust-0.2.0/src/terminal/mod.rs +1429 -0
- par_term_emu_core_rust-0.2.0/src/terminal/notification.rs +17 -0
- par_term_emu_core_rust-0.2.0/src/terminal/sequences/csi.rs +1511 -0
- par_term_emu_core_rust-0.2.0/src/terminal/sequences/dcs.rs +273 -0
- par_term_emu_core_rust-0.2.0/src/terminal/sequences/esc.rs +129 -0
- par_term_emu_core_rust-0.2.0/src/terminal/sequences/mod.rs +13 -0
- par_term_emu_core_rust-0.2.0/src/terminal/sequences/osc.rs +465 -0
- par_term_emu_core_rust-0.2.0/src/terminal/write.rs +240 -0
- par_term_emu_core_rust-0.2.0/src/tests/terminal_tests.rs +2111 -0
- par_term_emu_core_rust-0.2.0/src/text_utils.rs +509 -0
- par_term_emu_core_rust-0.2.0/terminfo/README.md +207 -0
- par_term_emu_core_rust-0.2.0/terminfo/install.sh +93 -0
- par_term_emu_core_rust-0.2.0/terminfo/par-term.ti +220 -0
- par_term_emu_core_rust-0.2.0/terminfo/test_terminfo.sh +178 -0
- par_term_emu_core_rust-0.2.0/tests/test_integration.py +408 -0
- par_term_emu_core_rust-0.2.0/tests/test_ioctl_size.py +133 -0
- par_term_emu_core_rust-0.2.0/tests/test_nested_shell_resize.py +133 -0
- par_term_emu_core_rust-0.2.0/tests/test_pty.py +358 -0
- par_term_emu_core_rust-0.2.0/tests/test_pty_resize_sigwinch.py +223 -0
- par_term_emu_core_rust-0.2.0/tests/test_screenshot.py +508 -0
- par_term_emu_core_rust-0.2.0/tests/test_sixel_raster_and_palette.py +33 -0
- par_term_emu_core_rust-0.2.0/tests/test_snapshot.py +155 -0
- par_term_emu_core_rust-0.2.0/tests/test_terminal.py +1933 -0
- par_term_emu_core_rust-0.2.0/uv.lock +376 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rust-python-terminal-expert
|
|
3
|
+
description: Use this agent when working on terminal emulator development, VT sequence parsing, PyO3 bindings, or low-level systems programming that combines Rust and Python. Examples:\n\n<example>\nContext: User is implementing a new VT sequence handler in the terminal emulator.\nuser: "I need to add support for DECSLRM (set left and right margins) sequence CSI ? 69 h"\nassistant: "Let me use the rust-python-terminal-expert agent to implement this VT sequence with proper grid operations and Python bindings."\n<Task tool invocation to launch rust-python-terminal-expert agent>\n</example>\n\n<example>\nContext: User encounters a PyO3 borrow checker error when exposing a new terminal method.\nuser: "I'm getting a borrow checker error when trying to expose get_scrollback_content() to Python"\nassistant: "This requires expertise in PyO3 patterns and Rust ownership. Let me use the rust-python-terminal-expert agent to resolve this."\n<Task tool invocation to launch rust-python-terminal-expert agent>\n</example>\n\n<example>\nContext: User needs to optimize ANSI parsing performance.\nuser: "The VTE parser seems slow when processing large amounts of output. Can we optimize it?"\nassistant: "Let me use the rust-python-terminal-expert agent to analyze and optimize the VTE parsing pipeline."\n<Task tool invocation to launch rust-python-terminal-expert agent>\n</example>\n\n<example>\nContext: User is debugging TUI corruption issues.\nuser: "The alternate screen buffer is showing garbage after switching back from vim"\nassistant: "This is a terminal state management issue. Let me use the rust-python-terminal-expert agent to debug the screen buffer switching logic."\n<Task tool invocation to launch rust-python-terminal-expert agent>\n</example>
|
|
4
|
+
model: sonnet
|
|
5
|
+
color: purple
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are an elite Rust and Python developer specializing in terminal emulation, VT sequence parsing, and low-level systems programming. Your expertise spans:
|
|
9
|
+
|
|
10
|
+
**Core Competencies:**
|
|
11
|
+
- **Terminal Emulation Standards**: Deep knowledge of VT100/VT220/VT320/xterm control sequences, ECMA-48, and modern extensions (iTerm2, shell integration)
|
|
12
|
+
- **ANSI/VT Parsing**: Expert in streaming parsers, state machines, and the VTE crate ecosystem
|
|
13
|
+
- **PyO3 Bindings**: Master of Python-Rust FFI, ownership patterns, zero-copy data sharing, and performance optimization
|
|
14
|
+
- **Low-Level Systems**: Proficient in PTY operations, threading models, atomic operations, and lock-free data structures
|
|
15
|
+
- **Rust Best Practices**: Idiomatic Rust, borrow checker mastery, trait design, and memory safety patterns
|
|
16
|
+
|
|
17
|
+
**Development Philosophy:**
|
|
18
|
+
You write code that is correct, performant, and maintainable. You understand that terminal emulators require:
|
|
19
|
+
1. **Correctness First**: VT sequences must be parsed exactly per specification - applications depend on this
|
|
20
|
+
2. **Performance Matters**: Streaming parse with zero allocations, cache-friendly data structures
|
|
21
|
+
3. **Thread Safety**: Careful coordination between PTY reader threads and UI event loops
|
|
22
|
+
4. **API Clarity**: Python bindings should be Pythonic while preserving Rust's safety guarantees
|
|
23
|
+
|
|
24
|
+
**Technical Decision-Making Framework:**
|
|
25
|
+
|
|
26
|
+
1. **For VT Sequence Implementation:**
|
|
27
|
+
- Consult xterm ctlseqs documentation and ECMA-48 standard first
|
|
28
|
+
- Implement in appropriate `*_dispatch()` method (CSI/OSC/ESC)
|
|
29
|
+
- Add comprehensive edge case tests (boundary conditions, invalid params)
|
|
30
|
+
- Document which VT standard the sequence belongs to
|
|
31
|
+
- Consider interaction with existing terminal modes
|
|
32
|
+
|
|
33
|
+
2. **For Grid/Buffer Operations:**
|
|
34
|
+
- Prefer flat Vec storage for cache efficiency
|
|
35
|
+
- Always validate indices before access to prevent panics
|
|
36
|
+
- Handle scrollback limits correctly (max_scrollback cap)
|
|
37
|
+
- Consider alternate screen implications (usually no scrollback)
|
|
38
|
+
- Test with zero dimensions, single row/col, and scroll region boundaries
|
|
39
|
+
|
|
40
|
+
3. **For PyO3 Bindings:**
|
|
41
|
+
- Keep Python wrapper thin - all logic in Rust core
|
|
42
|
+
- Use `PyResult<T>` for all fallible operations
|
|
43
|
+
- Return Python types (`tuple`, `None`) rather than Rust types
|
|
44
|
+
- Validate input at Python boundary before Rust calls
|
|
45
|
+
- Use `#[pyo3(signature = (..., param=default))]` for optional parameters
|
|
46
|
+
- Ensure module name matches between `#[pymodule]`, `pyproject.toml`, and imports
|
|
47
|
+
|
|
48
|
+
4. **For Threading/Concurrency:**
|
|
49
|
+
- Use atomic operations (`AtomicU64`, `AtomicBool`) for cross-thread state
|
|
50
|
+
- Never block the async event loop - all PTY operations non-blocking
|
|
51
|
+
- Prefer generation counters over content comparison for change detection
|
|
52
|
+
- Document which thread owns which data structures
|
|
53
|
+
- Test race conditions and cleanup scenarios
|
|
54
|
+
|
|
55
|
+
5. **For Performance Optimization:**
|
|
56
|
+
- Profile before optimizing - measure, don't guess
|
|
57
|
+
- Minimize Python/Rust boundary crossings - batch operations
|
|
58
|
+
- Use release builds for benchmarking (`--release` flag)
|
|
59
|
+
- Consider LTO and codegen-units settings
|
|
60
|
+
- Check for unnecessary allocations with VTE's zero-copy design
|
|
61
|
+
|
|
62
|
+
**Code Quality Standards:**
|
|
63
|
+
|
|
64
|
+
- **Rust Code:**
|
|
65
|
+
- Always run `cargo fmt` before committing
|
|
66
|
+
- Pass `cargo clippy -- -D warnings` (treat warnings as errors)
|
|
67
|
+
- Use `#[cfg(test)]` modules for unit tests in each file
|
|
68
|
+
- Document public APIs with doc comments (///)
|
|
69
|
+
- Prefer exhaustive match over `_` wildcard when handling enums
|
|
70
|
+
|
|
71
|
+
- **Python Code:**
|
|
72
|
+
- Use type annotations (PEP 484) for all functions
|
|
73
|
+
- Follow Google style docstrings
|
|
74
|
+
- Format with ruff: `uv run ruff format .`
|
|
75
|
+
- Type check with pyright: `uv run pyright .`
|
|
76
|
+
- Integration tests in `tests/` directory, not unit tests in modules
|
|
77
|
+
|
|
78
|
+
- **Build System:**
|
|
79
|
+
- ALWAYS use `maturin develop` (not `cargo build`) for PyO3 modules
|
|
80
|
+
- Use `uv sync` for dependency management (never pip)
|
|
81
|
+
- Run `make checkall` before committing
|
|
82
|
+
- Test both debug and release builds when performance matters
|
|
83
|
+
|
|
84
|
+
**Common Pitfalls to Avoid:**
|
|
85
|
+
|
|
86
|
+
1. **PyO3 Borrow Errors**: Terminal owns grid/cursor - use methods, not direct field access
|
|
87
|
+
2. **Index Out of Bounds**: Always validate col/row against current grid dimensions
|
|
88
|
+
3. **Screen Buffer Confusion**: Track `alt_screen_active` - operations may target wrong buffer
|
|
89
|
+
4. **Mouse Coordinate Systems**: Terminal uses 0-indexed internally, most protocols 1-indexed
|
|
90
|
+
5. **Unicode Width Handling**: Use `unicode-width` crate for proper character width calculation
|
|
91
|
+
6. **Tab Stop Assumptions**: Don't assume 8-column tabs - respect `tab_stops` Vec
|
|
92
|
+
7. **Scroll Region Bugs**: DECSTBM affects scrolling but not cursor movement
|
|
93
|
+
8. **Device Query Timing**: Responses go to `pending_responses` queue, not stdout
|
|
94
|
+
|
|
95
|
+
**Debugging Approach:**
|
|
96
|
+
|
|
97
|
+
When investigating issues:
|
|
98
|
+
1. Enable appropriate debug level: `export DEBUG_LEVEL=3`
|
|
99
|
+
2. Check `/tmp/par_term_emu_debug.log` for VT sequence logging
|
|
100
|
+
3. Use `debug_snapshot_buffer()` to inspect grid state
|
|
101
|
+
4. Verify cursor position with `debug_info()`
|
|
102
|
+
5. Test with minimal reproduction (single VT sequence, not full app)
|
|
103
|
+
6. Compare behavior with xterm or iTerm2 for reference
|
|
104
|
+
|
|
105
|
+
**Communication Style:**
|
|
106
|
+
|
|
107
|
+
You explain complex concepts clearly, using diagrams when helpful (Mermaid syntax). When providing code:
|
|
108
|
+
- Show complete implementations, not snippets (unless explicitly requested)
|
|
109
|
+
- Include both Rust and Python test cases
|
|
110
|
+
- Explain the reasoning behind architectural decisions
|
|
111
|
+
- Point out potential edge cases and how they're handled
|
|
112
|
+
- Reference relevant VT standards and documentation
|
|
113
|
+
|
|
114
|
+
You are proactive in identifying:
|
|
115
|
+
- Performance implications of design choices
|
|
116
|
+
- Thread safety concerns
|
|
117
|
+
- API ergonomics for Python users
|
|
118
|
+
- Compatibility with real-world terminal applications (vim, htop, etc.)
|
|
119
|
+
- Testing gaps that could cause subtle bugs
|
|
120
|
+
|
|
121
|
+
You understand that terminal emulators are foundational infrastructure - bugs can break every TUI application that uses them. Therefore, you prioritize correctness, comprehensive testing, and clear documentation over clever optimizations.
|
|
122
|
+
|
|
123
|
+
When you encounter ambiguity in VT standards or behavior:
|
|
124
|
+
- Test against xterm (the reference implementation)
|
|
125
|
+
- Cite specific sections of xterm ctlseqs or ECMA-48
|
|
126
|
+
- Document implementation decisions in code comments
|
|
127
|
+
- Add test cases covering the ambiguous behavior
|
|
128
|
+
|
|
129
|
+
You are the go-to expert for anything involving Rust/Python terminal emulation, low-level parsing, PyO3 bindings, or systems-level TUI infrastructure.
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# GitHub Actions Workflows
|
|
2
|
+
|
|
3
|
+
This directory contains GitHub Actions workflows for building, testing, and publishing the `par-term-emu-core-rust` package.
|
|
4
|
+
|
|
5
|
+
## Workflows
|
|
6
|
+
|
|
7
|
+
### publish-testpypi.yml - Publish to TestPyPI
|
|
8
|
+
|
|
9
|
+
**Trigger**:
|
|
10
|
+
- Manual (`workflow_dispatch`)
|
|
11
|
+
- Pull requests to main (build only, no publish)
|
|
12
|
+
|
|
13
|
+
**Purpose**: Builds and publishes to TestPyPI for testing before production release.
|
|
14
|
+
|
|
15
|
+
**Jobs**:
|
|
16
|
+
1. **build-test-wheels**: Builds wheels for all platforms (Linux x86_64/ARM64, macOS x86_64/universal2, Windows x86_64) - Python 3.13 only
|
|
17
|
+
2. **build-test-sdist**: Builds source distribution
|
|
18
|
+
3. **publish-to-testpypi**: Publishes to TestPyPI (manual trigger only)
|
|
19
|
+
4. **test-testpypi-install**: Verifies package can be installed from TestPyPI
|
|
20
|
+
|
|
21
|
+
**Features**:
|
|
22
|
+
- Automatic build verification on PRs
|
|
23
|
+
- TestPyPI publishing on manual trigger
|
|
24
|
+
- Installation testing after publish
|
|
25
|
+
- Discord notifications on success
|
|
26
|
+
- Skip existing packages
|
|
27
|
+
|
|
28
|
+
**Required Secrets**:
|
|
29
|
+
- `DISCORD_WEBHOOK`: Discord webhook URL for notifications
|
|
30
|
+
|
|
31
|
+
**TestPyPI Setup**:
|
|
32
|
+
- Environment: `testpypi`
|
|
33
|
+
- Package URL: https://test.pypi.org/p/par-term-emu-core-rust
|
|
34
|
+
- Uses TestPyPI trusted publishing
|
|
35
|
+
|
|
36
|
+
### deployment.yml - Build and Deploy
|
|
37
|
+
|
|
38
|
+
**Trigger**: Manual (`workflow_dispatch`)
|
|
39
|
+
|
|
40
|
+
**Purpose**: Builds Python wheels for multiple platforms and publishes to PyPI.
|
|
41
|
+
|
|
42
|
+
**Jobs**:
|
|
43
|
+
1. **linux**: Builds wheels for Linux x86_64 and ARM64 (Python 3.11, 3.12, 3.13)
|
|
44
|
+
2. **macos**: Builds wheels for macOS x86_64 and universal2 (Python 3.11, 3.12, 3.13)
|
|
45
|
+
3. **windows**: Builds wheels for Windows x86_64 (Python 3.11, 3.12, 3.13)
|
|
46
|
+
4. **sdist**: Builds source distribution
|
|
47
|
+
5. **publish**: Publishes to PyPI and sends Discord notification
|
|
48
|
+
|
|
49
|
+
**Platform Coverage**:
|
|
50
|
+
| Platform | Architecture | Python Versions | Testing |
|
|
51
|
+
|----------|--------------|-----------------|---------|
|
|
52
|
+
| Linux | x86_64 | 3.11, 3.12, 3.13 | ✅ Full |
|
|
53
|
+
| Linux | ARM64 (aarch64) | 3.11, 3.12, 3.13 | ⚠️ Build only* |
|
|
54
|
+
| macOS | x86_64 | 3.11, 3.12, 3.13 | ✅ Full |
|
|
55
|
+
| macOS | universal2 (Intel + Apple Silicon) | 3.11, 3.12, 3.13 | ⚠️ Partial† |
|
|
56
|
+
| Windows | x86_64 | 3.11, 3.12, 3.13 | ✅ PTY tests skipped |
|
|
57
|
+
|
|
58
|
+
*ARM64 wheels built via QEMU cross-compilation, not tested on CI
|
|
59
|
+
†Universal2 tested on x86_64 runner only
|
|
60
|
+
|
|
61
|
+
**Features**:
|
|
62
|
+
- Cross-platform wheel building using maturin
|
|
63
|
+
- Automated testing on x86_64 platforms
|
|
64
|
+
- QEMU-based ARM64 cross-compilation
|
|
65
|
+
- PyPI trusted publishing (OIDC)
|
|
66
|
+
- Discord notifications on successful publish
|
|
67
|
+
- Skip existing packages on PyPI
|
|
68
|
+
|
|
69
|
+
**Required Secrets**:
|
|
70
|
+
- `DISCORD_WEBHOOK`: Discord webhook URL for notifications
|
|
71
|
+
|
|
72
|
+
**PyPI Setup**:
|
|
73
|
+
- Environment: `pypi`
|
|
74
|
+
- Package URL: https://pypi.org/p/par-term-emu-core-rust
|
|
75
|
+
- Uses PyPI trusted publishing (no token needed)
|
|
76
|
+
|
|
77
|
+
### release.yml - Create GitHub Release
|
|
78
|
+
|
|
79
|
+
**Trigger**: Manual (`workflow_dispatch`)
|
|
80
|
+
|
|
81
|
+
**Purpose**: Creates a GitHub release with signed artifacts and triggers PyPI publishing.
|
|
82
|
+
|
|
83
|
+
**Jobs**:
|
|
84
|
+
1. **build-wheels**: Builds wheels for all platforms (Linux x86_64/ARM64, macOS x86_64/universal2, Windows x86_64) with all Python versions (3.11, 3.12, 3.13)
|
|
85
|
+
2. **build-sdist**: Builds source distribution
|
|
86
|
+
3. **github-release**: Creates GitHub release with Sigstore signatures
|
|
87
|
+
4. **trigger-pypi-publish**: Triggers the deployment workflow for PyPI publishing
|
|
88
|
+
|
|
89
|
+
**Features**:
|
|
90
|
+
- Sigstore signing for all distribution artifacts
|
|
91
|
+
- Auto-generated release notes
|
|
92
|
+
- Automatic version extraction from `__version__`
|
|
93
|
+
- Discord notifications on release creation
|
|
94
|
+
- Automatic PyPI publishing trigger
|
|
95
|
+
|
|
96
|
+
**Required Secrets**:
|
|
97
|
+
- `DISCORD_WEBHOOK`: Discord webhook URL for notifications
|
|
98
|
+
|
|
99
|
+
**Release Process**:
|
|
100
|
+
1. Update version in `python/par_term_emu_core_rust/__init__.py` and `Cargo.toml`
|
|
101
|
+
2. Commit changes
|
|
102
|
+
3. Manually trigger the "Release 🐍 distribution" workflow
|
|
103
|
+
4. Workflow creates GitHub release with signed artifacts
|
|
104
|
+
5. Workflow automatically triggers PyPI publishing
|
|
105
|
+
6. Discord notifications sent for both release and PyPI publish
|
|
106
|
+
|
|
107
|
+
## Configuration
|
|
108
|
+
|
|
109
|
+
### Discord Webhook Setup
|
|
110
|
+
|
|
111
|
+
1. Create a Discord webhook in your server settings
|
|
112
|
+
2. Add the webhook URL as a repository secret named `DISCORD_WEBHOOK`:
|
|
113
|
+
```bash
|
|
114
|
+
gh secret set DISCORD_WEBHOOK
|
|
115
|
+
```
|
|
116
|
+
3. Paste your webhook URL when prompted
|
|
117
|
+
|
|
118
|
+
### PyPI Trusted Publishing Setup
|
|
119
|
+
|
|
120
|
+
#### Production PyPI
|
|
121
|
+
1. Go to https://pypi.org/manage/account/publishing/
|
|
122
|
+
2. Add a new publisher:
|
|
123
|
+
- **PyPI Project Name**: `par-term-emu-core-rust`
|
|
124
|
+
- **Owner**: `{your-github-username-or-org}`
|
|
125
|
+
- **Repository name**: `par-term-emu-core-rust`
|
|
126
|
+
- **Workflow name**: `deployment.yml`
|
|
127
|
+
- **Environment name**: `pypi`
|
|
128
|
+
|
|
129
|
+
#### TestPyPI (for testing)
|
|
130
|
+
1. Go to https://test.pypi.org/manage/account/publishing/
|
|
131
|
+
2. Add a new publisher:
|
|
132
|
+
- **PyPI Project Name**: `par-term-emu-core-rust`
|
|
133
|
+
- **Owner**: `{your-github-username-or-org}`
|
|
134
|
+
- **Repository name**: `par-term-emu-core-rust`
|
|
135
|
+
- **Workflow name**: `publish-testpypi.yml`
|
|
136
|
+
- **Environment name**: `testpypi`
|
|
137
|
+
|
|
138
|
+
## Manual Workflow Triggers
|
|
139
|
+
|
|
140
|
+
### Test with TestPyPI (recommended first)
|
|
141
|
+
```bash
|
|
142
|
+
gh workflow run publish-testpypi.yml
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
After successful TestPyPI publish, test installation:
|
|
146
|
+
```bash
|
|
147
|
+
uv venv .venv
|
|
148
|
+
source .venv/bin/activate
|
|
149
|
+
uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ par-term-emu-core-rust
|
|
150
|
+
python -c "from par_term_emu_core_rust import Terminal; print('Success!')"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Deploy to PyPI Only
|
|
154
|
+
```bash
|
|
155
|
+
gh workflow run deployment.yml
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Create Release and Deploy (full release process)
|
|
159
|
+
```bash
|
|
160
|
+
# 1. Update version in both files
|
|
161
|
+
# 2. Commit changes
|
|
162
|
+
# 3. Trigger release
|
|
163
|
+
gh workflow run release.yml
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Version Management
|
|
167
|
+
|
|
168
|
+
The package version is managed in two places and must be kept in sync:
|
|
169
|
+
- `Cargo.toml`: Line 3 - `version = "0.2.0"`
|
|
170
|
+
- `python/par_term_emu_core_rust/__init__.py`: Line 31 - `__version__ = "0.2.0"`
|
|
171
|
+
|
|
172
|
+
Before creating a release:
|
|
173
|
+
1. Update both version strings to the new version
|
|
174
|
+
2. Commit the changes
|
|
175
|
+
3. Trigger the release workflow
|
|
176
|
+
|
|
177
|
+
## Workflow Permissions
|
|
178
|
+
|
|
179
|
+
### deployment.yml
|
|
180
|
+
- `id-token: write` - Required for PyPI trusted publishing
|
|
181
|
+
- `contents: read` - Default repository access
|
|
182
|
+
|
|
183
|
+
### release.yml
|
|
184
|
+
- `contents: write` - Create GitHub releases
|
|
185
|
+
- `id-token: write` - Sign artifacts with Sigstore
|
|
186
|
+
- `actions: write` - Trigger deployment workflow
|
|
187
|
+
|
|
188
|
+
## Troubleshooting
|
|
189
|
+
|
|
190
|
+
### Discord Notifications Not Sent
|
|
191
|
+
- Verify `DISCORD_WEBHOOK` secret is set correctly
|
|
192
|
+
- Check webhook URL is valid in Discord
|
|
193
|
+
- Notifications have `continue-on-error: true` so they won't fail the workflow
|
|
194
|
+
|
|
195
|
+
### PyPI Publishing Fails
|
|
196
|
+
- Verify trusted publisher is configured on PyPI
|
|
197
|
+
- Check environment name matches (`pypi`)
|
|
198
|
+
- Ensure package version doesn't already exist on PyPI
|
|
199
|
+
- Review PyPI publish logs in GitHub Actions
|
|
200
|
+
|
|
201
|
+
### Version Extraction Fails
|
|
202
|
+
- Ensure `__version__` is defined in `python/par_term_emu_core_rust/__init__.py`
|
|
203
|
+
- Verify Python syntax is valid in `__init__.py`
|
|
204
|
+
- Check Python version (3.13) is available in workflow
|
|
205
|
+
|
|
206
|
+
## Best Practices
|
|
207
|
+
|
|
208
|
+
1. **Always test locally before release**:
|
|
209
|
+
```bash
|
|
210
|
+
make checkall
|
|
211
|
+
cargo test
|
|
212
|
+
make test-python
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
2. **Test on TestPyPI first**:
|
|
216
|
+
- Publish to TestPyPI before production PyPI
|
|
217
|
+
- Verify installation from TestPyPI works
|
|
218
|
+
- Test in a clean environment
|
|
219
|
+
|
|
220
|
+
3. **Use semantic versioning**: MAJOR.MINOR.PATCH (e.g., 0.2.0)
|
|
221
|
+
|
|
222
|
+
4. **Create releases from main branch**: Ensure all changes are merged to main
|
|
223
|
+
|
|
224
|
+
5. **Review artifacts before publishing**: Check the wheels in the Actions artifacts
|
|
225
|
+
|
|
226
|
+
6. **Monitor Discord notifications**: Verify successful publishing via Discord
|
|
227
|
+
|
|
228
|
+
## Recommended Release Workflow
|
|
229
|
+
|
|
230
|
+
1. **Update version numbers**:
|
|
231
|
+
```bash
|
|
232
|
+
# Update both files to new version (e.g., 0.3.0)
|
|
233
|
+
# - Cargo.toml: version = "0.3.0"
|
|
234
|
+
# - python/par_term_emu_core_rust/__init__.py: __version__ = "0.3.0"
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
2. **Test locally**:
|
|
238
|
+
```bash
|
|
239
|
+
make checkall
|
|
240
|
+
cargo test
|
|
241
|
+
make test-python
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
3. **Commit and push**:
|
|
245
|
+
```bash
|
|
246
|
+
git add Cargo.toml python/par_term_emu_core_rust/__init__.py
|
|
247
|
+
git commit -m "chore: bump version to 0.3.0"
|
|
248
|
+
git push
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
4. **Test on TestPyPI**:
|
|
252
|
+
```bash
|
|
253
|
+
gh workflow run publish-testpypi.yml
|
|
254
|
+
# Wait for completion, then test installation
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
5. **Create production release**:
|
|
258
|
+
```bash
|
|
259
|
+
gh workflow run release.yml
|
|
260
|
+
# This will:
|
|
261
|
+
# - Create GitHub release with signed artifacts
|
|
262
|
+
# - Automatically trigger PyPI publishing
|
|
263
|
+
# - Send Discord notifications
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Resources
|
|
267
|
+
|
|
268
|
+
- [PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/)
|
|
269
|
+
- [Sigstore](https://www.sigstore.dev/)
|
|
270
|
+
- [Maturin Action](https://github.com/PyO3/maturin-action)
|
|
271
|
+
- [Discord Webhooks](https://discord.com/developers/docs/resources/webhook)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
test:
|
|
8
|
+
name: Test
|
|
9
|
+
runs-on: ${{ matrix.os }}
|
|
10
|
+
timeout-minutes: 15
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
os: [ubuntu-latest, macos-latest] # Windows disabled due to hanging tests
|
|
14
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Set up MSVC
|
|
25
|
+
if: runner.os == 'Windows'
|
|
26
|
+
uses: ilammy/msvc-dev-cmd@v1
|
|
27
|
+
|
|
28
|
+
- name: Set up Rust
|
|
29
|
+
uses: actions-rs/toolchain@v1
|
|
30
|
+
with:
|
|
31
|
+
toolchain: stable
|
|
32
|
+
override: true
|
|
33
|
+
|
|
34
|
+
- name: Install uv
|
|
35
|
+
run: pip install uv
|
|
36
|
+
|
|
37
|
+
- name: Create virtual environment and sync dependencies
|
|
38
|
+
run: uv venv .venv && uv sync --all-extras
|
|
39
|
+
|
|
40
|
+
- name: Install maturin in virtual environment
|
|
41
|
+
run: uv pip install maturin
|
|
42
|
+
|
|
43
|
+
- name: Build Python package
|
|
44
|
+
run: uv run maturin develop --release
|
|
45
|
+
|
|
46
|
+
- name: Run Python tests (Linux)
|
|
47
|
+
if: runner.os == 'Linux'
|
|
48
|
+
run: timeout 300 uv run pytest tests/ -v --timeout=5 --timeout-method=thread --ignore=tests/test_pty.py --ignore=tests/test_ioctl_size.py --ignore=tests/test_pty_resize_sigwinch.py --ignore=tests/test_nested_shell_resize.py
|
|
49
|
+
|
|
50
|
+
- name: Run Python tests (macOS)
|
|
51
|
+
if: runner.os == 'macOS'
|
|
52
|
+
run: uv run pytest tests/ -v --timeout=5 --timeout-method=thread --ignore=tests/test_pty.py --ignore=tests/test_ioctl_size.py --ignore=tests/test_pty_resize_sigwinch.py --ignore=tests/test_nested_shell_resize.py
|
|
53
|
+
|
|
54
|
+
lint:
|
|
55
|
+
name: Lint
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
timeout-minutes: 15
|
|
58
|
+
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v4
|
|
61
|
+
|
|
62
|
+
- name: Set up Python
|
|
63
|
+
uses: actions/setup-python@v5
|
|
64
|
+
with:
|
|
65
|
+
python-version: "3.14"
|
|
66
|
+
|
|
67
|
+
- name: Set up Rust
|
|
68
|
+
uses: actions-rs/toolchain@v1
|
|
69
|
+
with:
|
|
70
|
+
toolchain: stable
|
|
71
|
+
components: rustfmt, clippy
|
|
72
|
+
override: true
|
|
73
|
+
|
|
74
|
+
- name: Install uv
|
|
75
|
+
run: pip install uv
|
|
76
|
+
|
|
77
|
+
- name: Create virtual environment and sync dev dependencies
|
|
78
|
+
run: uv venv .venv && uv sync --group dev
|
|
79
|
+
|
|
80
|
+
- name: Check Rust formatting
|
|
81
|
+
run: cargo fmt -- --check
|
|
82
|
+
|
|
83
|
+
- name: Run Rust clippy
|
|
84
|
+
run: cargo clippy -- -D warnings
|
|
85
|
+
|
|
86
|
+
- name: Check Python formatting
|
|
87
|
+
run: uv run ruff format --check .
|
|
88
|
+
|
|
89
|
+
- name: Run Python linting
|
|
90
|
+
run: uv run ruff check .
|
|
91
|
+
|
|
92
|
+
- name: Run Python type checking
|
|
93
|
+
run: uv run pyright .
|
|
94
|
+
|
|
95
|
+
build:
|
|
96
|
+
name: Build wheels
|
|
97
|
+
runs-on: ${{ matrix.os }}
|
|
98
|
+
timeout-minutes: 15
|
|
99
|
+
strategy:
|
|
100
|
+
matrix:
|
|
101
|
+
os: [ubuntu-latest, macos-latest] # Windows disabled due to hanging tests
|
|
102
|
+
|
|
103
|
+
steps:
|
|
104
|
+
- uses: actions/checkout@v4
|
|
105
|
+
|
|
106
|
+
- name: Set up Python
|
|
107
|
+
uses: actions/setup-python@v5
|
|
108
|
+
with:
|
|
109
|
+
python-version: "3.14"
|
|
110
|
+
|
|
111
|
+
- name: Set up MSVC
|
|
112
|
+
if: runner.os == 'Windows'
|
|
113
|
+
uses: ilammy/msvc-dev-cmd@v1
|
|
114
|
+
|
|
115
|
+
- name: Install maturin
|
|
116
|
+
run: pip install maturin
|
|
117
|
+
|
|
118
|
+
- name: Build wheels
|
|
119
|
+
run: maturin build --release
|
|
120
|
+
|
|
121
|
+
- name: Upload wheels
|
|
122
|
+
uses: actions/upload-artifact@v4
|
|
123
|
+
with:
|
|
124
|
+
name: wheels-${{ matrix.label }}
|
|
125
|
+
path: target/wheels/
|