|
11 | 11 | from dagster._core.errors import DagsterImportError, DagsterInvariantViolationError
|
12 | 12 | from dagster._serdes import whitelist_for_serdes
|
13 | 13 | from dagster._seven import get_import_error_message, import_module_from_path
|
14 |
| -from dagster._utils import hash_collection |
| 14 | +from dagster._utils import alter_sys_path, hash_collection |
15 | 15 |
|
16 | 16 |
|
17 | 17 | class CodePointer(ABC):
|
@@ -74,11 +74,14 @@ def load_python_file(python_file: str, working_directory: Optional[str]) -> Modu
|
74 | 74 |
|
75 | 75 | module_name = os.path.splitext(os.path.basename(python_file))[0]
|
76 | 76 |
|
77 |
| - if working_directory and working_directory not in sys.path: |
78 |
| - sys.path.insert(0, working_directory) |
79 |
| - |
| 77 | + # Use the passed in working directory for local imports (sys.path[0] isn't |
| 78 | + # consistently set in the different entry points that Dagster uses to import code) |
| 79 | + script_path = sys.path[0] |
80 | 80 | try:
|
81 |
| - return import_module_from_path(module_name, python_file) |
| 81 | + with alter_sys_path( |
| 82 | + to_add=([working_directory] if working_directory else []), to_remove=[script_path] |
| 83 | + ): |
| 84 | + return import_module_from_path(module_name, python_file) |
82 | 85 | except ImportError as ie:
|
83 | 86 | python_file = os.path.abspath(os.path.expanduser(python_file))
|
84 | 87 |
|
@@ -113,35 +116,43 @@ def load_python_file(python_file: str, working_directory: Optional[str]) -> Modu
|
113 | 116 | def load_python_module(
|
114 | 117 | module_name: str,
|
115 | 118 | working_directory: Optional[str],
|
| 119 | + remove_from_path_fn: Optional[Callable[[], Sequence[str]]] = None, |
116 | 120 | ) -> ModuleType:
|
117 | 121 | check.str_param(module_name, "module_name")
|
118 | 122 | check.opt_str_param(working_directory, "working_directory")
|
119 |
| - |
120 |
| - if working_directory and working_directory not in sys.path: |
121 |
| - sys.path.insert(0, working_directory) |
122 |
| - |
123 |
| - try: |
124 |
| - return importlib.import_module(module_name) |
125 |
| - except ImportError as ie: |
126 |
| - msg = get_import_error_message(ie) |
127 |
| - if working_directory: |
128 |
| - abs_working_directory = os.path.abspath(os.path.expanduser(working_directory)) |
129 |
| - raise DagsterImportError( |
130 |
| - f"Encountered ImportError: `{msg}` while importing module {module_name}. " |
131 |
| - "Local modules were resolved using the working " |
132 |
| - f"directory `{abs_working_directory}`. If another working directory should be " |
133 |
| - "used, please explicitly specify the appropriate path using the `-d` or " |
134 |
| - "`--working-directory` for CLI based targets or the `working_directory` " |
135 |
| - "configuration option for workspace targets. " |
136 |
| - ) from ie |
137 |
| - else: |
138 |
| - raise DagsterImportError( |
139 |
| - f"Encountered ImportError: `{msg}` while importing module {module_name}. " |
140 |
| - "If relying on the working directory to resolve modules, please " |
141 |
| - "explicitly specify the appropriate path using the `-d` or " |
142 |
| - "`--working-directory` for CLI based targets or the `working_directory` " |
143 |
| - "configuration option for workspace targets. " |
144 |
| - ) from ie |
| 123 | + check.opt_callable_param(remove_from_path_fn, "remove_from_path_fn") |
| 124 | + |
| 125 | + # Use the passed in working directory for local imports (sys.path[0] isn't |
| 126 | + # consistently set in the different entry points that Dagster uses to import code) |
| 127 | + remove_paths: list[str] = ( |
| 128 | + list(remove_from_path_fn()) if remove_from_path_fn else [] |
| 129 | + ) # hook for tests |
| 130 | + remove_paths.insert(0, sys.path[0]) # remove the script path |
| 131 | + with alter_sys_path( |
| 132 | + to_add=([working_directory] if working_directory else []), to_remove=remove_paths |
| 133 | + ): |
| 134 | + try: |
| 135 | + return importlib.import_module(module_name) |
| 136 | + except ImportError as ie: |
| 137 | + msg = get_import_error_message(ie) |
| 138 | + if working_directory: |
| 139 | + abs_working_directory = os.path.abspath(os.path.expanduser(working_directory)) |
| 140 | + raise DagsterImportError( |
| 141 | + f"Encountered ImportError: `{msg}` while importing module {module_name}. " |
| 142 | + "Local modules were resolved using the working " |
| 143 | + f"directory `{abs_working_directory}`. If another working directory should be " |
| 144 | + "used, please explicitly specify the appropriate path using the `-d` or " |
| 145 | + "`--working-directory` for CLI based targets or the `working_directory` " |
| 146 | + "configuration option for workspace targets. " |
| 147 | + ) from ie |
| 148 | + else: |
| 149 | + raise DagsterImportError( |
| 150 | + f"Encountered ImportError: `{msg}` while importing module {module_name}. " |
| 151 | + "If relying on the working directory to resolve modules, please " |
| 152 | + "explicitly specify the appropriate path using the `-d` or " |
| 153 | + "`--working-directory` for CLI based targets or the `working_directory` " |
| 154 | + "configuration option for workspace targets. " |
| 155 | + ) from ie |
145 | 156 |
|
146 | 157 |
|
147 | 158 | @whitelist_for_serdes
|
|
0 commit comments