Esempio n. 1
0
    def test_as_declarative(self):
        class User(ComparableEntity):
            __tablename__ = 'users'

            id = Column('id', Integer, primary_key=True)
            name = Column('name', String(50))
            addresses = relation("Address", backref="user")

        class Address(ComparableEntity):
            __tablename__ = 'addresses'

            id = Column('id', Integer, primary_key=True)
            email = Column('email', String(50))
            user_id = Column('user_id', Integer, ForeignKey('users.id'))
        
        reg = {}
        decl.instrument_declarative(User, reg, Base.metadata)
        decl.instrument_declarative(Address, reg, Base.metadata)
        Base.metadata.create_all()
        
        u1 = User(name='u1', addresses=[
            Address(email='one'),
            Address(email='two'),
        ])
        sess = create_session()
        sess.add(u1)
        sess.flush()
        sess.clear()

        eq_(sess.query(User).all(), [User(name='u1', addresses=[
            Address(email='one'),
            Address(email='two'),
        ])])
Esempio n. 2
0
    def test_as_declarative(self):
        class User(fixtures.ComparableEntity):

            __tablename__ = "users"
            id = Column("id", Integer, primary_key=True, test_needs_autoincrement=True)
            name = Column("name", String(50))
            addresses = relationship("Address", backref="user")

        class Address(fixtures.ComparableEntity):

            __tablename__ = "addresses"
            id = Column("id", Integer, primary_key=True, test_needs_autoincrement=True)
            email = Column("email", String(50))
            user_id = Column("user_id", Integer, ForeignKey("users.id"))

        reg = {}
        decl.instrument_declarative(User, reg, Base.metadata)
        decl.instrument_declarative(Address, reg, Base.metadata)
        Base.metadata.create_all()
        u1 = User(name="u1", addresses=[Address(email="one"), Address(email="two")])
        sess = create_session()
        sess.add(u1)
        sess.flush()
        sess.expunge_all()
        eq_(sess.query(User).all(), [User(name="u1", addresses=[Address(email="one"), Address(email="two")])])
Esempio n. 3
0
    def execute(self, class_, tablename, metadata, reflected, tableargs, inherits, polymorphic_identity, polymorphic_on, **kw):
        class_.__tablename__ = tablename
        if tableargs is not None:
            class_.__table_args__ = tableargs
        
        if reflected:
            if not hasattr(metadata, '_reflected_registry'):
                metadata._reflected_registry = {}

            metadata._reflected_registry[class_] = dict(
                inherits=inherits,
                polymorphic_on=polymorphic_on,
                polymorphic_identity=polymorphic_identity,
                )


            # if this table is reflected, don't instrument now but
            # manually map later
            return True
        # we associate the _decl_registry with the metadata object
        # to make sure it's unique per metadata. A bit of a hack..
        if not hasattr(metadata, '_decl_registry'):
            metadata._decl_registry = {}
        try:
            instrument_declarative(class_, metadata._decl_registry, metadata)
        except sqlalchemy.exc.InvalidRequestError:
            # XXX scary - catching too many errors
            # allows re-grokking of classes that were already
            # instrument. Better would be to un-instrument classes
            # after tests, but how to uninstrument?
            pass

        return True
Esempio n. 4
0
    def register():
        if ignore_reattach:
            if '_decl_class_registry' in ModelClass.__dict__:
                assert ModelClass._decl_class_registry == Base._decl_class_registry, "Tried to attach to a different Base"
                return

        instrument_declarative(ModelClass, Base._decl_class_registry, Base.metadata)
Esempio n. 5
0
def attach_model_to_base(ModelClass:type, Base:type, ignore_reattach:bool=True):
    """Dynamically add a model to chosen SQLAlchemy Base class.

    More flexibility is gained by not inheriting from SQLAlchemy declarative base and instead plugging in models during the configuration time more.

    Directly inheritng from SQLAlchemy Base class has non-undoable side effects. All models automatically pollute SQLAlchemy namespace and may e.g. cause problems with conflicting table names. This also allows @declared_attr to access Pyramid registry.

    Example how to use Pyramid registry in SQLAlchemy's declared attributes::

        class SamplePluggableModel:
            '''Demostrate pluggable model which gets a referred class from Pyramid config.'''
            id = Column(Integer, primary_key=True)

            def __init__(self, **kwargs):
                # Default constructor
                self.__dict__.update(kwargs)

            @declared_attr
            def owner(cls):
                '''Refer to the configured user model.'''
                from websauna.system.user.utils import get_user_class
                config = cls.metadata.pyramid_config
                User = get_user_class(config.registry)
                return relationship(User, backref="referral_programs")

            @declared_attr
            def owner_id(cls):
                '''Refer to user.id column'''
                from websauna.system.user.utils import get_user_class
                config = cls.metadata.pyramid_config
                User = get_user_class(config.registry)
                return Column(Integer, ForeignKey('{}.id'.format(User.__tablename__)))

    Then you need to call in your Initializer::

        from example import models
        from websauna.system.model.meta import Base

        attach_model_to_base(models.SamplePluggableModel, Base)

    :param ModelClass: SQLAlchemy model class

    :param Base: SQLAlchemy declarative Base for which model should belong to

    :param ignore_reattach: Do nothing if ``ModelClass`` is already attached to base. Base registry is effectively global. ``attach_model_to_base()`` may be called several times within the same process during unit tests runs. Complain only if we try to attach a different base.
    """

    if ignore_reattach:
         if '_decl_class_registry' in ModelClass.__dict__:
            assert ModelClass._decl_class_registry == Base._decl_class_registry, "Tried to attach to a different Base"
            return

    instrument_declarative(ModelClass, Base._decl_class_registry, Base.metadata)
Esempio n. 6
0
def reflectTables(metadata):
    """Reflect tables into ORM.
    """
    if getattr(metadata, '_reflected_completed', False):
        # XXX thread safety?
        return
    if not getattr(metadata, '_reflected_registry', {}):
        # nothing to reflect
        return
    # first reflect database-defined schemas into metadata
    engine = Engine()
    for class_ in metadata._reflected_registry.keys():
        _reflectTableForClass(class_, metadata, engine)
    # reflect any remaining tables. This will not reload tables already loaded
    # (XXX is this necessary?)
    metadata.reflect(bind=engine)
    if not hasattr(metadata, '_decl_registry'):
        metadata._decl_registry = {}

    # XXX should sort by the inheritance tree
    for class_ in sorted(metadata._reflected_registry.keys(), key=lambda a: getattr(a, 'megrok.rdb.directive.inherits', 0)):
        class_args = metadata._reflected_registry[class_]
        polymorphic_on = class_args['polymorphic_on']
        polymorphic_identity = class_args['polymorphic_identity']
        inherits = class_args['inherits']
        mapper_args = getattr(class_, '__mapper_args__', {})

        if polymorphic_on:
            tablename, column = polymorphic_on
            mapper_args['polymorphic_on'] = getattr(metadata.tables[tablename].c, column)
        if polymorphic_identity:
            mapper_args['polymorphic_identity'] = polymorphic_identity
        if inherits:
            mapper_args['inherits'] = inherits
                    
        if mapper_args:
            class_.__mapper_args__ = mapper_args

        instrument_declarative(class_, metadata._decl_registry, metadata)

    # XXX thread safety?
    metadata._reflected_completed = True
Esempio n. 7
0
    def test_difficult_class(self):
        """test no getattr() errors with a customized class"""

        # metaclass to mock the way zope.interface breaks getattr()
        class BrokenMeta(type):
            def __getattribute__(self, attr):
                if attr == "xyzzy":
                    raise AttributeError, "xyzzy"
                else:
                    return object.__getattribute__(self, attr)

        # even though this class has an xyzzy attribute, getattr(cls,"xyzzy")
        # fails
        class BrokenParent(object):
            __metaclass__ = BrokenMeta
            xyzzy = "magic"

        # _as_declarative() inspects obj.__class__.__bases__
        class User(BrokenParent, fixtures.ComparableEntity):
            __tablename__ = "users"
            id = Column("id", Integer, primary_key=True, test_needs_autoincrement=True)
            name = Column("name", String(50))

        decl.instrument_declarative(User, {}, Base.metadata)
Esempio n. 8
0
    title = schema.Column(types.Unicode(128))
    address_visit_address = schema.Column(types.UnicodeText())
    address_visit_postal = schema.Column(types.Unicode(16))
    address_visit_city = schema.Column(types.Unicode(64))
    address_postal_address = schema.Column(types.UnicodeText())
    address_postal_postal = schema.Column(types.Unicode(16))
    address_postal_city = schema.Column(types.Unicode(64))
    email = schema.Column(types.String(128))
    phone = schema.Column(types.String(32))
    activity = schema.Column(types.Unicode(64))
    submitter_name = schema.Column(types.Unicode(64))
    submitter_function = schema.Column(types.Unicode(64))
    department = schema.Column(types.Unicode(64))
    location = schema.Column(types.Unicode(64))
    submit_date = schema.Column(types.Date(), default=functions.now())
    employees = schema.Column(Enum([None, "40h", "max25", "over25"]))
    absentee_percentage = schema.Column(types.Numeric(precision=5, scale=2))
    accidents = schema.Column(types.Integer())
    incapacitated_workers = schema.Column(types.Integer())
    arbo_expert = schema.Column(types.Unicode(128))
    works_council_approval = schema.Column(types.Date())


_instrumented = False
if not _instrumented:
    from sqlalchemy.ext import declarative
    from euphorie.client import model
    declarative.instrument_declarative(DutchCompany, model.metadata._decl_registry, model.metadata)
    declarative.instrument_declarative(OdLink, model.metadata._decl_registry, model.metadata)
    _instrumented = True
Esempio n. 9
0
    planning_end = schema.Column(types.Date())
    reference = schema.Column(types.Text())

    risk = orm.relation(Risk,
            backref=orm.backref(
                "action_plans",
                order_by=id,
                cascade="all, delete, delete-orphan"))


_instrumented = False
if not _instrumented:
    metadata._decl_registry = {}
    for cls in [SurveyTreeItem, SurveySession, Module, Risk,
                ActionPlan, Account, AccountChangeRequest, Company]:
        declarative.instrument_declarative(cls,
                metadata._decl_registry, metadata)
    _instrumented = True


schema.Index('tree_session_path',
        SurveyTreeItem.session_id, SurveyTreeItem.path)
schema.Index('tree_zodb_path',
        SurveyTreeItem.session_id, SurveyTreeItem.profile_index,
        SurveyTreeItem.zodb_path)


parent = orm.aliased(SurveyTreeItem)
# XXX This can be optimized by doing short-circuit on parent.type!=module
SKIPPED_PARENTS = \
    sql.exists().where(sql.and_(
        parent.session_id == SurveyTreeItem.session_id,
Esempio n. 10
0
                                                 ondelete="CASCADE"),
                               nullable=False,
                               index=True)
    account = orm.relation(model.Account,
                           backref=orm.backref(
                               "logins", cascade="all, delete, delete-orphan"))
    time = schema.Column(types.DateTime(timezone=False),
                         server_default=sql.text('CURRENT_TIMESTAMP'),
                         nullable=False,
                         index=True)


_instrumented = False
if not _instrumented:
    for cls in [LoginStatistics]:
        instrument_declarative(cls, model.metadata._decl_registry,
                               model.metadata)
    _instrumented = True

node = orm.aliased(model.SurveyTreeItem)
SKIPPED_MODULE = \
    sql.exists().where(
        sql.and_(
            model.SurveyTreeItem.type == "module",
            node.session_id == model.SurveyTreeItem.session_id,
            node.skip_children == True
        )
    )

UNANSWERED_RISKS_FILTER = \
        sql.and_(model.SurveyTreeItem.type == "risk",
                sql.exists(sql.select([model.Risk.sql_risk_id]).where(sql.and_(
Esempio n. 11
0
 def configure(cls, *klasses):
     registry = {}
     for c in BaseMeta.classes:
         instrument_declarative(c, registry, cls.metadata)
Esempio n. 12
0
def attach_model_to_base(ModelClass: type,
                         Base: type,
                         ignore_reattach: bool = True):
    """Dynamically add a model to chosen SQLAlchemy Base class.

    More flexibility is gained by not inheriting from SQLAlchemy declarative base and instead plugging in models during the configuration time more.

    Directly inheriting from SQLAlchemy Base class has non-undoable side effects. All models automatically pollute SQLAlchemy namespace and may e.g. cause problems with conflicting table names. This also allows @declared_attr to access Pyramid registry.

    Example how to use Pyramid registry in SQLAlchemy's declared attributes::

        class SamplePluggableModel:
            '''Demostrate pluggable model which gets a referred class from Pyramid config.'''
            id = Column(Integer, primary_key=True)

            def __init__(self, **kwargs):
                # Default constructor
                self.__dict__.update(kwargs)

            @declared_attr
            def owner(cls):
                '''Refer to the configured user model.'''
                from websauna.system.user.utils import get_user_class
                config = cls.metadata.pyramid_config
                User = get_user_class(config.registry)
                return relationship(User, backref="referral_programs")

            @declared_attr
            def owner_id(cls):
                '''Refer to user.id column'''
                from websauna.system.user.utils import get_user_class
                config = cls.metadata.pyramid_config
                User = get_user_class(config.registry)
                return Column(Integer, ForeignKey('{}.id'.format(User.__tablename__)))

    Then you need to call in your Initializer::

        from example import models
        from websauna.system.model.meta import Base

        attach_model_to_base(models.SamplePluggableModel, Base)

    :param ModelClass: SQLAlchemy model class

    :param Base: SQLAlchemy declarative Base for which model should belong to

    :param ignore_reattach: Do nothing if ``ModelClass`` is already attached to base. Base registry is effectively global. ``attach_model_to_base()`` may be called several times within the same process during unit tests runs. Complain only if we try to attach a different base.
    """

    if ignore_reattach:
        if '_decl_class_registry' in ModelClass.__dict__:
            assert ModelClass._decl_class_registry == Base._decl_class_registry, "Tried to attach to a different Base"
            return

    instrument_declarative(ModelClass, Base._decl_class_registry,
                           Base.metadata)

    # TODO: We now hardcode this event listener here.
    # from sqlalchemy.orm.instrumentation import _instrumentation_factory
    # _instrumentation_factory.dispatch.class_instrument(ModelClass)

    # The correct approach is through class_instrument() event firing,
    # but could not figure out yet how to make it happen with all bits flying around
    from .json import init_for_json
    init_for_json(ModelClass)
Esempio n. 13
0
    account_id = schema.Column(
        types.Integer(),
        schema.ForeignKey(model.Account.id, onupdate="CASCADE", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )
    account = orm.relation(model.Account, backref=orm.backref("logins", cascade="all, delete, delete-orphan"))
    time = schema.Column(
        types.DateTime(timezone=False), server_default=sql.text("CURRENT_TIMESTAMP"), nullable=False, index=True
    )


_instrumented = False
if not _instrumented:
    for cls in [LoginStatistics]:
        instrument_declarative(cls, model.metadata._decl_registry, model.metadata)
    _instrumented = True

node = orm.aliased(model.SurveyTreeItem)
SKIPPED_MODULE = sql.exists().where(
    sql.and_(
        model.SurveyTreeItem.type == "module",
        node.session_id == model.SurveyTreeItem.session_id,
        node.skip_children == True,
    )
)

UNANSWERED_RISKS_FILTER = sql.and_(
    model.SurveyTreeItem.type == "risk",
    sql.exists(
        sql.select([model.Risk.sql_risk_id]).where(
Esempio n. 14
0
 def configure(cls, *klasses):
     registry = {}
     for bmc in BaseMeta.classes:
         instrument_declarative(bmc, registry, cls.metadata)
Esempio n. 15
0
    address_postal_postal = schema.Column(types.Unicode(16))
    address_postal_city = schema.Column(types.Unicode(64))
    email = schema.Column(types.String(128))
    phone = schema.Column(types.String(32))
    activity = schema.Column(types.Unicode(64))
    submitter_name = schema.Column(types.Unicode(64))
    submitter_function = schema.Column(types.Unicode(64))
    department = schema.Column(types.Unicode(64))
    location = schema.Column(types.Unicode(64))
    submit_date = schema.Column(types.Date(), default=functions.now())
    employees = schema.Column(Enum([None, "40h", "max25", "over25"]))
    absentee_percentage = schema.Column(types.Numeric(precision=5, scale=2))
    accidents = schema.Column(types.Integer())
    incapacitated_workers = schema.Column(types.Integer())
    arbo_expert = schema.Column(types.Unicode(128))
    works_council_approval = schema.Column(types.Date())


_instrumented = False
if not _instrumented:
    from euphorie.client import model
    from sqlalchemy.ext import declarative

    declarative.instrument_declarative(
        DutchCompany, model.metadata._decl_registry, model.metadata
    )
    declarative.instrument_declarative(
        OdLink, model.metadata._decl_registry, model.metadata
    )
    _instrumented = True