Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/pip/_vendor/distro.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 # Copyright 2015,2016,2017 Nir Cohen | |
| 2 # | |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 # you may not use this file except in compliance with the License. | |
| 5 # You may obtain a copy of the License at | |
| 6 # | |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 # | |
| 9 # Unless required by applicable law or agreed to in writing, software | |
| 10 # distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 # See the License for the specific language governing permissions and | |
| 13 # limitations under the License. | |
| 14 | |
| 15 """ | |
| 16 The ``distro`` package (``distro`` stands for Linux Distribution) provides | |
| 17 information about the Linux distribution it runs on, such as a reliable | |
| 18 machine-readable distro ID, or version information. | |
| 19 | |
| 20 It is the recommended replacement for Python's original | |
| 21 :py:func:`platform.linux_distribution` function, but it provides much more | |
| 22 functionality. An alternative implementation became necessary because Python | |
| 23 3.5 deprecated this function, and Python 3.8 will remove it altogether. | |
| 24 Its predecessor function :py:func:`platform.dist` was already | |
| 25 deprecated since Python 2.6 and will also be removed in Python 3.8. | |
| 26 Still, there are many cases in which access to OS distribution information | |
| 27 is needed. See `Python issue 1322 <https://bugs.python.org/issue1322>`_ for | |
| 28 more information. | |
| 29 """ | |
| 30 | |
| 31 import os | |
| 32 import re | |
| 33 import sys | |
| 34 import json | |
| 35 import shlex | |
| 36 import logging | |
| 37 import argparse | |
| 38 import subprocess | |
| 39 | |
| 40 | |
| 41 _UNIXCONFDIR = os.environ.get('UNIXCONFDIR', '/etc') | |
| 42 _OS_RELEASE_BASENAME = 'os-release' | |
| 43 | |
| 44 #: Translation table for normalizing the "ID" attribute defined in os-release | |
| 45 #: files, for use by the :func:`distro.id` method. | |
| 46 #: | |
| 47 #: * Key: Value as defined in the os-release file, translated to lower case, | |
| 48 #: with blanks translated to underscores. | |
| 49 #: | |
| 50 #: * Value: Normalized value. | |
| 51 NORMALIZED_OS_ID = { | |
| 52 'ol': 'oracle', # Oracle Enterprise Linux | |
| 53 } | |
| 54 | |
| 55 #: Translation table for normalizing the "Distributor ID" attribute returned by | |
| 56 #: the lsb_release command, for use by the :func:`distro.id` method. | |
| 57 #: | |
| 58 #: * Key: Value as returned by the lsb_release command, translated to lower | |
| 59 #: case, with blanks translated to underscores. | |
| 60 #: | |
| 61 #: * Value: Normalized value. | |
| 62 NORMALIZED_LSB_ID = { | |
| 63 'enterpriseenterprise': 'oracle', # Oracle Enterprise Linux | |
| 64 'redhatenterpriseworkstation': 'rhel', # RHEL 6, 7 Workstation | |
| 65 'redhatenterpriseserver': 'rhel', # RHEL 6, 7 Server | |
| 66 } | |
| 67 | |
| 68 #: Translation table for normalizing the distro ID derived from the file name | |
| 69 #: of distro release files, for use by the :func:`distro.id` method. | |
| 70 #: | |
| 71 #: * Key: Value as derived from the file name of a distro release file, | |
| 72 #: translated to lower case, with blanks translated to underscores. | |
| 73 #: | |
| 74 #: * Value: Normalized value. | |
| 75 NORMALIZED_DISTRO_ID = { | |
| 76 'redhat': 'rhel', # RHEL 6.x, 7.x | |
| 77 } | |
| 78 | |
| 79 # Pattern for content of distro release file (reversed) | |
| 80 _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile( | |
| 81 r'(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)') | |
| 82 | |
| 83 # Pattern for base file name of distro release file | |
| 84 _DISTRO_RELEASE_BASENAME_PATTERN = re.compile( | |
| 85 r'(\w+)[-_](release|version)$') | |
| 86 | |
| 87 # Base file names to be ignored when searching for distro release file | |
| 88 _DISTRO_RELEASE_IGNORE_BASENAMES = ( | |
| 89 'debian_version', | |
| 90 'lsb-release', | |
| 91 'oem-release', | |
| 92 _OS_RELEASE_BASENAME, | |
| 93 'system-release' | |
| 94 ) | |
| 95 | |
| 96 | |
| 97 def linux_distribution(full_distribution_name=True): | |
| 98 """ | |
| 99 Return information about the current OS distribution as a tuple | |
| 100 ``(id_name, version, codename)`` with items as follows: | |
| 101 | |
| 102 * ``id_name``: If *full_distribution_name* is false, the result of | |
| 103 :func:`distro.id`. Otherwise, the result of :func:`distro.name`. | |
| 104 | |
| 105 * ``version``: The result of :func:`distro.version`. | |
| 106 | |
| 107 * ``codename``: The result of :func:`distro.codename`. | |
| 108 | |
| 109 The interface of this function is compatible with the original | |
| 110 :py:func:`platform.linux_distribution` function, supporting a subset of | |
| 111 its parameters. | |
| 112 | |
| 113 The data it returns may not exactly be the same, because it uses more data | |
| 114 sources than the original function, and that may lead to different data if | |
| 115 the OS distribution is not consistent across multiple data sources it | |
| 116 provides (there are indeed such distributions ...). | |
| 117 | |
| 118 Another reason for differences is the fact that the :func:`distro.id` | |
| 119 method normalizes the distro ID string to a reliable machine-readable value | |
| 120 for a number of popular OS distributions. | |
| 121 """ | |
| 122 return _distro.linux_distribution(full_distribution_name) | |
| 123 | |
| 124 | |
| 125 def id(): | |
| 126 """ | |
| 127 Return the distro ID of the current distribution, as a | |
| 128 machine-readable string. | |
| 129 | |
| 130 For a number of OS distributions, the returned distro ID value is | |
| 131 *reliable*, in the sense that it is documented and that it does not change | |
| 132 across releases of the distribution. | |
| 133 | |
| 134 This package maintains the following reliable distro ID values: | |
| 135 | |
| 136 ============== ========================================= | |
| 137 Distro ID Distribution | |
| 138 ============== ========================================= | |
| 139 "ubuntu" Ubuntu | |
| 140 "debian" Debian | |
| 141 "rhel" RedHat Enterprise Linux | |
| 142 "centos" CentOS | |
| 143 "fedora" Fedora | |
| 144 "sles" SUSE Linux Enterprise Server | |
| 145 "opensuse" openSUSE | |
| 146 "amazon" Amazon Linux | |
| 147 "arch" Arch Linux | |
| 148 "cloudlinux" CloudLinux OS | |
| 149 "exherbo" Exherbo Linux | |
| 150 "gentoo" GenToo Linux | |
| 151 "ibm_powerkvm" IBM PowerKVM | |
| 152 "kvmibm" KVM for IBM z Systems | |
| 153 "linuxmint" Linux Mint | |
| 154 "mageia" Mageia | |
| 155 "mandriva" Mandriva Linux | |
| 156 "parallels" Parallels | |
| 157 "pidora" Pidora | |
| 158 "raspbian" Raspbian | |
| 159 "oracle" Oracle Linux (and Oracle Enterprise Linux) | |
| 160 "scientific" Scientific Linux | |
| 161 "slackware" Slackware | |
| 162 "xenserver" XenServer | |
| 163 "openbsd" OpenBSD | |
| 164 "netbsd" NetBSD | |
| 165 "freebsd" FreeBSD | |
| 166 ============== ========================================= | |
| 167 | |
| 168 If you have a need to get distros for reliable IDs added into this set, | |
| 169 or if you find that the :func:`distro.id` function returns a different | |
| 170 distro ID for one of the listed distros, please create an issue in the | |
| 171 `distro issue tracker`_. | |
| 172 | |
| 173 **Lookup hierarchy and transformations:** | |
| 174 | |
| 175 First, the ID is obtained from the following sources, in the specified | |
| 176 order. The first available and non-empty value is used: | |
| 177 | |
| 178 * the value of the "ID" attribute of the os-release file, | |
| 179 | |
| 180 * the value of the "Distributor ID" attribute returned by the lsb_release | |
| 181 command, | |
| 182 | |
| 183 * the first part of the file name of the distro release file, | |
| 184 | |
| 185 The so determined ID value then passes the following transformations, | |
| 186 before it is returned by this method: | |
| 187 | |
| 188 * it is translated to lower case, | |
| 189 | |
| 190 * blanks (which should not be there anyway) are translated to underscores, | |
| 191 | |
| 192 * a normalization of the ID is performed, based upon | |
| 193 `normalization tables`_. The purpose of this normalization is to ensure | |
| 194 that the ID is as reliable as possible, even across incompatible changes | |
| 195 in the OS distributions. A common reason for an incompatible change is | |
| 196 the addition of an os-release file, or the addition of the lsb_release | |
| 197 command, with ID values that differ from what was previously determined | |
| 198 from the distro release file name. | |
| 199 """ | |
| 200 return _distro.id() | |
| 201 | |
| 202 | |
| 203 def name(pretty=False): | |
| 204 """ | |
| 205 Return the name of the current OS distribution, as a human-readable | |
| 206 string. | |
| 207 | |
| 208 If *pretty* is false, the name is returned without version or codename. | |
| 209 (e.g. "CentOS Linux") | |
| 210 | |
| 211 If *pretty* is true, the version and codename are appended. | |
| 212 (e.g. "CentOS Linux 7.1.1503 (Core)") | |
| 213 | |
| 214 **Lookup hierarchy:** | |
| 215 | |
| 216 The name is obtained from the following sources, in the specified order. | |
| 217 The first available and non-empty value is used: | |
| 218 | |
| 219 * If *pretty* is false: | |
| 220 | |
| 221 - the value of the "NAME" attribute of the os-release file, | |
| 222 | |
| 223 - the value of the "Distributor ID" attribute returned by the lsb_release | |
| 224 command, | |
| 225 | |
| 226 - the value of the "<name>" field of the distro release file. | |
| 227 | |
| 228 * If *pretty* is true: | |
| 229 | |
| 230 - the value of the "PRETTY_NAME" attribute of the os-release file, | |
| 231 | |
| 232 - the value of the "Description" attribute returned by the lsb_release | |
| 233 command, | |
| 234 | |
| 235 - the value of the "<name>" field of the distro release file, appended | |
| 236 with the value of the pretty version ("<version_id>" and "<codename>" | |
| 237 fields) of the distro release file, if available. | |
| 238 """ | |
| 239 return _distro.name(pretty) | |
| 240 | |
| 241 | |
| 242 def version(pretty=False, best=False): | |
| 243 """ | |
| 244 Return the version of the current OS distribution, as a human-readable | |
| 245 string. | |
| 246 | |
| 247 If *pretty* is false, the version is returned without codename (e.g. | |
| 248 "7.0"). | |
| 249 | |
| 250 If *pretty* is true, the codename in parenthesis is appended, if the | |
| 251 codename is non-empty (e.g. "7.0 (Maipo)"). | |
| 252 | |
| 253 Some distributions provide version numbers with different precisions in | |
| 254 the different sources of distribution information. Examining the different | |
| 255 sources in a fixed priority order does not always yield the most precise | |
| 256 version (e.g. for Debian 8.2, or CentOS 7.1). | |
| 257 | |
| 258 The *best* parameter can be used to control the approach for the returned | |
| 259 version: | |
| 260 | |
| 261 If *best* is false, the first non-empty version number in priority order of | |
| 262 the examined sources is returned. | |
| 263 | |
| 264 If *best* is true, the most precise version number out of all examined | |
| 265 sources is returned. | |
| 266 | |
| 267 **Lookup hierarchy:** | |
| 268 | |
| 269 In all cases, the version number is obtained from the following sources. | |
| 270 If *best* is false, this order represents the priority order: | |
| 271 | |
| 272 * the value of the "VERSION_ID" attribute of the os-release file, | |
| 273 * the value of the "Release" attribute returned by the lsb_release | |
| 274 command, | |
| 275 * the version number parsed from the "<version_id>" field of the first line | |
| 276 of the distro release file, | |
| 277 * the version number parsed from the "PRETTY_NAME" attribute of the | |
| 278 os-release file, if it follows the format of the distro release files. | |
| 279 * the version number parsed from the "Description" attribute returned by | |
| 280 the lsb_release command, if it follows the format of the distro release | |
| 281 files. | |
| 282 """ | |
| 283 return _distro.version(pretty, best) | |
| 284 | |
| 285 | |
| 286 def version_parts(best=False): | |
| 287 """ | |
| 288 Return the version of the current OS distribution as a tuple | |
| 289 ``(major, minor, build_number)`` with items as follows: | |
| 290 | |
| 291 * ``major``: The result of :func:`distro.major_version`. | |
| 292 | |
| 293 * ``minor``: The result of :func:`distro.minor_version`. | |
| 294 | |
| 295 * ``build_number``: The result of :func:`distro.build_number`. | |
| 296 | |
| 297 For a description of the *best* parameter, see the :func:`distro.version` | |
| 298 method. | |
| 299 """ | |
| 300 return _distro.version_parts(best) | |
| 301 | |
| 302 | |
| 303 def major_version(best=False): | |
| 304 """ | |
| 305 Return the major version of the current OS distribution, as a string, | |
| 306 if provided. | |
| 307 Otherwise, the empty string is returned. The major version is the first | |
| 308 part of the dot-separated version string. | |
| 309 | |
| 310 For a description of the *best* parameter, see the :func:`distro.version` | |
| 311 method. | |
| 312 """ | |
| 313 return _distro.major_version(best) | |
| 314 | |
| 315 | |
| 316 def minor_version(best=False): | |
| 317 """ | |
| 318 Return the minor version of the current OS distribution, as a string, | |
| 319 if provided. | |
| 320 Otherwise, the empty string is returned. The minor version is the second | |
| 321 part of the dot-separated version string. | |
| 322 | |
| 323 For a description of the *best* parameter, see the :func:`distro.version` | |
| 324 method. | |
| 325 """ | |
| 326 return _distro.minor_version(best) | |
| 327 | |
| 328 | |
| 329 def build_number(best=False): | |
| 330 """ | |
| 331 Return the build number of the current OS distribution, as a string, | |
| 332 if provided. | |
| 333 Otherwise, the empty string is returned. The build number is the third part | |
| 334 of the dot-separated version string. | |
| 335 | |
| 336 For a description of the *best* parameter, see the :func:`distro.version` | |
| 337 method. | |
| 338 """ | |
| 339 return _distro.build_number(best) | |
| 340 | |
| 341 | |
| 342 def like(): | |
| 343 """ | |
| 344 Return a space-separated list of distro IDs of distributions that are | |
| 345 closely related to the current OS distribution in regards to packaging | |
| 346 and programming interfaces, for example distributions the current | |
| 347 distribution is a derivative from. | |
| 348 | |
| 349 **Lookup hierarchy:** | |
| 350 | |
| 351 This information item is only provided by the os-release file. | |
| 352 For details, see the description of the "ID_LIKE" attribute in the | |
| 353 `os-release man page | |
| 354 <http://www.freedesktop.org/software/systemd/man/os-release.html>`_. | |
| 355 """ | |
| 356 return _distro.like() | |
| 357 | |
| 358 | |
| 359 def codename(): | |
| 360 """ | |
| 361 Return the codename for the release of the current OS distribution, | |
| 362 as a string. | |
| 363 | |
| 364 If the distribution does not have a codename, an empty string is returned. | |
| 365 | |
| 366 Note that the returned codename is not always really a codename. For | |
| 367 example, openSUSE returns "x86_64". This function does not handle such | |
| 368 cases in any special way and just returns the string it finds, if any. | |
| 369 | |
| 370 **Lookup hierarchy:** | |
| 371 | |
| 372 * the codename within the "VERSION" attribute of the os-release file, if | |
| 373 provided, | |
| 374 | |
| 375 * the value of the "Codename" attribute returned by the lsb_release | |
| 376 command, | |
| 377 | |
| 378 * the value of the "<codename>" field of the distro release file. | |
| 379 """ | |
| 380 return _distro.codename() | |
| 381 | |
| 382 | |
| 383 def info(pretty=False, best=False): | |
| 384 """ | |
| 385 Return certain machine-readable information items about the current OS | |
| 386 distribution in a dictionary, as shown in the following example: | |
| 387 | |
| 388 .. sourcecode:: python | |
| 389 | |
| 390 { | |
| 391 'id': 'rhel', | |
| 392 'version': '7.0', | |
| 393 'version_parts': { | |
| 394 'major': '7', | |
| 395 'minor': '0', | |
| 396 'build_number': '' | |
| 397 }, | |
| 398 'like': 'fedora', | |
| 399 'codename': 'Maipo' | |
| 400 } | |
| 401 | |
| 402 The dictionary structure and keys are always the same, regardless of which | |
| 403 information items are available in the underlying data sources. The values | |
| 404 for the various keys are as follows: | |
| 405 | |
| 406 * ``id``: The result of :func:`distro.id`. | |
| 407 | |
| 408 * ``version``: The result of :func:`distro.version`. | |
| 409 | |
| 410 * ``version_parts -> major``: The result of :func:`distro.major_version`. | |
| 411 | |
| 412 * ``version_parts -> minor``: The result of :func:`distro.minor_version`. | |
| 413 | |
| 414 * ``version_parts -> build_number``: The result of | |
| 415 :func:`distro.build_number`. | |
| 416 | |
| 417 * ``like``: The result of :func:`distro.like`. | |
| 418 | |
| 419 * ``codename``: The result of :func:`distro.codename`. | |
| 420 | |
| 421 For a description of the *pretty* and *best* parameters, see the | |
| 422 :func:`distro.version` method. | |
| 423 """ | |
| 424 return _distro.info(pretty, best) | |
| 425 | |
| 426 | |
| 427 def os_release_info(): | |
| 428 """ | |
| 429 Return a dictionary containing key-value pairs for the information items | |
| 430 from the os-release file data source of the current OS distribution. | |
| 431 | |
| 432 See `os-release file`_ for details about these information items. | |
| 433 """ | |
| 434 return _distro.os_release_info() | |
| 435 | |
| 436 | |
| 437 def lsb_release_info(): | |
| 438 """ | |
| 439 Return a dictionary containing key-value pairs for the information items | |
| 440 from the lsb_release command data source of the current OS distribution. | |
| 441 | |
| 442 See `lsb_release command output`_ for details about these information | |
| 443 items. | |
| 444 """ | |
| 445 return _distro.lsb_release_info() | |
| 446 | |
| 447 | |
| 448 def distro_release_info(): | |
| 449 """ | |
| 450 Return a dictionary containing key-value pairs for the information items | |
| 451 from the distro release file data source of the current OS distribution. | |
| 452 | |
| 453 See `distro release file`_ for details about these information items. | |
| 454 """ | |
| 455 return _distro.distro_release_info() | |
| 456 | |
| 457 | |
| 458 def uname_info(): | |
| 459 """ | |
| 460 Return a dictionary containing key-value pairs for the information items | |
| 461 from the distro release file data source of the current OS distribution. | |
| 462 """ | |
| 463 return _distro.uname_info() | |
| 464 | |
| 465 | |
| 466 def os_release_attr(attribute): | |
| 467 """ | |
| 468 Return a single named information item from the os-release file data source | |
| 469 of the current OS distribution. | |
| 470 | |
| 471 Parameters: | |
| 472 | |
| 473 * ``attribute`` (string): Key of the information item. | |
| 474 | |
| 475 Returns: | |
| 476 | |
| 477 * (string): Value of the information item, if the item exists. | |
| 478 The empty string, if the item does not exist. | |
| 479 | |
| 480 See `os-release file`_ for details about these information items. | |
| 481 """ | |
| 482 return _distro.os_release_attr(attribute) | |
| 483 | |
| 484 | |
| 485 def lsb_release_attr(attribute): | |
| 486 """ | |
| 487 Return a single named information item from the lsb_release command output | |
| 488 data source of the current OS distribution. | |
| 489 | |
| 490 Parameters: | |
| 491 | |
| 492 * ``attribute`` (string): Key of the information item. | |
| 493 | |
| 494 Returns: | |
| 495 | |
| 496 * (string): Value of the information item, if the item exists. | |
| 497 The empty string, if the item does not exist. | |
| 498 | |
| 499 See `lsb_release command output`_ for details about these information | |
| 500 items. | |
| 501 """ | |
| 502 return _distro.lsb_release_attr(attribute) | |
| 503 | |
| 504 | |
| 505 def distro_release_attr(attribute): | |
| 506 """ | |
| 507 Return a single named information item from the distro release file | |
| 508 data source of the current OS distribution. | |
| 509 | |
| 510 Parameters: | |
| 511 | |
| 512 * ``attribute`` (string): Key of the information item. | |
| 513 | |
| 514 Returns: | |
| 515 | |
| 516 * (string): Value of the information item, if the item exists. | |
| 517 The empty string, if the item does not exist. | |
| 518 | |
| 519 See `distro release file`_ for details about these information items. | |
| 520 """ | |
| 521 return _distro.distro_release_attr(attribute) | |
| 522 | |
| 523 | |
| 524 def uname_attr(attribute): | |
| 525 """ | |
| 526 Return a single named information item from the distro release file | |
| 527 data source of the current OS distribution. | |
| 528 | |
| 529 Parameters: | |
| 530 | |
| 531 * ``attribute`` (string): Key of the information item. | |
| 532 | |
| 533 Returns: | |
| 534 | |
| 535 * (string): Value of the information item, if the item exists. | |
| 536 The empty string, if the item does not exist. | |
| 537 """ | |
| 538 return _distro.uname_attr(attribute) | |
| 539 | |
| 540 | |
| 541 class cached_property(object): | |
| 542 """A version of @property which caches the value. On access, it calls the | |
| 543 underlying function and sets the value in `__dict__` so future accesses | |
| 544 will not re-call the property. | |
| 545 """ | |
| 546 def __init__(self, f): | |
| 547 self._fname = f.__name__ | |
| 548 self._f = f | |
| 549 | |
| 550 def __get__(self, obj, owner): | |
| 551 assert obj is not None, 'call {} on an instance'.format(self._fname) | |
| 552 ret = obj.__dict__[self._fname] = self._f(obj) | |
| 553 return ret | |
| 554 | |
| 555 | |
| 556 class LinuxDistribution(object): | |
| 557 """ | |
| 558 Provides information about a OS distribution. | |
| 559 | |
| 560 This package creates a private module-global instance of this class with | |
| 561 default initialization arguments, that is used by the | |
| 562 `consolidated accessor functions`_ and `single source accessor functions`_. | |
| 563 By using default initialization arguments, that module-global instance | |
| 564 returns data about the current OS distribution (i.e. the distro this | |
| 565 package runs on). | |
| 566 | |
| 567 Normally, it is not necessary to create additional instances of this class. | |
| 568 However, in situations where control is needed over the exact data sources | |
| 569 that are used, instances of this class can be created with a specific | |
| 570 distro release file, or a specific os-release file, or without invoking the | |
| 571 lsb_release command. | |
| 572 """ | |
| 573 | |
| 574 def __init__(self, | |
| 575 include_lsb=True, | |
| 576 os_release_file='', | |
| 577 distro_release_file='', | |
| 578 include_uname=True): | |
| 579 """ | |
| 580 The initialization method of this class gathers information from the | |
| 581 available data sources, and stores that in private instance attributes. | |
| 582 Subsequent access to the information items uses these private instance | |
| 583 attributes, so that the data sources are read only once. | |
| 584 | |
| 585 Parameters: | |
| 586 | |
| 587 * ``include_lsb`` (bool): Controls whether the | |
| 588 `lsb_release command output`_ is included as a data source. | |
| 589 | |
| 590 If the lsb_release command is not available in the program execution | |
| 591 path, the data source for the lsb_release command will be empty. | |
| 592 | |
| 593 * ``os_release_file`` (string): The path name of the | |
| 594 `os-release file`_ that is to be used as a data source. | |
| 595 | |
| 596 An empty string (the default) will cause the default path name to | |
| 597 be used (see `os-release file`_ for details). | |
| 598 | |
| 599 If the specified or defaulted os-release file does not exist, the | |
| 600 data source for the os-release file will be empty. | |
| 601 | |
| 602 * ``distro_release_file`` (string): The path name of the | |
| 603 `distro release file`_ that is to be used as a data source. | |
| 604 | |
| 605 An empty string (the default) will cause a default search algorithm | |
| 606 to be used (see `distro release file`_ for details). | |
| 607 | |
| 608 If the specified distro release file does not exist, or if no default | |
| 609 distro release file can be found, the data source for the distro | |
| 610 release file will be empty. | |
| 611 | |
| 612 * ``include_name`` (bool): Controls whether uname command output is | |
| 613 included as a data source. If the uname command is not available in | |
| 614 the program execution path the data source for the uname command will | |
| 615 be empty. | |
| 616 | |
| 617 Public instance attributes: | |
| 618 | |
| 619 * ``os_release_file`` (string): The path name of the | |
| 620 `os-release file`_ that is actually used as a data source. The | |
| 621 empty string if no distro release file is used as a data source. | |
| 622 | |
| 623 * ``distro_release_file`` (string): The path name of the | |
| 624 `distro release file`_ that is actually used as a data source. The | |
| 625 empty string if no distro release file is used as a data source. | |
| 626 | |
| 627 * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter. | |
| 628 This controls whether the lsb information will be loaded. | |
| 629 | |
| 630 * ``include_uname`` (bool): The result of the ``include_uname`` | |
| 631 parameter. This controls whether the uname information will | |
| 632 be loaded. | |
| 633 | |
| 634 Raises: | |
| 635 | |
| 636 * :py:exc:`IOError`: Some I/O issue with an os-release file or distro | |
| 637 release file. | |
| 638 | |
| 639 * :py:exc:`subprocess.CalledProcessError`: The lsb_release command had | |
| 640 some issue (other than not being available in the program execution | |
| 641 path). | |
| 642 | |
| 643 * :py:exc:`UnicodeError`: A data source has unexpected characters or | |
| 644 uses an unexpected encoding. | |
| 645 """ | |
| 646 self.os_release_file = os_release_file or \ | |
| 647 os.path.join(_UNIXCONFDIR, _OS_RELEASE_BASENAME) | |
| 648 self.distro_release_file = distro_release_file or '' # updated later | |
| 649 self.include_lsb = include_lsb | |
| 650 self.include_uname = include_uname | |
| 651 | |
| 652 def __repr__(self): | |
| 653 """Return repr of all info | |
| 654 """ | |
| 655 return \ | |
| 656 "LinuxDistribution(" \ | |
| 657 "os_release_file={self.os_release_file!r}, " \ | |
| 658 "distro_release_file={self.distro_release_file!r}, " \ | |
| 659 "include_lsb={self.include_lsb!r}, " \ | |
| 660 "include_uname={self.include_uname!r}, " \ | |
| 661 "_os_release_info={self._os_release_info!r}, " \ | |
| 662 "_lsb_release_info={self._lsb_release_info!r}, " \ | |
| 663 "_distro_release_info={self._distro_release_info!r}, " \ | |
| 664 "_uname_info={self._uname_info!r})".format( | |
| 665 self=self) | |
| 666 | |
| 667 def linux_distribution(self, full_distribution_name=True): | |
| 668 """ | |
| 669 Return information about the OS distribution that is compatible | |
| 670 with Python's :func:`platform.linux_distribution`, supporting a subset | |
| 671 of its parameters. | |
| 672 | |
| 673 For details, see :func:`distro.linux_distribution`. | |
| 674 """ | |
| 675 return ( | |
| 676 self.name() if full_distribution_name else self.id(), | |
| 677 self.version(), | |
| 678 self.codename() | |
| 679 ) | |
| 680 | |
| 681 def id(self): | |
| 682 """Return the distro ID of the OS distribution, as a string. | |
| 683 | |
| 684 For details, see :func:`distro.id`. | |
| 685 """ | |
| 686 def normalize(distro_id, table): | |
| 687 distro_id = distro_id.lower().replace(' ', '_') | |
| 688 return table.get(distro_id, distro_id) | |
| 689 | |
| 690 distro_id = self.os_release_attr('id') | |
| 691 if distro_id: | |
| 692 return normalize(distro_id, NORMALIZED_OS_ID) | |
| 693 | |
| 694 distro_id = self.lsb_release_attr('distributor_id') | |
| 695 if distro_id: | |
| 696 return normalize(distro_id, NORMALIZED_LSB_ID) | |
| 697 | |
| 698 distro_id = self.distro_release_attr('id') | |
| 699 if distro_id: | |
| 700 return normalize(distro_id, NORMALIZED_DISTRO_ID) | |
| 701 | |
| 702 distro_id = self.uname_attr('id') | |
| 703 if distro_id: | |
| 704 return normalize(distro_id, NORMALIZED_DISTRO_ID) | |
| 705 | |
| 706 return '' | |
| 707 | |
| 708 def name(self, pretty=False): | |
| 709 """ | |
| 710 Return the name of the OS distribution, as a string. | |
| 711 | |
| 712 For details, see :func:`distro.name`. | |
| 713 """ | |
| 714 name = self.os_release_attr('name') \ | |
| 715 or self.lsb_release_attr('distributor_id') \ | |
| 716 or self.distro_release_attr('name') \ | |
| 717 or self.uname_attr('name') | |
| 718 if pretty: | |
| 719 name = self.os_release_attr('pretty_name') \ | |
| 720 or self.lsb_release_attr('description') | |
| 721 if not name: | |
| 722 name = self.distro_release_attr('name') \ | |
| 723 or self.uname_attr('name') | |
| 724 version = self.version(pretty=True) | |
| 725 if version: | |
| 726 name = name + ' ' + version | |
| 727 return name or '' | |
| 728 | |
| 729 def version(self, pretty=False, best=False): | |
| 730 """ | |
| 731 Return the version of the OS distribution, as a string. | |
| 732 | |
| 733 For details, see :func:`distro.version`. | |
| 734 """ | |
| 735 versions = [ | |
| 736 self.os_release_attr('version_id'), | |
| 737 self.lsb_release_attr('release'), | |
| 738 self.distro_release_attr('version_id'), | |
| 739 self._parse_distro_release_content( | |
| 740 self.os_release_attr('pretty_name')).get('version_id', ''), | |
| 741 self._parse_distro_release_content( | |
| 742 self.lsb_release_attr('description')).get('version_id', ''), | |
| 743 self.uname_attr('release') | |
| 744 ] | |
| 745 version = '' | |
| 746 if best: | |
| 747 # This algorithm uses the last version in priority order that has | |
| 748 # the best precision. If the versions are not in conflict, that | |
| 749 # does not matter; otherwise, using the last one instead of the | |
| 750 # first one might be considered a surprise. | |
| 751 for v in versions: | |
| 752 if v.count(".") > version.count(".") or version == '': | |
| 753 version = v | |
| 754 else: | |
| 755 for v in versions: | |
| 756 if v != '': | |
| 757 version = v | |
| 758 break | |
| 759 if pretty and version and self.codename(): | |
| 760 version = u'{0} ({1})'.format(version, self.codename()) | |
| 761 return version | |
| 762 | |
| 763 def version_parts(self, best=False): | |
| 764 """ | |
| 765 Return the version of the OS distribution, as a tuple of version | |
| 766 numbers. | |
| 767 | |
| 768 For details, see :func:`distro.version_parts`. | |
| 769 """ | |
| 770 version_str = self.version(best=best) | |
| 771 if version_str: | |
| 772 version_regex = re.compile(r'(\d+)\.?(\d+)?\.?(\d+)?') | |
| 773 matches = version_regex.match(version_str) | |
| 774 if matches: | |
| 775 major, minor, build_number = matches.groups() | |
| 776 return major, minor or '', build_number or '' | |
| 777 return '', '', '' | |
| 778 | |
| 779 def major_version(self, best=False): | |
| 780 """ | |
| 781 Return the major version number of the current distribution. | |
| 782 | |
| 783 For details, see :func:`distro.major_version`. | |
| 784 """ | |
| 785 return self.version_parts(best)[0] | |
| 786 | |
| 787 def minor_version(self, best=False): | |
| 788 """ | |
| 789 Return the minor version number of the current distribution. | |
| 790 | |
| 791 For details, see :func:`distro.minor_version`. | |
| 792 """ | |
| 793 return self.version_parts(best)[1] | |
| 794 | |
| 795 def build_number(self, best=False): | |
| 796 """ | |
| 797 Return the build number of the current distribution. | |
| 798 | |
| 799 For details, see :func:`distro.build_number`. | |
| 800 """ | |
| 801 return self.version_parts(best)[2] | |
| 802 | |
| 803 def like(self): | |
| 804 """ | |
| 805 Return the IDs of distributions that are like the OS distribution. | |
| 806 | |
| 807 For details, see :func:`distro.like`. | |
| 808 """ | |
| 809 return self.os_release_attr('id_like') or '' | |
| 810 | |
| 811 def codename(self): | |
| 812 """ | |
| 813 Return the codename of the OS distribution. | |
| 814 | |
| 815 For details, see :func:`distro.codename`. | |
| 816 """ | |
| 817 try: | |
| 818 # Handle os_release specially since distros might purposefully set | |
| 819 # this to empty string to have no codename | |
| 820 return self._os_release_info['codename'] | |
| 821 except KeyError: | |
| 822 return self.lsb_release_attr('codename') \ | |
| 823 or self.distro_release_attr('codename') \ | |
| 824 or '' | |
| 825 | |
| 826 def info(self, pretty=False, best=False): | |
| 827 """ | |
| 828 Return certain machine-readable information about the OS | |
| 829 distribution. | |
| 830 | |
| 831 For details, see :func:`distro.info`. | |
| 832 """ | |
| 833 return dict( | |
| 834 id=self.id(), | |
| 835 version=self.version(pretty, best), | |
| 836 version_parts=dict( | |
| 837 major=self.major_version(best), | |
| 838 minor=self.minor_version(best), | |
| 839 build_number=self.build_number(best) | |
| 840 ), | |
| 841 like=self.like(), | |
| 842 codename=self.codename(), | |
| 843 ) | |
| 844 | |
| 845 def os_release_info(self): | |
| 846 """ | |
| 847 Return a dictionary containing key-value pairs for the information | |
| 848 items from the os-release file data source of the OS distribution. | |
| 849 | |
| 850 For details, see :func:`distro.os_release_info`. | |
| 851 """ | |
| 852 return self._os_release_info | |
| 853 | |
| 854 def lsb_release_info(self): | |
| 855 """ | |
| 856 Return a dictionary containing key-value pairs for the information | |
| 857 items from the lsb_release command data source of the OS | |
| 858 distribution. | |
| 859 | |
| 860 For details, see :func:`distro.lsb_release_info`. | |
| 861 """ | |
| 862 return self._lsb_release_info | |
| 863 | |
| 864 def distro_release_info(self): | |
| 865 """ | |
| 866 Return a dictionary containing key-value pairs for the information | |
| 867 items from the distro release file data source of the OS | |
| 868 distribution. | |
| 869 | |
| 870 For details, see :func:`distro.distro_release_info`. | |
| 871 """ | |
| 872 return self._distro_release_info | |
| 873 | |
| 874 def uname_info(self): | |
| 875 """ | |
| 876 Return a dictionary containing key-value pairs for the information | |
| 877 items from the uname command data source of the OS distribution. | |
| 878 | |
| 879 For details, see :func:`distro.uname_info`. | |
| 880 """ | |
| 881 return self._uname_info | |
| 882 | |
| 883 def os_release_attr(self, attribute): | |
| 884 """ | |
| 885 Return a single named information item from the os-release file data | |
| 886 source of the OS distribution. | |
| 887 | |
| 888 For details, see :func:`distro.os_release_attr`. | |
| 889 """ | |
| 890 return self._os_release_info.get(attribute, '') | |
| 891 | |
| 892 def lsb_release_attr(self, attribute): | |
| 893 """ | |
| 894 Return a single named information item from the lsb_release command | |
| 895 output data source of the OS distribution. | |
| 896 | |
| 897 For details, see :func:`distro.lsb_release_attr`. | |
| 898 """ | |
| 899 return self._lsb_release_info.get(attribute, '') | |
| 900 | |
| 901 def distro_release_attr(self, attribute): | |
| 902 """ | |
| 903 Return a single named information item from the distro release file | |
| 904 data source of the OS distribution. | |
| 905 | |
| 906 For details, see :func:`distro.distro_release_attr`. | |
| 907 """ | |
| 908 return self._distro_release_info.get(attribute, '') | |
| 909 | |
| 910 def uname_attr(self, attribute): | |
| 911 """ | |
| 912 Return a single named information item from the uname command | |
| 913 output data source of the OS distribution. | |
| 914 | |
| 915 For details, see :func:`distro.uname_release_attr`. | |
| 916 """ | |
| 917 return self._uname_info.get(attribute, '') | |
| 918 | |
| 919 @cached_property | |
| 920 def _os_release_info(self): | |
| 921 """ | |
| 922 Get the information items from the specified os-release file. | |
| 923 | |
| 924 Returns: | |
| 925 A dictionary containing all information items. | |
| 926 """ | |
| 927 if os.path.isfile(self.os_release_file): | |
| 928 with open(self.os_release_file) as release_file: | |
| 929 return self._parse_os_release_content(release_file) | |
| 930 return {} | |
| 931 | |
| 932 @staticmethod | |
| 933 def _parse_os_release_content(lines): | |
| 934 """ | |
| 935 Parse the lines of an os-release file. | |
| 936 | |
| 937 Parameters: | |
| 938 | |
| 939 * lines: Iterable through the lines in the os-release file. | |
| 940 Each line must be a unicode string or a UTF-8 encoded byte | |
| 941 string. | |
| 942 | |
| 943 Returns: | |
| 944 A dictionary containing all information items. | |
| 945 """ | |
| 946 props = {} | |
| 947 lexer = shlex.shlex(lines, posix=True) | |
| 948 lexer.whitespace_split = True | |
| 949 | |
| 950 # The shlex module defines its `wordchars` variable using literals, | |
| 951 # making it dependent on the encoding of the Python source file. | |
| 952 # In Python 2.6 and 2.7, the shlex source file is encoded in | |
| 953 # 'iso-8859-1', and the `wordchars` variable is defined as a byte | |
| 954 # string. This causes a UnicodeDecodeError to be raised when the | |
| 955 # parsed content is a unicode object. The following fix resolves that | |
| 956 # (... but it should be fixed in shlex...): | |
| 957 if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes): | |
| 958 lexer.wordchars = lexer.wordchars.decode('iso-8859-1') | |
| 959 | |
| 960 tokens = list(lexer) | |
| 961 for token in tokens: | |
| 962 # At this point, all shell-like parsing has been done (i.e. | |
| 963 # comments processed, quotes and backslash escape sequences | |
| 964 # processed, multi-line values assembled, trailing newlines | |
| 965 # stripped, etc.), so the tokens are now either: | |
| 966 # * variable assignments: var=value | |
| 967 # * commands or their arguments (not allowed in os-release) | |
| 968 if '=' in token: | |
| 969 k, v = token.split('=', 1) | |
| 970 if isinstance(v, bytes): | |
| 971 v = v.decode('utf-8') | |
| 972 props[k.lower()] = v | |
| 973 else: | |
| 974 # Ignore any tokens that are not variable assignments | |
| 975 pass | |
| 976 | |
| 977 if 'version_codename' in props: | |
| 978 # os-release added a version_codename field. Use that in | |
| 979 # preference to anything else Note that some distros purposefully | |
| 980 # do not have code names. They should be setting | |
| 981 # version_codename="" | |
| 982 props['codename'] = props['version_codename'] | |
| 983 elif 'ubuntu_codename' in props: | |
| 984 # Same as above but a non-standard field name used on older Ubuntus | |
| 985 props['codename'] = props['ubuntu_codename'] | |
| 986 elif 'version' in props: | |
| 987 # If there is no version_codename, parse it from the version | |
| 988 codename = re.search(r'(\(\D+\))|,(\s+)?\D+', props['version']) | |
| 989 if codename: | |
| 990 codename = codename.group() | |
| 991 codename = codename.strip('()') | |
| 992 codename = codename.strip(',') | |
| 993 codename = codename.strip() | |
| 994 # codename appears within paranthese. | |
| 995 props['codename'] = codename | |
| 996 | |
| 997 return props | |
| 998 | |
| 999 @cached_property | |
| 1000 def _lsb_release_info(self): | |
| 1001 """ | |
| 1002 Get the information items from the lsb_release command output. | |
| 1003 | |
| 1004 Returns: | |
| 1005 A dictionary containing all information items. | |
| 1006 """ | |
| 1007 if not self.include_lsb: | |
| 1008 return {} | |
| 1009 with open(os.devnull, 'w') as devnull: | |
| 1010 try: | |
| 1011 cmd = ('lsb_release', '-a') | |
| 1012 stdout = subprocess.check_output(cmd, stderr=devnull) | |
| 1013 except OSError: # Command not found | |
| 1014 return {} | |
| 1015 content = stdout.decode(sys.getfilesystemencoding()).splitlines() | |
| 1016 return self._parse_lsb_release_content(content) | |
| 1017 | |
| 1018 @staticmethod | |
| 1019 def _parse_lsb_release_content(lines): | |
| 1020 """ | |
| 1021 Parse the output of the lsb_release command. | |
| 1022 | |
| 1023 Parameters: | |
| 1024 | |
| 1025 * lines: Iterable through the lines of the lsb_release output. | |
| 1026 Each line must be a unicode string or a UTF-8 encoded byte | |
| 1027 string. | |
| 1028 | |
| 1029 Returns: | |
| 1030 A dictionary containing all information items. | |
| 1031 """ | |
| 1032 props = {} | |
| 1033 for line in lines: | |
| 1034 kv = line.strip('\n').split(':', 1) | |
| 1035 if len(kv) != 2: | |
| 1036 # Ignore lines without colon. | |
| 1037 continue | |
| 1038 k, v = kv | |
| 1039 props.update({k.replace(' ', '_').lower(): v.strip()}) | |
| 1040 return props | |
| 1041 | |
| 1042 @cached_property | |
| 1043 def _uname_info(self): | |
| 1044 with open(os.devnull, 'w') as devnull: | |
| 1045 try: | |
| 1046 cmd = ('uname', '-rs') | |
| 1047 stdout = subprocess.check_output(cmd, stderr=devnull) | |
| 1048 except OSError: | |
| 1049 return {} | |
| 1050 content = stdout.decode(sys.getfilesystemencoding()).splitlines() | |
| 1051 return self._parse_uname_content(content) | |
| 1052 | |
| 1053 @staticmethod | |
| 1054 def _parse_uname_content(lines): | |
| 1055 props = {} | |
| 1056 match = re.search(r'^([^\s]+)\s+([\d\.]+)', lines[0].strip()) | |
| 1057 if match: | |
| 1058 name, version = match.groups() | |
| 1059 | |
| 1060 # This is to prevent the Linux kernel version from | |
| 1061 # appearing as the 'best' version on otherwise | |
| 1062 # identifiable distributions. | |
| 1063 if name == 'Linux': | |
| 1064 return {} | |
| 1065 props['id'] = name.lower() | |
| 1066 props['name'] = name | |
| 1067 props['release'] = version | |
| 1068 return props | |
| 1069 | |
| 1070 @cached_property | |
| 1071 def _distro_release_info(self): | |
| 1072 """ | |
| 1073 Get the information items from the specified distro release file. | |
| 1074 | |
| 1075 Returns: | |
| 1076 A dictionary containing all information items. | |
| 1077 """ | |
| 1078 if self.distro_release_file: | |
| 1079 # If it was specified, we use it and parse what we can, even if | |
| 1080 # its file name or content does not match the expected pattern. | |
| 1081 distro_info = self._parse_distro_release_file( | |
| 1082 self.distro_release_file) | |
| 1083 basename = os.path.basename(self.distro_release_file) | |
| 1084 # The file name pattern for user-specified distro release files | |
| 1085 # is somewhat more tolerant (compared to when searching for the | |
| 1086 # file), because we want to use what was specified as best as | |
| 1087 # possible. | |
| 1088 match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) | |
| 1089 if 'name' in distro_info \ | |
| 1090 and 'cloudlinux' in distro_info['name'].lower(): | |
| 1091 distro_info['id'] = 'cloudlinux' | |
| 1092 elif match: | |
| 1093 distro_info['id'] = match.group(1) | |
| 1094 return distro_info | |
| 1095 else: | |
| 1096 try: | |
| 1097 basenames = os.listdir(_UNIXCONFDIR) | |
| 1098 # We sort for repeatability in cases where there are multiple | |
| 1099 # distro specific files; e.g. CentOS, Oracle, Enterprise all | |
| 1100 # containing `redhat-release` on top of their own. | |
| 1101 basenames.sort() | |
| 1102 except OSError: | |
| 1103 # This may occur when /etc is not readable but we can't be | |
| 1104 # sure about the *-release files. Check common entries of | |
| 1105 # /etc for information. If they turn out to not be there the | |
| 1106 # error is handled in `_parse_distro_release_file()`. | |
| 1107 basenames = ['SuSE-release', | |
| 1108 'arch-release', | |
| 1109 'base-release', | |
| 1110 'centos-release', | |
| 1111 'fedora-release', | |
| 1112 'gentoo-release', | |
| 1113 'mageia-release', | |
| 1114 'mandrake-release', | |
| 1115 'mandriva-release', | |
| 1116 'mandrivalinux-release', | |
| 1117 'manjaro-release', | |
| 1118 'oracle-release', | |
| 1119 'redhat-release', | |
| 1120 'sl-release', | |
| 1121 'slackware-version'] | |
| 1122 for basename in basenames: | |
| 1123 if basename in _DISTRO_RELEASE_IGNORE_BASENAMES: | |
| 1124 continue | |
| 1125 match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) | |
| 1126 if match: | |
| 1127 filepath = os.path.join(_UNIXCONFDIR, basename) | |
| 1128 distro_info = self._parse_distro_release_file(filepath) | |
| 1129 if 'name' in distro_info: | |
| 1130 # The name is always present if the pattern matches | |
| 1131 self.distro_release_file = filepath | |
| 1132 distro_info['id'] = match.group(1) | |
| 1133 if 'cloudlinux' in distro_info['name'].lower(): | |
| 1134 distro_info['id'] = 'cloudlinux' | |
| 1135 return distro_info | |
| 1136 return {} | |
| 1137 | |
| 1138 def _parse_distro_release_file(self, filepath): | |
| 1139 """ | |
| 1140 Parse a distro release file. | |
| 1141 | |
| 1142 Parameters: | |
| 1143 | |
| 1144 * filepath: Path name of the distro release file. | |
| 1145 | |
| 1146 Returns: | |
| 1147 A dictionary containing all information items. | |
| 1148 """ | |
| 1149 try: | |
| 1150 with open(filepath) as fp: | |
| 1151 # Only parse the first line. For instance, on SLES there | |
| 1152 # are multiple lines. We don't want them... | |
| 1153 return self._parse_distro_release_content(fp.readline()) | |
| 1154 except (OSError, IOError): | |
| 1155 # Ignore not being able to read a specific, seemingly version | |
| 1156 # related file. | |
| 1157 # See https://github.com/nir0s/distro/issues/162 | |
| 1158 return {} | |
| 1159 | |
| 1160 @staticmethod | |
| 1161 def _parse_distro_release_content(line): | |
| 1162 """ | |
| 1163 Parse a line from a distro release file. | |
| 1164 | |
| 1165 Parameters: | |
| 1166 * line: Line from the distro release file. Must be a unicode string | |
| 1167 or a UTF-8 encoded byte string. | |
| 1168 | |
| 1169 Returns: | |
| 1170 A dictionary containing all information items. | |
| 1171 """ | |
| 1172 if isinstance(line, bytes): | |
| 1173 line = line.decode('utf-8') | |
| 1174 matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match( | |
| 1175 line.strip()[::-1]) | |
| 1176 distro_info = {} | |
| 1177 if matches: | |
| 1178 # regexp ensures non-None | |
| 1179 distro_info['name'] = matches.group(3)[::-1] | |
| 1180 if matches.group(2): | |
| 1181 distro_info['version_id'] = matches.group(2)[::-1] | |
| 1182 if matches.group(1): | |
| 1183 distro_info['codename'] = matches.group(1)[::-1] | |
| 1184 elif line: | |
| 1185 distro_info['name'] = line.strip() | |
| 1186 return distro_info | |
| 1187 | |
| 1188 | |
| 1189 _distro = LinuxDistribution() | |
| 1190 | |
| 1191 | |
| 1192 def main(): | |
| 1193 logger = logging.getLogger(__name__) | |
| 1194 logger.setLevel(logging.DEBUG) | |
| 1195 logger.addHandler(logging.StreamHandler(sys.stdout)) | |
| 1196 | |
| 1197 parser = argparse.ArgumentParser(description="OS distro info tool") | |
| 1198 parser.add_argument( | |
| 1199 '--json', | |
| 1200 '-j', | |
| 1201 help="Output in machine readable format", | |
| 1202 action="store_true") | |
| 1203 args = parser.parse_args() | |
| 1204 | |
| 1205 if args.json: | |
| 1206 logger.info(json.dumps(info(), indent=4, sort_keys=True)) | |
| 1207 else: | |
| 1208 logger.info('Name: %s', name(pretty=True)) | |
| 1209 distribution_version = version(pretty=True) | |
| 1210 logger.info('Version: %s', distribution_version) | |
| 1211 distribution_codename = codename() | |
| 1212 logger.info('Codename: %s', distribution_codename) | |
| 1213 | |
| 1214 | |
| 1215 if __name__ == '__main__': | |
| 1216 main() |
