Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/create.py: 67%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

168 statements  

1# engine/create.py 

2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: https://www.opensource.org/licenses/mit-license.php 

7 

8from __future__ import annotations 

9 

10import inspect 

11import typing 

12from typing import Any 

13from typing import Callable 

14from typing import cast 

15from typing import Dict 

16from typing import List 

17from typing import Optional 

18from typing import overload 

19from typing import Type 

20from typing import Union 

21 

22from . import base 

23from . import url as _url 

24from .interfaces import DBAPIConnection 

25from .mock import create_mock_engine 

26from .. import event 

27from .. import exc 

28from .. import util 

29from ..pool import _AdhocProxiedConnection 

30from ..pool import ConnectionPoolEntry 

31from ..sql import compiler 

32from ..util import immutabledict 

33 

34if typing.TYPE_CHECKING: 

35 from typing import Literal 

36 

37 from .base import Engine 

38 from .interfaces import _ExecuteOptions 

39 from .interfaces import _ParamStyle 

40 from .interfaces import IsolationLevel 

41 from .url import URL 

42 from ..log import _EchoFlagType 

43 from ..pool import _CreatorFnType 

44 from ..pool import _CreatorWRecFnType 

45 from ..pool import _ResetStyleArgType 

46 from ..pool import Pool 

47 

48 

49@overload 

50def create_engine( 

51 url: Union[str, URL], 

52 *, 

53 connect_args: Dict[Any, Any] = ..., 

54 convert_unicode: bool = ..., 

55 creator: Union[_CreatorFnType, _CreatorWRecFnType] = ..., 

56 echo: _EchoFlagType = ..., 

57 echo_pool: _EchoFlagType = ..., 

58 enable_from_linting: bool = ..., 

59 execution_options: _ExecuteOptions = ..., 

60 future: Literal[True], 

61 hide_parameters: bool = ..., 

62 implicit_returning: Literal[True] = ..., 

63 insertmanyvalues_page_size: int = ..., 

64 isolation_level: IsolationLevel = ..., 

65 json_deserializer: Callable[..., Any] = ..., 

66 json_serializer: Callable[..., Any] = ..., 

67 label_length: Optional[int] = ..., 

68 logging_name: str = ..., 

69 max_identifier_length: Optional[int] = ..., 

70 max_overflow: int = ..., 

71 module: Optional[Any] = ..., 

72 paramstyle: Optional[_ParamStyle] = ..., 

73 pool: Optional[Pool] = ..., 

74 poolclass: Optional[Type[Pool]] = ..., 

75 pool_logging_name: str = ..., 

76 pool_pre_ping: bool = ..., 

77 pool_size: int = ..., 

78 pool_recycle: int = ..., 

79 pool_reset_on_return: Optional[_ResetStyleArgType] = ..., 

80 pool_timeout: float = ..., 

81 pool_use_lifo: bool = ..., 

82 plugins: List[str] = ..., 

83 query_cache_size: int = ..., 

84 use_insertmanyvalues: bool = ..., 

85 **kwargs: Any, 

86) -> Engine: ... 

87 

88 

89@overload 

90def create_engine(url: Union[str, URL], **kwargs: Any) -> Engine: ... 

91 

92 

93@util.deprecated_params( 

94 strategy=( 

95 "1.4", 

96 "The :paramref:`_sa.create_engine.strategy` keyword is deprecated, " 

97 "and the only argument accepted is 'mock'; please use " 

98 ":func:`.create_mock_engine` going forward. For general " 

99 "customization of create_engine which may have been accomplished " 

100 "using strategies, see :class:`.CreateEnginePlugin`.", 

101 ), 

102 empty_in_strategy=( 

103 "1.4", 

104 "The :paramref:`_sa.create_engine.empty_in_strategy` keyword is " 

105 "deprecated, and no longer has any effect. All IN expressions " 

106 "are now rendered using " 

107 'the "expanding parameter" strategy which renders a set of bound' 

108 'expressions, or an "empty set" SELECT, at statement execution' 

109 "time.", 

110 ), 

111 implicit_returning=( 

112 "2.0", 

113 "The :paramref:`_sa.create_engine.implicit_returning` parameter " 

114 "is deprecated and will be removed in a future release. ", 

115 ), 

116) 

117def create_engine(url: Union[str, _url.URL], **kwargs: Any) -> Engine: 

118 """Create a new :class:`_engine.Engine` instance. 

119 

120 The standard calling form is to send the :ref:`URL <database_urls>` as the 

121 first positional argument, usually a string 

122 that indicates database dialect and connection arguments:: 

123 

124 engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test") 

125 

126 .. note:: 

127 

128 Please review :ref:`database_urls` for general guidelines in composing 

129 URL strings. In particular, special characters, such as those often 

130 part of passwords, must be URL encoded to be properly parsed. 

131 

132 Additional keyword arguments may then follow it which 

133 establish various options on the resulting :class:`_engine.Engine` 

134 and its underlying :class:`.Dialect` and :class:`_pool.Pool` 

135 constructs:: 

136 

137 engine = create_engine( 

138 "mysql+mysqldb://scott:tiger@hostname/dbname", 

139 pool_recycle=3600, 

140 echo=True, 

141 ) 

142 

143 The string form of the URL is 

144 ``dialect[+driver]://user:password@host/dbname[?key=value..]``, where 

145 ``dialect`` is a database name such as ``mysql``, ``oracle``, 

146 ``postgresql``, etc., and ``driver`` the name of a DBAPI, such as 

147 ``psycopg2``, ``pyodbc``, ``cx_oracle``, etc. Alternatively, 

148 the URL can be an instance of :class:`~sqlalchemy.engine.url.URL`. 

149 

150 ``**kwargs`` takes a wide variety of options which are routed 

151 towards their appropriate components. Arguments may be specific to 

152 the :class:`_engine.Engine`, the underlying :class:`.Dialect`, 

153 as well as the 

154 :class:`_pool.Pool`. Specific dialects also accept keyword arguments that 

155 are unique to that dialect. Here, we describe the parameters 

156 that are common to most :func:`_sa.create_engine()` usage. 

157 

158 Once established, the newly resulting :class:`_engine.Engine` will 

159 request a connection from the underlying :class:`_pool.Pool` once 

160 :meth:`_engine.Engine.connect` is called, or a method which depends on it 

161 such as :meth:`_engine.Engine.execute` is invoked. The 

162 :class:`_pool.Pool` in turn 

163 will establish the first actual DBAPI connection when this request 

164 is received. The :func:`_sa.create_engine` call itself does **not** 

165 establish any actual DBAPI connections directly. 

166 

167 .. seealso:: 

168 

169 :doc:`/core/engines` 

170 

171 :doc:`/dialects/index` 

172 

173 :ref:`connections_toplevel` 

174 

175 :param connect_args: a dictionary of options which will be 

176 passed directly to the DBAPI's ``connect()`` method as 

177 additional keyword arguments. See the example 

178 at :ref:`custom_dbapi_args`. 

179 

180 :param creator: a callable which returns a DBAPI connection. 

181 This creation function will be passed to the underlying 

182 connection pool and will be used to create all new database 

183 connections. Usage of this function causes connection 

184 parameters specified in the URL argument to be bypassed. 

185 

186 This hook is not as flexible as the newer 

187 :meth:`_events.DialectEvents.do_connect` hook which allows complete 

188 control over how a connection is made to the database, given the full 

189 set of URL arguments and state beforehand. 

190 

191 .. seealso:: 

192 

193 :meth:`_events.DialectEvents.do_connect` - event hook that allows 

194 full control over DBAPI connection mechanics. 

195 

196 :ref:`custom_dbapi_args` 

197 

198 :param echo=False: if True, the Engine will log all statements 

199 as well as a ``repr()`` of their parameter lists to the default log 

200 handler, which defaults to ``sys.stdout`` for output. If set to the 

201 string ``"debug"``, result rows will be printed to the standard output 

202 as well. The ``echo`` attribute of ``Engine`` can be modified at any 

203 time to turn logging on and off; direct control of logging is also 

204 available using the standard Python ``logging`` module. 

205 

206 .. seealso:: 

207 

208 :ref:`dbengine_logging` - further detail on how to configure 

209 logging. 

210 

211 

212 :param echo_pool=False: if True, the connection pool will log 

213 informational output such as when connections are invalidated 

214 as well as when connections are recycled to the default log handler, 

215 which defaults to ``sys.stdout`` for output. If set to the string 

216 ``"debug"``, the logging will include pool checkouts and checkins. 

217 Direct control of logging is also available using the standard Python 

218 ``logging`` module. 

219 

220 .. seealso:: 

221 

222 :ref:`dbengine_logging` - further detail on how to configure 

223 logging. 

224 

225 

226 :param empty_in_strategy: No longer used; SQLAlchemy now uses 

227 "empty set" behavior for IN in all cases. 

228 

229 :param enable_from_linting: defaults to True. Will emit a warning 

230 if a given SELECT statement is found to have un-linked FROM elements 

231 which would cause a cartesian product. 

232 

233 .. versionadded:: 1.4 

234 

235 .. seealso:: 

236 

237 :ref:`change_4737` 

238 

239 :param execution_options: Dictionary execution options which will 

240 be applied to all connections. See 

241 :meth:`~sqlalchemy.engine.Connection.execution_options` 

242 

243 :param future: Use the 2.0 style :class:`_engine.Engine` and 

244 :class:`_engine.Connection` API. 

245 

246 As of SQLAlchemy 2.0, this parameter is present for backwards 

247 compatibility only and must remain at its default value of ``True``. 

248 

249 The :paramref:`_sa.create_engine.future` parameter will be 

250 deprecated in a subsequent 2.x release and eventually removed. 

251 

252 .. versionadded:: 1.4 

253 

254 .. versionchanged:: 2.0 All :class:`_engine.Engine` objects are 

255 "future" style engines and there is no longer a ``future=False`` 

256 mode of operation. 

257 

258 .. seealso:: 

259 

260 :ref:`migration_20_toplevel` 

261 

262 :param hide_parameters: Boolean, when set to True, SQL statement parameters 

263 will not be displayed in INFO logging nor will they be formatted into 

264 the string representation of :class:`.StatementError` objects. 

265 

266 .. seealso:: 

267 

268 :ref:`dbengine_logging` - further detail on how to configure 

269 logging. 

270 

271 :param implicit_returning=True: Legacy parameter that may only be set 

272 to True. In SQLAlchemy 2.0, this parameter does nothing. In order to 

273 disable "implicit returning" for statements invoked by the ORM, 

274 configure this on a per-table basis using the 

275 :paramref:`.Table.implicit_returning` parameter. 

276 

277 

278 :param insertmanyvalues_page_size: number of rows to format into an 

279 INSERT statement when the statement uses "insertmanyvalues" mode, which is 

280 a paged form of bulk insert that is used for many backends when using 

281 :term:`executemany` execution typically in conjunction with RETURNING. 

282 Defaults to 1000, but may also be subject to dialect-specific limiting 

283 factors which may override this value on a per-statement basis. 

284 

285 .. versionadded:: 2.0 

286 

287 .. seealso:: 

288 

289 :ref:`engine_insertmanyvalues` 

290 

291 :ref:`engine_insertmanyvalues_page_size` 

292 

293 :paramref:`_engine.Connection.execution_options.insertmanyvalues_page_size` 

294 

295 :param isolation_level: optional string name of an isolation level 

296 which will be set on all new connections unconditionally. 

297 Isolation levels are typically some subset of the string names 

298 ``"SERIALIZABLE"``, ``"REPEATABLE READ"``, 

299 ``"READ COMMITTED"``, ``"READ UNCOMMITTED"`` and ``"AUTOCOMMIT"`` 

300 based on backend. 

301 

302 The :paramref:`_sa.create_engine.isolation_level` parameter is 

303 in contrast to the 

304 :paramref:`.Connection.execution_options.isolation_level` 

305 execution option, which may be set on an individual 

306 :class:`.Connection`, as well as the same parameter passed to 

307 :meth:`.Engine.execution_options`, where it may be used to create 

308 multiple engines with different isolation levels that share a common 

309 connection pool and dialect. 

310 

311 .. versionchanged:: 2.0 The 

312 :paramref:`_sa.create_engine.isolation_level` 

313 parameter has been generalized to work on all dialects which support 

314 the concept of isolation level, and is provided as a more succinct, 

315 up front configuration switch in contrast to the execution option 

316 which is more of an ad-hoc programmatic option. 

317 

318 .. seealso:: 

319 

320 :ref:`dbapi_autocommit` 

321 

322 :param json_deserializer: for dialects that support the 

323 :class:`_types.JSON` 

324 datatype, this is a Python callable that will convert a JSON string 

325 to a Python object. By default, either the driver's built-in 

326 capabilities are used, or if none are available, the Python 

327 ``json.loads`` function is used. 

328 

329 :param json_serializer: for dialects that support the :class:`_types.JSON` 

330 datatype, this is a Python callable that will render a given object as 

331 JSON. By default, the Python ``json.dumps`` function is used. 

332 

333 :param label_length=None: optional integer value which limits 

334 the size of dynamically generated column labels to that many 

335 characters. If less than 6, labels are generated as 

336 "_(counter)". If ``None``, the value of 

337 ``dialect.max_identifier_length``, which may be affected via the 

338 :paramref:`_sa.create_engine.max_identifier_length` parameter, 

339 is used instead. The value of 

340 :paramref:`_sa.create_engine.label_length` 

341 may not be larger than that of 

342 :paramref:`_sa.create_engine.max_identfier_length`. 

343 

344 .. seealso:: 

345 

346 :paramref:`_sa.create_engine.max_identifier_length` 

347 

348 :param logging_name: String identifier which will be used within 

349 the "name" field of logging records generated within the 

350 "sqlalchemy.engine" logger. Defaults to a hexstring of the 

351 object's id. 

352 

353 .. seealso:: 

354 

355 :ref:`dbengine_logging` - further detail on how to configure 

356 logging. 

357 

358 :paramref:`_engine.Connection.execution_options.logging_token` 

359 

360 :param max_identifier_length: integer; override the max_identifier_length 

361 determined by the dialect. if ``None`` or zero, has no effect. This 

362 is the database's configured maximum number of characters that may be 

363 used in a SQL identifier such as a table name, column name, or label 

364 name. All dialects determine this value automatically, however in the 

365 case of a new database version for which this value has changed but 

366 SQLAlchemy's dialect has not been adjusted, the value may be passed 

367 here. 

368 

369 .. seealso:: 

370 

371 :paramref:`_sa.create_engine.label_length` 

372 

373 :param max_overflow=10: the number of connections to allow in 

374 connection pool "overflow", that is connections that can be 

375 opened above and beyond the pool_size setting, which defaults 

376 to five. this is only used with :class:`~sqlalchemy.pool.QueuePool`. 

377 

378 :param module=None: reference to a Python module object (the module 

379 itself, not its string name). Specifies an alternate DBAPI module to 

380 be used by the engine's dialect. Each sub-dialect references a 

381 specific DBAPI which will be imported before first connect. This 

382 parameter causes the import to be bypassed, and the given module to 

383 be used instead. Can be used for testing of DBAPIs as well as to 

384 inject "mock" DBAPI implementations into the :class:`_engine.Engine`. 

385 

386 :param paramstyle=None: The `paramstyle <https://legacy.python.org/dev/peps/pep-0249/#paramstyle>`_ 

387 to use when rendering bound parameters. This style defaults to the 

388 one recommended by the DBAPI itself, which is retrieved from the 

389 ``.paramstyle`` attribute of the DBAPI. However, most DBAPIs accept 

390 more than one paramstyle, and in particular it may be desirable 

391 to change a "named" paramstyle into a "positional" one, or vice versa. 

392 When this attribute is passed, it should be one of the values 

393 ``"qmark"``, ``"numeric"``, ``"named"``, ``"format"`` or 

394 ``"pyformat"``, and should correspond to a parameter style known 

395 to be supported by the DBAPI in use. 

396 

397 :param pool=None: an already-constructed instance of 

398 :class:`~sqlalchemy.pool.Pool`, such as a 

399 :class:`~sqlalchemy.pool.QueuePool` instance. If non-None, this 

400 pool will be used directly as the underlying connection pool 

401 for the engine, bypassing whatever connection parameters are 

402 present in the URL argument. For information on constructing 

403 connection pools manually, see :ref:`pooling_toplevel`. 

404 

405 :param poolclass=None: a :class:`~sqlalchemy.pool.Pool` 

406 subclass, which will be used to create a connection pool 

407 instance using the connection parameters given in the URL. Note 

408 this differs from ``pool`` in that you don't actually 

409 instantiate the pool in this case, you just indicate what type 

410 of pool to be used. 

411 

412 :param pool_logging_name: String identifier which will be used within 

413 the "name" field of logging records generated within the 

414 "sqlalchemy.pool" logger. Defaults to a hexstring of the object's 

415 id. 

416 

417 .. seealso:: 

418 

419 :ref:`dbengine_logging` - further detail on how to configure 

420 logging. 

421 

422 :param pool_pre_ping: boolean, if True will enable the connection pool 

423 "pre-ping" feature that tests connections for liveness upon 

424 each checkout. 

425 

426 .. seealso:: 

427 

428 :ref:`pool_disconnects_pessimistic` 

429 

430 :param pool_size=5: the number of connections to keep open 

431 inside the connection pool. This used with 

432 :class:`~sqlalchemy.pool.QueuePool` as 

433 well as :class:`~sqlalchemy.pool.SingletonThreadPool`. With 

434 :class:`~sqlalchemy.pool.QueuePool`, a ``pool_size`` setting 

435 of 0 indicates no limit; to disable pooling, set ``poolclass`` to 

436 :class:`~sqlalchemy.pool.NullPool` instead. 

437 

438 :param pool_recycle=-1: this setting causes the pool to recycle 

439 connections after the given number of seconds has passed. It 

440 defaults to -1, or no timeout. For example, setting to 3600 

441 means connections will be recycled after one hour. Note that 

442 MySQL in particular will disconnect automatically if no 

443 activity is detected on a connection for eight hours (although 

444 this is configurable with the MySQLDB connection itself and the 

445 server configuration as well). 

446 

447 .. seealso:: 

448 

449 :ref:`pool_setting_recycle` 

450 

451 :param pool_reset_on_return='rollback': set the 

452 :paramref:`_pool.Pool.reset_on_return` parameter of the underlying 

453 :class:`_pool.Pool` object, which can be set to the values 

454 ``"rollback"``, ``"commit"``, or ``None``. 

455 

456 .. seealso:: 

457 

458 :ref:`pool_reset_on_return` 

459 

460 :ref:`dbapi_autocommit_skip_rollback` - a more modern approach 

461 to using connections with no transactional instructions 

462 

463 :param pool_timeout=30: number of seconds to wait before giving 

464 up on getting a connection from the pool. This is only used 

465 with :class:`~sqlalchemy.pool.QueuePool`. This can be a float but is 

466 subject to the limitations of Python time functions which may not be 

467 reliable in the tens of milliseconds. 

468 

469 .. note: don't use 30.0 above, it seems to break with the :param tag 

470 

471 :param pool_use_lifo=False: use LIFO (last-in-first-out) when retrieving 

472 connections from :class:`.QueuePool` instead of FIFO 

473 (first-in-first-out). Using LIFO, a server-side timeout scheme can 

474 reduce the number of connections used during non- peak periods of 

475 use. When planning for server-side timeouts, ensure that a recycle or 

476 pre-ping strategy is in use to gracefully handle stale connections. 

477 

478 .. seealso:: 

479 

480 :ref:`pool_use_lifo` 

481 

482 :ref:`pool_disconnects` 

483 

484 :param plugins: string list of plugin names to load. See 

485 :class:`.CreateEnginePlugin` for background. 

486 

487 :param query_cache_size: size of the cache used to cache the SQL string 

488 form of queries. Set to zero to disable caching. 

489 

490 The cache is pruned of its least recently used items when its size reaches 

491 N * 1.5. Defaults to 500, meaning the cache will always store at least 

492 500 SQL statements when filled, and will grow up to 750 items at which 

493 point it is pruned back down to 500 by removing the 250 least recently 

494 used items. 

495 

496 Caching is accomplished on a per-statement basis by generating a 

497 cache key that represents the statement's structure, then generating 

498 string SQL for the current dialect only if that key is not present 

499 in the cache. All statements support caching, however some features 

500 such as an INSERT with a large set of parameters will intentionally 

501 bypass the cache. SQL logging will indicate statistics for each 

502 statement whether or not it were pull from the cache. 

503 

504 .. note:: some ORM functions related to unit-of-work persistence as well 

505 as some attribute loading strategies will make use of individual 

506 per-mapper caches outside of the main cache. 

507 

508 

509 .. seealso:: 

510 

511 :ref:`sql_caching` 

512 

513 .. versionadded:: 1.4 

514 

515 :param skip_autocommit_rollback: When True, the dialect will 

516 unconditionally skip all calls to the DBAPI ``connection.rollback()`` 

517 method if the DBAPI connection is confirmed to be in "autocommit" mode. 

518 The availability of this feature is dialect specific; if not available, 

519 a ``NotImplementedError`` is raised by the dialect when rollback occurs. 

520 

521 .. seealso:: 

522 

523 :ref:`dbapi_autocommit_skip_rollback` 

524 

525 .. versionadded:: 2.0.43 

526 

527 :param use_insertmanyvalues: True by default, use the "insertmanyvalues" 

528 execution style for INSERT..RETURNING statements by default. 

529 

530 .. versionadded:: 2.0 

531 

532 .. seealso:: 

533 

534 :ref:`engine_insertmanyvalues` 

535 

536 """ # noqa 

537 

538 if "strategy" in kwargs: 

539 strat = kwargs.pop("strategy") 

540 if strat == "mock": 

541 # this case is deprecated 

542 return create_mock_engine(url, **kwargs) # type: ignore 

543 else: 

544 raise exc.ArgumentError("unknown strategy: %r" % strat) 

545 

546 kwargs.pop("empty_in_strategy", None) 

547 

548 # create url.URL object 

549 u = _url.make_url(url) 

550 

551 u, plugins, kwargs = u._instantiate_plugins(kwargs) 

552 

553 entrypoint = u._get_entrypoint() 

554 _is_async = kwargs.pop("_is_async", False) 

555 if _is_async: 

556 dialect_cls = entrypoint.get_async_dialect_cls(u) 

557 else: 

558 dialect_cls = entrypoint.get_dialect_cls(u) 

559 

560 if kwargs.pop("_coerce_config", False): 

561 

562 def pop_kwarg(key: str, default: Optional[Any] = None) -> Any: 

563 value = kwargs.pop(key, default) 

564 if key in dialect_cls.engine_config_types: 

565 value = dialect_cls.engine_config_types[key](value) 

566 return value 

567 

568 else: 

569 pop_kwarg = kwargs.pop # type: ignore 

570 

571 dialect_args = {} 

572 # consume dialect arguments from kwargs 

573 for k in util.get_cls_kwargs(dialect_cls): 

574 if k in kwargs: 

575 dialect_args[k] = pop_kwarg(k) 

576 

577 dbapi = kwargs.pop("module", None) 

578 if dbapi is None: 

579 dbapi_args = {} 

580 

581 if "import_dbapi" in dialect_cls.__dict__: 

582 dbapi_meth = dialect_cls.import_dbapi 

583 

584 elif hasattr(dialect_cls, "dbapi") and inspect.ismethod( 

585 dialect_cls.dbapi 

586 ): 

587 util.warn_deprecated( 

588 "The dbapi() classmethod on dialect classes has been " 

589 "renamed to import_dbapi(). Implement an import_dbapi() " 

590 f"classmethod directly on class {dialect_cls} to remove this " 

591 "warning; the old .dbapi() classmethod may be maintained for " 

592 "backwards compatibility.", 

593 "2.0", 

594 ) 

595 dbapi_meth = dialect_cls.dbapi 

596 else: 

597 dbapi_meth = dialect_cls.import_dbapi 

598 

599 for k in util.get_func_kwargs(dbapi_meth): 

600 if k in kwargs: 

601 dbapi_args[k] = pop_kwarg(k) 

602 dbapi = dbapi_meth(**dbapi_args) 

603 

604 dialect_args["dbapi"] = dbapi 

605 

606 dialect_args.setdefault("compiler_linting", compiler.NO_LINTING) 

607 enable_from_linting = kwargs.pop("enable_from_linting", True) 

608 if enable_from_linting: 

609 dialect_args["compiler_linting"] ^= compiler.COLLECT_CARTESIAN_PRODUCTS 

610 

611 for plugin in plugins: 

612 plugin.handle_dialect_kwargs(dialect_cls, dialect_args) 

613 

614 # create dialect 

615 dialect = dialect_cls(**dialect_args) 

616 

617 # assemble connection arguments 

618 cargs_tup, _cparams = dialect.create_connect_args(u) 

619 cparams = util.immutabledict(_cparams).union(pop_kwarg("connect_args", {})) 

620 

621 # look for existing pool or create 

622 pool = pop_kwarg("pool", None) 

623 if pool is None: 

624 

625 def connect( 

626 connection_record: Optional[ConnectionPoolEntry] = None, 

627 ) -> DBAPIConnection: 

628 if dialect._has_events: 

629 mutable_cargs = list(cargs_tup) 

630 mutable_cparams = dict(cparams) 

631 for fn in dialect.dispatch.do_connect: 

632 connection = cast( 

633 DBAPIConnection, 

634 fn( 

635 dialect, 

636 connection_record, 

637 mutable_cargs, 

638 mutable_cparams, 

639 ), 

640 ) 

641 if connection is not None: 

642 return connection 

643 return dialect.connect(*mutable_cargs, **mutable_cparams) 

644 else: 

645 return dialect.connect(*cargs_tup, **cparams) 

646 

647 creator = pop_kwarg("creator", connect) 

648 

649 poolclass = pop_kwarg("poolclass", None) 

650 if poolclass is None: 

651 poolclass = dialect.get_dialect_pool_class(u) 

652 pool_args = {"dialect": dialect} 

653 

654 # consume pool arguments from kwargs, translating a few of 

655 # the arguments 

656 for k in util.get_cls_kwargs(poolclass): 

657 tk = _pool_translate_kwargs.get(k, k) 

658 if tk in kwargs: 

659 pool_args[k] = pop_kwarg(tk) 

660 

661 for plugin in plugins: 

662 plugin.handle_pool_kwargs(poolclass, pool_args) 

663 

664 pool = poolclass(creator, **pool_args) 

665 else: 

666 pool._dialect = dialect 

667 

668 if ( 

669 hasattr(pool, "_is_asyncio") 

670 and pool._is_asyncio is not dialect.is_async 

671 ): 

672 raise exc.ArgumentError( 

673 f"Pool class {pool.__class__.__name__} cannot be " 

674 f"used with {'non-' if not dialect.is_async else ''}" 

675 "asyncio engine", 

676 code="pcls", 

677 ) 

678 

679 # create engine. 

680 if not pop_kwarg("future", True): 

681 raise exc.ArgumentError( 

682 "The 'future' parameter passed to " 

683 "create_engine() may only be set to True." 

684 ) 

685 

686 engineclass = base.Engine 

687 

688 engine_args = {} 

689 for k in util.get_cls_kwargs(engineclass): 

690 if k in kwargs: 

691 engine_args[k] = pop_kwarg(k) 

692 

693 # internal flags used by the test suite for instrumenting / proxying 

694 # engines with mocks etc. 

695 _initialize = kwargs.pop("_initialize", True) 

696 

697 # all kwargs should be consumed 

698 if kwargs: 

699 raise TypeError( 

700 "Invalid argument(s) %s sent to create_engine(), " 

701 "using configuration %s/%s/%s. Please check that the " 

702 "keyword arguments are appropriate for this combination " 

703 "of components." 

704 % ( 

705 ",".join("'%s'" % k for k in kwargs), 

706 dialect.__class__.__name__, 

707 pool.__class__.__name__, 

708 engineclass.__name__, 

709 ) 

710 ) 

711 

712 engine = engineclass(pool, dialect, u, **engine_args) 

713 

714 if _initialize: 

715 do_on_connect = dialect.on_connect_url(u) 

716 if do_on_connect: 

717 

718 def on_connect( 

719 dbapi_connection: DBAPIConnection, 

720 connection_record: ConnectionPoolEntry, 

721 ) -> None: 

722 assert do_on_connect is not None 

723 do_on_connect(dbapi_connection) 

724 

725 event.listen(pool, "connect", on_connect) 

726 

727 builtin_on_connect = dialect._builtin_onconnect() 

728 if builtin_on_connect: 

729 event.listen(pool, "connect", builtin_on_connect) 

730 

731 def first_connect( 

732 dbapi_connection: DBAPIConnection, 

733 connection_record: ConnectionPoolEntry, 

734 ) -> None: 

735 c = base.Connection( 

736 engine, 

737 connection=_AdhocProxiedConnection( 

738 dbapi_connection, connection_record 

739 ), 

740 _has_events=False, 

741 # reconnecting will be a reentrant condition, so if the 

742 # connection goes away, Connection is then closed 

743 _allow_revalidate=False, 

744 # dont trigger the autobegin sequence 

745 # within the up front dialect checks 

746 _allow_autobegin=False, 

747 ) 

748 c._execution_options = util.EMPTY_DICT 

749 

750 try: 

751 dialect.initialize(c) 

752 finally: 

753 # note that "invalidated" and "closed" are mutually 

754 # exclusive in 1.4 Connection. 

755 if not c.invalidated and not c.closed: 

756 # transaction is rolled back otherwise, tested by 

757 # test/dialect/postgresql/test_dialect.py 

758 # ::MiscBackendTest::test_initial_transaction_state 

759 dialect.do_rollback(c.connection) 

760 

761 # previously, the "first_connect" event was used here, which was then 

762 # scaled back if the "on_connect" handler were present. now, 

763 # since "on_connect" is virtually always present, just use 

764 # "connect" event with once_unless_exception in all cases so that 

765 # the connection event flow is consistent in all cases. 

766 event.listen( 

767 pool, "connect", first_connect, _once_unless_exception=True 

768 ) 

769 

770 dialect_cls.engine_created(engine) 

771 if entrypoint is not dialect_cls: 

772 entrypoint.engine_created(engine) 

773 

774 for plugin in plugins: 

775 plugin.engine_created(engine) 

776 

777 return engine 

778 

779 

780def engine_from_config( 

781 configuration: Dict[str, Any], prefix: str = "sqlalchemy.", **kwargs: Any 

782) -> Engine: 

783 """Create a new Engine instance using a configuration dictionary. 

784 

785 The dictionary is typically produced from a config file. 

786 

787 The keys of interest to ``engine_from_config()`` should be prefixed, e.g. 

788 ``sqlalchemy.url``, ``sqlalchemy.echo``, etc. The 'prefix' argument 

789 indicates the prefix to be searched for. Each matching key (after the 

790 prefix is stripped) is treated as though it were the corresponding keyword 

791 argument to a :func:`_sa.create_engine` call. 

792 

793 The only required key is (assuming the default prefix) ``sqlalchemy.url``, 

794 which provides the :ref:`database URL <database_urls>`. 

795 

796 A select set of keyword arguments will be "coerced" to their 

797 expected type based on string values. The set of arguments 

798 is extensible per-dialect using the ``engine_config_types`` accessor. 

799 

800 :param configuration: A dictionary (typically produced from a config file, 

801 but this is not a requirement). Items whose keys start with the value 

802 of 'prefix' will have that prefix stripped, and will then be passed to 

803 :func:`_sa.create_engine`. 

804 

805 :param prefix: Prefix to match and then strip from keys 

806 in 'configuration'. 

807 

808 :param kwargs: Each keyword argument to ``engine_from_config()`` itself 

809 overrides the corresponding item taken from the 'configuration' 

810 dictionary. Keyword arguments should *not* be prefixed. 

811 

812 """ 

813 

814 options = { 

815 key[len(prefix) :]: configuration[key] 

816 for key in configuration 

817 if key.startswith(prefix) 

818 } 

819 options["_coerce_config"] = True 

820 options.update(kwargs) 

821 url = options.pop("url") 

822 return create_engine(url, **options) 

823 

824 

825@overload 

826def create_pool_from_url( 

827 url: Union[str, URL], 

828 *, 

829 poolclass: Optional[Type[Pool]] = ..., 

830 logging_name: str = ..., 

831 pre_ping: bool = ..., 

832 size: int = ..., 

833 recycle: int = ..., 

834 reset_on_return: Optional[_ResetStyleArgType] = ..., 

835 timeout: float = ..., 

836 use_lifo: bool = ..., 

837 **kwargs: Any, 

838) -> Pool: ... 

839 

840 

841@overload 

842def create_pool_from_url(url: Union[str, URL], **kwargs: Any) -> Pool: ... 

843 

844 

845def create_pool_from_url(url: Union[str, URL], **kwargs: Any) -> Pool: 

846 """Create a pool instance from the given url. 

847 

848 If ``poolclass`` is not provided the pool class used 

849 is selected using the dialect specified in the URL. 

850 

851 The arguments passed to :func:`_sa.create_pool_from_url` are 

852 identical to the pool argument passed to the :func:`_sa.create_engine` 

853 function. 

854 

855 .. versionadded:: 2.0.10 

856 """ 

857 

858 for key in _pool_translate_kwargs: 

859 if key in kwargs: 

860 kwargs[_pool_translate_kwargs[key]] = kwargs.pop(key) 

861 

862 engine = create_engine(url, **kwargs, _initialize=False) 

863 return engine.pool 

864 

865 

866_pool_translate_kwargs = immutabledict( 

867 { 

868 "logging_name": "pool_logging_name", 

869 "echo": "echo_pool", 

870 "timeout": "pool_timeout", 

871 "recycle": "pool_recycle", 

872 "events": "pool_events", # deprecated 

873 "reset_on_return": "pool_reset_on_return", 

874 "pre_ping": "pool_pre_ping", 

875 "use_lifo": "pool_use_lifo", 

876 } 

877)