API loader shares one module object per file (issue #132, BUG-1482)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate (push) Canceled after 8m49s

_load_local_module always re-executed the file as _jyotish_local_<name>, so
engine, dasha, varga and others ran as extra copies with their own caches.
It now reuses scripts.<name> / <name> when that file is already imported,
else imports it under its plain name so later imports share it; the private
copy remains only as a fallback. Call sites unchanged. Probe after one
consultation and one chart: loader-made copies 19 -> 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jesse_Chen
2026-10-28 12:43:59 +08:00
co-authored by Claude Opus 5.5
parent 0594afcd5c
commit 8a72aa5b44
4 changed files with 73 additions and 0 deletions
+14
View File
@@ -2536,6 +2536,20 @@ def _load_local_module(module_name):
return cached
relative = module_name.replace('.', os.sep)
module_path = os.path.join(SCRIPTS_DIR, f'{relative}.py')
# issue #132: one copy per file. Reuse what `import scripts.X` / `import X`
# already loaded, else import it under its plain name so later imports
# share it; a private `_jyotish_local_X` copy kept its own caches.
for loaded_name in (f'scripts.{module_name}', module_name):
loaded = sys.modules.get(loaded_name)
loaded_file = getattr(loaded, '__file__', None)
if loaded_file and os.path.realpath(loaded_file) == os.path.realpath(module_path):
_LOCAL_MODULE_CACHE[module_name] = loaded
return loaded
if os.path.isfile(module_path) and SCRIPTS_DIR in sys.path:
module = importlib.import_module(module_name)
if os.path.realpath(getattr(module, '__file__', '') or '') == os.path.realpath(module_path):
_LOCAL_MODULE_CACHE[module_name] = module
return module
spec = importlib.util.spec_from_file_location(f'_jyotish_local_{module_name}', module_path)
if not spec or not spec.loader:
raise ImportError(f'Cannot load local module: {module_name}')