| name | pythonista-debugging |
| description | Use when encountering errors, bugs, or problems. Triggers on "bug", "error", "fix", "debug", "traceback", "stack trace", "exception", "crash", "broken", "not working", "failing", "issue", "workaround", "wrapper", "hack", "reproduce", "bisect", or when tempted to add complexity to avoid fixing the real problem. |
Debugging and Root Cause Fixing
Core Philosophy
Find and fix the root cause. NEVER work around problems with wrappers or complexity.
Debugging Workflow
1. Read the Stack Trace
Traceback (most recent call last):
File "main.py", line 10, in <module>
result = process_data(data)
File "processor.py", line 25, in process_data
return transform(item)
TypeError: 'NoneType' has no attribute 'items'
Key info: File, line number, function name, actual error message.
2. Reproduce the Bug
pytest tests/test_module.py::test_specific -v
python -c "from module import func; func(problematic_input)"
3. Use Debugger or Print Statements
print(f"DEBUG: {variable=}, {type(variable)=}")
import pdb; pdb.set_trace()
breakpoint()
4. Bisect if Needed
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
The Anti-Pattern: Working Around Instead of Fixing
When you encounter an error, your instinct may be to:
- Add a wrapper class
- Use
__getattr__ for dynamic delegation
- Use
# type: ignore to suppress errors
- Create helper classes that "adapt" interfaces
This is WRONG. These are signs you're working around instead of fixing.
Common Workarounds to Avoid
Wrapper Classes with __getattr__
class TestWrapper:
def __init__(self, obj):
self.obj = obj
def __getattr__(self, name):
return getattr(self.obj, name)
def test_helper(obj):
pass
Adapter Classes
class TestAdapter:
def __init__(self, production_obj):
self.obj = production_obj
def adapted_method(self):
return self.obj.method().to_dict()
def test_something(production_obj):
result = production_obj.method()
assert result.to_dict()["field"] == expected
Type Ignores to Hide Problems
result = maybe_none.items()
if maybe_none is not None:
result = maybe_none.items()
Red Flags
You're working around instead of fixing if you're:
- Creating a wrapper class "just for tests"
- Using
__getattr__ or other magic methods
- Adding complexity to avoid changing existing code
- Thinking "I'll just adapt this interface..."
- Using
# type: ignore without investigating why
The Right Approach
- Stop when you realize you're working around
- Identify the root cause (read stack trace, reproduce)
- Fix the root cause with simple, explicit code
- Delete any workarounds you created
Questions to Ask
- Am I adding complexity to avoid fixing the real problem?
- Is there a simpler, more direct way to do this?
- Would someone reading this code understand what's happening?
- Can I reproduce this bug with a minimal test case?
Related Skills