| 3478 | return item |
| 3479 | @cut_traceback |
| 3480 | def add(wrapper, new_items): |
| 3481 | obj = wrapper._obj_ |
| 3482 | attr = wrapper._attr_ |
| 3483 | cache = obj._session_cache_ |
| 3484 | if cache is None or not cache.is_alive: throw_db_session_is_over('change collection', obj, attr) |
| 3485 | if obj._status_ in del_statuses: throw_object_was_deleted(obj) |
| 3486 | with cache.flush_disabled(): |
| 3487 | reverse = attr.reverse |
| 3488 | if not reverse: throw(NotImplementedError) |
| 3489 | new_items = attr.validate(new_items, obj) |
| 3490 | if not new_items: return |
| 3491 | setdata = obj._vals_.get(attr) |
| 3492 | if setdata is not None: new_items -= setdata |
| 3493 | if setdata is None or not setdata.is_fully_loaded: |
| 3494 | setdata = attr.load(obj, new_items) |
| 3495 | new_items -= setdata |
| 3496 | undo_funcs = [] |
| 3497 | try: |
| 3498 | if not reverse.is_collection: |
| 3499 | for item in new_items: reverse.__set__(item, obj, undo_funcs) |
| 3500 | else: reverse.reverse_add(new_items, obj, undo_funcs) |
| 3501 | except: |
| 3502 | for undo_func in reversed(undo_funcs): undo_func() |
| 3503 | raise |
| 3504 | setdata |= new_items |
| 3505 | if setdata.count is not None: setdata.count += len(new_items) |
| 3506 | added = setdata.added |
| 3507 | removed = setdata.removed |
| 3508 | if removed: (new_items, setdata.removed) = (new_items-removed, removed-new_items) |
| 3509 | if added: added |= new_items |
| 3510 | else: setdata.added = new_items # added may be None |
| 3511 | |
| 3512 | cache.modified_collections[attr].add(obj) |
| 3513 | cache.modified = True |
| 3514 | @cut_traceback |
| 3515 | def __iadd__(wrapper, items): |
| 3516 | wrapper.add(items) |