# -*- coding: utf-8 -*- """ module_loader.py — Carregador dinâmico de módulos por ambiente (TESTE/Produção) Permite importar 'operacao', 'consulta', etc. a partir de um base_path escolhido no login. """ import os import importlib.util import types import streamlit as st SESSION_ENV_BASE_KEY = "__env_base_path__" SESSION_MOD_CACHE_KEY = "__env_module_cache__" def set_env_base(base_path: str): """Define o caminho base do ambiente (ex.: pasta de produção ou teste).""" base_path = os.path.abspath(base_path) if not os.path.isdir(base_path): raise RuntimeError(f"Caminho do ambiente inválido: {base_path}") st.session_state[SESSION_ENV_BASE_KEY] = base_path # Zera cache ao trocar ambiente st.session_state[SESSION_MOD_CACHE_KEY] = {} def get_env_base() -> str: base = st.session_state.get(SESSION_ENV_BASE_KEY) if not base: # Default: usar a própria pasta onde está o app (Produção) base = os.path.abspath(os.getcwd()) st.session_state[SESSION_ENV_BASE_KEY] = base st.session_state[SESSION_MOD_CACHE_KEY] = {} return base def _mod_cache() -> dict: cache = st.session_state.get(SESSION_MOD_CACHE_KEY) if cache is None: cache = {} st.session_state[SESSION_MOD_CACHE_KEY] = cache return cache def load_module(module_name: str) -> types.ModuleType: """ Carrega um módulo pelo nome (ex.: 'operacao') a partir do base_path atual. Mantém cache por ambiente/arquivo para evitar reimportações. """ base_path = get_env_base() mod_path = os.path.join(base_path, f"{module_name}.py") if not os.path.isfile(mod_path): # fallback: se não achar .py direto, permita subpastas (ex.: envs/test/modulos/operacao.py) # ajuste conforme sua estrutura real: mod_path_alt = os.path.join(base_path, "modulos", f"{module_name}.py") if os.path.isfile(mod_path_alt): mod_path = mod_path_alt else: raise FileNotFoundError(f"Módulo '{module_name}' não encontrado em {base_path}") cache_key = f"{base_path}::{module_name}" cache = _mod_cache() mod = cache.get(cache_key) if mod: return mod spec = importlib.util.spec_from_file_location(module_name, mod_path) mod = importlib.util.module_from_spec(spec) assert spec and spec.loader, f"Falha ao preparar spec para {mod_path}" spec.loader.exec_module(mod) cache[cache_key] = mod return mod