Shlomit-B commented on code in PR #56066:
URL: https://github.com/apache/airflow/pull/56066#discussion_r2779005466
##########
task-sdk/src/airflow/sdk/definitions/dag.py:
##########
@@ -1576,3 +1582,79 @@ def factory(*args, **kwargs):
return wrapper(dag_id_or_func)
return wrapper
+
+
+@contextmanager
+def safe_dag():
Review Comment:
I looked into custom init / pre_init, but one concern is that on exception
we may end up with a partially initialized DAG that is then used in the context
manager body, without a clear signal of which args were successfully set.
I explored an alternative approach to work around this by using a metaclass
that wraps the `DAG` constructor and, on exception, returns a `FailedDAG`
object instead. Something like:
```python
class DAGMeta(type):
def __call__(cls, *args: Any, **kwargs: Any) -> DAG | FailedDAG:
try:
return super().__call__(*args, **kwargs)
except Exception as e:
return FailedDAG(dag_id, e)
```
In both approaches, the context manager body still runs after a constructor
failure. With the metaclass, however, it is explicit which object we’re working
with, and the body fails fast when accessing missing attributes (with the
resulting exception being handled by `DAG.__exit__`), allowing parsing to
continue to the next `DAG`. For example:
```python
with DAG(<error>) as dag: # returns FailedDAG
task1 = BashOp(...) # fails when accessing missing DAG state
```
Would appreciate your feedback on this.
--
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]