diff --git a/pysus/online_data/CIHA.py b/pysus/online_data/CIHA.py index 9be4ecc..a8de94d 100644 --- a/pysus/online_data/CIHA.py +++ b/pysus/online_data/CIHA.py @@ -12,8 +12,9 @@ from pysus.ftp import CACHEPATH from pysus.ftp.databases.ciha import CIHA from pysus.ftp.utils import parse_UFs +from pysus.online_data._lazy import _LazyDatabase -ciha = CIHA().load() +ciha = _LazyDatabase(CIHA) def get_available_years( diff --git a/pysus/online_data/CNES.py b/pysus/online_data/CNES.py index a3b1188..85546f8 100644 --- a/pysus/online_data/CNES.py +++ b/pysus/online_data/CNES.py @@ -4,8 +4,9 @@ from pysus.ftp import CACHEPATH from pysus.ftp.databases.cnes import CNES from pysus.ftp.utils import parse_UFs +from pysus.online_data._lazy import _LazyDatabase -cnes = CNES().load() +cnes = _LazyDatabase(CNES) group_dict = { diff --git a/pysus/online_data/IBGE.py b/pysus/online_data/IBGE.py index 33fba90..9ebe81f 100644 --- a/pysus/online_data/IBGE.py +++ b/pysus/online_data/IBGE.py @@ -14,13 +14,14 @@ import urllib3 from pysus.data.local import ParquetSet from pysus.ftp.databases.ibge_datasus import IBGEDATASUS +from pysus.online_data._lazy import _LazyDatabase # requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL:@SECLEVEL=1' APIBASE = "https://servicodados.ibge.gov.br/api/v3/" -ibge = IBGEDATASUS().load() +ibge = _LazyDatabase(IBGEDATASUS) def get_sidra_table( diff --git a/pysus/online_data/PNI.py b/pysus/online_data/PNI.py index 2df41c1..a4fa13f 100644 --- a/pysus/online_data/PNI.py +++ b/pysus/online_data/PNI.py @@ -7,8 +7,9 @@ from pysus.ftp import CACHEPATH from pysus.ftp.databases.pni import PNI from pysus.ftp.utils import parse_UFs +from pysus.online_data._lazy import _LazyDatabase -pni = PNI().load() +pni = _LazyDatabase(PNI) def get_available_years(group, states): diff --git a/pysus/online_data/SIA.py b/pysus/online_data/SIA.py index 19ff22a..6825f6f 100644 --- a/pysus/online_data/SIA.py +++ b/pysus/online_data/SIA.py @@ -13,8 +13,9 @@ from pysus.ftp import CACHEPATH from pysus.ftp.databases.sia import SIA from pysus.ftp.utils import parse_UFs +from pysus.online_data._lazy import _LazyDatabase -sia = SIA().load() +sia = _LazyDatabase(SIA) group_dict: Dict[str, Tuple[str, int, int]] = { diff --git a/pysus/online_data/SIH.py b/pysus/online_data/SIH.py index 67749f5..e9afffa 100644 --- a/pysus/online_data/SIH.py +++ b/pysus/online_data/SIH.py @@ -10,8 +10,9 @@ from pysus.ftp import CACHEPATH from pysus.ftp.databases.sih import SIH from pysus.ftp.utils import parse_UFs +from pysus.online_data._lazy import _LazyDatabase -sih = SIH().load() +sih = _LazyDatabase(SIH) def get_available_years( diff --git a/pysus/online_data/SIM.py b/pysus/online_data/SIM.py index c021111..f5d565e 100644 --- a/pysus/online_data/SIM.py +++ b/pysus/online_data/SIM.py @@ -14,8 +14,9 @@ from pysus.ftp import CACHEPATH from pysus.ftp.databases.sim import SIM from pysus.ftp.utils import parse_UFs +from pysus.online_data._lazy import _LazyDatabase -sim = SIM().load() +sim = _LazyDatabase(SIM) def get_available_years( diff --git a/pysus/online_data/SINAN.py b/pysus/online_data/SINAN.py index fe5692d..5a7c0b1 100644 --- a/pysus/online_data/SINAN.py +++ b/pysus/online_data/SINAN.py @@ -4,8 +4,9 @@ import pandas as pd from pysus.ftp import CACHEPATH from pysus.ftp.databases.sinan import SINAN +from pysus.online_data._lazy import _LazyDatabase -sinan = SINAN().load() +sinan = _LazyDatabase(SINAN) def list_diseases() -> dict: diff --git a/pysus/online_data/SINASC.py b/pysus/online_data/SINASC.py index 2469d88..66f535c 100644 --- a/pysus/online_data/SINASC.py +++ b/pysus/online_data/SINASC.py @@ -10,8 +10,9 @@ from pysus.ftp import CACHEPATH from pysus.ftp.databases.sinasc import SINASC from pysus.ftp.utils import parse_UFs +from pysus.online_data._lazy import _LazyDatabase -sinasc = SINASC().load() +sinasc = _LazyDatabase(SINASC) def get_available_years(group: str, states: Union[str, list[str]]) -> list: diff --git a/pysus/online_data/_lazy.py b/pysus/online_data/_lazy.py new file mode 100644 index 0000000..970d442 --- /dev/null +++ b/pysus/online_data/_lazy.py @@ -0,0 +1,44 @@ +""" +Lazy database wrapper to defer FTP connections until first use. + +This avoids connecting to the FTP server on import, which can cause +hangs and failures when the server is unavailable. +""" + +from loguru import logger + + +class _LazyDatabase: + """Base lazy wrapper that defers FTP connection until the database is + actually accessed. All attribute access is transparently proxied to + the underlying database instance. + + Subclasses only need to override ``_ensure_loaded`` if custom + initialisation logic is required; the default implementation calls + ``db_class().load()`` with error handling for FTP failures. + """ + + def __init__(self, db_class): + # Use object.__setattr__ to avoid triggering __getattr__ + object.__setattr__(self, "_db_class", db_class) + object.__setattr__(self, "_instance", None) + + def _ensure_loaded(self): + if self._instance is None: + try: + instance = self._db_class().load() + except Exception as exc: + logger.error( + "Failed to connect to FTP server for " + f"{self._db_class.__name__}: {exc}" + ) + raise ConnectionError( + f"Could not load {self._db_class.__name__} database. " + "The FTP server may be unavailable. " + f"Original error: {exc}" + ) from exc + object.__setattr__(self, "_instance", instance) + return self._instance + + def __getattr__(self, name): + return getattr(self._ensure_loaded(), name)