summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/__init__.py2
-rw-r--r--lib/sqlalchemy/orm/attributes.py9
-rw-r--r--lib/sqlalchemy/orm/collections.py68
-rw-r--r--lib/sqlalchemy/orm/descriptor_props.py2
-rw-r--r--lib/sqlalchemy/orm/evaluator.py18
-rw-r--r--lib/sqlalchemy/orm/identity.py41
-rw-r--r--lib/sqlalchemy/orm/instrumentation.py32
-rw-r--r--lib/sqlalchemy/orm/interfaces.py9
-rw-r--r--lib/sqlalchemy/orm/loading.py12
-rw-r--r--lib/sqlalchemy/orm/mapper.py25
-rw-r--r--lib/sqlalchemy/orm/persistence.py24
-rw-r--r--lib/sqlalchemy/orm/properties.py4
-rw-r--r--lib/sqlalchemy/orm/query.py177
-rw-r--r--lib/sqlalchemy/orm/session.py12
-rw-r--r--lib/sqlalchemy/orm/strategies.py64
-rw-r--r--lib/sqlalchemy/orm/unitofwork.py4
-rw-r--r--lib/sqlalchemy/orm/util.py47
17 files changed, 336 insertions, 214 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index 35315d5d1..1173d5d09 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -1661,7 +1661,7 @@ def contains_eager(*keys, **kwargs):
alias = kwargs.pop('alias', None)
if kwargs:
raise exc.ArgumentError(
- 'Invalid kwargs for contains_eager: %r' % kwargs.keys())
+ 'Invalid kwargs for contains_eager: %r' % list(kwargs.keys()))
return strategies.EagerLazyOption(keys, lazy='joined',
propagate_to_loaders=False, chained=True), \
strategies.LoadEagerFromAliasOption(keys, alias=alias, chained=True)
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index 3eda127fd..bfba695b8 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -386,8 +386,8 @@ def create_proxied_attribute(descriptor):
return getattr(self.comparator, attribute)
except AttributeError:
raise AttributeError(
- 'Neither %r object nor %r object associated with %s '
- 'has an attribute %r' % (
+ 'Neither %r object nor %r object associated with %s '
+ 'has an attribute %r' % (
type(descriptor).__name__,
type(self.comparator).__name__,
self,
@@ -866,7 +866,7 @@ class CollectionAttributeImpl(AttributeImpl):
self.collection_factory = typecallable
def __copy(self, item):
- return [y for y in list(collections.collection_adapter(item))]
+ return [y for y in collections.collection_adapter(item)]
def get_history(self, state, dict_, passive=PASSIVE_OFF):
current = self.get(state, dict_, passive=passive)
@@ -1214,8 +1214,9 @@ class History(History):
"""
- def __nonzero__(self):
+ def __bool__(self):
return self != HISTORY_BLANK
+ __nonzero__ = __bool__
def empty(self):
"""Return True if this :class:`.History` has no changes
diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py
index 5691acfff..03917d112 100644
--- a/lib/sqlalchemy/orm/collections.py
+++ b/lib/sqlalchemy/orm/collections.py
@@ -657,11 +657,10 @@ class CollectionAdapter(object):
if getattr(obj, '_sa_adapter', None) is not None:
return getattr(obj, '_sa_adapter')
elif setting_type == dict:
- # Py3K
- #return obj.values()
- # Py2K
- return getattr(obj, 'itervalues', getattr(obj, 'values'))()
- # end Py2K
+ if util.py3k:
+ return obj.values()
+ else:
+ return getattr(obj, 'itervalues', getattr(obj, 'values'))()
else:
return iter(obj)
@@ -705,16 +704,17 @@ class CollectionAdapter(object):
def __iter__(self):
"""Iterate over entities in the collection."""
- # Py3K requires iter() here
return iter(getattr(self._data(), '_sa_iterator')())
def __len__(self):
"""Count entities in the collection."""
return len(list(getattr(self._data(), '_sa_iterator')()))
- def __nonzero__(self):
+ def __bool__(self):
return True
+ __nonzero__ = __bool__
+
def fire_append_event(self, item, initiator=None):
"""Notify that a entity has entered the collection.
@@ -1094,14 +1094,14 @@ def _list_decorators():
stop += len(self)
if step == 1:
- for i in xrange(start, stop, step):
+ for i in range(start, stop, step):
if len(self) > start:
del self[start]
for i, item in enumerate(value):
self.insert(i + start, item)
else:
- rng = range(start, stop, step)
+ rng = list(range(start, stop, step))
if len(value) != len(rng):
raise ValueError(
"attempt to assign sequence of size %s to "
@@ -1128,24 +1128,23 @@ def _list_decorators():
_tidy(__delitem__)
return __delitem__
- # Py2K
- def __setslice__(fn):
- def __setslice__(self, start, end, values):
- for value in self[start:end]:
- __del(self, value)
- values = [__set(self, value) for value in values]
- fn(self, start, end, values)
- _tidy(__setslice__)
- return __setslice__
-
- def __delslice__(fn):
- def __delslice__(self, start, end):
- for value in self[start:end]:
- __del(self, value)
- fn(self, start, end)
- _tidy(__delslice__)
- return __delslice__
- # end Py2K
+ if util.py2k:
+ def __setslice__(fn):
+ def __setslice__(self, start, end, values):
+ for value in self[start:end]:
+ __del(self, value)
+ values = [__set(self, value) for value in values]
+ fn(self, start, end, values)
+ _tidy(__setslice__)
+ return __setslice__
+
+ def __delslice__(fn):
+ def __delslice__(self, start, end):
+ for value in self[start:end]:
+ __del(self, value)
+ fn(self, start, end)
+ _tidy(__delslice__)
+ return __delslice__
def extend(fn):
def extend(self, iterable):
@@ -1251,7 +1250,7 @@ def _dict_decorators():
def update(self, __other=Unspecified, **kw):
if __other is not Unspecified:
if hasattr(__other, 'keys'):
- for key in __other.keys():
+ for key in list(__other):
if (key not in self or
self[key] is not __other[key]):
self[key] = __other[key]
@@ -1270,11 +1269,7 @@ def _dict_decorators():
l.pop('Unspecified')
return l
-if util.py3k_warning:
- _set_binop_bases = (set, frozenset)
-else:
- import sets
- _set_binop_bases = (set, frozenset, sets.BaseSet)
+_set_binop_bases = (set, frozenset)
def _set_binops_check_strict(self, obj):
@@ -1467,11 +1462,8 @@ __interfaces = {
),
# decorators are required for dicts and object collections.
- # Py3K
- #dict: ({'iterator': 'values'}, _dict_decorators()),
- # Py2K
- dict: ({'iterator': 'itervalues'}, _dict_decorators()),
- # end Py2K
+ dict: ({'iterator': 'values'}, _dict_decorators()) if util.py3k
+ else ({'iterator': 'itervalues'}, _dict_decorators()),
}
diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py
index 1969bd03b..86b445bb6 100644
--- a/lib/sqlalchemy/orm/descriptor_props.py
+++ b/lib/sqlalchemy/orm/descriptor_props.py
@@ -184,7 +184,7 @@ class CompositeProperty(DescriptorProperty):
def _init_props(self):
self.props = props = []
for attr in self.attrs:
- if isinstance(attr, basestring):
+ if isinstance(attr, str):
prop = self.parent.get_property(attr)
elif isinstance(attr, schema.Column):
prop = self.parent._columntoproperty[attr]
diff --git a/lib/sqlalchemy/orm/evaluator.py b/lib/sqlalchemy/orm/evaluator.py
index 0844e2f72..458eab7a1 100644
--- a/lib/sqlalchemy/orm/evaluator.py
+++ b/lib/sqlalchemy/orm/evaluator.py
@@ -13,9 +13,9 @@ class UnevaluatableError(Exception):
_straight_ops = set(getattr(operators, op)
for op in ('add', 'mul', 'sub',
- # Py2K
- 'div',
- # end Py2K
+# start Py2K
+# 'div',
+# end Py2K
'mod', 'truediv',
'lt', 'le', 'ne', 'gt', 'ge', 'eq'))
@@ -40,6 +40,12 @@ class EvaluatorCompiler(object):
def visit_null(self, clause):
return lambda obj: None
+ def visit_false(self, clause):
+ return lambda obj: False
+
+ def visit_true(self, clause):
+ return lambda obj: True
+
def visit_column(self, clause):
if 'parentmapper' in clause._annotations:
key = clause._annotations['parentmapper'].\
@@ -50,7 +56,7 @@ class EvaluatorCompiler(object):
return lambda obj: get_corresponding_attr(obj)
def visit_clauselist(self, clause):
- evaluators = map(self.process, clause.clauses)
+ evaluators = list(map(self.process, clause.clauses))
if clause.operator is operators.or_:
def evaluate(obj):
has_null = False
@@ -79,8 +85,8 @@ class EvaluatorCompiler(object):
return evaluate
def visit_binary(self, clause):
- eval_left, eval_right = map(self.process,
- [clause.left, clause.right])
+ eval_left, eval_right = list(map(self.process,
+ [clause.left, clause.right]))
operator = clause.operator
if operator is operators.is_:
def evaluate(obj):
diff --git a/lib/sqlalchemy/orm/identity.py b/lib/sqlalchemy/orm/identity.py
index 01d34428e..d0234a1d3 100644
--- a/lib/sqlalchemy/orm/identity.py
+++ b/lib/sqlalchemy/orm/identity.py
@@ -6,7 +6,7 @@
import weakref
from . import attributes
-
+from .. import util
class IdentityMap(dict):
def __init__(self):
@@ -75,7 +75,7 @@ class WeakInstanceDict(IdentityMap):
state = dict.__getitem__(self, key)
o = state.obj()
if o is None:
- raise KeyError, key
+ raise KeyError(key)
return o
def __contains__(self, key):
@@ -152,30 +152,27 @@ class WeakInstanceDict(IdentityMap):
return result
- # Py3K
- #def items(self):
- # return iter(self._items())
- #
- #def values(self):
- # return iter(self._values())
- # Py2K
- items = _items
+ if util.py2k:
+ items = _items
+ values = _values
- def iteritems(self):
- return iter(self.items())
+ def iteritems(self):
+ return iter(self.items())
- values = _values
+ def itervalues(self):
+ return iter(self.values())
+ else:
+ def items(self):
+ return iter(self._items())
- def itervalues(self):
- return iter(self.values())
- # end Py2K
+ def values(self):
+ return iter(self._values())
def all_states(self):
- # Py3K
- # return list(dict.values(self))
- # Py2K
- return dict.values(self)
- # end Py2K
+ if util.py2k:
+ return dict.values(self)
+ else:
+ return list(dict.values(self))
def discard(self, state):
st = dict.get(self, state.key, None)
@@ -189,7 +186,7 @@ class WeakInstanceDict(IdentityMap):
class StrongInstanceDict(IdentityMap):
def all_states(self):
- return [attributes.instance_state(o) for o in self.itervalues()]
+ return [attributes.instance_state(o) for o in self.values()]
def contains_state(self, state):
return (
diff --git a/lib/sqlalchemy/orm/instrumentation.py b/lib/sqlalchemy/orm/instrumentation.py
index 0e71494c4..f2d0df43f 100644
--- a/lib/sqlalchemy/orm/instrumentation.py
+++ b/lib/sqlalchemy/orm/instrumentation.py
@@ -279,7 +279,7 @@ class ClassManager(dict):
@property
def attributes(self):
- return self.itervalues()
+ return iter(self.values())
## InstanceState management
@@ -325,10 +325,12 @@ class ClassManager(dict):
"""TODO"""
return self.get_impl(key).hasparent(state, optimistic=optimistic)
- def __nonzero__(self):
+ def __bool__(self):
"""All ClassManagers are non-zero regardless of attribute state."""
return True
+ __nonzero__ = __bool__
+
def __repr__(self):
return '<%s of %r at %x>' % (
self.__class__.__name__, self.class_, id(self))
@@ -444,21 +446,23 @@ def __init__(%(apply_pos)s):
func_vars = util.format_argspec_init(original__init__, grouped=False)
func_text = func_body % func_vars
- # Py3K
- #func_defaults = getattr(original__init__, '__defaults__', None)
- #func_kw_defaults = getattr(original__init__, '__kwdefaults__', None)
- # Py2K
- func = getattr(original__init__, 'im_func', original__init__)
- func_defaults = getattr(func, 'func_defaults', None)
- # end Py2K
+# start Py3K
+ func_defaults = getattr(original__init__, '__defaults__', None)
+ func_kw_defaults = getattr(original__init__, '__kwdefaults__', None)
+# end Py3K
+# start Py2K
+# func = getattr(original__init__, 'im_func', original__init__)
+# func_defaults = getattr(func, 'func_defaults', None)
+# end Py2K
env = locals().copy()
- exec func_text in env
+ exec(func_text, env)
__init__ = env['__init__']
__init__.__doc__ = original__init__.__doc__
if func_defaults:
- __init__.func_defaults = func_defaults
- # Py3K
- #if func_kw_defaults:
- # __init__.__kwdefaults__ = func_kw_defaults
+ __init__.__defaults__ = func_defaults
+# start Py3K
+ if func_kw_defaults:
+ __init__.__kwdefaults__ = func_kw_defaults
+# end Py3K
return __init__
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index 70743624c..396f234c4 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -15,6 +15,7 @@ Other than the deprecated extensions, this module and the
classes within should be considered mostly private.
"""
+
from __future__ import absolute_import
from .. import exc as sa_exc, util, inspect
@@ -659,7 +660,7 @@ class PropertyOption(MapperOption):
tokens = deque(self.key)
while tokens:
token = tokens.popleft()
- if isinstance(token, basestring):
+ if isinstance(token, str):
# wildcard token
if token.endswith(':*'):
return [path.token(token)]
@@ -744,7 +745,7 @@ class PropertyOption(MapperOption):
ext_info.mapper, aliased=True,
_use_mapper_path=True)
ext_info = inspect(ac)
- path.set(query, "path_with_polymorphic", ext_info)
+ path.set(query._attributes, "path_with_polymorphic", ext_info)
else:
path_element = mapper = getattr(prop, 'mapper', None)
if mapper is None and tokens:
@@ -775,13 +776,13 @@ class StrategizedOption(PropertyOption):
if self.chained:
for path in paths:
path.set(
- query,
+ query._attributes,
"loaderstrategy",
strategy
)
else:
paths[-1].set(
- query,
+ query._attributes,
"loaderstrategy",
strategy
)
diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py
index 5937197fd..e1f4d1b7c 100644
--- a/lib/sqlalchemy/orm/loading.py
+++ b/lib/sqlalchemy/orm/loading.py
@@ -11,7 +11,7 @@ the functions here are called primarily by Query, Mapper,
as well as some of the attribute loading strategies.
"""
-from __future__ import absolute_import
+
from .. import util
from . import attributes, exc as orm_exc, state as statelib
@@ -47,11 +47,11 @@ def instances(query, cursor, context):
query._entities[0].mapper.dispatch.append_result
(process, labels) = \
- zip(*[
+ list(zip(*[
query_entity.row_processor(query,
context, custom_rows)
for query_entity in query._entities
- ])
+ ]))
while True:
context.progress = {}
@@ -84,11 +84,11 @@ def instances(query, cursor, context):
context.progress.pop(context.refresh_state)
statelib.InstanceState._commit_all_states(
- context.progress.items(),
+ list(context.progress.items()),
session.identity_map
)
- for state, (dict_, attrs) in context.partials.iteritems():
+ for state, (dict_, attrs) in context.partials.items():
state._commit(dict_, attrs)
for row in rows:
@@ -507,7 +507,7 @@ def _populators(mapper, context, path, row, adapter,
pops = (new_populators, existing_populators, delayed_populators,
eager_populators)
- for prop in mapper._props.itervalues():
+ for prop in mapper._props.values():
for i, pop in enumerate(prop.create_row_processor(
context,
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index c08d91b57..285d338de 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -14,6 +14,7 @@ available in :class:`~sqlalchemy.orm.`.
"""
from __future__ import absolute_import
+
import types
import weakref
from itertools import chain
@@ -26,8 +27,8 @@ from . import instrumentation, attributes, \
from .interfaces import MapperProperty, _InspectionAttr, _MappedAttribute
from .util import _INSTRUMENTOR, _class_to_mapper, \
- _state_mapper, class_mapper, \
- PathRegistry
+ _state_mapper, class_mapper, \
+ PathRegistry
import sys
properties = util.importlater("sqlalchemy.orm", "properties")
descriptor_props = util.importlater("sqlalchemy.orm", "descriptor_props")
@@ -581,7 +582,7 @@ class Mapper(_InspectionAttr):
if with_polymorphic == '*':
self.with_polymorphic = ('*', None)
elif isinstance(with_polymorphic, (tuple, list)):
- if isinstance(with_polymorphic[0], (basestring, tuple, list)):
+ if isinstance(with_polymorphic[0], util.string_types + (tuple, list)):
self.with_polymorphic = with_polymorphic
else:
self.with_polymorphic = (with_polymorphic, None)
@@ -626,7 +627,7 @@ class Mapper(_InspectionAttr):
self.inherits._inheriting_mappers.add(self)
self.passive_updates = self.inherits.passive_updates
self._all_tables = self.inherits._all_tables
- for key, prop in mapper._props.iteritems():
+ for key, prop in mapper._props.items():
if key not in self._props and \
not self._should_exclude(key, key, local=False,
column=None):
@@ -866,12 +867,12 @@ class Mapper(_InspectionAttr):
# load custom properties
if self._init_properties:
- for key, prop in self._init_properties.iteritems():
+ for key, prop in self._init_properties.items():
self._configure_property(key, prop, False)
# pull properties from the inherited mapper if any.
if self.inherits:
- for key, prop in self.inherits._props.iteritems():
+ for key, prop in self.inherits._props.items():
if key not in self._props and \
not self._should_exclude(key, key, local=False,
column=None):
@@ -919,7 +920,7 @@ class Mapper(_InspectionAttr):
if self.polymorphic_on is not None:
setter = True
- if isinstance(self.polymorphic_on, basestring):
+ if isinstance(self.polymorphic_on, util.string_types):
# polymorphic_on specified as as string - link
# it to mapped ColumnProperty
try:
@@ -1235,7 +1236,7 @@ class Mapper(_InspectionAttr):
"""
self._log("_post_configure_properties() started")
- l = [(key, prop) for key, prop in self._props.iteritems()]
+ l = [(key, prop) for key, prop in self._props.items()]
for key, prop in l:
self._log("initialize prop %s", key)
@@ -1253,7 +1254,7 @@ class Mapper(_InspectionAttr):
using `add_property`.
"""
- for key, value in dict_of_properties.iteritems():
+ for key, value in dict_of_properties.items():
self.add_property(key, value)
def add_property(self, key, prop):
@@ -1350,7 +1351,7 @@ class Mapper(_InspectionAttr):
"""return an iterator of all MapperProperty objects."""
if _new_mappers:
configure_mappers()
- return self._props.itervalues()
+ return iter(self._props.values())
def _mappers_from_spec(self, spec, selectable):
"""given a with_polymorphic() argument, return the set of mappers it
@@ -1623,7 +1624,7 @@ class Mapper(_InspectionAttr):
if _new_mappers:
configure_mappers()
return util.ImmutableProperties(util.OrderedDict(
- (k, v) for k, v in self._props.iteritems()
+ (k, v) for k, v in self._props.items()
if isinstance(v, type_)
))
@@ -2040,7 +2041,7 @@ class Mapper(_InspectionAttr):
return fk.parent not in cols
return False
- sorted_ = sql_util.sort_tables(table_to_mapper.iterkeys(),
+ sorted_ = sql_util.sort_tables(table_to_mapper,
skip_fn=skip,
extra_dependencies=extra_dependencies)
diff --git a/lib/sqlalchemy/orm/persistence.py b/lib/sqlalchemy/orm/persistence.py
index e225a7c83..a773786c4 100644
--- a/lib/sqlalchemy/orm/persistence.py
+++ b/lib/sqlalchemy/orm/persistence.py
@@ -19,6 +19,7 @@ from .. import sql, util, exc as sa_exc, schema
from . import attributes, sync, exc as orm_exc, evaluator
from .util import _state_mapper, state_str, _attr_as_key
from ..sql import expression
+from . import loading
def save_obj(base_mapper, states, uowtransaction, single=False):
@@ -45,7 +46,7 @@ def save_obj(base_mapper, states, uowtransaction, single=False):
cached_connections = _cached_connection_dict(base_mapper)
- for table, mapper in base_mapper._sorted_tables.iteritems():
+ for table, mapper in base_mapper._sorted_tables.items():
insert = _collect_insert_commands(base_mapper, uowtransaction,
table, states_to_insert)
@@ -77,7 +78,7 @@ def post_update(base_mapper, states, uowtransaction, post_update_cols):
base_mapper,
states, uowtransaction)
- for table, mapper in base_mapper._sorted_tables.iteritems():
+ for table, mapper in base_mapper._sorted_tables.items():
update = _collect_post_update_commands(base_mapper, uowtransaction,
table, states_to_update,
post_update_cols)
@@ -105,7 +106,7 @@ def delete_obj(base_mapper, states, uowtransaction):
table_to_mapper = base_mapper._sorted_tables
- for table in reversed(table_to_mapper.keys()):
+ for table in reversed(list(table_to_mapper.keys())):
delete = _collect_delete_commands(base_mapper, uowtransaction,
table, states_to_delete)
@@ -318,7 +319,7 @@ def _collect_update_commands(base_mapper, uowtransaction,
# history is only
# in a different table than the one
# where the version_id_col is.
- for prop in mapper._columntoproperty.itervalues():
+ for prop in mapper._columntoproperty.values():
history = attributes.get_state_history(
state, prop.key,
attributes.PASSIVE_NO_INITIALIZE)
@@ -526,7 +527,7 @@ def _emit_insert_statements(base_mapper, uowtransaction,
for (connection, pkeys, hasvalue, has_all_pks), \
records in groupby(insert,
lambda rec: (rec[4],
- rec[2].keys(),
+ list(rec[2].keys()),
bool(rec[5]),
rec[6])
):
@@ -612,7 +613,7 @@ def _emit_post_update_statements(base_mapper, uowtransaction,
# also group them into common (connection, cols) sets
# to support executemany().
for key, grouper in groupby(
- update, lambda rec: (rec[4], rec[2].keys())
+ update, lambda rec: (rec[4], list(rec[2].keys()))
):
connection = key[0]
multiparams = [params for state, state_dict,
@@ -646,7 +647,7 @@ def _emit_delete_statements(base_mapper, uowtransaction, cached_connections,
return table.delete(clause)
- for connection, del_objects in delete.iteritems():
+ for connection, del_objects in delete.items():
statement = base_mapper._memo(('delete', table), delete_stmt)
connection = cached_connections[connection]
@@ -699,7 +700,6 @@ def _finalize_insert_update_commands(base_mapper, uowtransaction,
# refresh whatever has been expired.
if base_mapper.eager_defaults and state.unloaded:
state.key = base_mapper._identity_key_from_state(state)
- from . import loading
loading.load_on_ident(
uowtransaction.session.query(base_mapper),
state.key, refresh_state=state,
@@ -803,7 +803,7 @@ class BulkUD(object):
raise sa_exc.ArgumentError(
"Valid strategies for session synchronization "
"are %s" % (", ".join(sorted(repr(x)
- for x in lookup.keys()))))
+ for x in lookup))))
else:
return klass(*arg)
@@ -868,7 +868,7 @@ class BulkEvaluate(BulkUD):
#TODO: detect when the where clause is a trivial primary key match
self.matched_objects = [
obj for (cls, pk), obj in
- query.session.identity_map.iteritems()
+ query.session.identity_map.items()
if issubclass(cls, target_cls) and
eval_condition(obj)]
@@ -951,7 +951,7 @@ class BulkUpdateEvaluate(BulkEvaluate, BulkUpdate):
def _additional_evaluators(self, evaluator_compiler):
self.value_evaluators = {}
- for key, value in self.values.iteritems():
+ for key, value in self.values.items():
key = _attr_as_key(key)
self.value_evaluators[key] = evaluator_compiler.process(
expression._literal_as_binds(value))
@@ -959,7 +959,7 @@ class BulkUpdateEvaluate(BulkEvaluate, BulkUpdate):
def _do_post_synchronize(self):
session = self.query.session
states = set()
- evaluated_keys = self.value_evaluators.keys()
+ evaluated_keys = list(self.value_evaluators.keys())
for obj in self.matched_objects:
state, dict_ = attributes.instance_state(obj),\
attributes.instance_dict(obj)
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index 9f8721de9..8c0576527 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -27,7 +27,7 @@ from .interfaces import MANYTOMANY, MANYTOONE, ONETOMANY,\
mapperlib = util.importlater("sqlalchemy.orm", "mapperlib")
NoneType = type(None)
-from descriptor_props import CompositeProperty, SynonymProperty, \
+from .descriptor_props import CompositeProperty, SynonymProperty, \
ComparableProperty, ConcreteInheritedProperty
__all__ = ['ColumnProperty', 'CompositeProperty', 'SynonymProperty',
@@ -1204,7 +1204,7 @@ class RelationshipProperty(StrategizedProperty):
if not self.is_primary():
return
if self.backref is not None and not self.back_populates:
- if isinstance(self.backref, basestring):
+ if isinstance(self.backref, str):
backref_key, kwargs = self.backref, {}
else:
backref_key, kwargs = self.backref
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index c9f3a2699..beae7aba0 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -47,7 +47,7 @@ def _generative(*assertions):
def generate(fn, *args, **kw):
self = args[0]._clone()
for assertion in assertions:
- assertion(self, fn.func_name)
+ assertion(self, fn.__name__)
fn(self, *args[1:], **kw)
return self
return generate
@@ -162,15 +162,19 @@ class Query(object):
for m in m2.iterate_to_root():
self._polymorphic_adapters[m.local_table] = adapter
- def _set_select_from(self, *obj):
+ def _set_select_from(self, obj, set_base_alias):
fa = []
select_from_alias = None
+
for from_obj in obj:
info = inspect(from_obj)
if hasattr(info, 'mapper') and \
(info.is_mapper or info.is_aliased_class):
- self._select_from_entity = from_obj
+ if set_base_alias:
+ raise sa_exc.ArgumentError(
+ "A selectable (FromClause) instance is "
+ "expected when the base alias is being set.")
fa.append(info.selectable)
elif not info.is_selectable:
raise sa_exc.ArgumentError(
@@ -179,12 +183,14 @@ class Query(object):
else:
if isinstance(from_obj, expression.SelectBase):
from_obj = from_obj.alias()
- select_from_alias = from_obj
+ if set_base_alias:
+ select_from_alias = from_obj
fa.append(from_obj)
self._from_obj = tuple(fa)
- if len(self._from_obj) == 1 and \
+ if set_base_alias and \
+ len(self._from_obj) == 1 and \
isinstance(select_from_alias, expression.Alias):
equivs = self.__all_equivs()
self._from_obj_alias = sql_util.ColumnAdapter(
@@ -953,7 +959,7 @@ class Query(object):
'_prefixes',
):
self.__dict__.pop(attr, None)
- self._set_select_from(fromclause)
+ self._set_select_from([fromclause], True)
# this enables clause adaptation for non-ORM
# expressions.
@@ -981,11 +987,7 @@ class Query(object):
"""Return a scalar result corresponding to the given
column expression."""
try:
- # Py3K
- #return self.values(column).__next__()[0]
- # Py2K
- return self.values(column).next()[0]
- # end Py2K
+ return next(self.values(column))[0]
except StopIteration:
return None
@@ -1231,7 +1233,7 @@ class Query(object):
"""
clauses = [_entity_descriptor(self._joinpoint_zero(), key) == value
- for key, value in kwargs.iteritems()]
+ for key, value in kwargs.items()]
return self.filter(sql.and_(*clauses))
@_generative(_no_statement_condition, _no_limit_offset)
@@ -1296,7 +1298,7 @@ class Query(object):
"""
- if isinstance(criterion, basestring):
+ if isinstance(criterion, util.string_types):
criterion = sql.text(criterion)
if criterion is not None and \
@@ -1655,7 +1657,7 @@ class Query(object):
kwargs.pop('from_joinpoint', False)
if kwargs:
raise TypeError("unknown arguments: %s" %
- ','.join(kwargs.iterkeys()))
+ ','.join(kwargs.keys))
return self._join(props,
outerjoin=False, create_aliases=aliased,
from_joinpoint=from_joinpoint)
@@ -1671,7 +1673,7 @@ class Query(object):
kwargs.pop('from_joinpoint', False)
if kwargs:
raise TypeError("unknown arguments: %s" %
- ','.join(kwargs.iterkeys()))
+ ','.join(kwargs))
return self._join(props,
outerjoin=True, create_aliases=aliased,
from_joinpoint=from_joinpoint)
@@ -1701,7 +1703,7 @@ class Query(object):
if len(keys) == 2 and \
isinstance(keys[0], (expression.FromClause,
type, AliasedClass)) and \
- isinstance(keys[1], (basestring, expression.ClauseElement,
+ isinstance(keys[1], (str, expression.ClauseElement,
interfaces.PropComparator)):
# detect 2-arg form of join and
# convert to a tuple.
@@ -1721,14 +1723,14 @@ class Query(object):
# is a little bit of legacy behavior still at work here
# which means they might be in either order. may possibly
# lock this down to (right_entity, onclause) in 0.6.
- if isinstance(arg1, (interfaces.PropComparator, basestring)):
+ if isinstance(arg1, (interfaces.PropComparator, util.string_types)):
right_entity, onclause = arg2, arg1
else:
right_entity, onclause = arg1, arg2
left_entity = prop = None
- if isinstance(onclause, basestring):
+ if isinstance(onclause, util.string_types):
left_entity = self._joinpoint_zero()
descriptor = _entity_descriptor(left_entity, onclause)
@@ -1922,7 +1924,7 @@ class Query(object):
clause = orm_join(clause,
right,
onclause, isouter=outerjoin)
- except sa_exc.ArgumentError, ae:
+ except sa_exc.ArgumentError as ae:
raise sa_exc.InvalidRequestError(
"Could not find a FROM clause to join from. "
"Tried joining to %s, but got: %s" % (right, ae))
@@ -1947,7 +1949,7 @@ class Query(object):
try:
clause = orm_join(clause, right, onclause, isouter=outerjoin)
- except sa_exc.ArgumentError, ae:
+ except sa_exc.ArgumentError as ae:
raise sa_exc.InvalidRequestError(
"Could not find a FROM clause to join from. "
"Tried joining to %s, but got: %s" % (right, ae))
@@ -1974,21 +1976,134 @@ class Query(object):
def select_from(self, *from_obj):
"""Set the FROM clause of this :class:`.Query` explicitly.
- Sending a mapped class or entity here effectively replaces the
+ :meth:`.Query.select_from` is often used in conjunction with
+ :meth:`.Query.join` in order to control which entity is selected
+ from on the "left" side of the join.
+
+ The entity or selectable object here effectively replaces the
"left edge" of any calls to :meth:`~.Query.join`, when no
joinpoint is otherwise established - usually, the default "join
point" is the leftmost entity in the :class:`~.Query` object's
list of entities to be selected.
- Mapped entities or plain :class:`~.Table` or other selectables
- can be sent here which will form the default FROM clause.
+ A typical example::
+
+ q = session.query(Address).select_from(User).\\
+ join(User.addresses).\\
+ filter(User.name == 'ed')
+
+ Which produces SQL equivalent to::
+
+ SELECT address.* FROM user
+ JOIN address ON user.id=address.user_id
+ WHERE user.name = :name_1
+
+ :param \*from_obj: collection of one or more entities to apply
+ to the FROM clause. Entities can be mapped classes,
+ :class:`.AliasedClass` objects, :class:`.Mapper` objects
+ as well as core :class:`.FromClause` elements like subqueries.
+
+ .. versionchanged:: 0.9
+ This method no longer applies the given FROM object
+ to be the selectable from which matching entities
+ select from; the :meth:`.select_entity_from` method
+ now accomplishes this. See that method for a description
+ of this behavior.
+
+ .. seealso::
+
+ :meth:`~.Query.join`
+
+ :meth:`.Query.select_entity_from`
+
+ """
+
+ self._set_select_from(from_obj, False)
+
+ @_generative(_no_clauseelement_condition)
+ def select_entity_from(self, from_obj):
+ """Set the FROM clause of this :class:`.Query` to a
+ core selectable, applying it as a replacement FROM clause
+ for corresponding mapped entities.
+
+ This method is similar to the :meth:`.Query.select_from`
+ method, in that it sets the FROM clause of the query. However,
+ where :meth:`.Query.select_from` only affects what is placed
+ in the FROM, this method also applies the given selectable
+ to replace the FROM which the selected entities would normally
+ select from.
+
+ The given ``from_obj`` must be an instance of a :class:`.FromClause`,
+ e.g. a :func:`.select` or :class:`.Alias` construct.
+
+ An example would be a :class:`.Query` that selects ``User`` entities,
+ but uses :meth:`.Query.select_entity_from` to have the entities
+ selected from a :func:`.select` construct instead of the
+ base ``user`` table::
+
+ select_stmt = select([User]).where(User.id == 7)
+
+ q = session.query(User).\\
+ select_entity_from(select_stmt).\\
+ filter(User.name == 'ed')
+
+ The query generated will select ``User`` entities directly
+ from the given :func:`.select` construct, and will be::
+
+ SELECT anon_1.id AS anon_1_id, anon_1.name AS anon_1_name
+ FROM (SELECT "user".id AS id, "user".name AS name
+ FROM "user"
+ WHERE "user".id = :id_1) AS anon_1
+ WHERE anon_1.name = :name_1
+
+ Notice above that even the WHERE criterion was "adapted" such that
+ the ``anon_1`` subquery effectively replaces all references to the
+ ``user`` table, except for the one that it refers to internally.
+
+ Compare this to :meth:`.Query.select_from`, which as of
+ version 0.9, does not affect existing entities. The
+ statement below::
+
+ q = session.query(User).\\
+ select_from(select_stmt).\\
+ filter(User.name == 'ed')
+
+ Produces SQL where both the ``user`` table as well as the
+ ``select_stmt`` construct are present as separate elements
+ in the FROM clause. No "adaptation" of the ``user`` table
+ is applied::
+
+ SELECT "user".id AS user_id, "user".name AS user_name
+ FROM "user", (SELECT "user".id AS id, "user".name AS name
+ FROM "user"
+ WHERE "user".id = :id_1) AS anon_1
+ WHERE "user".name = :name_1
+
+ :meth:`.Query.select_entity_from` maintains an older
+ behavior of :meth:`.Query.select_from`. In modern usage,
+ similar results can also be achieved using :func:`.aliased`::
+
+ select_stmt = select([User]).where(User.id == 7)
+ user_from_select = aliased(User, select_stmt.alias())
+
+ q = session.query(user_from_select)
+
+ :param from_obj: a :class:`.FromClause` object that will replace
+ the FROM clause of this :class:`.Query`.
+
+ .. seealso::
+
+ :meth:`.Query.select_from`
- See the example in :meth:`~.Query.join` for a typical
- usage of :meth:`~.Query.select_from`.
+ .. versionadded:: 0.8
+ :meth:`.Query.select_entity_from` was added to specify
+ the specific behavior of entity replacement, however
+ the :meth:`.Query.select_from` maintains this behavior
+ as well until 0.9.
"""
- self._set_select_from(*from_obj)
+ self._set_select_from([from_obj], True)
def __getitem__(self, item):
if isinstance(item, slice):
@@ -2115,7 +2230,7 @@ class Query(object):
appropriate to the entity class represented by this ``Query``.
"""
- if isinstance(statement, basestring):
+ if isinstance(statement, util.string_types):
statement = sql.text(statement)
if not isinstance(statement,
@@ -2697,7 +2812,7 @@ class _QueryEntity(object):
def __new__(cls, *args, **kwargs):
if cls is _QueryEntity:
entity = args[1]
- if not isinstance(entity, basestring) and \
+ if not isinstance(entity, util.string_types) and \
_is_mapped_class(entity):
cls = _MapperEntity
else:
@@ -2905,7 +3020,7 @@ class _ColumnEntity(_QueryEntity):
self.expr = column
self.namespace = namespace
- if isinstance(column, basestring):
+ if isinstance(column, util.string_types):
column = sql.literal_column(column)
self._label_name = column.name
elif isinstance(column, (
@@ -3071,7 +3186,7 @@ class QueryContext(object):
self.create_eager_joins = []
self.propagate_options = set(o for o in query._with_options if
o.propagate_to_loaders)
- self.attributes = self._attributes = query._attributes.copy()
+ self.attributes = query._attributes.copy()
class AliasOption(interfaces.MapperOption):
@@ -3080,7 +3195,7 @@ class AliasOption(interfaces.MapperOption):
self.alias = alias
def process_query(self, query):
- if isinstance(self.alias, basestring):
+ if isinstance(self.alias, util.string_types):
alias = query._mapper_zero().mapped_table.alias(self.alias)
else:
alias = self.alias
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index ffb8a4e03..5a4486eef 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -5,7 +5,7 @@
# the MIT License: http://www.opensource.org/licenses/mit-license.php
"""Provides the Session class and related utilities."""
-from __future__ import with_statement
+
import weakref
from .. import util, sql, engine, exc as sa_exc, event
@@ -328,7 +328,7 @@ class SessionTransaction(object):
subtransaction.commit()
if not self.session._flushing:
- for _flush_guard in xrange(100):
+ for _flush_guard in range(100):
if self.session._is_clean():
break
self.session.flush()
@@ -605,7 +605,7 @@ class Session(_SessionClassMethods):
SessionExtension._adapt_listener(self, ext)
if binds is not None:
- for mapperortable, bind in binds.iteritems():
+ for mapperortable, bind in binds.items():
if isinstance(mapperortable, (type, Mapper)):
self.bind_mapper(mapperortable, bind)
else:
@@ -1776,7 +1776,7 @@ class Session(_SessionClassMethods):
Session.
"""
- return iter(list(self._new.values()) + self.identity_map.values())
+ return iter(list(self._new.values()) + list(self.identity_map.values()))
def _contains_state(self, state):
return state in self._new or self.identity_map.contains_state(state)
@@ -2139,13 +2139,13 @@ class Session(_SessionClassMethods):
def deleted(self):
"The set of all instances marked as 'deleted' within this ``Session``"
- return util.IdentitySet(self._deleted.values())
+ return util.IdentitySet(list(self._deleted.values()))
@property
def new(self):
"The set of all instances marked as 'new' within this ``Session``."
- return util.IdentitySet(self._new.values())
+ return util.IdentitySet(list(self._new.values()))
class sessionmaker(_SessionClassMethods):
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 6660a39ef..cabfb35b9 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -359,7 +359,7 @@ class LazyLoader(AbstractRelationshipLoader):
)
if self.use_get:
- for col in self._equated_columns.keys():
+ for col in list(self._equated_columns):
if col in self.mapper._equivalent_columns:
for c in self.mapper._equivalent_columns[col]:
self._equated_columns[c] = self._equated_columns[col]
@@ -688,7 +688,8 @@ class SubqueryLoader(AbstractRelationshipLoader):
# build up a path indicating the path from the leftmost
# entity to the thing we're subquery loading.
- with_poly_info = path.get(context, "path_with_polymorphic", None)
+ with_poly_info = path.get(context.attributes,
+ "path_with_polymorphic", None)
if with_poly_info is not None:
effective_entity = with_poly_info.entity
else:
@@ -701,7 +702,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
# if not via query option, check for
# a cycle
- if not path.contains(context, "loaderstrategy"):
+ if not path.contains(context.attributes, "loaderstrategy"):
if self.join_depth:
if path.length / 2 > self.join_depth:
return
@@ -747,7 +748,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
# add new query to attributes to be picked up
# by create_row_processor
- path.set(context, "subquery", q)
+ path.set(context.attributes, "subquery", q)
def _get_leftmost(self, subq_path):
subq_path = subq_path.path
@@ -781,7 +782,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
# set a real "from" if not present, as this is more
# accurate than just going off of the column expression
if not q._from_obj and entity_mapper.isa(leftmost_mapper):
- q._set_select_from(entity_mapper)
+ q._set_select_from([entity_mapper], False)
# select from the identity columns of the outer
q._set_entities(q._adapt_col_list(leftmost_attr))
@@ -924,7 +925,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
path = path[self.parent_property]
- subq = path.get(context, 'subquery')
+ subq = path.get(context.attributes, 'subquery')
if subq is None:
return None, None, None
@@ -934,7 +935,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
# cache the loaded collections in the context
# so that inheriting mappers don't re-load when they
# call upon create_row_processor again
- collections = path.get(context, "collections")
+ collections = path.get(context.attributes, "collections")
if collections is None:
collections = dict(
(k, [v[0] for v in v])
@@ -942,7 +943,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
subq,
lambda x: x[1:]
))
- path.set(context, 'collections', collections)
+ path.set(context.attributes, 'collections', collections)
if adapter:
local_cols = [adapter.columns[c] for c in local_cols]
@@ -1011,7 +1012,7 @@ class JoinedLoader(AbstractRelationshipLoader):
with_polymorphic = None
- user_defined_adapter = path.get(context,
+ user_defined_adapter = path.get(context.attributes,
"user_defined_eager_row_processor",
False)
if user_defined_adapter is not False:
@@ -1023,7 +1024,7 @@ class JoinedLoader(AbstractRelationshipLoader):
else:
# if not via query option, check for
# a cycle
- if not path.contains(context, "loaderstrategy"):
+ if not path.contains(context.attributes, "loaderstrategy"):
if self.join_depth:
if path.length / 2 > self.join_depth:
return
@@ -1037,7 +1038,7 @@ class JoinedLoader(AbstractRelationshipLoader):
)
with_poly_info = path.get(
- context,
+ context.attributes,
"path_with_polymorphic",
None
)
@@ -1065,11 +1066,11 @@ class JoinedLoader(AbstractRelationshipLoader):
adapter = entity._get_entity_clauses(context.query, context)
if adapter and user_defined_adapter:
user_defined_adapter = user_defined_adapter.wrap(adapter)
- path.set(context, "user_defined_eager_row_processor",
+ path.set(context.attributes, "user_defined_eager_row_processor",
user_defined_adapter)
elif adapter:
user_defined_adapter = adapter
- path.set(context, "user_defined_eager_row_processor",
+ path.set(context.attributes, "user_defined_eager_row_processor",
user_defined_adapter)
add_to_collection = context.primary_columns
@@ -1080,7 +1081,7 @@ class JoinedLoader(AbstractRelationshipLoader):
column_collection, parentmapper, allow_innerjoin
):
with_poly_info = path.get(
- context,
+ context.attributes,
"path_with_polymorphic",
None
)
@@ -1098,7 +1099,7 @@ class JoinedLoader(AbstractRelationshipLoader):
if self.parent_property.direction != interfaces.MANYTOONE:
context.multi_row_eager_loaders = True
- innerjoin = allow_innerjoin and path.get(context,
+ innerjoin = allow_innerjoin and path.get(context.attributes,
"eager_join_type",
self.parent_property.innerjoin)
if not innerjoin:
@@ -1113,7 +1114,7 @@ class JoinedLoader(AbstractRelationshipLoader):
)
add_to_collection = context.secondary_columns
- path.set(context, "eager_row_processor", clauses)
+ path.set(context.attributes, "eager_row_processor", clauses)
return clauses, adapter, add_to_collection, allow_innerjoin
@@ -1208,7 +1209,7 @@ class JoinedLoader(AbstractRelationshipLoader):
)
def _create_eager_adapter(self, context, row, adapter, path):
- user_defined_adapter = path.get(context,
+ user_defined_adapter = path.get(context.attributes,
"user_defined_eager_row_processor",
False)
if user_defined_adapter is not False:
@@ -1221,7 +1222,7 @@ class JoinedLoader(AbstractRelationshipLoader):
elif context.adapter:
decorator = context.adapter
else:
- decorator = path.get(context, "eager_row_processor")
+ decorator = path.get(context.attributes, "eager_row_processor")
if decorator is None:
return False
@@ -1332,7 +1333,7 @@ class EagerLazyOption(StrategizedOption):
def __init__(self, key, lazy=True, chained=False,
propagate_to_loaders=True
):
- if isinstance(key[0], basestring) and key[0] == '*':
+ if isinstance(key[0], str) and key[0] == '*':
if len(key) != 1:
raise sa_exc.ArgumentError(
"Wildcard identifier '*' must "
@@ -1374,9 +1375,9 @@ class EagerJoinOption(PropertyOption):
def process_query_property(self, query, paths):
if self.chained:
for path in paths:
- path.set(query, "eager_join_type", self.innerjoin)
+ path.set(query._attributes, "eager_join_type", self.innerjoin)
else:
- paths[-1].set(query, "eager_join_type", self.innerjoin)
+ paths[-1].set(query._attributes, "eager_join_type", self.innerjoin)
class LoadEagerFromAliasOption(PropertyOption):
@@ -1384,7 +1385,7 @@ class LoadEagerFromAliasOption(PropertyOption):
def __init__(self, key, alias=None, chained=False):
super(LoadEagerFromAliasOption, self).__init__(key)
if alias is not None:
- if not isinstance(alias, basestring):
+ if not isinstance(alias, str):
info = inspect(alias)
alias = info.selectable
self.alias = alias
@@ -1395,29 +1396,32 @@ class LoadEagerFromAliasOption(PropertyOption):
for path in paths[0:-1]:
(root_mapper, prop) = path.path[-2:]
adapter = query._polymorphic_adapters.get(prop.mapper, None)
- path.setdefault(query,
+ path.setdefault(query._attributes,
"user_defined_eager_row_processor",
adapter)
root_mapper, prop = paths[-1].path[-2:]
if self.alias is not None:
- if isinstance(self.alias, basestring):
+ if isinstance(self.alias, str):
self.alias = prop.target.alias(self.alias)
- paths[-1].set(query, "user_defined_eager_row_processor",
- sql_util.ColumnAdapter(self.alias,
+ paths[-1].set(query._attributes,
+ "user_defined_eager_row_processor",
+ sql_util.ColumnAdapter(self.alias,
equivalents=prop.mapper._equivalent_columns)
)
else:
- if paths[-1].contains(query, "path_with_polymorphic"):
- with_poly_info = paths[-1].get(query, "path_with_polymorphic")
+ if paths[-1].contains(query._attributes, "path_with_polymorphic"):
+ with_poly_info = paths[-1].get(query._attributes,
+ "path_with_polymorphic")
adapter = orm_util.ORMAdapter(
with_poly_info.entity,
equivalents=prop.mapper._equivalent_columns,
adapt_required=True)
else:
adapter = query._polymorphic_adapters.get(prop.mapper, None)
- paths[-1].set(query, "user_defined_eager_row_processor",
- adapter)
+ paths[-1].set(query._attributes,
+ "user_defined_eager_row_processor",
+ adapter)
def single_parent_validator(desc, prop):
diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py
index 1f5115c41..aa5f7836c 100644
--- a/lib/sqlalchemy/orm/unitofwork.py
+++ b/lib/sqlalchemy/orm/unitofwork.py
@@ -315,7 +315,7 @@ class UOWTransaction(object):
# see if the graph of mapper dependencies has cycles.
self.cycles = cycles = topological.find_cycles(
self.dependencies,
- self.postsort_actions.values())
+ list(self.postsort_actions.values()))
if cycles:
# if yes, break the per-mapper actions into
@@ -381,7 +381,7 @@ class UOWTransaction(object):
"""
states = set(self.states)
isdel = set(
- s for (s, (isdelete, listonly)) in self.states.iteritems()
+ s for (s, (isdelete, listonly)) in self.states.items()
if isdelete
)
other = states.difference(isdel)
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 390e83538..bd8228f2c 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -120,7 +120,7 @@ def polymorphic_union(table_map, typecolname,
colnames = util.OrderedSet()
colnamemaps = {}
types = {}
- for key in table_map.keys():
+ for key in table_map:
table = table_map[key]
# mysql doesnt like selecting from a select;
@@ -146,7 +146,7 @@ def polymorphic_union(table_map, typecolname,
return sql.type_coerce(sql.null(), types[name]).label(name)
result = []
- for type, table in table_map.iteritems():
+ for type, table in table_map.items():
if typecolname is not None:
result.append(
sql.select([col(name, table) for name in colnames] +
@@ -203,7 +203,7 @@ def identity_key(*args, **kwargs):
"positional arguments, got %s" % len(args))
if kwargs:
raise sa_exc.ArgumentError("unknown keyword arguments: %s"
- % ", ".join(kwargs.keys()))
+ % ", ".join(kwargs))
mapper = class_mapper(class_)
if "ident" in locals():
return mapper.identity_key_from_primary_key(util.to_list(ident))
@@ -211,7 +211,7 @@ def identity_key(*args, **kwargs):
instance = kwargs.pop("instance")
if kwargs:
raise sa_exc.ArgumentError("unknown keyword arguments: %s"
- % ", ".join(kwargs.keys()))
+ % ", ".join(kwargs.keys))
mapper = object_mapper(instance)
return mapper.identity_key_from_instance(instance)
@@ -278,16 +278,16 @@ class PathRegistry(object):
return other is not None and \
self.path == other.path
- def set(self, reg, key, value):
- reg._attributes[(key, self.path)] = value
+ def set(self, attributes, key, value):
+ attributes[(key, self.path)] = value
- def setdefault(self, reg, key, value):
- reg._attributes.setdefault((key, self.path), value)
+ def setdefault(self, attributes, key, value):
+ attributes.setdefault((key, self.path), value)
- def get(self, reg, key, value=None):
+ def get(self, attributes, key, value=None):
key = (key, self.path)
- if key in reg._attributes:
- return reg._attributes[key]
+ if key in attributes:
+ return attributes[key]
else:
return value
@@ -300,7 +300,7 @@ class PathRegistry(object):
def pairs(self):
path = self.path
- for i in xrange(0, len(path), 2):
+ for i in range(0, len(path), 2):
yield path[i], path[i + 1]
def contains_mapper(self, mapper):
@@ -313,18 +313,18 @@ class PathRegistry(object):
else:
return False
- def contains(self, reg, key):
- return (key, self.path) in reg._attributes
+ def contains(self, attributes, key):
+ return (key, self.path) in attributes
def __reduce__(self):
return _unreduce_path, (self.serialize(), )
def serialize(self):
path = self.path
- return zip(
+ return list(zip(
[m.class_ for m in [path[i] for i in range(0, len(path), 2)]],
[path[i].key for i in range(1, len(path), 2)] + [None]
- )
+ ))
@classmethod
def deserialize(cls, path):
@@ -418,8 +418,9 @@ class EntityRegistry(PathRegistry, dict):
self.path = parent.path + (entity,)
- def __nonzero__(self):
+ def __bool__(self):
return True
+ __nonzero__ = __bool__
def __getitem__(self, entity):
if isinstance(entity, (int, slice)):
@@ -440,8 +441,8 @@ class EntityRegistry(PathRegistry, dict):
"""
path = dict.__getitem__(self, prop)
path_key = (key, path.path)
- if path_key in context._attributes:
- return context._attributes[path_key]
+ if path_key in context.attributes:
+ return context.attributes[path_key]
else:
return None
@@ -596,8 +597,8 @@ class AliasedClass(object):
return self.__adapt_prop(attr, key)
elif hasattr(attr, 'func_code'):
is_method = getattr(self.__target, key, None)
- if is_method and is_method.im_self is not None:
- return util.types.MethodType(attr.im_func, self, self)
+ if is_method and is_method.__self__ is not None:
+ return util.types.MethodType(attr.__func__, self, self)
else:
return None
elif hasattr(attr, '__get__'):
@@ -887,7 +888,7 @@ class _ORMJoin(expression.Join):
self._joined_from_info = right_info
- if isinstance(onclause, basestring):
+ if isinstance(onclause, util.string_types):
onclause = getattr(left_orm_info.entity, onclause)
if isinstance(onclause, attributes.QueryableAttribute):
@@ -1008,7 +1009,7 @@ def with_parent(instance, prop):
parent/child relationship.
"""
- if isinstance(prop, basestring):
+ if isinstance(prop, util.string_types):
mapper = object_mapper(instance)
prop = getattr(mapper.class_, prop).property
elif isinstance(prop, attributes.QueryableAttribute):