Skip to content

Commit

Permalink
py/deactivate vs slots: A slot variable could not be initialized at all
Browse files Browse the repository at this point in the history
fe2219f (On deactivate release in-slots objects too) started to release
objects from slotted variables but was not careful enough while doing so: we
have to be careful while deleting as for unset variables it will raise
AttributeError:

    class C(object):
        __slots__ = ['aaa', 'unset']

        def __init__(self, aaa):
            self.aaa = 1

    c = C(111)
    del c.aaa
    del c.unset

    Traceback (most recent call last):
      File "y.py", line 9, in <module>
        del c.unset
    AttributeError: unset

Caught by preparing fix for #44 (comment)

C version already have this protection in the original fe2219f patch:

    +            if (PyObject_GenericSetAttr((PyObject *)self, name, NULL) < 0)
    +                /* delattr of non-set slot will raise AttributeError - we
    +                 * simply ignore. */
    +                PyErr_Clear();
  • Loading branch information
navytux authored and jamadden committed Oct 28, 2016
1 parent c4116ac commit ac51dff
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 2 deletions.
3 changes: 2 additions & 1 deletion persistent/persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ def _p_invalidate_deactivate_helper(self, clear=True):
try:
getattr(type_, slotname).__delete__(self)
except AttributeError:
pass
# AttributeError means slot variable was not initialized at all -
# - we can simply skip its deletion.

# Implementation detail: deactivating/invalidating
# updates the size of the cache (if we have one)
Expand Down
2 changes: 1 addition & 1 deletion persistent/tests/test_persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -1321,7 +1321,7 @@ def __init__(self):

def test__p_invalidate_from_changed_w_slots(self):
class Derived(self._getTargetClass()):
__slots__ = ('myattr1', 'myattr2')
__slots__ = ('myattr1', 'myattr2', 'unset')
def __init__(self):
self.myattr1 = 'value1'
self.myattr2 = 'value2'
Expand Down

0 comments on commit ac51dff

Please sign in to comment.