sibi-dst 0.3.55__tar.gz → 0.3.56__tar.gz

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.
Files changed (80) hide show
  1. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/PKG-INFO +1 -1
  2. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/pyproject.toml +1 -1
  3. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/_artifact_updater_multi_wrapper.py +1 -1
  4. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/sqlalchemy/_db_connection.py +41 -6
  5. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/data_wrapper.py +1 -1
  6. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/README.md +0 -0
  7. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/__init__.py +0 -0
  8. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/__init__.py +0 -0
  9. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/_df_helper.py +0 -0
  10. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/_parquet_artifact.py +0 -0
  11. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/_parquet_reader.py +0 -0
  12. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/__init__.py +0 -0
  13. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/django/__init__.py +0 -0
  14. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/django/_db_connection.py +0 -0
  15. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/django/_io_dask.py +0 -0
  16. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/django/_load_from_db.py +0 -0
  17. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/django/_sql_model_builder.py +0 -0
  18. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/http/__init__.py +0 -0
  19. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/http/_http_config.py +0 -0
  20. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/parquet/__init__.py +0 -0
  21. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/parquet/_filter_handler.py +0 -0
  22. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/parquet/_parquet_options.py +0 -0
  23. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/sqlalchemy/__init__.py +0 -0
  24. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/sqlalchemy/_filter_handler.py +0 -0
  25. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/sqlalchemy/_io_dask.py +0 -0
  26. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/sqlalchemy/_load_from_db.py +0 -0
  27. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/backends/sqlalchemy/_sql_model_builder.py +0 -0
  28. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/core/__init__.py +0 -0
  29. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/core/_defaults.py +0 -0
  30. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/core/_filter_handler.py +0 -0
  31. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/core/_params_config.py +0 -0
  32. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/core/_query_config.py +0 -0
  33. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/df_helper/data_cleaner.py +0 -0
  34. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/geopy_helper/__init__.py +0 -0
  35. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/geopy_helper/geo_location_service.py +0 -0
  36. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/geopy_helper/utils.py +0 -0
  37. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/osmnx_helper/__init__.py +0 -0
  38. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/osmnx_helper/base_osm_map.py +0 -0
  39. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/osmnx_helper/basemaps/__init__.py +0 -0
  40. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/osmnx_helper/basemaps/calendar_html.py +0 -0
  41. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/osmnx_helper/basemaps/router_plotter.py +0 -0
  42. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/osmnx_helper/utils.py +0 -0
  43. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/tests/__init__.py +0 -0
  44. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/tests/test_data_wrapper_class.py +0 -0
  45. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/__init__.py +0 -0
  46. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/airflow_manager.py +0 -0
  47. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/clickhouse_writer.py +0 -0
  48. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/credentials.py +0 -0
  49. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/data_from_http_source.py +0 -0
  50. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/data_utils.py +0 -0
  51. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/date_utils.py +0 -0
  52. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/df_utils.py +0 -0
  53. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/file_utils.py +0 -0
  54. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/filepath_generator.py +0 -0
  55. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/log_utils.py +0 -0
  56. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/parquet_saver.py +0 -0
  57. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/phone_formatter.py +0 -0
  58. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/storage_config.py +0 -0
  59. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/storage_manager.py +0 -0
  60. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/utils/webdav_client.py +0 -0
  61. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/__init__.py +0 -0
  62. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/__init__.py +0 -0
  63. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/_df_helper.py +0 -0
  64. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/__init__.py +0 -0
  65. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlalchemy/__init__.py +0 -0
  66. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlalchemy/_db_connection.py +0 -0
  67. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlalchemy/_io_dask.py +0 -0
  68. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlalchemy/_load_from_db.py +0 -0
  69. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlalchemy/_model_builder.py +0 -0
  70. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlmodel/__init__.py +0 -0
  71. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlmodel/_db_connection.py +0 -0
  72. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlmodel/_io_dask.py +0 -0
  73. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlmodel/_load_from_db.py +0 -0
  74. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/backends/sqlmodel/_model_builder.py +0 -0
  75. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/core/__init__.py +0 -0
  76. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/core/_filter_handler.py +0 -0
  77. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/core/_params_config.py +0 -0
  78. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/df_helper/core/_query_config.py +0 -0
  79. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/utils/__init__.py +0 -0
  80. {sibi_dst-0.3.55 → sibi_dst-0.3.56}/sibi_dst/v2/utils/log_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sibi-dst
3
- Version: 0.3.55
3
+ Version: 0.3.56
4
4
  Summary: Data Science Toolkit
5
5
  Author: Luis Valverde
6
6
  Author-email: lvalverdeb@gmail.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "sibi-dst"
3
- version = "0.3.55"
3
+ version = "0.3.56"
4
4
  description = "Data Science Toolkit"
5
5
  authors = ["Luis Valverde <lvalverdeb@gmail.com>"]
6
6
  readme = "README.md"
@@ -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 2GB per worker
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,26 +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
36
- pool_recycle:int = 3600
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()
37
43
 
38
44
  @model_validator(mode="after")
39
45
  def validate_and_initialize(self):
40
46
  """
41
47
  Validate connection parameters, initialize the engine, and build the dynamic model if necessary.
42
48
  """
43
- # Validate `connection_url`
49
+ if not self.logger:
50
+ self.logger = Logger.default_logger(logger_name=self.__class__.__name__)
51
+
44
52
  if not self.connection_url:
45
53
  raise ValueError("`connection_url` must be provided.")
46
54
 
47
- # Initialize the engine
48
- self.engine = create_engine(self.connection_url,
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,
49
78
  pool_size=self.pool_size,
50
79
  max_overflow=self.max_overflow,
51
80
  pool_timeout=self.pool_timeout,
52
81
  pool_recycle=self.pool_recycle)
82
+ self.__class__._engine_registry[engine_key] = self.engine
53
83
 
54
84
  # Validate the connection
55
85
  self.validate_connection()
@@ -72,3 +102,8 @@ class SqlAlchemyConnectionConfig(BaseModel):
72
102
  except OperationalError as e:
73
103
  raise ValueError(f"Failed to connect to the database: {e}")
74
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()
@@ -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 = 3):
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)
File without changes