classification
Title: _replace() no longer works on platform.uname_result objects
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.10, Python 3.9
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: jaraco Nosy List: cs-shadow, jaraco, lemburg, rocallahan
Priority: normal Keywords: patch

Created on 2020-10-26 22:21 by cs-shadow, last changed 2021-01-16 19:46 by jaraco. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 23010 merged jaraco, 2020-10-27 22:38
PR 24232 merged jaraco, 2021-01-16 19:22
Messages (6)
msg379694 - (view) Author: Chandan Singh (cs-shadow) * Date: 2020-10-26 22:21
Starting from Python 3.9, it seems like the `_replace()` method no longer  works on `platform.uname_result` objects, that are returned by
`platform.uname()`. A simple example can be seen below, which works on Python 3.8, but not on Python 3.9.

```
>>> import platform
>>> result = platform.uname()
>>> result._replace(machine="x86_64")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/collections/__init__.py", line 448, in _replace
    result = self._make(_map(kwds.pop, field_names, self))
  File "/usr/local/lib/python3.9/collections/__init__.py", line 441, in _make
    raise TypeError(f'Expected {num_fields} arguments, got {len(result)}')
TypeError: Expected 5 arguments, got 6
```

I'm not sure if this is an intended change or an uninteded side-effect. The `_replace` method does work on simple namedtuple objects, and `uname_result` claims to be:

> largely compatible with a simple namedtumple` object except that 'platform' is resolved late and cached to avoid calling "uname" except when needed`

This late resolution is what's new in Python 3.9 and also the source of the issue  as far as I can tell. I suppose the answer may depend on how braod our definition of  "largely compatible" is.

For some context, we use `_replace` in the tests of our BuildStream project, which is why we ran into this. The fix is reasonably simple on our end by changing how we mock some bits. But I wanted to check here if it's considered a bug or not. For reference, this is the patch we neded on our end: https://gitlab.com/BuildStream/buildstream/-/merge_requests/2092.
msg379756 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2020-10-27 13:05
Indeed, it was unexpected that consumers of the `uname_result` were using `_replace`. In fact, the focus of the tests is on ensuring that users are able to access the items by index, e.g. `uname()[0]`.

It should be possible to support `_replace` on the `uname_result` as found in Python 3.9+. The real question is - is it important enough to declare and restore support for this use case based on this one report (and likely handful of other cases), or would it be better to discourage use of `_replace` for `uname_result` and provide a straightforward workaround (to be documented here) for those use-cases to employ?

Marc, do you have an opinion?
msg379854 - (view) Author: Robert O'Callahan (rocallahan) Date: 2020-10-29 02:06
I filed issue 42189, which is similar but maybe worse: copy.deepcopy() is broken for platform.uname_result objects.
msg379872 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2020-10-29 13:23
Please take a look at the PR. Let me know what you think about the limited compatibility it adds (still doesn't allow _replace on 'processor').
msg384129 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2020-12-31 19:08
New changeset a6fd0f414c0cb4cd5cc20eb2df3340b31c6f7743 by Jason R. Coombs in branch 'master':
bpo-42163, bpo-42189, bpo-42659: Support uname_tuple._replace (for all but processor) (#23010)
https://github.com/python/cpython/commit/a6fd0f414c0cb4cd5cc20eb2df3340b31c6f7743
msg385146 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2021-01-16 19:45
New changeset 799722cb0ddb90752cde7798cab543f30623ebf2 by Jason R. Coombs in branch '3.9':
[3.9] bpo-42163, bpo-42189, bpo-42659: Support uname_tuple._replace (for all but processor) (GH-23010) (#24232)
https://github.com/python/cpython/commit/799722cb0ddb90752cde7798cab543f30623ebf2
History
Date User Action Args
2021-01-16 19:46:20jaracosetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2021-01-16 19:45:51jaracosetmessages: + msg385146
2021-01-16 19:22:28jaracosetpull_requests: + pull_request23055
2020-12-31 19:08:11jaracosetmessages: + msg384129
2020-10-29 13:23:58jaracosetmessages: + msg379872
2020-10-29 02:06:31rocallahansetnosy: + rocallahan
messages: + msg379854
2020-10-27 22:38:04jaracosetkeywords: + patch
stage: patch review
pull_requests: + pull_request21926
2020-10-27 13:05:21jaracosetassignee: jaraco
2020-10-27 13:05:06jaracosetnosy: + lemburg, - rhettinger
messages: + msg379756
versions: + Python 3.10
2020-10-27 06:56:33serhiy.storchakasetnosy: + rhettinger, jaraco
2020-10-26 22:21:52cs-shadowcreate