Skip to content

Commit

Permalink
Honors /usr/lib/os-release when /etc/os-release is not available (p…
Browse files Browse the repository at this point in the history
…ython-distro#262)

* Honors `/usr/lib/os-release` when `/etc/os-release` is not available

See <https://www.freedesktop.org/software/systemd/man/os-release.html#Description>.

* Updates documentation according to the new (but expected) behavior

* Partially reverts `c7e88ba` based on @hartwork comments

* Renames `UNIXLIBSDIR` according to @hartwork thoughts

* Follow-up to `90ceac8` according to @hartwork findings

* Prefers a fully API backward-compatible implementation for `c7e88baa`

Co-authored-by: Sebastian Pipping <[email protected]>

* Re-adds an empty new-line that somehow got lost in `distro.py`

* Don't touch those lines to keep the final patch clean

* Removes a leftover empty new-line wrongly kept across previous commits

[skip ci]

* Fixes BLACK linting

Co-authored-by: Sebastian Pipping <[email protected]>
  • Loading branch information
HorlogeSkynet and hartwork authored Jul 2, 2021
1 parent 53a031d commit b5a1a1e
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ The `distro` package implements a robust and inclusive way of retrieving the
information about a distribution based on new standards and old methods,
namely from these data sources (from high to low precedence):

* The os-release file `/etc/os-release`, if present.
* The os-release file `/etc/os-release` if present, with a fall-back on `/usr/lib/os-release` if needed.
* The output of the `lsb_release` command, if available.
* The distro release file (`/etc/*(-|_)(release|version)`), if present.
* The `uname` command for BSD based distrubtions.
Expand Down
23 changes: 21 additions & 2 deletions distro.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@


_UNIXCONFDIR = os.environ.get("UNIXCONFDIR", "/etc")
_UNIXUSRLIBDIR = os.environ.get("UNIXUSRLIBDIR", "/usr/lib")
_OS_RELEASE_BASENAME = "os-release"

#: Translation table for normalizing the "ID" attribute defined in os-release
Expand Down Expand Up @@ -714,9 +715,27 @@ def __init__(
"""
self.root_dir = root_dir
self.etc_dir = os.path.join(root_dir, "etc") if root_dir else _UNIXCONFDIR
self.os_release_file = os_release_file or os.path.join(
self.etc_dir, _OS_RELEASE_BASENAME
self.usr_lib_dir = (
os.path.join(root_dir, "usr/lib") if root_dir else _UNIXUSRLIBDIR
)

if os_release_file:
self.os_release_file = os_release_file
else:
etc_dir_os_release_file = os.path.join(self.etc_dir, _OS_RELEASE_BASENAME)
usr_lib_os_release_file = os.path.join(
self.usr_lib_dir, _OS_RELEASE_BASENAME
)

# NOTE: The idea is to respect order **and** have it set
# at all times for API backwards compatibility.
if os.path.isfile(etc_dir_os_release_file) or not os.path.isfile(
usr_lib_os_release_file
):
self.os_release_file = etc_dir_os_release_file
else:
self.os_release_file = usr_lib_os_release_file

self.distro_release_file = distro_release_file or "" # updated later
self.include_lsb = include_lsb
self.include_uname = include_uname
Expand Down
5 changes: 3 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ If you want to add test data for more distributions, please
create an issue in the `distro issue tracker`_
and provide the following information in the issue:

* The content of the `/etc/os-release` file, if any.
* The os-release file `/etc/os-release` if present, with a fall-back on `/usr/lib/os-release` if needed.
* The file names and content of the `/etc/*release` and `/etc/*version` files, if any.
* The output of the command: `lsb_release -a`, if available.
* The file names and content of any other files you are aware of that provide
Expand Down Expand Up @@ -184,7 +184,8 @@ Os-release file
===============

The os-release file is looked up using the path name ``/etc/os-release``. Its
optional additional location ``/usr/lib/os-release`` is ignored.
optional additional location ``/usr/lib/os-release`` would be looked up for if
the former couldn't be read.

The os-release file is expected to be encoded in UTF-8.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NAME="usr_lib_os-release_only"
ID=usrlibosreleaseonly
PRETTY_NAME="/usr/lib/os-release only"
19 changes: 18 additions & 1 deletion tests/test_distro.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import distro

RELATIVE_UNIXCONFDIR = distro._UNIXCONFDIR[1:]
RELATIVE_UNIXUSRLIBDIR = distro._UNIXUSRLIBDIR[1:]
MODULE_DISTRO = distro._distro


Expand Down Expand Up @@ -118,17 +119,20 @@ def setup_method(self, test_method):
# changes it:
self._saved_path = os.environ["PATH"]
self._saved_UNIXCONFDIR = distro._UNIXCONFDIR
self._saved_UNIXUSRLIBDIR = distro._UNIXUSRLIBDIR

def teardown_method(self, test_method):
os.environ["PATH"] = self._saved_path
distro._UNIXCONFDIR = self._saved_UNIXCONFDIR
distro._UNIXUSRLIBDIR = self._saved_UNIXUSRLIBDIR

def _setup_for_distro(self, distro_root):
distro_bin = os.path.join(distro_root, "bin")
# We don't want to pick up a possibly present lsb_release in the
# distro that runs this test, so we use a PATH with only one entry:
os.environ["PATH"] = distro_bin
distro._UNIXCONFDIR = os.path.join(distro_root, RELATIVE_UNIXCONFDIR)
distro._UNIXUSRLIBDIR = os.path.join(distro_root, RELATIVE_UNIXUSRLIBDIR)


@pytest.mark.skipif(not IS_LINUX, reason="Irrelevant on non-linux")
Expand Down Expand Up @@ -708,6 +712,19 @@ def test_bad_uname(self):
assert self.distro.uname_attr("name") == ""
assert self.distro.uname_attr("release") == ""

def test_usrlibosreleaseonly(self):
self._setup_for_distro(
os.path.join(TESTDISTROS, "distro", "usrlibosreleaseonly")
)
self.distro = distro.LinuxDistribution()

desired_outcome = {
"id": "usrlibosreleaseonly",
"name": "usr_lib_os-release_only",
"pretty_name": "/usr/lib/os-release only",
}
self._test_outcome(desired_outcome)


@pytest.mark.skipif(not IS_LINUX, reason="Irrelevant on non-linux")
class TestDistroRelease:
Expand Down Expand Up @@ -2113,7 +2130,7 @@ def test_repr(self):
repr_str = repr(distro._distro)
assert "LinuxDistribution" in repr_str
for attr in MODULE_DISTRO.__dict__.keys():
if attr in ("root_dir", "etc_dir"):
if attr in ("root_dir", "etc_dir", "usr_lib_dir"):
continue
assert attr + "=" in repr_str

Expand Down

0 comments on commit b5a1a1e

Please sign in to comment.