classification
Title: _replace() no longer works on platform.uname_result objects
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.10, Python 3.9
process
Status: open Resolution:
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 2020-10-29 13:23 by jaraco.

Pull Requests
URL Status Linked Edit
PR 23010 open jaraco, 2020-10-27 22:38
Messages (4)
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').
History
Date User Action Args
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