[New-bugs-announce] [issue9732] Addition of getattr_static for inspect module

Michael Foord report at bugs.python.org
Wed Sep 1 15:21:10 CEST 2010


New submission from Michael Foord <michael at voidspace.org.uk>:

As discussed on python-dev, a version of getattr that does static lookups - bypassing the descriptor protocol, __getattr__, and __getattribute__. Initial implementation by Nick Coghlan, amended and tests added by me.

Phillip Eby objects to this code existing at all as it doesn't play well with proxy objects.

The purpose of getattr_static is for "passive introspection" without triggering code execution (as hasattr and getattr both do). Use cases include debugging and fetching docstrings from objects.

Caveats with the current implementation are:

Cases that will break `getattr_static`, all pathological enough not
to worry about (i.e. if you do any of these then you deserve to
have everything break anyway):

* `__dict__` existing (e.g. as a property) but not returning a
  dictionary
* classes created with `__slots__` that then have the `__slots__`
  member deleted from the class (or otherwise monkeyed with)

Cases handled incorrectly:

1. where a descriptor with a `__set__` method is shadowed by an
   instance member we return the instance member in preference to
   the descriptor, unlike `getattr`
2. types implemented in C may have neither `__dict__` nor `__slots__`,
   in this case we will be unable to find instance members and return
   the attribute descriptor instead
3. classes that inherit from a class with `__slots__` (whether or not
   they use `__slots__` themselves) will return the slot descriptor
   for instance members 'owned' by a slot on a base class
4. objects that lie about being a type by having __class__ as a
   descriptor (we traverse the mro of whatever type `obj.__class__`
   returns instead of the real type)

1 could be fixed but the code would be annoying. Is it worth fixing?

2 could be detected and where fetching an attribute from an instance
fails but an attribute descriptor is found on the type we could try
it's __get__ method. Worth it?

3 could be detected if we find a slot descriptor on a type trying
its __get__ method. Worth it?

4 could be fixed by using type everywhere instead of __class__.
We also can't use isinstance that uses __class__. If an object
is lying about __class__ then it obviously *intends* us to look
at the 'faked' version. However, this breaks the 'no code
execution' purpose of getattr_static and is inconsistent with
the rest of our behaviour. Worth fixing?

Fixing *all* of these (or any) will significantly complicate the
implimentation. 

Fetching an uninitialized instance member from an instance of a class
with __slots__ returns the slot descriptor rather than raising an
AttributeError as the descriptor does. As the slot descriptor is
a Python implementation detail perhaps we are better off propagating
the exception here. (?) On the other hand, the descriptor is
available on the class and the job of this function is to fetch
members when they are available...

I'm not aware of any other caveats / potential pitfalls. Please
point them out to me. :-)Cases that will break `getattr_static`, all pathological enough not
to worry about (i.e. if you do any of these then you deserve to
have everything break anyway):

* `__dict__` existing (e.g. as a property) but not returning a
  dictionary
* classes created with `__slots__` that then have the `__slots__`
  member deleted from the class (or otherwise monkeyed with)

Cases handled incorrectly:

1. where a descriptor with a `__set__` method is shadowed by an
   instance member we return the instance member in preference to
   the descriptor, unlike `getattr`
2. types implemented in C may have neither `__dict__` nor `__slots__`,
   in this case we will be unable to find instance members and return
   the attribute descriptor instead
3. classes that inherit from a class with `__slots__` (whether or not
   they use `__slots__` themselves) will return the slot descriptor
   for instance members 'owned' by a slot on a base class
4. objects that lie about being a type by having __class__ as a
   descriptor (we traverse the mro of whatever type `obj.__class__`
   returns instead of the real type)

1 could be fixed but the code would be annoying. Is it worth fixing?

2 could be detected and where fetching an attribute from an instance
fails but an attribute descriptor is found on the type we could try
it's __get__ method. Worth it?

3 could be detected if we find a slot descriptor on a type trying
its __get__ method. Worth it?

4 could be fixed by using type everywhere instead of __class__.
We also can't use isinstance that uses __class__. If an object
is lying about __class__ then it obviously *intends* us to look
at the 'faked' version. However, this breaks the 'no code
execution' purpose of getattr_static and is inconsistent with
the rest of our behaviour. Worth fixing?

Fixing *all* of these (or any) will significantly complicate the
implimentation. 

Fetching an uninitialized instance member from an instance of a class
with __slots__ returns the slot descriptor rather than raising an
AttributeError as the descriptor does. As the slot descriptor is
a Python implementation detail perhaps we are better off propagating
the exception here. (?) On the other hand, the descriptor is
available on the class and the job of this function is to fetch
members when they are available...

I'm not aware of any other caveats / potential pitfalls. Please
point them out to me. :-)

----------
assignee: michael.foord
components: Library (Lib)
files: static.py
keywords: needs review
messages: 115296
nosy: benjamin.peterson, michael.foord, ncoghlan
priority: normal
severity: normal
status: open
title: Addition of getattr_static for inspect module
versions: Python 3.2
Added file: http://bugs.python.org/file18699/static.py

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue9732>
_______________________________________


More information about the New-bugs-announce mailing list