par-term-emu-core-rust 0.2.1__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.
Files changed (136) hide show
  1. par_term_emu_core_rust-0.2.1/.claude/agents/rust-python-terminal-expert.md +129 -0
  2. par_term_emu_core_rust-0.2.1/.github/workflows/README.md +271 -0
  3. par_term_emu_core_rust-0.2.1/.github/workflows/ci.yml +129 -0
  4. par_term_emu_core_rust-0.2.1/.github/workflows/deployment.yml +307 -0
  5. par_term_emu_core_rust-0.2.1/.github/workflows/publish-testpypi.yml +187 -0
  6. par_term_emu_core_rust-0.2.1/.github/workflows/release.yml +34 -0
  7. par_term_emu_core_rust-0.2.1/.gitignore +37 -0
  8. par_term_emu_core_rust-0.2.1/.pre-commit-config.yaml +83 -0
  9. par_term_emu_core_rust-0.2.1/AGENTS.md +81 -0
  10. par_term_emu_core_rust-0.2.1/CLAUDE.md +60 -0
  11. par_term_emu_core_rust-0.2.1/Cargo.lock +1513 -0
  12. par_term_emu_core_rust-0.2.1/Cargo.toml +35 -0
  13. par_term_emu_core_rust-0.2.1/LICENSE +21 -0
  14. par_term_emu_core_rust-0.2.1/Makefile +284 -0
  15. par_term_emu_core_rust-0.2.1/PKG-INFO +1261 -0
  16. par_term_emu_core_rust-0.2.1/QUICKSTART.md +178 -0
  17. par_term_emu_core_rust-0.2.1/README.md +1225 -0
  18. par_term_emu_core_rust-0.2.1/debug/diagnose_corruption.py +133 -0
  19. par_term_emu_core_rust-0.2.1/debug/test_debug_features.py +291 -0
  20. par_term_emu_core_rust-0.2.1/debug/test_wide_chars.py +129 -0
  21. par_term_emu_core_rust-0.2.1/docs/ADVANCED_FEATURES.md +1313 -0
  22. par_term_emu_core_rust-0.2.1/docs/ARCHITECTURE.md +595 -0
  23. par_term_emu_core_rust-0.2.1/docs/BUILDING.md +376 -0
  24. par_term_emu_core_rust-0.2.1/docs/CONFIG_REFERENCE.md +482 -0
  25. par_term_emu_core_rust-0.2.1/docs/CROSS_PLATFORM.md +302 -0
  26. par_term_emu_core_rust-0.2.1/docs/DOCUMENTATION_STYLE_GUIDE.md +1054 -0
  27. par_term_emu_core_rust-0.2.1/docs/FONTS.md +236 -0
  28. par_term_emu_core_rust-0.2.1/docs/MATURIN_BEST_PRACTICES.md +380 -0
  29. par_term_emu_core_rust-0.2.1/docs/SECURITY.md +575 -0
  30. par_term_emu_core_rust-0.2.1/docs/VT_FEATURE_PARITY.md +990 -0
  31. par_term_emu_core_rust-0.2.1/examples/README.md +391 -0
  32. par_term_emu_core_rust-0.2.1/examples/alt_screen.py +115 -0
  33. par_term_emu_core_rust-0.2.1/examples/basic_usage_improved.py +128 -0
  34. par_term_emu_core_rust-0.2.1/examples/bracketed_paste.py +134 -0
  35. par_term_emu_core_rust-0.2.1/examples/colors_demo.py +67 -0
  36. par_term_emu_core_rust-0.2.1/examples/cursor_movement.py +58 -0
  37. par_term_emu_core_rust-0.2.1/examples/display_image_sixel.py +282 -0
  38. par_term_emu_core_rust-0.2.1/examples/feature_showcase.py +468 -0
  39. par_term_emu_core_rust-0.2.1/examples/hyperlink_demo.py +87 -0
  40. par_term_emu_core_rust-0.2.1/examples/mouse_tracking.py +136 -0
  41. par_term_emu_core_rust-0.2.1/examples/notifications.py +126 -0
  42. par_term_emu_core_rust-0.2.1/examples/pty_basic.py +92 -0
  43. par_term_emu_core_rust-0.2.1/examples/pty_custom_env.py +193 -0
  44. par_term_emu_core_rust-0.2.1/examples/pty_event_loop.py +191 -0
  45. par_term_emu_core_rust-0.2.1/examples/pty_mouse_events.py +193 -0
  46. par_term_emu_core_rust-0.2.1/examples/pty_multiple.py +182 -0
  47. par_term_emu_core_rust-0.2.1/examples/pty_resize.py +179 -0
  48. par_term_emu_core_rust-0.2.1/examples/pty_shell.py +116 -0
  49. par_term_emu_core_rust-0.2.1/examples/pty_with_par_term.py +138 -0
  50. par_term_emu_core_rust-0.2.1/examples/rectangle_operations.py +167 -0
  51. par_term_emu_core_rust-0.2.1/examples/render_utils.py +167 -0
  52. par_term_emu_core_rust-0.2.1/examples/screenshot_demo.py +272 -0
  53. par_term_emu_core_rust-0.2.1/examples/scrollback_demo.py +43 -0
  54. par_term_emu_core_rust-0.2.1/examples/shell_integration.py +187 -0
  55. par_term_emu_core_rust-0.2.1/examples/synchronized_updates.py +97 -0
  56. par_term_emu_core_rust-0.2.1/examples/test_kitty_keyboard.py +88 -0
  57. par_term_emu_core_rust-0.2.1/examples/test_osc52_clipboard.py +201 -0
  58. par_term_emu_core_rust-0.2.1/examples/test_sixel_display.py +188 -0
  59. par_term_emu_core_rust-0.2.1/examples/test_sixel_simple.py +145 -0
  60. par_term_emu_core_rust-0.2.1/examples/test_tui_clipboard.py +119 -0
  61. par_term_emu_core_rust-0.2.1/examples/test_underline_styles.py +295 -0
  62. par_term_emu_core_rust-0.2.1/examples/text_attributes.py +55 -0
  63. par_term_emu_core_rust-0.2.1/examples/unicode_emoji.py +85 -0
  64. par_term_emu_core_rust-0.2.1/pyproject.toml +104 -0
  65. par_term_emu_core_rust-0.2.1/pyrightconfig.json +19 -0
  66. par_term_emu_core_rust-0.2.1/python/par_term_emu_core_rust/__init__.py +41 -0
  67. par_term_emu_core_rust-0.2.1/python/par_term_emu_core_rust/debug.py +255 -0
  68. par_term_emu_core_rust-0.2.1/requirements-dev.txt +6 -0
  69. par_term_emu_core_rust-0.2.1/scripts/install_font.sh +42 -0
  70. par_term_emu_core_rust-0.2.1/shell_integration/README.md +290 -0
  71. par_term_emu_core_rust-0.2.1/shell_integration/install.sh +248 -0
  72. par_term_emu_core_rust-0.2.1/shell_integration/par_term_emu_core_rust_shell_integration.bash +325 -0
  73. par_term_emu_core_rust-0.2.1/shell_integration/par_term_emu_core_rust_shell_integration.fish +145 -0
  74. par_term_emu_core_rust-0.2.1/shell_integration/par_term_emu_core_rust_shell_integration.zsh +171 -0
  75. par_term_emu_core_rust-0.2.1/shell_integration/test_directory_tracking.sh +29 -0
  76. par_term_emu_core_rust-0.2.1/snake.tiff +0 -0
  77. par_term_emu_core_rust-0.2.1/src/ansi_utils.rs +263 -0
  78. par_term_emu_core_rust-0.2.1/src/cell.rs +544 -0
  79. par_term_emu_core_rust-0.2.1/src/color.rs +244 -0
  80. par_term_emu_core_rust-0.2.1/src/color_utils.rs +286 -0
  81. par_term_emu_core_rust-0.2.1/src/cursor.rs +266 -0
  82. par_term_emu_core_rust-0.2.1/src/debug.rs +445 -0
  83. par_term_emu_core_rust-0.2.1/src/grid.rs +1616 -0
  84. par_term_emu_core_rust-0.2.1/src/html_export.rs +184 -0
  85. par_term_emu_core_rust-0.2.1/src/lib.rs +102 -0
  86. par_term_emu_core_rust-0.2.1/src/mouse.rs +253 -0
  87. par_term_emu_core_rust-0.2.1/src/pty_error.rs +155 -0
  88. par_term_emu_core_rust-0.2.1/src/pty_session.rs +897 -0
  89. par_term_emu_core_rust-0.2.1/src/python_bindings/conversions.rs +22 -0
  90. par_term_emu_core_rust-0.2.1/src/python_bindings/enums.rs +68 -0
  91. par_term_emu_core_rust-0.2.1/src/python_bindings/mod.rs +20 -0
  92. par_term_emu_core_rust-0.2.1/src/python_bindings/pty.rs +2040 -0
  93. par_term_emu_core_rust-0.2.1/src/python_bindings/terminal.rs +1611 -0
  94. par_term_emu_core_rust-0.2.1/src/python_bindings/types.rs +253 -0
  95. par_term_emu_core_rust-0.2.1/src/screenshot/JetBrainsMono-Regular.ttf +0 -0
  96. par_term_emu_core_rust-0.2.1/src/screenshot/NotoEmoji-Regular.ttf +0 -0
  97. par_term_emu_core_rust-0.2.1/src/screenshot/config.rs +173 -0
  98. par_term_emu_core_rust-0.2.1/src/screenshot/error.rs +52 -0
  99. par_term_emu_core_rust-0.2.1/src/screenshot/font_cache.rs +913 -0
  100. par_term_emu_core_rust-0.2.1/src/screenshot/formats/bmp.rs +11 -0
  101. par_term_emu_core_rust-0.2.1/src/screenshot/formats/jpeg.rs +25 -0
  102. par_term_emu_core_rust-0.2.1/src/screenshot/formats/mod.rs +4 -0
  103. par_term_emu_core_rust-0.2.1/src/screenshot/formats/png.rs +11 -0
  104. par_term_emu_core_rust-0.2.1/src/screenshot/formats/svg.rs +216 -0
  105. par_term_emu_core_rust-0.2.1/src/screenshot/mod.rs +234 -0
  106. par_term_emu_core_rust-0.2.1/src/screenshot/renderer.rs +1016 -0
  107. par_term_emu_core_rust-0.2.1/src/screenshot/shaper.rs +240 -0
  108. par_term_emu_core_rust-0.2.1/src/screenshot/utils.rs +262 -0
  109. par_term_emu_core_rust-0.2.1/src/shell_integration.rs +145 -0
  110. par_term_emu_core_rust-0.2.1/src/sixel.rs +423 -0
  111. par_term_emu_core_rust-0.2.1/src/terminal/colors.rs +205 -0
  112. par_term_emu_core_rust-0.2.1/src/terminal/graphics.rs +126 -0
  113. par_term_emu_core_rust-0.2.1/src/terminal/mod.rs +1429 -0
  114. par_term_emu_core_rust-0.2.1/src/terminal/notification.rs +17 -0
  115. par_term_emu_core_rust-0.2.1/src/terminal/sequences/csi.rs +1511 -0
  116. par_term_emu_core_rust-0.2.1/src/terminal/sequences/dcs.rs +273 -0
  117. par_term_emu_core_rust-0.2.1/src/terminal/sequences/esc.rs +129 -0
  118. par_term_emu_core_rust-0.2.1/src/terminal/sequences/mod.rs +13 -0
  119. par_term_emu_core_rust-0.2.1/src/terminal/sequences/osc.rs +465 -0
  120. par_term_emu_core_rust-0.2.1/src/terminal/write.rs +240 -0
  121. par_term_emu_core_rust-0.2.1/src/tests/terminal_tests.rs +2111 -0
  122. par_term_emu_core_rust-0.2.1/src/text_utils.rs +509 -0
  123. par_term_emu_core_rust-0.2.1/terminfo/README.md +207 -0
  124. par_term_emu_core_rust-0.2.1/terminfo/install.sh +93 -0
  125. par_term_emu_core_rust-0.2.1/terminfo/par-term.ti +220 -0
  126. par_term_emu_core_rust-0.2.1/terminfo/test_terminfo.sh +178 -0
  127. par_term_emu_core_rust-0.2.1/tests/test_integration.py +408 -0
  128. par_term_emu_core_rust-0.2.1/tests/test_ioctl_size.py +133 -0
  129. par_term_emu_core_rust-0.2.1/tests/test_nested_shell_resize.py +133 -0
  130. par_term_emu_core_rust-0.2.1/tests/test_pty.py +358 -0
  131. par_term_emu_core_rust-0.2.1/tests/test_pty_resize_sigwinch.py +223 -0
  132. par_term_emu_core_rust-0.2.1/tests/test_screenshot.py +508 -0
  133. par_term_emu_core_rust-0.2.1/tests/test_sixel_raster_and_palette.py +33 -0
  134. par_term_emu_core_rust-0.2.1/tests/test_snapshot.py +155 -0
  135. par_term_emu_core_rust-0.2.1/tests/test_terminal.py +1933 -0
  136. par_term_emu_core_rust-0.2.1/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,129 @@
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-latest]
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
+ - name: Run Python tests (Windows)
55
+ if: runner.os == 'Windows'
56
+ 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
57
+
58
+ lint:
59
+ name: Lint
60
+ runs-on: ubuntu-latest
61
+ timeout-minutes: 15
62
+
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+
66
+ - name: Set up Python
67
+ uses: actions/setup-python@v5
68
+ with:
69
+ python-version: "3.14"
70
+
71
+ - name: Set up Rust
72
+ uses: actions-rs/toolchain@v1
73
+ with:
74
+ toolchain: stable
75
+ components: rustfmt, clippy
76
+ override: true
77
+
78
+ - name: Install uv
79
+ run: pip install uv
80
+
81
+ - name: Create virtual environment and sync dev dependencies
82
+ run: uv venv .venv && uv sync --group dev
83
+
84
+ - name: Check Rust formatting
85
+ run: cargo fmt -- --check
86
+
87
+ - name: Run Rust clippy
88
+ run: cargo clippy -- -D warnings
89
+
90
+ - name: Check Python formatting
91
+ run: uv run ruff format --check .
92
+
93
+ - name: Run Python linting
94
+ run: uv run ruff check .
95
+
96
+ - name: Run Python type checking
97
+ run: uv run pyright .
98
+
99
+ build:
100
+ name: Build wheels
101
+ runs-on: ${{ matrix.os }}
102
+ timeout-minutes: 15
103
+ strategy:
104
+ matrix:
105
+ os: [ubuntu-latest, macos-latest, windows-latest]
106
+
107
+ steps:
108
+ - uses: actions/checkout@v4
109
+
110
+ - name: Set up Python
111
+ uses: actions/setup-python@v5
112
+ with:
113
+ python-version: "3.14"
114
+
115
+ - name: Set up MSVC
116
+ if: runner.os == 'Windows'
117
+ uses: ilammy/msvc-dev-cmd@v1
118
+
119
+ - name: Install maturin
120
+ run: pip install maturin
121
+
122
+ - name: Build wheels
123
+ run: maturin build --release
124
+
125
+ - name: Upload wheels
126
+ uses: actions/upload-artifact@v4
127
+ with:
128
+ name: wheels-${{ matrix.label }}
129
+ path: target/wheels/