| name | pythonista-debugging |
| description | Root cause fixing and avoiding workarounds. Use when encountering errors, bugs, or problems. Triggers on "bug", "error", "fix", "debug", "workaround", "wrapper", "hack", "broken", "not working", "failing", "issue", or when tempted to add complexity to avoid fixing the real problem. |
Root Cause Fixing - No Workarounds
Core Philosophy
NEVER use overengineering tricks to work around problems. Always fix the root cause with proper, simple code.
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
- Return tuples and unpack them
- Use
# type: ignore to suppress errors
- Create helper classes that "adapt" interfaces
This is WRONG. These are all signs you're working around a problem instead of fixing it.
Common Workarounds to Avoid
1. Wrapper Classes with __getattr__
class TestWrapper:
def __init__(self, obj):
self.obj = obj
def test_helper(self):
pass
def __getattr__(self, name):
return getattr(self.obj, name)
def test_helper(obj):
pass
2. Tuple Unpacking from Fixtures
@pytest.fixture
def my_fixture():
obj1 = create_obj1()
obj2 = create_obj2()
return obj1, obj2
def test_something(my_fixture):
obj1, obj2 = my_fixture
@pytest.fixture
def obj1():
return create_obj1()
@pytest.fixture
def obj2():
return create_obj2()
def test_something(obj1, obj2):
3. Dynamic Attribute Assignment
@pytest.fixture
def enhanced_object():
obj = ProductionClass()
obj.helper = lambda: None
return obj
@pytest.fixture
def production_object():
return ProductionClass()
def helper_method(obj):
pass
def test_something(production_object):
helper_method(production_object)
4. Adapter/Wrapper Classes
class TestAdapter:
"""Adapts production class for testing."""
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()
data = result.to_dict()
assert data["field"] == expected
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..."
- Creating an "adapter" or "wrapper" class
- Returning tuples from fixtures
- Using
# type: ignore to suppress errors instead of fixing types
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?
- Am I using overengineering tricks instead of straightforward code?
The Right Approach
- Stop when you realize you're working around
- Identify the root cause of the problem
- Fix the root cause with simple, explicit code
- Delete any workarounds you created
Real Example
Wrong - Working Around
class VideoModerationSinkWrapper:
def __init__(self, sink, fake_consumer):
self.sink = sink
self.fake_consumer = fake_consumer
async def consume_all(self):
while True:
message = await self.fake_consumer.getone()
if message is None:
break
await self.sink.on_process_message(message)
def __getattr__(self, name):
return getattr(self.sink, name)
Correct - Fix the Root Cause
@pytest_asyncio.fixture
async def kafka_consumer(kafka_setup):
"""Separate fixture for consumer."""
consumer = FakeAIOKafkaConsumer()
await consumer.start()
yield consumer
await consumer.stop()
@pytest_asyncio.fixture
async def video_moderation_sink(real_mongodb_client):
"""Separate fixture for sink."""
sink = VideoModerationDBSink(db_client=real_mongodb_client)
await sink.pre_run()
yield sink
async def consume_all_messages(sink, consumer):
"""Simple helper function - no wrapper needed."""
while True:
message = await consumer.getone()
if message is None:
break
await sink.on_process_message(message)
async def test_something(kafka_consumer, video_moderation_sink):
await consume_all_messages(video_moderation_sink, kafka_consumer)
General Principle
Simple, explicit code is ALWAYS better than overengineered workarounds that hide issues.
When faced with a problem:
- Fix the root cause
- Use simple, straightforward solutions
- Write code that's easy to understand
- Don't work around with wrappers
- Don't use magic methods
- Don't create adapters
If you find yourself thinking "I'll just wrap this..." - STOP. Fix the real problem instead.
Related Skills
- For pattern discovery, see
/pythonista-patterning
- For testing patterns, see
/pythonista-testing
- For type safety, see
/pythonista-typing