From: Mike Bayer Date: Sat, 31 Mar 2007 23:49:57 +0000 (+0000) Subject: latest #214 fixups X-Git-Tag: rel_0_3_7~85 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8607de3159fd37923ae99118c499935c4a54d0e2;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git latest #214 fixups --- diff --git a/lib/sqlalchemy/databases/oracle.py b/lib/sqlalchemy/databases/oracle.py index 4633a0a8c9..adea127bfe 100644 --- a/lib/sqlalchemy/databases/oracle.py +++ b/lib/sqlalchemy/databases/oracle.py @@ -332,7 +332,7 @@ class OracleDialect(ansisql.ANSIDialect): try: coltype = ischema_names[coltype] except KeyError: - raise exceptions.AssertionError("Cant get coltype for type '%s' on colname '%s'" % (coltype, colname)) + raise exceptions.AssertionError("Can't get coltype for type '%s' on colname '%s'" % (coltype, colname)) colargs = [] if default is not None: diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py index 43d570070f..d83607793e 100644 --- a/lib/sqlalchemy/databases/postgres.py +++ b/lib/sqlalchemy/databases/postgres.py @@ -310,7 +310,7 @@ class PGDialect(ansisql.ANSIDialect): def last_inserted_ids(self): if self.context.last_inserted_ids is None: - raise exceptions.InvalidRequestError("no INSERT executed, or cant use cursor.lastrowid without Postgres OIDs enabled") + raise exceptions.InvalidRequestError("no INSERT executed, or can't use cursor.lastrowid without Postgres OIDs enabled") else: return self.context.last_inserted_ids diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index cf0d350358..0baaeb8268 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -94,7 +94,7 @@ class Dialect(sql.AbstractDialect): raise NotImplementedError() def oid_column_name(self, column): - """Return the oid column name for this dialect, or None if the dialect cant/wont support OID/ROWID. + """Return the oid column name for this dialect, or None if the dialect can't/won't support OID/ROWID. The Column instance which represents OID for the query being compiled is passed, so that the dialect can inspect the column diff --git a/lib/sqlalchemy/engine/strategies.py b/lib/sqlalchemy/engine/strategies.py index 7a7b84aa99..8ac721b77c 100644 --- a/lib/sqlalchemy/engine/strategies.py +++ b/lib/sqlalchemy/engine/strategies.py @@ -62,7 +62,7 @@ class DefaultEngineStrategy(EngineStrategy): if pool is None: dbapi = kwargs.pop('module', dialect.dbapi()) if dbapi is None: - raise exceptions.InvalidRequestError("Cant get DBAPI module for dialect '%s'" % dialect) + raise exceptions.InvalidRequestError("Can't get DBAPI module for dialect '%s'" % dialect) def connect(): try: diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index c3bbef1ef1..e3bd98e3e1 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -288,7 +288,11 @@ class PropertyLoader(StrategizedProperty): mapperutil.BinaryVisitor(visit_binary).traverse(self.primaryjoin) if len(self.foreign_keys) == 0: - raise exceptions.ArgumentError("Cant locate any foreign key columns in primary join condition '%s' for relationship '%s'. Specify 'foreign_keys' argument to indicate which columns in the join condition are foreign." %(str(self.primaryjoin), str(self))) + raise exceptions.ArgumentError( + "Can't locate any foreign key columns in primary join " + "condition '%s' for relationship '%s'. Specify " + "'foreign_keys' argument to indicate which columns in " + "the join condition are foreign." %(str(self.primaryjoin), str(self))) if self.secondaryjoin is not None: mapperutil.BinaryVisitor(visit_binary).traverse(self.secondaryjoin) @@ -325,9 +329,16 @@ class PropertyLoader(StrategizedProperty): manytoone = len([c for c in self.foreign_keys if self.parent.unjoined_table.c.contains_column(c)]) if not onetomany and not manytoone: - raise exceptions.ArgumentError("Cant determine relation direction for relationship '%s' - foreign key columns are not present in neither the parent nor the child's mapped tables" %(str(self))) + raise exceptions.ArgumentError( + "Can't determine relation direction for relationship '%s' " + "- foreign key columns are not present in neither the " + "parent nor the child's mapped tables" %(str(self))) elif onetomany and manytoone: - raise exceptions.ArgumentError("Cant 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))) + 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))) elif onetomany: self.direction = sync.ONETOMANY elif manytoone: @@ -476,15 +487,22 @@ class BackRef(object): 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) + 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.props[self.key], PropertyLoader): - raise exceptions.ArgumentError("Cant create backref '%s' on mapper '%s'; an incompatible property of that name already exists" % (self.key, str(mapper))) + 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.props[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.props[self.key].mapper.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.props[self.key].mapper.class_))) if not mapper.props[self.key].is_backref: prop.is_backref=True if not prop.viewonly: diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index b1a267431d..f61e477b6c 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -521,7 +521,7 @@ class Query(object): return None p = search_for_prop(start or self.mapper) if p is None: - raise exceptions.InvalidRequestError("Cant locate property named '%s'" % key) + raise exceptions.InvalidRequestError("Can't locate property named '%s'" % key) return [keys, p] def _col_aggregate(self, col, func): diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 86d61c7c9e..d1639d395a 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -124,10 +124,10 @@ class Session(object): echo_uow = property(_get_echo_uow,_set_echo_uow) def create_transaction(self, **kwargs): - """Return a new SessionTransaction corresponding to an + """Return a new ``SessionTransaction`` corresponding to an existing or new transaction. - If the transaction is new, the returned SessionTransaction + If the transaction is new, the returned ``SessionTransaction`` will have commit control over the underlying transaction, else will have rollback control only. """ @@ -148,16 +148,16 @@ class Session(object): return self.get_bind(mapper).connect(**kwargs) def connection(self, mapper, **kwargs): - """Return a Connection corresponding to the given mapper. + """Return a ``Connection`` corresponding to the given mapper. Used by the ``execute()`` method which performs select - operations for Mapper and Query. + operations for ``Mapper`` and ``Query``. - If this Session is transactional, the connection will be in + If this ``Session`` is transactional, the connection will be in the context of this session's transaction. Otherwise, the - connection is returned by the contextual_connect method, which + connection is returned by the ``contextual_connect()`` method, which some Engines override to return a thread-local connection, and - will have close_with_result set to True. + will have `close_with_result` set to `True`. The given `**kwargs` will be sent to the engine's ``contextual_connect()`` method, if no transaction is in @@ -170,15 +170,15 @@ class Session(object): return self.get_bind(mapper).contextual_connect(**kwargs) def execute(self, mapper, clause, params, **kwargs): - """Using the given mapper to identify the appropriate Engine - or Connection to be used for statement execution, execute the - given ClauseElement using the provided parameter dictionary. + """Using the given mapper to identify the appropriate ``Engine`` + or ``Connection`` to be used for statement execution, execute the + given ``ClauseElement`` using the provided parameter dictionary. - Return a ResultProxy corresponding to the execution's results. + Return a ``ResultProxy`` corresponding to the execution's results. - If this method allocates a new Connection for the operation, - then the ResultProxy's ``close()`` method will release the - resources of the underlying Connection, otherwise its a no-op. + If this method allocates a new ``Connection`` for the operation, + then the ``ResultProxy`` 's ``close()`` method will release the + resources of the underlying ``Connection``, otherwise its a no-op. """ return self.connection(mapper, close_with_result=True).execute(clause, params, **kwargs) @@ -195,10 +195,10 @@ class Session(object): self.transaction.close() def clear(self): - """Remove all object instances from this Session. + """Remove all object instances from this ``Session``. This is equivalent to calling ``expunge()`` for all objects in - this Session. + this ``Session``. """ for instance in self: @@ -208,54 +208,54 @@ class Session(object): self.uow.echo = echo def mapper(self, class_, entity_name=None): - """Given an Class, return the primary Mapper responsible for + """Given a ``Class``, return the primary ``Mapper`` responsible for persisting it.""" return _class_mapper(class_, entity_name = entity_name) def bind_mapper(self, mapper, bindto): - """Bind the given `Mapper` to the given Engine or Connection. + """Bind the given `mapper` to the given ``Engine`` or ``Connection``. - All subsequent operations involving this Mapper will use the + All subsequent operations involving this ``Mapper`` will use the given `bindto`. """ self.binds[mapper] = bindto def bind_table(self, table, bindto): - """Bind the given `Table` to the given Engine or Connection. + """Bind the given `table` to the given ``Engine`` or ``Connection``. - All subsequent operations involving this Table will use the + All subsequent operations involving this ``Table`` will use the given `bindto`. """ self.binds[table] = bindto def get_bind(self, mapper): - """Return the Engine or Connection which is used to execute - statements on behalf of the given `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. + in a ``Connection`` object. This method disregards any + ``SessionTransaction`` that may be in progress. The order of searching is as follows: - 1. if an Engine or Connection was bound to this Mapper - specifically within this Session, return that Engine or - Connection. + 1. if an ``Engine`` or ``Connection`` was bound to this ``Mapper`` + specifically within this ``Session``, return that ``Engine`` or + ``Connection``. - 2. if an Engine or Connection was bound to this Mapper's - underlying Table within this Session (i.e. not to the Table - directly), return that Engine or Conneciton. + 2. if an ``Engine`` or ``Connection`` was bound to this `mapper` 's + underlying ``Table`` within this ``Session`` (i.e. not to the ``Table`` + directly), return that ``Engine`` or ``Connection``. - 3. if an Engine or Connection was bound to this Session, - return that Engine or Connection. + 3. if an ``Engine`` or ``Connection`` was bound to this ``Session``, + return that ``Engine`` or ``Connection``. - 4. finally, return the Engine which was bound directly to the - Table's MetaData object. + 4. finally, return 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 no ``Engine`` is bound to the ``Table``, an exception is raised. """ if mapper is None: @@ -273,7 +273,7 @@ class Session(object): return e def query(self, mapper_or_class, entity_name=None, **kwargs): - """Return a new Query object corresponding to this Session and + """Return a new ``Query`` object corresponding to this ``Session`` and the mapper, or the classes' primary mapper. """ @@ -296,14 +296,14 @@ class Session(object): to the database. `objects` is a list or tuple of objects specifically to be - flushed; if None, all new and modified objects are flushed. + flushed; if ``None``, all new and modified objects are flushed. """ self.uow.flush(self, objects) def get(self, class_, ident, **kwargs): """Return an instance of the object based on the given - identifier, or None if not found. + identifier, or ``None`` if not found. The `ident` argument is a scalar or tuple of primary key column values in the order of the table def's primary key @@ -323,12 +323,12 @@ class Session(object): If not found, raises an exception. The method will **remove all pending changes** to the object already existing in the - Session. The `ident` argument is a scalar or tuple of primary + ``Session``. The `ident` argument is a scalar or tuple of primary key columns in the order of the table def's primary key columns. The `entity_name` keyword argument may also be specified which - further qualifies the underlying Mapper used to perform the + further qualifies the underlying ``Mapper`` used to perform the query. """ @@ -374,7 +374,7 @@ class Session(object): return ret def expunge(self, object): - """Remove the given object from this Session. + """Remove the given `object` from this ``Session``. This will free all internal references to the object. Cascading will be applied according to the *expunge* cascade @@ -386,25 +386,27 @@ class Session(object): self._unattach(c) def save(self, object, entity_name=None): - """Add a transient (unsaved) instance to this Session. + """Add a transient (unsaved) instance to this ``Session``. This operation cascades the `save_or_update` method to associated instances if the relation is mapped with ``cascade="save-update"``. The `entity_name` keyword argument will further qualify the - specific Mapper used to handle this instance. + specific ``Mapper`` used to handle this instance. """ self._save_impl(object, entity_name=entity_name) - _object_mapper(object).cascade_callable('save-update', object, lambda c, e:self._save_or_update_impl(c, e), halt_on=lambda c:c in self) + _object_mapper(object).cascade_callable('save-update', object, + lambda c, e:self._save_or_update_impl(c, e), + halt_on=lambda c:c in self) def update(self, object, entity_name=None): """Bring the given detached (saved) instance into this - Session. + ``Session``. If there is a persistent instance with the same identifier - already associated with this Session, an exception is thrown. + already associated with this ``Session``, an exception is thrown. This operation cascades the `save_or_update` method to associated instances if the relation is mapped with @@ -412,17 +414,21 @@ class Session(object): """ self._update_impl(object, entity_name=entity_name) - _object_mapper(object).cascade_callable('save-update', object, lambda c, e:self._save_or_update_impl(c, e), halt_on=lambda c:c in self) + _object_mapper(object).cascade_callable('save-update', object, + lambda c, e:self._save_or_update_impl(c, e), + halt_on=lambda c:c in self) def save_or_update(self, object, entity_name=None): - """Save or update the given object into this Session. + """Save or update the given object into this ``Session``. The presence of an `_instance_key` attribute on the instance determines whether to ``save()`` or ``update()`` the instance. """ self._save_or_update_impl(object, entity_name=entity_name) - _object_mapper(object).cascade_callable('save-update', object, lambda c, e:self._save_or_update_impl(c, e), halt_on=lambda c:c in self) + _object_mapper(object).cascade_callable('save-update', object, + lambda c, e:self._save_or_update_impl(c, e), + halt_on=lambda c:c in self) def _save_or_update_impl(self, object, entity_name=None): key = getattr(object, '_instance_key', None) @@ -441,7 +447,7 @@ class Session(object): self.uow.register_deleted(c) def merge(self, object, entity_name=None, _recursive=None): - """Copy the state of the given object onto the persistent + """Copy the state of the given `object` onto the persistent object with the same identifier. If there is no persistent instance currently associated with @@ -476,30 +482,34 @@ class Session(object): 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) + * ``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] @@ -533,14 +543,18 @@ class Session(object): 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)) + 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)) # this would be a nice exception to raise...however this is incompatible with a contextual # session which puts all objects into the session upon construction. #if m._is_orphan(object): - # raise exceptions.InvalidRequestError("Instance '%s' is an orphan, and must be attached to a parent object to be saved" % (repr(object))) + # raise exceptions.InvalidRequestError("Instance '%s' is an orphan, " + # "and must be attached to a parent " + # "object to be saved" % (repr(object))) m._assign_entity_name(object) self._register_pending(object) @@ -565,12 +579,14 @@ class Session(object): self.uow.register_deleted(obj) def _attach(self, obj): - """Attach the given object to this Session.""" + """Attach the given object to this ``Session``.""" if getattr(obj, '_sa_session_id', None) != self.hash_key: old = getattr(obj, '_sa_session_id', None) if old is not None and _sessions.has_key(old): - raise exceptions.InvalidRequestError("Object '%s' is already attached to session '%s' (this is '%s')" % (repr(obj), old, id(self))) + raise exceptions.InvalidRequestError("Object '%s' is already attached " + "to session '%s' (this is '%s')" % + (repr(obj), old, id(self))) # auto-removal from the old session is disabled. but if we decide to # turn it back on, do it as below: gingerly since _sessions is a WeakValueDict @@ -600,7 +616,7 @@ class Session(object): def _validate_persistent(self, obj): """Validate that the given object is persistent within this - Session. + ``Session``. """ self.uow._validate_obj(obj) @@ -621,16 +637,21 @@ class Session(object): return self.identity_map.has_key(key) dirty = property(lambda s:s.uow.locate_dirty(), - doc="A Set of all objects marked as 'dirty' within this Session") + doc="A ``Set`` of all objects marked as 'dirty' within this ``Session``") + deleted = property(lambda s:s.uow.deleted, - doc="A Set of all objects marked as 'deleted' within this Session") + doc="A ``Set`` of all objects marked as 'deleted' within this ``Session``") + new = property(lambda s:s.uow.new, - doc="A Set of all objects marked as 'new' within this Session.") + doc="A ``Set`` of all objects marked as 'new' within this ``Session``.") + identity_map = property(lambda s:s.uow.identity_map, - doc="A dictionary consisting of all objects within this Session keyed to their _instance_key value.") + doc="A dictionary consisting of all objects " + "within this ``Session`` keyed to their `_instance_key` value.") def import_instance(self, *args, **kwargs): """Deprecated. A synynom for ``merge()``.""" + return self.merge(*args, **kwargs) # this is the AttributeManager instance used to provide attribute behavior on objects. @@ -644,7 +665,7 @@ attribute_manager = unitofwork.attribute_manager _sessions = weakref.WeakValueDictionary() def object_session(obj): - """Return the Session to which the given object is bound, or None if none.""" + """Return the ``Session`` to which the given object is bound, or ``None`` if none.""" hashkey = getattr(obj, '_sa_session_id', None) if hashkey is not None: diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index f980a189c4..e9d992d185 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -312,7 +312,11 @@ class EagerLoader(AbstractRelationLoader): def init(self): super(EagerLoader, self).init() if self.parent.isa(self.mapper): - raise exceptions.ArgumentError("Error creating eager relationship '%s' on parent class '%s' to child class '%s': Cant use eager loading on a self referential relationship." % (self.key, repr(self.parent.class_), repr(self.mapper.class_))) + raise exceptions.ArgumentError( + "Error creating eager relationship '%s' on parent class '%s' " + "to child class '%s': Cant use eager loading on a self " + "referential relationship." % + (self.key, repr(self.parent.class_), repr(self.mapper.class_))) self.parent._eager_loaders.add(self.parent_property) self.clauses = {} diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py index 7a12d554d6..781e2ba267 100644 --- a/lib/sqlalchemy/orm/unitofwork.py +++ b/lib/sqlalchemy/orm/unitofwork.py @@ -151,7 +151,7 @@ class UnitOfWork(object): def register_new(self, obj): if hasattr(obj, '_instance_key'): - raise InvalidRequestError("Object '%s' already has an identity - it cant be registered as new" % repr(obj)) + raise InvalidRequestError("Object '%s' already has an identity - it can't be registered as new" % repr(obj)) if obj not in self.new: self.new.add(obj) obj._sa_insert_order = len(self.new) diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index cb62eab530..6cb4fed6ed 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -6,7 +6,8 @@ from sqlalchemy import sql, util, exceptions -all_cascades = util.Set(["delete", "delete-orphan", "all", "merge", "expunge", "save-update", "refresh-expire", "none"]) +all_cascades = util.Set(["delete", "delete-orphan", "all", "merge", + "expunge", "save-update", "refresh-expire", "none"]) class CascadeOptions(object): """Keeps track of the options sent to relation().cascade""" @@ -19,7 +20,6 @@ class CascadeOptions(object): self.merge = "merge" in values or "all" in values self.expunge = "expunge" in values or "all" in values self.refresh_expire = "refresh-expire" in values or "all" in values - for x in values: if x not in all_cascades: raise exceptions.ArgumentError("Invalid cascade option '%s'" % x) @@ -28,12 +28,15 @@ class CascadeOptions(object): return getattr(self, item.replace("-", "_"), False) def __repr__(self): - return "CascadeOptions(arg=%s)" % repr(",".join([x for x in ['delete', 'save_update', 'merge', 'expunge', 'delete_orphan', 'refresh-expire'] if getattr(self, x, False) is True])) + return "CascadeOptions(arg=%s)" % repr(",".join( + [x for x in ['delete', 'save_update', 'merge', 'expunge', + 'delete_orphan', 'refresh-expire'] + if getattr(self, x, False) is True])) def polymorphic_union(table_map, typecolname, aliasname='p_union'): """Create a ``UNION`` statement used by a polymorphic mapper. - See the SQLAlchemy advanced mapping docs for an example of how + See the `SQLAlchemy` advanced mapping docs for an example of how this is used. """ @@ -64,18 +67,20 @@ def polymorphic_union(table_map, typecolname, aliasname='p_union'): result = [] for type, table in table_map.iteritems(): if typecolname is not None: - result.append(sql.select([col(name, table) for name in colnames] + [sql.literal_column("'%s'" % type).label(typecolname)], from_obj=[table])) + result.append(sql.select([col(name, table) for name in colnames] + + [sql.literal_column("'%s'" % type).label(typecolname)], + from_obj=[table])) else: result.append(sql.select([col(name, table) for name in colnames], from_obj=[table])) return sql.union_all(*result).alias(aliasname) class TranslatingDict(dict): - """A dictionary that stores ColumnElement objects as keys. + """A dictionary that stores ``ColumnElement`` objects as keys. - Incoming ColumnElement keys are translated against those of an - underling FromClause for all operations. This way the columns - from any Selectable that is derived from or underlying this - TranslatingDict's selectable can be used as keys. + Incoming ``ColumnElement`` keys are translated against those of an + underling ``FromClause`` for all operations. This way the columns + from any ``Selectable`` that is derived from or underlying this + ``TranslatingDict`` 's selectable can be used as keys. """ def __init__(self, selectable): diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index b9e9896a84..87cbdaf0c3 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -249,23 +249,29 @@ def case(whens, value=None, else_=None): for c in cc.clauses: c.parens = False return cc - + def cast(clause, totype, **kwargs): - """return CAST function CAST(clause AS totype) - - Use with a sqlalchemy.types.TypeEngine object, i.e - ``cast(table.c.unit_price * table.c.qty, Numeric(10,4))`` - or ``cast(table.c.timestamp, DATE)`` - + """Return ``CAST`` function. + + Equivalent of SQL ``CAST(clause AS totype)``. + + Use with a ``sqlalchemy.types.TypeEngine`` object, i.e:: + + cast(table.c.unit_price * table.c.qty, Numeric(10,4)) + + or:: + + cast(table.c.timestamp, DATE) """ + return _Cast(clause, totype, **kwargs) def extract(field, expr): - """return extract(field FROM expr)""" + """Return ``extract(field FROM expr)``.""" + expr = _BinaryClause(text(field), expr, "FROM") return func.extract(expr) - def exists(*args, **kwargs): return _Exists(*args, **kwargs) @@ -1030,12 +1036,12 @@ class ColumnElement(Selectable, _CompareMixin): with Selectable objects. """) - def _one_fkey(self): if len(self._foreign_keys): return list(self._foreign_keys)[0] else: return None + foreign_key = property(_one_fkey) def _get_orig_set(self): @@ -1049,6 +1055,7 @@ class ColumnElement(Selectable, _CompareMixin): if len(s) == 0: s.add(self) self.__orig_set = s + orig_set = property(_get_orig_set, _set_orig_set, doc=\ """A Set containing TableClause-bound, non-proxied ColumnElements @@ -1058,7 +1065,9 @@ class ColumnElement(Selectable, _CompareMixin): """) def shares_lineage(self, othercolumn): - """Return True if the given ``ColumnElement`` has a common ancestor to this ``ColumnElement``.""" + """Return True if the given ``ColumnElement`` has a common + ancestor to this ``ColumnElement``. + """ for c in self.orig_set: if c in othercolumn.orig_set: @@ -1398,15 +1407,18 @@ class _TextClause(ClauseElement): if typemap is not None: for key in typemap.keys(): typemap[key] = sqltypes.to_instance(typemap[key]) + def repl(m): self.bindparams[m.group(1)] = bindparam(m.group(1)) return ":%s" % m.group(1) - # scan the string and search for bind parameter names, add them + + # scan the string and search for bind parameter names, add them # to the list of bindparams self.text = re.compile(r'(? 1: - raise exceptions.ArgumentError("Cant 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." % (primary.name, secondary.name)) + 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." % (primary.name, secondary.name)) elif len(crit) == 1: return (crit[0]) else: @@ -1808,6 +1856,7 @@ class Join(FromClause): def get_children(self, **kwargs): return self.left, self.right, self.onclause + def accept_visitor(self, visitor): visitor.visit_join(self) @@ -1894,6 +1943,7 @@ class _Label(ColumnElement): def get_children(self, **kwargs): return self.obj, + def accept_visitor(self, visitor): visitor.visit_label(self) @@ -1925,11 +1975,12 @@ class _ColumnClause(ColumnElement): self.is_literal = is_literal def _get_label(self): - """generate a 'label' for this column. + """Generate a 'label' for this column. - the label is a product of the parent table name and column name, and - is treated as a unique identifier of this Column across all Tables and derived - selectables for a particular metadata collection. + The label is a product of the parent table name and column + name, and is treated as a unique identifier of this ``Column`` + across all ``Tables`` and derived selectables for a particular + metadata collection. """ # for a "literal" column, we've no idea what the text is @@ -2282,26 +2333,28 @@ class Select(_SelectBaseMixin, FromClause): if self.is_scalar and not hasattr(self, 'type'): self.type = column.type - # if the column is a Select statement itself, + # if the column is a Select statement itself, # accept visitor self.__correlator.traverse(column) - + # visit the FROM objects of the column looking for more Selects for f in column._get_from_objects(): if f is not self: self.__correlator.traverse(f) self._process_froms(column, False) + def _make_proxy(self, selectable, name): if self.is_scalar: return self._raw_columns[0]._make_proxy(selectable, name) else: raise exceptions.InvalidRequestError("Not a scalar select statement") + def label(self, name): if not self.is_scalar: raise exceptions.InvalidRequestError("Not a scalar select statement") else: return label(name, self) - + def _exportable_columns(self): return [c for c in self._raw_columns if isinstance(c, Selectable)] @@ -2310,7 +2363,7 @@ class Select(_SelectBaseMixin, FromClause): return column._make_proxy(self, name=column._label) else: return column._make_proxy(self) - + def _process_froms(self, elem, asfrom): for f in elem._get_from_objects(): self.__froms.add(f) @@ -2369,7 +2422,9 @@ class Select(_SelectBaseMixin, FromClause): else: return f - froms = property(_calc_froms, doc="""A collection containing all elements of the FROM clause""") + froms = property(_calc_froms, + doc="""A collection containing all elements + of the ``FROM`` clause.""") def get_children(self, column_collections=True, **kwargs): return (column_collections and list(self.columns) or []) + \