Exception for setting attributes of built-in type
Exception for setting attributes of built-in type differs between CPython and IronPython. This is not purely theoretical, as zope.interface tries to set Implements declaration as __implemented__ attribute of built-in type object, and excepts TypeError. Python 2.6.1
object.flag = True TypeError: can't set attributes of built-in/extension type 'object'
IronPython 2.6
object.flag = True AttributeError: 'object' object has no attribute 'flag'
I was surprised that CPython raises TypeError. Library Reference seems to mention it here: exception AttributeError Raised when an attribute reference or assignment fails. (When an object does not support attribute references or attribute assignments at all, TypeError is raised.) http://docs.python.org/library/exceptions.html What does it mean that "an object does not support attribute references or attribute assignments at all"? -- Seo Sanghyeon
Seo Sanghyeon wrote:
Exception for setting attributes of built-in type differs between CPython and IronPython. This is not purely theoretical, as zope.interface tries to set Implements declaration as __implemented__ attribute of built-in type object, and excepts TypeError.
Python 2.6.1
object.flag = True TypeError: can't set attributes of built-in/extension type 'object'
IronPython 2.6
object.flag = True AttributeError: 'object' object has no attribute 'flag'
I was surprised that CPython raises TypeError. Library Reference seems to mention it here:
exception AttributeError Raised when an attribute reference or assignment fails. (When an object does not support attribute references or attribute assignments at all, TypeError is raised.) http://docs.python.org/library/exceptions.html
What does it mean that "an object does not support attribute references or attribute assignments at all"?
I see it as slightly ambiguous: 1. It neither supports references nor assignments. 2. It either does not support reference or it does not support assignments. 1 could hardly apply any more, certainly to built-ins since everything now has attributes. 2 covers object, so if that is meant, then TypeError is appropriate. Or were you unclear about 'at all', which means 'never'? Terry Jan Reedy
Seo Sanghyeon wrote:
Exception for setting attributes of built-in type differs between CPython and IronPython. This is not purely theoretical, as zope.interface tries to set Implements declaration as __implemented__ attribute of built-in type object, and excepts TypeError.
Python 2.6.1
object.flag = True TypeError: can't set attributes of built-in/extension type 'object'
IronPython 2.6
object.flag = True AttributeError: 'object' object has no attribute 'flag'
I was surprised that CPython raises TypeError. Library Reference seems to mention it here:
exception AttributeError Raised when an attribute reference or assignment fails. (When an object does not support attribute references or attribute assignments at all, TypeError is raised.) http://docs.python.org/library/exceptions.html
What does it mean that "an object does not support attribute references or attribute assignments at all"?
Here's my guess: Some objects have a fixed (and possibly empty) set of attributes. Attempting to add a new attribute or get a non-existent attribute raises an AttributeError. Other objects, such as types (are there any that aren't types?), don't have attributes at all. Attempting to add or get an attribute raises a TypeError.
On Sun, Jun 14, 2009 at 3:42 PM, MRAB<python@mrabarnett.plus.com> wrote:
Seo Sanghyeon wrote:
Exception for setting attributes of built-in type differs between CPython and IronPython. This is not purely theoretical, as zope.interface tries to set Implements declaration as __implemented__ attribute of built-in type object, and excepts TypeError.
Python 2.6.1
object.flag = True
TypeError: can't set attributes of built-in/extension type 'object'
IronPython 2.6
object.flag = True
AttributeError: 'object' object has no attribute 'flag'
I was surprised that CPython raises TypeError. Library Reference seems to mention it here:
exception AttributeError Raised when an attribute reference or assignment fails. (When an object does not support attribute references or attribute assignments at all, TypeError is raised.) http://docs.python.org/library/exceptions.html
What does it mean that "an object does not support attribute references or attribute assignments at all"?
Here's my guess:
Some objects have a fixed (and possibly empty) set of attributes. Attempting to add a new attribute or get a non-existent attribute raises an AttributeError.
Other objects, such as types (are there any that aren't types?), don't have attributes at all. Attempting to add or get an attribute raises a TypeError.
This particular error comes (grep tells me :-) from type_setattro() in Objects/typeobject.c. It makes a specific check whether the type object whose attribute you want to set is a "built-in type" (this is done by checking the HEAPTYPE flag, which is never set for built-in types and always for user-defined types). For built-in types it disallows setting attributes. This is a pure policy issue: it prevents different 3rd party modules to make incompatible modifications of built-in types. In general, CPython isn't always consistent in raising AttributeError and TypeError when it comes to such policy issues: there are various places that raise TypeError in typeobject.c (and probably elsewhere) that simply forbid setting a specific attribute (another example is __name__). Given how poorly Python exceptions are specified in general, I don't want to hold IronPython to this standard (nor CPython :-). The reason this breaks zope.interfaces in IronPython is probably just that zope.interfaces was primarily written/tested against CPython. Going back to the phrase quoted from the reference manual, it's probably referring to the possibility that a type's tp_getattro slot is NULL; but even so it's wrong: PyObject_GetAttr() raises AttributeError in this case. Uselessly y'rs, -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
In general, CPython isn't always consistent in raising AttributeError and TypeError when it comes to such policy issues: there are various places that raise TypeError in typeobject.c (and probably elsewhere) that simply forbid setting a specific attribute (another example is __name__).
We're pretty inconsistent when it comes to looking up special methods as well - those that are looked up through dedicated slots in abstract.c usually raise TypeError, while those that are looked up via a PyType method usually raise AttributeError. I'm not sure that there is any practical way to handle that other than for applications that care about cross-implementation compatibility in this area to catch a (TypeError, AttributeError) tuple rather than one or the other. CHeers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
2009/6/15 Nick Coghlan <ncoghlan@gmail.com>:
Guido van Rossum wrote:
In general, CPython isn't always consistent in raising AttributeError and TypeError when it comes to such policy issues: there are various places that raise TypeError in typeobject.c (and probably elsewhere) that simply forbid setting a specific attribute (another example is __name__).
We're pretty inconsistent when it comes to looking up special methods as well - those that are looked up through dedicated slots in abstract.c usually raise TypeError, while those that are looked up via a PyType method usually raise AttributeError.
What's a PyType method? -- Regards, Benjamin
Benjamin Peterson wrote:
2009/6/15 Nick Coghlan <ncoghlan@gmail.com>:
Guido van Rossum wrote:
In general, CPython isn't always consistent in raising AttributeError and TypeError when it comes to such policy issues: there are various places that raise TypeError in typeobject.c (and probably elsewhere) that simply forbid setting a specific attribute (another example is __name__). We're pretty inconsistent when it comes to looking up special methods as well - those that are looked up through dedicated slots in abstract.c usually raise TypeError, while those that are looked up via a PyType method usually raise AttributeError.
What's a PyType method?
I was misremembering - for some reason I thought: a) _PyObject_LookupSpecial was a PyType method b) That it raised AttributeError itself instead of letting the caller decide what error to raise It's still the case that (e.g.) special_lookup() in ceval.c raises an AttributeError, as do special method lookups from Python of the form "type(obj).__method__(obj)". Whether CPython raises TypeError or AttributeError when it comes to special methods is really pretty arbitrary rather than a matter of any grand design. Cheers, Nick. P.S. If anyone feels like digging into the archives, the last time I can recall this topic coming up is when I was concerned about the original with statement implementation raising AttributeError rather than TypeError when it couldn't find an __enter__ or __exit__ method. Guido chimed in then (as now) to say that either exception was fine. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
On Sun, Jun 14, 2009 at 4:19 PM, Guido van Rossum<guido@python.org> wrote:
In general, CPython isn't always consistent in raising AttributeError and TypeError when it comes to such policy issues: there are various places that raise TypeError in typeobject.c (and probably elsewhere) that simply forbid setting a specific attribute (another example is __name__).
I should add that this policy is also forced somewhat by the existence of the "multiple interpreters in one address space" feature, which is used e.g. by mod_python. This feature attempts to provide isolation between interpreters to the point that each one can have a completely different set of modules loaded and can be working on a totally different application. The implementation of CPython shares built-in types between multiple interpreters (and it wouldn't be easy to change this); if you were able to modify a built-in type from one interpreter, all other interpreters would see that same modification. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido wrote:
I should add that this policy is also forced somewhat by the existence of the "multiple interpreters in one address space" feature, which is used e.g. by mod_python. This feature attempts to provide isolation between interpreters to the point that each one can have a completely different set of modules loaded and can be working on a totally different application. The implementation of CPython shares built-in types between multiple interpreters (and it wouldn't be easy to change this); if you were able to modify a built-in type from one interpreter, all other interpreters would see that same modification.
IronPython is in the exact same boat here - we share built-in types Across multiple Python engines as well.
Dino Viehland wrote:
Guido wrote:
I should add that this policy is also forced somewhat by the existence of the "multiple interpreters in one address space" feature, which is used e.g. by mod_python. This feature attempts to provide isolation between interpreters to the point that each one can have a completely different set of modules loaded and can be working on a totally different application. The implementation of CPython shares built-in types between multiple interpreters (and it wouldn't be easy to change this); if you were able to modify a built-in type from one interpreter, all other interpreters would see that same modification.
IronPython is in the exact same boat here - we share built-in types Across multiple Python engines as well.
And indeed it is needed - if you are working with multiple interpreters (engines in IronPython) you don't want isinstance(something, dict) to fail because it is a dictionary from a different interpreter... Michael
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.u...
-- http://www.ironpythoninaction.com/ http://www.voidspace.org.uk/blog
On Mon, Jun 15, 2009 at 9:10 AM, Michael Foord<fuzzyman@voidspace.org.uk> wrote:
Dino Viehland wrote:
Guido wrote:
I should add that this policy is also forced somewhat by the existence of the "multiple interpreters in one address space" feature, which is used e.g. by mod_python. This feature attempts to provide isolation between interpreters to the point that each one can have a completely different set of modules loaded and can be working on a totally different application. The implementation of CPython shares built-in types between multiple interpreters (and it wouldn't be easy to change this); if you were able to modify a built-in type from one interpreter, all other interpreters would see that same modification.
IronPython is in the exact same boat here - we share built-in types Across multiple Python engines as well.
And indeed it is needed - if you are working with multiple interpreters (engines in IronPython) you don't want isinstance(something, dict) to fail because it is a dictionary from a different interpreter...
Ah, but that suggests you have sharing between different interpreters. If you're doing that, perhaps you shouldn't be using multiple interpreters, but instead multiple threads? -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
On Mon, Jun 15, 2009 at 9:10 AM, Michael Foord<fuzzyman@voidspace.org.uk> wrote:
Dino Viehland wrote:
Guido wrote:
I should add that this policy is also forced somewhat by the existence of the "multiple interpreters in one address space" feature, which is used e.g. by mod_python. This feature attempts to provide isolation between interpreters to the point that each one can have a completely different set of modules loaded and can be working on a totally different application. The implementation of CPython shares built-in types between multiple interpreters (and it wouldn't be easy to change this); if you were able to modify a built-in type from one interpreter, all other interpreters would see that same modification.
IronPython is in the exact same boat here - we share built-in types Across multiple Python engines as well.
And indeed it is needed - if you are working with multiple interpreters (engines in IronPython) you don't want isinstance(something, dict) to fail because it is a dictionary from a different interpreter...
Ah, but that suggests you have sharing between different interpreters. If you're doing that, perhaps you shouldn't be using multiple interpreters, but instead multiple threads?
Well, in our use case we use multiple engines to provide an isolated execution context for every document (the Resolver One spreadsheet written in IronPython). Each of these has their own calculation thread as well - but the engine per document structure is nice and clean and means each document can have its own set of modules loaded without affecting the other documents (although they share a core set of modules). Once we move these engines into their own app domains we can completely isolate each document and apply separate security permissions to each one. That might mean each document effectively paying the not-insubstantial startup time hit and we haven't begun to look at how to mitigate that. Michael -- http://www.ironpythoninaction.com/ http://www.voidspace.org.uk/blog
Seo wrote:
Exception for setting attributes of built-in type differs between CPython and IronPython. This is not purely theoretical, as zope.interface tries to set Implements declaration as __implemented__ attribute of built-in type object, and excepts TypeError.
Python 2.6.1
object.flag = True TypeError: can't set attributes of built-in/extension type 'object'
IronPython 2.6
object.flag = True AttributeError: 'object' object has no attribute 'flag'
I was surprised that CPython raises TypeError. Library Reference seems to mention it here:
exception AttributeError Raised when an attribute reference or assignment fails. (When an object does not support attribute references or attribute assignments at all, TypeError is raised.) http://docs.python.org/library/exceptions.html
What does it mean that "an object does not support attribute references or attribute assignments at all"?
Even though Guido said we didn't have to match it I've updated IronPython so that we'll throw the same exception now. The change will be in tomorrow's source push to CodePlex. We've matched specific exceptions in the past and this one is at least documented :)
participants (8)
-
Benjamin Peterson -
Dino Viehland -
Guido van Rossum -
Michael Foord -
MRAB -
Nick Coghlan -
Seo Sanghyeon -
Terry Reedy