summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/session.py
Commit message (Collapse)AuthorAgeFilesLines
* add full parameter types for ORM with_for_updateMike Bayer2023-05-101-3/+4
| | | | | | | | | | Fixed typing for the :paramref:`_orm.Session.get.with_for_update` parameter of :meth:`_orm.Session.get` and :meth:`_orm.Session.refresh` (as well as corresponding methods on :class:`_asyncio.AsyncSession`) to accept boolean ``True`` and all other argument forms accepted by the parameter at runtime. Fixes: #9762 Change-Id: Ied4d37a269906b3d9be5ab7d31a2fa863360cced
* dont assume _compile_options are presentMike Bayer2023-04-171-1/+5
| | | | | | | | | | | | Fixed bug where various ORM-specific getters such as :attr:`.ORMExecuteState.is_column_load`, :attr:`.ORMExecuteState.is_relationship_load`, :attr:`.ORMExecuteState.loader_strategy_path` etc. would throw an ``AttributeError`` if the SQL statement itself were a "compound select" such as a UNION. Fixes: #9634 Change-Id: Ia37df5d6f89d6534d69237dcab294bd849ece28b
* Remove old versionadded and versionchangedFederico Caselli2023-04-121-6/+0
| | | | | | | Removed versionadded and versionchanged for version prior to 1.2 since they are no longer useful. Change-Id: I5c53d1188bc5fec3ab4be39ef761650ed8fa6d3e
* Merge "Improve orm event docs" into mainmike bayer2023-02-281-2/+2
|\
| * Improve orm event docsFederico Caselli2023-02-271-2/+2
| | | | | | | | Change-Id: Ia4f8ce497565c9d5e8df4ef7cc3c3e645f995ff3
* | Add separate version notes for scalarsGrey Li2023-02-261-1/+3
|/ | | | | | | | | | | | | | | | | | | Add separate 1.4.24 and 1.4.26 version notes for the .scalars method; this covers Session, scoped_session, AsyncSession, async_scoped_session as the "scoped" versions did not have the method added until 1.4.26 as part of :ticket:`7103`. Also indicate scoped_session as ``sqlalchemy.orm.scoped_session`` in docs rather than ``sqlalchemy.orm.scoping.scoped_session``. This is also happening in I77da54891860095edcb1f0625ead99fee89bd76f separately, as both changesets refer to scoped_session without using ".scoping". References: #7103 Closes: #9371 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/9371 Pull-request-sha: 61132230cc6e897ab61beff25d98b19a4c0aefd0 Change-Id: I84c8b1aad752db124cfee6bc8516f6eed7ba2faf
* immediateload lazy relationships named in refresh.attribute_namesMike Bayer2023-02-161-2/+15
| | | | | | | | | | | | | | | | | | The :meth:`_orm.Session.refresh` method will now immediately load a relationship-bound attribute that is explicitly named within the :paramref:`_orm.Session.refresh.attribute_names` collection even if it is currently linked to the "select" loader, which normally is a "lazy" loader that does not fire off during a refresh. The "lazy loader" strategy will now detect that the operation is specifically a user-initiated :meth:`_orm.Session.refresh` operation which named this attribute explicitly, and will then call upon the "immediateload" strategy to actually emit SQL to load the attribute. This should be helpful in particular for some asyncio situations where the loading of an unloaded lazy-loaded attribute must be forced, without using the actual lazy-loading attribute pattern not supported in asyncio. Fixes: #9298 Change-Id: I9b50f339bdf06cdb2ec98f8e5efca2b690895dd7
* Merge "add context for warnings emitted from configure_mappers(), ↵mike bayer2023-01-261-0/+6
|\ | | | | | | autoflush()" into main
| * add context for warnings emitted from configure_mappers(), autoflush()jonathan vanasco2023-01-241-0/+6
| | | | | | | | | | | | | | | | | | | | | | Improved the notification of warnings that are emitted within the configure mappers or flush process, which are often invoked as part of a different operation, to add additional context to the message that indicates one of these operations as the source of the warning within operations that may not be obviously related. Fixes: #7305 Change-Id: I79da7a6a5d4cf67d57615d0ffc2b8d8454011c84
* | add set_shard_id() loader option for horizontal shardMike Bayer2023-01-251-0/+9
|/ | | | | | | | | | | | | | Added new option to horizontal sharding API :class:`_horizontal.set_shard_id` which sets the effective shard identifier to query against, for both the primary query as well as for all secondary loaders including relationship eager loaders as well as relationship and column lazy loaders. Modernize sharding examples with new-style mappings, add new asyncio example. Fixes: #7226 Fixes: #7028 Change-Id: Ie69248060c305e8de04f75a529949777944ad511
* accept TableClause through mapped selectable chainMike Bayer2023-01-091-3/+4
| | | | | | | | | | | | | | type annotation somehow decided that TableClause doesn't have primary key fields which is not the case at all. In particular the "views" recipe relies on TableClause so adding a restriction like this does not make any sense. It seems the issue was to open this up for typing, by allowing TableClause out as far as ddl.sort_tables() typing is passing for now. Support it out in get_bind() etc. Fixes: #9071 Change-Id: If0e22e0e7df7bee0ff4b295b0ffacfbc6b7a0142
* happy new year 2023Mike Bayer2023-01-031-1/+1
| | | | Change-Id: I625af65b3fb1815b1af17dc2ef47dd697fdc3fb1
* rename 2.0.0b5 to 2.0.0rc1Mike Bayer2022-12-271-2/+2
| | | | | | it's hoped for 2.0.0 final to be next, in early January Change-Id: If4285f0929f4a2895f2bc93d9e8336599b973bcf
* establish explicit join transaction modesMike Bayer2022-12-271-16/+133
| | | | | | | | | | | | | | | | | | | | | | | | The behavior of "joining an external transaction into a Session" has been revised and improved, allowing explicit control over how the :class:`_orm.Session` will accommodate an incoming :class:`_engine.Connection` that already has a transaction and possibly a savepoint already established. The new parameter :paramref:`_orm.Session.join_transaction_mode` includes a series of option values which can accommodate the existing transaction in several ways, most importantly allowing a :class:`_orm.Session` to operate in a fully transactional style using savepoints exclusively, while leaving the externally initiated transaction non-committed and active under all circumstances, allowing test suites to rollback all changes that take place within tests. Additionally, revised the :meth:`_orm.Session.close` method to fully close out savepoints that may still be present, which also allows the "external transaction" recipe to proceed without warnings if the :class:`_orm.Session` did not explicitly end its own SAVEPOINT transactions. Fixes: #9015 Change-Id: I31c22ee0fd9372fa0eddfe057e76544aee627107
* reorganize pre_session_exec around do_orm_executeMike Bayer2022-12-261-24/+62
| | | | | | | | | | | | | | | | | | | | | | | | | | | Allow do_orm_execute() events to both receive the complete state of bind_argments, load_options, update_delete_options as they do already, but also allow them to *change* all those things via new execution options. Options like autoflush, populate_existing etc. can now be updated within a do_orm_execute() hook and those changes will take effect all the way through. Took a few tries to get something that covers every case here, in particular horizontal sharding which is consuming those options as well as using context.invoke(), without excess complexity. The good news seems to be that a simple reorg and replacing the "reentrant" boolean with "is this before do_orm_execute is invoked" was all that was needed. As part of this we add a new "identity_token" option allowing this option to be controlled from do_orm_execute() as well as from the outside. WIP Fixes: #7837 Change-Id: I087728215edec8d1b1712322ab389e3f52ff76ba
* include pk cols in refresh() if relationships are requestedMike Bayer2022-12-181-0/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A series of changes and improvements regarding :meth:`_orm.Session.refresh`. The overall change is that primary key attributes for an object are now included in a refresh operation unconditionally when relationship-bound attributes are to be refreshed, even if not expired and even if not specified in the refresh. * Improved :meth:`_orm.Session.refresh` so that if autoflush is enabled (as is the default for :class:`_orm.Session`), the autoflush takes place at an earlier part of the refresh process so that pending primary key changes are applied without errors being raised. Previously, this autoflush took place too late in the process and the SELECT statement would not use the correct key to locate the row and an :class:`.InvalidRequestError` would be raised. * When the above condition is present, that is, unflushed primary key changes are present on the object, but autoflush is not enabled, the refresh() method now explicitly disallows the operation to proceed, and an informative :class:`.InvalidRequestError` is raised asking that the pending primary key changes be flushed first. Previously, this use case was simply broken and :class:`.InvalidRequestError` would be raised anyway. This restriction is so that it's safe for the primary key attributes to be refreshed, as is necessary for the case of being able to refresh the object with relationship-bound secondary eagerloaders also being emitted. This rule applies in all cases to keep API behavior consistent regardless of whether or not the PK cols are actually needed in the refresh, as it is unusual to be refreshing some attributes on an object while keeping other attributes "pending" in any case. * The :meth:`_orm.Session.refresh` method has been enhanced such that attributes which are :func:`_orm.relationship`-bound and linked to an eager loader, either at mapping time or via last-used loader options, will be refreshed in all cases even when a list of attributes is passed that does not include any columns on the parent row. This builds upon the feature first implemented for non-column attributes as part of :ticket:`1763` fixed in 1.4 allowing eagerly-loaded relationship-bound attributes to participate in the :meth:`_orm.Session.refresh` operation. If the refresh operation does not indicate any columns on the parent row to be refreshed, the primary key columns will nonetheless be included in the refresh operation, which allows the load to proceed into the secondary relationship loaders indicated as it does normally. Previously an :class:`.InvalidRequestError` error would be raised for this condition (:ticket:`8703`) * Fixed issue where an unnecessary additional SELECT would be emitted in the case where :meth:`_orm.Session.refresh` were called with a combination of expired attributes, as well as an eager loader such as :func:`_orm.selectinload` that emits a "secondary" query, if the primary key attributes were also in an expired state. As the primary key attributes are now included in the refresh automatically, there is no additional load for these attributes when a relationship loader goes to select for them (:ticket:`8997`) * Fixed regression caused by :ticket:`8126` released in 2.0.0b1 where the :meth:`_orm.Session.refresh` method would fail with an ``AttributeError``, if passed both an expired column name as well as the name of a relationship-bound attribute that was linked to a "secondary" eagerloader such as the :func:`_orm.selectinload` eager loader (:ticket:`8996`) Fixes: #8703 Fixes: #8996 Fixes: #8997 Fixes: #8126 Change-Id: I88dcbc0a9a8337f6af0bc4bcc5b0261819acd1c4
* Type annotations for sqlalchemy.ext.horizontal_shardGleb Kisenkov2022-12-111-1/+2
| | | | | | | | | | | The horizontal sharding extension is now pep-484 typed. Thanks to Gleb Kisenkov for their efforts on this. Closes: #8948 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/8948 Pull-request-sha: e40e768492685aa9ce57c4762c571f935e3fd3c7 Change-Id: I2374e174c9433846c453c20a37ec5e5584fd3b31
* Fix inferred type of async_sessionmakerSam Bull2022-11-211-0/+27
| | | | | | | | | | | | | | | | | | | | | | | Improved the typing for :class:`.sessionmaker` and :class:`.asyncsessionmaker`, so that the default type of their return value will be :class:`.Session` or :class:`.AsyncSession`, without the need to type this explicitly. Previously, Mypy would not automaticaly infer these return types from its generic base. As part of this change, arguments for :class:`.Session`, :class:`.AsyncSession`, :class:`.sessionmaker` and :class:`.asyncsessionmaker` beyond the initial "bind" argument have been made keyword-only, which includes parameters that have always been documented as keyword arguments, such as :paramref:`.Session.autoflush`, :paramref:`.Session.class_`, etc. Pull request courtesy Sam Bull. Closes: #8842 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/8842 Pull-request-sha: fa6d1a8468e98b40e12f82ed7ddaddc1fde060ac Change-Id: Iaaabc4572a87489d61617d970f62b9b50db4fac7
* resolve synonyms in dictionary form of Session.get()Mike Bayer2022-11-041-1/+16
| | | | | | | | | Improved "dictionary mode" for :meth:`_orm.Session.get` so that synonym names which refer to primary key attribute names may be indicated in the named dictionary. Fixes: #8753 Change-Id: I56112564a5c23b51b26e01c64087cbf4399cd951
* Improve typings of execution optionsFederico Caselli2022-11-021-16/+16
| | | | | Fixes: #8605 Change-Id: I4aec83b9f321462427c3f4ac941c3b272255c088
* implement autobegin=False optionMike Bayer2022-10-111-47/+119
| | | | | | | | | | | | | | | | | | Added new parameter :paramref:`_orm.Session.autobegin`, which when set to ``False`` will prevent the :class:`_orm.Session` from beginning a transaction implicitly. The :meth:`_orm.Session.begin` method must be called explicitly first in order to proceed with operations, otherwise an error is raised whenever any operation would otherwise have begun automatically. This option can be used to create a "safe" :class:`_orm.Session` that won't implicitly start new transactions. As part of this change, also added a new status variable :class:`_orm.SessionTransaction.origin` which may be useful for event handling code to be aware of the origin of a particular :class:`_orm.SessionTransaction`. Fixes: #6928 Change-Id: I246f895c4a475bff352216e5bc74b6a25e6a4ae7
* Merge "doc edits" into mainmike bayer2022-10-111-0/+5
|\
| * doc editsMike Bayer2022-10-101-0/+5
| | | | | | | | | | | | | | | | | | this is addressing comments still remaining on I9929daab7797be9515f71c888b28af1209e789ff removes "asyncio" wording discussed in #7659 Change-Id: I1bab2a6fde330b83ef34602956c2988ee6331b21
* | dont mutate bind_arguments incoming dictionaryMike Bayer2022-10-071-0/+2
|/ | | | | | | | | | | | | | | The :paramref:`_orm.Session.execute.bind_arguments` dictionary is no longer mutated when passed to :meth:`_orm.Session.execute` and similar; instead, it's copied to an internal dictionary for state changes. Among other things, this fixes and issue where the "clause" passed to the :meth:`_orm.Session.get_bind` method would be incorrectly referring to the :class:`_sql.Select` construct used for the "fetch" synchronization strategy, when the actual query being emitted was a :class:`_dml.Delete` or :class:`_dml.Update`. This would interfere with recipes for "routing sessions". Fixes: #8614 Change-Id: I8d237449485c9bbf41db2b29a34b6136aa43b7bc
* the future is hereMike Bayer2022-10-021-1/+1
| | | | | | | | | the autodoc for the "future" Engine / Connection were removed, so all these links weren't working. Replace all _future for these with _engine. There was just one _future pointing to select, changed that separately. Change-Id: Ib28270d8da8616b533953204e22eabee9388d620
* add autobuild; improve a few session docsMike Bayer2022-09-301-7/+48
| | | | | | | this is from the writeonly patch, some doc edits became more general so will backport these to 1.4. Change-Id: I19231e4bcfa33a0742c8995b6059c9a9488b1a6f
* New ORM Query Guide featuring DML supportMike Bayer2022-09-251-76/+30
| | | | | | | | | | | | | | | | | reviewers: these docs publish periodically at: https://docs.sqlalchemy.org/en/gerrit/4042/orm/queryguide/index.html See the "last generated" timestamp near the bottom of the page to ensure the latest version is up Change includes some other adjustments: * small typing fixes for end-user benefit * removal of a bunch of old examples for patterns that nobody uses or aren't really what we promote now * modernization of some examples, including inheritance Change-Id: I9929daab7797be9515f71c888b28af1209e789ff
* ORM bulk insert via executeMike Bayer2022-09-241-12/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * ORM Insert now includes "bulk" mode that will run essentially the same process as session.bulk_insert_mappings; interprets the given list of values as ORM attributes for key names * ORM UPDATE has a similar feature, without RETURNING support, for session.bulk_update_mappings * Added support for upserts to do RETURNING ORM objects as well * ORM UPDATE/DELETE with list of parameters + WHERE criteria is a not implemented; use connection * ORM UPDATE/DELETE defaults to "auto" synchronize_session; use fetch if RETURNING is present, evaluate if not, as "fetch" is much more efficient (no expired object SELECT problem) and less error prone if RETURNING is available UPDATE: howver this is inefficient! please continue to use evaluate for simple cases, auto can move to fetch if criteria not evaluable * "Evaluate" criteria will now not preemptively unexpire and SELECT attributes that were individually expired. Instead, if evaluation of the criteria indicates that the necessary attrs were expired, we expire the object completely (delete) or expire the SET attrs unconditionally (update). This keeps the object in the same unloaded state where it will refresh those attrs on the next pass, for this generally unusual case. (originally #5664) * Core change! update/delete rowcount comes from len(rows) if RETURNING was used. SQLite at least otherwise did not support this. adjusted test_rowcount accordingly * ORM DELETE with a list of parameters at all is also a not implemented as this would imply "bulk", and there is no bulk_delete_mappings (could be, but we dont have that) * ORM insert().values() with single or multi-values translates key names based on ORM attribute names * ORM returning() implemented for insert, update, delete; explcit returning clauses now interpret rows in an ORM context, with support for qualifying loader options as well * session.bulk_insert_mappings() assigns polymorphic identity if not set. * explicit RETURNING + synchronize_session='fetch' is now supported with UPDATE and DELETE. * expanded return_defaults() to work with DELETE also. * added support for composite attributes to be present in the dictionaries used by bulk_insert_mappings and bulk_update_mappings, which is also the new ORM bulk insert/update feature, that will expand the composite values into their individual mapped attributes the way they'd be on a mapped instance. * bulk UPDATE supports "synchronize_session=evaluate", is the default. this does not apply to session.bulk_update_mappings, just the new version * both bulk UPDATE and bulk INSERT, the latter with or without RETURNING, support *heterogenous* parameter sets. session.bulk_insert/update_mappings did this, so this feature is maintained. now cursor result can be both horizontally and vertically spliced :) This is now a long story with a lot of options, which in itself is a problem to be able to document all of this in some way that makes sense. raising exceptions for use cases we haven't supported is pretty important here too, the tradition of letting unsupported things just not work is likely not a good idea at this point, though there are still many cases that aren't easily avoidable Fixes: #8360 Fixes: #7864 Fixes: #7865 Change-Id: Idf28379f8705e403a3c6a937f6a798a042ef2540
* implement batched INSERT..VALUES () () for executemanyMike Bayer2022-09-241-43/+12
| | | | | | | | | | | | | | | | | | | | the feature is enabled for all built in backends when RETURNING is used, except for Oracle that doesn't need it, and on psycopg2 and mssql+pyodbc it is used for all INSERT statements, not just those that use RETURNING. third party dialects would need to opt in to the new feature by setting use_insertmanyvalues to True. Also adds dialect-level guards against using returning with executemany where we dont have an implementation to suit it. execute single w/ returning still defers to the server without us checking. Fixes: #6047 Fixes: #7907 Change-Id: I3936d3c00003f02e322f2e43fb949d0e6e568304
* implement event for merge/load=False for mutable state setupMike Bayer2022-08-301-0/+3
| | | | | | | | | | | | | Fixed issue in :mod:`sqlalchemy.ext.mutable` extension where collection links to the parent object would be lost if the object were merged with :meth:`.Session.merge` while also passing :paramref:`.Session.merge.load` as False. The event added here is currently private for expediency, but is acceptable to become a public event at some point. Fixes: #8446 Change-Id: I9e5b9f1f5a0c5a9781f51635d5e57b1134c9e866
* reorg bulk persistence into a separate moduleMike Bayer2022-08-111-6/+6
| | | | | | | | | | | | This restores persistence.py to only functions that are used by unitofwork.py, and all the "bulk" stuff gets its own module bulk_persistence.py. Also fixes up the ORM context class hierarchy for bulk. This is all ahead of the ORM-insert changes coming in, so that the later review can be about logic and not about reorganization. Change-Id: I035896e9e77fcece866d246edf30097cccad0182
* doc fixesMike Bayer2022-08-101-0/+53
| | | | | | | | | | | | | | | | | * fixed erroneous use of mapped_column() in m2m relationship Table * Fill in full imports for some relationship examples that had partial imports; examples that have no imports, leave empty for now * converted joined/single inh mappings to annotated style * We have a problem with @declared_attr in that the error message is wrong if the mapped_column() returned doesnt have a type, and/or mapped_column() with @declared_attr doesnt use the annotation * fix thing where sphinx with undoc-members global setting seems to no longer tolerate ":attribute:" entries in autodoc classes, which is fine we can document the annotations now * Fix mapper params in inheritance to be on Mapper * add missing changelog file for instances remove Change-Id: I9b70b25a320d8122fade68bc4d1f82f8b72b26f3
* typing adjustments for compositesMike Bayer2022-06-141-2/+10
| | | | | | | | | * if dataclass isn't used, columns have to be named * _CompositeClassProto is not useful as dataclasses have no methods / bases we can use, so composite is against Any * Adjust session.get() feature to work w/ dataclass composites Change-Id: Icc606cc76871c738dc794ea4555fca8a1ab0e0fd
* establish sessionmaker and async_sessionmaker as genericMike Bayer2022-05-311-7/+11
| | | | | | | | | | | This is so that custom Session and AsyncSession classes can be typed for these factories. Added appropriate typevars to `__call__()`, `__enter__()` and other methods so that a custom Session or AsyncSession subclass is carried through. Fixes: #7656 Change-Id: Ia2b8c1f22b4410db26005c3285f6ba3d13d7f0e0
* revenge of pep 484Mike Bayer2022-05-151-3/+4
| | | | | | trying to get remaining must-haves for ORM Change-Id: I66a3ecbbb8e5ba37c818c8a92737b576ecf012f7
* update for flake8-future-imports 0.0.5Mike Bayer2022-05-141-4/+0
| | | | | | | | a whole bunch of errors were apparently blocked by 0.0.4 being installed. Fixes: #8020 Change-Id: I22a0faeaabe03de501897893391946d677c2df7e
* more expire_on_commit remindersMike Bayer2022-05-131-2/+18
| | | | | | | | | | | | the session commit/close docs still feel awkward in how one learns about this operation. hopefully another pass over 2.0 can make things more linear. removed a 1.4 note about autobegin that was completely inaccurate; commit() does autobegin so it has an effect, just not usually on the database. Change-Id: Iaa4b96bd3df6cf82e851b2943322ddad7abbbac0
* inline mypy config; files ignoring type errors for the momentMike Bayer2022-04-281-0/+1
| | | | | | | | | | | | | | | | | | | to simplify pyproject.toml change the remaining files that aren't going to be typed on this first pass (unless of course someone wants to type some of these) to include # mypy: ignore-errors. for the moment, only a handful of ORM modules are to have more type checking implemented. It's important that ignore-errors is used and not "# type: ignore", as in the latter case, mypy doesn't even read the existing types in the file, which makes it impossible to type any files that refer to those modules at all. to simplify ongoing typing work use inline mypy config for remaining files that are "done" for now, indicating the level of type checking they currently have. Change-Id: I98669c1a305c2f0adba85d10b5425541f3fe9533
* pep484 ORM / SQL result supportMike Bayer2022-04-271-11/+200
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | after some experimentation it seems mypy is more amenable to the generic types being fully integrated rather than having separate spin-off types. so key structures like Result, Row, Select become generic. For DML Insert, Update, Delete, these are spun into type-specific subclasses ReturningInsert, ReturningUpdate, ReturningDelete, which is fine since the "row-ness" of these constructs doesn't happen until returning() is called in any case. a Tuple based model is then integrated so that these objects can carry along information about their return types. Overloads at the .execute() level carry through the Tuple from the invoked object to the result. To suit the issue of AliasedClass generating attributes that are dynamic, experimented with a custom subclass AsAliased, but then just settled on having aliased() lie to the type checker and return `Type[_O]`, essentially. will need some type-related accessors for with_polymorphic() also. Additionally, identified an issue in Update when used "mysql style" against a join(), it basically doesn't work if asked to UPDATE two tables on the same column name. added an error message to the specific condition where it happens with a very non-specific error message that we hit a thing we can't do right now, suggest multi-table update as a possible cause. Change-Id: I5eff7eefe1d6166ee74160b2785c5e6a81fa8b95
* pep-484: ORM public API, constructorsMike Bayer2022-04-201-5/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | for the moment, abandoning using @overload with relationship() and mapped_column(). The overloads are very difficult to get working at all, and the overloads that were there all wouldn't pass on mypy. various techniques of getting them to "work", meaning having right hand side dictate what's legal on the left, have mixed success and wont give consistent results; additionally, it's legal to have Optional / non-optional independent of nullable in any case for columns. relationship cases are less ambiguous but mypy was not going along with things. we have a comprehensive system of allowing left side annotations to drive the right side, in the absense of explicit settings on the right. so type-centric SQLAlchemy will be left-side driven just like dataclasses, and the various flags and switches on the right side will just not be needed very much. in other matters, one surprise, forgot to remove string support from orm.join(A, B, "somename") or do deprecations for it in 1.4. This is a really not-directly-used structure barely mentioned in the docs for many years, the example shows a relationship being used, not a string, so we will just change it to raise the usual error here. Change-Id: Iefbbb8d34548b538023890ab8b7c9a5d9496ec6e
* pep484: schema APIMike Bayer2022-04-151-63/+130
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | implement strict typing for schema.py this module has lots of public API, lots of old decisions and very hard to follow construction sequences in many cases, and is also where we get a lot of new feature requests, so strict typing should help keep things clean. among improvements here, fixed the pool .info getters and also figured out how to get ColumnCollection and related to be covariant so that we may set them up as returning Column or ColumnClause without any conflicts. DDL was affected, noting that superclasses of DDLElement (_DDLCompiles, added recently) can now be passed into "ddl_if" callables; reorganized ddl into ExecutableDDLElement as a new name for DDLElement and _DDLCompiles renamed to BaseDDLElement. setting up strict also located an API use case that is completely broken, which is connection.execute(some_default) returns a scalar value. This case has been deprecated and new paths have been set up so that connection.scalar() may be used. This likely wasn't possible in previous versions because scalar() would assume a CursorResult. The scalar() change also impacts Session as we have explicit support (since someone had reported it as a regression) for session.execute(Sequence()) to work. They will get the same deprecation message (which omits the word "Connection", just uses ".execute()" and ".scalar()") and they can then use Session.scalar() as well. Getting this to type correctly while still supporting ORM use cases required some refactoring, and I also set up a keyword only delimeter for Session.execute() and related as execution_options / bind_arguments should always be keyword only, applied these changes to AsyncSession as well. Additionally simpify Table __init__ now that we are Python 3 only, we can have positional plus explicit kwargs finally. Simplify Column.__init__ as well again taking advantage of kw only arguments. Fill in most/all __init__ methods in sqltypes.py as the constructor for types is most of the API. should likely do this for dialect-specific types as well. Apply _InfoType for all info attributes as should have been done originally and update descriptor decorators. Change-Id: I3f9f8ff3f1c8858471ff4545ac83d68c88107527
* pep-484: asyncioMike Bayer2022-04-111-12/+14
| | | | | | | | | | | | | | | | | | | | | in this patch the asyncio/events.py module, which existed only to raise errors when trying to attach event listeners, is removed, as we were already coding an asyncio-specific workaround in upstream Pool / Session to raise this error, just moved the error out to the target and did the same thing for Engine. We also add an async_sessionmaker class. The initial rationale here is because sessionmaker() is hardcoded to Session subclasses, and there's not a way to get the use case of sessionmaker(class_=AsyncSession) to type correctly without changing the sessionmaker() symbol itself to be a function and not a class, which gets too complicated for what this is. Additionally, _SessionClassMethods has only three methods on it, one of which is not usable with asyncio (close_all()), the others not generally used from the session class. Change-Id: I064a5fa5d91cc8d5bbe9597437536e37b4e801fe
* pep-484: session, instancestate, etcMike Bayer2022-04-121-363/+573
| | | | | | | | Also adds some fixes to annotation-based mapping that have come up, as well as starts to add more pep-484 test cases Change-Id: Ia722bbbc7967a11b23b66c8084eb61df9d233fee
* use code generation for scoped_sessionMike Bayer2022-04-121-4/+2
| | | | | | | | | | | | | | | | | | | our decorator thing generates code in any case, so point it at the file itself to generate real code for the blocks rather than doing things dynamically. this will allow typing tools to have no problem whatsoever and we also reduce import time overhead. file size will be a lot bigger though, shrugs. syntax / dupe method / etc. checking will be accomplished by our existing linting / typing / formatting tools. As we are also using "from __future__ import annotations", we also no longer have to apply quotes to generated annotations. Change-Id: I20962cb65bda63ff0fb67357ab346e9b1ef4f108
* clarify autoflush setting does not apply to commitMike Bayer2022-04-081-0/+9
| | | | | Change-Id: Icad0f3bd071422b8d1af204c9a1193a9ce6124ba References: #7916
* pep-484: the pep-484ening, SQL part threeMike Bayer2022-03-301-2/+2
| | | | | | | | | | | | | | | hitting DML which is causing us to open up the ColumnCollection structure a bit, as we do put anonymous column expressions with None here. However, we still want Table /TableClause to have named column collections that don't return None, so parametrize the "key" in this collection also. * rename some "immutable" elements to "readonly". we change the contents of immutablecolumncollection underneath, so it's not "immutable" Change-Id: I2593995a4e5c6eae874bed5bf76117198be8ae97
* pep-484 for sqlalchemy.event; use future annotationsMike Bayer2022-02-151-0/+2
| | | | | | | | | | __future__.annotations mode allows us to use non-string annotations for argument and return types in most cases, but more importantly it removes a large amount of runtime overhead that would be spent in evaluating the annotations. Change-Id: I2f5b6126fe0019713fc50001be3627b664019ede References: #6810
* establish mypy / typing approach for v2.0Mike Bayer2022-02-131-34/+137
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | large patch to get ORM / typing efforts started. this is to support adding new test cases to mypy, support dropping sqlalchemy2-stubs entirely from the test suite, validate major ORM typing reorganization to eliminate the need for the mypy plugin. * New declarative approach which uses annotation introspection, fixes: #7535 * Mapped[] is now at the base of all ORM constructs that find themselves in classes, to support direct typing without plugins * Mypy plugin updated for new typing structures * Mypy test suite broken out into "plugin" tests vs. "plain" tests, and enhanced to better support test structures where we assert that various objects are introspected by the type checker as we expect. as we go forward with typing, we will add new use cases to "plain" where we can assert that types are introspected as we expect. * For typing support, users will be much more exposed to the class names of things. Add these all to "sqlalchemy" import space. * Column(ForeignKey()) no longer needs to be `@declared_attr` if the FK refers to a remote table * composite() attributes mapped to a dataclass no longer need to implement a `__composite_values__()` method * with_variant() accepts multiple dialect names Change-Id: I22797c0be73a8fbbd2d6f5e0c0b7258b17fe145d Fixes: #7535 Fixes: #7551 References: #6810
* repair mapper sortMike Bayer2022-01-201-5/+15
| | | | | | | | | | | | | | | | Fixed issue in :meth:`_orm.Session.bulk_save_mappings` where the sorting that takes place when the ``preserve_order`` parameter is set to False would sort partially on ``Mapper`` objects, which is rejected in Python 3.11. Also uses typing_extensions for NotRequired as this symbol does not seem to be in Python 3.11.0a4 yet. For interim 3.11 support, adds the git main build of greenlet for Python 3.11 Fixes: #7591 Change-Id: I24a62f2322ad7dac5d8e4a00853f8a9408877c9c
* happy new year 2022Mike Bayer2022-01-061-1/+1
| | | | Change-Id: I49abf2607e0eb0623650efdf0091b1fb3db737ea