예제 #1
0
        def _import_model_classes_from_file(filepath):
            """
            Import the SQLAlchemy models from the Python module at `filepath`
            """
            imported_model_classes = []
            mod = import_module_from_file(filepath)
            # NOTE - We cannot use
            # pfb_exporter.utils.import_subclass_from_module here because
            # we are unable to use issubclass to test if the SQLAlchemy model
            # class is a subclass of its parent
            # (sqlalchemy.ext.declarative.api.Base)
            # The best we can do is make sure the class is a SQLAlchemy object
            # and check that the object is a DeclarativeMeta type
            for cls_name, cls_path in inspect.getmembers(mod, inspect.isclass):
                cls = getattr(mod, cls_name)
                try:
                    sqla_inspect(cls)
                except NoInspectionAvailable:
                    # Not a SQLAlchemy object
                    pass
                else:
                    if type(cls) == DeclarativeMeta:
                        imported_model_classes.append(cls)

            return imported_model_classes
예제 #2
0
    def _create_pfb_schema(self):
        """
        Transform SQLAlchemy models into PFB schema
        """
        self.logger.info('Creating PFB schema from SQLAlchemy models ...')
        relational_model = {}

        for model_name, model_cls in self.model_dict.items():
            self.logger.info(f'Building schema for {model_name} ...')
            # Inspect model columns and types
            for p in sqla_inspect(model_cls).iterate_properties:
                model_schema = defaultdict(list)

                if not isinstance(p, ColumnProperty):
                    continue

                if not hasattr(p, 'columns'):
                    continue

                column_obj = p.columns[0]

                # Check if foreign key
                if column_obj.foreign_keys:
                    fkname = column_obj.foreign_keys.pop().target_fullname
                    model_schema['foreign_keys'].append({
                        'table':
                        fkname.split('.')[0],
                        'name':
                        p.key
                    })

                # Convert SQLAlchemy column type to avro type
                stype = type(column_obj.type).__name__
                # Get avro primitive type
                ptype = SQLA_AVRO_TYPE_MAP['primitive'].get(stype)
                if not ptype:
                    self.logger.warn(f'⚠️ Could not find avro type for {p}, '
                                     f'SQLAlchemy type: {stype}')
                attr_dict = {'name': p.key, 'type': ptype}

                # Get avro logical type if applicable
                ltype = SQLA_AVRO_TYPE_MAP['logical'].get(stype)
                if ltype:
                    attr_dict.update({'logicalType': ltype})

                # Get default value for attr
                # if column_obj.default:
                #     attr_dict.update({'default': column_obj.default})

                # if column_obj.nullable:
                #     attr_dict.update({'nullable': column_obj.nullable})

                model_schema['attributes'].append(attr_dict)

            relational_model[model_cls.__tablename__] = model_schema

        return relational_model
예제 #3
0
    def test_init(self):
        fn = inspect.stack()[0][3]
        from sqlalchemy.inspection import inspect as sqla_inspect

        class SomeClass1(TableModel):
            __tablename__ = "%s_%d" % (fn, 1)
            i = Integer32(pk=True)
            e = Unicode(32)

        from spyne.util.dictdoc import get_dict_as_object
        inst = get_dict_as_object(dict(i=4), SomeClass1)
        assert not sqla_inspect(inst).attrs.e.history.has_changes()
예제 #4
0
def scan_all_relations(klass):
    relations = []
    for rel in sqla_inspect(klass).relationships:
        relations.append((rel.key, rel.mapper.class_.__name__))
    return relations
예제 #5
0
def scan_relations(klass):
    relations = []
    for rel in sqla_inspect(klass).relationships:
        if rel.direction.name == 'MANYTOONE':
            relations.append((rel.key, rel.mapper.class_.__name__))
    return relations
예제 #6
0
def scan_attributes(klass):
    attributes = []
    for column in sqla_inspect(klass).columns:
        attributes.append(column.key)
    return attributes
예제 #7
0
    def to_dict(self):
        """
        Serialize each SQLAlchemy model into a dict that captures
        a each model's name, attributes, types of attributes, and foreign keys.

        The dict will look like:

        {
            '<table name>': {
                'class': <full module path to the model class>,
                'table_name': <table name>,
                'properties': [
                    {
                        Output of _column_obj_to_dict
                    },
                    ...
                ],
                'foreign_keys': [
                    {
                        'attribute': <foreign key column name>,
                        'table': <foreign key table name>
                    }
                ]
            }
        }
        """
        orm_models_dict = {}

        self.logger.info('Serializing SQLAlchemy models to dicts')
        model_dict_template = {
            'class': None,
            'table_name': None,
            'properties': [],
            'foreign_keys': []
        }

        for model_cls in self.imported_model_classes:
            model_dict = deepcopy(model_dict_template)
            model_name = model_cls.__name__
            model_dict['table_name'] = model_cls.__tablename__
            model_dict['class'] = model_name

            self.logger.info(f'Building model dict for {model_name} ...')

            # Inspect model columns and types
            for p in sqla_inspect(model_cls).iterate_properties:
                if not isinstance(p, ColumnProperty):
                    continue

                if not hasattr(p, 'columns'):
                    continue

                d = self._column_obj_to_dict(p.key, p.columns[0])

                if d.pop('primary_key', None):
                    model_dict['primary_key'] = p.key

                model_dict['properties'].append(d)

                fk = d.pop('foreign_key', {})
                if fk:
                    model_dict['foreign_keys'].append(fk)

            orm_models_dict[model_dict['table_name']] = model_dict

        return orm_models_dict
예제 #8
0
 def _scan_relations(self, klass):
     relations = []
     for rel in sqla_inspect(klass).relationships:
         if rel.direction.name == 'MANYTOONE':
             relations.append(rel.key)
     return relations