def _entity_descriptor(entity, key): """Return attribute/property information given an entity and string name. Returns a 2-tuple representing InstrumentedAttribute/MapperProperty. """ if isinstance(entity, AliasedClass): try: desc = getattr(entity, key) return desc, desc.property except AttributeError: raise sa_exc.InvalidRequestError( "Entity '%s' has no property '%s'" % (entity, key)) elif isinstance(entity, type): try: desc = attributes.manager_of_class(entity)[key] return desc, desc.property except KeyError: raise sa_exc.InvalidRequestError( "Entity '%s' has no property '%s'" % (entity, key)) else: try: desc = entity.class_manager[key] return desc, desc.property except KeyError: raise sa_exc.InvalidRequestError( "Entity '%s' has no property '%s'" % (entity, key))
def selectone_by(self, *args, **params): """works like selectfirst_by(), but throws an error if not exactly one result was returned.""" ret = self.select_whereclause(self.join_by(*args, **params), limit=2) if len(ret) == 1: return ret[0] elif len(ret) == 0: raise exceptions.InvalidRequestError('No rows returned for selectone_by') else: raise exceptions.InvalidRequestError('Multiple rows returned for selectone_by')
def selectone(self, *args, **params): """works like selectfirst(), but throws an error if not exactly one result was returned.""" ret = list(self.select(*args, **params)[0:2]) if len(ret) == 1: return ret[0] elif len(ret) == 0: raise exceptions.InvalidRequestError('No rows returned for selectone_by') else: raise exceptions.InvalidRequestError('Multiple rows returned for selectone')
def selectone(self, arg=None, **kwargs): """Like ``selectfirst()``, but throw an error if not exactly one result was returned. """ ret = list(self.select(arg, **kwargs)[0:2]) if len(ret) == 1: return ret[0] elif len(ret) == 0: raise exceptions.InvalidRequestError('No rows returned for selectone_by') else: raise exceptions.InvalidRequestError('Multiple rows returned for selectone')
def get_bind(self, mapper, clause=None, **kwargs): """return an engine corresponding to the given arguments. mapper mapper relative to the desired operation clause a ClauseElement which is to be executed. if mapper is not present, this may be used to locate Table objects, which are then associated with mappers which have associated binds. \**kwargs Subclasses (i.e. ShardedSession) may add additional arguments to get_bind() which are passed through here. """ if mapper is None and clause is None: if self.bind is not None: return self.bind else: raise exceptions.InvalidRequestError( "This session is unbound to any Engine or Connection; specify a mapper to get_bind()" ) elif len(self.__binds): if mapper is not None: if isinstance(mapper, type): mapper = _class_mapper(mapper) if mapper.base_mapper in self.__binds: return self.__binds[mapper.base_mapper] elif mapper.compile().mapped_table in self.__binds: return self.__binds[mapper.mapped_table] if clause is not None: for t in clause._table_iterator(): if t in self.__binds: return self.__binds[t] if self.bind is not None: return self.bind else: if isinstance(mapper, type): mapper = _class_mapper(mapper) else: mapper = mapper.compile() e = mapper.mapped_table.bind if e is None: raise exceptions.InvalidRequestError( "Could not locate any Engine or Connection bound to mapper '%s'" % str(mapper)) return e
def __getattr__(self, key): mapper = class_mapper(self.cls, compile=False) if mapper: prop = mapper.get_property(key, raiseerr=False) if prop is None: raise exceptions.InvalidRequestError( "Class %r does not have a mapped column named %r" % (self.cls, key)) elif not isinstance(prop, ColumnProperty): raise exceptions.InvalidRequestError( "Property %r is not an instance of" " ColumnProperty (i.e. does not correspond" " directly to a Column)." % key) return getattr(self.cls, key)
def selectone_by(self, *args, **params): """Like ``selectfirst_by()``, but throws an error if not exactly one result was returned. The criterion is constructed in the same way as the ``select_by()`` method. """ ret = self.select_whereclause(self.join_by(*args, **params), limit=2) if len(ret) == 1: return ret[0] elif len(ret) == 0: raise exceptions.InvalidRequestError('No rows returned for selectone_by') else: raise exceptions.InvalidRequestError('Multiple rows returned for selectone_by')
def lazy_collection(): obj = weakobjref() if obj is None: raise exceptions.InvalidRequestError( "stale association proxy, parent object has gone out of " "scope") return getattr(obj, target)
def return_cls(): try: return cls._decl_class_registry[arg] except KeyError: raise exceptions.InvalidRequestError( "When compiling mapper %s, could not locate a declarative class named %r. Consider adding this property to the %r class after both dependent classes have been defined." % (prop.parent, arg, prop.parent.class_))
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 __eq__(self, other): if other is None: if self.prop.direction in [ONETOMANY, MANYTOMANY]: return ~sql.exists([1], self.prop.primaryjoin) else: return self.prop._optimized_compare(None) elif self.prop.uselist: if not hasattr(other, '__iter__'): raise exceptions.InvalidRequestError( "Can only compare a collection to an iterable object. Use contains()." ) else: j = self.prop.primaryjoin if self.prop.secondaryjoin: j = j & self.prop.secondaryjoin clauses = [] for o in other: clauses.append( sql.exists([1], j & sql.and_(*[ x == y for (x, y) in zip( self.prop.mapper.primary_key, self.prop.mapper.primary_key_from_instance( o)) ]))) return sql.and_(*clauses) else: return self.prop._optimized_compare(other)
def order_by_clause(self, select): order_by = self.process(select._order_by_clause) # ORDER BY clauses in DISTINCT queries must reference aliased # inner columns by alias name, not true column name. if order_by and getattr(select, '_distinct', False): labels = self._find_labeled_columns(select.inner_columns, select.use_labels) if labels: for needs_alias in labels.keys(): r = re.compile(r'(^| )(%s)(,| |$)' % re.escape(needs_alias)) order_by = r.sub((r'\1%s\3' % labels[needs_alias]), order_by) # No ORDER BY in subqueries. if order_by: if self.is_subquery(select): # It's safe to simply drop the ORDER BY if there is no # LIMIT. Right? Other dialects seem to get away with # dropping order. if select._limit: raise exceptions.InvalidRequestError( "MaxDB does not support ORDER BY in subqueries") else: return "" return " ORDER BY " + order_by else: return ""
def any(self, criterion=None, **kwargs): if not self.prop.uselist: raise sa_exc.InvalidRequestError( "'any()' not implemented for scalar attributes. Use has()." ) return self._criterion_exists(criterion, **kwargs)
def _locate_prop(self, key, start=None): import properties keys = [] seen = util.Set() def search_for_prop(mapper_): if mapper_ in seen: return None seen.add(mapper_) if mapper_.props.has_key(key): prop = mapper_.props[key] if isinstance(prop, SynonymProperty): prop = mapper_.props[prop.name] if isinstance(prop, properties.PropertyLoader): keys.insert(0, prop.key) return prop else: for prop in mapper_.props.values(): if not isinstance(prop, properties.PropertyLoader): continue x = search_for_prop(prop.mapper) if x: keys.insert(0, prop.key) return x else: return None p = search_for_prop(start or self.mapper) if p is None: raise exceptions.InvalidRequestError("Cant locate property named '%s'" % key) return [keys, p]
def object_mapper(object, entity_name=None, raiseerror=True): """Given an object, return the primary Mapper associated with the object instance. object The object instance. entity_name Entity name of the mapper to retrieve, if the given instance is transient. Otherwise uses the entity name already associated with the instance. raiseerror Defaults to True: raise an ``InvalidRequestError`` if no mapper can be located. If False, return None. """ try: mapper = object.__class__._class_state.mappers[getattr(object, '_entity_name', entity_name)] except (KeyError, AttributeError): if raiseerror: raise exceptions.InvalidRequestError("Class '%s' entity name '%s' has no mapper associated with it" % (object.__class__.__name__, getattr(object, '_entity_name', entity_name))) else: return None return mapper
def get_or_add(self, bind): if self.__parent is not None: if not self.nested: return self.__parent.get_or_add(bind) if bind in self.__connections: return self.__connections[bind][0] if bind in self.__parent._connection_dict(): (conn, trans, autoclose) = self.__parent.__connections[bind] self.__connections[conn] = self.__connections[bind.engine] = ( conn, conn.begin_nested(), autoclose) return conn elif bind in self.__connections: return self.__connections[bind][0] if not isinstance(bind, engine.Connection): e = bind c = bind.contextual_connect() else: e = bind.engine c = bind if e in self.__connections: raise exceptions.InvalidRequestError( "Session already has a Connection associated for the given Connection's Engine" ) if self.nested: trans = c.begin_nested() elif self.session.twophase: trans = c.begin_twophase() else: trans = c.begin() self.__connections[c] = self.__connections[e] = (c, trans, c is not bind) return self.__connections[c][0]
def commit(self): """commit the current transaction in progress. If no transaction is in progress, this method raises an InvalidRequestError. If the ``begin()`` method was called on this ``Session`` additional times subsequent to its first call, ``commit()`` will not actually commit, and instead pops an internal SessionTransaction off its internal stack of transactions. Only when the "root" SessionTransaction is reached does an actual database-level commit occur. """ if self.transaction is None: if self.transactional: self.begin() self.transaction = self.transaction.commit() else: raise exceptions.InvalidRequestError( "No transaction is begun.") else: self.transaction = self.transaction.commit() if self.transaction is None and self.transactional: self.begin()
def _update_impl(self, obj, **kwargs): if self._is_attached(obj) and obj not in self.deleted: return if not hasattr(obj, '_instance_key'): raise exceptions.InvalidRequestError( "Instance '%s' is not persisted" % repr(obj)) self._attach(obj)
def __call__(self): obj = self.ref() if obj is None: raise exceptions.InvalidRequestError( "stale association proxy, parent object has gone out of " "scope") return getattr(obj, self.target)
def last_inserted_ids(self): if self.context.last_inserted_ids is None: raise exceptions.InvalidRequestError( "no INSERT executed, or can't use cursor.lastrowid without Postgres OIDs enabled" ) else: return self.context.last_inserted_ids
def refresh(self, obj): """reload the attributes for the given object from the database, clear any changes made.""" self._validate_persistent(obj) if self.query(obj.__class__)._get(obj._instance_key, reload=True) is None: raise exceptions.InvalidRequestError( "Could not refresh instance '%s'" % repr(obj))
def get_bind(self, mapper): """return the Engine or Connection which is used to execute statements on behalf of the given Mapper. Calling connect() on the return result will always result in a Connection object. This method disregards any SessionTransaction that may be in progress. The order of searching is as follows: if an Engine or Connection was bound to this Mapper specifically within this Session, returns that Engine or Connection. if an Engine or Connection was bound to this Mapper's underlying Table within this Session (i.e. not to the Table directly), returns that Engine or Conneciton. if an Engine or Connection was bound to this Session, returns that Engine or Connection. finally, returns the Engine which was bound directly to the Table's MetaData object. If no Engine is bound to the Table, an exception is raised. """ if mapper is None: return self.bind_to elif self.binds.has_key(mapper): return self.binds[mapper] elif self.binds.has_key(mapper.mapped_table): return self.binds[mapper.mapped_table] elif self.bind_to is not None: return self.bind_to else: e = mapper.mapped_table.engine if e is None: raise exceptions.InvalidRequestError("Could not locate any Engine bound to mapper '%s'" % str(mapper)) return e
def _close(self): if self._cursors is not None: # cursors should be closed before connection is returned to the pool. some dbapis like # mysql have real issues if they are not. if self.__pool.auto_close_cursors: self.close_open_cursors() elif self.__pool.disallow_open_cursors: if len(self._cursors): raise exceptions.InvalidRequestError( "This connection still has %d open cursors" % len(self._cursors)) if self.connection is not None: try: self.connection.rollback() except: if self._connection_record is not None: self._connection_record.invalidate() if self._connection_record is not None: if self.__pool.echo: self.__pool.log("Connection %s being returned to pool" % repr(self.connection)) self.__pool.return_conn(self) self.connection = None self._connection_record = None self._threadfairy = None self._cursors = None
def invalidate(self): if self.connection is None: raise exceptions.InvalidRequestError("This connection is closed") self._connection_record.invalidate() self.connection = None self._cursors = None self._close()
def _executioncontext(self): try: return self.__executioncontext except AttributeError: raise exceptions.InvalidRequestError( "This ResultProxy does not have an execution context with which to complete this operation. Execution contexts are not generated for literal SQL execution." )
def commit(self): if not self.__parent.__is_active: raise exceptions.InvalidRequestError( "This transaction is inactive") if self.__parent is self: self.__connection._commit_impl() self.__is_active = False
def visit_select_precolumns(self, select): """ MS-SQL puts TOP, it's version of LIMIT here """ s = select.distinct and "DISTINCT " or "" if select.limit: s += "TOP %s " % (select.limit,) if select.offset: raise exceptions.InvalidRequestError('MSSQL does not support LIMIT with an offset') return s
def has(self, criterion=None, **kwargs): if self.prop.uselist: raise exceptions.InvalidRequestError( "'has()' not implemented for collections. Use any().") j, criterion, from_obj = self._join_and_criterion( criterion, **kwargs) return sql.exists([1], j & criterion, from_obj=from_obj)
def _save_impl(self, object, **kwargs): if hasattr(object, '_instance_key'): if not self.identity_map.has_key(object._instance_key): raise exceptions.InvalidRequestError("Instance '%s' is a detached instance or is already persistent in a different Session" % repr(object)) else: m = class_mapper(object.__class__, entity_name=kwargs.get('entity_name', None)) m._assign_entity_name(object) self._register_new(object)
def execute(self, object, *multiparams, **params): for c in type(object).__mro__: if c in Connection.executors: return Connection.executors[c](self, object, *multiparams, **params) else: raise exceptions.InvalidRequestError( "Unexecuteable object type: " + str(type(object)))