pydpm_xl 0.2.6__tar.gz → 0.2.8__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 (99) hide show
  1. {pydpm_xl-0.2.6/pydpm_xl.egg-info → pydpm_xl-0.2.8}/PKG-INFO +1 -1
  2. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/__init__.py +1 -1
  3. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm/data_dictionary.py +11 -2
  4. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm_xl/ast_generator.py +8 -1
  5. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm_xl/operation_scopes.py +8 -2
  6. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm_xl/semantic.py +8 -2
  7. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/utils.py +43 -7
  8. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8/pydpm_xl.egg-info}/PKG-INFO +1 -1
  9. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/pyproject.toml +2 -2
  10. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/LICENSE +0 -0
  11. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/README.md +0 -0
  12. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/__init__.py +0 -0
  13. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm/__init__.py +0 -0
  14. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm/explorer.py +0 -0
  15. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm/hierarchical_queries.py +0 -0
  16. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm/instance.py +0 -0
  17. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm/migration.py +0 -0
  18. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm_xl/__init__.py +0 -0
  19. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm_xl/complete_ast.py +0 -0
  20. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/api/dpm_xl/syntax.py +0 -0
  21. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/cli/__init__.py +0 -0
  22. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/cli/commands/__init__.py +0 -0
  23. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/cli/main.py +0 -0
  24. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/__init__.py +0 -0
  25. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/migration.py +0 -0
  26. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/models.py +0 -0
  27. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/queries/base.py +0 -0
  28. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/queries/basic_objects.py +0 -0
  29. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/queries/explorer_queries.py +0 -0
  30. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/queries/filters.py +0 -0
  31. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/queries/glossary.py +0 -0
  32. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/queries/hierarchical_queries.py +0 -0
  33. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm/queries/tables.py +0 -0
  34. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/__init__.py +0 -0
  35. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/__init__.py +0 -0
  36. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/constructor.py +0 -0
  37. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/ml_generation.py +0 -0
  38. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/module_analyzer.py +0 -0
  39. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/module_dependencies.py +0 -0
  40. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/nodes.py +0 -0
  41. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/operands.py +0 -0
  42. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/template.py +0 -0
  43. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/visitor.py +0 -0
  44. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/ast/where_clause.py +0 -0
  45. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/__init__.py +0 -0
  46. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/__init__.py +0 -0
  47. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.interp +0 -0
  48. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.py +0 -0
  49. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.tokens +0 -0
  50. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.interp +0 -0
  51. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.py +0 -0
  52. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.tokens +0 -0
  53. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/dpm_xlParserListener.py +0 -0
  54. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/dpm_xlParserVisitor.py +0 -0
  55. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/grammar/generated/listeners.py +0 -0
  56. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/__init__.py +0 -0
  57. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/aggregate.py +0 -0
  58. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/arithmetic.py +0 -0
  59. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/base.py +0 -0
  60. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/boolean.py +0 -0
  61. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/clause.py +0 -0
  62. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/comparison.py +0 -0
  63. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/conditional.py +0 -0
  64. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/string.py +0 -0
  65. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/operators/time.py +0 -0
  66. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/semantic_analyzer.py +0 -0
  67. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/symbols.py +0 -0
  68. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/types/__init__.py +0 -0
  69. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/types/promotion.py +0 -0
  70. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/types/scalar.py +0 -0
  71. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/types/time.py +0 -0
  72. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/utils/__init__.py +0 -0
  73. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/utils/data_handlers.py +0 -0
  74. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/utils/operands_mapping.py +0 -0
  75. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/utils/operator_mapping.py +0 -0
  76. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/utils/scopes_calculator.py +0 -0
  77. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/utils/serialization.py +0 -0
  78. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/dpm_xl/utils/tokens.py +0 -0
  79. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/exceptions/__init__.py +0 -0
  80. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/exceptions/exceptions.py +0 -0
  81. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/exceptions/messages.py +0 -0
  82. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/instance/__init__.py +0 -0
  83. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/py_dpm/instance/instance.py +0 -0
  84. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/pydpm_xl.egg-info/SOURCES.txt +0 -0
  85. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/pydpm_xl.egg-info/dependency_links.txt +0 -0
  86. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/pydpm_xl.egg-info/entry_points.txt +0 -0
  87. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/pydpm_xl.egg-info/requires.txt +0 -0
  88. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/pydpm_xl.egg-info/top_level.txt +0 -0
  89. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/setup.cfg +0 -0
  90. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_cli_semantic.py +0 -0
  91. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_data_dictionary_releases.py +0 -0
  92. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_db_connection_handling.py +0 -0
  93. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_get_table_details.py +0 -0
  94. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_get_tables_date_filter.py +0 -0
  95. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_get_tables_release_code.py +0 -0
  96. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_hierarchical_query.py +0 -0
  97. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_query_refactor.py +0 -0
  98. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_release_filters_semantic.py +0 -0
  99. {pydpm_xl-0.2.6 → pydpm_xl-0.2.8}/tests/test_semantic_release.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydpm_xl
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: Python library for DPM-XL data processing and analysis
5
5
  Author-email: "MeaningfulData S.L." <info@meaningfuldata.eu>
6
6
  License: GPL-3.0-or-later
@@ -41,7 +41,7 @@ Available packages:
41
41
  - pydpm.api: Main APIs for migration, syntax, and semantic analysis
42
42
  """
43
43
 
44
- __version__ = "0.2.6"
44
+ __version__ = "0.2.8"
45
45
  __author__ = "MeaningfulData S.L."
46
46
  __email__ = "info@meaningfuldata.eu"
47
47
  __license__ = "GPL-3.0-or-later"
@@ -50,7 +50,10 @@ class DataDictionaryAPI:
50
50
  """
51
51
 
52
52
  def __init__(
53
- self, database_path: Optional[str] = None, connection_url: Optional[str] = None
53
+ self,
54
+ database_path: Optional[str] = None,
55
+ connection_url: Optional[str] = None,
56
+ pool_config: Optional[Dict[str, Any]] = None,
54
57
  ):
55
58
  """
56
59
  Initialize the Data Dictionary API.
@@ -58,8 +61,14 @@ class DataDictionaryAPI:
58
61
  Args:
59
62
  database_path: Path to SQLite database (optional)
60
63
  connection_url: SQLAlchemy connection URL for PostgreSQL (optional)
64
+ pool_config: Connection pool configuration for PostgreSQL/MySQL (optional)
65
+ Supported keys: pool_size, max_overflow, pool_timeout, pool_recycle, pool_pre_ping.
61
66
  """
62
- engine = get_engine(database_path=database_path, connection_url=connection_url)
67
+ engine = get_engine(
68
+ database_path=database_path,
69
+ connection_url=connection_url,
70
+ pool_config=pool_config
71
+ )
63
72
  self.session = get_session()
64
73
 
65
74
  # ==================== Release Query Methods ====================
@@ -48,6 +48,7 @@ class ASTGeneratorAPI:
48
48
 
49
49
  def __init__(self, database_path: Optional[str] = None,
50
50
  connection_url: Optional[str] = None,
51
+ pool_config: Optional[Dict[str, Any]] = None,
51
52
  compatibility_mode: str = "auto",
52
53
  enable_semantic_validation: bool = False):
53
54
  """
@@ -56,13 +57,19 @@ class ASTGeneratorAPI:
56
57
  Args:
57
58
  database_path: Optional path to SQLite data dictionary database
58
59
  connection_url: Optional SQLAlchemy connection URL for PostgreSQL
60
+ pool_config: Connection pool configuration for PostgreSQL/MySQL
59
61
  compatibility_mode: "auto", "3.1.0", "4.0.0", or "current"
60
62
  enable_semantic_validation: Enable semantic validation (requires database)
61
63
  """
62
64
  self.syntax_api = SyntaxAPI()
63
- self.semantic_api = SemanticAPI(database_path=database_path, connection_url=connection_url) if enable_semantic_validation else None
65
+ self.semantic_api = SemanticAPI(
66
+ database_path=database_path,
67
+ connection_url=connection_url,
68
+ pool_config=pool_config
69
+ ) if enable_semantic_validation else None
64
70
  self.database_path = database_path
65
71
  self.connection_url = connection_url
72
+ self.pool_config = pool_config
66
73
  self.compatibility_mode = compatibility_mode
67
74
  self.enable_semantic = enable_semantic_validation
68
75
 
@@ -100,7 +100,10 @@ class OperationScopesAPI:
100
100
  """
101
101
 
102
102
  def __init__(
103
- self, database_path: Optional[str] = None, connection_url: Optional[str] = None
103
+ self,
104
+ database_path: Optional[str] = None,
105
+ connection_url: Optional[str] = None,
106
+ pool_config: Optional[Dict[str, Any]] = None,
104
107
  ):
105
108
  """
106
109
  Initialize the Operation Scopes API.
@@ -109,9 +112,12 @@ class OperationScopesAPI:
109
112
  database_path (Optional[str]): Path to SQLite database. If None, uses default from environment.
110
113
  connection_url (Optional[str]): Full SQLAlchemy connection URL (e.g., postgresql://user:pass@host:port/db).
111
114
  Takes precedence over database_path.
115
+ pool_config (Optional[Dict[str, Any]]): Connection pool configuration for PostgreSQL/MySQL.
116
+ Supported keys: pool_size, max_overflow, pool_timeout, pool_recycle, pool_pre_ping.
112
117
  """
113
118
  self.database_path = database_path
114
119
  self.connection_url = connection_url
120
+ self.pool_config = pool_config
115
121
 
116
122
  if connection_url:
117
123
  # Create isolated engine and session for the provided connection URL
@@ -119,7 +125,7 @@ class OperationScopesAPI:
119
125
  from py_dpm.dpm.utils import create_engine_from_url
120
126
 
121
127
  # Create engine for the connection URL (supports SQLite, PostgreSQL, MySQL, etc.)
122
- self.engine = create_engine_from_url(connection_url)
128
+ self.engine = create_engine_from_url(connection_url, pool_config=pool_config)
123
129
  session_maker = sessionmaker(bind=self.engine)
124
130
  self.session = session_maker()
125
131
 
@@ -44,7 +44,10 @@ class SemanticAPI:
44
44
  """
45
45
 
46
46
  def __init__(
47
- self, database_path: Optional[str] = None, connection_url: Optional[str] = None
47
+ self,
48
+ database_path: Optional[str] = None,
49
+ connection_url: Optional[str] = None,
50
+ pool_config: Optional[Dict[str, Any]] = None,
48
51
  ):
49
52
  """
50
53
  Initialize the Semantic API.
@@ -53,9 +56,12 @@ class SemanticAPI:
53
56
  database_path (Optional[str]): Path to SQLite database. If None, uses default from environment.
54
57
  connection_url (Optional[str]): Full SQLAlchemy connection URL (e.g., postgresql://user:pass@host:port/db).
55
58
  Takes precedence over database_path.
59
+ pool_config (Optional[Dict[str, Any]]): Connection pool configuration for PostgreSQL/MySQL.
60
+ Supported keys: pool_size, max_overflow, pool_timeout, pool_recycle, pool_pre_ping.
56
61
  """
57
62
  self.database_path = database_path
58
63
  self.connection_url = connection_url
64
+ self.pool_config = pool_config
59
65
  # Store last parsed AST for consumers that need it (e.g. complete AST generation)
60
66
  self.ast = None
61
67
 
@@ -65,7 +71,7 @@ class SemanticAPI:
65
71
  from py_dpm.dpm.utils import create_engine_from_url
66
72
 
67
73
  # Create engine for the connection URL (supports SQLite, PostgreSQL, MySQL, etc.)
68
- self.engine = create_engine_from_url(connection_url)
74
+ self.engine = create_engine_from_url(connection_url, pool_config=pool_config)
69
75
  session_maker = sessionmaker(bind=self.engine)
70
76
  self.session = session_maker()
71
77
 
@@ -84,7 +84,7 @@ sessionMakerObject = None
84
84
  _current_engine_url = None
85
85
 
86
86
 
87
- def create_engine_from_url(connection_url):
87
+ def create_engine_from_url(connection_url, pool_config=None):
88
88
  """
89
89
  Create SQLAlchemy engine from a connection URL with appropriate pooling parameters.
90
90
 
@@ -96,6 +96,12 @@ def create_engine_from_url(connection_url):
96
96
 
97
97
  Args:
98
98
  connection_url (str): SQLAlchemy connection URL (e.g., 'sqlite:///path.db', 'postgresql://user:pass@host/db')
99
+ pool_config (dict, optional): Custom pool configuration. Supported keys:
100
+ - pool_size (int): Maximum number of connections to maintain in the pool (default: 20)
101
+ - max_overflow (int): Maximum overflow connections beyond pool_size (default: 10)
102
+ - pool_timeout (int): Seconds to wait before giving up on getting a connection (default: 30)
103
+ - pool_recycle (int): Seconds before recycling connections (default: 180)
104
+ - pool_pre_ping (bool): Health check connections before using from pool (default: True)
99
105
 
100
106
  Returns:
101
107
  sqlalchemy.engine.Engine: Configured database engine
@@ -103,12 +109,21 @@ def create_engine_from_url(connection_url):
103
109
  Examples:
104
110
  >>> engine = create_engine_from_url('sqlite:///database.db')
105
111
  >>> engine = create_engine_from_url('postgresql://user:pass@localhost/mydb')
112
+ >>> engine = create_engine_from_url('postgresql://user:pass@localhost/mydb',
113
+ ... pool_config={'pool_size': 5, 'max_overflow': 10})
106
114
  """
107
115
  global engine, sessionMakerObject, _current_engine_url
108
116
 
109
117
  # Detect database type from URL scheme
110
118
  is_sqlite = connection_url.startswith("sqlite://")
111
119
 
120
+ # For PostgreSQL, ensure ISO datestyle if not already set
121
+ # This prevents date parsing errors when PostgreSQL returns dates in locale format
122
+ is_postgres = connection_url.startswith("postgresql://")
123
+ if is_postgres and "datestyle" not in connection_url.lower():
124
+ separator = "&" if "?" in connection_url else "?"
125
+ connection_url = f"{connection_url}{separator}options=-c%20datestyle%3DISO"
126
+
112
127
  # For SQLite URLs, always create a fresh engine to avoid
113
128
  # surprising cross-test or cross-call state sharing, especially
114
129
  # for in-memory databases. For server-based databases, reuse the
@@ -123,12 +138,22 @@ def create_engine_from_url(connection_url):
123
138
  engine = create_engine(connection_url, pool_pre_ping=True)
124
139
  else:
125
140
  # Server-based databases (PostgreSQL, MySQL, etc.) with connection pooling
141
+ # Default pool configuration
142
+ default_pool_config = {
143
+ 'pool_size': 20,
144
+ 'max_overflow': 10,
145
+ 'pool_timeout': 30,
146
+ 'pool_recycle': 180,
147
+ 'pool_pre_ping': True,
148
+ }
149
+
150
+ # Merge custom pool_config with defaults
151
+ if pool_config:
152
+ default_pool_config.update(pool_config)
153
+
126
154
  engine = create_engine(
127
155
  connection_url,
128
- pool_size=20,
129
- max_overflow=10,
130
- pool_recycle=180,
131
- pool_pre_ping=True,
156
+ **default_pool_config
132
157
  )
133
158
 
134
159
  # Initialize global sessionMakerObject
@@ -149,6 +174,14 @@ def create_engine_object(url):
149
174
  # Detect database type from URL scheme (not from environment variables)
150
175
  is_sqlite = url_str.startswith("sqlite://")
151
176
 
177
+ # For PostgreSQL, ensure ISO datestyle if not already set
178
+ # This prevents date parsing errors when PostgreSQL returns dates in locale format
179
+ is_postgres = url_str.startswith("postgresql://")
180
+ if is_postgres and "datestyle" not in url_str.lower():
181
+ separator = "&" if "?" in url_str else "?"
182
+ url_str = f"{url_str}{separator}options=-c%20datestyle%3DISO"
183
+ url = url_str # Use modified URL for engine creation
184
+
152
185
  # Only reuse engines for non-SQLite URLs. SQLite (especially in-memory)
153
186
  # should create independent engines to avoid leaking state between calls.
154
187
  if not is_sqlite and engine is not None and _current_engine_url == url_str:
@@ -170,7 +203,7 @@ def create_engine_object(url):
170
203
  return engine
171
204
 
172
205
 
173
- def get_engine(owner=None, database_path=None, connection_url=None):
206
+ def get_engine(owner=None, database_path=None, connection_url=None, pool_config=None):
174
207
  """
175
208
  Get database engine based on configuration or explicit parameters.
176
209
 
@@ -184,13 +217,14 @@ def get_engine(owner=None, database_path=None, connection_url=None):
184
217
  owner: Owner for SQL Server databases (EBA/EIOPA) - legacy support
185
218
  database_path: Explicit SQLite database path
186
219
  connection_url: Explicit SQLAlchemy connection URL (e.g., for PostgreSQL)
220
+ pool_config: Connection pool configuration dict (for PostgreSQL/MySQL)
187
221
 
188
222
  Returns:
189
223
  SQLAlchemy Engine
190
224
  """
191
225
  # Priority 1: If explicit connection URL is provided, use it directly
192
226
  if connection_url:
193
- return create_engine_from_url(connection_url)
227
+ return create_engine_from_url(connection_url, pool_config=pool_config)
194
228
 
195
229
  # Priority 2: If explicit database_path is provided, use SQLite with that path
196
230
  if database_path:
@@ -211,6 +245,7 @@ def get_engine(owner=None, database_path=None, connection_url=None):
211
245
  port = db_port or "5432"
212
246
  connection_url = (
213
247
  f"postgresql://{db_user}:{db_password}@{db_host}:{port}/{db_name}"
248
+ "?options=-c%20datestyle%3DISO"
214
249
  )
215
250
  return create_engine_object(connection_url)
216
251
  else:
@@ -258,6 +293,7 @@ def get_engine(owner=None, database_path=None, connection_url=None):
258
293
  connection_url = (
259
294
  f"postgresql://{postgres_user}:{postgres_pass}@"
260
295
  f"{postgres_host}:{postgres_port}/{postgres_db}"
296
+ "?options=-c%20datestyle%3DISO"
261
297
  )
262
298
  return create_engine_object(connection_url)
263
299
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydpm_xl
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: Python library for DPM-XL data processing and analysis
5
5
  Author-email: "MeaningfulData S.L." <info@meaningfuldata.eu>
6
6
  License: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pydpm_xl"
3
- version = "0.2.6"
3
+ version = "0.2.8"
4
4
  description = "Python library for DPM-XL data processing and analysis"
5
5
  authors = [
6
6
  {name = "MeaningfulData S.L.", email = "info@meaningfuldata.eu"}
@@ -52,7 +52,7 @@ exclude = []
52
52
 
53
53
  [tool.poetry]
54
54
  name = "pydpm_xl"
55
- version = "0.2.5"
55
+ version = "0.2.8"
56
56
  description = "Python library for DPM-XL data processing and analysis"
57
57
  authors = ["MeaningfulData S.L. <info@meaningfuldata.eu>"]
58
58
  readme = "README.md"
File without changes
File without changes
File without changes
File without changes
File without changes