bpo-42163, bpo-42189, bpo-42659: Support uname_tuple._replace (for all but processor) (#23010)
* 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>
This commit is contained in:
parent
dfdca85dfa
commit
a6fd0f414c
|
@ -769,7 +769,7 @@ class uname_result(
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
A uname_result that's largely compatible with a
|
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"
|
resolved late and cached to avoid calling "uname"
|
||||||
except when needed.
|
except when needed.
|
||||||
"""
|
"""
|
||||||
|
@ -784,12 +784,25 @@ class uname_result(
|
||||||
(self.processor,)
|
(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):
|
def __getitem__(self, key):
|
||||||
return tuple(iter(self))[key]
|
return tuple(self)[key]
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(tuple(iter(self)))
|
return len(tuple(iter(self)))
|
||||||
|
|
||||||
|
def __reduce__(self):
|
||||||
|
return uname_result, tuple(self)[:len(self._fields)]
|
||||||
|
|
||||||
|
|
||||||
_uname_cache = None
|
_uname_cache = None
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import os
|
import os
|
||||||
|
import copy
|
||||||
|
import pickle
|
||||||
import platform
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
@ -234,6 +236,38 @@ class PlatformTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(tuple(res), expected)
|
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")
|
@unittest.skipIf(sys.platform in ['win32', 'OpenVMS'], "uname -p not used")
|
||||||
def test_uname_processor(self):
|
def test_uname_processor(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Restore compatibility for ``uname_result`` around deepcopy and _replace.
|
Loading…
Reference in New Issue