-
-
Notifications
You must be signed in to change notification settings - Fork 37
/
distributions.py
153 lines (133 loc) · 5.69 KB
/
distributions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""
Distributions enumeration module.
Operating Systems detection logic.
Interface to `os-release` (through `distro` module).
"""
import os
import platform
import sys
from contextlib import suppress
from enum import Enum
from functools import lru_cache
from typing import List, Optional
import distro
class Distributions(Enum):
"""
This enumeration lists supported operating systems (keys).
Values contain their respective `distro` identifier.
See <https://distro.readthedocs.io/en/latest/#distro.id>.
"""
ALPINE = "alpine"
ANDROID = "android"
ARCH = "arch"
ARMBIAN = "armbian"
BUILDROOT = "buildroot"
BUNSENLABS = "bunsenlabs"
CENTOS = "centos"
CRUNCHBANG = "crunchbang"
DARWIN = "darwin"
DEBIAN = "debian"
DEVUAN = "devuan"
ELEMENTARY = "elementary"
ENDEAVOUROS = "endeavouros"
ENSO = "enso"
FEDORA = "fedora"
FREEBSD = "freebsd"
GENTOO = "gentoo"
GUIX = "guix"
KALI = "kali"
MANJARO = "manjaro"
MOEVALENT = "moevalent"
NETBSD = "netbsd"
NIXOS = "nixos"
NOBARA = "nobara"
LINUX = "linux"
LINUXMINT = "linuxmint"
OPENBSD = "openbsd"
OPENSUSE = "opensuse"
POP = "pop"
PARABOLA = "parabola"
QUIRINUX = "quirinux"
RASPBIAN = "raspbian"
ROCKY = "rocky"
RHEL = "rhel"
SIDUCTION = "siduction"
SLACKWARE = "slackware"
UBUNTU = "ubuntu"
UNIVALENT = "univalent"
WINDOWS = "windows"
@staticmethod
def get_identifiers() -> List[str]:
"""Simple getter returning current supported distributions identifiers"""
return [d.value for d in Distributions.__members__.values()]
@staticmethod
@lru_cache(maxsize=None) # Python < 3.9, `functools.cache` is not yet available.
def get_local() -> "Distributions": # pylint: disable=too-many-return-statements
"""Entry point of Archey distribution detection logic"""
distribution = Distributions._vendor_detection()
# In case nothing got detected the "regular" way...
if not distribution:
# Are we running on Darwin (somehow not previously detected by `distro`) ?
if platform.system() == "Darwin":
return Distributions.DARWIN
# Android systems are currently not being handled by `distro`.
# At first, we imitate the Python standard library, by checking whether CPython
# has been built for Android.
# See <https://github.com/python/cpython/search?l=Python&q=getandroidapilevel>
# As a fallback, we mimic Neofetch behavior, by relying on the file-system.
# See <https://github.com/nir0s/distro/issues/253>
if hasattr(sys, "getandroidapilevel") or (
os.path.isdir("/system/app") and os.path.isdir("/system/priv-app")
):
return Distributions.ANDROID
# If nothing of the above matched, fall-back on the Linux logo.
return Distributions.LINUX
# Below are brain-dead cases for distributions not properly handled by `distro`.
# One _may_ want to add its own logic to add support for such undetectable systems.
if distribution == Distributions.DEBIAN:
# CrunchBang is tagged as _regular_ Debian by `distro`.
# Below conditions are here to work-around this issue.
# First condition : CrunchBang-Linux and CrunchBang-Monara.
# Second condition : CrunchBang++ (CBPP).
if os.path.isfile("/etc/lsb-release-crunchbang") or os.path.isfile(
"/usr/bin/cbpp-exit"
):
return Distributions.CRUNCHBANG
# Armbian is also detected as _regular_ Debian by `distro`, but going directly
# through release info gives us a proper id (see <python-distro/distro#366>).
if distro.distro_release_attr("id") == "armbian":
return Distributions.ARMBIAN
elif distribution == Distributions.UBUNTU:
# Older Pop!_OS releases (< 20.*) didn't ship their own `ID` (from `os-release`).
# Thus, they are detected as "regular" Ubuntu distributions.
# We may here rely on their `NAME` (from `os-release`), which is sufficient.
if Distributions.get_distro_name(pretty=False) == "Pop!_OS":
return Distributions.POP
return distribution
@staticmethod
def _vendor_detection() -> Optional["Distributions"]:
"""Main distribution detection logic, relying on `distro`, handling _common_ cases"""
# Are we running on Windows ?
if platform.system() == "Windows":
return Distributions.WINDOWS
# Is `ID` (from `os-release`) well-known and supported ?
with suppress(ValueError):
return Distributions(distro.id())
# Is any of `ID_LIKE` (from `os-release`) well-known and supported ?
# See <https://www.freedesktop.org/software/systemd/man/os-release.html#ID_LIKE=>.
for id_like in distro.like().split(" "):
with suppress(ValueError):
return Distributions(id_like)
# Nothing of the above matched, let's return `None` and let the caller handle it.
return None
@staticmethod
def get_distro_name(pretty: bool = True) -> Optional[str]:
"""Simple wrapper to `distro` to return the current distribution _pretty_ name"""
return distro.name(pretty=pretty) or None
@staticmethod
def get_ansi_color() -> Optional[str]:
"""
Simple wrapper to `distro` to return the distribution preferred ANSI color.
See <https://www.freedesktop.org/software/systemd/man/os-release.html#ANSI_COLOR=>.
"""
return distro.os_release_attr("ansi_color") or None