peeka 0.1.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 (83) hide show
  1. peeka-0.1.1/PKG-INFO +11 -0
  2. peeka-0.1.1/README.md +281 -0
  3. peeka-0.1.1/peeka/__init__.py +2 -0
  4. peeka-0.1.1/peeka/cli/__init__.py +2 -0
  5. peeka-0.1.1/peeka/cli/main.py +1300 -0
  6. peeka-0.1.1/peeka/commands/__init__.py +0 -0
  7. peeka-0.1.1/peeka/commands/base.py +46 -0
  8. peeka-0.1.1/peeka/commands/complete.py +182 -0
  9. peeka-0.1.1/peeka/commands/detach.py +46 -0
  10. peeka-0.1.1/peeka/commands/logger.py +153 -0
  11. peeka-0.1.1/peeka/commands/memory.py +642 -0
  12. peeka-0.1.1/peeka/commands/monitor.py +333 -0
  13. peeka-0.1.1/peeka/commands/reset.py +59 -0
  14. peeka-0.1.1/peeka/commands/search.py +304 -0
  15. peeka-0.1.1/peeka/commands/stack.py +125 -0
  16. peeka-0.1.1/peeka/commands/thread.py +282 -0
  17. peeka-0.1.1/peeka/commands/top.py +368 -0
  18. peeka-0.1.1/peeka/commands/trace.py +122 -0
  19. peeka-0.1.1/peeka/commands/vmtool.py +558 -0
  20. peeka-0.1.1/peeka/commands/watch.py +125 -0
  21. peeka-0.1.1/peeka/core/__init__.py +0 -0
  22. peeka-0.1.1/peeka/core/agent.py +258 -0
  23. peeka-0.1.1/peeka/core/attach.py +381 -0
  24. peeka-0.1.1/peeka/core/client.py +278 -0
  25. peeka-0.1.1/peeka/core/injector.py +1266 -0
  26. peeka-0.1.1/peeka/core/monitor.py +134 -0
  27. peeka-0.1.1/peeka/core/observer.py +245 -0
  28. peeka-0.1.1/peeka/core/output.py +74 -0
  29. peeka-0.1.1/peeka/core/safeeval/__init__.py +8 -0
  30. peeka-0.1.1/peeka/core/safeeval/simpleeval.py +931 -0
  31. peeka-0.1.1/peeka/tui/__init__.py +106 -0
  32. peeka-0.1.1/peeka/tui/__main__.py +9 -0
  33. peeka-0.1.1/peeka/tui/app.py +128 -0
  34. peeka-0.1.1/peeka/tui/completion.py +60 -0
  35. peeka-0.1.1/peeka/tui/screens/__init__.py +1 -0
  36. peeka-0.1.1/peeka/tui/screens/help.py +89 -0
  37. peeka-0.1.1/peeka/tui/screens/main.py +185 -0
  38. peeka-0.1.1/peeka/tui/screens/process_selector.py +185 -0
  39. peeka-0.1.1/peeka/tui/styles/peeka.tcss +582 -0
  40. peeka-0.1.1/peeka/tui/views/__init__.py +1 -0
  41. peeka-0.1.1/peeka/tui/views/dashboard.py +435 -0
  42. peeka-0.1.1/peeka/tui/views/inspect.py +162 -0
  43. peeka-0.1.1/peeka/tui/views/logger.py +194 -0
  44. peeka-0.1.1/peeka/tui/views/memory.py +1034 -0
  45. peeka-0.1.1/peeka/tui/views/monitor.py +322 -0
  46. peeka-0.1.1/peeka/tui/views/stack.py +367 -0
  47. peeka-0.1.1/peeka/tui/views/thread.py +295 -0
  48. peeka-0.1.1/peeka/tui/views/top.py +270 -0
  49. peeka-0.1.1/peeka/tui/views/trace.py +567 -0
  50. peeka-0.1.1/peeka/tui/views/watch.py +645 -0
  51. peeka-0.1.1/peeka/tui/widgets/__init__.py +1 -0
  52. peeka-0.1.1/peeka/tui/widgets/autocomplete_input.py +195 -0
  53. peeka-0.1.1/peeka/utils/__init__.py +0 -0
  54. peeka-0.1.1/peeka/utils/formatters.py +195 -0
  55. peeka-0.1.1/peeka/utils/patterns.py +96 -0
  56. peeka-0.1.1/peeka.egg-info/PKG-INFO +11 -0
  57. peeka-0.1.1/peeka.egg-info/SOURCES.txt +81 -0
  58. peeka-0.1.1/peeka.egg-info/dependency_links.txt +1 -0
  59. peeka-0.1.1/peeka.egg-info/entry_points.txt +3 -0
  60. peeka-0.1.1/peeka.egg-info/requires.txt +8 -0
  61. peeka-0.1.1/peeka.egg-info/top_level.txt +1 -0
  62. peeka-0.1.1/pyproject.toml +42 -0
  63. peeka-0.1.1/setup.cfg +4 -0
  64. peeka-0.1.1/tests/test_client_thread_safety.py +617 -0
  65. peeka-0.1.1/tests/test_client_unit.py +300 -0
  66. peeka-0.1.1/tests/test_compatibility.py +307 -0
  67. peeka-0.1.1/tests/test_detach_cmd.py +114 -0
  68. peeka-0.1.1/tests/test_injector.py +538 -0
  69. peeka-0.1.1/tests/test_integration.py +285 -0
  70. peeka-0.1.1/tests/test_logger_cmd.py +180 -0
  71. peeka-0.1.1/tests/test_memory.py +369 -0
  72. peeka-0.1.1/tests/test_monitor.py +302 -0
  73. peeka-0.1.1/tests/test_observer.py +141 -0
  74. peeka-0.1.1/tests/test_output_formatter.py +291 -0
  75. peeka-0.1.1/tests/test_reset.py +484 -0
  76. peeka-0.1.1/tests/test_search.py +262 -0
  77. peeka-0.1.1/tests/test_stack.py +257 -0
  78. peeka-0.1.1/tests/test_theme.py +260 -0
  79. peeka-0.1.1/tests/test_trace.py +355 -0
  80. peeka-0.1.1/tests/test_tui.py +279 -0
  81. peeka-0.1.1/tests/test_utils_formatters.py +286 -0
  82. peeka-0.1.1/tests/test_utils_patterns.py +163 -0
  83. peeka-0.1.1/tests/test_vmtool.py +575 -0
peeka-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: peeka
3
+ Version: 0.1.1
4
+ Summary: A Python dynamic debugger inspired by Arthas, using Python 3.14's safe external debugger interface
5
+ Requires-Python: >=3.9
6
+ Provides-Extra: tui
7
+ Requires-Dist: textual>=7.5.0; extra == "tui"
8
+ Provides-Extra: dev
9
+ Requires-Dist: textual>=7.5.0; extra == "dev"
10
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
11
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
peeka-0.1.1/README.md ADDED
@@ -0,0 +1,281 @@
1
+ <p align="right">
2
+ <a href="README.zh-CN.md">中文</a> | <strong>English</strong>
3
+ </p>
4
+
5
+ # Peeka
6
+
7
+ Runtime diagnostic tool for Python applications, inspired by [Alibaba Arthas](https://github.com/alibaba/arthas). Non-invasive function observation with zero code changes.
8
+
9
+ Uses [PEP 768](https://peps.python.org/pep-0768/) (`sys.remote_exec`) on Python 3.14+, with a GDB + ptrace fallback for Python 3.9–3.13.
10
+
11
+ ## Key Features
12
+
13
+ - **Non-invasive** — Inject observation logic at runtime, fully restored on detach
14
+ - **Real-time streaming** — Millisecond-latency data via Unix domain sockets
15
+ - **Production-safe** — < 5% overhead, fixed-size memory buffers, graceful error recovery
16
+ - **Secure filtering** — [simpleeval](https://github.com/danthedeckie/simpleeval)-based condition expressions, blocks all code injection
17
+ - **Dual interface** — CLI (JSONL output, pipe-friendly) and interactive TUI
18
+
19
+ ## Quick Start
20
+
21
+ ### Install
22
+
23
+ ```bash
24
+ pip install peeka # CLI only
25
+ pip install peeka[tui] # CLI + TUI
26
+ ```
27
+
28
+ ### Basic Usage
29
+
30
+ ```bash
31
+ # 1. Attach to a running Python process
32
+ peeka-cli attach <pid>
33
+
34
+ # 2. Watch function calls
35
+ peeka-cli watch "module.Class.method" -n 5
36
+
37
+ # 3. Watch with condition filter
38
+ peeka-cli watch "module.func" --condition "params[0] > 100"
39
+
40
+ # 4. Trace call tree with timing
41
+ peeka-cli trace "module.func" -d 3
42
+
43
+ # 5. Capture call stack
44
+ peeka-cli stack "module.func" -n 3
45
+
46
+ # 6. Launch TUI
47
+ peeka
48
+ ```
49
+
50
+ ### Pipe-Friendly Output (JSONL)
51
+
52
+ All CLI output is JSONL — one JSON object per line with a `type` field:
53
+
54
+ ```bash
55
+ # Filter observations with jq
56
+ peeka-cli watch "module.func" | jq 'select(.type == "observation")'
57
+
58
+ # Find slow calls
59
+ peeka-cli watch "module.func" | jq 'select(.type == "observation" and .data.duration_ms > 100)'
60
+
61
+ # Save to file
62
+ peeka-cli watch "module.func" > observations.jsonl
63
+ ```
64
+
65
+ ## Commands
66
+
67
+ | Command | Description |
68
+ |-----------|---------------------------------------------|
69
+ | `attach` | Attach to a running Python process |
70
+ | `watch` | Observe function calls (args, return, time) |
71
+ | `trace` | Trace call tree with timing breakdown |
72
+ | `stack` | Capture call stack at function entry |
73
+ | `monitor` | Periodic performance statistics |
74
+ | `logger` | Adjust log levels at runtime |
75
+ | `memory` | Memory usage analysis |
76
+ | `inspect` | Runtime object inspection |
77
+ | `sc`/`sm` | Search classes / search methods |
78
+ | `reset` | Remove all injected enhancements |
79
+ | `detach` | Detach from target process |
80
+
81
+ ### watch
82
+
83
+ ```bash
84
+ peeka-cli watch <pattern> [options]
85
+ ```
86
+
87
+ | Option | Description | Default |
88
+ |--------------------|-----------------------------------------|---------|
89
+ | `-x, --depth` | Output depth for nested objects | 2 |
90
+ | `-n, --times` | Number of observations (-1 = infinite) | -1 |
91
+ | `--condition` | Filter expression (supports `cost` var) | — |
92
+ | `-b, --before` | Observe at function entry | false |
93
+ | `-s, --success` | Observe on success only | false |
94
+ | `-e, --exception` | Observe on exception only | false |
95
+ | `-f, --finish` | Observe on both success and exception | true |
96
+
97
+ **Pattern format**: `module.Class.method` or `module.function`
98
+
99
+ ### trace
100
+
101
+ ```bash
102
+ peeka-cli trace <pattern> [options]
103
+ ```
104
+
105
+ | Option | Description | Default |
106
+ |--------------------|--------------------------------------------|---------|
107
+ | `-d, --depth` | Max call tree depth | 3 |
108
+ | `-n, --times` | Number of observations (-1 = infinite) | -1 |
109
+ | `--condition` | Filter expression (supports `cost` var) | — |
110
+ | `--skip-builtin` | Skip stdlib/built-in functions | true |
111
+ | `--min-duration` | Minimum duration filter (ms) | 0 |
112
+
113
+ **Output example:**
114
+
115
+ ```
116
+ `---[125.3ms] calculator.Calculator.calculate()
117
+ +---[2.1ms] calculator.Calculator._validate()
118
+ +---[98.2ms] calculator.Calculator._compute()
119
+ | `---[95.1ms] math.sqrt()
120
+ `---[15.7ms] calculator.Logger.info()
121
+ ```
122
+
123
+ ### stack
124
+
125
+ ```bash
126
+ peeka-cli stack <pattern> [options]
127
+ ```
128
+
129
+ | Option | Description | Default |
130
+ |--------------------|--------------------------------------------|---------|
131
+ | `-n, --times` | Number of captures (-1 = infinite) | -1 |
132
+ | `--condition` | Filter expression | — |
133
+ | `--depth` | Stack depth limit | 10 |
134
+
135
+ ## Condition Expressions
136
+
137
+ Powered by [simpleeval](https://github.com/danthedeckie/simpleeval) for safe evaluation:
138
+
139
+ ```python
140
+ params[0] > 100 # Positional argument check
141
+ len(params) > 2 # Argument count
142
+ kwargs.get('debug') == True # Keyword argument check
143
+ cost > 50 # Execution time in ms (watch/trace)
144
+ str(x).startswith('prefix') # String operations
145
+ x + y > 10 # Arithmetic
146
+ ```
147
+
148
+ **Security**: Only safe operations (comparisons, arithmetic, logic) are allowed. `eval`, `exec`, `__import__`, `open`, `compile` and reflection via `__class__`/`__subclasses__` are all blocked.
149
+
150
+ ## Output Format
151
+
152
+ Every line is a JSON object with a `type` field:
153
+
154
+ | Type | Description | Commands |
155
+ |---------------|-------------------------------------|------------------------|
156
+ | `status` | Progress/info messages | attach |
157
+ | `success` | Command completed successfully | attach, detach |
158
+ | `error` | Command failed | all |
159
+ | `event` | Control events (started/stopped) | watch, stack, monitor |
160
+ | `observation` | Real-time observation data | watch, stack, monitor |
161
+ | `result` | Query results (non-streaming) | logger, memory, sc, sm |
162
+
163
+ <details>
164
+ <summary>Output examples</summary>
165
+
166
+ ```json
167
+ {"type": "status", "level": "info", "message": "Attaching to process 12345"}
168
+ {"type": "success", "command": "attach", "data": {"pid": 12345, "socket": "/tmp/peeka_xxx.sock"}}
169
+ {"type": "event", "event": "watch_started", "data": {"watch_id": "watch_001", "pattern": "module.func"}}
170
+ {
171
+ "type": "observation",
172
+ "watch_id": "watch_001",
173
+ "timestamp": 1705586200.123,
174
+ "func_name": "demo.Calculator.add",
175
+ "args": [1, 2],
176
+ "kwargs": {},
177
+ "result": 3,
178
+ "success": true,
179
+ "duration_ms": 0.123,
180
+ "count": 1
181
+ }
182
+ {"type": "error", "command": "watch", "error": "Cannot find target: invalid.pattern"}
183
+ ```
184
+
185
+ </details>
186
+
187
+ ## Python Version Support
188
+
189
+ | Python Version | Attach Mechanism | Requirements |
190
+ |----------------|-------------------------------|-----------------------------------|
191
+ | 3.14+ | PEP 768 `sys.remote_exec()` | Same UID or `CAP_SYS_PTRACE` |
192
+ | 3.9–3.13 | GDB + ptrace fallback | GDB 7.3+, ptrace_scope ≤ 1 |
193
+
194
+ ### Python < 3.14 Setup
195
+
196
+ GDB is required. Debug symbols are **strongly recommended** — some distros include them by default, but if GDB reports "no symbol" errors, install them:
197
+
198
+ ```bash
199
+ # Debian/Ubuntu
200
+ sudo apt-get install gdb python3-dbg
201
+
202
+ # RHEL/Fedora
203
+ sudo yum install gdb python3-debuginfo
204
+
205
+ # Arch
206
+ sudo pacman -S gdb
207
+ ```
208
+
209
+ ### Docker
210
+
211
+ ```bash
212
+ docker run --cap-add=SYS_PTRACE your-image
213
+ ```
214
+
215
+ ### ptrace Restrictions
216
+
217
+ ```bash
218
+ # Check current setting
219
+ cat /proc/sys/kernel/yama/ptrace_scope
220
+
221
+ # Temporarily allow (for testing)
222
+ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
223
+
224
+ # SELinux (Fedora/RHEL)
225
+ sudo setsebool -P deny_ptrace=off
226
+ ```
227
+
228
+ ## Environment Variables
229
+
230
+ | Variable | Description | Default |
231
+ |----------------------|------------------------------|----------|
232
+ | `PEEKA_SOCKET_DIR` | Socket file directory | `/tmp` |
233
+ | `PEEKA_TIMEOUT` | Command timeout (seconds) | `30` |
234
+ | `PEEKA_BUFFER_SIZE` | Observation buffer size | `10000` |
235
+
236
+ ## Troubleshooting
237
+
238
+ ### Attach fails (permission denied)
239
+
240
+ - Ensure same UID or `CAP_SYS_PTRACE`
241
+ - Check `ptrace_scope` (see above)
242
+ - For GDB fallback: install debug symbols if "no symbol" error appears
243
+
244
+ ### No observation data
245
+
246
+ - Verify function name (use fully qualified name: `module.Class.method`)
247
+ - Confirm the function is actually being called
248
+ - Check if condition expression is too restrictive
249
+
250
+ ### Target process behaving abnormally
251
+
252
+ ```bash
253
+ # Stop observation
254
+ peeka-cli watch --action stop <watch_id>
255
+
256
+ # If issues persist, restart target process
257
+ ```
258
+
259
+ ## Architecture
260
+
261
+ ```
262
+ CLI/TUI → AgentClient → Unix Socket → PeekaAgent (injected in target)
263
+ ├─ CommandRouter → BaseCommand subclasses
264
+ ├─ DecoratorInjector (function wrapping)
265
+ └─ ObservationManager (buffered streaming)
266
+ ```
267
+
268
+ - **Attach**: PEP 768 `sys.remote_exec()` on 3.14+, GDB + ptrace on 3.9–3.13
269
+ - **Observe**: Decorator injection wraps target functions, captures args/return/exceptions/timing
270
+ - **Stream**: Real-time observation data via Unix domain socket (length-prefixed JSON)
271
+ - **Commands**: Modular `BaseCommand` subclasses, registered in `PeekaAgent._register_handlers()`
272
+
273
+ ## License
274
+
275
+ MIT License
276
+
277
+ ## Acknowledgments
278
+
279
+ - Inspired by [Alibaba Arthas](https://github.com/alibaba/arthas)
280
+ - Safe evaluation: [simpleeval](https://github.com/danthedeckie/simpleeval)
281
+ - Remote debugging protocol: [PEP 768](https://peps.python.org/pep-0768/)
@@ -0,0 +1,2 @@
1
+ """PeekA - Python Dynamic Debugger"""
2
+ __version__ = "0.1.1"
@@ -0,0 +1,2 @@
1
+ from .main import main
2
+