|  | 
| 2 | 2 | import sys | 
| 3 | 3 | from importlib.machinery import ModuleSpec | 
| 4 | 4 | from importlib.util import module_from_spec, spec_from_file_location | 
|  | 5 | +from pathlib import Path | 
| 5 | 6 | from types import ModuleType | 
| 6 | 7 | from typing import Any, Optional, Tuple | 
| 7 | 8 | 
 | 
| @@ -68,18 +69,28 @@ def load(self, name: Optional[str] = None) -> Tuple[ModuleType, str]: | 
| 68 | 69 |             name = self.config.tasks.collection_name | 
| 69 | 70 |         spec = self.find(name) | 
| 70 | 71 |         if spec and spec.loader and spec.origin: | 
| 71 |  | -            path = spec.origin | 
| 72 |  | -            # Ensure containing directory is on sys.path in case the module | 
| 73 |  | -            # being imported is trying to load local-to-it names. | 
| 74 |  | -            if os.path.isfile(spec.origin): | 
| 75 |  | -                path = os.path.dirname(spec.origin) | 
| 76 |  | -            if path not in sys.path: | 
| 77 |  | -                sys.path.insert(0, path) | 
|  | 72 | +            # Typically either tasks.py or tasks/__init__.py | 
|  | 73 | +            source_file = Path(spec.origin) | 
|  | 74 | +            # Will be 'the dir tasks.py is in', or 'tasks/', in both cases this | 
|  | 75 | +            # is what wants to be in sys.path for "from . import sibling" | 
|  | 76 | +            enclosing_dir = source_file.parent | 
|  | 77 | +            # Will be "the directory above the spot that 'import tasks' found", | 
|  | 78 | +            # namely the parent of "your task tree", i.e. "where project level | 
|  | 79 | +            # config files are looked for". So, same as enclosing_dir for | 
|  | 80 | +            # tasks.py, but one more level up for tasks/__init__.py... | 
|  | 81 | +            module_parent = enclosing_dir | 
|  | 82 | +            if spec.parent:  # it's a package, so we have to go up again | 
|  | 83 | +                module_parent = module_parent.parent | 
|  | 84 | +            # Get the enclosing dir on the path | 
|  | 85 | +            enclosing_str = str(enclosing_dir) | 
|  | 86 | +            if enclosing_str not in sys.path: | 
|  | 87 | +                sys.path.insert(0, enclosing_str) | 
| 78 | 88 |             # Actual import | 
| 79 | 89 |             module = module_from_spec(spec) | 
| 80 | 90 |             sys.modules[spec.name] = module  # so 'from . import xxx' works | 
| 81 | 91 |             spec.loader.exec_module(module) | 
| 82 |  | -            return module, os.path.dirname(spec.origin) | 
|  | 92 | +            # Return the module and the folder it was found in | 
|  | 93 | +            return module, str(module_parent) | 
| 83 | 94 |         msg = "ImportError loading {!r}, raising ImportError" | 
| 84 | 95 |         debug(msg.format(name)) | 
| 85 | 96 |         raise ImportError | 
|  | 
0 commit comments