Skip to content

Commit 49a7554

Browse files
committed
debugging functionality added
1 parent 23a773c commit 49a7554

File tree

5 files changed

+386
-1
lines changed

5 files changed

+386
-1
lines changed

README.md

+40
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,46 @@ $ telnet 127.0.0.1 6899
799799
in another terminal, where `127.0.0.1` is the IP address and `6899` is port you
800800
find in `./debug.log`.
801801

802+
#### Remote debugging example
803+
804+
Here's a complete example of how to debug a specific issue:
805+
806+
1. Let's say you suspect an issue when sending messages. Find the function in the codebase that handles this (e.g., in `zulipterminal/ui/ui.py`).
807+
808+
2. Add the debugger statement just before the suspicious code:
809+
```python
810+
def send_message(self):
811+
from pudb.remote import set_trace
812+
set_trace() # This will pause execution here
813+
# Rest of the function...
814+
```
815+
816+
3. Run Zulip Terminal with debug mode enabled:
817+
```bash
818+
zulip-term -d
819+
```
820+
821+
4. When you trigger the send_message function, check debug.log for telnet connection details:
822+
```bash
823+
tail -f debug.log
824+
```
825+
826+
5. Connect with telnet and you'll get an interactive debugger to step through the code.
827+
828+
#### Profiling for performance issues
829+
830+
If you're experiencing performance problems, you can run Zulip Terminal with profiling enabled:
831+
832+
```bash
833+
zulip-term --profile
834+
```
835+
836+
This will create a profile output file which you can analyze using:
837+
838+
```bash
839+
snakeviz zulip-terminal.prof
840+
```
841+
802842
#### There's no effect in Zulip Terminal after making local changes!
803843

804844
This likely means that you have installed both normal and development versions

makefile

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: install-devel check lint test check-clean-tree fix force-fix venv
1+
.PHONY: install-devel check lint test check-clean-tree fix force-fix venv debug debug-profile debug-clean
22

33
# NOTE: ZT_VENV and BASEPYTHON are advanced undocumented features
44
# Customize your venv name by running make as "ZT_VENV=my_venv_name make <command>"
@@ -24,6 +24,20 @@ lint: venv
2424
test: venv
2525
@pytest
2626

27+
### DEBUG TARGETS ###
28+
29+
debug: venv
30+
@echo "=== Running with debug enabled ==="
31+
$(PYTHON) -m zulipterminal.cli.run -d
32+
33+
debug-profile: venv
34+
@echo "=== Running with profiling enabled ==="
35+
$(PYTHON) -m zulipterminal.cli.run --profile
36+
37+
debug-clean:
38+
@echo "=== Cleaning debug files ==="
39+
rm -f debug.log zulip-terminal.prof zulip-terminal-tracebacks.log
40+
2741
### FIX FILES ###
2842

2943
check-clean-tree:

setup.py

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def long_description():
5454
helper_deps = [
5555
"pudb==2022.1.1",
5656
"snakeviz>=2.1.1",
57+
"requests>=2.25.0", # Added for debug_helper.py
5758
]
5859

5960
setup(
@@ -93,6 +94,7 @@ def long_description():
9394
"console_scripts": [
9495
"zulip-term = zulipterminal.cli.run:main",
9596
"zulip-term-check-symbols = zulipterminal.scripts.render_symbols:main",
97+
"zulip-term-debug = zulipterminal.scripts.debug_helper:main", # Added debug helper
9698
],
9799
},
98100
extras_require={

tools/debug_helper.py

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Helper script for debugging Zulip Terminal.
4+
5+
This script provides utilities for common debugging tasks:
6+
1. Analyzing debug logs
7+
2. Testing connectivity to Zulip server
8+
3. Checking terminal capabilities
9+
"""
10+
11+
import argparse
12+
import os
13+
import re
14+
import sys
15+
import subprocess
16+
import json
17+
from pathlib import Path
18+
19+
20+
def analyze_debug_log(log_file="debug.log"):
21+
"""
22+
Analyze a debug log file for common issues.
23+
"""
24+
if not os.path.exists(log_file):
25+
print(f"Error: Log file '{log_file}' not found")
26+
return
27+
28+
print(f"Analyzing {log_file}...")
29+
with open(log_file, 'r') as f:
30+
content = f.read()
31+
32+
# Look for error patterns
33+
error_patterns = [
34+
r'ERROR',
35+
r'Exception',
36+
r'Traceback',
37+
r'Failed to'
38+
]
39+
40+
errors_found = False
41+
for pattern in error_patterns:
42+
matches = re.finditer(pattern, content, re.IGNORECASE)
43+
for match in matches:
44+
line_start = content.rfind('\n', 0, match.start()) + 1
45+
line_end = content.find('\n', match.end())
46+
if line_end == -1:
47+
line_end = len(content)
48+
49+
line = content[line_start:line_end].strip()
50+
print(f"Potential issue found: {line}")
51+
errors_found = True
52+
53+
if not errors_found:
54+
print("No obvious errors found in the log file.")
55+
56+
57+
def test_connectivity(server_url=None):
58+
"""
59+
Test connectivity to a Zulip server.
60+
"""
61+
if not server_url:
62+
# Try to get server URL from zuliprc
63+
zuliprc_path = os.path.expanduser("~/.zuliprc")
64+
if os.path.exists(zuliprc_path):
65+
with open(zuliprc_path, 'r') as f:
66+
for line in f:
67+
if line.startswith('site='):
68+
server_url = line.split('=')[1].strip()
69+
break
70+
71+
if not server_url:
72+
print("Error: No server URL provided and couldn't find one in ~/.zuliprc")
73+
return
74+
75+
print(f"Testing connectivity to {server_url}...")
76+
try:
77+
import requests
78+
response = requests.get(f"{server_url}/api/v1/server_settings")
79+
if response.status_code == 200:
80+
print(f"Successfully connected to {server_url}")
81+
try:
82+
settings = response.json()
83+
print(f"Server version: {settings.get('zulip_version', 'unknown')}")
84+
except json.JSONDecodeError:
85+
print("Received response, but couldn't parse as JSON")
86+
else:
87+
print(f"Failed to connect: HTTP status {response.status_code}")
88+
except Exception as e:
89+
print(f"Connection error: {e}")
90+
91+
92+
def check_terminal_capabilities():
93+
"""
94+
Check for terminal capabilities that might affect Zulip Terminal.
95+
"""
96+
print("Checking terminal capabilities...")
97+
98+
# Check for color support
99+
colors = os.environ.get('TERM', 'unknown')
100+
print(f"TERM environment: {colors}")
101+
102+
if 'COLORTERM' in os.environ:
103+
print(f"COLORTERM: {os.environ['COLORTERM']}")
104+
105+
# Check for Unicode support
106+
print("\nTesting Unicode rendering capabilities:")
107+
test_chars = [
108+
("Basic symbols", "▶ ◀ ✓ ✗"),
109+
("Emoji (simple)", "😀 🙂 👍"),
110+
("Box drawing", "│ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼"),
111+
("Math symbols", "∞ ∑ √ ∫ π")
112+
]
113+
114+
for name, chars in test_chars:
115+
print(f" {name}: {chars}")
116+
117+
# Check for urwid compatibility
118+
try:
119+
import urwid
120+
print("\nUrwid detected. Running basic urwid test...")
121+
# This doesn't actually run a visual test - just checks if urwid can be imported
122+
print("Urwid import successful")
123+
except ImportError:
124+
print("Urwid not found. This may indicate installation issues.")
125+
126+
127+
def main():
128+
parser = argparse.ArgumentParser(description="Zulip Terminal Debugging Helper")
129+
subparsers = parser.add_subparsers(dest="command", help="Command to run")
130+
131+
# Log analyzer
132+
log_parser = subparsers.add_parser("log", help="Analyze debug logs")
133+
log_parser.add_argument("--file", default="debug.log", help="Log file to analyze")
134+
135+
# Connectivity test
136+
conn_parser = subparsers.add_parser("connect", help="Test connectivity")
137+
conn_parser.add_argument("--server", help="Server URL (e.g., https://chat.zulip.org)")
138+
139+
# Terminal test
140+
term_parser = subparsers.add_parser("terminal", help="Check terminal capabilities")
141+
142+
# Run zulip-term with debug
143+
run_parser = subparsers.add_parser("run", help="Run zulip-term with debugging")
144+
run_parser.add_argument("--profile", action="store_true", help="Enable profiling")
145+
146+
args = parser.parse_args()
147+
148+
if args.command == "log":
149+
analyze_debug_log(args.file)
150+
elif args.command == "connect":
151+
test_connectivity(args.server)
152+
elif args.command == "terminal":
153+
check_terminal_capabilities()
154+
elif args.command == "run":
155+
cmd = ["zulip-term", "-d"]
156+
if args.profile:
157+
cmd.append("--profile")
158+
print(f"Running: {' '.join(cmd)}")
159+
subprocess.run(cmd)
160+
else:
161+
parser.print_help()
162+
163+
164+
if __name__ == "__main__":
165+
main()

0 commit comments

Comments
 (0)