Skip to content

Commit b1085b5

Browse files
gavin-aguiarGavin Aguiar
andauthored
Enabled dependency isolation by default (#1055)
* Enabled dependency isolation by default * Unit test fixes * Fixed flake8 tests * Enabled dependency isolation by default * Unit test fixes * Fixed flake8 tests * Reverted loader.py change * Added unit tests * Added unit tests * Reverted loader.py change * Added copyright comment Co-authored-by: Gavin Aguiar <[email protected]>
1 parent b582f2b commit b1085b5

File tree

5 files changed

+40
-97
lines changed

5 files changed

+40
-97
lines changed

azure_functions_worker/constants.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@
4343
PYTHON_THREADPOOL_THREAD_COUNT_MAX = sys.maxsize
4444
PYTHON_THREADPOOL_THREAD_COUNT_MAX_37 = 32
4545

46-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT = False
47-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT_310 = False
46+
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT = True
4847
PYTHON_ENABLE_WORKER_EXTENSIONS_DEFAULT = False
4948
PYTHON_ENABLE_WORKER_EXTENSIONS_DEFAULT_39 = True
5049

azure_functions_worker/utils/dependency.py

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
from azure_functions_worker.utils.common import is_true_like
2-
from typing import List, Optional
3-
from types import ModuleType
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
43
import importlib
54
import inspect
65
import os
76
import re
87
import sys
8+
from types import ModuleType
9+
from typing import List, Optional
910

10-
from ..logging import logger
11+
from azure_functions_worker.utils.common import is_true_like
1112
from ..constants import (
1213
AZURE_WEBJOBS_SCRIPT_ROOT,
1314
CONTAINER_NAME,
1415
PYTHON_ISOLATE_WORKER_DEPENDENCIES,
15-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT,
16-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT_310
16+
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT
1717
)
18-
from ..utils.common import is_python_version
18+
from ..logging import logger
1919
from ..utils.wrappers import enable_feature_by
2020

2121

@@ -75,12 +75,7 @@ def is_in_linux_consumption(cls):
7575
@classmethod
7676
@enable_feature_by(
7777
flag=PYTHON_ISOLATE_WORKER_DEPENDENCIES,
78-
flag_default=(
79-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT_310 if
80-
is_python_version('3.10') else
81-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT
82-
)
83-
)
78+
flag_default=PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT)
8479
def use_worker_dependencies(cls):
8580
"""Switch the sys.path and ensure the worker imports are loaded from
8681
Worker's dependenciess.
@@ -106,12 +101,7 @@ def use_worker_dependencies(cls):
106101
@classmethod
107102
@enable_feature_by(
108103
flag=PYTHON_ISOLATE_WORKER_DEPENDENCIES,
109-
flag_default=(
110-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT_310 if
111-
is_python_version('3.10') else
112-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT
113-
)
114-
)
104+
flag_default=PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT)
115105
def prioritize_customer_dependencies(cls, cx_working_dir=None):
116106
"""Switch the sys.path and ensure the customer's code import are loaded
117107
from CX's deppendencies.
@@ -180,11 +170,7 @@ def reload_customer_libraries(cls, cx_working_dir: str):
180170
"""
181171
use_new_env = os.getenv(PYTHON_ISOLATE_WORKER_DEPENDENCIES)
182172
if use_new_env is None:
183-
use_new = (
184-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT_310 if
185-
is_python_version('3.10') else
186-
PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT
187-
)
173+
use_new = PYTHON_ISOLATE_WORKER_DEPENDENCIES_DEFAULT
188174
else:
189175
use_new = is_true_like(use_new_env)
190176

tests/endtoend/dependency_isolation_functions/dependency_isolation_stein/function_app.py

Whitespace-only changes.

tests/unittests/test_rpc_messages.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import unittest
99

1010
from azure_functions_worker import protos, testutils
11-
from azure_functions_worker.utils.common import is_python_version
1211

1312

1413
class TestGRPC(testutils.AsyncTestCase):
@@ -127,13 +126,7 @@ def test_failed_azure_namespace_import(self):
127126

128127
@unittest.skipIf(sys.platform == 'win32',
129128
'Linux .sh script only works on Linux')
130-
@unittest.skipIf(
131-
is_python_version('3.10'),
132-
'In Python 3.10, isolate worker dependencies is turned on by default.'
133-
' Reloading all customer dependencies on specialization is a must.'
134-
' This partially reloading namespace feature is no longer needed.'
135-
)
136129
def test_successful_azure_namespace_import(self):
137130
self._verify_azure_namespace_import(
138131
'true',
139-
'module_b is imported')
132+
'module_b fails to import')

tests/unittests/test_utilities_dependency.py

Lines changed: 28 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
3+
import importlib.util
34
import os
45
import sys
5-
import importlib.util
66
import unittest
77
from unittest.mock import patch
88

99
from azure_functions_worker import testutils
10-
from azure_functions_worker.utils.common import is_python_version
1110
from azure_functions_worker.utils.dependency import DependencyManager
1211

1312

@@ -229,7 +228,7 @@ def test_add_to_sys_path_no_duplication(self):
229228

230229
def test_add_to_sys_path_import_module(self):
231230
DependencyManager._add_to_sys_path(self._customer_deps_path, True)
232-
import common_module # NoQA
231+
import common_module # NoQA
233232
self.assertEqual(
234233
common_module.package_location,
235234
os.path.join(self._customer_deps_path, 'common_module')
@@ -240,7 +239,7 @@ def test_add_to_sys_path_import_namespace_path(self):
240239
into sys.path
241240
"""
242241
DependencyManager._add_to_sys_path(self._customer_deps_path, True)
243-
import common_namespace # NoQA
242+
import common_namespace # NoQA
244243
self.assertEqual(len(common_namespace.__path__), 1)
245244
self.assertEqual(
246245
common_namespace.__path__[0],
@@ -517,7 +516,7 @@ def test_clear_path_importer_cache_and_modules_retain_namespace(self):
517516
sys.path.insert(0, self._worker_deps_path)
518517

519518
# Ensure new import is from _worker_deps_path
520-
import common_module as worker_mod # NoQA
519+
import common_module as worker_mod # NoQA
521520
self.assertIn('common_module', sys.modules)
522521
self.assertEqual(
523522
worker_mod.package_location,
@@ -555,39 +554,6 @@ def test_use_worker_dependencies_disable(self):
555554
with self.assertRaises(ImportError):
556555
import common_module # NoQA
557556

558-
@unittest.skipUnless(
559-
sys.version_info.major == 3 and sys.version_info.minor != 10,
560-
'Test only available for Python 3.6, 3.7, 3.8 or 3.9'
561-
)
562-
def test_use_worker_dependencies_default_python_36_37_38_39(self):
563-
# Feature should be disabled in Python 3.6, 3.7, 3.8 and 3.9
564-
# Setup paths
565-
DependencyManager.worker_deps_path = self._worker_deps_path
566-
DependencyManager.cx_deps_path = self._customer_deps_path
567-
DependencyManager.cx_working_dir = self._customer_func_path
568-
569-
# The common_module cannot be imported since feature is disabled
570-
DependencyManager.use_worker_dependencies()
571-
with self.assertRaises(ImportError):
572-
import common_module # NoQA
573-
574-
@unittest.skip('Skipping since PYTHON_ISOLATE_WORKER_DEPENDENCIES is '
575-
'disabled by default')
576-
def test_use_worker_dependencies_default_python_310(self):
577-
# Feature should be enabled in Python 3.10 by default
578-
# Setup paths
579-
DependencyManager.worker_deps_path = self._worker_deps_path
580-
DependencyManager.cx_deps_path = self._customer_deps_path
581-
DependencyManager.cx_working_dir = self._customer_func_path
582-
583-
# Ensure the common_module is imported from _worker_deps_path
584-
DependencyManager.use_worker_dependencies()
585-
import common_module # NoQA
586-
self.assertEqual(
587-
common_module.package_location,
588-
os.path.join(self._worker_deps_path, 'common_module')
589-
)
590-
591557
def test_prioritize_customer_dependencies(self):
592558
# Setup app settings
593559
os.environ['PYTHON_ISOLATE_WORKER_DEPENDENCIES'] = 'true'
@@ -626,52 +592,51 @@ def test_prioritize_customer_dependencies_disable(self):
626592
with self.assertRaises(ImportError):
627593
import common_module # NoQA
628594

629-
@unittest.skipIf(is_python_version('3.10'),
630-
'Test not available for python 3.10')
631-
def test_prioritize_customer_dependencies_default_python_36_37_38_39(self):
632-
# Feature should be disabled in Python 3.6, 3.7, 3.8 and 3.9
595+
def test_prioritize_customer_dependencies_from_working_directory(self):
596+
self._initialize_scenario()
597+
633598
# Setup paths
634599
DependencyManager.worker_deps_path = self._worker_deps_path
635600
DependencyManager.cx_deps_path = self._customer_deps_path
636601
DependencyManager.cx_working_dir = self._customer_func_path
637602

638-
# Ensure the common_module is imported from _customer_deps_path
603+
# Ensure the func_specific_module is imported from _customer_func_path
639604
DependencyManager.prioritize_customer_dependencies()
640-
with self.assertRaises(ImportError):
641-
import common_module # NoQA
605+
import func_specific_module # NoQA
606+
self.assertEqual(
607+
func_specific_module.package_location,
608+
os.path.join(self._customer_func_path, 'func_specific_module')
609+
)
642610

643-
@unittest.skip('Skipping since PYTHON_ISOLATE_WORKER_DEPENDENCIES is '
644-
'disabled by default')
645-
def test_prioritize_customer_dependencies_default_python_310(self):
646-
# Feature should be enabled in Python 3.10 by default
611+
def test_reload_customer_libraries_dependency_isolation_true(self):
612+
os.environ['PYTHON_ISOLATE_WORKER_DEPENDENCIES'] = 'true'
647613
# Setup paths
648614
DependencyManager.worker_deps_path = self._worker_deps_path
649615
DependencyManager.cx_deps_path = self._customer_deps_path
650616
DependencyManager.cx_working_dir = self._customer_func_path
651617

652-
# Ensure the common_module is imported from _customer_deps_path
653-
DependencyManager.prioritize_customer_dependencies()
618+
DependencyManager.reload_customer_libraries(self._customer_deps_path)
654619
import common_module # NoQA
655620
self.assertEqual(
656621
common_module.package_location,
657-
os.path.join(self._customer_deps_path, 'common_module')
658-
)
659-
660-
def test_prioritize_customer_dependencies_from_working_directory(self):
661-
self._initialize_scenario()
622+
os.path.join(self._customer_deps_path, 'common_module'))
662623

624+
def test_reload_customer_libraries_dependency_isolation_false(self):
625+
os.environ['PYTHON_ISOLATE_WORKER_DEPENDENCIES'] = 'false'
663626
# Setup paths
664627
DependencyManager.worker_deps_path = self._worker_deps_path
665628
DependencyManager.cx_deps_path = self._customer_deps_path
666629
DependencyManager.cx_working_dir = self._customer_func_path
667630

668-
# Ensure the func_specific_module is imported from _customer_func_path
669-
DependencyManager.prioritize_customer_dependencies()
670-
import func_specific_module # NoQA
671-
self.assertEqual(
672-
func_specific_module.package_location,
673-
os.path.join(self._customer_func_path, 'func_specific_module')
674-
)
631+
DependencyManager._add_to_sys_path(self._worker_deps_path, True)
632+
import azure.functions # NoQA
633+
634+
DependencyManager._add_to_sys_path(self._customer_deps_path, True)
635+
DependencyManager.reload_customer_libraries(self._customer_deps_path)
636+
# Checking if azure.functions gets reloaded
637+
self.assertIn(
638+
os.path.join(self._customer_deps_path, 'azure', 'functions'),
639+
sys.modules['azure.functions'].__path__)
675640

676641
def test_remove_module_cache(self):
677642
# First import the common_module and create a sys.modules cache

0 commit comments

Comments
 (0)