sqlspec 0.11.1__py3-none-any.whl → 0.12.0__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.

Potentially problematic release.


This version of sqlspec might be problematic. Click here for more details.

Files changed (155) hide show
  1. sqlspec/__init__.py +16 -3
  2. sqlspec/_serialization.py +3 -10
  3. sqlspec/_sql.py +1147 -0
  4. sqlspec/_typing.py +343 -41
  5. sqlspec/adapters/adbc/__init__.py +2 -6
  6. sqlspec/adapters/adbc/config.py +474 -149
  7. sqlspec/adapters/adbc/driver.py +330 -621
  8. sqlspec/adapters/aiosqlite/__init__.py +2 -6
  9. sqlspec/adapters/aiosqlite/config.py +143 -57
  10. sqlspec/adapters/aiosqlite/driver.py +269 -431
  11. sqlspec/adapters/asyncmy/__init__.py +3 -8
  12. sqlspec/adapters/asyncmy/config.py +247 -202
  13. sqlspec/adapters/asyncmy/driver.py +218 -436
  14. sqlspec/adapters/asyncpg/__init__.py +4 -7
  15. sqlspec/adapters/asyncpg/config.py +329 -176
  16. sqlspec/adapters/asyncpg/driver.py +417 -487
  17. sqlspec/adapters/bigquery/__init__.py +2 -2
  18. sqlspec/adapters/bigquery/config.py +407 -0
  19. sqlspec/adapters/bigquery/driver.py +600 -553
  20. sqlspec/adapters/duckdb/__init__.py +4 -1
  21. sqlspec/adapters/duckdb/config.py +432 -321
  22. sqlspec/adapters/duckdb/driver.py +392 -406
  23. sqlspec/adapters/oracledb/__init__.py +3 -8
  24. sqlspec/adapters/oracledb/config.py +625 -0
  25. sqlspec/adapters/oracledb/driver.py +548 -921
  26. sqlspec/adapters/psqlpy/__init__.py +4 -7
  27. sqlspec/adapters/psqlpy/config.py +372 -203
  28. sqlspec/adapters/psqlpy/driver.py +197 -533
  29. sqlspec/adapters/psycopg/__init__.py +3 -8
  30. sqlspec/adapters/psycopg/config.py +741 -0
  31. sqlspec/adapters/psycopg/driver.py +734 -694
  32. sqlspec/adapters/sqlite/__init__.py +2 -6
  33. sqlspec/adapters/sqlite/config.py +146 -81
  34. sqlspec/adapters/sqlite/driver.py +242 -405
  35. sqlspec/base.py +220 -784
  36. sqlspec/config.py +354 -0
  37. sqlspec/driver/__init__.py +22 -0
  38. sqlspec/driver/_async.py +252 -0
  39. sqlspec/driver/_common.py +338 -0
  40. sqlspec/driver/_sync.py +261 -0
  41. sqlspec/driver/mixins/__init__.py +17 -0
  42. sqlspec/driver/mixins/_pipeline.py +523 -0
  43. sqlspec/driver/mixins/_result_utils.py +122 -0
  44. sqlspec/driver/mixins/_sql_translator.py +35 -0
  45. sqlspec/driver/mixins/_storage.py +993 -0
  46. sqlspec/driver/mixins/_type_coercion.py +131 -0
  47. sqlspec/exceptions.py +299 -7
  48. sqlspec/extensions/aiosql/__init__.py +10 -0
  49. sqlspec/extensions/aiosql/adapter.py +474 -0
  50. sqlspec/extensions/litestar/__init__.py +1 -6
  51. sqlspec/extensions/litestar/_utils.py +1 -5
  52. sqlspec/extensions/litestar/config.py +5 -6
  53. sqlspec/extensions/litestar/handlers.py +13 -12
  54. sqlspec/extensions/litestar/plugin.py +22 -24
  55. sqlspec/extensions/litestar/providers.py +37 -55
  56. sqlspec/loader.py +528 -0
  57. sqlspec/service/__init__.py +3 -0
  58. sqlspec/service/base.py +24 -0
  59. sqlspec/service/pagination.py +26 -0
  60. sqlspec/statement/__init__.py +21 -0
  61. sqlspec/statement/builder/__init__.py +54 -0
  62. sqlspec/statement/builder/_ddl_utils.py +119 -0
  63. sqlspec/statement/builder/_parsing_utils.py +135 -0
  64. sqlspec/statement/builder/base.py +328 -0
  65. sqlspec/statement/builder/ddl.py +1379 -0
  66. sqlspec/statement/builder/delete.py +80 -0
  67. sqlspec/statement/builder/insert.py +274 -0
  68. sqlspec/statement/builder/merge.py +95 -0
  69. sqlspec/statement/builder/mixins/__init__.py +65 -0
  70. sqlspec/statement/builder/mixins/_aggregate_functions.py +151 -0
  71. sqlspec/statement/builder/mixins/_case_builder.py +91 -0
  72. sqlspec/statement/builder/mixins/_common_table_expr.py +91 -0
  73. sqlspec/statement/builder/mixins/_delete_from.py +34 -0
  74. sqlspec/statement/builder/mixins/_from.py +61 -0
  75. sqlspec/statement/builder/mixins/_group_by.py +119 -0
  76. sqlspec/statement/builder/mixins/_having.py +35 -0
  77. sqlspec/statement/builder/mixins/_insert_from_select.py +48 -0
  78. sqlspec/statement/builder/mixins/_insert_into.py +36 -0
  79. sqlspec/statement/builder/mixins/_insert_values.py +69 -0
  80. sqlspec/statement/builder/mixins/_join.py +110 -0
  81. sqlspec/statement/builder/mixins/_limit_offset.py +53 -0
  82. sqlspec/statement/builder/mixins/_merge_clauses.py +405 -0
  83. sqlspec/statement/builder/mixins/_order_by.py +46 -0
  84. sqlspec/statement/builder/mixins/_pivot.py +82 -0
  85. sqlspec/statement/builder/mixins/_returning.py +37 -0
  86. sqlspec/statement/builder/mixins/_select_columns.py +60 -0
  87. sqlspec/statement/builder/mixins/_set_ops.py +122 -0
  88. sqlspec/statement/builder/mixins/_unpivot.py +80 -0
  89. sqlspec/statement/builder/mixins/_update_from.py +54 -0
  90. sqlspec/statement/builder/mixins/_update_set.py +91 -0
  91. sqlspec/statement/builder/mixins/_update_table.py +29 -0
  92. sqlspec/statement/builder/mixins/_where.py +374 -0
  93. sqlspec/statement/builder/mixins/_window_functions.py +86 -0
  94. sqlspec/statement/builder/protocols.py +20 -0
  95. sqlspec/statement/builder/select.py +206 -0
  96. sqlspec/statement/builder/update.py +178 -0
  97. sqlspec/statement/filters.py +571 -0
  98. sqlspec/statement/parameters.py +736 -0
  99. sqlspec/statement/pipelines/__init__.py +67 -0
  100. sqlspec/statement/pipelines/analyzers/__init__.py +9 -0
  101. sqlspec/statement/pipelines/analyzers/_analyzer.py +649 -0
  102. sqlspec/statement/pipelines/base.py +315 -0
  103. sqlspec/statement/pipelines/context.py +119 -0
  104. sqlspec/statement/pipelines/result_types.py +41 -0
  105. sqlspec/statement/pipelines/transformers/__init__.py +8 -0
  106. sqlspec/statement/pipelines/transformers/_expression_simplifier.py +256 -0
  107. sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +623 -0
  108. sqlspec/statement/pipelines/transformers/_remove_comments.py +66 -0
  109. sqlspec/statement/pipelines/transformers/_remove_hints.py +81 -0
  110. sqlspec/statement/pipelines/validators/__init__.py +23 -0
  111. sqlspec/statement/pipelines/validators/_dml_safety.py +275 -0
  112. sqlspec/statement/pipelines/validators/_parameter_style.py +297 -0
  113. sqlspec/statement/pipelines/validators/_performance.py +703 -0
  114. sqlspec/statement/pipelines/validators/_security.py +990 -0
  115. sqlspec/statement/pipelines/validators/base.py +67 -0
  116. sqlspec/statement/result.py +527 -0
  117. sqlspec/statement/splitter.py +701 -0
  118. sqlspec/statement/sql.py +1198 -0
  119. sqlspec/storage/__init__.py +15 -0
  120. sqlspec/storage/backends/__init__.py +0 -0
  121. sqlspec/storage/backends/base.py +166 -0
  122. sqlspec/storage/backends/fsspec.py +315 -0
  123. sqlspec/storage/backends/obstore.py +464 -0
  124. sqlspec/storage/protocol.py +170 -0
  125. sqlspec/storage/registry.py +315 -0
  126. sqlspec/typing.py +157 -36
  127. sqlspec/utils/correlation.py +155 -0
  128. sqlspec/utils/deprecation.py +3 -6
  129. sqlspec/utils/fixtures.py +6 -11
  130. sqlspec/utils/logging.py +135 -0
  131. sqlspec/utils/module_loader.py +45 -43
  132. sqlspec/utils/serializers.py +4 -0
  133. sqlspec/utils/singleton.py +6 -8
  134. sqlspec/utils/sync_tools.py +15 -27
  135. sqlspec/utils/text.py +58 -26
  136. {sqlspec-0.11.1.dist-info → sqlspec-0.12.0.dist-info}/METADATA +97 -26
  137. sqlspec-0.12.0.dist-info/RECORD +145 -0
  138. sqlspec/adapters/bigquery/config/__init__.py +0 -3
  139. sqlspec/adapters/bigquery/config/_common.py +0 -40
  140. sqlspec/adapters/bigquery/config/_sync.py +0 -87
  141. sqlspec/adapters/oracledb/config/__init__.py +0 -9
  142. sqlspec/adapters/oracledb/config/_asyncio.py +0 -186
  143. sqlspec/adapters/oracledb/config/_common.py +0 -131
  144. sqlspec/adapters/oracledb/config/_sync.py +0 -186
  145. sqlspec/adapters/psycopg/config/__init__.py +0 -19
  146. sqlspec/adapters/psycopg/config/_async.py +0 -169
  147. sqlspec/adapters/psycopg/config/_common.py +0 -56
  148. sqlspec/adapters/psycopg/config/_sync.py +0 -168
  149. sqlspec/filters.py +0 -331
  150. sqlspec/mixins.py +0 -305
  151. sqlspec/statement.py +0 -378
  152. sqlspec-0.11.1.dist-info/RECORD +0 -69
  153. {sqlspec-0.11.1.dist-info → sqlspec-0.12.0.dist-info}/WHEEL +0 -0
  154. {sqlspec-0.11.1.dist-info → sqlspec-0.12.0.dist-info}/licenses/LICENSE +0 -0
  155. {sqlspec-0.11.1.dist-info → sqlspec-0.12.0.dist-info}/licenses/NOTICE +0 -0
@@ -1,9 +1,4 @@
1
- from sqlspec.adapters.asyncmy.config import AsyncmyConfig, AsyncmyPoolConfig
2
- from sqlspec.adapters.asyncmy.driver import AsyncmyConnection, AsyncmyDriver # type: ignore[attr-defined]
1
+ from sqlspec.adapters.asyncmy.config import CONNECTION_FIELDS, POOL_FIELDS, AsyncmyConfig
2
+ from sqlspec.adapters.asyncmy.driver import AsyncmyConnection, AsyncmyDriver
3
3
 
4
- __all__ = (
5
- "AsyncmyConfig",
6
- "AsyncmyConnection",
7
- "AsyncmyDriver",
8
- "AsyncmyPoolConfig",
9
- )
4
+ __all__ = ("CONNECTION_FIELDS", "POOL_FIELDS", "AsyncmyConfig", "AsyncmyConnection", "AsyncmyDriver")
@@ -1,241 +1,286 @@
1
+ """Asyncmy database configuration with direct field-based configuration."""
2
+
3
+ import logging
4
+ from collections.abc import AsyncGenerator
1
5
  from contextlib import asynccontextmanager
2
- from dataclasses import dataclass, field
3
- from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
6
+ from dataclasses import replace
7
+ from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union
4
8
 
5
- from asyncmy.connection import Connection # pyright: ignore[reportUnknownVariableType]
9
+ import asyncmy
6
10
 
7
- from sqlspec.adapters.asyncmy.driver import AsyncmyDriver # type: ignore[attr-defined]
8
- from sqlspec.base import AsyncDatabaseConfig, GenericPoolConfig
9
- from sqlspec.exceptions import ImproperConfigurationError
10
- from sqlspec.typing import Empty, EmptyType, dataclass_to_dict
11
+ from sqlspec.adapters.asyncmy.driver import AsyncmyConnection, AsyncmyDriver
12
+ from sqlspec.config import AsyncDatabaseConfig
13
+ from sqlspec.statement.sql import SQLConfig
14
+ from sqlspec.typing import DictRow, Empty
11
15
 
12
16
  if TYPE_CHECKING:
13
- from collections.abc import AsyncGenerator
14
-
15
- from asyncmy.cursors import Cursor, DictCursor # pyright: ignore[reportUnknownVariableType]
16
- from asyncmy.pool import Pool # pyright: ignore[reportUnknownVariableType]
17
-
18
- __all__ = (
19
- "AsyncmyConfig",
20
- "AsyncmyPoolConfig",
17
+ from asyncmy.cursors import Cursor, DictCursor
18
+ from asyncmy.pool import Pool
19
+ from sqlglot.dialects.dialect import DialectType
20
+
21
+
22
+ __all__ = ("CONNECTION_FIELDS", "POOL_FIELDS", "AsyncmyConfig")
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+ CONNECTION_FIELDS = frozenset(
27
+ {
28
+ "host",
29
+ "user",
30
+ "password",
31
+ "database",
32
+ "port",
33
+ "unix_socket",
34
+ "charset",
35
+ "connect_timeout",
36
+ "read_default_file",
37
+ "read_default_group",
38
+ "autocommit",
39
+ "local_infile",
40
+ "ssl",
41
+ "sql_mode",
42
+ "init_command",
43
+ "cursor_class",
44
+ }
21
45
  )
22
46
 
23
-
24
- T = TypeVar("T")
25
-
26
-
27
- @dataclass
28
- class AsyncmyPoolConfig(GenericPoolConfig):
29
- """Configuration for Asyncmy's connection pool.
30
-
31
- This class provides configuration options for Asyncmy database connection pools.
32
-
33
- For details see: https://github.com/long2ice/asyncmy
34
- """
35
-
36
- host: "Union[str, EmptyType]" = Empty
37
- """Host where the database server is located."""
38
-
39
- user: "Union[str, EmptyType]" = Empty
40
- """The username used to authenticate with the database."""
41
-
42
- password: "Union[str, EmptyType]" = Empty
43
- """The password used to authenticate with the database."""
44
-
45
- database: "Union[str, EmptyType]" = Empty
46
- """The database name to use."""
47
-
48
- port: "Union[int, EmptyType]" = Empty
49
- """The TCP/IP port of the MySQL server. Must be an integer."""
50
-
51
- unix_socket: "Union[str, EmptyType]" = Empty
52
- """The location of the Unix socket file."""
53
-
54
- charset: "Union[str, EmptyType]" = Empty
55
- """The character set to use for the connection."""
56
-
57
- connect_timeout: "Union[float, EmptyType]" = Empty
58
- """Timeout before throwing an error when connecting."""
59
-
60
- read_default_file: "Union[str, EmptyType]" = Empty
61
- """MySQL configuration file to read."""
62
-
63
- read_default_group: "Union[str, EmptyType]" = Empty
64
- """Group to read from the configuration file."""
65
-
66
- autocommit: "Union[bool, EmptyType]" = Empty
67
- """If True, autocommit mode will be enabled."""
68
-
69
- local_infile: "Union[bool, EmptyType]" = Empty
70
- """If True, enables LOAD LOCAL INFILE."""
71
-
72
- ssl: "Union[dict[str, Any], bool, EmptyType]" = Empty
73
- """If present, a dictionary of SSL connection parameters, or just True."""
74
-
75
- sql_mode: "Union[str, EmptyType]" = Empty
76
- """Default SQL_MODE to use."""
77
-
78
- init_command: "Union[str, EmptyType]" = Empty
79
- """Initial SQL statement to execute once connected."""
80
-
81
- cursor_class: "Union[type[Union[Cursor, DictCursor]], EmptyType]" = Empty
82
- """Custom cursor class to use."""
83
-
84
- minsize: "Union[int, EmptyType]" = Empty
85
- """Minimum number of connections to keep in the pool."""
86
-
87
- maxsize: "Union[int, EmptyType]" = Empty
88
- """Maximum number of connections allowed in the pool."""
89
-
90
- echo: "Union[bool, EmptyType]" = Empty
91
- """If True, logging will be enabled for all SQL statements."""
92
-
93
- pool_recycle: "Union[int, EmptyType]" = Empty
94
- """Number of seconds after which a connection is recycled."""
47
+ POOL_FIELDS = CONNECTION_FIELDS.union({"minsize", "maxsize", "echo", "pool_recycle"})
48
+
49
+
50
+ class AsyncmyConfig(AsyncDatabaseConfig[AsyncmyConnection, "Pool", AsyncmyDriver]): # pyright: ignore
51
+ """Configuration for Asyncmy database connections with direct field-based configuration."""
52
+
53
+ __slots__ = (
54
+ "_dialect",
55
+ "autocommit",
56
+ "charset",
57
+ "connect_timeout",
58
+ "cursor_class",
59
+ "database",
60
+ "default_row_type",
61
+ "echo",
62
+ "extras",
63
+ "host",
64
+ "init_command",
65
+ "local_infile",
66
+ "maxsize",
67
+ "minsize",
68
+ "password",
69
+ "pool_instance",
70
+ "pool_recycle",
71
+ "port",
72
+ "read_default_file",
73
+ "read_default_group",
74
+ "sql_mode",
75
+ "ssl",
76
+ "statement_config",
77
+ "unix_socket",
78
+ "user",
79
+ )
80
+
81
+ is_async: ClassVar[bool] = True
82
+ supports_connection_pooling: ClassVar[bool] = True
83
+ driver_type: type[AsyncmyDriver] = AsyncmyDriver
84
+ connection_type: type[AsyncmyConnection] = AsyncmyConnection # pyright: ignore
85
+
86
+ # Parameter style support information
87
+ supported_parameter_styles: ClassVar[tuple[str, ...]] = ("pyformat_positional",)
88
+ """AsyncMy only supports %s (pyformat_positional) parameter style."""
89
+
90
+ preferred_parameter_style: ClassVar[str] = "pyformat_positional"
91
+ """AsyncMy's native parameter style is %s (pyformat_positional)."""
92
+
93
+ def __init__(
94
+ self,
95
+ statement_config: Optional[SQLConfig] = None,
96
+ default_row_type: type[DictRow] = DictRow,
97
+ # Connection parameters
98
+ host: Optional[str] = None,
99
+ user: Optional[str] = None,
100
+ password: Optional[str] = None,
101
+ database: Optional[str] = None,
102
+ port: Optional[int] = None,
103
+ unix_socket: Optional[str] = None,
104
+ charset: Optional[str] = None,
105
+ connect_timeout: Optional[float] = None,
106
+ read_default_file: Optional[str] = None,
107
+ read_default_group: Optional[str] = None,
108
+ autocommit: Optional[bool] = None,
109
+ local_infile: Optional[bool] = None,
110
+ ssl: Optional[Any] = None,
111
+ sql_mode: Optional[str] = None,
112
+ init_command: Optional[str] = None,
113
+ cursor_class: Optional[Union["type[Cursor]", "type[DictCursor]"]] = None,
114
+ # Pool parameters
115
+ minsize: Optional[int] = None,
116
+ maxsize: Optional[int] = None,
117
+ echo: Optional[bool] = None,
118
+ pool_recycle: Optional[int] = None,
119
+ pool_instance: Optional["Pool"] = None,
120
+ **kwargs: Any,
121
+ ) -> None:
122
+ """Initialize Asyncmy configuration.
123
+
124
+ Args:
125
+ statement_config: Default SQL statement configuration
126
+ default_row_type: Default row type for results
127
+ host: Host where the database server is located
128
+ user: The username used to authenticate with the database
129
+ password: The password used to authenticate with the database
130
+ database: The database name to use
131
+ port: The TCP/IP port of the MySQL server
132
+ unix_socket: The location of the Unix socket file
133
+ charset: The character set to use for the connection
134
+ connect_timeout: Timeout before throwing an error when connecting
135
+ read_default_file: MySQL configuration file to read
136
+ read_default_group: Group to read from the configuration file
137
+ autocommit: If True, autocommit mode will be enabled
138
+ local_infile: If True, enables LOAD LOCAL INFILE
139
+ ssl: SSL connection parameters or boolean
140
+ sql_mode: Default SQL_MODE to use
141
+ init_command: Initial SQL statement to execute once connected
142
+ cursor_class: Custom cursor class to use
143
+ minsize: Minimum number of connections to keep in the pool
144
+ maxsize: Maximum number of connections allowed in the pool
145
+ echo: If True, logging will be enabled for all SQL statements
146
+ pool_recycle: Number of seconds after which a connection is recycled
147
+ pool_instance: Existing connection pool instance to use
148
+ **kwargs: Additional parameters (stored in extras)
149
+ """
150
+ # Store connection parameters as instance attributes
151
+ self.host = host
152
+ self.user = user
153
+ self.password = password
154
+ self.database = database
155
+ self.port = port
156
+ self.unix_socket = unix_socket
157
+ self.charset = charset
158
+ self.connect_timeout = connect_timeout
159
+ self.read_default_file = read_default_file
160
+ self.read_default_group = read_default_group
161
+ self.autocommit = autocommit
162
+ self.local_infile = local_infile
163
+ self.ssl = ssl
164
+ self.sql_mode = sql_mode
165
+ self.init_command = init_command
166
+ self.cursor_class = cursor_class
167
+
168
+ # Store pool parameters as instance attributes
169
+ self.minsize = minsize
170
+ self.maxsize = maxsize
171
+ self.echo = echo
172
+ self.pool_recycle = pool_recycle
173
+ self.extras = kwargs or {}
174
+
175
+ # Store other config
176
+ self.statement_config = statement_config or SQLConfig()
177
+ self.default_row_type = default_row_type
178
+ self.pool_instance: Optional[Pool] = pool_instance
179
+ self._dialect: DialectType = None
180
+
181
+ super().__init__() # pyright: ignore
95
182
 
96
183
  @property
97
- def pool_config_dict(self) -> "dict[str, Any]":
98
- """Return the pool configuration as a dict.
184
+ def connection_config_dict(self) -> dict[str, Any]:
185
+ """Return the connection configuration as a dict for asyncmy.connect().
99
186
 
100
- Returns:
101
- A string keyed dict of config kwargs for the Asyncmy create_pool function.
187
+ This method filters out pool-specific parameters that are not valid for asyncmy.connect().
102
188
  """
103
- return dataclass_to_dict(self, exclude_empty=True, convert_nested=False)
104
-
189
+ # Gather non-None connection parameters
190
+ config = {
191
+ field: getattr(self, field)
192
+ for field in CONNECTION_FIELDS
193
+ if getattr(self, field, None) is not None and getattr(self, field) is not Empty
194
+ }
105
195
 
106
- @dataclass
107
- class AsyncmyConfig(AsyncDatabaseConfig["Connection", "Pool", "AsyncmyDriver"]):
108
- """Asyncmy Configuration."""
196
+ # Add connection-specific extras (not pool-specific ones)
197
+ config.update(self.extras)
109
198
 
110
- __is_async__ = True
111
- __supports_connection_pooling__ = True
112
-
113
- pool_config: "Optional[AsyncmyPoolConfig]" = None
114
- """Asyncmy Pool configuration"""
115
- connection_type: "type[Connection]" = field(hash=False, init=False, default_factory=lambda: Connection) # pyright: ignore
116
- """Type of the connection object"""
117
- driver_type: "type[AsyncmyDriver]" = field(hash=False, init=False, default_factory=lambda: AsyncmyDriver)
118
- """Type of the driver object"""
119
- pool_instance: "Optional[Pool]" = field(hash=False, default=None) # pyright: ignore[reportUnknownVariableType]
120
- """Instance of the pool"""
199
+ return config
121
200
 
122
201
  @property
123
- def connection_config_dict(self) -> "dict[str, Any]":
124
- """Return the connection configuration as a dict.
202
+ def pool_config_dict(self) -> dict[str, Any]:
203
+ """Return the full pool configuration as a dict for asyncmy.create_pool().
125
204
 
126
205
  Returns:
127
- A string keyed dict of config kwargs for the Asyncmy connect function.
128
-
129
- Raises:
130
- ImproperConfigurationError: If the connection configuration is not provided.
206
+ A dictionary containing all pool configuration parameters.
131
207
  """
132
- if self.pool_config:
133
- # Filter out pool-specific parameters
134
- pool_only_params = {"minsize", "maxsize", "echo", "pool_recycle"}
135
- return dataclass_to_dict(
136
- self.pool_config,
137
- exclude_empty=True,
138
- convert_nested=False,
139
- exclude=pool_only_params.union({"pool_instance", "driver_type", "connection_type"}),
140
- )
141
- msg = "You must provide a 'pool_config' for this adapter."
142
- raise ImproperConfigurationError(msg)
208
+ # Gather non-None parameters from all fields (connection + pool)
209
+ config = {
210
+ field: getattr(self, field)
211
+ for field in POOL_FIELDS
212
+ if getattr(self, field, None) is not None and getattr(self, field) is not Empty
213
+ }
143
214
 
144
- @property
145
- def pool_config_dict(self) -> "dict[str, Any]":
146
- """Return the pool configuration as a dict.
215
+ # Merge extras parameters
216
+ config.update(self.extras)
147
217
 
148
- Returns:
149
- A string keyed dict of config kwargs for the Asyncmy create_pool function.
150
-
151
- Raises:
152
- ImproperConfigurationError: If the pool configuration is not provided.
153
- """
154
- if self.pool_config:
155
- return dataclass_to_dict(
156
- self.pool_config,
157
- exclude_empty=True,
158
- convert_nested=False,
159
- exclude={"pool_instance", "driver_type", "connection_type"},
160
- )
161
- msg = "'pool_config' methods can not be used when a 'pool_instance' is provided."
162
- raise ImproperConfigurationError(msg)
163
-
164
- async def create_connection(self) -> "Connection": # pyright: ignore[reportUnknownParameterType]
165
- """Create and return a new asyncmy connection from the pool.
218
+ return config
166
219
 
167
- Returns:
168
- A Connection instance.
220
+ async def _create_pool(self) -> "Pool": # pyright: ignore
221
+ """Create the actual async connection pool."""
222
+ return await asyncmy.create_pool(**self.pool_config_dict)
169
223
 
170
- Raises:
171
- ImproperConfigurationError: If the connection could not be created.
172
- """
173
- try:
174
- async with self.provide_connection() as conn:
175
- return conn
176
- except Exception as e:
177
- msg = f"Could not configure the Asyncmy connection. Error: {e!s}"
178
- raise ImproperConfigurationError(msg) from e
224
+ async def _close_pool(self) -> None:
225
+ """Close the actual async connection pool."""
226
+ if self.pool_instance:
227
+ await self.pool_instance.close()
179
228
 
180
- async def create_pool(self) -> "Pool": # pyright: ignore[reportUnknownParameterType]
181
- """Return a pool. If none exists yet, create one.
229
+ async def create_connection(self) -> AsyncmyConnection: # pyright: ignore
230
+ """Create a single async connection (not from pool).
182
231
 
183
232
  Returns:
184
- Getter that returns the pool instance used by the plugin.
185
-
186
- Raises:
187
- ImproperConfigurationError: If the pool could not be created.
233
+ An Asyncmy connection instance.
188
234
  """
189
- if self.pool_instance is not None: # pyright: ignore[reportUnknownMemberType]
190
- return self.pool_instance # pyright: ignore[reportUnknownVariableType,reportUnknownMemberType]
191
-
192
- if self.pool_config is None:
193
- msg = "One of 'pool_config' or 'pool_instance' must be provided."
194
- raise ImproperConfigurationError(msg)
235
+ if self.pool_instance is None:
236
+ self.pool_instance = await self.create_pool()
237
+ return await self.pool_instance.acquire() # pyright: ignore
195
238
 
196
- try:
197
- import asyncmy # pyright: ignore[reportMissingTypeStubs]
198
-
199
- self.pool_instance = await asyncmy.create_pool(**self.pool_config_dict) # pyright: ignore[reportUnknownMemberType]
200
- except Exception as e:
201
- msg = f"Could not configure the Asyncmy pool. Error: {e!s}"
202
- raise ImproperConfigurationError(msg) from e
203
- else:
204
- return self.pool_instance # pyright: ignore[reportUnknownVariableType,reportUnknownMemberType]
239
+ @asynccontextmanager
240
+ async def provide_connection(self, *args: Any, **kwargs: Any) -> AsyncGenerator[AsyncmyConnection, None]: # pyright: ignore
241
+ """Provide an async connection context manager.
205
242
 
206
- async def provide_pool(self, *args: "Any", **kwargs: "Any") -> "Pool": # pyright: ignore[reportUnknownParameterType]
207
- """Create a pool instance.
243
+ Args:
244
+ *args: Additional arguments.
245
+ **kwargs: Additional keyword arguments.
208
246
 
209
- Returns:
210
- A Pool instance.
247
+ Yields:
248
+ An Asyncmy connection instance.
211
249
  """
212
- return await self.create_pool() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
250
+ if self.pool_instance is None:
251
+ self.pool_instance = await self.create_pool()
252
+ async with self.pool_instance.acquire() as connection: # pyright: ignore
253
+ yield connection
213
254
 
214
255
  @asynccontextmanager
215
- async def provide_connection(self, *args: "Any", **kwargs: "Any") -> "AsyncGenerator[Connection, None]": # pyright: ignore[reportUnknownParameterType]
216
- """Create and provide a database connection.
256
+ async def provide_session(self, *args: Any, **kwargs: Any) -> AsyncGenerator[AsyncmyDriver, None]:
257
+ """Provide an async driver session context manager.
217
258
 
218
- Yields:
219
- An Asyncmy connection instance.
259
+ Args:
260
+ *args: Additional arguments.
261
+ **kwargs: Additional keyword arguments.
220
262
 
263
+ Yields:
264
+ An AsyncmyDriver instance.
221
265
  """
222
- pool = await self.provide_pool(*args, **kwargs) # pyright: ignore[reportUnknownVariableType,reportUnknownMemberType]
223
- async with pool.acquire() as connection: # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
224
- yield connection # pyright: ignore[reportUnknownMemberType]
266
+ async with self.provide_connection(*args, **kwargs) as connection:
267
+ # Create statement config with parameter style info if not already set
268
+ statement_config = self.statement_config
269
+ if statement_config.allowed_parameter_styles is None:
270
+ statement_config = replace(
271
+ statement_config,
272
+ allowed_parameter_styles=self.supported_parameter_styles,
273
+ target_parameter_style=self.preferred_parameter_style,
274
+ )
225
275
 
226
- @asynccontextmanager
227
- async def provide_session(self, *args: "Any", **kwargs: "Any") -> "AsyncGenerator[AsyncmyDriver, None]":
228
- """Create and provide a database session.
276
+ yield self.driver_type(connection=connection, config=statement_config)
229
277
 
230
- Yields:
231
- An Asyncmy driver instance.
278
+ async def provide_pool(self, *args: Any, **kwargs: Any) -> "Pool": # pyright: ignore
279
+ """Provide async pool instance.
232
280
 
281
+ Returns:
282
+ The async connection pool.
233
283
  """
234
- async with self.provide_connection(*args, **kwargs) as connection: # pyright: ignore[reportUnknownVariableType]
235
- yield self.driver_type(connection) # pyright: ignore[reportUnknownArgumentType]
236
-
237
- async def close_pool(self) -> None:
238
- """Close the connection pool."""
239
- if self.pool_instance is not None: # pyright: ignore[reportUnknownMemberType]
240
- await self.pool_instance.close() # pyright: ignore[reportUnknownMemberType]
241
- self.pool_instance = None
284
+ if not self.pool_instance:
285
+ self.pool_instance = await self.create_pool()
286
+ return self.pool_instance