@@ -3459,7 +3459,7 @@ def _remove_newly_deleted(
34593459 if persistent_to_deleted is not None :
34603460 persistent_to_deleted (self , state )
34613461
3462- def add (self , instance : object , _warn : bool = True ) -> None :
3462+ def add (self , instance : object , * , _warn : bool = True ) -> None :
34633463 """Place an object into this :class:`_orm.Session`.
34643464
34653465 Objects that are in the :term:`transient` state when passed to the
@@ -3544,16 +3544,30 @@ def delete(self, instance: object) -> None:
35443544
35453545 :ref:`session_deleting` - at :ref:`session_basics`
35463546
3547+ :meth:`.Session.delete_all` - multiple instance version
3548+
35473549 """
35483550 if self ._warn_on_events :
35493551 self ._flush_warning ("Session.delete()" )
35503552
3551- try :
3552- state = attributes . instance_state ( instance )
3553- except exc . NO_STATE as err :
3554- raise exc . UnmappedInstanceError ( instance ) from err
3553+ self . _delete_impl ( object_state ( instance ), instance , head = True )
3554+
3555+ def delete_all ( self , instances : Iterable [ object ]) -> None :
3556+ """Calls :meth:`.Session.delete` on multiple instances.
35553557
3556- self ._delete_impl (state , instance , head = True )
3558+ .. seealso::
3559+
3560+ :meth:`.Session.delete` - main documentation on delete
3561+
3562+ .. versionadded: 2.1
3563+
3564+ """
3565+
3566+ if self ._warn_on_events :
3567+ self ._flush_warning ("Session.delete_all()" )
3568+
3569+ for instance in instances :
3570+ self ._delete_impl (object_state (instance ), instance , head = True )
35573571
35583572 def _delete_impl (
35593573 self , state : InstanceState [Any ], obj : object , head : bool
@@ -3955,32 +3969,62 @@ def merge(
39553969 :func:`.make_transient_to_detached` - provides for an alternative
39563970 means of "merging" a single object into the :class:`.Session`
39573971
3972+ :meth:`.Session.merge_all` - multiple instance version
3973+
39583974 """
39593975
39603976 if self ._warn_on_events :
39613977 self ._flush_warning ("Session.merge()" )
39623978
3963- _recursive : Dict [InstanceState [Any ], object ] = {}
3964- _resolve_conflict_map : Dict [_IdentityKeyType [Any ], object ] = {}
3965-
39663979 if load :
39673980 # flush current contents if we expect to load data
39683981 self ._autoflush ()
39693982
3970- object_mapper (instance ) # verify mapped
3971- autoflush = self .autoflush
3972- try :
3973- self .autoflush = False
3983+ with self .no_autoflush :
39743984 return self ._merge (
3975- attributes . instance_state (instance ),
3985+ object_state (instance ),
39763986 attributes .instance_dict (instance ),
39773987 load = load ,
39783988 options = options ,
3979- _recursive = _recursive ,
3980- _resolve_conflict_map = _resolve_conflict_map ,
3989+ _recursive = {} ,
3990+ _resolve_conflict_map = {} ,
39813991 )
3982- finally :
3983- self .autoflush = autoflush
3992+
3993+ def merge_all (
3994+ self ,
3995+ instances : Iterable [_O ],
3996+ * ,
3997+ load : bool = True ,
3998+ options : Optional [Sequence [ORMOption ]] = None ,
3999+ ) -> Sequence [_O ]:
4000+ """Calls :meth:`.Session.merge` on multiple instances.
4001+
4002+ .. seealso::
4003+
4004+ :meth:`.Session.merge` - main documentation on merge
4005+
4006+ .. versionadded: 2.1
4007+
4008+ """
4009+
4010+ if self ._warn_on_events :
4011+ self ._flush_warning ("Session.merge_all()" )
4012+
4013+ if load :
4014+ # flush current contents if we expect to load data
4015+ self ._autoflush ()
4016+
4017+ return [
4018+ self ._merge (
4019+ object_state (instance ),
4020+ attributes .instance_dict (instance ),
4021+ load = load ,
4022+ options = options ,
4023+ _recursive = {},
4024+ _resolve_conflict_map = {},
4025+ )
4026+ for instance in instances
4027+ ]
39844028
39854029 def _merge (
39864030 self ,
0 commit comments