Commits

Mike Bayer committed af8c8b0

- more accurate changelog message
- generalized the descriptor detection to any object with a __get__ attribute

Comments (0)

Files changed (3)

     - A critical fix to dynamic relations allows the 
       "modified" history to be properly cleared after
       a flush().
-    
-    - An inheriting class can now override an attribute
-      inherited from the base class with a plain descriptor, 
-      or exclude an inherited attribute via the 
+
+    - user-defined @properties on a class are detected
+      and left in place during mapper initialization.
+      This means that a table-bound column of the same
+      name will not be mapped at all if a @property is
+      in the way (and the column is not remapped to 
+      a different name), nor will an instrumented attribute
+      from an inherited class be applied.  The same
+      rules apply for names excluded using the 
       include_properties/exclude_properties collections.
-      
+
     - Added a new SessionExtension hook called after_attach().
       This is called at the point of attachment for objects
       via add(), add_all(), delete(), and merge().

lib/sqlalchemy/orm/mapper.py

         
         """
         # check for an existing descriptor
-        if isinstance(
-            getattr(self.class_, name, None),
-            property):
+        if getattr(self.class_, name, None) \
+            and hasattr(getattr(self.class_, name), '__get__'):
             return True
         
         if (self.include_properties is not None and

test/orm/inheritance/basic.py

         sess.add(s1)
         sess.flush()
         assert sess.query(Sub).one().data == "im the data"
+
+    def test_custom_descriptor(self):
+        """test that descriptors prevent inheritance from propigating properties to subclasses."""
+
+        class MyDesc(object):
+            def __get__(self, instance, owner):
+                if instance is None:
+                    return self
+                return "im the data"
+            
+        class Base(object):
+            pass
+        class Sub(Base):
+            data = MyDesc()
+
+        mapper(Base, base)
+        mapper(Sub, subtable, inherits=Base)
+
+        s1 = Sub()
+        sess = create_session()
+        sess.add(s1)
+        sess.flush()
+        assert sess.query(Sub).one().data == "im the data"
         
 
 if __name__ == "__main__":