1# Copyright (c) 2009, Willow Garage, Inc. 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are met: 6# 7# * Redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer. 9# * Redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution. 12# * Neither the name of the Willow Garage, Inc. nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26# POSSIBILITY OF SUCH DAMAGE. 27 28# Author Tully Foote/tfoote@willowgarage.com, Ken Conley/kwc@willowgarage.com 29 30""" 31Library for detecting the current OS, including detecting specific 32Linux distributions. 33""" 34 35from __future__ import print_function 36 37import codecs 38import locale 39import os 40import platform 41import subprocess 42 43 44def _read_stdout(cmd): 45 try: 46 pop = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 47 (std_out, std_err) = pop.communicate() 48 # Python 2.6 compatibility 49 if isinstance(std_out, str): 50 return std_out.strip() 51 return std_out.decode(encoding='UTF-8').strip() 52 except: 53 return None 54 55 56def uname_get_machine(): 57 """ 58 Linux: wrapper around uname to determine if OS is 64-bit 59 """ 60 return _read_stdout(['uname', '-m']) 61 62 63def read_issue(filename="/etc/issue"): 64 """ 65 :returns: list of strings in issue file, or None if issue file cannot be read/split 66 """ 67 if os.path.exists(filename): 68 with codecs.open(filename, 'r', encoding=locale.getpreferredencoding()) as f: 69 return f.read().split() 70 return None 71 72 73def read_os_release(filename=None): 74 """ 75 :returns: Dictionary of key value pairs from /etc/os-release or fallback to 76 /usr/lib/os-release, with quotes stripped from values 77 """ 78 if filename is None: 79 filename = '/etc/os-release' 80 if not os.path.exists(filename): 81 filename = '/usr/lib/os-release' 82 83 if not os.path.exists(filename): 84 return None 85 86 release_info = {} 87 with codecs.open(filename, 'r', encoding=locale.getpreferredencoding()) as f: 88 for line in f: 89 key, val = line.rstrip('\n').partition('=')[::2] 90 release_info[key] = val.strip('"') 91 return release_info 92 93 94class OsNotDetected(Exception): 95 """ 96 Exception to indicate failure to detect operating system. 97 """ 98 pass 99 100 101class OsDetector(object): 102 """ 103 Generic API for detecting a specific OS. 104 """ 105 def is_os(self): 106 """ 107 :returns: if the specific OS which this class is designed to 108 detect is present. Only one version of this class should 109 return for any version. 110 """ 111 raise NotImplementedError("is_os unimplemented") 112 113 def get_version(self): 114 """ 115 :returns: standardized version for this OS. (aka Ubuntu Hardy Heron = "8.04") 116 :raises: :exc:`OsNotDetected` if called on incorrect OS. 117 """ 118 raise NotImplementedError("get_version unimplemented") 119 120 def get_codename(self): 121 """ 122 :returns: codename for this OS. (aka Ubuntu Hardy Heron = "hardy"). If codenames are not available for this OS, return empty string. 123 :raises: :exc:`OsNotDetected` if called on incorrect OS. 124 """ 125 raise NotImplementedError("get_codename unimplemented") 126 127 128class LsbDetect(OsDetector): 129 """ 130 Generic detector for Debian, Ubuntu, and Mint 131 """ 132 def __init__(self, lsb_name, get_version_fn=None): 133 self.lsb_name = lsb_name 134 if hasattr(platform, "linux_distribution"): 135 self.lsb_info = platform.linux_distribution(full_distribution_name=0) 136 elif hasattr(platform, "dist"): 137 self.lsb_info = platform.dist() 138 else: 139 self.lsb_info = None 140 141 def is_os(self): 142 return self.lsb_info is not None and self.lsb_info[0] == self.lsb_name 143 144 def get_version(self): 145 if self.is_os(): 146 return self.lsb_info[1] 147 raise OsNotDetected('called in incorrect OS') 148 149 def get_codename(self): 150 if self.is_os(): 151 return self.lsb_info[2] 152 raise OsNotDetected('called in incorrect OS') 153 154 155class Debian(LsbDetect): 156 157 def __init__(self, get_version_fn=None): 158 super(Debian, self).__init__('debian', get_version_fn) 159 160 def get_codename(self): 161 if self.is_os(): 162 v = self.get_version() 163 if v.startswith('7.'): 164 return 'wheezy' 165 if v.startswith('8.'): 166 return 'jessie' 167 if v.startswith('9.'): 168 return 'stretch' 169 if v.startswith('10.'): 170 return 'buster' 171 return '' 172 173 174class FdoDetect(OsDetector): 175 """ 176 Generic detector for operating systems implementing /etc/os-release, as defined by the os-release spec hosted at Freedesktop.org (Fdo): 177 http://www.freedesktop.org/software/systemd/man/os-release.html 178 Requires that the "ID", and "VERSION_ID" keys are set in the os-release file. 179 180 Codename is parsed from the VERSION key if available: either using the format "foo, CODENAME" or "foo (CODENAME)." 181 If the VERSION key is not present, the VERSION_ID is value is used as the codename. 182 """ 183 def __init__(self, fdo_id): 184 release_info = read_os_release() 185 if release_info is not None and "ID" in release_info and release_info["ID"] == fdo_id: 186 self.release_info = release_info 187 else: 188 self.release_info = None 189 190 def is_os(self): 191 return self.release_info is not None and "VERSION_ID" in self.release_info 192 193 def get_version(self): 194 if self.is_os(): 195 return self.release_info["VERSION_ID"] 196 raise OsNotDetected("called in incorrect OS") 197 198 def get_codename(self): 199 if self.is_os(): 200 if "VERSION" in self.release_info: 201 version = self.release_info["VERSION"] 202 # FDO style: works with Fedora, Debian, Suse. 203 if version.find("(") is not -1: 204 codename = version[version.find("(") + 1:version.find(")")] 205 # Ubuntu style 206 elif version.find(",") is not -1: 207 codename = version[version.find(",") + 1:].lstrip(' ').split()[0] 208 # Indeterminate style 209 else: 210 codename = version 211 return codename.lower() 212 else: 213 return self.get_version() 214 raise OsNotDetected("called in incorrect OS") 215 216 217class OpenEmbedded(OsDetector): 218 """ 219 Detect OpenEmbedded. 220 """ 221 def is_os(self): 222 return "ROS_OS_OVERRIDE" in os.environ and os.environ["ROS_OS_OVERRIDE"] == "openembedded" 223 224 def get_version(self): 225 if self.is_os(): 226 return "" 227 raise OsNotDetected('called in incorrect OS') 228 229 def get_codename(self): 230 if self.is_os(): 231 return "" 232 raise OsNotDetected('called in incorrect OS') 233 234 235class OpenSuse(OsDetector): 236 """ 237 Detect OpenSuse OS. 238 """ 239 def __init__(self, brand_file="/etc/SuSE-brand", release_file="/etc/SuSE-release"): 240 self._brand_file = brand_file 241 self._release_file = release_file 242 243 def is_os(self): 244 os_list = read_issue(self._brand_file) 245 return os_list and os_list[0] == "openSUSE" 246 247 def get_version(self): 248 if self.is_os() and os.path.exists(self._brand_file): 249 with open(self._brand_file, 'r') as fh: 250 os_list = fh.read().strip().split('\n') 251 if len(os_list) == 2: 252 os_list = os_list[1].split(' = ') 253 if os_list[0] == "VERSION": 254 return os_list[1] 255 raise OsNotDetected('cannot get version on this OS') 256 257 def get_codename(self): 258 # /etc/SuSE-release is deprecated since 13.1 259 if self._release_file is None: 260 return "" 261 if self.is_os() and os.path.exists(self._release_file): 262 with open(self._release_file, 'r') as fh: 263 os_list = fh.read().strip().split('\n') 264 for line in os_list: 265 kv = line.split(' = ') 266 if kv[0] == "CODENAME": 267 return kv[1] 268 raise OsNotDetected('called in incorrect OS') 269 270 271class Fedora(OsDetector): 272 """ 273 Detect Fedora OS. 274 """ 275 def __init__(self, release_file="/etc/redhat-release", issue_file="/etc/issue"): 276 self._release_file = release_file 277 self._issue_file = issue_file 278 279 def is_os(self): 280 os_list = read_issue(self._release_file) 281 return os_list and os_list[0] == "Fedora" 282 283 def get_version(self): 284 if self.is_os(): 285 os_list = read_issue(self._issue_file) 286 idx = os_list.index('release') 287 if idx > 0: 288 return os_list[idx + 1] 289 raise OsNotDetected('cannot get version on this OS') 290 291 def get_codename(self): 292 if self.is_os(): 293 os_list = read_issue(self._release_file) 294 idx = os_list.index('release') 295 matches = [x for x in os_list if x[0] == '('] 296 codename = matches[0][1:] 297 if codename[-1] == ')': 298 codename = codename[:-1] 299 return codename.lower() 300 raise OsNotDetected('called in incorrect OS') 301 302 303class Rhel(Fedora): 304 """ 305 Detect Redhat OS. 306 """ 307 def __init__(self, release_file="/etc/redhat-release"): 308 self._release_file = release_file 309 310 def is_os(self): 311 os_list = read_issue(self._release_file) 312 return os_list and os_list[:3] == ['Red', 'Hat', 'Enterprise'] 313 314 def get_version(self): 315 if self.is_os(): 316 os_list = read_issue(self._release_file) 317 idx = os_list.index('release') 318 return os_list[idx + 1] 319 raise OsNotDetected('called in incorrect OS') 320 321 def get_codename(self): 322 # taroon, nahant, tikanga, santiago, pensacola 323 if self.is_os(): 324 os_list = read_issue(self._release_file) 325 idx = os_list.index('release') 326 matches = [x for x in os_list if x[0] == '('] 327 codename = matches[0][1:] 328 if codename[-1] == ')': 329 codename = codename[:-1] 330 return codename.lower() 331 raise OsNotDetected('called in incorrect OS') 332 333 334# Source: https://en.wikipedia.org/wiki/MacOS#Versions 335_osx_codename_map = { 336 4: 'tiger', 337 5: 'leopard', 338 6: 'snow', 339 7: 'lion', 340 8: 'mountain lion', 341 9: 'mavericks', 342 10: 'yosemite', 343 11: 'el capitan', 344 12: 'sierra', 345 13: 'high sierra', 346 14: 'mojave', 347 15: 'catalina', 348} 349 350 351def _osx_codename(major, minor): 352 if major != 10 or minor not in _osx_codename_map: 353 raise OsNotDetected("unrecognized version: %s.%s" % (major, minor)) 354 return _osx_codename_map[minor] 355 356 357class OSX(OsDetector): 358 """ 359 Detect OS X 360 """ 361 def __init__(self, sw_vers_file="/usr/bin/sw_vers"): 362 self._sw_vers_file = sw_vers_file 363 364 def is_os(self): 365 return os.path.exists(self._sw_vers_file) 366 367 def get_codename(self): 368 if self.is_os(): 369 version = self.get_version() 370 import distutils.version # To parse version numbers 371 try: 372 ver = distutils.version.StrictVersion(version).version 373 except ValueError: 374 raise OsNotDetected("invalid version string: %s" % (version)) 375 return _osx_codename(*ver[0:2]) 376 raise OsNotDetected('called in incorrect OS') 377 378 def get_version(self): 379 if self.is_os(): 380 return _read_stdout([self._sw_vers_file, '-productVersion']) 381 raise OsNotDetected('called in incorrect OS') 382 383 384class QNX(OsDetector): 385 ''' 386 Detect QNX realtime OS. 387 @author: Isaac Saito 388 ''' 389 def __init__(self, uname_file='/bin/uname'): 390 ''' 391 @param uname_file: An executable that can be used for detecting 392 OS name and version. 393 ''' 394 self._os_name_qnx = 'QNX' 395 self._uname_file = uname_file 396 397 def is_os(self): 398 if os.path.exists(self._uname_file): 399 std_out = _read_stdout([self._uname_file]) 400 return std_out.strip() == self._os_name_qnx 401 else: 402 return False 403 404 def get_codename(self): 405 if self.is_os(): 406 return '' 407 raise OsNotDetected('called in incorrect OS') 408 409 def get_version(self): 410 if self.is_os() and os.path.exists(self._uname_file): 411 return _read_stdout([self._uname_file, "-r"]) 412 raise OsNotDetected('called in incorrect OS') 413 414 415class Arch(OsDetector): 416 """ 417 Detect Arch Linux. 418 """ 419 def __init__(self, release_file='/etc/arch-release'): 420 self._release_file = release_file 421 422 def is_os(self): 423 return os.path.exists(self._release_file) 424 425 def get_version(self): 426 if self.is_os(): 427 return "" 428 raise OsNotDetected('called in incorrect OS') 429 430 def get_codename(self): 431 if self.is_os(): 432 return "" 433 raise OsNotDetected('called in incorrect OS') 434 435 436class Manjaro(Arch): 437 """ 438 Detect Manjaro. 439 """ 440 def __init__(self, release_file='/etc/manjaro-release'): 441 super(Manjaro, self).__init__(release_file) 442 443 444class Centos(OsDetector): 445 """ 446 Detect CentOS. 447 """ 448 def __init__(self, release_file='/etc/redhat-release'): 449 self._release_file = release_file 450 451 def is_os(self): 452 os_list = read_issue(self._release_file) 453 return os_list and os_list[0] == 'CentOS' 454 455 def get_version(self): 456 if self.is_os(): 457 os_list = read_issue(self._release_file) 458 idx = os_list.index('release') 459 return os_list[idx + 1] 460 raise OsNotDetected('called in incorrect OS') 461 462 def get_codename(self): 463 if self.is_os(): 464 os_list = read_issue(self._release_file) 465 idx = os_list.index('release') 466 matches = [x for x in os_list if x[0] == '('] 467 codename = matches[0][1:] 468 if codename[-1] == ')': 469 codename = codename[:-1] 470 return codename.lower() 471 raise OsNotDetected('called in incorrect OS') 472 473 474class Cygwin(OsDetector): 475 """ 476 Detect Cygwin presence on Windows OS. 477 """ 478 def is_os(self): 479 return os.path.exists("/usr/bin/cygwin1.dll") 480 481 def get_version(self): 482 if self.is_os(): 483 return _read_stdout(['uname', '-r']) 484 raise OsNotDetected('called in incorrect OS') 485 486 def get_codename(self): 487 if self.is_os(): 488 return '' 489 raise OsNotDetected('called in incorrect OS') 490 491 492class Gentoo(OsDetector): 493 """ 494 Detect Gentoo OS. 495 """ 496 def __init__(self, release_file="/etc/gentoo-release"): 497 self._release_file = release_file 498 499 def is_os(self): 500 os_list = read_issue(self._release_file) 501 return os_list and os_list[0] == "Gentoo" and os_list[1] == "Base" 502 503 def get_version(self): 504 if self.is_os(): 505 os_list = read_issue(self._release_file) 506 return os_list[4] 507 raise OsNotDetected('called in incorrect OS') 508 509 def get_codename(self): 510 if self.is_os(): 511 return '' 512 raise OsNotDetected('called in incorrect OS') 513 514 515class Funtoo(Gentoo): 516 """ 517 Detect Funtoo OS, a Gentoo Variant. 518 """ 519 def __init__(self, release_file="/etc/gentoo-release"): 520 Gentoo.__init__(self, release_file) 521 522 def is_os(self): 523 os_list = read_issue(self._release_file) 524 return os_list and os_list[0] == "Funtoo" and os_list[1] == "Linux" 525 526 527class FreeBSD(OsDetector): 528 """ 529 Detect FreeBSD OS. 530 """ 531 def __init__(self, uname_file="/usr/bin/uname"): 532 self._uname_file = uname_file 533 534 def is_os(self): 535 if os.path.exists(self._uname_file): 536 std_out = _read_stdout([self._uname_file]) 537 return std_out.strip() == "FreeBSD" 538 else: 539 return False 540 541 def get_version(self): 542 if self.is_os() and os.path.exists(self._uname_file): 543 return _read_stdout([self._uname_file, "-r"]) 544 raise OsNotDetected('called in incorrect OS') 545 546 def get_codename(self): 547 if self.is_os(): 548 return '' 549 raise OsNotDetected('called in incorrect OS') 550 551 552class Slackware(OsDetector): 553 """ 554 Detect SlackWare Linux. 555 """ 556 def __init__(self, release_file='/etc/slackware-version'): 557 self._release_file = release_file 558 559 def is_os(self): 560 return os.path.exists(self._release_file) 561 562 def get_version(self): 563 if self.is_os(): 564 os_list = read_issue(self._release_file) 565 return os_list[1] 566 raise OsNotDetected('called in incorrect OS') 567 568 def get_codename(self): 569 if self.is_os(): 570 return '' 571 raise OsNotDetected('called in incorrect OS') 572 573 574class Windows(OsDetector): 575 """ 576 Detect Windows OS. 577 """ 578 def is_os(self): 579 return platform.system() == "Windows" 580 581 def get_version(self): 582 if self.is_os(): 583 return platform.version() 584 raise OsNotDetected('called in incorrect OS') 585 586 def get_codename(self): 587 if self.is_os(): 588 return platform.release() 589 raise OsNotDetected('called in incorrect OS') 590 591 592class OsDetect: 593 """ 594 This class will iterate over registered classes to lookup the 595 active OS and version 596 """ 597 598 default_os_list = [] 599 600 def __init__(self, os_list=None): 601 if os_list is None: 602 os_list = OsDetect.default_os_list 603 self._os_list = os_list 604 self._os_name = None 605 self._os_version = None 606 self._os_codename = None 607 self._os_detector = None 608 self._override = False 609 610 @staticmethod 611 def register_default(os_name, os_detector): 612 """ 613 Register detector to be used with all future instances of 614 :class:`OsDetect`. The new detector will have precedence over 615 any previously registered detectors associated with *os_name*. 616 617 :param os_name: OS key associated with OS detector 618 :param os_detector: :class:`OsDetector` instance 619 """ 620 OsDetect.default_os_list.insert(0, (os_name, os_detector)) 621 622 def detect_os(self, env=None): 623 """ 624 Detect operating system. Return value can be overridden by 625 the :env:`ROS_OS_OVERRIDE` environment variable. 626 627 :param env: override ``os.environ`` 628 :returns: (os_name, os_version, os_codename), ``(str, str, str)`` 629 :raises: :exc:`OsNotDetected` if OS could not be detected 630 """ 631 if env is None: 632 env = os.environ 633 if 'ROS_OS_OVERRIDE' in env: 634 splits = env["ROS_OS_OVERRIDE"].split(':') 635 self._os_name = splits[0] 636 if len(splits) > 1: 637 self._os_version = splits[1] 638 if len(splits) > 2: 639 self._os_codename = splits[2] 640 else: 641 self._os_codename = '' 642 else: 643 self._os_version = self._os_codename = '' 644 self._override = True 645 else: 646 for os_name, os_detector in self._os_list: 647 if os_detector.is_os(): 648 self._os_name = os_name 649 self._os_version = os_detector.get_version() 650 self._os_codename = os_detector.get_codename() 651 self._os_detector = os_detector 652 break 653 654 if self._os_name: 655 return self._os_name, self._os_version, self._os_codename 656 else: # No solution found 657 attempted = [x[0] for x in self._os_list] 658 raise OsNotDetected("Could not detect OS, tried %s" % attempted) 659 660 def get_detector(self, name=None): 661 """ 662 Get detector used for specified OS name, or the detector for this OS if name is ``None``. 663 664 :raises: :exc:`KeyError` 665 """ 666 if name is None: 667 if not self._os_detector: 668 self.detect_os() 669 return self._os_detector 670 else: 671 try: 672 return [d for d_name, d in self._os_list if d_name == name][0] 673 except IndexError: 674 raise KeyError(name) 675 676 def add_detector(self, name, detector): 677 """ 678 Add detector to list of detectors used by this instance. *detector* will override any previous 679 detectors associated with *name*. 680 681 :param name: OS name that detector matches 682 :param detector: :class:`OsDetector` instance 683 """ 684 self._os_list.insert(0, (name, detector)) 685 686 def get_name(self): 687 if not self._os_name: 688 self.detect_os() 689 return self._os_name 690 691 def get_version(self): 692 if not self._os_version: 693 self.detect_os() 694 return self._os_version 695 696 def get_codename(self): 697 if not self._os_codename: 698 self.detect_os() 699 return self._os_codename 700 701 702OS_ALPINE = 'alpine' 703OS_ARCH = 'arch' 704OS_MANJARO = 'manjaro' 705OS_CENTOS = 'centos' 706OS_CYGWIN = 'cygwin' 707OS_DEBIAN = 'debian' 708OS_ELEMENTARY = 'elementary' 709OS_ELEMENTARY_OLD = 'elementary' 710OS_FEDORA = 'fedora' 711OS_FREEBSD = 'freebsd' 712OS_FUNTOO = 'funtoo' 713OS_GENTOO = 'gentoo' 714OS_LINARO = 'linaro' 715OS_MINT = 'mint' 716OS_MX = 'mx' 717OS_NEON = 'neon' 718OS_OPENEMBEDDED = 'openembedded' 719OS_OPENSUSE = 'opensuse' 720OS_OPENSUSE13 = 'opensuse' 721OS_TIZEN = 'tizen' 722OS_OSX = 'osx' 723OS_QNX = 'qnx' 724OS_RHEL = 'rhel' 725OS_SLACKWARE = 'slackware' 726OS_UBUNTU = 'ubuntu' 727OS_CLEARLINUX = 'clearlinux' 728OS_NIXOS = 'nixos' 729OS_WINDOWS = 'windows' 730OS_ZORIN = 'zorin' 731 732OsDetect.register_default(OS_ALPINE, FdoDetect("alpine")) 733OsDetect.register_default(OS_ARCH, Arch()) 734OsDetect.register_default(OS_MANJARO, Manjaro()) 735OsDetect.register_default(OS_CENTOS, Centos()) 736OsDetect.register_default(OS_CYGWIN, Cygwin()) 737OsDetect.register_default(OS_DEBIAN, Debian()) 738OsDetect.register_default(OS_ELEMENTARY, LsbDetect("elementary")) 739OsDetect.register_default(OS_ELEMENTARY_OLD, LsbDetect("elementary OS")) 740OsDetect.register_default(OS_FEDORA, FdoDetect("fedora")) 741OsDetect.register_default(OS_FREEBSD, FreeBSD()) 742OsDetect.register_default(OS_FUNTOO, Funtoo()) 743OsDetect.register_default(OS_GENTOO, Gentoo()) 744OsDetect.register_default(OS_LINARO, LsbDetect("Linaro")) 745OsDetect.register_default(OS_MINT, LsbDetect("LinuxMint")) 746OsDetect.register_default(OS_MX, LsbDetect("MX")) 747OsDetect.register_default(OS_NEON, LsbDetect("neon")) 748OsDetect.register_default(OS_OPENEMBEDDED, OpenEmbedded()) 749OsDetect.register_default(OS_OPENSUSE, OpenSuse()) 750OsDetect.register_default(OS_OPENSUSE13, OpenSuse(brand_file='/etc/SUSE-brand', release_file=None)) 751OsDetect.register_default(OS_OPENSUSE, FdoDetect("opensuse-tumbleweed")) 752OsDetect.register_default(OS_OPENSUSE, FdoDetect("opensuse")) 753OsDetect.register_default(OS_TIZEN, FdoDetect("tizen")) 754OsDetect.register_default(OS_OSX, OSX()) 755OsDetect.register_default(OS_QNX, QNX()) 756OsDetect.register_default(OS_RHEL, Rhel()) 757OsDetect.register_default(OS_SLACKWARE, Slackware()) 758OsDetect.register_default(OS_UBUNTU, LsbDetect("Ubuntu")) 759OsDetect.register_default(OS_CLEARLINUX, FdoDetect("clear-linux-os")) 760OsDetect.register_default(OS_NIXOS, FdoDetect("nixos")) 761OsDetect.register_default(OS_WINDOWS, Windows()) 762OsDetect.register_default(OS_ZORIN, LsbDetect("Zorin")) 763 764 765if __name__ == '__main__': 766 detect = OsDetect() 767 print("OS Name: %s" % detect.get_name()) 768 print("OS Version: %s" % detect.get_version()) 769 print("OS Codename: %s" % detect.get_codename()) 770