classification
Title: Implementing __getattr__ breaks copy and deepcopy
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 2.7
process
Status: closed Resolution: duplicate
Dependencies: Superseder: pickle special methods are looked up on the instance rather than the type
View: 16251
Assigned To: Nosy List: Kassym.Dorsel, alexandre.vassalotti, eric.snow
Priority: normal Keywords:

Created on 2013-10-23 13:49 by Kassym.Dorsel, last changed 2013-10-25 02:39 by eric.snow. This issue is now closed.

Messages (4)
msg201024 - (view) Author: Kassym Dorsel (Kassym.Dorsel) Date: 2013-10-23 13:49
When __getattr__ is implemented without also implementing __copy__ and __deepcopy__ trying to (deep)copy the class fails.

>>> import copy
>>> class foo():
...   def __getattr__(self, attr):
...     return None
...
>>> f = foo()
>>> copy(f)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'module' object is not callable

The copy module checks if a class has implemented __copy__ using hasattr:

if hasattr(x, '__copy__'):
  ...

An easy fix would be to use:

if getattr(x, '__copy__', None):
  ...

In Python 3 this change has already been made.
msg201089 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-10-24 04:04
Your example worked correctly, since the copy module is indeed not copiable. :)  Did you mean "from copy import copy"?
msg201200 - (view) Author: Kassym Dorsel (Kassym.Dorsel) Date: 2013-10-25 02:15
Yes. You're correct. Sorry for the confusion. Below is an updated snippet of code.

>>> from copy import copy
>>> class foo():
...   def __getattr__(self, attr):
...     return None
... 
>>> f = foo()
>>> copy(f)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 76, in copy
    return copier(x)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 125, in _copy_inst
    return x.__copy__()
TypeError: 'NoneType' object is not callable
msg201201 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-10-25 02:39
I knew this sounded familiar.  Take a look at issue16251.
History
Date User Action Args
2013-10-25 02:39:12eric.snowsetstatus: open -> closed
superseder: pickle special methods are looked up on the instance rather than the type
messages: + msg201201

resolution: duplicate
stage: resolved
2013-10-25 02:15:30Kassym.Dorselsetmessages: + msg201200
2013-10-24 04:04:59eric.snowsetnosy: + eric.snow
messages: + msg201089
2013-10-23 13:49:43Kassym.Dorselcreate