]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.9] bpo-42163, bpo-42189, bpo-42659: Support uname_tuple._replace (for all but...
authorJason R. Coombs <jaraco@jaraco.com>
Sat, 16 Jan 2021 19:45:30 +0000 (14:45 -0500)
committerGitHub <noreply@github.com>
Sat, 16 Jan 2021 19:45:30 +0000 (14:45 -0500)
* 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>
Lib/platform.py
Lib/test/test_platform.py
Misc/NEWS.d/next/Library/2020-10-29-09-22-56.bpo-42163.O4VcCY.rst [new file with mode: 0644]

index e9f50ab622d3169d1c46e04d4c27f1ae275f4c33..6258827d0e41f80cd7096f65598734a0b7dd1574 100755 (executable)
@@ -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
 
index a3b06feb6552ec6b87804dafb6b6236b88ce18d6..9f04c79e09ba462fc36136470f4819f501bfb2bc 100644 (file)
@@ -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 (file)
index 0000000..0c357eb
--- /dev/null
@@ -0,0 +1 @@
+Restore compatibility for ``uname_result`` around deepcopy and _replace.