|
1 | 1 | # This file is part of the QuestionPy Server. (https://questionpy.org)
|
2 | 2 | # The QuestionPy Server is free software released under terms of the MIT license. See LICENSE.md.
|
3 | 3 | # (c) Technische Universität Berlin, innoCampus <[email protected]>
|
| 4 | +import importlib |
4 | 5 | import inspect
|
5 | 6 | import json
|
6 | 7 | import sys
|
7 | 8 | import zipfile
|
8 | 9 | from abc import ABC, abstractmethod
|
9 | 10 | from functools import cached_property
|
10 |
| -from importlib import import_module, resources |
11 | 11 | from importlib.resources.abc import Traversable
|
12 | 12 | from pathlib import Path
|
13 | 13 | from types import ModuleType
|
@@ -38,20 +38,23 @@ class ImportablePackage(ABC, Package):
|
38 | 38 | def setup_imports(self) -> None:
|
39 | 39 | """Modifies ``sys.path`` to include the package's python code."""
|
40 | 40 |
|
41 |
| - def init_as_main(self, env: Environment) -> BaseQuestionType: |
| 41 | + def init_as_main(self, env: Environment, *, reload: bool = False) -> BaseQuestionType: |
42 | 42 | """Imports the package's entrypoint and executes its ``init`` function.
|
43 | 43 |
|
44 | 44 | :meth:`setup_imports` should be called beforehand to allow the import.
|
45 | 45 | """
|
46 | 46 | set_qpy_environment(env)
|
47 | 47 |
|
48 |
| - main_module: ModuleType |
49 |
| - if self.manifest.entrypoint: |
50 |
| - main_module = import_module( |
51 |
| - f"{self.manifest.namespace}.{self.manifest.short_name}.{self.manifest.entrypoint}" |
52 |
| - ) |
53 |
| - else: |
54 |
| - main_module = import_module(f"{self.manifest.namespace}.{self.manifest.short_name}") |
| 48 | + module_name = f"{self.manifest.namespace}.{self.manifest.short_name}" |
| 49 | + main_module_name = f"{module_name}.{self.manifest.entrypoint}" if self.manifest.entrypoint else module_name |
| 50 | + |
| 51 | + main_module = importlib.import_module(main_module_name) |
| 52 | + |
| 53 | + if reload: |
| 54 | + for name, module in sys.modules.copy().items(): |
| 55 | + if name.startswith(module_name) and name != main_module_name: |
| 56 | + importlib.reload(module) |
| 57 | + main_module = importlib.reload(main_module) |
55 | 58 |
|
56 | 59 | if not hasattr(main_module, "init") or not callable(main_module.init):
|
57 | 60 | raise NoInitFunctionError(main_module)
|
@@ -141,16 +144,16 @@ def manifest(self) -> Manifest:
|
141 | 144 | return self._manifest
|
142 | 145 |
|
143 | 146 | def get_path(self, path: str) -> Traversable:
|
144 |
| - return resources.files(self.module_name).joinpath(path) |
| 147 | + return importlib.resources.files(self.module_name).joinpath(path) |
145 | 148 |
|
146 | 149 | def setup_imports(self) -> None:
|
147 | 150 | # Nothing to do.
|
148 | 151 | pass
|
149 | 152 |
|
150 |
| - def init_as_main(self, env: Environment) -> BaseQuestionType: |
| 153 | + def init_as_main(self, env: Environment, *, reload: bool = False) -> BaseQuestionType: |
151 | 154 | set_qpy_environment(env)
|
152 | 155 |
|
153 |
| - main_module = import_module(self.module_name) |
| 156 | + main_module = importlib.import_module(self.module_name) |
154 | 157 | init_function = getattr(main_module, self.function_name, None)
|
155 | 158 | if not init_function or not callable(init_function):
|
156 | 159 | raise NoInitFunctionError(main_module)
|
|
0 commit comments