Beispiel #1
0
    def init_versioning(self, app, database, versioning_manager=None):
        """Initialize the versioning support using SQLAlchemy-Continuum."""
        try:
            pkg_resources.get_distribution('sqlalchemy_continuum')
        except pkg_resources.DistributionNotFound:  # pragma: no cover
            default_versioning = False
        else:
            default_versioning = True

        app.config.setdefault('DB_VERSIONING', default_versioning)

        if not app.config['DB_VERSIONING']:
            return

        if not default_versioning:  # pragma: no cover
            raise RuntimeError(
                'Please install extra versioning support first by running '
                'pip install invenio-db[versioning].'
            )

        # Now we can import SQLAlchemy-Continuum.
        from sqlalchemy_continuum import make_versioned
        from sqlalchemy_continuum import versioning_manager as default_vm
        from sqlalchemy_continuum.plugins import FlaskPlugin

        # Try to guess user model class:
        if 'DB_VERSIONING_USER_MODEL' not in app.config:  # pragma: no cover
            try:
                pkg_resources.get_distribution('invenio_accounts')
            except pkg_resources.DistributionNotFound:
                user_cls = None
            else:
                user_cls = 'User'
        else:
            user_cls = app.config.get('DB_VERSIONING_USER_MODEL')

        plugins = [FlaskPlugin()] if user_cls else []

        extra_plugins = app.config.get('DB_EXTRA_PLUGINS', [])
        plugins.extend(import_string(obj)() for obj in extra_plugins)

        # Call make_versioned() before your models are defined.
        self.versioning_manager = versioning_manager or default_vm
        make_versioned(
            user_cls=user_cls,
            manager=self.versioning_manager,
            plugins=plugins,
        )

        # Register models that have been loaded beforehand.
        builder = self.versioning_manager.builder

        for tbl in database.metadata.tables.values():
            builder.instrument_versioned_classes(
                database.mapper, get_class_by_table(database.Model, tbl)
            )
Beispiel #2
0
    def init_versioning(self, app, database, versioning_manager=None):
        """Initialize the versioning support using SQLAlchemy-Continuum."""
        try:
            pkg_resources.get_distribution('sqlalchemy_continuum')
        except pkg_resources.DistributionNotFound:  # pragma: no cover
            default_versioning = False
        else:
            default_versioning = True

        app.config.setdefault('DB_VERSIONING', default_versioning)

        if not app.config['DB_VERSIONING']:
            return

        if not default_versioning:  # pragma: no cover
            raise RuntimeError(
                'Please install extra versioning support first by running '
                'pip install invenio-db[versioning].'
            )

        # Now we can import SQLAlchemy-Continuum.
        from sqlalchemy_continuum import make_versioned
        from sqlalchemy_continuum import versioning_manager as default_vm
        from sqlalchemy_continuum.plugins import FlaskPlugin

        # Try to guess user model class:
        if 'DB_VERSIONING_USER_MODEL' not in app.config:  # pragma: no cover
            try:
                pkg_resources.get_distribution('invenio_accounts')
            except pkg_resources.DistributionNotFound:
                user_cls = None
            else:
                user_cls = 'User'
        else:
            user_cls = app.config.get('DB_VERSIONING_USER_MODEL')

        plugins = [FlaskPlugin()] if user_cls else []

        # Call make_versioned() before your models are defined.
        self.versioning_manager = versioning_manager or default_vm
        make_versioned(
            user_cls=user_cls,
            manager=self.versioning_manager,
            plugins=plugins,
        )

        # Register models that have been loaded beforehand.
        builder = self.versioning_manager.builder

        for tbl in database.metadata.tables.values():
            builder.instrument_versioned_classes(
                database.mapper, get_class_by_table(database.Model, tbl)
            )
Beispiel #3
0
    def init_versioning(self, app, database, versioning_manager=None):
        """Initialize the versioning support using SQLAlchemy-Continuum."""
        try:
            importlib_metadata.version("sqlalchemy_continuum")
        except importlib_metadata.PackageNotFoundError:  # pragma: no cover
            default_versioning = False
        else:
            default_versioning = True

        app.config.setdefault("DB_VERSIONING", default_versioning)

        if not app.config["DB_VERSIONING"]:
            return

        if not default_versioning:  # pragma: no cover
            raise RuntimeError(
                "Please install extra versioning support first by running "
                "pip install invenio-db[versioning].")

        # Now we can import SQLAlchemy-Continuum.
        from sqlalchemy_continuum import make_versioned
        from sqlalchemy_continuum import versioning_manager as default_vm
        from sqlalchemy_continuum.plugins import FlaskPlugin

        # Try to guess user model class:
        if "DB_VERSIONING_USER_MODEL" not in app.config:  # pragma: no cover
            try:
                importlib_metadata.version("invenio_accounts")
            except importlib_metadata.PackageNotFoundError:
                user_cls = None
            else:
                user_cls = "User"
        else:
            user_cls = app.config.get("DB_VERSIONING_USER_MODEL")

        plugins = [FlaskPlugin()] if user_cls else []

        # Call make_versioned() before your models are defined.
        self.versioning_manager = versioning_manager or default_vm
        make_versioned(
            user_cls=user_cls,
            manager=self.versioning_manager,
            plugins=plugins,
        )

        # Register models that have been loaded beforehand.
        builder = self.versioning_manager.builder

        for tbl in database.metadata.tables.values():
            builder.instrument_versioned_classes(
                database.mapper, get_class_by_table(database.Model, tbl))
Beispiel #4
0
    def test_volume_dependent_models_list(self):
        """Make sure the volume dependent tables list is accurate."""
        # Addresses LP Bug #1542169

        volume_declarative_base = saf.get_declarative_base(models.Volume)
        volume_fks = saf.get_referencing_foreign_keys(models.Volume)

        dependent_tables = []
        for table, fks in saf.group_foreign_keys(volume_fks):
            dependent_tables.append(table)

        found_dependent_models = []
        for table in dependent_tables:
            found_dependent_models.append(
                saf.get_class_by_table(volume_declarative_base, table))

        self.assertEqual(len(found_dependent_models),
                         len(db_api.VOLUME_DEPENDENT_MODELS))
        for model in found_dependent_models:
            self.assertIn(model, db_api.VOLUME_DEPENDENT_MODELS)
Beispiel #5
0
    def get_sqlalchemy_mapping(self, registry, namespace, fieldname,
                               properties):
        """ Create the relationship

        :param registry: the registry which load the relationship
        :param namespace: the name space of the model
        :param fieldname: fieldname of the relationship
        :param properties: the properties known
        :rtype: Many2One relationship
        """
        self.model.check_model(registry)
        self.local_model = ModelRepr(namespace)
        local_columns, remote_columns = self.get_local_and_remote_columns(
            registry)
        join_table = self.get_join_table(registry, namespace, fieldname)
        has_join_table, schema = self.has_join_table_for_schema(
            registry, namespace, properties, join_table)
        if not has_join_table:
            modelname = ''.join(x.capitalize() for x in join_table.split('_'))
            remote_columns, remote_fk, secondaryjoin = self.get_m2m_columns(
                registry, remote_columns, self.m2m_remote_columns, modelname,
                suffix="right" if namespace == self.model.model_name else ""
            )
            local_columns, local_fk, primaryjoin = self.get_m2m_columns(
                registry, local_columns, self.m2m_local_columns, modelname,
                suffix="left" if namespace == self.model.model_name else ""
            )

            Node = Table(join_table, registry.declarativebase.metadata, *(
                local_columns + remote_columns + [local_fk, remote_fk]),
                schema=schema)

            if namespace == self.model.model_name:
                type(modelname, (registry.declarativebase,), {
                    '__table__': Node
                })
                self.kwargs['primaryjoin'] = primaryjoin
                self.kwargs['secondaryjoin'] = secondaryjoin

        elif namespace == self.model.model_name or self.compute_join:
            table = registry.declarativebase.metadata.tables[
                '%s.%s' % (schema, join_table) if schema else join_table]
            cls = get_class_by_table(registry.declarativebase, table)
            modelname = ModelRepr(cls.__registry_name__).modelname(registry)
            if (
                self.m2m_local_columns is None and
                self.m2m_remote_columns is None
            ):
                raise FieldException(
                    "No 'm2m_local_columns' and 'm2m_remote_columns' "
                    "attribute filled for many2many "
                    "%r on model %r" % (fieldname, namespace))
            elif self.m2m_local_columns is None:
                raise FieldException(
                    "No 'm2m_local_columns' attribute filled for many2many "
                    "%r on model %r" % (fieldname, namespace))
            elif self.m2m_remote_columns is None:
                raise FieldException(
                    "No 'm2m_remote_columns' attribute filled for many2many"
                    " %r on model %r" % (fieldname, namespace))

            remote_columns, remote_fk, secondaryjoin = self.get_m2m_columns(
                registry, remote_columns, self.m2m_remote_columns,
                modelname,
                suffix="right" if namespace == self.model.model_name else ""
            )

            local_columns, local_fk, primaryjoin = self.get_m2m_columns(
                registry, local_columns, self.m2m_local_columns, modelname,
                suffix="left" if namespace == self.model.model_name else ""
            )
            self.kwargs['primaryjoin'] = primaryjoin
            self.kwargs['secondaryjoin'] = secondaryjoin

        self.kwargs['secondary'] = (
            '%s.%s' % (schema, join_table) if schema else join_table)
        # definition of expiration
        if self.kwargs.get('backref'):
            self.init_expire_attributes(registry, namespace, fieldname)
            backref = self.kwargs['backref']
            if isinstance(backref, (tuple, list)):
                backref = backref[0]

            registry.expire_attributes[namespace][fieldname].add(
                ('x2m', fieldname, backref))
            model_name = self.model.model_name
            self.init_expire_attributes(registry, model_name, backref)
            registry.expire_attributes[model_name][backref].add(
                ('x2m', backref, fieldname))

        return super(Many2Many, self).get_sqlalchemy_mapping(
            registry, namespace, fieldname, properties)
Beispiel #6
0
    def get_sqlalchemy_mapping(self, registry, namespace, fieldname,
                               properties):
        """ Create the relationship

        :param registry: the registry which load the relationship
        :param namespace: the name space of the model
        :param fieldname: fieldname of the relationship
        :param properties: the properties known
        :rtype: Many2One relationship
        """
        self.model.check_model(registry)
        self.local_model = ModelRepr(namespace)
        local_columns, remote_columns = self.get_local_and_remote_columns(
            registry)
        join_table = self.get_join_table(registry, namespace, fieldname)
        if join_table not in registry.declarativebase.metadata.tables:
            modelname = ''.join(x.capitalize() for x in join_table.split('_'))
            remote_columns, remote_fk, secondaryjoin = self.get_m2m_columns(
                registry, remote_columns, self.m2m_remote_columns, modelname,
                suffix="right" if namespace == self.model.model_name else ""
            )
            local_columns, local_fk, primaryjoin = self.get_m2m_columns(
                registry, local_columns, self.m2m_local_columns, modelname,
                suffix="left" if namespace == self.model.model_name else ""
            )

            Node = Table(join_table, registry.declarativebase.metadata, *(
                local_columns + remote_columns + [local_fk, remote_fk]))

            if namespace == self.model.model_name:
                type(modelname, (registry.declarativebase,), {
                    '__table__': Node
                })
                self.kwargs['primaryjoin'] = primaryjoin
                self.kwargs['secondaryjoin'] = secondaryjoin

        elif namespace == self.model.model_name or self.compute_join:
            table = registry.declarativebase.metadata.tables[join_table]
            cls = get_class_by_table(registry.declarativebase, table)
            modelname = ModelRepr(cls.__registry_name__).modelname(registry)
            if (
                self.m2m_local_columns is None and
                self.m2m_remote_columns is None
            ):
                raise FieldException(
                    "No 'm2m_local_columns' and 'm2m_remote_columns' "
                    "attribute filled for many2many "
                    "%r on model %r" % (fieldname, namespace))
            elif self.m2m_local_columns is None:
                raise FieldException(
                    "No 'm2m_local_columns' attribute filled for many2many "
                    "%r on model %r" % (fieldname, namespace))
            elif self.m2m_remote_columns is None:
                raise FieldException(
                    "No 'm2m_remote_columns' attribute filled for many2many"
                    " %r on model %r" % (fieldname, namespace))

            remote_columns, remote_fk, secondaryjoin = self.get_m2m_columns(
                registry, remote_columns, self.m2m_remote_columns,
                modelname,
                suffix="right" if namespace == self.model.model_name else ""
            )

            local_columns, local_fk, primaryjoin = self.get_m2m_columns(
                registry, local_columns, self.m2m_local_columns, modelname,
                suffix="left" if namespace == self.model.model_name else ""
            )
            self.kwargs['primaryjoin'] = primaryjoin
            self.kwargs['secondaryjoin'] = secondaryjoin

        self.kwargs['secondary'] = join_table
        # definition of expiration
        if self.kwargs.get('backref'):
            self.init_expire_attributes(registry, namespace, fieldname)
            backref = self.kwargs['backref']
            if isinstance(backref, (tuple, list)):
                backref = backref[0]

            registry.expire_attributes[namespace][fieldname].add(
                ('x2m', fieldname, backref))
            model_name = self.model.model_name
            self.init_expire_attributes(registry, model_name, backref)
            registry.expire_attributes[model_name][backref].add(
                ('x2m', backref, fieldname))

        return super(Many2Many, self).get_sqlalchemy_mapping(
            registry, namespace, fieldname, properties)
 def item(self):
     return get_class_by_table(db.Model, db.Model.metadata.tables[self.item_table]).query.filter_by(id=self.item_id).first()
Beispiel #8
0
 def make_pair(v):
     c = get_class_by_table(base, v[1])
     return (c.__name__, c)