Coverage for adhoc-cicd-odoo-odoo / odoo / _monkeypatches / __init__.py: 94%
37 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-09 18:22 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-09 18:22 +0000
1"""Lazy module monkeypatcher
3Submodules should be named after the module (stdlib or third-party) they need
4to patch, and should define a `patch_module` function.
6This function will be called either immediately if the module to patch is
7already imported when the monkey patcher runs, or right after that module is
8imported otherwise.
9"""
11import importlib
12import os
13import pkgutil
14import sys
15import time
16from types import ModuleType, SimpleNamespace
19class PatchImportHook:
20 """Register hooks that are run on import."""
22 def __init__(self):
23 self.hooks = set()
25 def add_hook(self, fullname: str) -> None:
26 """Register a hook after a module is loaded.
27 If already loaded, run hook immediately."""
28 self.hooks.add(fullname)
29 if fullname in sys.modules:
30 patch_module(fullname)
32 def find_spec(self, fullname, path=None, target=None):
33 if fullname not in self.hooks:
34 return None # let python use another import hook to import this fullname
36 # skip all finders before this one
37 idx = sys.meta_path.index(self)
38 for finder in sys.meta_path[idx + 1:]: 38 ↛ 49line 38 didn't jump to line 49 because the loop on line 38 didn't complete
39 spec = finder.find_spec(fullname, path, target)
40 if spec is not None:
41 # we found a spec, change the loader
43 def exec_module(module: ModuleType, exec_module=spec.loader.exec_module) -> None:
44 exec_module(module)
45 patch_module(module.__name__)
47 spec.loader = SimpleNamespace(create_module=spec.loader.create_module, exec_module=exec_module)
48 return spec
49 raise ImportError(f"Could not load the module {fullname!r} to patch")
52HOOK_IMPORT = PatchImportHook()
53sys.meta_path.insert(0, HOOK_IMPORT)
56def patch_init() -> None:
57 os.environ['TZ'] = 'UTC' # Set the timezone
58 if hasattr(time, 'tzset'): 58 ↛ 61line 58 didn't jump to line 61 because the condition on line 58 was always true
59 time.tzset()
61 for submodule in pkgutil.iter_modules(__path__):
62 HOOK_IMPORT.add_hook(submodule.name)
65def patch_module(name: str) -> None:
66 module = importlib.import_module(f'.{name}', __name__)
67 module.patch_module()