-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
bpo-28468: Add platform.freedesktop_osrelease #23492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
8a99778
ceb9f5d
8c0550e
0fc7d03
0ed04ea
679af65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1230,6 +1230,65 @@ def platform(aliased=0, terse=0): | |||||
_platform_cache[(aliased, terse)] = platform | ||||||
return platform | ||||||
|
||||||
### freedesktop.org os-release standard | ||||||
# https://www.freedesktop.org/software/systemd/man/os-release.html | ||||||
|
||||||
# NAME=value with optional quotes (' or "). The regular expression is less | ||||||
# strict than shell lexer, but that's ok. | ||||||
_os_release_line = re.compile( | ||||||
"^(?P<name>[a-zA-Z0-9_]+)=(?P<quote>[\"\']?)(?P<value>.*)(?P=quote)$" | ||||||
) | ||||||
# /etc takes precedence over /usr/lib | ||||||
_os_release_candidates = ("/etc/os-release", "/usr/lib/os-relesase") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ooops, nicely spotted :-) I created PR #23913 to fix it. |
||||||
_os_release_cache = None | ||||||
|
||||||
|
||||||
def _parse_os_release(lines): | ||||||
# These fields are mandatory fields with well-known defaults | ||||||
# in pratice all Linux distributions override NAME, ID, and PRETTY_NAME. | ||||||
info = { | ||||||
"NAME": "Linux", | ||||||
"ID": "linux", | ||||||
"PRETTY_NAME": "Linux", | ||||||
} | ||||||
|
||||||
for line in lines: | ||||||
mo = _os_release_line.match(line) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The distro module uses
The freedesktop specification says:
It seems like your code and the distro module parse There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please give an example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something like:
Note: I wrote the example manually, it doesn't come from a concrete os-release file. |
||||||
if mo is not None: | ||||||
info[mo.group('name')] = mo.group('value') | ||||||
|
||||||
# ID_LIKE is a space separated field of ids | ||||||
if 'ID_LIKE' in info: | ||||||
info['ID_LIKE'] = tuple( | ||||||
id_like for id_like in info['ID_LIKE'].split(' ') if id_like | ||||||
) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest to remove this code. I'm not sure if it's worth it to have a special case only for the ID_LIKE variable. The platform module is mostly based on strings. You introduce a special case where a single variable is a tuple. Since it's well specified that it's space separated, the caller can split the string by themselves, no? Splitting at spaces it trivial in Python:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the only special case that a lot of users will get wrong and that won't get detected by CI. For almost all distros the Users always have to split the field and always check for "name in info["ID_LIKE"].split()". The explicit handling of ID_LIKE get rids of a foot gun. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem is that if tomorrow a new field is added with a value separated by spaces, the caller might expect Python to magically split it as a tuple. But now, we will have to update the function whenever a new field is added for add a special case. If there is no special case and it's a dummy parser, the code is more likely to stay for the same for the next 10 years. I would prefer to not reintroduce the same problem that we fixed by removing linux_distribution(): having to update the stdlib when the filename changes or file content evolves. If you want a more advanced view of the os-release, I suggest to write a higher level API on top of it and put it on PyPI, so it can be easily updated (similar to the distro module which contains many special cases). |
||||||
|
||||||
return info | ||||||
|
||||||
|
||||||
def freedesktop_os_release(): | ||||||
"""Return operation system identification from freedesktop.org os-release | ||||||
""" | ||||||
global _os_release_cache | ||||||
|
||||||
if _os_release_cache is None: | ||||||
errno = None | ||||||
for candidate in _os_release_candidates: | ||||||
try: | ||||||
with open(candidate, encoding="utf-8") as f: | ||||||
_os_release_cache = _parse_os_release(f) | ||||||
break | ||||||
except OSError as e: | ||||||
errno = e.errno | ||||||
tiran marked this conversation as resolved.
Show resolved
H
A3E2
ide resolved
|
||||||
else: | ||||||
raise OSError( | ||||||
errno, | ||||||
f"Unable to read files {', '.join(_os_release_candidates)}" | ||||||
) | ||||||
tiran marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
return _os_release_cache.copy() | ||||||
|
||||||
|
||||||
### Command line interface | ||||||
|
||||||
if __name__ == '__main__': | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Add :func:`platform.freedesktop_os_release` function to parse freedesktop.org | ||
``os-release`` files. |
Uh oh!
There was an error while loading. Please reload this page.