[Python-3000] Confused about getattr() and special methods

Thomas Heller theller at ctypes.org
Tue Sep 4 11:34:46 CEST 2007


I was looking into the Lib\test\test_uuid on Windows, which fails with this traceback:

test test_uuid failed -- Traceback (most recent call last):
  File "C:\buildbot\work\3.0.heller-windows\build\lib\test\test_uuid.py", line 323, in test_ipconfig_getnode
    node = uuid._ipconfig_getnode()
  File "C:\buildbot\work\3.0.heller-windows\build\lib\uuid.py", line 376, in _ipconfig_getnode
    for line in pipe:
TypeError: '_wrap_close' object is not iterable

The test can be fixed with this little patch:

Index: Lib/os.py
===================================================================
--- Lib/os.py	(revision 57827)
+++ Lib/os.py	(working copy)
@@ -664,6 +664,8 @@
         return self._proc.wait() << 8  # Shift left to match old behavior
     def __getattr__(self, name):
         return getattr(self._stream, name)
+    def __iter__(self):
+        return iter(self._stream)
 
 # Supply os.fdopen() (used by subprocess!)
 def fdopen(fd, mode="r", buffering=-1):

However, looking further into this I'm getting confused.
Shouldn't the __getattr__ implementation find the __iter__ method
of the _stream instance variable?

Consider this code:

<code>
##__metaclass__ = type

class X:
    def __str__(self):
        return "foo"
    def __len__(self):
        return 42
    def __iter__(self):
        return iter([1, 2, 3])

class proxy:
    def __init__(self):
        self.x = X()
    def __getattr__(self, name):
        return getattr(self.x, name)

p = proxy()

print(len(p))
print(str(p))
print(iter(p))

<code/>

In Python2.5 and trunk, all the calls len(p), str(p), and iter(p) return the attributes
of the X class instance.  Uncommenting the '__metaclass__ = type' line makes the code fail.

IIUC, in py3k, classic classes do not exist any longer, so the __metaclass__ line
has no effect anyway.  Is this behaviour intended?

Thomas



More information about the Python-3000 mailing list