Skip to content

Commit 7733ba2

Browse files
Samuel FORESTIERHorlogeSkynet
authored andcommitted
Add support for AIX (closes #241)
1 parent 91aa0df commit 7733ba2

4 files changed

Lines changed: 60 additions & 3 deletions

File tree

src/distro/distro.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ def id() -> str:
220220
"freebsd" FreeBSD
221221
"midnightbsd" MidnightBSD
222222
"rocky" Rocky Linux
223+
"aix" AIX
223224
============== =========================================
224225
225226
If you have a need to get distros for reliable IDs added into this set,
@@ -644,6 +645,7 @@ def __init__(
644645
distro_release_file: str = "",
645646
include_uname: bool = True,
646647
root_dir: Optional[str] = None,
648+
include_oslevel: bool = True,
647649
) -> None:
648650
"""
649651
The initialization method of this class gathers information from the
@@ -686,6 +688,11 @@ def __init__(
686688
* ``root_dir`` (string): The absolute path to the root directory to use
687689
to find distro-related information files.
688690
691+
* ``include_oslevel`` (bool): Controls whether (AIX) oslevel command
692+
output is included as a data source. If the oslevel command is not
693+
available in the program execution path the data source will be
694+
empty.
695+
689696
Public instance attributes:
690697
691698
* ``os_release_file`` (string): The path name of the
@@ -703,6 +710,10 @@ def __init__(
703710
parameter. This controls whether the uname information will
704711
be loaded.
705712
713+
* ``include_oslevel`` (bool): The result of the ``include_oslevel``
714+
parameter. This controls whether (AIX) oslevel information will be
715+
loaded.
716+
706717
Raises:
707718
708719
* :py:exc:`OSError`: Some I/O issue with an os-release file or distro
@@ -741,6 +752,7 @@ def __init__(
741752
self.distro_release_file = distro_release_file or "" # updated later
742753
self.include_lsb = include_lsb
743754
self.include_uname = include_uname
755+
self.include_oslevel = include_oslevel
744756

745757
def __repr__(self) -> str:
746758
"""Return repr of all info"""
@@ -750,10 +762,12 @@ def __repr__(self) -> str:
750762
"distro_release_file={self.distro_release_file!r}, "
751763
"include_lsb={self.include_lsb!r}, "
752764
"include_uname={self.include_uname!r}, "
765+
"include_oslevel={self.include_oslevel!r}, "
753766
"_os_release_info={self._os_release_info!r}, "
754767
"_lsb_release_info={self._lsb_release_info!r}, "
755768
"_distro_release_info={self._distro_release_info!r}, "
756-
"_uname_info={self._uname_info!r})".format(self=self)
769+
"_uname_info={self._uname_info!r}, "
770+
"_oslevel_info={self._oslevel_info!r})".format(self=self)
757771
)
758772

759773
def linux_distribution(
@@ -841,6 +855,9 @@ def version(self, pretty: bool = False, best: bool = False) -> str:
841855
).get("version_id", ""),
842856
self.uname_attr("release"),
843857
]
858+
if self.uname_attr("id").startswith("aix"):
859+
# On AIX platforms, prefer oslevel command output.
860+
versions.insert(0, self.oslevel_info())
844861
version = ""
845862
if best:
846863
# This algorithm uses the last version in priority order that has
@@ -981,6 +998,12 @@ def uname_info(self) -> Dict[str, str]:
981998
"""
982999
return self._uname_info
9831000

1001+
def oslevel_info(self) -> str:
1002+
"""
1003+
Return AIX' oslevel command output.
1004+
"""
1005+
return self._oslevel_info
1006+
9841007
def os_release_attr(self, attribute: str) -> str:
9851008
"""
9861009
Return a single named information item from the os-release file data
@@ -1135,6 +1158,16 @@ def _uname_info(self) -> Dict[str, str]:
11351158
content = self._to_str(stdout).splitlines()
11361159
return self._parse_uname_content(content)
11371160

1161+
@cached_property
1162+
def _oslevel_info(self) -> str:
1163+
if not self.include_oslevel:
1164+
return ""
1165+
try:
1166+
stdout = subprocess.check_output("oslevel", stderr=subprocess.DEVNULL)
1167+
except (OSError, subprocess.CalledProcessError):
1168+
return ""
1169+
return self._to_str(stdout).strip()
1170+
11381171
@staticmethod
11391172
def _parse_uname_content(lines: Sequence[str]) -> Dict[str, str]:
11401173
if not lines:
@@ -1301,7 +1334,10 @@ def main() -> None:
13011334

13021335
if args.root_dir:
13031336
dist = LinuxDistribution(
1304-
include_lsb=False, include_uname=False, root_dir=args.root_dir
1337+
include_lsb=False,
1338+
include_uname=False,
1339+
include_oslevel=False,
1340+
root_dir=args.root_dir,
13051341
)
13061342
else:
13071343
dist = _distro
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
echo "7.2.0.0"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
echo "AIX 2"

tests/test_distro.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,9 +490,10 @@ def setup_method(self, test_method: FunctionType) -> None:
490490
root_dir = os.path.join(DISTROS_DIR, dist)
491491
self.distro = distro.LinuxDistribution(
492492
include_lsb=False,
493+
include_uname=False,
494+
include_oslevel=False,
493495
os_release_file="",
494496
distro_release_file="path-to-non-existing-file",
495-
include_uname=False,
496497
root_dir=root_dir,
497498
)
498499

@@ -1128,6 +1129,20 @@ def test_arch_release(self) -> None:
11281129
# considered a valid distro release file:
11291130
self._test_non_existing_release_file()
11301131

1132+
def test_aix72_release(self) -> None:
1133+
desired_outcome = {
1134+
"id": "aix",
1135+
"name": "AIX",
1136+
"pretty_name": "AIX 7.2.0.0",
1137+
"version": "7.2.0.0",
1138+
"pretty_version": "7.2.0.0",
1139+
"best_version": "7.2.0.0",
1140+
"major_version": "7",
1141+
"minor_version": "2",
1142+
"build_number": "0",
1143+
}
1144+
self._test_outcome(desired_outcome)
1145+
11311146
def test_centos5_release(self) -> None:
11321147
desired_outcome = {
11331148
"id": "centos",

0 commit comments

Comments
 (0)