mò qã¸Ec@sbdZdklZdkZdklZdefd„ƒYZdefd„ƒYZd„ZdS( s¯Overriding attr methods This module tests and documents, through example, overriding attribute access methods. $Id: test_overriding_attrs.py 38214 2005-08-31 20:43:54Z mj $ (s PersistentN(sDBtSampleOverridingGetattrcBstZdZd„ZRS(s&Example of overriding __getattr__ cCsG|idƒo |idƒot|ƒ‚n|iƒ|ifSdS(sâGet attributes that can't be gotten the usual way The __getattr__ method works pretty much the same for persistent classes as it does for other classes. No special handling is needed. If an object is a ghost, then it will be activated before __getattr__ is called. In this example, our objects returns a tuple with the attribute name, converted to upper case and the value of _p_changed, for any attribute that isn't handled by the default machinery. >>> o = SampleOverridingGetattr() >>> o._p_changed False >>> o._p_oid >>> o._p_jar >>> o.spam ('SPAM', False) >>> o.spam = 1 >>> o.spam 1 We'll save the object, so it can be deactivated: >>> db = DB() >>> conn = db.open() >>> conn.root()['o'] = o >>> transaction.commit() >>> o._p_deactivate() >>> o._p_changed And now, if we ask for an attribute it doesn't have, >>> o.eggs ('EGGS', False) And we see that the object was activated before calling the __getattr__ method. We always close databases after we use them: >>> db.close() t__N(tnamet startswitht endswrithtAttributeErrortuppertselft _p_changed(RR((tE/data/zmath/zope/lib/python/persistent/tests/test_overriding_attrs.pyt __getattr__s+ (t__name__t __module__t__doc__R (((R Rs t-SampleOverridingGetattributeSetattrAndDelattrcBs2tZdZd„Zd„Zd„Zd„ZRS(s¯Example of overriding __getattribute__, __setattr__, and __delattr__ In this example, we'll provide an example that shows how to override the __getattribute__, __setattr__, and __delattr__ methods. We'll create a class that stores it's attributes in a secret dictionary within it's instance dictionary. The class will have the policy that variables with names starting with 'tmp_' will be volatile. cKs|iƒ|id>> o = SampleOverridingGetattributeSetattrAndDelattr(x=1) >>> o._p_changed 0 >>> o._p_oid >>> o._p_jar >>> o.x 1 >>> o.y Traceback (most recent call last): ... AttributeError: y Next, we'll save the object in a database so that we can deactivate it: >>> db = DB() >>> conn = db.open() >>> conn.root()['o'] = o >>> transaction.commit() >>> o._p_deactivate() >>> o._p_changed And we'll get some data: >>> o.x 1 which activates the object: >>> o._p_changed 0 It works for missing attribes too: >>> o._p_deactivate() >>> o._p_changed >>> o.y Traceback (most recent call last): ... AttributeError: y >>> o._p_changed 0 See the very important note in the comment below! We always close databases after we use them: >>> db.close() RN( t Persistentt _p_getattrRRt__getattribute__Rtsecrettgetattrt __class__tNonetmethRt__get__(RRRR((R R`s<    cCsPti|||ƒodSn||id|<|idƒp d|_ndS(s<Set an attribute value The __setattr__ method is called for all attribute assignments. It overrides the attribute assignment support inherited from Persistent. Implementors of __setattr__ methods: 1. Must call Persistent._p_setattr first to allow it to handle some attributes and to make sure that the object is activated if necessary, and 2. Must set _p_changed to mark objects as changed. See the comments in the source below. >>> o = SampleOverridingGetattributeSetattrAndDelattr() >>> o._p_changed 0 >>> o._p_oid >>> o._p_jar >>> o.x Traceback (most recent call last): ... AttributeError: x >>> o.x = 1 >>> o.x 1 Because the implementation doesn't store attributes directly in the instance dictionary, we don't have a key for the attribute: >>> 'x' in o.__dict__ False Next, we'll save the object in a database so that we can deactivate it: >>> db = DB() >>> conn = db.open() >>> conn.root()['o'] = o >>> transaction.commit() >>> o._p_deactivate() >>> o._p_changed We'll modify an attribute >>> o.y = 2 >>> o.y 2 which reactivates it, and markes it as modified, because our implementation marked it as modified: >>> o._p_changed 1 Now, if commit: >>> transaction.commit() >>> o._p_changed 0 And deactivate the object: >>> o._p_deactivate() >>> o._p_changed and then set a variable with a name starting with 'tmp_', The object will be activated, but not marked as modified, because our __setattr__ implementation doesn't mark the object as changed if the name starts with 'tmp_': >>> o.tmp_foo = 3 >>> o._p_changed 0 >>> o.tmp_foo 3 We always close databases after we use them: >>> db.close() NRttmp_i(Rt _p_setattrRRtvalueRRR(RRR((R t __setattr__ºs U cCsJti||ƒodSn|id|=|idƒp d|_ndS(sXDelete an attribute value The __delattr__ method is called for all attribute deletions. It overrides the attribute deletion support inherited from Persistent. Implementors of __delattr__ methods: 1. Must call Persistent._p_delattr first to allow it to handle some attributes and to make sure that the object is activated if necessary, and 2. Must set _p_changed to mark objects as changed. See the comments in the source below. >>> o = SampleOverridingGetattributeSetattrAndDelattr( ... x=1, y=2, tmp_z=3) >>> o._p_changed 0 >>> o._p_oid >>> o._p_jar >>> o.x 1 >>> del o.x >>> o.x Traceback (most recent call last): ... AttributeError: x Next, we'll save the object in a database so that we can deactivate it: >>> db = DB() >>> conn = db.open() >>> conn.root()['o'] = o >>> transaction.commit() >>> o._p_deactivate() >>> o._p_changed If we delete an attribute: >>> del o.y The object is activated. It is also marked as changed because our implementation marked it as changed. >>> o._p_changed 1 >>> o.y Traceback (most recent call last): ... AttributeError: y >>> o.tmp_z 3 Now, if commit: >>> transaction.commit() >>> o._p_changed 0 And deactivate the object: >>> o._p_deactivate() >>> o._p_changed and then delete a variable with a name starting with 'tmp_', The object will be activated, but not marked as modified, because our __delattr__ implementation doesn't mark the object as changed if the name starts with 'tmp_': >>> del o.tmp_z >>> o._p_changed 0 >>> o.tmp_z Traceback (most recent call last): ... AttributeError: tmp_z We always close databases after we use them: >>> db.close() NRRi(Rt _p_delattrRRRRR(RR((R t __delattr__$s V (R R R RRR R"(((R RPs   Z jcCsdkl}|ƒS(N(s DocTestSuite(tzope.testing.doctestt DocTestSuite(R$((R t test_suites ( R t persistentRt transactiontZODB.tests.utiltDBRRR%(R'RR)RRR%((R t?s   6ÿA