Re: setattr() oddness
Dieter Maurer wrote: Steven D'Aprano ste...@remove.this.cybersource.com.au writes on 18 Jan 2010 06:47:59 GMT: On Mon, 18 Jan 2010 07:25:58 +0100, Dieter Maurer wrote: Lie Ryan lie.1...@gmail.com writes on Sat, 16 Jan 2010 19:37:29 +1100: On 01/16/10 10:10, Sean DiZazzo wrote: Interesting. I can understand the would take time argument, but I don't see any legitimate use case for an attribute only accessible via getattr(). Well, at least not a pythonic use case. mostly for people (ab)using attributes instead of dictionary. Here is one use case: A query application. Queries are described by complex query objects. For efficiency reasons, query results should be cached. For this, it is not unnatural to use query objects as cache keys. Then, query objects must not get changed in an uncontrolled way. I use __setattr__ to control access to the objects. (1) Wouldn't it be more natural to store these query keys in a list or dictionary rather than as attributes on an object? e.g. instead of: cache.__setattr__('complex query object', value) use: cache['complex query object'] = value Few will use cache.__setattr__(...) but cache.attr = ... which is nicer than cache['attr'] = Moreover, it is not the cache but the query of which I want to protect modification. My cache indeed uses cache[query_object] = But I want to prevent query_object from being changed after a potential caching. You might want to look at mxProxy which provides object-level access control: http://www.egenix.com/products/python/mxBase/mxProxy/ See the Access Protocol in the documentation: http://www.egenix.com/products/python/mxBase/mxProxy/doc/#_Toc162774446 (2) How does __setattr__ let you control access to the object? If a user wants to modify the cache, and they know the complex query object, what's stopping them from using __setattr__ too? In my specific case, __setattr__ prevents all modifications via attribute assignment. The class uses __dict__ access to set attributes when it knows it is still safe. Of course, this is no real protection against attackers (which could use __dict__ as well). It only protects against accidental change of query objects. Meanwhile, I remembered a more important use case for __setattr__: providing for transparent persistancy. The ZODB (Zope Object DataBase) customizes __setattr__ in order to intercept object modifications and register automatically that the change needs to be persisted at the next transaction commit. -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Jan 20 2010) Python/Zope Consulting and Support ...http://www.egenix.com/ mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ mxODBC, mxDateTime, mxTextTools ...http://python.egenix.com/ ::: Try our new mxODBC.Connect Python Database Interface for free ! eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/ -- http://mail.python.org/mailman/listinfo/python-list
Re: setattr() oddness
Steven D'Aprano ste...@remove.this.cybersource.com.au writes on 18 Jan 2010 06:47:59 GMT: On Mon, 18 Jan 2010 07:25:58 +0100, Dieter Maurer wrote: Lie Ryan lie.1...@gmail.com writes on Sat, 16 Jan 2010 19:37:29 +1100: On 01/16/10 10:10, Sean DiZazzo wrote: Interesting. I can understand the would take time argument, but I don't see any legitimate use case for an attribute only accessible via getattr(). Well, at least not a pythonic use case. mostly for people (ab)using attributes instead of dictionary. Here is one use case: A query application. Queries are described by complex query objects. For efficiency reasons, query results should be cached. For this, it is not unnatural to use query objects as cache keys. Then, query objects must not get changed in an uncontrolled way. I use __setattr__ to control access to the objects. (1) Wouldn't it be more natural to store these query keys in a list or dictionary rather than as attributes on an object? e.g. instead of: cache.__setattr__('complex query object', value) use: cache['complex query object'] = value Few will use cache.__setattr__(...) but cache.attr = ... which is nicer than cache['attr'] = Moreover, it is not the cache but the query of which I want to protect modification. My cache indeed uses cache[query_object] = But I want to prevent query_object from being changed after a potential caching. (2) How does __setattr__ let you control access to the object? If a user wants to modify the cache, and they know the complex query object, what's stopping them from using __setattr__ too? In my specific case, __setattr__ prevents all modifications via attribute assignment. The class uses __dict__ access to set attributes when it knows it is still safe. Of course, this is no real protection against attackers (which could use __dict__ as well). It only protects against accidental change of query objects. Meanwhile, I remembered a more important use case for __setattr__: providing for transparent persistancy. The ZODB (Zope Object DataBase) customizes __setattr__ in order to intercept object modifications and register automatically that the change needs to be persisted at the next transaction commit. Dieter -- http://mail.python.org/mailman/listinfo/python-list
Re: setattr() oddness
Lie Ryan lie.1...@gmail.com writes on Sat, 16 Jan 2010 19:37:29 +1100: On 01/16/10 10:10, Sean DiZazzo wrote: Interesting. I can understand the would take time argument, but I don't see any legitimate use case for an attribute only accessible via getattr(). Well, at least not a pythonic use case. mostly for people (ab)using attributes instead of dictionary. Here is one use case: A query application. Queries are described by complex query objects. For efficiency reasons, query results should be cached. For this, it is not unnatural to use query objects as cache keys. Then, query objects must not get changed in an uncontrolled way. I use __setattr__ to control access to the objects. Dieter -- http://mail.python.org/mailman/listinfo/python-list
Re: setattr() oddness
On Mon, 18 Jan 2010 07:25:58 +0100, Dieter Maurer wrote: Lie Ryan lie.1...@gmail.com writes on Sat, 16 Jan 2010 19:37:29 +1100: On 01/16/10 10:10, Sean DiZazzo wrote: Interesting. I can understand the would take time argument, but I don't see any legitimate use case for an attribute only accessible via getattr(). Well, at least not a pythonic use case. mostly for people (ab)using attributes instead of dictionary. Here is one use case: A query application. Queries are described by complex query objects. For efficiency reasons, query results should be cached. For this, it is not unnatural to use query objects as cache keys. Then, query objects must not get changed in an uncontrolled way. I use __setattr__ to control access to the objects. (1) Wouldn't it be more natural to store these query keys in a list or dictionary rather than as attributes on an object? e.g. instead of: cache.__setattr__('complex query object', value) use: cache['complex query object'] = value (2) How does __setattr__ let you control access to the object? If a user wants to modify the cache, and they know the complex query object, what's stopping them from using __setattr__ too? -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: setattr() oddness
On 01/16/10 10:10, Sean DiZazzo wrote: Interesting. I can understand the would take time argument, but I don't see any legitimate use case for an attribute only accessible via getattr(). Well, at least not a pythonic use case. mostly for people (ab)using attributes instead of dictionary. -- http://mail.python.org/mailman/listinfo/python-list
Re: setattr() oddness
On 1/15/2010 3:37 PM, Sean DiZazzo wrote: Should the following be legal? class TEST(object): pass ... t = TEST() setattr(t, , 123) getattr(t, ) '123' Different people have different opinions as to whether setattr (and correspondingly getattr) should be strict or permissive as to whether or not the 'name' string is a legal name. CPython is permissive. The rationale is that checking would take time and prevent possible legitimate use cases. CPython is actually looser than this. Try t.__dict__[1] = 2 Now there is an 'attribute' whose 'name' is an int! -- and which can only be accessed via the same trick of delving into the internals. This is, however, implementation behavior that would go away if an implementation used string-key-only dicts to store attributes. Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: setattr() oddness
Terry Reedy wrote: On 1/15/2010 3:37 PM, Sean DiZazzo wrote: Should the following be legal? class TEST(object): pass ... t = TEST() setattr(t, , 123) getattr(t, ) '123' Different people have different opinions as to whether setattr (and correspondingly getattr) should be strict or permissive as to whether or not the 'name' string is a legal name. CPython is permissive. The rationale is that checking would take time and prevent possible legitimate use cases. CPython is actually looser than this. Try t.__dict__[1] = 2 Now there is an 'attribute' whose 'name' is an int! -- and which can only be accessed via the same trick of delving into the internals. This is, however, implementation behavior that would go away if an implementation used string-key-only dicts to store attributes. Good question, great answer! regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/ Holden Web LLC http://www.holdenweb.com/ UPCOMING EVENTS:http://holdenweb.eventbrite.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: setattr() oddness
On Jan 15, 2:22 pm, Terry Reedy tjre...@udel.edu wrote: On 1/15/2010 3:37 PM, Sean DiZazzo wrote: Should the following be legal? class TEST(object): pass ... t = TEST() setattr(t, , 123) getattr(t, ) '123' Different people have different opinions as to whether setattr (and correspondingly getattr) should be strict or permissive as to whether or not the 'name' string is a legal name. CPython is permissive. The rationale is that checking would take time and prevent possible legitimate use cases. CPython is actually looser than this. Try t.__dict__[1] = 2 Now there is an 'attribute' whose 'name' is an int! -- and which can only be accessed via the same trick of delving into the internals. This is, however, implementation behavior that would go away if an implementation used string-key-only dicts to store attributes. Terry Jan Reedy Interesting. I can understand the would take time argument, but I don't see any legitimate use case for an attribute only accessible via getattr(). Well, at least not a pythonic use case. Thanks for the info! ~Sean -- http://mail.python.org/mailman/listinfo/python-list
Re: setattr() oddness
On 1/15/2010 6:10 PM, Sean DiZazzo wrote: On Jan 15, 2:22 pm, Terry Reedytjre...@udel.edu wrote: On 1/15/2010 3:37 PM, Sean DiZazzo wrote: Should the following be legal? class TEST(object): pass ... t = TEST() setattr(t, , 123) getattr(t, ) '123' Different people have different opinions as to whether setattr (and correspondingly getattr) should be strict or permissive as to whether or not the 'name' string is a legal name. CPython is permissive. The rationale is that checking would take time and prevent possible legitimate use cases. CPython is actually looser than this. Try t.__dict__[1] = 2 Now there is an 'attribute' whose 'name' is an int! -- and which can only be accessed via the same trick of delving into the internals. This is, however, implementation behavior that would go away if an implementation used string-key-only dicts to store attributes. Terry Jan Reedy Interesting. I can understand the would take time argument, but I don't see any legitimate use case for an attribute only accessible via getattr(). Well, at least not a pythonic use case. That was my first thought, but one thing I thought of would be a proxy object for remote objects coded in a language with different name rules, or any situation where 'names' and values come over the wire to be stored and later retrieved, so that all 'foreign' attribute access was done with set/get/del/attr. I expect that creative Python programmers have found other uses too. Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list