|
24 | 24 | import textwrap |
25 | 25 | import typing |
26 | 26 | import uuid |
27 | | -from collections.abc import Callable |
| 27 | +from collections.abc import Callable, Iterable |
28 | 28 | from socket import socketpair |
29 | | -from typing import TYPE_CHECKING, BinaryIO |
| 29 | +from typing import TYPE_CHECKING, Any, BinaryIO |
30 | 30 | from unittest.mock import MagicMock, patch |
31 | 31 |
|
32 | 32 | import pytest |
@@ -1571,6 +1571,24 @@ def fake_collect_dags(self, *args, **kwargs): |
1571 | 1571 | _execute_task_callbacks(dagbag, request, log) |
1572 | 1572 |
|
1573 | 1573 |
|
| 1574 | +def _recording_email_backend( |
| 1575 | + to: list[str] | Iterable[str], |
| 1576 | + subject: str, |
| 1577 | + html_content: str, |
| 1578 | + files: list[str] | None = None, |
| 1579 | + dryrun: bool = False, |
| 1580 | + cc: str | Iterable[str] | None = None, |
| 1581 | + bcc: str | Iterable[str] | None = None, |
| 1582 | + mime_subtype: str = "mixed", |
| 1583 | + mime_charset: str = "utf-8", |
| 1584 | + conn_id: str | None = None, |
| 1585 | + custom_headers: dict[str, Any] | None = None, |
| 1586 | + **kwargs, |
| 1587 | +) -> None: |
| 1588 | + """Legacy ``[email] email_backend`` stub, patched with a spec'd mock in tests.""" |
| 1589 | + raise AssertionError("should be patched in the test") |
| 1590 | + |
| 1591 | + |
1574 | 1592 | class TestExecuteEmailCallbacks: |
1575 | 1593 | """Test the email callback execution functionality.""" |
1576 | 1594 |
|
@@ -1923,6 +1941,70 @@ def test_parse_file_passes_bundle_name_to_dagbag(self): |
1923 | 1941 | call_kwargs = mock_dagbag_class.call_args.kwargs |
1924 | 1942 | assert call_kwargs["bundle_name"] == "test_bundle" |
1925 | 1943 |
|
| 1944 | + def test_execute_email_callbacks_uses_custom_email_backend(self): |
| 1945 | + """The Dag-processor path honours a custom ``[email] email_backend``, like the worker path.""" |
| 1946 | + backend = MagicMock(spec=_recording_email_backend) |
| 1947 | + dagbag = MagicMock(spec=DagBag) |
| 1948 | + with DAG(dag_id="test_dag") as dag: |
| 1949 | + BaseOperator(task_id="test_task", email=["test@example.com"]) |
| 1950 | + dagbag.dags = {"test_dag": dag} |
| 1951 | + |
| 1952 | + current_time = timezone.utcnow() |
| 1953 | + request = EmailRequest( |
| 1954 | + filepath="/path/to/dag.py", |
| 1955 | + bundle_name="test_bundle", |
| 1956 | + bundle_version="1.0.0", |
| 1957 | + ti=TIDataModel( |
| 1958 | + id=str(uuid.uuid4()), |
| 1959 | + task_id="test_task", |
| 1960 | + dag_id="test_dag", |
| 1961 | + run_id="test_run", |
| 1962 | + logical_date="2023-01-01T00:00:00Z", |
| 1963 | + try_number=1, |
| 1964 | + attempt_number=1, |
| 1965 | + state="failed", |
| 1966 | + dag_version_id=str(uuid.uuid4()), |
| 1967 | + ), |
| 1968 | + context_from_server=TIRunContext( |
| 1969 | + dag_run=DRDataModel( |
| 1970 | + dag_id="test_dag", |
| 1971 | + run_id="test_run", |
| 1972 | + logical_date="2023-01-01T00:00:00Z", |
| 1973 | + data_interval_start=current_time, |
| 1974 | + data_interval_end=current_time, |
| 1975 | + run_after=current_time, |
| 1976 | + start_date=current_time, |
| 1977 | + end_date=None, |
| 1978 | + run_type="manual", |
| 1979 | + state="running", |
| 1980 | + consumed_asset_events=[], |
| 1981 | + partition_key=None, |
| 1982 | + ), |
| 1983 | + max_tries=2, |
| 1984 | + ), |
| 1985 | + email_type="failure", |
| 1986 | + msg="Task failed", |
| 1987 | + ) |
| 1988 | + |
| 1989 | + conf_overrides = { |
| 1990 | + ("email", "email_backend"): f"{__name__}._recording_email_backend", |
| 1991 | + ("email", "email_conn_id"): "my_smtp", |
| 1992 | + ("email", "from_email"): "from@airflow", |
| 1993 | + } |
| 1994 | + with conf_vars(conf_overrides): |
| 1995 | + with patch(f"{__name__}._recording_email_backend", backend): |
| 1996 | + with patch( |
| 1997 | + "airflow.providers.smtp.notifications.smtp.SmtpNotifier", autospec=True |
| 1998 | + ) as mock_smtp_notifier: |
| 1999 | + _execute_email_callbacks(dagbag, request, MagicMock(spec=FilteringBoundLogger)) |
| 2000 | + |
| 2001 | + mock_smtp_notifier.assert_not_called() |
| 2002 | + backend.assert_called_once() |
| 2003 | + args, kwargs = backend.call_args |
| 2004 | + assert args[0] == ["test@example.com"] |
| 2005 | + assert kwargs["conn_id"] == "my_smtp" |
| 2006 | + assert kwargs["from_email"] == "from@airflow" |
| 2007 | + |
1926 | 2008 |
|
1927 | 2009 | class TestDagProcessingMessageTypes: |
1928 | 2010 | def test_message_types_in_dag_processor(self): |
|
0 commit comments