def __determine_targets(self): if isinstance(self.argument, type): self.mapper = mapper.class_mapper(self.argument, entity_name=self.entity_name, compile=False) elif isinstance(self.argument, mapper.Mapper): self.mapper = self.argument elif callable(self.argument): # accept a callable to suit various deferred-configurational schemes self.mapper = mapper.class_mapper(self.argument(), entity_name=self.entity_name, compile=False) else: raise exceptions.ArgumentError("relation '%s' expects a class or a mapper argument (received: %s)" % (self.key, type(self.argument))) if not self.parent.concrete: for inheriting in self.parent.iterate_to_root(): if inheriting is not self.parent and inheriting._get_property(self.key, raiseerr=False): util.warn( ("Warning: relation '%s' on mapper '%s' supercedes " "the same relation on inherited mapper '%s'; this " "can cause dependency issues during flush") % (self.key, self.parent, inheriting)) self.target = self.mapper.mapped_table self.table = self.mapper.mapped_table if self.cascade.delete_orphan: if self.parent.class_ is self.mapper.class_: raise exceptions.ArgumentError("In relationship '%s', can't establish 'delete-orphan' cascade " "rule on a self-referential relationship. " "You probably want cascade='all', which includes delete cascading but not orphan detection." %(str(self))) self.mapper.primary_mapper().delete_orphans.append((self.key, self.parent.class_))
def _determine_direction(self): """Determine our *direction*, i.e. do we represent one to many, many to many, etc. """ if self.secondaryjoin is not None: self.direction = sync.MANYTOMANY elif self._is_self_referential(): # for a self referential mapper, if the "foreignkey" is a single or composite primary key, # then we are "many to one", since the remote site of the relationship identifies a singular entity. # otherwise we are "one to many". if self._legacy_foreignkey: for f in self._legacy_foreignkey: if not f.primary_key: self.direction = sync.ONETOMANY else: self.direction = sync.MANYTOONE elif self.remote_side: for f in self.foreign_keys: if f in self.remote_side: self.direction = sync.ONETOMANY return else: self.direction = sync.MANYTOONE else: self.direction = sync.ONETOMANY else: for mappedtable, parenttable in [ (self.mapper.mapped_table, self.parent.mapped_table), (self.mapper.local_table, self.parent.local_table) ]: onetomany = len([ c for c in self.foreign_keys if mappedtable.c.contains_column(c) ]) manytoone = len([ c for c in self.foreign_keys if parenttable.c.contains_column(c) ]) if not onetomany and not manytoone: raise exceptions.ArgumentError( "Can't determine relation direction for relationship '%s' " "- foreign key columns are present in neither the " "parent nor the child's mapped tables" % (str(self))) elif onetomany and manytoone: continue elif onetomany: self.direction = sync.ONETOMANY break elif manytoone: self.direction = sync.MANYTOONE break else: raise exceptions.ArgumentError( "Can't determine relation direction for relationship '%s' " "- foreign key columns are present in both the parent and " "the child's mapped tables. Specify 'foreign_keys' " "argument." % (str(self)))
def wrapper(*args, **kw): if before: if pos_arg is None: if named_arg not in kw: raise exceptions.ArgumentError("Missing argument %s" % argument) value = kw[named_arg] else: if len(args) > pos_arg: value = args[pos_arg] elif named_arg in kw: value = kw[named_arg] else: raise exceptions.ArgumentError("Missing argument %s" % argument) initiator = kw.pop('_sa_initiator', None) if initiator is False: executor = None else: executor = getattr(args[0], '_sa_adapter', None) if before and executor: getattr(executor, before)(value, initiator) if not after or not executor: return method(*args, **kw) else: res = method(*args, **kw) if res is not None: getattr(executor, after)(res, initiator) return res
def _determine_targets(self): if isinstance(self.argument, type): self.mapper = mapper.class_mapper(self.argument, compile=False)._check_compile() elif isinstance(self.argument, mapper.Mapper): self.mapper = self.argument._check_compile() else: raise exceptions.ArgumentError( "relation '%s' expects a class or a mapper argument (received: %s)" % (self.key, type(self.argument))) # ensure the "select_mapper", if different from the regular target mapper, is compiled. self.mapper.get_select_mapper()._check_compile() if self.association is not None: if isinstance(self.association, type): self.association = mapper.class_mapper( self.association, compile=False)._check_compile() self.target = self.mapper.mapped_table self.select_mapper = self.mapper.get_select_mapper() self.select_table = self.mapper.select_table self.loads_polymorphic = self.target is not self.select_table if self.cascade.delete_orphan: if self.parent.class_ is self.mapper.class_: raise exceptions.ArgumentError( "In relationship '%s', can't establish 'delete-orphan' cascade rule on a self-referential relationship. You probably want cascade='all', which includes delete cascading but not orphan detection." % (str(self))) self.mapper.primary_mapper().delete_orphans.append( (self.key, self.parent.class_))
def identity_key(self, *args, **kwargs): """Get an identity key. Valid call signatures: identity_key(class\_, ident, entity_name=None) class\_ mapped class (must be a positional argument) ident primary key, if the key is composite this is a tuple entity_name optional entity name identity_key(instance=instance) instance object instance (must be given as a keyword arg) identity_key(class\_, row=row, entity_name=None) class\_ mapped class (must be a positional argument) row result proxy row (must be given as a keyword arg) entity_name optional entity name (must be given as a keyword arg) """ if args: if len(args) == 1: class_ = args[0] try: row = kwargs.pop("row") except KeyError: ident = kwargs.pop("ident") entity_name = kwargs.pop("entity_name", None) elif len(args) == 2: class_, ident = args entity_name = kwargs.pop("entity_name", None) elif len(args) == 3: class_, ident, entity_name = args else: raise exceptions.ArgumentError("expected up to three " "positional arguments, got %s" % len(args)) if kwargs: raise exceptions.ArgumentError( "unknown keyword arguments: %s" % ", ".join(kwargs.keys())) mapper = _class_mapper(class_, entity_name=entity_name) if "ident" in locals(): return mapper.identity_key_from_primary_key(ident) return mapper.identity_key_from_row(row) instance = kwargs.pop("instance") if kwargs: raise exceptions.ArgumentError("unknown keyword arguments: %s" % ", ".join(kwargs.keys())) mapper = _object_mapper(instance) return mapper.identity_key_from_instance(instance)
def assert_arg_type(arg, argtype, name): if isinstance(arg, argtype): return arg else: if isinstance(argtype, tuple): raise exceptions.ArgumentError("Argument '%s' is expected to be one of type %s, got '%s'" % (name, ' or '.join(["'%s'" % str(a) for a in argtype]), str(type(arg)))) else: raise exceptions.ArgumentError("Argument '%s' is expected to be of type '%s', got '%s'" % (name, str(argtype), str(type(arg))))
def join_condition(a, b, ignore_nonexistent_tables=False): """create a join condition between two tables. ignore_nonexistent_tables=True allows a join condition to be determined between two tables which may contain references to other not-yet-defined tables. In general the NoSuchTableError raised is only required if the user is trying to join selectables across multiple MetaData objects (which is an extremely rare use case). """ crit = [] constraints = util.Set() for fk in b.foreign_keys: try: col = fk.get_referent(a) except exceptions.NoReferencedTableError: if ignore_nonexistent_tables: continue else: raise if col: crit.append(col == fk.parent) constraints.add(fk.constraint) if a is not b: for fk in a.foreign_keys: try: col = fk.get_referent(b) except exceptions.NoReferencedTableError: if ignore_nonexistent_tables: continue else: raise if col: crit.append(col == fk.parent) constraints.add(fk.constraint) if len(crit) == 0: raise exceptions.ArgumentError( "Can't find any foreign key relationships " "between '%s' and '%s'" % (a.description, b.description)) elif len(constraints) > 1: raise exceptions.ArgumentError( "Can't determine join between '%s' and '%s'; " "tables have more than one foreign key " "constraint relationship between them. " "Please specify the 'onclause' of this " "join explicitly." % (a.description, b.description)) elif len(crit) == 1: return (crit[0]) else: return sql.and_(*crit)
def __call__(self, name, metadata, *args, **kwargs): try: if isinstance(metadata, sql.Engine): # backwards compatibility - get a BoundSchema associated with the engine engine = metadata if not hasattr(engine, '_legacy_metadata'): engine._legacy_metadata = BoundMetaData(engine) metadata = engine._legacy_metadata elif metadata is not None and not isinstance(metadata, MetaData): # they left MetaData out, so assume its another SchemaItem, add it to *args args = list(args) args.insert(0, metadata) metadata = None if metadata is None: metadata = default_metadata name = str(name) # in case of incoming unicode schema = kwargs.get('schema', None) autoload = kwargs.pop('autoload', False) autoload_with = kwargs.pop('autoload_with', False) redefine = kwargs.pop('redefine', False) mustexist = kwargs.pop('mustexist', False) useexisting = kwargs.pop('useexisting', False) key = _get_table_key(name, schema) table = metadata.tables[key] if len(args): if redefine: table._reload_values(*args) elif not useexisting: raise exceptions.ArgumentError( "Table '%s.%s' is already defined. specify 'redefine=True' to remap columns, or 'useexisting=True' to use the existing table" % (schema, name)) return table except KeyError: if mustexist: raise exceptions.ArgumentError("Table '%s.%s' not defined" % (schema, name)) table = type.__call__(self, name, metadata, **kwargs) table._set_parent(metadata) # load column definitions from the database if 'autoload' is defined # we do it after the table is in the singleton dictionary to support # circular foreign keys if autoload: if autoload_with: autoload_with.reflecttable(table) else: metadata.engine.reflecttable(table) # initialize all the column, etc. objects. done after # reflection to allow user-overrides table._init_items(*args) return table
def _determine_direction(self): if self.secondaryjoin is not None: self.direction = MANYTOMANY elif self._refers_to_parent_table(): # self referential defaults to ONETOMANY unless the "remote" side is present # and does not reference any foreign key columns if self.local_remote_pairs: remote = [r for l, r in self.local_remote_pairs] elif self.remote_side: remote = self.remote_side else: remote = None if not remote or self._foreign_keys.intersection(remote): self.direction = ONETOMANY else: self.direction = MANYTOONE else: for mappedtable, parenttable in [ (self.mapper.mapped_table, self.parent.mapped_table), (self.mapper.local_table, self.parent.local_table) ]: onetomany = [ c for c in self._foreign_keys if mappedtable.c.contains_column(c) ] manytoone = [ c for c in self._foreign_keys if parenttable.c.contains_column(c) ] if not onetomany and not manytoone: raise sa_exc.ArgumentError( "Can't determine relation direction for relationship '%s' " "- foreign key columns are present in neither the " "parent nor the child's mapped tables" % (str(self))) elif onetomany and manytoone: continue elif onetomany: self.direction = ONETOMANY break elif manytoone: self.direction = MANYTOONE break else: raise sa_exc.ArgumentError( "Can't determine relation direction for relationship '%s' " "- foreign key columns are present in both the parent and " "the child's mapped tables. Specify 'foreign_keys' " "argument." % (str(self)))
def _get_paths(self, query, raiseerr): path = None l = [] current_path = list(query._current_path) if self.mapper: global class_mapper if class_mapper is None: from sqlalchemy.orm import class_mapper mapper = self.mapper if isinstance(self.mapper, type): mapper = class_mapper(mapper) if mapper is not query.mapper and mapper not in [ q.mapper for q in query._entities ]: raise exceptions.ArgumentError( "Can't find entity %s in Query. Current list: %r" % (str(mapper), [str(m) for m in query._entities])) else: mapper = query.mapper if isinstance(self.key, basestring): tokens = self.key.split('.') else: tokens = util.to_list(self.key) for token in tokens: if isinstance(token, basestring): prop = mapper.get_property(token, resolve_synonyms=True, raiseerr=raiseerr) elif isinstance(token, PropComparator): prop = token.property token = prop.key else: raise exceptions.ArgumentError( "mapper option expects string key or list of attributes") if current_path and token == current_path[1]: current_path = current_path[2:] continue if prop is None: return [] path = build_path(mapper, prop.key, path) l.append(path) if getattr(token, '_of_type', None): mapper = token._of_type else: mapper = getattr(prop, 'mapper', None) return l
def __init__(self, **kwargs): for key, value in kwargs.items(): if validate: if not key in self.mapper.props: raise exceptions.ArgumentError( "Invalid __init__ argument: '%s'" % key) setattr(self, key, value)
def _get_direction(self): """determines our 'direction', i.e. do we represent one to many, many to many, etc.""" if self.secondaryjoin is not None: return sync.MANYTOMANY elif self.parent.mapped_table is self.target or self.parent.select_table is self.target: if list(self.foreignkey)[0].primary_key: return sync.MANYTOONE else: return sync.ONETOMANY elif len([ c for c in self.foreignkey if self.mapper.unjoined_table.corresponding_column(c, False) is not None ]): return sync.ONETOMANY elif len([ c for c in self.foreignkey if self.parent.unjoined_table.corresponding_column(c, False) is not None ]): return sync.MANYTOONE else: raise exceptions.ArgumentError( "Cant determine relation direction '%s', for '%s' in mapper '%s' with primary join\n '%s'" % (repr(self.foreignkey), self.key, str( self.mapper), str(self.primaryjoin)))
def compile(self, prop): if self.prop: return self.prop = prop mapper = prop.mapper.primary_mapper() if mapper._get_property(self.key, raiseerr=False) is None: if prop.secondary: pj = self.kwargs.pop('primaryjoin', prop.secondaryjoin) sj = self.kwargs.pop('secondaryjoin', prop.primaryjoin) else: pj = self.kwargs.pop('primaryjoin', prop.primaryjoin) sj = self.kwargs.pop('secondaryjoin', None) if sj: raise sa_exc.InvalidRequestError( "Can't assign 'secondaryjoin' on a backref against " "a non-secondary relation.") parent = prop.parent.primary_mapper() self.kwargs.setdefault('viewonly', prop.viewonly) self.kwargs.setdefault('post_update', prop.post_update) relation = RelationProperty(parent, prop.secondary, pj, sj, backref=BackRef(prop.key, _prop=prop), **self.kwargs) mapper._configure_property(self.key, relation); prop._add_reverse_property(self.key) else: raise sa_exc.ArgumentError("Error creating backref '%s' on relation '%s': " "property of that name exists on mapper '%s'" % (self.key, prop, mapper))
def compile_binary(binary): """Assemble a SyncRule given a single binary condition.""" if binary.operator != operators.eq or not isinstance( binary.left, schema.Column) or not isinstance( binary.right, schema.Column): return source_column = None dest_column = None if foreign_keys is None: if binary.left.table == binary.right.table: raise exceptions.ArgumentError( "need foreign_keys argument for self-referential sync") if binary.left in util.Set( [f.column for f in binary.right.foreign_keys]): dest_column = binary.right source_column = binary.left elif binary.right in util.Set( [f.column for f in binary.left.foreign_keys]): dest_column = binary.left source_column = binary.right else: if binary.left in foreign_keys: source_column = binary.right dest_column = binary.left elif binary.right in foreign_keys: source_column = binary.left dest_column = binary.right if source_column and dest_column: if self.direction == ONETOMANY: self.syncrules.append( SyncRule(self.parent_mapper, source_column, dest_column, dest_mapper=self.child_mapper)) elif self.direction == MANYTOONE: self.syncrules.append( SyncRule(self.child_mapper, source_column, dest_column, dest_mapper=self.parent_mapper)) else: if not issecondary: self.syncrules.append( SyncRule(self.parent_mapper, source_column, dest_column, dest_mapper=self.child_mapper, issecondary=issecondary)) else: self.syncrules.append( SyncRule(self.child_mapper, source_column, dest_column, dest_mapper=self.parent_mapper, issecondary=issecondary))
def _post_init(self): if self._should_log_info: self.logger.info(str(self) + " setup primary join %s" % self.primaryjoin) self.logger.info(str(self) + " setup secondary join %s" % self.secondaryjoin) self.logger.info(str(self) + " synchronize pairs [%s]" % ",".join("(%s => %s)" % (l, r) for l, r in self.synchronize_pairs)) self.logger.info(str(self) + " secondary synchronize pairs [%s]" % ",".join(("(%s => %s)" % (l, r) for l, r in self.secondary_synchronize_pairs or []))) self.logger.info(str(self) + " local/remote pairs [%s]" % ",".join("(%s / %s)" % (l, r) for l, r in self.local_remote_pairs)) self.logger.info(str(self) + " relation direction %s" % self.direction) if self.uselist is None and self.direction is MANYTOONE: self.uselist = False if self.uselist is None: self.uselist = True if not self.viewonly: self._dependency_processor = dependency.create_dependency_processor(self) # primary property handler, set up class attributes if self.is_primary(): if self.back_populates: self.extension = util.to_list(self.extension) or [] self.extension.append(attributes.GenericBackrefExtension(self.back_populates)) self._add_reverse_property(self.back_populates) if self.backref is not None: self.backref.compile(self) elif not mapper.class_mapper(self.parent.class_, compile=False)._get_property(self.key, raiseerr=False): raise sa_exc.ArgumentError("Attempting to assign a new relation '%s' to " "a non-primary mapper on class '%s'. New relations can only be " "added to the primary mapper, i.e. the very first " "mapper created for class '%s' " % (self.key, self.parent.class_.__name__, self.parent.class_.__name__)) super(RelationProperty, self).do_init()
def column_mapped_collection(mapping_spec): """A dictionary-based collection type with column-based keying. Returns a MappedCollection factory with a keying function generated from mapping_spec, which may be a Column or a sequence of Columns. The key value must be immutable for the lifetime of the object. You can not, for example, map on foreign key values if those key values will change during the session, i.e. from None to a database-assigned integer after a session flush. """ if isinstance(mapping_spec, schema.Column): def keyfunc(value): m = mapper.object_mapper(value) return m.get_attr_by_column(value, mapping_spec) else: cols = [] for c in mapping_spec: if not isinstance(c, schema.Column): raise exceptions.ArgumentError( "mapping_spec tuple may only contain columns") cols.append(c) mapping_spec = tuple(cols) def keyfunc(value): m = mapper.object_mapper(value) return tuple( [m.get_attr_by_column(value, c) for c in mapping_spec]) return lambda: MappedCollection(keyfunc)
def _get_paths(self, query, raiseerr): path = None l = [] current_path = list(query._current_path) if self.mapper: global class_mapper if class_mapper is None: from sqlalchemy.orm import class_mapper mapper = self.mapper if isinstance(self.mapper, type): mapper = class_mapper(mapper) if mapper is not query.mapper and mapper not in [ q[0] for q in query._entities ]: raise exceptions.ArgumentError( "Can't find entity %s in Query. Current list: %r" % (str(mapper), [str(m) for m in [query.mapper] + query._entities])) else: mapper = query.mapper for token in self.key.split('.'): if current_path and token == current_path[1]: current_path = current_path[2:] continue prop = mapper.get_property(token, resolve_synonyms=True, raiseerr=raiseerr) if prop is None: return [] path = build_path(mapper, prop.key, path) l.append(path) mapper = getattr(prop, 'mapper', None) return l
def _post_init(self): if logging.is_info_enabled(self.logger): self.logger.info(str(self) + " setup primary join %s" % self.primaryjoin) self.logger.info(str(self) + " setup secondary join %s" % self.secondaryjoin) self.logger.info(str(self) + " synchronize pairs [%s]" % ",".join(["(%s => %s)" % (l, r) for l, r in self.synchronize_pairs])) self.logger.info(str(self) + " secondary synchronize pairs [%s]" % ",".join(["(%s => %s)" % (l, r) for l, r in self.secondary_synchronize_pairs or []])) self.logger.info(str(self) + " local/remote pairs [%s]" % ",".join(["(%s / %s)" % (l, r) for l, r in self.local_remote_pairs])) self.logger.info(str(self) + " relation direction %s" % self.direction) if self.uselist is None and self.direction is MANYTOONE: self.uselist = False if self.uselist is None: self.uselist = True if not self.viewonly: self._dependency_processor = dependency.create_dependency_processor(self) # primary property handler, set up class attributes if self.is_primary(): # if a backref name is defined, set up an extension to populate # attributes in the other direction if self.backref is not None: self.attributeext = self.backref.get_extension() if self.backref is not None: self.backref.compile(self) elif not mapper.class_mapper(self.parent.class_, compile=False)._get_property(self.key, raiseerr=False): raise exceptions.ArgumentError("Attempting to assign a new relation '%s' to a non-primary mapper on class '%s'. New relations can only be added to the primary mapper, i.e. the very first mapper created for class '%s' " % (self.key, self.parent.class_.__name__, self.parent.class_.__name__)) super(PropertyLoader, self).do_init()
def append_column(self, column): # make sure all columns are from the same table # and no column is repeated if self.table is None: self.table = column.table self.table.append_index(self) elif column.table != self.table: # all columns muse be from same table raise exceptions.ArgumentError( "All index columns must be from same table. " "%s is from %s not %s" % (column, column.table, self.table)) elif column.name in [c.name for c in self.columns]: raise exceptions.ArgumentError( "A column may not appear twice in the " "same index (%s already has column %s)" % (self.name, column)) self.columns.append(column)
def compile(self, prop): if self.prop: return self.prop = prop mapper = prop.mapper.primary_mapper() if mapper._get_property(self.key, raiseerr=False) is None: pj = self.kwargs.pop('primaryjoin', None) sj = self.kwargs.pop('secondaryjoin', None) parent = prop.parent.primary_mapper() self.kwargs.setdefault('viewonly', prop.viewonly) self.kwargs.setdefault('post_update', prop.post_update) relation = PropertyLoader(parent, prop.secondary, pj, sj, backref=BackRef(prop.key, _prop=prop), is_backref=True, **self.kwargs) mapper._compile_property(self.key, relation); prop._reverse_property = mapper._get_property(self.key) mapper._get_property(self.key)._reverse_property = prop else: raise exceptions.ArgumentError("Error creating backref '%s' on relation '%s': property of that name exists on mapper '%s'" % (self.key, prop, mapper))
def __init__(self, attr, obj, data, init=True): self.attr = attr # this weakref is to prevent circular references between the parent object # and the list attribute, which interferes with immediate garbage collection. self.__obj = weakref.ref(obj) self.key = attr.key self.data = data or attr._blank_list() # adapt to lists or sets # TODO: make three subclasses of InstrumentedList that come off from a # metaclass, based on the type of data sent in if hasattr(self.data, 'append'): self._data_appender = self.data.append self._clear_data = self._clear_list elif hasattr(self.data, 'add'): self._data_appender = self.data.add self._clear_data = self._clear_set else: raise exceptions.ArgumentError("Collection type " + repr(type(self.data)) + " has no append() or add() method") if isinstance(self.data, dict): self._clear_data = self._clear_dict if init: for x in self.data: self.__setrecord(x)
def _new(self, lazy_collection): creator = self.creator and self.creator or self.target_class self.collection_class = util.duck_type_collection(lazy_collection()) if self.proxy_factory: return self.proxy_factory(lazy_collection, creator, self.value_attr, self) if self.getset_factory: getter, setter = self.getset_factory(self.collection_class, self) else: getter, setter = self._default_getset(self.collection_class) if self.collection_class is list: return _AssociationList(lazy_collection, creator, getter, setter, self) elif self.collection_class is dict: return _AssociationDict(lazy_collection, creator, getter, setter, self) elif self.collection_class is set: return _AssociationSet(lazy_collection, creator, getter, setter, self) else: raise exceptions.ArgumentError( 'could not guess which interface to use for ' 'collection_class "%s" backing "%s"; specify a ' 'proxy_factory and proxy_bulk_set manually' % (self.collection_class.__name__, self.target_collection))
def __get_paths(self, query, raiseerr): path = None entity = None l = [] # _current_path implies we're in a secondary load # with an existing path current_path = list(query._current_path) if self.mapper: entity = self.__find_entity(query, self.mapper, raiseerr) mapper = entity.mapper path_element = entity.path_entity for key in util.to_list(self.key): if isinstance(key, basestring): tokens = key.split('.') else: tokens = [key] for token in tokens: if isinstance(token, basestring): if not entity: entity = query._entity_zero() path_element = entity.path_entity mapper = entity.mapper prop = mapper.get_property(token, resolve_synonyms=True, raiseerr=raiseerr) key = token elif isinstance(token, PropComparator): prop = token.property if not entity: entity = self.__find_entity(query, token.parententity, raiseerr) if not entity: return [] path_element = entity.path_entity key = prop.key else: raise sa_exc.ArgumentError("mapper option expects string key or list of attributes") if current_path and key == current_path[1]: current_path = current_path[2:] continue if prop is None: return [] path = build_path(path_element, prop.key, path) l.append(path) if getattr(token, '_of_type', None): path_element = mapper = token._of_type else: path_element = mapper = getattr(prop, 'mapper', None) if path_element: path_element = path_element.base_mapper # if current_path tokens remain, then # we didn't have an exact path match. if current_path: return [] return l
def relation(*args, **kwargs): """provides a relationship of a primary Mapper to a secondary Mapper, which corresponds to a parent-child or associative table relationship.""" if len(args) > 1 and isinstance(args[0], type): raise exceptions.ArgumentError( "relation(class, table, **kwargs) is deprecated. Please use relation(class, **kwargs) or relation(mapper, **kwargs)." ) return _relation_loader(*args, **kwargs)
def __init__(self, **kwargs): for key, value in kwargs.items(): if ext.validate: if not mapper.get_property(key, resolve_synonyms=False, raiseerr=False): raise sa_exc.ArgumentError( "Invalid __init__ argument: '%s'" % key) setattr(self, key, value)
def _add_reverse_property(self, key): other = self.mapper._get_property(key) self._reverse_property.add(other) other._reverse_property.add(self) if not other._get_target().common_parent(self.parent): raise sa_exc.ArgumentError("reverse_property %r on relation %s references " "relation %s, which does not reference mapper %s" % (key, self, other, self.parent))
def traverse(self, elem, clone=True): if not clone: raise exceptions.ArgumentError( "AbstractClauseProcessor 'clone' argument must be True") return self._traverse(elem, util.Set(self.stop_on or []), {}, _clone_toplevel=True)
def compile(self, prop): """Called by the owning PropertyLoader to set up a backreference on the PropertyLoader's mapper. """ # try to set a LazyLoader on our mapper referencing the parent mapper mapper = prop.mapper.primary_mapper() if not mapper.get_property(self.key, raiseerr=False) is not None: pj = self.kwargs.pop('primaryjoin', None) sj = self.kwargs.pop('secondaryjoin', None) # the backref property is set on the primary mapper parent = prop.parent.primary_mapper() self.kwargs.setdefault('viewonly', prop.viewonly) self.kwargs.setdefault('post_update', prop.post_update) relation = PropertyLoader(parent, prop.secondary, pj, sj, backref=prop.key, is_backref=True, **self.kwargs) mapper._compile_property(self.key, relation) elif not isinstance(mapper.get_property(self.key), PropertyLoader): raise exceptions.ArgumentError( "Can't create backref '%s' on mapper '%s'; an incompatible " "property of that name already exists" % (self.key, str(mapper))) else: # else set one of us as the "backreference" parent = prop.parent.primary_mapper() if parent.class_ is not mapper.get_property( self.key)._get_target_class(): raise exceptions.ArgumentError( "Backrefs do not match: backref '%s' expects to connect to %s, " "but found a backref already connected to %s" % (self.key, str(parent.class_), str(mapper.get_property(self.key).mapper.class_))) if not mapper.get_property(self.key).is_backref: prop.is_backref = True if not prop.viewonly: prop._dependency_processor.is_backref = True # reverse_property used by dependencies.ManyToManyDP to check # association table operations prop.reverse_property = mapper.get_property(self.key) mapper.get_property(self.key).reverse_property = prop
def _determine_local_remote_pairs(self): if not self.local_remote_pairs: if self.remote_side: if self.direction is MANYTOONE: self.local_remote_pairs = [ (r, l) for l, r in criterion_as_pairs(self.primaryjoin, consider_as_referenced_keys=self.remote_side, any_operator=True) ] else: self.local_remote_pairs = criterion_as_pairs(self.primaryjoin, consider_as_foreign_keys=self.remote_side, any_operator=True) if not self.local_remote_pairs: raise sa_exc.ArgumentError("Relation %s could not determine any local/remote column pairs from remote side argument %r" % (self, self.remote_side)) else: if self.viewonly: eq_pairs = self.synchronize_pairs if self.secondaryjoin: eq_pairs += self.secondary_synchronize_pairs else: eq_pairs = criterion_as_pairs(self.primaryjoin, consider_as_foreign_keys=self._foreign_keys, any_operator=True) if self.secondaryjoin: eq_pairs += criterion_as_pairs(self.secondaryjoin, consider_as_foreign_keys=self._foreign_keys, any_operator=True) eq_pairs = [(l, r) for l, r in eq_pairs if self._col_is_part_of_mappings(l) and self._col_is_part_of_mappings(r)] if self.direction is MANYTOONE: self.local_remote_pairs = [(r, l) for l, r in eq_pairs] else: self.local_remote_pairs = eq_pairs elif self.remote_side: raise sa_exc.ArgumentError("remote_side argument is redundant against more detailed _local_remote_side argument.") for l, r in self.local_remote_pairs: if self.direction is ONETOMANY and not self._col_is_part_of_mappings(l): raise sa_exc.ArgumentError("Local column '%s' is not part of mapping %s. " "Specify remote_side argument to indicate which column " "lazy join condition should compare against." % (l, self.parent)) elif self.direction is MANYTOONE and not self._col_is_part_of_mappings(r): raise sa_exc.ArgumentError("Remote column '%s' is not part of mapping %s. " "Specify remote_side argument to indicate which column lazy " "join condition should bind." % (r, self.mapper)) self.local_side, self.remote_side = [util.ordered_column_set(x) for x in zip(*list(self.local_remote_pairs))]
def __init__(self, precision=10, length=2, **kw): if (precision is None and length is not None) or (precision is not None and length is None): raise exceptions.ArgumentError( "You must specify both precision and length or omit both altogether." ) self.unsigned = 'unsigned' in kw self.zerofill = 'zerofill' in kw super(MSDouble, self).__init__(precision, length)