From 9f3fc6c5b4993f2b362263b494f84793a21aa073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20Natan=20Gunnarsson?= <1493259+GudniNatan@users.noreply.github.com> Date: Sun, 12 Jan 2020 17:41:49 +0000 Subject: [PATCH] bpo-38293: Allow shallow and deep copying of property objects (GH-16438) Copying property objects results in a TypeError. Steps to reproduce: ``` >>> import copy >>> obj = property() >>> copy.copy(obj) ```` This affects both shallow and deep copying. My idea for a fix is to add property objects to the list of "atomic" objects in the copy module. These already include types like functions and type objects. I also added property objects to the unit tests test_copy_atomic and test_deepcopy_atomic. This is my first PR, and it's highly likely I've made some mistake, so please be kind :) https://bugs.python.org/issue38293 --- Lib/copy.py | 3 ++- Lib/test/test_copy.py | 4 ++-- .../next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst diff --git a/Lib/copy.py b/Lib/copy.py index f53cd8c5874..41873f2c046 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -107,7 +107,7 @@ _copy_dispatch = d = {} def _copy_immutable(x): return x for t in (type(None), int, float, bool, complex, str, tuple, - bytes, frozenset, type, range, slice, + bytes, frozenset, type, range, slice, property, types.BuiltinFunctionType, type(Ellipsis), type(NotImplemented), types.FunctionType, weakref.ref): d[t] = _copy_immutable @@ -195,6 +195,7 @@ d[type] = _deepcopy_atomic d[types.BuiltinFunctionType] = _deepcopy_atomic d[types.FunctionType] = _deepcopy_atomic d[weakref.ref] = _deepcopy_atomic +d[property] = _deepcopy_atomic def _deepcopy_list(x, memo, deepcopy=deepcopy): y = [] diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index 45a692022f2..35f72fb216b 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -99,7 +99,7 @@ class TestCopy(unittest.TestCase): 42, 2**100, 3.14, True, False, 1j, "hello", "hello\u1234", f.__code__, b"world", bytes(range(256)), range(10), slice(1, 10, 2), - NewStyle, Classic, max, WithMetaclass] + NewStyle, Classic, max, WithMetaclass, property()] for x in tests: self.assertIs(copy.copy(x), x) @@ -357,7 +357,7 @@ class TestCopy(unittest.TestCase): pass tests = [None, 42, 2**100, 3.14, True, False, 1j, "hello", "hello\u1234", f.__code__, - NewStyle, Classic, max] + NewStyle, Classic, max, property()] for x in tests: self.assertIs(copy.deepcopy(x), x) diff --git a/Misc/NEWS.d/next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst b/Misc/NEWS.d/next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst new file mode 100644 index 00000000000..0b19551970e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst @@ -0,0 +1 @@ +Add :func:`copy.copy` and :func:`copy.deepcopy` support to :func:`property` objects. \ No newline at end of file