diff options
author | Christian Heimes <christian@python.org> | 2020-11-30 21:34:45 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-30 21:34:45 (GMT) |
commit | 5c73afc36ee6cca41009a510092e1f901c5dc0a0 (patch) | |
tree | eb72eecfbbaf3809eead8a972f47064272b34fe3 /Lib/platform.py | |
parent | 9bdc40ee3e0d886fb62b5334e8a88c1fe9460ba0 (diff) | |
download | cpython-5c73afc36ee6cca41009a510092e1f901c5dc0a0.zip cpython-5c73afc36ee6cca41009a510092e1f901c5dc0a0.tar.gz cpython-5c73afc36ee6cca41009a510092e1f901c5dc0a0.tar.bz2 |
bpo-28468: Add platform.freedesktop_os_release() (GH-23492)
Add platform.freedesktop_os_release() function to parse freedesktop.org
os-release files.
Signed-off-by: Christian Heimes <christian@python.org>
Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Lib/platform.py')
-rwxr-xr-x | Lib/platform.py | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/Lib/platform.py b/Lib/platform.py index 0eb5167..138a974 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -1230,6 +1230,63 @@ 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)$" +) +# unescape five special characters mentioned in the standard +_os_release_unescape = re.compile(r"\\([\\\$\"\'`])") +# /etc takes precedence over /usr/lib +_os_release_candidates = ("/etc/os-release", "/usr/lib/os-relesase") +_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) + if mo is not None: + info[mo.group('name')] = _os_release_unescape.sub( + r"\1", mo.group('value') + ) + + 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 + else: + raise OSError( + errno, + f"Unable to read files {', '.join(_os_release_candidates)}" + ) + + return _os_release_cache.copy() + + ### Command line interface if __name__ == '__main__': |