16
16
# under the License.
17
17
from __future__ import annotations
18
18
19
- from importlib import reload
20
19
from unittest import mock
21
20
22
21
import pytest
23
22
24
23
from airflow .exceptions import AirflowConfigException
25
24
from airflow .executors import executor_loader
26
- from airflow .executors .executor_loader import ConnectorSource , ExecutorLoader , ExecutorName
25
+ from airflow .executors .executor_loader import ConnectorSource , ExecutorName
27
26
from airflow .executors .local_executor import LocalExecutor
28
27
from airflow .providers .amazon .aws .executors .ecs .ecs_executor import AwsEcsExecutor
29
28
from airflow .providers .celery .executors .celery_executor import CeleryExecutor
@@ -35,24 +34,12 @@ class FakeExecutor:
35
34
pass
36
35
37
36
37
+ @pytest .mark .usefixtures ("clean_executor_loader" )
38
38
class TestExecutorLoader :
39
- def setup_method (self ) -> None :
40
- from airflow .executors import executor_loader
41
-
42
- reload (executor_loader )
43
- global ExecutorLoader
44
- ExecutorLoader = executor_loader .ExecutorLoader # type: ignore
45
-
46
- def teardown_method (self ) -> None :
47
- from airflow .executors import executor_loader
48
-
49
- reload (executor_loader )
50
- ExecutorLoader .init_executors ()
51
-
52
39
def test_no_executor_configured (self ):
53
40
with conf_vars ({("core" , "executor" ): None }):
54
41
with pytest .raises (AirflowConfigException , match = r".*not found in config$" ):
55
- ExecutorLoader .get_default_executor ()
42
+ executor_loader . ExecutorLoader .get_default_executor ()
56
43
57
44
@pytest .mark .parametrize (
58
45
"executor_name" ,
@@ -66,16 +53,18 @@ def test_no_executor_configured(self):
66
53
)
67
54
def test_should_support_executor_from_core (self , executor_name ):
68
55
with conf_vars ({("core" , "executor" ): executor_name }):
69
- executor = ExecutorLoader .get_default_executor ()
56
+ executor = executor_loader . ExecutorLoader .get_default_executor ()
70
57
assert executor is not None
71
58
assert executor_name == executor .__class__ .__name__
72
59
assert executor .name is not None
73
- assert executor .name == ExecutorName (ExecutorLoader .executors [executor_name ], alias = executor_name )
60
+ assert executor .name == ExecutorName (
61
+ executor_loader .ExecutorLoader .executors [executor_name ], alias = executor_name
62
+ )
74
63
assert executor .name .connector_source == ConnectorSource .CORE
75
64
76
65
def test_should_support_custom_path (self ):
77
66
with conf_vars ({("core" , "executor" ): "tests.executors.test_executor_loader.FakeExecutor" }):
78
- executor = ExecutorLoader .get_default_executor ()
67
+ executor = executor_loader . ExecutorLoader .get_default_executor ()
79
68
assert executor is not None
80
69
assert executor .__class__ .__name__ == "FakeExecutor"
81
70
assert executor .name is not None
@@ -249,17 +238,17 @@ def test_get_hybrid_executors_from_config(
249
238
"airflow.executors.executor_loader.ExecutorLoader._get_team_executor_configs" ,
250
239
return_value = team_executor_config ,
251
240
):
252
- executors = ExecutorLoader ._get_executor_names ()
241
+ executors = executor_loader . ExecutorLoader ._get_executor_names ()
253
242
assert executors == expected_executors_list
254
243
255
244
def test_init_executors (self ):
256
245
with conf_vars ({("core" , "executor" ): "CeleryExecutor" }):
257
- executors = ExecutorLoader .init_executors ()
258
- executor_name = ExecutorLoader .get_default_executor_name ()
246
+ executors = executor_loader . ExecutorLoader .init_executors ()
247
+ executor_name = executor_loader . ExecutorLoader .get_default_executor_name ()
259
248
assert len (executors ) == 1
260
249
assert isinstance (executors [0 ], CeleryExecutor )
261
- assert "CeleryExecutor" in ExecutorLoader .executors
262
- assert ExecutorLoader .executors ["CeleryExecutor" ] == executor_name .module_path
250
+ assert "CeleryExecutor" in executor_loader . ExecutorLoader .executors
251
+ assert executor_loader . ExecutorLoader .executors ["CeleryExecutor" ] == executor_name .module_path
263
252
264
253
@pytest .mark .parametrize (
265
254
"executor_config" ,
@@ -276,7 +265,7 @@ def test_get_hybrid_executors_from_config_duplicates_should_fail(self, executor_
276
265
with pytest .raises (
277
266
AirflowConfigException , match = r".+Duplicate executors are not yet supported.+"
278
267
):
279
- ExecutorLoader ._get_executor_names ()
268
+ executor_loader . ExecutorLoader ._get_executor_names ()
280
269
281
270
@pytest .mark .parametrize (
282
271
"executor_config" ,
@@ -292,7 +281,7 @@ def test_get_hybrid_executors_from_config_duplicates_should_fail(self, executor_
292
281
def test_get_hybrid_executors_from_config_core_executors_bad_config_format (self , executor_config ):
293
282
with conf_vars ({("core" , "executor" ): executor_config }):
294
283
with pytest .raises (AirflowConfigException ):
295
- ExecutorLoader ._get_executor_names ()
284
+ executor_loader . ExecutorLoader ._get_executor_names ()
296
285
297
286
@pytest .mark .parametrize (
298
287
("executor_config" , "expected_value" ),
@@ -308,7 +297,7 @@ def test_get_hybrid_executors_from_config_core_executors_bad_config_format(self,
308
297
)
309
298
def test_should_support_import_executor_from_core (self , executor_config , expected_value ):
310
299
with conf_vars ({("core" , "executor" ): executor_config }):
311
- executor , import_source = ExecutorLoader .import_default_executor_cls ()
300
+ executor , import_source = executor_loader . ExecutorLoader .import_default_executor_cls ()
312
301
assert expected_value == executor .__name__
313
302
assert import_source == ConnectorSource .CORE
314
303
@@ -322,26 +311,43 @@ def test_should_support_import_executor_from_core(self, executor_config, expecte
322
311
)
323
312
def test_should_support_import_custom_path (self , executor_config ):
324
313
with conf_vars ({("core" , "executor" ): executor_config }):
325
- executor , import_source = ExecutorLoader .import_default_executor_cls ()
314
+ executor , import_source = executor_loader . ExecutorLoader .import_default_executor_cls ()
326
315
assert executor .__name__ == "FakeExecutor"
327
316
assert import_source == ConnectorSource .CUSTOM_PATH
328
317
329
318
def test_load_executor (self ):
330
319
with conf_vars ({("core" , "executor" ): "LocalExecutor" }):
331
- ExecutorLoader .init_executors ()
332
- assert isinstance (ExecutorLoader .load_executor ("LocalExecutor" ), LocalExecutor )
333
- assert isinstance (ExecutorLoader .load_executor (executor_loader ._executor_names [0 ]), LocalExecutor )
334
- assert isinstance (ExecutorLoader .load_executor (None ), LocalExecutor )
320
+ executor_loader .ExecutorLoader .init_executors ()
321
+ assert isinstance (executor_loader .ExecutorLoader .load_executor ("LocalExecutor" ), LocalExecutor )
322
+ assert isinstance (
323
+ executor_loader .ExecutorLoader .load_executor (executor_loader ._executor_names [0 ]),
324
+ LocalExecutor ,
325
+ )
326
+ assert isinstance (executor_loader .ExecutorLoader .load_executor (None ), LocalExecutor )
335
327
336
328
def test_load_executor_alias (self ):
337
329
with conf_vars ({("core" , "executor" ): "local_exec:airflow.executors.local_executor.LocalExecutor" }):
338
- ExecutorLoader .init_executors ()
339
- assert isinstance (ExecutorLoader .load_executor ("local_exec" ), LocalExecutor )
330
+ executor_loader . ExecutorLoader .init_executors ()
331
+ assert isinstance (executor_loader . ExecutorLoader .load_executor ("local_exec" ), LocalExecutor )
340
332
assert isinstance (
341
- ExecutorLoader .load_executor ("airflow.executors.local_executor.LocalExecutor" ),
333
+ executor_loader .ExecutorLoader .load_executor (
334
+ "airflow.executors.local_executor.LocalExecutor"
335
+ ),
336
+ LocalExecutor ,
337
+ )
338
+ assert isinstance (
339
+ executor_loader .ExecutorLoader .load_executor (executor_loader ._executor_names [0 ]),
342
340
LocalExecutor ,
343
341
)
344
- assert isinstance (ExecutorLoader .load_executor (executor_loader ._executor_names [0 ]), LocalExecutor )
342
+
343
+ @mock .patch (
344
+ "airflow.executors.executor_loader.ExecutorLoader._get_executor_names" ,
345
+ wraps = executor_loader .ExecutorLoader ._get_executor_names ,
346
+ )
347
+ def test_call_load_executor_method_without_init_executors (self , mock_get_executor_names ):
348
+ with conf_vars ({("core" , "executor" ): "LocalExecutor" }):
349
+ executor_loader .ExecutorLoader .load_executor ("LocalExecutor" )
350
+ mock_get_executor_names .assert_called_once ()
345
351
346
352
@mock .patch ("airflow.providers.amazon.aws.executors.ecs.ecs_executor.AwsEcsExecutor" , autospec = True )
347
353
def test_load_custom_executor_with_classname (self , mock_executor ):
@@ -353,15 +359,16 @@ def test_load_custom_executor_with_classname(self, mock_executor):
353
359
): "my_alias:airflow.providers.amazon.aws.executors.ecs.ecs_executor.AwsEcsExecutor"
354
360
}
355
361
):
356
- ExecutorLoader .init_executors ()
357
- assert isinstance (ExecutorLoader .load_executor ("my_alias" ), AwsEcsExecutor )
358
- assert isinstance (ExecutorLoader .load_executor ("AwsEcsExecutor" ), AwsEcsExecutor )
362
+ executor_loader . ExecutorLoader .init_executors ()
363
+ assert isinstance (executor_loader . ExecutorLoader .load_executor ("my_alias" ), AwsEcsExecutor )
364
+ assert isinstance (executor_loader . ExecutorLoader .load_executor ("AwsEcsExecutor" ), AwsEcsExecutor )
359
365
assert isinstance (
360
- ExecutorLoader .load_executor (
366
+ executor_loader . ExecutorLoader .load_executor (
361
367
"airflow.providers.amazon.aws.executors.ecs.ecs_executor.AwsEcsExecutor"
362
368
),
363
369
AwsEcsExecutor ,
364
370
)
365
371
assert isinstance (
366
- ExecutorLoader .load_executor (executor_loader ._executor_names [0 ]), AwsEcsExecutor
372
+ executor_loader .ExecutorLoader .load_executor (executor_loader ._executor_names [0 ]),
373
+ AwsEcsExecutor ,
367
374
)
0 commit comments