]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Raise UnmappedInstanceError if the attribute of a database object is an unmapped...
authorRamonWill <ramonwilliams@hotmail.co.uk>
Thu, 13 Aug 2020 21:23:16 +0000 (17:23 -0400)
committersqla-tester <sqla-tester@sqlalchemy.org>
Thu, 13 Aug 2020 21:23:16 +0000 (17:23 -0400)
The proposed change will raise an UnmappedInstanceError instead of an attribute error if an instance an Instrumented Attribute is unmapped.

### Description
If a user tries to access an attribute of a database object that is unmapped then an error is raised. The reason for this is because the __get__  descriptor  uses instance_state(instance) which uses the operator.attrgetter method to see if the object in question has the attribute "_sa_instance_state" that mapped objects have.  If it doesn't contain this attribute it means that the object is unmapped.

This pull request is:

- [ ] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [X ] A short code fix
- please include the issue number, and create an issue if none exists, which
  must include a complete example of the issue.  one line code fixes without an
  issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
  include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.

**Have a nice day!**
Fixes: #3858
Closes: #5478
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5478
Pull-request-sha: 853051c9225446b69f52b13ade78709ad2617f6d

Change-Id: I5989c81227e55e628babdd11406d1e8ec0e8d93a

doc/build/changelog/unreleased_14/3858.rst [new file with mode: 0644]
lib/sqlalchemy/orm/attributes.py
test/orm/test_attributes.py

diff --git a/doc/build/changelog/unreleased_14/3858.rst b/doc/build/changelog/unreleased_14/3858.rst
new file mode 100644 (file)
index 0000000..62d57cc
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: bug, orm
+    :tickets: 3858
+
+    An ``UnmappedInstanceError`` is now raised for :class:`.InstrumentedAttribute`
+    if an instance is an unmapped object. Prior to this an ``AttributeError``
+    was raised. Pull request courtesy Ramon Williams.
index 2e1b9dc75ee716207b1268f4bd29983b205b69a6..07b147f10f85dde904670f07b8ad4f5a5d5d2d54 100644 (file)
@@ -353,7 +353,14 @@ class InstrumentedAttribute(QueryableAttribute):
         if self._supports_population and self.key in dict_:
             return dict_[self.key]
         else:
-            return self.impl.get(instance_state(instance), dict_)
+            try:
+                state = instance_state(instance)
+            except AttributeError as err:
+                util.raise_(
+                    orm_exc.UnmappedInstanceError(instance),
+                    replace_context=err,
+                )
+            return self.impl.get(state, dict_)
 
 
 HasEntityNamespace = util.namedtuple(
index 43a7d8dc83f7408ef0491549faad65cc64dd7040..671c75fa7ce2552eb512cfd6537b3fd04e3cb2ce 100644 (file)
@@ -361,6 +361,26 @@ class AttributesTest(fixtures.ORMTest):
             lambda: Foo().bars.append(Bar()),
         )
 
+    def test_unmapped_instance_raises(self):
+        class User(object):
+            pass
+
+        instrumentation.register_class(User)
+        attributes.register_attribute(
+            User, "user_name", uselist=False, useobject=False
+        )
+
+        class Blog(object):
+            name = User.user_name
+
+        def go():
+            b = Blog()
+            return b.name
+
+        assert_raises(
+            orm_exc.UnmappedInstanceError, go,
+        )
+
     def test_del_scalar_nonobject(self):
         class Foo(object):
             pass