예제 #1
0
    def test_tablename(self, db):
        class NotLazy(db.Model):
            class Meta:
                abstract = True
                lazy_mapped = False

        class Auto(NotLazy):
            pass

        assert Auto.Meta.table is None
        assert '__tablename__' not in Auto.Meta._mcs_args.clsdict
        assert Auto.__tablename__ == 'auto'

        class DeclaredAttr(NotLazy):
            @db.declared_attr
            def __tablename__(cls):
                return cls.__name__.lower()

        assert DeclaredAttr.Meta.table is None
        assert DeclaredAttr.__tablename__ == 'declaredattr'

        class Manual(NotLazy):
            __tablename__ = 'manuals'

        assert Manual.Meta.table == 'manuals'
        assert Manual.Meta._mcs_args.clsdict['__tablename__'] == 'manuals'
        assert Manual.__tablename__ == 'manuals'

        class AutoMV(db.MaterializedView):
            @classmethod
            def selectable(cls):
                return db.select([Auto.id])

        UnchainedModelRegistry().finalize_mappings()

        assert AutoMV.Meta.table == 'auto_mv'
        assert AutoMV.__table__.fullname == 'auto_mv'
        assert AutoMV.Meta._mcs_args.clsdict['__tablename__'] == 'auto_mv'
        assert AutoMV.__tablename__ == 'auto_mv'

        class ManualMV(db.MaterializedView):
            class Meta:
                table = 'manual_materialized_view'

            @classmethod
            def selectable(cls):
                return db.select([Manual.id])

        UnchainedModelRegistry().finalize_mappings()

        assert ManualMV.Meta.table == 'manual_materialized_view'
        assert ManualMV.__table__.fullname == 'manual_materialized_view'
        assert ManualMV.Meta._mcs_args.clsdict['__tablename__'] == \
               'manual_materialized_view'
        assert ManualMV.__tablename__ == 'manual_materialized_view'
예제 #2
0
def setup(db):
    class Node(db.Model):
        class Meta:
            repr = ('id', 'name', 'path')

        slug = db.Column(db.String, index=True, unique=True)

        parent_id = db.foreign_key('Node', nullable=True)
        parent = db.relationship('Node',
                                 back_populates='children',
                                 remote_side='Node.id')
        children = db.relationship('Node', back_populates='parent')

        mv = db.relationship('NodeMV',
                             uselist=False,
                             foreign_keys='NodeMV.id',
                             primaryjoin='Node.id == NodeMV.id',
                             viewonly=True)
        depth = db.association_proxy('mv', 'depth')
        path = db.association_proxy('mv', 'path')

    class NodeMV(db.MaterializedView):
        class Meta:
            mv_for = 'Node'

        @classmethod
        def selectable(cls):
            _cte = (db.select([
                Node.id.label('id'),
                literal(0).label('depth'),
                literal('/').label('path')
            ]).where(Node.parent_id == None).cte(name='nodes_cte',
                                                 recursive=True))
            _union = _cte.union_all(
                db.select([
                    Node.id.label('id'),
                    label('depth', _cte.c.depth + 1),
                    label(
                        'path',
                        case(
                            [
                                # tuple(if condition, then value),
                                (_cte.c.depth == 0, _cte.c.path + Node.slug),
                            ],
                            else_=_cte.c.path + '/' + Node.slug)),
                ]).select_from(db.join(_cte, Node,
                                       _cte.c.id == Node.parent_id)))
            return db.select([_union])

    unchained.sqlalchemy_bundle.models = UnchainedModelRegistry(
    ).finalize_mappings()
    db.create_all()

    class NodeManager(ModelManager):
        class Meta:
            model = Node

    return Node, NodeMV, NodeManager()
예제 #3
0
def db_ext(bundles):
    os.environ['FLASK_ENV'] = TEST
    os.environ['SQLA_TESTING'] = 'True'

    sqla_bundle = 'flask_unchained.bundles.sqlalchemy'
    db_bundles = [
        sqla_bundle, 'tests.bundles.sqlalchemy._bundles.custom_extension'
    ]
    try:
        bundle_under_test = [m for m in db_bundles if m in bundles][0]
    except (IndexError, TypeError):
        bundle_under_test = sqla_bundle

    UnchainedModelRegistry()._reset()
    clear_mappers()
    unchained._reset()

    # NOTE: this logic is only correct for one level deep of bundle extension
    # (the proper behavior from unchained hooks is to import the full
    # inheritance hierarchy, and that is especially essential for all of the
    # metaclass magic in this bundle to work correctly)
    modules_to_import = ([bundle_under_test] if bundle_under_test
                         == sqla_bundle else [sqla_bundle, bundle_under_test])

    for module_name in modules_to_import:
        if module_name in sys.modules:
            del sys.modules[module_name]
        db_module = importlib.import_module(module_name)

        ext_module_name = f'{module_name}.extensions'
        if ext_module_name in sys.modules:
            del sys.modules[ext_module_name]
        db_extensions_module = importlib.import_module(ext_module_name)

    kwargs = getattr(
        db_extensions_module, 'kwargs',
        dict(metadata=MetaData(
            naming_convention={
                'ix': 'ix_%(column_0_label)s',
                'uq': 'uq_%(table_name)s_%(column_0_name)s',
                'ck': 'ck_%(table_name)s_%(constraint_name)s',
                'fk':
                'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s',
                'pk': 'pk_%(table_name)s',
            }), ))

    db = db_extensions_module.SQLAlchemy(**kwargs)
    unchained.extensions.db = db

    for module in [db_module, db_extensions_module]:
        setattr(module, 'db', db)

    EXTENSIONS = getattr(db_extensions_module, 'EXTENSIONS')
    EXTENSIONS['db'] = db
    setattr(db_extensions_module, 'EXTENSIONS', EXTENSIONS)

    yield db
예제 #4
0
def setup(db: SQLAlchemy):
    class Foo(db.Model):
        name = db.Column(db.String)

    # simulate the register models hook
    unchained.sqlalchemy_bundle.models['Foo'] = Foo

    class FooManager(ModelManager):
        class Meta:
            model = Foo

    UnchainedModelRegistry().finalize_mappings()
    db.create_all()

    return Foo, FooManager()