def prepare(cls, engine): """Reflect all the tables and map !""" while cls._mapper_args: args, kw = cls._mapper_args.pop() klass = args[0] # autoload Table, which is already # present in the metadata. This # will fill in db-loaded columns # into the existing Table object. if args[1] is not None: table = args[1] Table(table.name, cls.metadata, extend_existing=True, autoload_replace=False, autoload=True, autoload_with=engine, schema=table.schema) # see if we need 'inherits' in the # mapper args. Declarative will have # skipped this since mappings weren't # available yet. for c in klass.__bases__: if _is_mapped_class(c): # pragma: nocover kw['inherits'] = c break klass.__mapper__ = mapper(*args, **kw)
def prepare(cls, engine): """Reflect all the tables and map !""" while cls._mapper_args: args, kw = cls._mapper_args.pop() klass = args[0] # autoload Table, which is already # present in the metadata. This # will fill in db-loaded columns # into the existing Table object. if args[1] is not None: table = args[1] Table( table.name, cls.metadata, extend_existing=True, autoload_replace=False, autoload=True, autoload_with=engine, schema=table.schema, ) # see if we need 'inherits' in the # mapper args. Declarative will have # skipped this since mappings weren't # available yet. for c in klass.__bases__: if _is_mapped_class(c): kw["inherits"] = c break klass.__mapper__ = mapper(*args, **kw)
def _as_declarative(cls, classname, dict_): # dict_ will be a dictproxy, which we can't write to, and we need to! dict_ = dict(dict_) column_copies = {} potential_columns = {} mapper_args = {} table_args = inherited_table_args = None tablename = None parent_columns = () for base in cls.__mro__: if _is_mapped_class(base): parent_columns = base.__table__.c.keys() else: for name,obj in vars(base).items(): if name == '__mapper_args__': if not mapper_args: mapper_args = cls.__mapper_args__ elif name == '__tablename__': if not tablename: tablename = cls.__tablename__ elif name == '__table_args__': if not table_args: table_args = cls.__table_args__ if base is not cls: inherited_table_args = True elif base is not cls: # we're a mixin. if isinstance(obj, Column): if obj.foreign_keys: raise exceptions.InvalidRequestError( "Columns with foreign keys to other columns " "must be declared as @classproperty callables " "on declarative mixin classes. ") if name not in dict_ and not ( '__table__' in dict_ and name in dict_['__table__'].c ): potential_columns[name] = \ column_copies[obj] = \ obj.copy() column_copies[obj]._creation_order = \ obj._creation_order elif isinstance(obj, MapperProperty): raise exceptions.InvalidRequestError( "Mapper properties (i.e. deferred," "column_property(), relationship(), etc.) must " "be declared as @classproperty callables " "on declarative mixin classes.") elif isinstance(obj, util.classproperty): dict_[name] = ret = \ column_copies[obj] = getattr(cls, name) if isinstance(ret, (Column, MapperProperty)) and \ ret.doc is None: ret.doc = obj.__doc__ # apply inherited columns as we should for k, v in potential_columns.items(): if tablename or k not in parent_columns: dict_[k] = v if inherited_table_args and not tablename: table_args = None # make sure that column copies are used rather # than the original columns from any mixins for k, v in mapper_args.iteritems(): mapper_args[k] = column_copies.get(v,v) cls._decl_class_registry[classname] = cls our_stuff = util.OrderedDict() for k in dict_: value = dict_[k] if isinstance(value, util.classproperty): value = getattr(cls, k) if (isinstance(value, tuple) and len(value) == 1 and isinstance(value[0], (Column, MapperProperty))): util.warn("Ignoring declarative-like tuple value of attribute " "%s: possibly a copy-and-paste error with a comma " "left at the end of the line?" % k) continue if not isinstance(value, (Column, MapperProperty)): continue prop = _deferred_relationship(cls, value) our_stuff[k] = prop # set up attributes in the order they were created our_stuff.sort(key=lambda key: our_stuff[key]._creation_order) # extract columns from the class dict cols = [] for key, c in our_stuff.iteritems(): if isinstance(c, ColumnProperty): for col in c.columns: if isinstance(col, Column) and col.table is None: _undefer_column_name(key, col) cols.append(col) elif isinstance(c, Column): _undefer_column_name(key, c) cols.append(c) # if the column is the same name as the key, # remove it from the explicit properties dict. # the normal rules for assigning column-based properties # will take over, including precedence of columns # in multi-column ColumnProperties. if key == c.key: del our_stuff[key] table = None if '__table__' not in dict_: if tablename is not None: if isinstance(table_args, dict): args, table_kw = (), table_args elif isinstance(table_args, tuple): args = table_args[0:-1] table_kw = table_args[-1] if len(table_args) < 2 or not isinstance(table_kw, dict): raise exceptions.ArgumentError( "Tuple form of __table_args__ is " "(arg1, arg2, arg3, ..., {'kw1':val1, " "'kw2':val2, ...})" ) else: args, table_kw = (), {} autoload = dict_.get('__autoload__') if autoload: table_kw['autoload'] = True cls.__table__ = table = Table(tablename, cls.metadata, *(tuple(cols) + tuple(args)), **table_kw) else: table = cls.__table__ if cols: for c in cols: if not table.c.contains_column(c): raise exceptions.ArgumentError( "Can't add additional column %r when " "specifying __table__" % c.key ) if 'inherits' not in mapper_args: for c in cls.__bases__: if _is_mapped_class(c): mapper_args['inherits'] = cls._decl_class_registry.get( c.__name__, None) break if hasattr(cls, '__mapper_cls__'): mapper_cls = util.unbound_method_to_callable(cls.__mapper_cls__) else: mapper_cls = mapper if table is None and 'inherits' not in mapper_args: raise exceptions.InvalidRequestError( "Class %r does not have a __table__ or __tablename__ " "specified and does not inherit from an existing " "table-mapped class." % cls ) elif 'inherits' in mapper_args and not mapper_args.get('concrete', False): inherited_mapper = class_mapper(mapper_args['inherits'], compile=False) inherited_table = inherited_mapper.local_table if 'inherit_condition' not in mapper_args and table is not None: # figure out the inherit condition with relaxed rules # about nonexistent tables, to allow for ForeignKeys to # not-yet-defined tables (since we know for sure that our # parent table is defined within the same MetaData) mapper_args['inherit_condition'] = sql_util.join_condition( mapper_args['inherits'].__table__, table, ignore_nonexistent_tables=True) if table is None: # single table inheritance. # ensure no table args if table_args: raise exceptions.ArgumentError( "Can't place __table_args__ on an inherited class " "with no table." ) # add any columns declared here to the inherited table. for c in cols: if c.primary_key: raise exceptions.ArgumentError( "Can't place primary key columns on an inherited " "class with no table." ) if c.name in inherited_table.c: raise exceptions.ArgumentError( "Column '%s' on class %s conflicts with " "existing column '%s'" % (c, cls, inherited_table.c[c.name]) ) inherited_table.append_column(c) # single or joined inheritance # exclude any cols on the inherited table which are not mapped on the # parent class, to avoid # mapping columns specific to sibling/nephew classes inherited_mapper = class_mapper(mapper_args['inherits'], compile=False) inherited_table = inherited_mapper.local_table if 'exclude_properties' not in mapper_args: mapper_args['exclude_properties'] = exclude_properties = \ set([c.key for c in inherited_table.c if c not in inherited_mapper._columntoproperty]) exclude_properties.difference_update([c.key for c in cols]) cls.__mapper__ = mapper_cls(cls, table, properties=our_stuff, **mapper_args)
def _as_declarative(cls, classname, dict_): cls._decl_class_registry[classname] = cls our_stuff = util.OrderedDict() for k in dict_: value = dict_[k] if (isinstance(value, tuple) and len(value) == 1 and isinstance(value[0], (Column, MapperProperty))): util.warn("Ignoring declarative-like tuple value of attribute " "%s: possibly a copy-and-paste error with a comma " "left at the end of the line?" % k) continue if not isinstance(value, (Column, MapperProperty)): continue prop = _deferred_relation(cls, value) our_stuff[k] = prop # set up attributes in the order they were created our_stuff.sort(key=lambda key: our_stuff[key]._creation_order) # extract columns from the class dict cols = [] for key, c in our_stuff.iteritems(): if isinstance(c, ColumnProperty): for col in c.columns: if isinstance(col, Column) and col.table is None: _undefer_column_name(key, col) cols.append(col) elif isinstance(c, Column): _undefer_column_name(key, c) cols.append(c) # if the column is the same name as the key, # remove it from the explicit properties dict. # the normal rules for assigning column-based properties # will take over, including precedence of columns # in multi-column ColumnProperties. if key == c.key: del our_stuff[key] table = None if '__table__' not in cls.__dict__: if '__tablename__' in cls.__dict__: tablename = cls.__tablename__ table_args = cls.__dict__.get('__table_args__') if isinstance(table_args, dict): args, table_kw = (), table_args elif isinstance(table_args, tuple): args = table_args[0:-1] table_kw = table_args[-1] else: args, table_kw = (), {} autoload = cls.__dict__.get('__autoload__') if autoload: table_kw['autoload'] = True cls.__table__ = table = Table(tablename, cls.metadata, *(tuple(cols) + tuple(args)), **table_kw) else: table = cls.__table__ if cols: for c in cols: if not table.c.contains_column(c): raise exceptions.ArgumentError("Can't add additional column %r when specifying __table__" % key) mapper_args = getattr(cls, '__mapper_args__', {}) if 'inherits' not in mapper_args: for c in cls.__bases__: if _is_mapped_class(c): mapper_args['inherits'] = cls._decl_class_registry.get(c.__name__, None) break if hasattr(cls, '__mapper_cls__'): mapper_cls = util.unbound_method_to_callable(cls.__mapper_cls__) else: mapper_cls = mapper if not table and 'inherits' not in mapper_args: raise exceptions.InvalidRequestError("Class %r does not have a __table__ or __tablename__ " "specified and does not inherit from an existing table-mapped class." % cls) elif 'inherits' in mapper_args and not mapper_args.get('concrete', False): inherited_mapper = class_mapper(mapper_args['inherits'], compile=False) inherited_table = inherited_mapper.local_table if 'inherit_condition' not in mapper_args and table: # figure out the inherit condition with relaxed rules # about nonexistent tables, to allow for ForeignKeys to # not-yet-defined tables (since we know for sure that our # parent table is defined within the same MetaData) mapper_args['inherit_condition'] = sql_util.join_condition( mapper_args['inherits'].__table__, table, ignore_nonexistent_tables=True) if not table: # single table inheritance. # ensure no table args table_args = cls.__dict__.get('__table_args__') if table_args is not None: raise exceptions.ArgumentError("Can't place __table_args__ on an inherited class with no table.") # add any columns declared here to the inherited table. for c in cols: if c.primary_key: raise exceptions.ArgumentError("Can't place primary key columns on an inherited class with no table.") inherited_table.append_column(c) # single or joined inheritance # exclude any cols on the inherited table which are not mapped on the parent class, to avoid # mapping columns specific to sibling/nephew classes inherited_mapper = class_mapper(mapper_args['inherits'], compile=False) inherited_table = inherited_mapper.local_table if 'exclude_properties' not in mapper_args: mapper_args['exclude_properties'] = exclude_properties = \ set([c.key for c in inherited_table.c if c not in inherited_mapper._columntoproperty]) exclude_properties.difference_update([c.key for c in cols]) cls.__mapper__ = mapper_cls(cls, table, properties=our_stuff, **mapper_args)
def _as_declarative(cls, classname, dict_): cls._decl_class_registry[classname] = cls our_stuff = util.OrderedDict() for k in dict_: value = dict_[k] if (isinstance(value, tuple) and len(value) == 1 and isinstance(value[0], (Column, MapperProperty))): util.warn("Ignoring declarative-like tuple value of attribute " "%s: possibly a copy-and-paste error with a comma " "left at the end of the line?" % k) continue if not isinstance(value, (Column, MapperProperty)): continue prop = _deferred_relation(cls, value) our_stuff[k] = prop # set up attributes in the order they were created our_stuff.sort(key=lambda key: our_stuff[key]._creation_order) # extract columns from the class dict cols = [] for key, c in our_stuff.iteritems(): if isinstance(c, ColumnProperty): for col in c.columns: if isinstance(col, Column) and col.table is None: _undefer_column_name(key, col) cols.append(col) elif isinstance(c, Column): _undefer_column_name(key, c) cols.append(c) # if the column is the same name as the key, # remove it from the explicit properties dict. # the normal rules for assigning column-based properties # will take over, including precedence of columns # in multi-column ColumnProperties. if key == c.key: del our_stuff[key] table = None if '__table__' not in cls.__dict__: if '__tablename__' in cls.__dict__: tablename = cls.__tablename__ table_args = cls.__dict__.get('__table_args__') if isinstance(table_args, dict): args, table_kw = (), table_args elif isinstance(table_args, tuple): args = table_args[0:-1] table_kw = table_args[-1] if len(table_args) < 2 or not isinstance(table_kw, dict): raise exceptions.ArgumentError( "Tuple form of __table_args__ is " "(arg1, arg2, arg3, ..., {'kw1':val1, 'kw2':val2, ...})" ) else: args, table_kw = (), {} autoload = cls.__dict__.get('__autoload__') if autoload: table_kw['autoload'] = True cls.__table__ = table = Table(tablename, cls.metadata, *(tuple(cols) + tuple(args)), **table_kw) else: table = cls.__table__ if cols: for c in cols: if not table.c.contains_column(c): raise exceptions.ArgumentError( "Can't add additional column %r when specifying __table__" % key) mapper_args = getattr(cls, '__mapper_args__', {}) if 'inherits' not in mapper_args: for c in cls.__bases__: if _is_mapped_class(c): mapper_args['inherits'] = cls._decl_class_registry.get( c.__name__, None) break if hasattr(cls, '__mapper_cls__'): mapper_cls = util.unbound_method_to_callable(cls.__mapper_cls__) else: mapper_cls = mapper if not table and 'inherits' not in mapper_args: raise exceptions.InvalidRequestError( "Class %r does not have a __table__ or __tablename__ " "specified and does not inherit from an existing table-mapped class." % cls) elif 'inherits' in mapper_args and not mapper_args.get('concrete', False): inherited_mapper = class_mapper(mapper_args['inherits'], compile=False) inherited_table = inherited_mapper.local_table if 'inherit_condition' not in mapper_args and table: # figure out the inherit condition with relaxed rules # about nonexistent tables, to allow for ForeignKeys to # not-yet-defined tables (since we know for sure that our # parent table is defined within the same MetaData) mapper_args['inherit_condition'] = sql_util.join_condition( mapper_args['inherits'].__table__, table, ignore_nonexistent_tables=True) if not table: # single table inheritance. # ensure no table args table_args = cls.__dict__.get('__table_args__') if table_args is not None: raise exceptions.ArgumentError( "Can't place __table_args__ on an inherited class with no table." ) # add any columns declared here to the inherited table. for c in cols: if c.primary_key: raise exceptions.ArgumentError( "Can't place primary key columns on an inherited class with no table." ) inherited_table.append_column(c) # single or joined inheritance # exclude any cols on the inherited table which are not mapped on the parent class, to avoid # mapping columns specific to sibling/nephew classes inherited_mapper = class_mapper(mapper_args['inherits'], compile=False) inherited_table = inherited_mapper.local_table if 'exclude_properties' not in mapper_args: mapper_args['exclude_properties'] = exclude_properties = \ set([c.key for c in inherited_table.c if c not in inherited_mapper._columntoproperty]) exclude_properties.difference_update([c.key for c in cols]) cls.__mapper__ = mapper_cls(cls, table, properties=our_stuff, **mapper_args)
def _as_declarative(cls, classname, dict_): # doing it this way enables these attributes to be descriptors, # see below... get_mapper_args = '__mapper_args__' in dict_ get_table_args = '__table_args__' in dict_ # dict_ will be a dictproxy, which we can't write to, and we need to! dict_ = dict(dict_) column_copies = dict() for base in cls.__bases__: names = dir(base) if not _is_mapped_class(base): for name in names: obj = getattr(base,name) if isinstance(obj, Column): dict_[name]=column_copies[obj]=obj.copy() get_mapper_args = get_mapper_args or getattr(base,'__mapper_args__',None) get_table_args = get_table_args or getattr(base,'__table_args__',None) tablename = getattr(base,'__tablename__',None) if tablename: # subtle: if tablename is a descriptor here, we actually # put the wrong value in, but it serves as a marker to get # the right value value... dict_['__tablename__']=tablename # now that we know whether or not to get these, get them from the class # if we should, enabling them to be decorators mapper_args = get_mapper_args and cls.__mapper_args__ or {} table_args = get_table_args and cls.__table_args__ or None # make sure that column copies are used rather than the original columns # from any mixins for k, v in mapper_args.iteritems(): mapper_args[k] = column_copies.get(v,v) cls._decl_class_registry[classname] = cls our_stuff = util.OrderedDict() for k in dict_: value = dict_[k] if (isinstance(value, tuple) and len(value) == 1 and isinstance(value[0], (Column, MapperProperty))): util.warn("Ignoring declarative-like tuple value of attribute " "%s: possibly a copy-and-paste error with a comma " "left at the end of the line?" % k) continue if not isinstance(value, (Column, MapperProperty)): continue prop = _deferred_relation(cls, value) our_stuff[k] = prop # set up attributes in the order they were created our_stuff.sort(key=lambda key: our_stuff[key]._creation_order) # extract columns from the class dict cols = [] for key, c in our_stuff.iteritems(): if isinstance(c, ColumnProperty): for col in c.columns: if isinstance(col, Column) and col.table is None: _undefer_column_name(key, col) cols.append(col) elif isinstance(c, Column): _undefer_column_name(key, c) cols.append(c) # if the column is the same name as the key, # remove it from the explicit properties dict. # the normal rules for assigning column-based properties # will take over, including precedence of columns # in multi-column ColumnProperties. if key == c.key: del our_stuff[key] table = None if '__table__' not in dict_: if '__tablename__' in dict_: # see above: if __tablename__ is a descriptor, this # means we get the right value used! tablename = cls.__tablename__ if isinstance(table_args, dict): args, table_kw = (), table_args elif isinstance(table_args, tuple): args = table_args[0:-1] table_kw = table_args[-1] if len(table_args) < 2 or not isinstance(table_kw, dict): raise exceptions.ArgumentError( "Tuple form of __table_args__ is " "(arg1, arg2, arg3, ..., {'kw1':val1, 'kw2':val2, ...})" ) else: args, table_kw = (), {} autoload = dict_.get('__autoload__') if autoload: table_kw['autoload'] = True cls.__table__ = table = Table(tablename, cls.metadata, *(tuple(cols) + tuple(args)), **table_kw) else: table = cls.__table__ if cols: for c in cols: if not table.c.contains_column(c): raise exceptions.ArgumentError( "Can't add additional column %r when specifying __table__" % key ) if 'inherits' not in mapper_args: for c in cls.__bases__: if _is_mapped_class(c): mapper_args['inherits'] = cls._decl_class_registry.get(c.__name__, None) break if hasattr(cls, '__mapper_cls__'): mapper_cls = util.unbound_method_to_callable(cls.__mapper_cls__) else: mapper_cls = mapper if table is None and 'inherits' not in mapper_args: raise exceptions.InvalidRequestError( "Class %r does not have a __table__ or __tablename__ " "specified and does not inherit from an existing table-mapped class." % cls ) elif 'inherits' in mapper_args and not mapper_args.get('concrete', False): inherited_mapper = class_mapper(mapper_args['inherits'], compile=False) inherited_table = inherited_mapper.local_table if 'inherit_condition' not in mapper_args and table is not None: # figure out the inherit condition with relaxed rules # about nonexistent tables, to allow for ForeignKeys to # not-yet-defined tables (since we know for sure that our # parent table is defined within the same MetaData) mapper_args['inherit_condition'] = sql_util.join_condition( mapper_args['inherits'].__table__, table, ignore_nonexistent_tables=True) if table is None: # single table inheritance. # ensure no table args if table_args is not None: raise exceptions.ArgumentError( "Can't place __table_args__ on an inherited class with no table." ) # add any columns declared here to the inherited table. for c in cols: if c.primary_key: raise exceptions.ArgumentError( "Can't place primary key columns on an inherited class with no table." ) inherited_table.append_column(c) # single or joined inheritance # exclude any cols on the inherited table which are not mapped on the # parent class, to avoid # mapping columns specific to sibling/nephew classes inherited_mapper = class_mapper(mapper_args['inherits'], compile=False) inherited_table = inherited_mapper.local_table if 'exclude_properties' not in mapper_args: mapper_args['exclude_properties'] = exclude_properties = \ set([c.key for c in inherited_table.c if c not in inherited_mapper._columntoproperty]) exclude_properties.difference_update([c.key for c in cols]) cls.__mapper__ = mapper_cls(cls, table, properties=our_stuff, **mapper_args)