sibi-dst 0.3.54__py3-none-any.whl → 0.3.56__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sibi_dst/df_helper/_artifact_updater_multi_wrapper.py +1 -1
- sibi_dst/df_helper/backends/sqlalchemy/_db_connection.py +43 -6
- sibi_dst/utils/data_wrapper.py +1 -1
- {sibi_dst-0.3.54.dist-info → sibi_dst-0.3.56.dist-info}/METADATA +1 -8
- {sibi_dst-0.3.54.dist-info → sibi_dst-0.3.56.dist-info}/RECORD +6 -6
- {sibi_dst-0.3.54.dist-info → sibi_dst-0.3.56.dist-info}/WHEEL +0 -0
@@ -45,7 +45,7 @@ class ArtifactUpdaterMultiWrapper:
|
|
45
45
|
# dynamic scaling config
|
46
46
|
self.min_workers = kwargs.get('min_workers', 1)
|
47
47
|
self.max_workers = kwargs.get('max_workers', 8)
|
48
|
-
self.memory_per_worker_gb = kwargs.get('memory_per_worker_gb', 1) # default
|
48
|
+
self.memory_per_worker_gb = kwargs.get('memory_per_worker_gb', 1) # default 1GB per worker
|
49
49
|
self.monitor_interval = kwargs.get('monitor_interval', 10) # default monitor interval in seconds
|
50
50
|
self.retry_attempts = kwargs.get('retry_attempts', 3)
|
51
51
|
self.update_timeout_seconds = kwargs.get('update_timeout_seconds', 600)
|
@@ -1,13 +1,14 @@
|
|
1
|
-
from typing import Any, Optional
|
1
|
+
from typing import Any, Optional, ClassVar
|
2
|
+
import threading
|
2
3
|
|
3
4
|
from pydantic import BaseModel, model_validator
|
4
5
|
from sqlalchemy import create_engine
|
5
6
|
from sqlalchemy.exc import OperationalError
|
6
7
|
from sqlalchemy.sql import text
|
8
|
+
from sibi_dst.utils import Logger
|
7
9
|
|
8
10
|
from ._sql_model_builder import SqlAlchemyModelBuilder
|
9
11
|
|
10
|
-
|
11
12
|
class SqlAlchemyConnectionConfig(BaseModel):
|
12
13
|
"""
|
13
14
|
Configuration class for managing an SQLAlchemy database connection.
|
@@ -30,24 +31,55 @@ class SqlAlchemyConnectionConfig(BaseModel):
|
|
30
31
|
table: Optional[str] = None
|
31
32
|
model: Any = None
|
32
33
|
engine: Optional[Any] = None
|
34
|
+
logger: Optional[Any] = None
|
33
35
|
pool_size: int = 10
|
34
36
|
max_overflow: int = 5
|
35
37
|
pool_timeout: int = 30
|
38
|
+
pool_recycle:int = 300
|
39
|
+
|
40
|
+
# Class-level registry and lock for thread-safe engine reuse
|
41
|
+
_engine_registry: ClassVar[dict] = {}
|
42
|
+
_registry_lock: ClassVar[threading.Lock] = threading.Lock()
|
36
43
|
|
37
44
|
@model_validator(mode="after")
|
38
45
|
def validate_and_initialize(self):
|
39
46
|
"""
|
40
47
|
Validate connection parameters, initialize the engine, and build the dynamic model if necessary.
|
41
48
|
"""
|
42
|
-
|
49
|
+
if not self.logger:
|
50
|
+
self.logger = Logger.default_logger(logger_name=self.__class__.__name__)
|
51
|
+
|
43
52
|
if not self.connection_url:
|
44
53
|
raise ValueError("`connection_url` must be provided.")
|
45
54
|
|
46
|
-
#
|
47
|
-
self.engine
|
55
|
+
# Validate `connection_url`
|
56
|
+
if self.engine is not None:
|
57
|
+
engine_url = str(self.engine.url)
|
58
|
+
if engine_url != self.connection_url:
|
59
|
+
raise ValueError(f"Engine URL '{engine_url}' does not match the provided connection URL '{self.connection_url}'.")
|
60
|
+
else:
|
61
|
+
# Generate a unique key for the engine registry based on the connection URL
|
62
|
+
engine_key = (
|
63
|
+
self.connection_url,
|
64
|
+
self.pool_size,
|
65
|
+
self.max_overflow,
|
66
|
+
self.pool_timeout,
|
67
|
+
self.pool_recycle
|
68
|
+
)
|
69
|
+
with self.__class__._registry_lock:
|
70
|
+
if engine_key in self.__class__._engine_registry:
|
71
|
+
# Reuse the existing engine
|
72
|
+
self.logger.info(f"Reusing existing engine for connection URL: {self.connection_url}")
|
73
|
+
self.engine = self.__class__._engine_registry[engine_key]
|
74
|
+
else:
|
75
|
+
# Initialize the engine
|
76
|
+
self.logger.info(f"Creating new engine for connection URL: {self.connection_url}")
|
77
|
+
self.engine = create_engine(self.connection_url,
|
48
78
|
pool_size=self.pool_size,
|
49
79
|
max_overflow=self.max_overflow,
|
50
|
-
pool_timeout=self.pool_timeout
|
80
|
+
pool_timeout=self.pool_timeout,
|
81
|
+
pool_recycle=self.pool_recycle)
|
82
|
+
self.__class__._engine_registry[engine_key] = self.engine
|
51
83
|
|
52
84
|
# Validate the connection
|
53
85
|
self.validate_connection()
|
@@ -70,3 +102,8 @@ class SqlAlchemyConnectionConfig(BaseModel):
|
|
70
102
|
except OperationalError as e:
|
71
103
|
raise ValueError(f"Failed to connect to the database: {e}")
|
72
104
|
|
105
|
+
@classmethod
|
106
|
+
def clear_engine_registry(cls):
|
107
|
+
"""Clear the global engine registry (useful for testing)."""
|
108
|
+
with cls._registry_lock:
|
109
|
+
cls._engine_registry.clear()
|
sibi_dst/utils/data_wrapper.py
CHANGED
@@ -48,7 +48,7 @@ class DataWrapper:
|
|
48
48
|
timeout: float = 60,
|
49
49
|
reference_date: datetime.date = None,
|
50
50
|
custom_priority_map: Dict[str, int] = None,
|
51
|
-
max_threads: int =
|
51
|
+
max_threads: int = 10):
|
52
52
|
self.dataclass = dataclass
|
53
53
|
self.date_field = date_field
|
54
54
|
self.data_path = self._ensure_forward_slash(data_path)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: sibi-dst
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.56
|
4
4
|
Summary: Data Science Toolkit
|
5
5
|
Author: Luis Valverde
|
6
6
|
Author-email: lvalverdeb@gmail.com
|
@@ -51,13 +51,6 @@ Requires-Dist: uvicorn-worker (>=0.3.0,<0.4.0)
|
|
51
51
|
Requires-Dist: webdav4[fsspec] (>=0.10.0,<0.11.0)
|
52
52
|
Description-Content-Type: text/markdown
|
53
53
|
|
54
|
-
---
|
55
|
-
title: "Sibi Data Science Toolkit"
|
56
|
-
description: "Data Science Toolkit built with Python, Pandas, Dask, GeoPandas, OpenStreetMaps, SQLAlchemy"
|
57
|
-
author: "Luis Valverde"
|
58
|
-
current_mantainer: "Luis Valverde"
|
59
|
-
---
|
60
|
-
|
61
54
|
### SIBI-DST
|
62
55
|
|
63
56
|
Data Science Toolkit built with Python, Pandas, Dask, OpenStreetMaps, NetworkX, SQLAlchemy, GeoPandas, and Folium.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
sibi_dst/__init__.py,sha256=3pbriM7Ym5f9gew7n9cO4G_p9n-0bnxdmQ0hwBdJjr4,253
|
2
2
|
sibi_dst/df_helper/__init__.py,sha256=McYrw2N0MsMgtawLrONXTGdyHfQWVOBUvIDbklfjb54,342
|
3
|
-
sibi_dst/df_helper/_artifact_updater_multi_wrapper.py,sha256=
|
3
|
+
sibi_dst/df_helper/_artifact_updater_multi_wrapper.py,sha256=zkgF4kiP9AuGTipFpx4jE7Ys6j5KXkdFBOshScN46yM,11646
|
4
4
|
sibi_dst/df_helper/_df_helper.py,sha256=D85n4oUdu92IN2QaPc6k9uJJ_Vm197me1aoHojuWEYs,29833
|
5
5
|
sibi_dst/df_helper/_parquet_artifact.py,sha256=dDoR5Tq0EJViW52tD9XW_vno7hkOfA8WeAilR1mAb_g,10636
|
6
6
|
sibi_dst/df_helper/_parquet_reader.py,sha256=L6mr2FeKtTeIn37G9EGpvOx8PwMqXb6qnEECqBaiwxo,3954
|
@@ -16,7 +16,7 @@ sibi_dst/df_helper/backends/parquet/__init__.py,sha256=esWJ9aSuYC26d-T01z9dPrJ1u
|
|
16
16
|
sibi_dst/df_helper/backends/parquet/_filter_handler.py,sha256=TvDf0RXta7mwJv11GNQttYJsXgFf2XDj4oLIjt4xTzA,5219
|
17
17
|
sibi_dst/df_helper/backends/parquet/_parquet_options.py,sha256=TaU5_wG1Y3lQC8DVCItVvMnc6ZJmECLu3avssVEMbaM,10591
|
18
18
|
sibi_dst/df_helper/backends/sqlalchemy/__init__.py,sha256=TuVp8Ce49dCIIxtyrtFGRblarQUl8QGcS-TDZd515IE,348
|
19
|
-
sibi_dst/df_helper/backends/sqlalchemy/_db_connection.py,sha256=
|
19
|
+
sibi_dst/df_helper/backends/sqlalchemy/_db_connection.py,sha256=GJK_8JQJQTXL3tv2sqNq6en0iKg20_Ocl7dDDSfsqAw,4572
|
20
20
|
sibi_dst/df_helper/backends/sqlalchemy/_filter_handler.py,sha256=58RCda1Hg_nsuJw-2V36IstsT8O84IQFgsdE7FnqvMk,4655
|
21
21
|
sibi_dst/df_helper/backends/sqlalchemy/_io_dask.py,sha256=BtiRSYA4kFIM-mBCdrwE20vzByfq8_Biv_jPLUCDv58,5466
|
22
22
|
sibi_dst/df_helper/backends/sqlalchemy/_load_from_db.py,sha256=I2Us3RrxHci561yyZYBuUCrLVOhB0F3KBnae78m_ARw,6259
|
@@ -44,7 +44,7 @@ sibi_dst/utils/clickhouse_writer.py,sha256=iAUe4_Kn2WR1xZjpLW2FOWCWfOTw6fCGMTUcW
|
|
44
44
|
sibi_dst/utils/credentials.py,sha256=cHJPPsmVyijqbUQIq7WWPe-lIallA-mI5RAy3YUuRME,1724
|
45
45
|
sibi_dst/utils/data_from_http_source.py,sha256=AcpKNsqTgN2ClNwuhgUpuNCx62r5_DdsAiKY8vcHEBA,1867
|
46
46
|
sibi_dst/utils/data_utils.py,sha256=MqbwXk33BuANWeKKmsabHouhb8GZswSmbM-VetWWE-M,10357
|
47
|
-
sibi_dst/utils/data_wrapper.py,sha256
|
47
|
+
sibi_dst/utils/data_wrapper.py,sha256=UJSFoy4qQP1bu9vze9QSBTeiVd5aIC8heWztA3zTBWk,12447
|
48
48
|
sibi_dst/utils/date_utils.py,sha256=OCJqkWl5e8fE7z11Ufz4206DUeuLMd_Gf_JGZu914Pg,18539
|
49
49
|
sibi_dst/utils/df_utils.py,sha256=TzIAUCLbgOn3bvCFvzkc1S9YU-OlZTImdCj-88dtg8g,11401
|
50
50
|
sibi_dst/utils/file_utils.py,sha256=Z99CZ_4nPDIaZqbCfzzUDfAYJjSudWDj-mwEO8grhbc,1253
|
@@ -75,6 +75,6 @@ sibi_dst/v2/df_helper/core/_params_config.py,sha256=DYx2drDz3uF-lSPzizPkchhy-kxR
|
|
75
75
|
sibi_dst/v2/df_helper/core/_query_config.py,sha256=Y8LVSyaKuVkrPluRDkQoOwuXHQxner1pFWG3HPfnDHM,441
|
76
76
|
sibi_dst/v2/utils/__init__.py,sha256=6H4cvhqTiFufnFPETBF0f8beVVMpfJfvUs6Ne0TQZNY,58
|
77
77
|
sibi_dst/v2/utils/log_utils.py,sha256=rfk5VsLAt-FKpv6aPTC1FToIPiyrnHAFFBAkHme24po,4123
|
78
|
-
sibi_dst-0.3.
|
79
|
-
sibi_dst-0.3.
|
80
|
-
sibi_dst-0.3.
|
78
|
+
sibi_dst-0.3.56.dist-info/METADATA,sha256=4glUnenNOPnp57g6ztPBMp0TgLIngYnVqMhX55HzVkg,4292
|
79
|
+
sibi_dst-0.3.56.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
80
|
+
sibi_dst-0.3.56.dist-info/RECORD,,
|
File without changes
|