Exemplo n.º 1
0
    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_))
Exemplo n.º 2
0
    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)))
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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_))
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
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))))
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
    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
Exemplo n.º 9
0
    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)))
Exemplo n.º 10
0
    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
Exemplo n.º 11
0
 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)
Exemplo n.º 12
0
 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)))
Exemplo n.º 13
0
    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))
Exemplo n.º 14
0
        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))
Exemplo n.º 15
0
    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()
Exemplo n.º 16
0
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)
Exemplo n.º 17
0
    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
Exemplo n.º 18
0
    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()
Exemplo n.º 19
0
 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)
Exemplo n.º 20
0
    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))
Exemplo n.º 21
0
    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)
Exemplo n.º 22
0
    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))
Exemplo n.º 23
0
    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
Exemplo n.º 24
0
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)
Exemplo n.º 25
0
 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)
Exemplo n.º 26
0
 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))
Exemplo n.º 27
0
    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)
Exemplo n.º 28
0
    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
Exemplo n.º 29
0
    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))]
Exemplo n.º 30
0
 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)