summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-01-20 09:31:42 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-01-20 14:46:09 -0500
commit769dc1d2cb217c66918bec01718aa657a0239040 (patch)
tree6e61ced520057bdfea5154b07277379b7de9077e /lib/sqlalchemy
parent5677ea7f1b8de3cba5c8c0fbf70e3840a5a9889f (diff)
downloadsqlalchemy-769dc1d2cb217c66918bec01718aa657a0239040.tar.gz
repair mapper sort
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
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/session.py20
-rw-r--r--lib/sqlalchemy/util/typing.py7
2 files changed, 17 insertions, 10 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index aa642e65e..cf47ee729 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -3389,14 +3389,24 @@ class Session(_SessionClassMethods):
"""
- def key(state):
- return (state.mapper, state.key is not None)
-
obj_states = (attributes.instance_state(obj) for obj in objects)
+
if not preserve_order:
- obj_states = sorted(obj_states, key=key)
+ # the purpose of this sort is just so that common mappers
+ # and persistence states are grouped together, so that groupby
+ # will return a single group for a particular type of mapper.
+ # it's not trying to be deterministic beyond that.
+ obj_states = sorted(
+ obj_states,
+ key=lambda state: (id(state.mapper), state.key is not None),
+ )
- for (mapper, isupdate), states in itertools.groupby(obj_states, key):
+ def grouping_key(state):
+ return (state.mapper, state.key is not None)
+
+ for (mapper, isupdate), states in itertools.groupby(
+ obj_states, grouping_key
+ ):
self._bulk_save_mappings(
mapper,
states,
diff --git a/lib/sqlalchemy/util/typing.py b/lib/sqlalchemy/util/typing.py
index e2d42db6e..5767d258b 100644
--- a/lib/sqlalchemy/util/typing.py
+++ b/lib/sqlalchemy/util/typing.py
@@ -6,6 +6,8 @@ from typing import Type
from typing import TypeVar
from typing import Union
+from typing_extensions import NotRequired # noqa
+
from . import compat
_T = TypeVar("_T", bound=Any)
@@ -26,11 +28,6 @@ else:
from typing_extensions import Concatenate # noqa
from typing_extensions import ParamSpec # noqa
-if compat.py311:
- from typing import NotRequired # noqa
-else:
- from typing_extensions import NotRequired # noqa
-
_T = TypeVar("_T")