AmosG commented on issue #51861:
URL: https://github.com/apache/airflow/issues/51861#issuecomment-3591637288
I've successfully reproduced and fixed this issue!
I do think this is high priority - writing and debugging code is a critical
task
## Root Cause
The problem occurs because **debuggers try to introspect the context
dictionary** to display variables. In Airflow 3.x, the context contains
`VariableAccessor`, `ConnectionAccessor`, and `MacrosAccessor` objects that use
`__getattr__` for dynamic access.
When the debugger calls `hasattr(obj, "__iter__")` to check if these objects
are iterable, it triggers `__getattr__("__iter__")`, which attempts to fetch a
variable named `"__iter__"` from the Airflow variable store, causing the
infinite loop.
### Stack Trace Evidence
```python
File "debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_safe_repr.py", line
128, in _is_long_iter
if not hasattr(obj, "__iter__"):
File "airflow/sdk/execution_time/context.py", line 390, in __getattr__
return _get_variable(key, self._deserialize_json)
```
## The Solution
Add explicit `__iter__` methods to the Accessor classes in
`airflow/sdk/execution_time/context.py`:
### Changes Required
**1. VariableAccessor** (after `__repr__` method, around line 393):
```python
def __iter__(self):
raise TypeError(f"'{self.__class__.__name__}' object is not iterable")
```
**2. ConnectionAccessor** (after `__repr__` method, around line 355):
```python
def __iter__(self):
raise TypeError(f"'{self.__class__.__name__}' object is not iterable")
```
**3. MacrosAccessor** (after `__repr__` method, around line 439):
```python
def __iter__(self):
raise TypeError(f"'{self.__class__.__name__}' object is not iterable")
```
**Optional Enhancement** - Add dunder method protection in `__getattr__`
methods:
```python
def __getattr__(self, key: str) -> Any:
# Don't treat special methods (dunder methods) as variable/connection
names
if key.startswith('__') and key.endswith('__'):
raise AttributeError(f"'{self.__class__.__name__}' object has no
attribute '{key}'")
# ... rest of existing code
```
## Why This Works
- **Before**: `hasattr(obj, "__iter__")` → calls `__getattr__("__iter__")` →
tries to fetch variable → hang
- **After**: `hasattr(obj, "__iter__")` → returns `True` → calls
`obj.__iter__()` → raises `TypeError` → debugger handles gracefully
This follows Python's standard pattern for non-iterable objects.
## Testing Results
After applying this fix:
✅ Debugger works perfectly with `**context` parameters
✅ Variable access preserved: `context['var']['value'].my_var`
✅ Connection access preserved: `context['conn'].my_conn`
✅ Macro access preserved: `context['macros'].ds_add()`
✅ Works with VSCode, Zed debuggers (Problem did not seem to show on Pycharm)
✅ Tested on Airflow 3.0.2 and 3.1.3
## Temporary Workaround
Until this is fixed, users can:
1. Use named parameters: `def my_task(ti=None, ds=None):` instead of
`**context`
2. Disable variable inspection in debugger settings
3. Avoid breakpoints in functions with `**context`
## I'm Ready to Submit a PR
This is a minimal, non-breaking fix that only adds ~15 lines of code. Would
the maintainers like me to submit a PR with these changes?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]