aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2021-01-16 14:45:30 -0500
committerGitHub <noreply@github.com>2021-01-16 14:45:30 -0500
commit799722cb0ddb90752cde7798cab543f30623ebf2 (patch)
tree1a2b77e6a085b87be3cc8ebda21f9bdd90c41d35
parentbpo-42931: randbytes missing from random.__all__ (GH-24219) (GH-24225) (diff)
downloadcpython-799722cb0ddb90752cde7798cab543f30623ebf2.tar.gz
cpython-799722cb0ddb90752cde7798cab543f30623ebf2.tar.bz2
cpython-799722cb0ddb90752cde7798cab543f30623ebf2.zip
[3.9] bpo-42163, bpo-42189, bpo-42659: Support uname_tuple._replace (for all but processor) (GH-23010) (#24232)
* Add test capturing missed expectation with uname_result._replace. * bpo-42163: Override uname_result._make to allow uname_result._replace to work (for everything but 'processor'. * Replace hard-coded length with one derived from the definition. * Add test capturing missed expectation with copy/deepcopy on namedtuple (bpo-42189). * bpo-42189: Exclude processor parameter when constructing uname_result. * In _make, rely on __new__ to strip processor. * Add blurb. * iter is not necessary here. * Rely on num_fields in __new__ * Add test for slices on uname * Add test for copy and pickle. Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> * import pickle * Fix equality test after pickling. * Simply rely on __reduce__ for pickling. Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> (cherry picked from commit a6fd0f414c0cb4cd5cc20eb2df3340b31c6f7743) Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>
-rwxr-xr-xLib/platform.py17
-rw-r--r--Lib/test/test_platform.py34
-rw-r--r--Misc/NEWS.d/next/Library/2020-10-29-09-22-56.bpo-42163.O4VcCY.rst1
3 files changed, 50 insertions, 2 deletions
diff --git a/Lib/platform.py b/Lib/platform.py
index e9f50ab622d..6258827d0e4 100755
--- a/Lib/platform.py
+++ b/Lib/platform.py
@@ -782,7 +782,7 @@ class uname_result(
):
"""
A uname_result that's largely compatible with a
- simple namedtuple except that 'platform' is
+ simple namedtuple except that 'processor' is
resolved late and cached to avoid calling "uname"
except when needed.
"""
@@ -797,12 +797,25 @@ class uname_result(
(self.processor,)
)
+ @classmethod
+ def _make(cls, iterable):
+ # override factory to affect length check
+ num_fields = len(cls._fields)
+ result = cls.__new__(cls, *iterable)
+ if len(result) != num_fields + 1:
+ msg = f'Expected {num_fields} arguments, got {len(result)}'
+ raise TypeError(msg)
+ return result
+
def __getitem__(self, key):
- return tuple(iter(self))[key]
+ return tuple(self)[key]
def __len__(self):
return len(tuple(iter(self)))
+ def __reduce__(self):
+ return uname_result, tuple(self)[:len(self._fields)]
+
_uname_cache = None
diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py
index a3b06feb655..9f04c79e09b 100644
--- a/Lib/test/test_platform.py
+++ b/Lib/test/test_platform.py
@@ -1,4 +1,6 @@
import os
+import copy
+import pickle
import platform
import subprocess
import sys
@@ -175,6 +177,38 @@ class PlatformTest(unittest.TestCase):
)
self.assertEqual(tuple(res), expected)
+ def test_uname_replace(self):
+ res = platform.uname()
+ new = res._replace(
+ system='system', node='node', release='release',
+ version='version', machine='machine')
+ self.assertEqual(new.system, 'system')
+ self.assertEqual(new.node, 'node')
+ self.assertEqual(new.release, 'release')
+ self.assertEqual(new.version, 'version')
+ self.assertEqual(new.machine, 'machine')
+ # processor cannot be replaced
+ self.assertEqual(new.processor, res.processor)
+
+ def test_uname_copy(self):
+ uname = platform.uname()
+ self.assertEqual(copy.copy(uname), uname)
+ self.assertEqual(copy.deepcopy(uname), uname)
+
+ def test_uname_pickle(self):
+ orig = platform.uname()
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(protocol=proto):
+ pickled = pickle.dumps(orig, proto)
+ restored = pickle.loads(pickled)
+ self.assertEqual(restored, orig)
+
+ def test_uname_slices(self):
+ res = platform.uname()
+ expected = tuple(res)
+ self.assertEqual(res[:], expected)
+ self.assertEqual(res[:5], expected[:5])
+
@unittest.skipIf(sys.platform in ['win32', 'OpenVMS'], "uname -p not used")
def test_uname_processor(self):
"""
diff --git a/Misc/NEWS.d/next/Library/2020-10-29-09-22-56.bpo-42163.O4VcCY.rst b/Misc/NEWS.d/next/Library/2020-10-29-09-22-56.bpo-42163.O4VcCY.rst
new file mode 100644
index 00000000000..0c357eb4ac1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-10-29-09-22-56.bpo-42163.O4VcCY.rst
@@ -0,0 +1 @@
+Restore compatibility for ``uname_result`` around deepcopy and _replace.