def direction(self): symbols = [part.property.direction for part in self.parts] if symbol('MANYTOMANY') in symbols: return symbol('MANYTOMANY') elif symbol('MANYTOONE') in symbols and symbol('ONETOMANY') in symbols: return symbol('MANYTOMANY') return symbols[0]
def _get_valid_field_names(self): inspect_mapper = inspect(self.model) columns = inspect_mapper.columns orm_descriptors = inspect_mapper.all_orm_descriptors column_names = columns.keys() hybrid_names = [ key for key, item in orm_descriptors.items() if item.extension_type == symbol('HYBRID_PROPERTY') or item.extension_type == symbol('HYBRID_METHOD') ] return set(column_names) | set(hybrid_names)
def on_set_attr(target, value, old_value, initiator): if old_value is None or old_value in (symbol('NEVER_SET'), symbol('NO_VALUE')): return store_manager = StoreManager.get_current_store_manager() if store_manager.delete_orphan: if value is not old_value: if collection: if isinstance(old_value, dict): store_manager.orphaned(*(set(old_value.values()) - set(value.values()))) else: store_manager.orphaned(*(set(old_value) - set(value))) else: store_manager.orphaned(old_value)
def create_offer_event_on_payout_changed(target, value, old_value, initiator): if old_value != symbol('NO_VALUE'): if value != old_value: offer_event = models.OfferEvent() event_type = models.OfferEvent.TYPE_PAYOUT_UP if value > old_value else models.OfferEvent.TYPE_PAYOUT_DOWN offer_event.name = event_type offer_event.offer = target db.session.add(offer_event) db.session.flush()
def before_flush(session, *args): from intranet3.models import Client project_or_client = None for obj in session: if isinstance(obj, (Project, Client)) and hasattr(obj, 'old_coordinator'): project_or_client = obj if not project_or_client: return oldc = project_or_client.old_coordinator if oldc and oldc != symbol('NO_VALUE'): remove_coordinator(session, project_or_client.old_coordinator) if project_or_client.coordinator_id: add_coordinator(session, project_or_client.coordinator_id)
def db_attr_event(target, value, oldvalue, initiator): """ Find the appropriate object and verify. Dispatch if necessary. """ op = 'new' if oldvalue == symbol('NO_VALUE') else 'dirty' reg_key = 'database:%s:%s:%s' % (target.__tablename__, initiator.key, op) _pv_semaphore.acquire() actions = event_registry.get(reg_key, None) _pv_semaphore.release() kwargs = {'newvalue': value, 'oldvalue': oldvalue} if actions: for action in actions: if action.verify(target, op, **kwargs): action.dispatch(target, op, **kwargs) return target
def create(target, value, oldvalue, initiator): if any( [ oldvalue is symbol("NO_VALUE"), value == oldvalue, ] ): return value db.session.add( cls( table=target.__tablename__, row=target.id, field=initiator.key, old_value=_convert(oldvalue), new_value=_convert(value), ) ) return value
def last_fixture(model): """ Return the last created and non-deleted fixture for given model. If no non-deleted record was found this function returns None. :param model: sqlalchemy declarative model """ while FixtureRegistry.records[model]: # fetch the last inserted record record = FixtureRegistry.records[model][-1] state = record._sa_instance_state detached = False # if we find expired attributes, force load them all if state.expired_attributes: try: state(None, symbol('PASSIVE_OFF')) except DetachedInstanceError: detached = True except ObjectDeletedError: state.deleted = True if detached or state.deleted or not object_session(record): FixtureRegistry.records[model].pop() else: return record
__tablename__ = 'somemodel' id = sa.Column(sa.Integer, primary_key=True) """ created = sa.Column(sa.DateTime, default=datetime.utcnow, nullable=False) updated = sa.Column(sa.DateTime, default=datetime.utcnow, nullable=False) @sa.event.listens_for(Timestamp, 'before_update', propagate=True) def timestamp_before_update(mapper, connection, target): # When a model with a timestamp is updated; force update the updated # timestamp. target.updated = datetime.utcnow() NO_VALUE = symbol('NO_VALUE') NOT_LOADED_REPR = '<not loaded>' def _generic_repr_method(self, fields): state = sa.inspect(self) field_reprs = [] if not fields: fields = state.mapper.columns.keys() for key in fields: value = state.attrs[key].loaded_value if value == NO_VALUE: value = NOT_LOADED_REPR else: value = repr(value) field_reprs.append('='.join((key, value)))
def test_direction(self, SubSection): assert (AttrPath(SubSection, 'section').direction == symbol('MANYTOONE'))
def test_direction(self, SubSection): assert ( AttrPath(SubSection, 'section').direction == symbol('MANYTOONE') )
""" from abc import ABCMeta import typing as t import sqlalchemy as sa from sqlalchemy import MetaData, orm from sqlalchemy.orm import DeclarativeMeta, declarative_base as _declarative_base from sqlalchemy.sql import Delete, Insert, Select, Update from sqlalchemy.util.langhelpers import symbol from . import event from .utils import is_iterable_but_not_string NO_VALUE = symbol("NO_VALUE") class DeclarativeModel(metaclass=ABCMeta): @classmethod def __subclasshook__(cls, class_): if cls is DeclarativeModel: return isinstance(class_, DeclarativeMeta) return NotImplemented # pragma: no cover class ModelMeta(DeclarativeMeta): """Model metaclass that prepares model classes for event registration hooks.""" def __new__(mcs, name, bases, dct): cls = DeclarativeMeta.__new__(mcs, name, bases, dct)
class TestAttrPath(TestCase): def create_models(self): class Document(self.Base): __tablename__ = 'document' id = sa.Column(sa.Integer, primary_key=True) name = sa.Column(sa.Unicode(255)) locale = sa.Column(sa.String(10)) class Section(self.Base): __tablename__ = 'section' id = sa.Column(sa.Integer, primary_key=True) name = sa.Column(sa.Unicode(255)) locale = sa.Column(sa.String(10)) document_id = sa.Column(sa.Integer, sa.ForeignKey(Document.id)) document = sa.orm.relationship(Document, backref='sections') class SubSection(self.Base): __tablename__ = 'subsection' id = sa.Column(sa.Integer, primary_key=True) name = sa.Column(sa.Unicode(255)) locale = sa.Column(sa.String(10)) section_id = sa.Column(sa.Integer, sa.ForeignKey(Section.id)) section = sa.orm.relationship(Section, backref='subsections') self.Document = Document self.Section = Section self.SubSection = SubSection @mark.parametrize(('class_', 'path', 'direction'), (('SubSection', 'section', symbol('MANYTOONE')), )) def test_direction(self, class_, path, direction): assert (AttrPath(getattr(self, class_), path).direction == direction) def test_invert(self): path = ~AttrPath(self.SubSection, 'section.document') assert path.parts == [self.Document.sections, self.Section.subsections] assert str(path.path) == 'sections.subsections' def test_len(self): len(AttrPath(self.SubSection, 'section.document')) == 2 def test_init(self): path = AttrPath(self.SubSection, 'section.document') assert path.class_ == self.SubSection assert path.path == Path('section.document') def test_iter(self): path = AttrPath(self.SubSection, 'section.document') assert list(path) == [self.SubSection.section, self.Section.document] def test_repr(self): path = AttrPath(self.SubSection, 'section.document') assert repr(path) == ("AttrPath(SubSection, 'section.document')") def test_index(self): path = AttrPath(self.SubSection, 'section.document') assert path.index(self.Section.document) == 1 assert path.index(self.SubSection.section) == 0 def test_getitem(self): path = AttrPath(self.SubSection, 'section.document') assert path[0] is self.SubSection.section assert path[1] is self.Section.document def test_getitem_with_slice(self): path = AttrPath(self.SubSection, 'section.document') assert path[:] == AttrPath(self.SubSection, 'section.document') assert path[:-1] == AttrPath(self.SubSection, 'section') assert path[1:] == AttrPath(self.Section, 'document') def test_eq(self): assert (AttrPath(self.SubSection, 'section.document') == AttrPath( self.SubSection, 'section.document')) assert not (AttrPath(self.SubSection, 'section') == AttrPath( self.SubSection, 'section.document')) def test_ne(self): assert not (AttrPath(self.SubSection, 'section.document') != AttrPath( self.SubSection, 'section.document')) assert (AttrPath(self.SubSection, 'section') != AttrPath( self.SubSection, 'section.document'))
def before_flush(session, *args): """ Set 'parent_url' and update it when 'url_part' was changed. """ nones = (symbol('NO_VALUE'), symbol('NEVER_SET'), None) # NOTE: cannot know objects order in session.new and session.dirty, # for that reason multiple 'for' cicles are needed. # Handle 'CommonInfo.parent_url' for 'new' objects. for obj in session.new: if not isinstance(obj, CommonInfo): continue if obj.node is None and obj.node_id is None: msg = '{} object must belong to a Node.' msg = msg.format(obj.__class__.__name__) raise ValueError(msg) elif obj.node is None: obj.node = Node.get(session, obj.node_id) #log.info("Update 'parent_url' of %s", obj.label) obj.update_parent_url() # Handle 'PageInfo.content' for 'new' objects. for obj in session.new: if not isinstance(obj, PageInfo): continue #log.info("Update associations of %s", obj.label) obj.update_associations() # Handle 'PageInfo.content' for 'new' objects. for obj in session.dirty: if not isinstance(obj, PageInfo) or \ not hasattr(obj, '_attrs_updates') or \ 'content' not in obj._attrs_updates: continue #log.info("Update associations of %s", obj.label) obj.update_associations() # First phase. # Handle 'node' changes in CommonInfo objects: # replace olds CommonInfo.parent_url with new ones. for obj in session.dirty: if not isinstance(obj, CommonInfo) or \ not hasattr(obj, '_attrs_updates') or \ 'node' not in obj._attrs_updates: continue #log.info("Update parent_url of %s", obj.label) obj.update_parent_url() # Second phase: handle Page|Section objects changes. # Handle 'parent_id' changes in Page and Section objects: # replace olds CommonInfo.parent_url with new ones. for obj in session.dirty: if not isinstance(obj, (Page, Section)) or \ not hasattr(obj, '_attrs_updates') or \ 'parent_id' not in obj._attrs_updates: continue #log.debug('Update translations of %s', obj.id) for translation in obj.translations: #log.info('Update translation: %s', translation.label) translation.update_parent_url() # Third phase: handle CommonInfo.url_part changes. # Handle 'url_part' changes in CommonInfo objects: # replace olds CommonInfo.parent_url with new ones. for obj in session.dirty: if not isinstance(obj, CommonInfo) or \ not hasattr(obj, '_attrs_updates') or \ 'url_part' not in obj._attrs_updates: continue old = obj._attrs_updates['url_part']['old'] new = obj._attrs_updates['url_part']['new'] if old in nones or old == new: continue #log.info("Update children of %s", obj.label) obj.update_children_parent_url()
import pdb from conf import config from sqlalchemy import event from sqlalchemy.orm import mapper from sqlalchemy.util.langhelpers import symbol from sqlalchemy.sql.expression import Select NO_VALUE = symbol("NO_VALUE") from lib.db_connection import db_session try: from celery.task import task as ctask CELERY_INSTALLED = True except ImportError, e: print "You don't have celery installed, running in syncronous mode" def ctask(actual_func, *args, **kwargs): return actual_func CELERY_INSTALLED = False class deferred(object): def __init__(self, trigger_condition, change_field=False, before_predicate=lambda obj: True, run_predicate=lambda obj: True): """The arguments to init are the arguments that are available to the @deferred decorator """ self.before_predicate = before_predicate