From a456fd54759fb99d6575c8abe85cbbba638b3179 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 27 Apr 2006 23:56:09 +0000 Subject: [PATCH] the latest and greatest method to keep attributes from growing --- lib/sqlalchemy/attributes.py | 27 +++++---------------------- test/attributes.py | 3 ++- test/masscreate2.py | 36 ++++++++++++++++++++++++++++++++++++ test/massload.py | 2 +- 4 files changed, 44 insertions(+), 24 deletions(-) create mode 100644 test/masscreate2.py diff --git a/lib/sqlalchemy/attributes.py b/lib/sqlalchemy/attributes.py index 98884df441..627cac4b61 100644 --- a/lib/sqlalchemy/attributes.py +++ b/lib/sqlalchemy/attributes.py @@ -79,8 +79,12 @@ class ManagedAttribute(object): ManagedAttribute objects associated with the instance via this dictionary.""" def __init__(self, obj, key): self.__obj = weakref.ref(obj) - #self.obj = obj self.key = key + def __getstate__(self): + return {'key':self.key, 'obj':self.obj} + def __setstate__(self, d): + self.key = d['key'] + self.__obj = weakref.ref(d['obj']) obj = property(lambda s:s.__obj()) def history(self, **kwargs): return self @@ -496,25 +500,4 @@ class AttributeManager(object): will be passed along to newly created ManagedAttribute.""" if not hasattr(class_, '_attribute_manager'): class_._attribute_manager = self - class_._managed_attributes = ObjectAttributeGateway() setattr(class_, key, self.create_prop(class_, key, uselist, callable_, **kwargs)) - -managed_attributes = weakref.WeakKeyDictionary() - -class ObjectAttributeGateway(object): - """handles the dictionary of ManagedAttributes for instances. this level of indirection - is to prevent circular references upon objects, as well as keeping them Pickle-compatible.""" - def __set__(self, obj, value): - managed_attributes[obj] = value - def __delete__(self, obj): - try: - del managed_attributes[obj] - except KeyError: - raise AttributeError() - def __get__(self, obj, owner): - if obj is None: - return self - try: - return managed_attributes[obj] - except KeyError: - raise AttributeError() \ No newline at end of file diff --git a/test/attributes.py b/test/attributes.py index bff864fa69..126f504564 100644 --- a/test/attributes.py +++ b/test/attributes.py @@ -45,7 +45,8 @@ class AttributesTest(PersistTest): manager.register_attribute(MyTest, 'email_address', uselist = False) x = MyTest() x.user_id=7 - pickle.dumps(x) + s = pickle.dumps(x) + y = pickle.loads(s) def testlist(self): class User(object):pass diff --git a/test/masscreate2.py b/test/masscreate2.py new file mode 100644 index 0000000000..f261f832ce --- /dev/null +++ b/test/masscreate2.py @@ -0,0 +1,36 @@ +import gc + +import random, string + +from sqlalchemy.attributes import * + +# with this test, run top. make sure the Python process doenst grow in size arbitrarily. + +class User(object): + pass + +class Address(object): + pass + +attr_manager = AttributeManager() +attr_manager.register_attribute(User, 'id', uselist=False) +attr_manager.register_attribute(User, 'name', uselist=False) +attr_manager.register_attribute(User, 'addresses', uselist=True) +attr_manager.register_attribute(Address, 'email', uselist=False) +attr_manager.register_attribute(Address, 'user', uselist=False) + + +for i in xrange(1000): + for j in xrange(1000): + u = User() + u.name = str(random.randint(0, 100000000)) + for k in xrange(10): + a = Address() + a.email_address = str(random.randint(0, 100000000)) + u.addresses.append(a) + a.user = u + print "clearing" + #managed_attributes.clear() + gc.collect() + + diff --git a/test/massload.py b/test/massload.py index 43309467ab..ab47415e8a 100644 --- a/test/massload.py +++ b/test/massload.py @@ -56,7 +56,7 @@ class LoadTest(AssertMixin): a.value = 'changed...' assert len(objectstore.get_session().dirty) == len(l) assert len(objectstore.get_session().identity_map) == len(l) - assert len(attributes.managed_attributes) == len(l) + #assert len(attributes.managed_attributes) == len(l) print len(objectstore.get_session().dirty) print len(objectstore.get_session().identity_map) objectstore.expunge(*l) -- 2.47.2