- [feature] Can now provide class-bound attributes

that override columns which are of any
    non-ORM type, not just descriptors.
    [ticket:2535]
This commit is contained in:
Mike Bayer
2012-08-04 18:11:18 -04:00
parent b99480aac2
commit 79f26dbff9
3 changed files with 67 additions and 14 deletions
+5
View File
@@ -185,6 +185,11 @@ underneath "0.7.xx".
when dereferenced by a unit test.
[ticket:2526]
- [feature] Can now provide class-bound attributes
that override columns which are of any
non-ORM type, not just descriptors.
[ticket:2535]
- [feature] Added with_labels and
reduce_columns keyword arguments to
Query.subquery(), to provide two alternate
+6 -12
View File
@@ -1630,18 +1630,12 @@ class Mapper(_InspectionAttr):
def _is_userland_descriptor(self, obj):
if isinstance(obj, (MapperProperty,
attributes.QueryableAttribute)):
return False
elif not hasattr(obj, '__get__'):
attributes.QueryableAttribute,
instrumentation.ClassManager,
expression.ColumnElement)):
return False
else:
obj = util.unbound_method_to_callable(obj)
if isinstance(
obj.__get__(None, obj),
attributes.QueryableAttribute
):
return False
return True
return True
def _should_exclude(self, name, assigned_name, local, column):
"""determine whether a particular property should be implicitly
@@ -1652,8 +1646,8 @@ class Mapper(_InspectionAttr):
"""
# check for descriptors, either local or from
# an inherited class
# check for class-bound attributes and/or descriptors,
# either local or from an inherited class
if local:
if self.class_.__dict__.get(assigned_name, None) is not None \
and self._is_userland_descriptor(
+56 -2
View File
@@ -12,7 +12,7 @@ from sqlalchemy.orm import mapper, relationship, backref, \
column_property, composite, dynamic_loader, \
comparable_property, Session
from sqlalchemy.orm.persistence import _sort_states
from test.lib.testing import eq_, AssertsCompiledSQL
from test.lib.testing import eq_, AssertsCompiledSQL, is_
from test.lib import fixtures
from test.orm import _fixtures
from test.lib.assertsql import CompiledSQL
@@ -3098,6 +3098,61 @@ class RequirementsTest(fixtures.MappedTest):
h2.value = "Asdf"
h2.value = "asdf asdf" # ding
class IsUserlandTest(fixtures.MappedTest):
@classmethod
def define_tables(cls, metadata):
Table('foo', metadata,
Column('id', Integer, primary_key=True),
Column('someprop', Integer)
)
def _test(self, value, instancelevel=None):
class Foo(object):
someprop = value
m = mapper(Foo, self.tables.foo)
eq_(Foo.someprop, value)
f1 = Foo()
if instancelevel is not None:
eq_(f1.someprop, instancelevel)
else:
eq_(f1.someprop, value)
assert self.tables.foo.c.someprop not in m._columntoproperty
def _test_not(self, value):
class Foo(object):
someprop = value
m = mapper(Foo, self.tables.foo)
is_(Foo.someprop.property.columns[0], self.tables.foo.c.someprop)
assert self.tables.foo.c.someprop in m._columntoproperty
def test_string(self):
self._test("someprop")
def test_unicode(self):
self._test(u"someprop")
def test_int(self):
self._test(5)
def test_dict(self):
self._test({"bar": "bat"})
def test_set(self):
self._test(set([6]))
def test_column(self):
self._test_not(self.tables.foo.c.someprop)
def test_relationship(self):
self._test_not(relationship("bar"))
def test_descriptor(self):
def somefunc(self):
return "hi"
self._test(property(somefunc), "hi")
class MagicNamesTest(fixtures.MappedTest):
@classmethod
@@ -3157,7 +3212,6 @@ class MagicNamesTest(fixtures.MappedTest):
Column(reserved, Integer))
class T(object):
pass
assert_raises_message(
KeyError,
('%r: requested attribute name conflicts with '