def __init__(self, model, **kwargs): BaseFieldSet.__init__(self, model, **kwargs) self.iface = model self.rebind(model) self._fields = OrderedDict() self._render_fields = OrderedDict() self._bound_pk = None for name, field in schema.getFieldsInOrder(self.iface): klass = field.__class__ try: t = self._fields_mapping[klass] except KeyError: raise NotImplementedError('%s is not mapped to a type' % klass) else: self.append(Field(name=name, type=t)) self._fields[name].label_text = field.title or name if field.description: self._fields[name].set(instructions=field.description) if field.required: self._fields[name].validators.append(validators.required) if klass is schema.Password: self._fields[name].set(renderer=fields.PasswordFieldRenderer) if klass is schema.Text: self._fields[name].set(renderer=fields.TextAreaFieldRenderer) if klass is schema.List: value_type = self.iface[name].value_type if isinstance(value_type, schema.Choice): self._fields[name].set(options=value_type, multiple=True) else: self._fields[name].set(multiple=True) elif klass is schema.Choice: self._fields[name].set(renderer=fields.SelectFieldRenderer, options=self.iface[name])
def insert_after(self, field, new_field): """Insert a new field *after* an existing field. Use this if your business logic requires to add after a certain field, and not before. """ fields_ = self._render_fields or self._fields if not isinstance(new_field, fields.Field): raise ValueError('Can only add Field objects; got %s instead' % field) if isinstance(field, fields.AbstractField): try: index = fields_.keys().index(field.name) except ValueError: raise ValueError('%s not in fields' % field.name) else: raise TypeError('field must be a Field. Got %r' % field) new_field.parent = self items = list(fields_.iteritems()) new_item = (new_field.name, new_field) if index + 1 == len(items): # after the last element ? items.append(new_item) else: items.insert(index + 1, new_item) if self._render_fields: self._render_fields = OrderedDict(items) else: self._fields = OrderedDict(items)
class FieldSet(BaseFieldSet): def __init__(self, model, session=None, data=None, prefix=None): self._fields = OrderedDict() self._render_fields = OrderedDict() self.model = self.session = None BaseFieldSet.rebind(self, model, data=data) self.prefix = prefix self.model = model self.readonly = False self.focus = True self._errors = [] focus = True for k, v in model().iteritems(): if not k.startswith('_'): try: t = getattr(fatypes, v.__class__.__name__.replace('Property','')) except AttributeError: raise NotImplementedError('%s is not mapped to a type' % v.__class__) else: self.add(Field(name=k, type=t)) if v.required: self._fields[k].validators.append(validators.required) def bind(self, model, session=None, data=None): """Bind to an instance""" if not (model or session or data): raise Exception('must specify at least one of {model, session, data}') if not model: if not self.model: raise Exception('model must be specified when none is already set') model = fields._pk(self.model) is None and type(self.model) or self.model # copy.copy causes a stacktrace on python 2.5.2/OSX + pylons. unable to reproduce w/ simpler sample. mr = object.__new__(self.__class__) mr.__dict__ = dict(self.__dict__) # two steps so bind's error checking can work mr.rebind(model, session, data) mr._fields = OrderedDict([(key, renderer.bind(mr)) for key, renderer in self._fields.iteritems()]) if self._render_fields: mr._render_fields = OrderedDict([(field.key, field) for field in [field.bind(mr) for field in self._render_fields.itervalues()]]) return mr def rebind(self, model, session=None, data=None): if model: if isinstance(model, type): try: model = model() except: raise Exception('%s appears to be a class, not an instance, but FormAlchemy cannot instantiate it. (Make sure all constructor parameters are optional!)' % model) self.model = model self._bound_pk = model._doc.get('_id', None) if data is None: self.data = None elif hasattr(data, 'getall') and hasattr(data, 'getone'): self.data = data else: try: self.data = SimpleMultiDict(data) except: raise Exception('unsupported data object %s. currently only dicts and Paste multidicts are supported' % self.data)
class ResponseTimer(object): """Nearly trivial class, used for tracking how long the page took to create. Properties are `total_time`, `sql_time`, and `sql_queries`. In SQL debug mode, `sql_query_log` is also populated. Its keys are queries; values are dicts of parameters, time, and caller. """ def __init__(self): self._start_time = datetime.now() self._total_time = None self.from_cache = None # SQLAlchemy will add to these using the above event listeners; see # spline.config.environment self.sql_time = timedelta() self.sql_queries = 0 self.sql_query_log = OrderedDict() @property def total_time(self): # Calculate and save the total render time as soon as this is accessed if self._total_time is None: self._total_time = datetime.now() - self._start_time return self._total_time def add_log(self, log): self.sql_query_log.setdefault(log["statement"], []).append(log)
class FieldSet(BaseFieldSet): def __init__(self, model, session=None, data=None, prefix=None): self._fields = OrderedDict() self._render_fields = OrderedDict() self.model = self.session = None self.prefix = prefix self.model = model self.readonly = False self.focus = True self._errors = [] self.iface = model focus = True for name, field in schema.getFieldsInOrder(model): try: t = FIELDS_MAPPING[field.__class__] except KeyError: raise NotImplementedError('%s is not mapped to a type' % field.__class__) else: self.add(Field(name=name, type=t)) if field.title: self._fields[name].label_text = field.title if field.required: self._fields[name].validators.append(validators.required) def bind(self, model, session=None, data=None): """Bind to an instance""" if not (model or session or data): raise Exception('must specify at least one of {model, session, data}') if not model: if not self.model: raise Exception('model must be specified when none is already set') model = fields._pk(self.model) is None and type(self.model) or self.model # copy.copy causes a stacktrace on python 2.5.2/OSX + pylons. unable to reproduce w/ simpler sample. mr = object.__new__(self.__class__) mr.__dict__ = dict(self.__dict__) # two steps so bind's error checking can work mr.rebind(model, session, data) mr._fields = OrderedDict([(key, renderer.bind(mr)) for key, renderer in self._fields.iteritems()]) if self._render_fields: mr._render_fields = OrderedDict([(field.key, field) for field in [field.bind(mr) for field in self._render_fields.itervalues()]]) return mr def rebind(self, model, session=None, data=None): if model: if not self.iface.providedBy(model): raise Exception('%r is not provided by %r' % (self.iface, model)) self.model = model self._bound_pk = None if data is None: self.data = None elif hasattr(data, 'getall') and hasattr(data, 'getone'): self.data = data else: try: self.data = SimpleMultiDict(data) except: raise Exception('unsupported data object %s. currently only dicts and Paste multidicts are supported' % self.data)
def pkg_xl_dict_to_fs_dict(cls, pkg_xl_dict, logger=None): '''Convert a Package represented in an Excel-type dictionary to a dictionary suitable for fieldset data. Takes Excel-type dict: {'name':'wikipedia', 'resource-0-url':'http://static.wikipedia.org/'} Returns Fieldset-type dict: {'name':'wikipedia', 'resources':[{'url':'http://static.wikipedia.org/'}]} ''' import ckan.forms standard_fields = model.Package.get_fields() pkg_fs_dict = OrderedDict() for title, cell in pkg_xl_dict.items(): if cell: if title in standard_fields: pkg_fs_dict[title] = cell elif title == 'license': license_id = cls.license_2_license_id(cell) if license: pkg_fs_dict['license_id'] = license_id else: logger('Warning: No license name matches \'%s\'. Ignoring license.' % cell) elif title.startswith('resource-'): match = re.match('resource-(\d+)-(\w+)', title) if match: res_index, field = match.groups() res_index = int(res_index) field = str(field) if not pkg_fs_dict.has_key('resources'): pkg_fs_dict['resources'] = [] resources = pkg_fs_dict['resources'] num_new_resources = 1 + res_index - len(resources) for i in range(num_new_resources): blank_dict = OrderedDict() for blank_field in model.Resource.get_columns(): blank_dict[blank_field] = u'' pkg_fs_dict['resources'].append(blank_dict) pkg_fs_dict['resources'][res_index][field] = cell else: logger('Warning: Could not understand resource title \'%s\'. Ignoring value: %s' % (title, cell)) elif title.startswith('relationships'): # TODO pass elif title == 'download_url': # deprecated - only in there for compatibility pass elif title in readonly_keys: pass else: if not pkg_fs_dict.has_key('extras'): pkg_fs_dict['extras'] = {} pkg_fs_dict['extras'][title] = cell return pkg_fs_dict
def records(self): """Returns each record as a dict.""" for row_index in range(self._first_record_row, self._data.get_num_rows()): row = self._data.get_row(row_index) row_has_content = False for cell in row: if cell: row_has_content = True break if row_has_content: record_dict = OrderedDict(zip(self.titles, row)) if record_dict.has_key(None): del record_dict[None] yield record_dict
class Relationship(object): def __init__(self, source_cls, target_cls): super(Relationship, self).__init__() self.source_cls = source_cls self.target_cls = target_cls self.kwargs = OrderedDict() @property def suggested_names(self): yield self.preferred_name if not iskeyword(self.preferred_name) else self.preferred_name + '_' iteration = 0 while True: iteration += 1 yield self.preferred_name + str(iteration) def render(self): text = 'relationship(' args = [repr(self.target_cls)] if 'secondaryjoin' in self.kwargs: text += '\n ' delimiter, end = ',\n ', '\n )' else: delimiter, end = ', ', ')' args.extend([key + '=' + value for key, value in list(self.kwargs.items())]) return text + delimiter.join(args) + end
def _grab_table_elements(self): schema = self.table.schema self.columns = OrderedDict() for c in self.table.c: c_copy = c.copy(schema=schema) c_copy.unique = c_copy.index = False # ensure that the type object was copied, # as we may need to modify it in-place if isinstance(c.type, SchemaEventTarget): assert c_copy.type is not c.type self.columns[c.name] = c_copy self.named_constraints = {} self.unnamed_constraints = [] self.indexes = {} self.new_indexes = {} for const in self.table.constraints: if _is_type_bound(const): continue elif self.reflected and isinstance(const, CheckConstraint): # TODO: we are skipping reflected CheckConstraint because # we have no way to determine _is_type_bound() for these. pass elif const.name: self.named_constraints[const.name] = const else: self.unnamed_constraints.append(const) for idx in self.table.indexes: self.indexes[idx.name] = idx for k in self.table.kwargs: self.table_kwargs.setdefault(k, self.table.kwargs[k])
def __init__(self, table_name, columns=None): self.table_name = table_name self._options = {} self._annot = OrderedDict() if columns: for info in columns: self._annot[ info['name'] ] = info
def __init__(self, table, association_tables, inflect_engine, detect_joined): super(ModelClass, self).__init__(table) self.name = self._tablename_to_classname(table.name, inflect_engine) self.children = [] self.attributes = OrderedDict() # Assign attribute names for columns for column in table.columns: self._add_attribute(column.name, column) # Add many-to-one relationships pk_column_names = set(col.name for col in table.primary_key.columns) for constraint in sorted(table.constraints, key=_get_constraint_sort_key): if isinstance(constraint, ForeignKeyConstraint): target_cls = self._tablename_to_classname(constraint.elements[0].column.table.name, inflect_engine) if (detect_joined and self.parent_name == 'Base' and set(_get_column_names(constraint)) == pk_column_names): self.parent_name = target_cls else: relationship_ = ManyToOneRelationship(self.name, target_cls, constraint, inflect_engine) self._add_attribute(relationship_.preferred_name, relationship_) # Add many-to-many relationships for association_table in association_tables: fk_constraints = [c for c in association_table.constraints if isinstance(c, ForeignKeyConstraint)] fk_constraints.sort(key=_get_constraint_sort_key) target_cls = self._tablename_to_classname(fk_constraints[1].elements[0].column.table.name, inflect_engine) relationship_ = ManyToManyRelationship(self.name, target_cls, association_table, inflect_engine) self._add_attribute(relationship_.preferred_name, relationship_)
def create_title_mapping(self): """Creates a mapping between the spreadsheet\'s actual column titles and the normalised versions. Results in self.title_map and self.title_reverse_map which are comprehensive for this spreadsheet. """ self.title_map = OrderedDict() for title in self.titles: for norm_title, regex in self.title_normaliser: if regex.match(title): self.title_map[title] = norm_title break else: raise AssertionError("Did not recognise title: %r" % title) self.title_reverse_map = dict((v, k) for k, v in self.title_map.iteritems()) # check all keys map both ways unmatched_keys = set(self.title_map.keys()) - set(self.title_reverse_map.values()) if unmatched_keys: msg = "Columns not identified by REs: %r" % ( set(self.title_map.keys()) - set(self.title_reverse_map.values()) ) msg += "\nColumns over identified by REs: %r" % ( set(self.title_reverse_map.keys()) - set(self.title_map.values()) ) raise AssertionError(msg)
def __init__(self, model, session=None, data=None, prefix=None): self._fields = OrderedDict() self._render_fields = OrderedDict() self.model = self.session = None BaseFieldSet.rebind(self, model, data=data) self.prefix = prefix self.model = model self.readonly = False self.focus = True self._errors = [] focus = True for k, v in model.__dict__.iteritems(): if not k.startswith("_"): descriptor = type(v) t = self._mapping.get(descriptor) if t: self.append(Field(name=k, type=t))
class TableAnnotation( object ): """ Annotations for Table objects, to annotate as needed, the notion is that the annotation keys correspond to column, and values correspond to application specific column metadata. """ _marker = object() schema_invariants = () def __init__(self, table_name, columns=(), properties=(), schema_order=(), listing_columns=(), order_by=()): self.table_name = table_name self._options = {} self._annot = OrderedDict() for info in columns: self._annot[ info['name'] ] = info self.properties = properties self.schema_order = schema_order self.listing_columns = listing_columns self.order_by = order_by def setOption( self, name, value ): self._options[ name ] = value def getOption( self, name, default=None ): return self._options.get( name, default ) def __call__( self, iface ): return self def __setitem__(self, name, value ): self._annot[name] = value def get( self, name, default=None ): return self._annot.get( name, default ) def __getitem__(self, name): return self.get( name ) def values( self ): return self._annot.values() def __contains__(self, name ): return not self._marker == self.get( name, self._marker )
def render_fields(self): """ The set of attributes that will be rendered, as a (ordered) dict of `{fieldname: Field}` pairs """ if not self._render_fields: self._render_fields = OrderedDict([(field.key, field) for field in self._get_fields()]) return self._render_fields
def __init__(self, table, table_args, table_kwargs): self.table = table # this is a Table object self.table_args = table_args self.table_kwargs = table_kwargs self.new_table = None self.column_transfers = OrderedDict( (c.name, {'expr': c}) for c in self.table.c ) self._grab_table_elements()
def reconfigure(self, pk=False, focus=True, readonly=False, global_validator=None, exclude=[], include=[], options=[]): """ Like `configure`, but does not undo the effects of a previous call to `configure` or `reconfigure`. """ self.focus = focus self.readonly = readonly self.validator = global_validator self._render_fields = OrderedDict([(field.key, field) for field in self._get_fields(pk, exclude, include, options, use_rendered=True)])
def render_fields(self): """ The set of attributes that will be rendered, as a (ordered) dict of `{fieldname: Field}` pairs. If you haven't called configure with exclude/include, then this will be the list of default Fields as found by introspecting the SQLAlchemy model. """ if not self._render_fields: self._render_fields = OrderedDict([(field.key, field) for field in self._get_fields()]) return self._render_fields
def __init__(self): self._start_time = datetime.now() self._total_time = None self.from_cache = None # SQLAlchemy will add to these using the above event listeners; see # spline.config.environment self.sql_time = timedelta() self.sql_queries = 0 self.sql_query_log = OrderedDict()
def __init__(self, table, table_args, table_kwargs, reflected): self.table = table # this is a Table object self.table_args = table_args self.table_kwargs = table_kwargs self.temp_table_name = self._calc_temp_name(table.name) self.new_table = None self.column_transfers = OrderedDict( (c.name, {"expr": c}) for c in self.table.c ) self.reflected = reflected self._grab_table_elements()
def insert(self, field, new_field): """Insert a new field before an existing field""" fields_ = self._render_fields or self._fields if not isinstance(new_field, fields.Field): raise ValueError('Can only add Field objects; got %s instead' % field) if isinstance(field, fields.AbstractField): try: index = fields_.keys().index(field.name) except ValueError: raise ValueError('%s not in fields' % field.name) else: raise TypeError('field must be a Field. Got %r' % new_field) items = fields_.items() new_field.parent = self items.insert(index, (new_field.name, new_field)) if self._render_fields: self._render_fields = OrderedDict(items) else: self._fields = OrderedDict(items) return self # Cascade pattern
class TableAnnotation( object ): #__slots__ = ("table_name", "_annot", "_options") def __init__(self, table_name, columns=(), properties=(), schema_order=(), table_columns=(), order_by=()): self.table_name = table_name self._options = {} self._annot = OrderedDict() for info in columns: self._annot[ info['name'] ] = info self.properties = properties self.schema_order = schema_order self.table_columns = table_columns self.order_by = order_by def setOption( self, name, value ): self._options[ name ] = value def getOption( self, name, default=None ): return self._options.get( name, default ) def __call__( self, context ): return ModelAnnotation( context, self ) def __setitem__(self, name, value ): self._annot[name] = value def get( self, name, default=None ): return self._annot.get( name, default ) def __getitem__(self, anme): return self.get( name ) def values( self ): return self._annot.values() def __contains__(self, name ): marker = object() return not marker == self.get( name, marker )
def __init__(self, model, session=None, data=None, prefix=None): self._fields = OrderedDict() self._render_fields = OrderedDict() self.model = self.session = None BaseFieldSet.rebind(self, model, data=data) self.prefix = prefix self.model = model self.readonly = False self.focus = True self._errors = [] focus = True for k, v in model().iteritems(): if not k.startswith('_'): try: t = getattr(fatypes, v.__class__.__name__.replace('Property','')) except AttributeError: raise NotImplementedError('%s is not mapped to a type' % v.__class__) else: self.add(Field(name=k, type=t)) if v.required: self._fields[k].validators.append(validators.required)
def __init__(self, table_name, columns=(), properties=(), schema_order=(), listing_columns=(), order_by=()): self.table_name = table_name self._options = {} self._annot = OrderedDict() for info in columns: self._annot[ info['name'] ] = info self.properties = properties self.schema_order = schema_order self.listing_columns = listing_columns self.order_by = order_by
def __init__(self, model, session=None, data=None, prefix=None): self._fields = OrderedDict() self._render_fields = OrderedDict() self.model = self.session = None self.prefix = prefix self.model = model self.readonly = False self.focus = True self._errors = [] self.iface = model focus = True for name, field in schema.getFieldsInOrder(model): try: t = FIELDS_MAPPING[field.__class__] except KeyError: raise NotImplementedError('%s is not mapped to a type' % field.__class__) else: self.add(Field(name=name, type=t)) if field.title: self._fields[name].label_text = field.title if field.required: self._fields[name].validators.append(validators.required)
def __init__(self, engine=None): self._tables = OrderedDict() self._peer_factories = {} self.engine = engine or ProxyEngine() self.generateDefaults() self.serializer = self.serializer_factory( self ) # rebind self.ident_translate = self.translator_factory.ident_translate self.saveObject = self.serializer.saveObject self.deleteObject = self.serializer.deleteObject
def __init__(self, model, session=None, data=None, prefix=None): self._fields = OrderedDict() self._render_fields = OrderedDict() self.model = self.session = None self.prefix = prefix self.model = model self.readonly = False self.focus = True self._errors = [] self._bound_pk = None self.data = None self.validator = None self.iface = model focus = True for name, field in schema.getFieldsInOrder(model): klass = field.__class__ try: t = self._fields_mapping[klass] except KeyError: raise NotImplementedError('%s is not mapped to a type' % klass) else: self.append(Field(name=name, type=t)) self._fields[name].label_text = field.title or name if field.description: self._fields[name].set(instructions=field.description) if field.required: self._fields[name].validators.append(validators.required) if klass is schema.Text: self._fields[name].set(renderer=fields.TextAreaFieldRenderer) if klass is schema.List: value_type = self.model[name].value_type if isinstance(value_type, schema.Choice): self._fields[name].set(options=value_type, multiple=True) else: self._fields[name].set(multiple=True) elif klass is schema.Choice: self._fields[name].set(renderer=fields.SelectFieldRenderer, options=self.model[name])
def insert(self, field, new_field): """Insert a new field *before* an existing field. This is like the normal ``insert()`` function of ``list`` objects. It takes the place of the previous element, and pushes the rest forward. """ fields_ = self._render_fields or self._fields if not isinstance(new_field, fields.Field): raise ValueError('Can only add Field objects; got %s instead' % field) if isinstance(field, fields.AbstractField): try: index = fields_.keys().index(field.name) except ValueError: raise ValueError('%s not in fields' % field.name) else: raise TypeError('field must be a Field. Got %r' % field) new_field.parent = self items = list(fields_.iteritems()) # prepare for Python 3 items.insert(index, (new_field.name, new_field)) if self._render_fields: self._render_fields = OrderedDict(items) else: self._fields = OrderedDict(items)
def _grab_table_elements(self): schema = self.table.schema self.columns = OrderedDict() for c in self.table.c: c_copy = c.copy(schema=schema) c_copy.unique = c_copy.index = False self.columns[c.name] = c_copy self.named_constraints = {} self.unnamed_constraints = [] self.indexes = {} for const in self.table.constraints: if const.name: self.named_constraints[const.name] = const else: self.unnamed_constraints.append(const) for idx in self.table.indexes: self.indexes[idx.name] = idx
class Relationship(object): def __init__(self, source_cls, target_cls): super(Relationship, self).__init__() self.source_cls = source_cls self.target_cls = target_cls self.kwargs = OrderedDict() self.backref_name = _underscore(self.source_cls) def render(self): text = _flask_prepend + 'relationship(' args = [repr(self.target_cls)] if 'secondaryjoin' in self.kwargs: text += '\n ' delimiter, end = ',\n ', '\n )' else: delimiter, end = ', ', ')' args.extend([key + '=' + value for key, value in self.kwargs.items()]) return text + delimiter.join(args) + end def make_backref(self, relationships, classes): backref = self.backref_name original_backref = backref # Check if backref already exists for relationship source_cls to target_cls and add suffix suffix = 0 while (self.target_cls, backref) in [(x.target_cls, x.backref_name) for x in relationships]: backref = original_backref + str('_{0}'.format(suffix)) suffix += 1 self.kwargs['backref'] = repr(backref) # Check if any of the target_cls inherit from other target_cls # If so, modify backref name of descendant # "backref({0}, lazy='dynamic')".format(repr(backref)) for rel in [x for x in relationships if 'backref' in x.kwargs]: if self.target_cls in classes and rel.target_cls in classes: if _is_model_descendant(classes[self.target_cls], classes[rel.target_cls]): self.backref_name = self.target_cls.lower() + '_' + backref self.kwargs['backref'] = repr(self.backref_name) if _is_model_descendant(classes[rel.target_cls], classes[self.target_cls]): backref = rel.backref_name rel.backref_name = rel.target_cls.lower() + '_' + backref rel.kwargs['backref'] = repr(rel.backref_name)
class ModelClass(Model): parent_name = 'Base' def __init__(self, table, association_tables, inflect_engine, detect_joined): super(ModelClass, self).__init__(table) self.name = self._tablename_to_classname(table.name, inflect_engine) self.children = [] self.attributes = OrderedDict() # Assign attribute names for columns for column in table.columns: self._add_attribute(column.name, column) # Add many-to-one relationships pk_column_names = set(col.name for col in table.primary_key.columns) for constraint in sorted(table.constraints, key=_get_constraint_sort_key): if isinstance(constraint, ForeignKeyConstraint): target_cls = self._tablename_to_classname( constraint.elements[0].column.table.name, inflect_engine) if (detect_joined and self.parent_name == 'Base' and set( _get_column_names(constraint)) == pk_column_names): self.parent_name = target_cls else: relationship_ = ManyToOneRelationship( self.name, target_cls, constraint, inflect_engine) self._add_attribute(relationship_.preferred_name, relationship_) # Add many-to-many relationships for association_table in association_tables: fk_constraints = [ c for c in association_table.constraints if isinstance(c, ForeignKeyConstraint) ] fk_constraints.sort(key=_get_constraint_sort_key) target_cls = self._tablename_to_classname( fk_constraints[1].elements[0].column.table.name, inflect_engine) relationship_ = ManyToManyRelationship(self.name, target_cls, association_table) self._add_attribute(relationship_.preferred_name, relationship_) @classmethod def _tablename_to_classname(cls, tablename, inflect_engine): tablename = cls._convert_to_valid_identifier(tablename) camel_case_name = ''.join(part[:1].upper() + part[1:] for part in tablename.split('_')) return inflect_engine.singular_noun(camel_case_name) or camel_case_name @staticmethod def _convert_to_valid_identifier(name): assert name, 'Identifier cannot be empty' if name[0].isdigit() or iskeyword(name): name = '_' + name elif name == 'metadata': name = 'metadata_' return _re_invalid_identifier.sub('_', name) def _add_attribute(self, attrname, value): attrname = tempname = self._convert_to_valid_identifier(attrname) counter = 1 while tempname in self.attributes: tempname = attrname + str(counter) counter += 1 self.attributes[tempname] = value return tempname def add_imports(self, collector): super(ModelClass, self).add_imports(collector) if any( isinstance(value, Relationship) for value in self.attributes.values()): collector.add_literal_import('sqlalchemy.orm', 'relationship') for child in self.children: child.add_imports(collector)
def __init__(self, source_cls, target_cls): super(Relationship, self).__init__() self.source_cls = source_cls self.target_cls = target_cls self.kwargs = OrderedDict()