◐ Shell
clean mode source ↗

Issue 19364: Implementing __getattr__ breaks copy and deepcopy

Issue19364

Created on 2013-10-23 13:49 by Kassym.Dorsel, last changed 2022-04-11 14:57 by admin. 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
2022-04-11 14:57:52adminsetgithub: 63563
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