Package pythonids :: Module pythondist

Source Code for Module pythonids.pythondist

   1  # -*- coding: utf-8 -*- 
   2  """*pythonids.pythondist* provides information about the Python implementation. 
   3   
   4  Raises 'pythonids.PythonIDsImplementationError' when implementation is not supported. 
   5  """ 
   6  ############################################# 
   7  # 
   8  # See manuals for the detailed API. 
   9  # 
  10  ############################################# 
  11   
  12  import sys 
  13  try: 
  14      import platform 
  15      import re 
  16   
  17  except: 
  18      # 
  19      # missing *platform* and/or *re* requires various special code-sections 
  20      # possible supported are currently MicroPython and CircuitPython 
  21      # see 'pythonids.implementation' 
  22      # 
  23   
  24      from pythonids import PythonIDsImplementationError 
  25      try: 
  26          raise PythonIDsImplementationError("use implementation module for: " + str(sys.implementation))  # @UndefinedVariable 
  27      except: 
  28          raise PythonIDsImplementationError("implementation is not supported") 
  29   
  30  from collections import namedtuple 
  31   
  32  import pythonids 
  33  from pythonids import PythonIDsError, ISSTR, decode_pysyntax_str_to_num 
  34   
  35   
  36  __author__ = 'Arno-Can Uestuensoez' 
  37  __license__ = "Artistic-License-2.0 + Forced-Fairplay-Constraints" 
  38  __copyright__ = "Copyright (C) 2010-2018 Arno-Can Uestuensoez" \ 
  39                  " @Ingenieurbuero Arno-Can Uestuensoez" 
  40  __version__ = '0.1.35' 
  41  __uuid__ = "5624dc41-775a-4d17-ac42-14a0d5c41d1a" 
  42   
  43  __docformat__ = "restructuredtext en" 
  44   
  45   
  46  # 
  47  # the empty record 
  48  # 
  49  PYE_EMPTY = 0x00000000 
  50   
  51  # 
  52  # separation masks  
  53  # 
  54  # the combined vector semantics os separation masks is separative, 
  55  # thus no hierarchical semantics 
  56  # 
  57   
  58  # category type bits - for structural integrity 
  59  PYE_CATEGORY = 0x80000000  # bit 31 only - constant 1 for Python 
  60   
  61  # syntax type bits 
  62  PYE_SYNTAXTYPE = 0x7f800000  # major + minor 
  63  PYE_SYNTAXTYPE_MAJOR = 0x70000000  # major 
  64  PYE_SYNTAXTYPE_MINOR = 0x0f800000  # minor 
  65   
  66  # distribution type bits 
  67  PYE_DIST = 0x007c0000  # dist enum 
  68   
  69  # distribution release version bits 
  70  PYE_DISTREL = 0x0003ffff  # major + minor + micro 
  71  PYE_DISTREL_MAJOR = 0x0003f000  # major 
  72  PYE_DISTREL_MINOR = 0x00000fc0  # minor 
  73  PYE_DISTREL_MICRO = 0x0000003f  # micro 
  74   
  75   
  76  # 
  77  # category: constant PYE_PYTHOPN 
  78  # 
  79  # : CPython is basically the reference implementation of the Python Foundation @python.org  
  80  # 
  81  PYE_PYTHON = 0x80000000  # this value is ignored 
  82  PYE_PYTHON_PRETTY = 'Python' 
  83  PYE_PYTHON_NAME = 'python' 
  84   
  85  # 
  86  # disttype - the predefined values cover the major and minor version only 
  87  # see manual: pythonids/python_categorization.html#bit-mask-layout 
  88  # 
  89  PYE_PYTHON27 = 0x23800000  # Python2.7 
  90  PYE_PYTHON35 = 0x32800000  # Python3.5 
  91  PYE_PYTHON36 = 0x33000000  # Python3.6 
  92  PYE_PYTHON37 = 0x33800000  # Python3.7 
  93  PYE_PYTHON38 = 0x34000000  # Python3.8 
  94  PYE_PYTHON39 = 0x34800000  # Python3.9 
  95   
  96  # 
  97  # dist - the distribution may define it's own variant of the core reference syntax including another set of stdlibs 
  98  # 
  99   
 100  # : CPython is basically the reference implementation of the Python Foundation @python.org  
 101  PYE_CPYTHON = 0x00040000  # nr: 1 
 102  PYE_CPYTHON_PRETTY = 'CPython' 
 103  PYE_CPYTHON_NAME = 'cpython' 
 104   
 105  # : The variant of MicroPython for tiney devices and IoT by Adafruit inc. 
 106  PYE_CIRCUITPYTHON = 0x00080000  # nr: 2 
 107  PYE_CIRCUITPYTHON_PRETTY = 'CircuitPython' 
 108  PYE_CIRCUITPYTHON_NAME = 'circuitpython' 
 109   
 110  # : Python with extensions compilation into C-like results  
 111  PYE_CYTHON = 0x000c0000  # nr: 3 
 112  PYE_CYTHON_PRETTY = 'Cython' 
 113  PYE_CYTHON_NAME = 'cython' 
 114   
 115  # : Pynteractive Python with a smart command line interface too - beneath it's GUI capabilities. 
 116  PYE_IPYTHON = 0x00100000  # nr: 4 
 117  PYE_IPYTHON_PRETTY = 'iPython' 
 118  PYE_IPYTHON_NAME = 'ipython' 
 119   
 120  # : The Python variant specialized on .NET and mono runtime platforms - so basically targeting Windows environments 
 121  PYE_IRONPYTHON = 0x00140000  # nr: 5 
 122  PYE_IRONPYTHON_PRETTY = 'IronPython' 
 123  PYE_IRONPYTHON_NAME = 'ironpython' 
 124   
 125  # : Java JVM and JIT based Python 
 126  PYE_JYTHON = 0x00180000  # nr: 6 
 127  PYE_JYTHON_PRETTY = 'Jython' 
 128  PYE_JYTHON_NAME = 'jython' 
 129   
 130  # : The crowd funded variant of Python with a schedular, basically replacing a shell and OS by pure and only Python with optional C-plugins  
 131  PYE_MICROPYTHON = 0x001c0000  # nr: 7 
 132  PYE_MICROPYTHON_PRETTY = 'MicroPython' 
 133  PYE_MICROPYTHON_NAME = 'micropython' 
 134   
 135  PYE_PYPY = 0x00200000  # nr: 8 
 136  PYE_PYPY_PRETTY = 'PyPy' 
 137  PYE_PYPY_NAME = 'pypy' 
 138   
 139  # 
 140  # Some reference values of 32bit hexrelease for test and validation. 
 141  # E.g. valid as: 
 142  # 
 143  #   pythonids.pydist.PythonDist.hexrelease 
 144  # 
 145  PYE_PYDIST_CPYTHON2715 = 0xa38421cf  #: CPython-2.7.15   - Python2.7 
 146  PYE_PYDIST_CPYTHON372 = 0xb38431c2  #: CPython-3.7.2    - Python3.7 
 147  PYE_PYDIST_IPYTHON550 = 0xA3905140  #: IPython-5.5.0    - Python2.7 
 148  PYE_PYDIST_IPYTHON560 = 0xA3905180  # IPython-5.6.0    - Python2.7 
 149  PYE_PYDIST_IRONPYTHON277 = 0xA39421C7  #: IRonPython-2.7.7 - Python2.7 
 150  PYE_PYDIST_IRONPYTHON279 = 0xA39421C9  #: IRonPython-2.7.9 - Python2.7 
 151  PYE_PYDIST_JYTHON270 = 0xA39821C0  #: Jython-2.7.0     - Python2.7 
 152  PYE_PYDIST_JYTHON271 = 0xA39821C1  #: Jython-2.7.1     - Python2.7 
 153  PYE_PYDIST_PYPY580 = 0xA3A05200  #: PyPy-5.8.0       - Python2.7 
 154  PYE_PYDIST_PYPY60027 = 0xA3A06000  #: PyPy-6.0.0       - Python2.7 
 155  PYE_PYDIST_PYPY60035 = 0xB2A06000  #: PyPy-6.0.0       - Python3.5 
 156  PYE_PYDIST_PYPY70036 = 0xB3207000  #: PyPy-7.0.0       - Python3.6 
 157   
 158  dist2num = { 
 159      PYE_CIRCUITPYTHON: PYE_CIRCUITPYTHON, 
 160      PYE_CIRCUITPYTHON_NAME: PYE_CIRCUITPYTHON, 
 161      PYE_CIRCUITPYTHON_PRETTY: PYE_CIRCUITPYTHON, 
 162      PYE_CPYTHON: PYE_CPYTHON, 
 163      PYE_CPYTHON_NAME: PYE_CPYTHON, 
 164      PYE_CPYTHON_PRETTY: PYE_CPYTHON, 
 165      PYE_CYTHON: PYE_CYTHON, 
 166      PYE_CYTHON_NAME: PYE_CYTHON, 
 167      PYE_CYTHON_PRETTY: PYE_CYTHON, 
 168      PYE_IPYTHON: PYE_IPYTHON, 
 169      PYE_IPYTHON_NAME: PYE_IPYTHON, 
 170      PYE_IPYTHON_PRETTY: PYE_IPYTHON, 
 171      PYE_IRONPYTHON: PYE_IRONPYTHON, 
 172      PYE_IRONPYTHON_NAME: PYE_IRONPYTHON, 
 173      PYE_IRONPYTHON_PRETTY: PYE_IRONPYTHON, 
 174      PYE_JYTHON: PYE_JYTHON, 
 175      PYE_JYTHON_NAME: PYE_JYTHON, 
 176      PYE_JYTHON_PRETTY: PYE_JYTHON, 
 177      PYE_MICROPYTHON: PYE_MICROPYTHON, 
 178      PYE_MICROPYTHON_NAME: PYE_MICROPYTHON, 
 179      PYE_MICROPYTHON_PRETTY: PYE_MICROPYTHON, 
 180      PYE_PYPY: PYE_PYPY, 
 181      PYE_PYPY_NAME: PYE_PYPY, 
 182      PYE_PYPY_PRETTY: PYE_PYPY, 
 183      PYE_PYTHON: PYE_PYTHON, 
 184      PYE_PYTHON_PRETTY: PYE_PYTHON, 
 185      PYE_PYTHON_NAME: PYE_PYTHON, 
 186      PYE_PYTHON27: PYE_PYTHON27, 
 187      PYE_PYTHON35: PYE_PYTHON35, 
 188      PYE_PYTHON36: PYE_PYTHON36, 
 189      PYE_PYTHON37: PYE_PYTHON37, 
 190      PYE_PYTHON38: PYE_PYTHON38, 
 191      PYE_PYTHON39: PYE_PYTHON39, 
 192  } 
 193   
 194  num2name = { 
 195      PYE_EMPTY: "", 
 196      PYE_CPYTHON: PYE_CPYTHON_NAME, 
 197      PYE_IPYTHON: PYE_IPYTHON_NAME, 
 198      PYE_IRONPYTHON: PYE_IRONPYTHON_NAME, 
 199      PYE_JYTHON: PYE_JYTHON_NAME, 
 200      PYE_PYPY: PYE_PYPY_NAME, 
 201      PYE_PYTHON: PYE_PYTHON_NAME, 
 202      PYE_PYTHON27: "python2.7", 
 203      PYE_PYTHON35: "python3.5", 
 204      PYE_PYTHON36: "python3.6", 
 205      PYE_PYTHON37: "python3.7", 
 206      PYE_PYTHON38: "python3.8", 
 207      PYE_PYTHON39: "python3.9", 
 208  } 
 209   
 210  num2pretty = { 
 211      PYE_EMPTY: "", 
 212      PYE_CPYTHON: PYE_CPYTHON_PRETTY, 
 213      PYE_IPYTHON: PYE_IPYTHON_PRETTY, 
 214      PYE_IRONPYTHON: PYE_IRONPYTHON_PRETTY, 
 215      PYE_JYTHON: PYE_JYTHON_PRETTY, 
 216      PYE_PYPY: PYE_PYPY_PRETTY, 
 217      PYE_PYTHON: PYE_PYTHON_PRETTY, 
 218      PYE_PYTHON27: "Python-2.7", 
 219      PYE_PYTHON35: "Python-3.5", 
 220      PYE_PYTHON36: "Python-3.6", 
 221      PYE_PYTHON37: "Python-3.7", 
 222      PYE_PYTHON38: "Python-3.8", 
 223      PYE_PYTHON39: "Python-3.9", 
 224  } 
 225   
 226  # 
 227  # static parsers 
 228  # 
 229  SPLITVERS = re.compile(r'(?s)(^[0-9]+)[.]([0-9]*)[.]([0-9]*).*') 
 230  SPLITVERS2 = re.compile(r'(?s)(^[0-9]+)[.]([0-9]*).*') 
 231  STR2DISTREL = re.compile(r'([0-9.]*)[^0-9]*') 
 232   
 233  # : The corresponding *bash* environment names. 
 234  bash_map = { 
 235      'category': "PYDIST_CATEGORY", 
 236      'disttype': "PYDIST_DISTTYPE", 
 237      'dist': "PYDIST_DIST", 
 238      'distrel': "PYDIST_DISTREL", 
 239      'hexrelease': "PYDIST_DISTREL_HEXVERSION", 
 240      'compiler': "PYDIST_COMPILER", 
 241      'compiler_version': "PYDIST_COMPILER_VERSION", 
 242      'c_libc_version': "PYDIST_C_LIBC_VERSION", 
 243      'c_compiler': "PYDIST_C_COMPILER", 
 244      'c_compiler_version': "PYDIST_C_COMPILER_VERSION", 
 245  } 
 246   
 247  # : The mapping of attributes to values. 
 248  attribute_map = { 
 249      'category': "category", 
 250      'disttype': "disttype", 
 251      'dist': "dist", 
 252      'distrel': "distrel", 
 253      'hexrelease': "hexrelease", 
 254      'compiler': "compiler", 
 255      'compiler_version': "compiler_version", 
 256      'c_libc_version': "c_libc_version", 
 257      'c_compiler': "c_compiler", 
 258      'c_compiler_version': "c_compiler_version", 
 259  } 
 260   
 261   
 262  #: Named tuple for structured results. See *collections.namedtuple*. 
 263  PyDist = namedtuple('PyDist', ('category', 'disttype', 'dist', 'distrel'))  
 264   
 265  #: Named tuple for structured results as sub-parts. See *collections.namedtuple*. 
 266  PyDistSegments = namedtuple('PyDistSegments', ('category', 'disttype', 'dist', 'distrel'))  
 267   
 268  #: Named tuple for structured results as *str*. See *collections.namedtuple*. 
 269  PyDistStr = namedtuple('PyDistStr', ('category', 'disttype', 'dist', 'distrel'))  
 270   
271 -class PythonDistError(PythonIDsError):
272 pass
273 274
275 -def _encode_distrel_bitmask(dx=0, dy=0, dz=0):
276 # 32bit - dx.dy.dz 277 return ( 278 (dx & 63) << 12 # bit 17 - 12 - see version_info[0] 279 | (dy & 63) << 6 # bit 11 - 6 - see version_info[1] 280 | (dz & 63) # bit 5 - 0 - see version_info[2] 281 282 )
283 284
285 -def _encode_distrel_str_bitmask(sxyz=''):
286 # 32bit 287 res = STR2DISTREL.sub(r'\1', sxyz).split('.') # variable length 288 if len(res) == 3: 289 return ( 290 (int(res[0]) & 63) << 12 # bit 17 - 12 - see version_info[0] 291 | (int(res[1]) & 63) << 6 # bit 11 - 6 - see version_info[1] 292 | (int(res[2]) & 63) # bit 5 - 0 - see version_info[2] 293 ) 294 elif len(res) == 2: 295 return ( 296 (int(res[0]) & 63) << 12 # bit 17 - 12 - see version_info[0] 297 | (int(res[1]) & 63) << 6 # bit 11 - 6 - see version_info[1] 298 ) 299 elif len(res) == 1: 300 return ( 301 (int(res[0]) & 63) << 12 # bit 17 - 12 - see version_info[0] 302 ) 303 return ()
304 305
306 -def _encode_disttype_bitmask(sma=0, smi=0):
307 # 32bit 308 return ( 309 (sma & 7) << 28 # bit 30 - 28 - see version_info[0] 310 | (smi & 31) << 23 # bit 27 - 23 - see version_info[1] 311 )
312 313
314 -def _encode_disttype_str_bitmask(sxy=''):
315 # 32bit 316 res = STR2DISTREL.sub(r'\1', sxy).split('.') # variable length 317 if len(res) >= 2: 318 return ( 319 (int(res[0]) & 7) << 28 # bit 17 - 12 - see version_info[0] 320 | (int(res[1]) & 31) << 23 # bit 11 - 6 - see version_info[1] 321 ) 322 elif len(res) == 1: 323 return ( 324 (int(res[0]) & 63) << 12 # bit 17 - 12 - see version_info[0] 325 ) 326 return ()
327
328 -def decode_pydist_32bit_to_tuple_str(ddat=0):
329 """ Decodes the 32bit hex representation of the Python distribution 330 into a dict structure with str names and str representation of releases. 331 332 Args: 333 334 ddat: 335 336 The 32bit value. 337 338 Returns: 339 340 Dictionary with components: :: 341 342 result := { 343 'category': 'python', 344 'styntaxtype': <str-syntax-release>, 345 'dist': <dist-name>, 346 'distrel': <str-dist-release> 347 } 348 349 category: canonical str name 350 str-syntax-release: string representation 351 dist: canonical str name 352 str-dist-release: string representation 353 354 Raises: 355 356 pass-through 357 358 """ 359 try: 360 _syn = num2name[ddat & PYE_SYNTAXTYPE] 361 except KeyError: 362 _syn = '' 363 364 try: 365 _dis = num2name[ddat & PYE_DIST] 366 except KeyError: 367 _dis = '' 368 369 if _dis or (ddat & PYE_DISTREL): 370 _disrel = "%d.%d.%d" % ( 371 (ddat & PYE_DISTREL_MAJOR) >> 12, 372 (ddat & PYE_DISTREL_MINOR) >> 6, 373 ddat & PYE_DISTREL_MICRO, 374 ) 375 else: 376 _disrel = '' 377 378 return PyDistStr( 379 PYE_PYTHON_NAME, 380 _syn, 381 _dis, 382 _disrel, 383 )
384 385
386 -def decode_pydist_32bit_to_tuple_segments(ddat=0):
387 """ Decodes the 32bit hex representation of the Python distribution 388 into a dict structure with str names and numeric release vectors. 389 390 Args: 391 392 ddat: 393 394 The 32bit value. 395 396 Returns: 397 398 Nametupel with the components: :: 399 400 PyDist = namedtuple('PyDist', ('category', 'disttype', 'dist', 'distrel')) 401 402 result := PyDist( 403 PYE_PYTHON, (<syntax-major>,<syntax-minor>), <32bit-dist>, (<dist-major>, <dist-minor>, <dist-micro>) 404 ) 405 406 PYE_PYTHON: 32bit-enum for category 407 32bit-syntax-release: 32bit-value for syntax release 408 32bit-dist: 32bit-enum for distribution 409 32bit-dist-release: 32bit-value for distribution release 410 411 Dictionary with components: :: 412 413 result := { 414 'category': 'python', 415 'styntaxtype': (<syntax-major>,<syntax-minor>), 416 'dist': <dist-name>, 417 'distrel': (<dist-major>, <dist-minor>, <dist-micro>) 418 } 419 420 category: canonical str name 421 syntax-major: int value 422 syntax-minor: int value 423 dist: canonical str name 424 dist-major: int value 425 dist-minor: int value 426 dist-micro: int value 427 428 Raises: 429 430 pass-through 431 432 """ 433 return PyDistSegments( 434 PYE_PYTHON >> 31, # the only and one 435 ( 436 (ddat & PYE_SYNTAXTYPE_MAJOR) >> 28, 437 (ddat & PYE_SYNTAXTYPE_MINOR) >> 23, 438 ), 439 (ddat & PYE_DIST) >> 18, 440 ( 441 (ddat & PYE_DISTREL_MAJOR) >> 12, 442 (ddat & PYE_DISTREL_MINOR) >> 6, 443 ddat & PYE_DISTREL_MICRO, 444 ) 445 )
446 447
448 -def decode_pydist_32bit_to_tuple(ddat=0):
449 """ Decodes the 32bit hex representation of the Python distribution 450 into a flat tuple of numbers. 451 452 Args: 453 454 ddat: 455 456 The 32bit value. 457 458 Returns: 459 460 Nametupel with the components: :: 461 462 PyDist = namedtuple('PyDist', ('category', 'disttype', 'dist', 'distrel')) 463 464 result := PyDist( 465 PYE_PYTHON, <32bit-syntax-release>, <32bit-dist>, <32bit-dist-release> 466 ) 467 468 PYE_PYTHON: 32bit-enum for category 469 32bit-syntax-release: 32bit-value for syntax release 470 32bit-dist: 32bit-enum for distribution 471 32bit-dist-release: 32bit-value for distribution release 472 473 Raises: 474 475 pass-through 476 477 """ 478 return PyDist( 479 ddat & PYE_CATEGORY, 480 ddat & PYE_SYNTAXTYPE, 481 ddat & PYE_DIST, 482 ddat & PYE_DISTREL, 483 )
484 485
486 -def encode_pydist_to_32bit(d=0, dx=0, dy=0, dz=0, sma=0, smi=0):
487 """ Encodes the Python distribution by calculating the 32bit integer 488 bitmask for the provided Python distribution and syntax 489 release information. 490 491 Args: 492 d: 493 The numeric enum value of the distribution with original bit-positions. 494 495 dx: 496 The major distribution version number. 497 498 dy: 499 The minor distribution version number. 500 501 dz: 502 The micro distribution version number. 503 504 sma: 505 The major syntax version number. 506 507 smi: 508 The minor syntax version number. 509 510 Returns: 511 512 The 32bit bitmask. 513 514 See `Python Distribution Categorization <python_categorization.html>`_. 515 516 Raises: 517 518 pass-through 519 520 """ 521 return ( 522 PYE_PYTHON # here anything is category=Python 523 | d # distribution enum in it's original bit positions 524 | (dx & 63) << 12 # bit 17 - 12 - see version_info[0] 525 | (dy & 63) << 6 # bit 11 - 6 - see version_info[1] 526 | (dz & 63) # bit 5 - 0 - see version_info[2] 527 | (sma & 7) << 28 # bit 30 - 28 - see version_info[0] 528 | (smi & 31) << 23 # bit 27 - 23 - see version_info[1] 529 )
530 531
532 -def encode_pydist_segments_to_32bit(**kargs):
533 """ Encodes the 32bit bitmask of the compressed platform information 534 by the provided values of the sub fields. Non-provided values are 535 set to *0*, and though ignored. 536 537 This function is mainly designed and foreseen for cache preparation and test 538 environments, though it inherently requires some of the systems performance. 539 Thus do not use it within repetitive calls for performance critical large 540 scale loops with small code sections. 541 542 Args: 543 544 kargs: 545 546 category: 547 548 The category. The only and one permitted is *Python*: :: 549 550 category := ( 551 PYE_PYTHON # enum 552 | 'Python' # Pretty name 553 | 'python' # key 554 | 0 # None 555 ) 556 557 default := 0 558 559 dist: 560 561 The dist: :: 562 563 dist := ( 564 PYE_CPYTHON | PYE_IPYTHON | PYE_IRONPYTHON 565 | PYE_JYTHON | PYE_PYPY 566 | PYE_CIRCUITPYTHON | PYE_MICROPYTHON 567 | <known-name-of-dist> 568 | 0 569 ) 570 known-name-of-dist := "case insensitive name or pretty name of the distribution" 571 0 := None 572 573 default:=0 574 575 distrel: 576 577 The distrel: :: 578 579 distrel := ( 580 <int-val> 581 | (<major>, <minor>, <micro>) 582 | 0 583 ) 584 int-val := the relative integer value of the distrel bits 585 (<major>, <minor>, <micro>):= the tuple of the Python distribution release 586 0 := None 587 588 default := 0 589 590 disttype: 591 592 The disttype: :: 593 594 disttype := ( 595 <int-val> 596 | (<major>, <minor>) 597 | 0 598 ) 599 int-val := the relative integer value of the disttype bits 600 (<major>, <minor>) := the tuple of Python syntax version 601 0 := None 602 603 default := 0 604 605 Returns: 606 607 The 32bit compressed bitmask of the of the distribution. 608 609 Raises: 610 611 pass-through 612 613 """ 614 category = kargs.get('category', 0) 615 616 if kargs.get('category'): 617 category = 1 618 619 dist = kargs.get('dist', 0) 620 try: 621 if isinstance(dist, ISSTR): 622 dist = dist2num[dist.lower()] 623 except KeyError as e: 624 # sys.stderr.write("ERROR: unknown dist: " + str(dist)) 625 e += "\nERROR: unknown dist: %s\n" % (str(dist)) 626 raise 627 628 distrel = kargs.get('distrel', 0) 629 if isinstance(distrel, (tuple, list)): 630 distrel = distrel[0] << 12 | distrel[1] << 6 | distrel[2] 631 elif isinstance(distrel, ISSTR): 632 distrel = decode_pysyntax_str_to_num(distrel) 633 634 disttype = kargs.get('disttype', 0) 635 if isinstance(disttype, (tuple, list)): 636 disttype = int(disttype[0]) << 5 | int(disttype[1]) 637 elif isinstance(disttype, ISSTR): 638 disttype = decode_pysyntax_str_to_num(disttype) 639 disttype = int(disttype[0]) << 5 | int(disttype[1]) # ignore [3] 640 641 return ( 642 category << 31 | disttype << 23 | dist | distrel 643 )
644 645
646 -class PythonDist(object):
647
648 - def __init__(self, *args, **kargs):
649 """ Creates an empty object. The instance could be 650 either initialized by the provided parameters, 651 or remains empty - which is zero *0*. 652 653 Provides *PythonDist.scan()* for the readout of 654 the implementation information. The *scan()* is 655 not called automatic. Each call of *scan()* 656 replaces the previous values. 657 658 Args: 659 660 args: 661 662 Optional positional parameters in the following order. 663 The corresponding keyword-arguments dominate. :: 664 665 *args := [category [, disttype [, dist [, distrel]]]] 666 667 kargs: 668 669 category: 670 671 The registered *category* for initialization. 672 673 default := 0 674 675 disttype: 676 677 The registered *disttype* for initialization. 678 679 default := 0 680 681 dist: 682 683 The registered *dist* for initialization. 684 685 default := 0 686 687 distrel: 688 689 The registered *distrel* for initialization. 690 691 default := 0 692 693 forceall: 694 695 Controls the default for the scan of content: :: 696 697 forceall := ( 698 True # scan distribution and compiler 699 | False # scan distribution only 700 ) 701 702 default := False 703 704 valuetype: 705 Defines the representation of the values - where possible:: 706 707 valuetype := ( 708 raw # original internal value 709 | hex # as hex 710 | sym # mapped to symbolic names 711 ) 712 713 default := sym 714 715 Returns: 716 717 Initial instance, optionally initialized by the provided 718 parameters. 719 720 Raises: 721 PythonIDsError 722 723 pass-through 724 725 """ 726 self.valuetype = kargs.get('valuetype', False) 727 728 self.category = PYE_PYTHON # : the category ID 729 self.disttype = 0 # : the type ID of the syntax 730 self.hexrelease = 0 # : the resulting hex release 731 self.dist = 0 # : the distribution ID 732 self.distrel = 0 # : the release of the distribution 733 734 self.compiler = '' 735 self.compiler_version = 0 736 self.compiler_version_tuple = (0, 0, 0,) 737 738 self.c_libc_version = 0 739 self.c_compiler = '' 740 self.c_compiler_version = 0 741 742 self.forceall = kargs.get('forceall', False) # : control the optional part of the scan 743 744 self.osrel_sp = [] 745 746 if args: 747 748 try: 749 # 0 750 _x = args[0] 751 try: 752 # the category, currently only one: Python 753 self.category = dist2num[_x] & PYE_CATEGORY 754 except KeyError: 755 raise PythonIDsError("'category' not registered: " + str(_x)) 756 757 try: 758 # 1 759 _x = args[1] 760 try: 761 # the syntax type of the distribution 762 # defined by Python syntax version <major>.<minor> 763 self.disttype = dist2num[_x] & PYE_SYNTAXTYPE 764 except KeyError: 765 if not type(_x) is int: 766 # cannot map 767 raise PythonIDsError("'disttype' not registered: " + str(_x)) 768 self.dist = _x & PYE_SYNTAXTYPE 769 770 try: 771 # 2 772 _x = args[2] 773 try: 774 # the implementation, current supported: CPython, IPython, IronPython, Jython, PyPy 775 self.dist = dist2num[_x] & PYE_DIST 776 except KeyError: 777 raise PythonIDsError("'dist' not registered: " + str(_x)) 778 779 try: 780 # 3 781 _x = args[3] 782 try: 783 # the release version <major>.<minor>.<micro> 784 self.distrel = dist2num[_x] & PYE_DISTREL 785 except KeyError: 786 if not type(_x) is int: 787 # cannot be mapped 788 raise PythonIDsError("'distrel' not registered: " + str(_x)) 789 # any release version is supported 790 self.distrel = _x & PYE_DISTREL 791 792 except KeyError: 793 pass 794 except KeyError: 795 pass 796 except KeyError: 797 pass 798 except KeyError: 799 pass 800 801 802 # keyword arguments dominate 803 self.category = kargs.get('category', self.category) 804 self.disttype = kargs.get('disttype', self.disttype) 805 self.dist = kargs.get('dist', self.dist) 806 self.distrel = kargs.get('distrel', self.distrel) 807 808 self.hexrelease = self.get_hexrelease()
809
810 - def get_distribution(self, rtype=PyDist):
811 """ Reads out the distribution data into a tuple of selected type. 812 813 Args: 814 rtype: 815 The return type: 816 817 .. parsed-literal:: 818 819 rtype := ( 820 :ref:`PyDist <SPEC_PyDist_Class>` 821 | :ref:`PyDistSegments <SPEC_PyDistSegments>` 822 | :ref:`PyDistStr <SPEC_PyDistStr>` 823 | tuple 824 | <user-defined-tuple-type> 825 ) 826 827 default := :ref:`PyDist <SPEC_PyDist_Class>` 828 829 Returns: 830 Returns a tuple of the provided attributes: :: 831 832 ( 833 category, 834 disttype, 835 dist, 836 distrel 837 ) 838 839 Raises: 840 pass-through 841 842 """ 843 if rtype == PyDist: 844 return PyDist( 845 self.category, 846 self.disttype, 847 self.dist, 848 self.distrel, 849 ) 850 851 elif rtype == PyDistStr: 852 return PyDistStr( 853 str(self.category), 854 str(self.disttype), 855 str(self.dist), 856 str(self.distrel), 857 ) 858 859 elif rtype == PyDistSegments: 860 return decode_pydist_32bit_to_tuple_segments(self.get_hexrelease()) 861 862 else: 863 # expect a pure tuple type 864 return rtype( 865 self.category, 866 self.disttype, 867 self.dist, 868 self.distrel, 869 )
870 871
872 - def scan(self, forceall=None):
873 """Scans local platform for attributes specifying the platform. 874 Supports: :: 875 876 CPython, iPython, IronPython, Jython, PyPy 877 878 Args: 879 forceall: 880 Controls the scan content: :: 881 882 forceall := ( 883 True # scan distribution and compiler 884 | False # scan distribution only 885 ) 886 887 default := None 888 889 Returns: 890 Superposes the following mandatory attributes by the scanned values: 891 892 * The tuple of Python identifiers: :: 893 894 category 895 disttype 896 dist 897 distrel 898 899 * Additional shortcuts prepared for direct processing: :: 900 901 hexrelease 902 903 * In addition the optional, but strongly supported attributes. 904 These are scanned only in case of *forceall==True*. :: 905 906 c_libc_version 907 c_compiler 908 c_compiler_version 909 910 Returns the value of *hexrelease*. 911 912 Raises: 913 914 PythonDistError 915 916 """ 917 if forceall == None: 918 _forceall = self.forceall 919 else: 920 _forceall = forceall 921 922 # 923 # syntax category 924 # 925 self.category = PYE_PYTHON # the only and one supported, contain it for pattern consistance 926 927 # 928 # reference syntax 929 # 930 # _syntaxrel = platform.python_version() 931 _syntaxrel_tuple = platform.python_version_tuple() 932 self.disttype = _encode_disttype_bitmask(int(_syntaxrel_tuple[0]), int(_syntaxrel_tuple[1])) 933 934 # 935 # distribution 936 # 937 _d = platform.python_implementation() 938 try: 939 _dist = self.dist = dist2num[_d] 940 except KeyError: 941 raise PythonDistError("Distribution is not supported: " + str(_d)) 942 943 if _dist in (PYE_CPYTHON, PYE_IPYTHON,): # does not distinguish CPython and IPython - which is a interactive-addon 944 945 # see docu: [ARTICLESTACKOFLOWIPYTHON]_ 946 try: 947 __IPYTHON__ # @UndefinedVariable 948 # running under control of IPython addons 949 950 except NameError: 951 # the standard interpreter and the reference, thus syntaxrel == distrel 952 try: 953 self.distrel = _encode_distrel_bitmask(*(int(x) for x in _syntaxrel_tuple[0:3])) 954 955 except ValueError: 956 # handle pre-releases, e.g. '3.8.0a5' - these are basically not supported... 957 # these are treated with their version numbers only by dropping any alpha, beta, etc. appendix 958 # though the pythondist package targets production system components only 959 self.distrel = _encode_distrel_bitmask(*(int(x) for x in ( 960 _syntaxrel_tuple[0], 961 _syntaxrel_tuple[1], 962 re.sub(r'^([0-9]).*', r'\1', _syntaxrel_tuple[2]) 963 ))) 964 965 else: 966 _dist = PYE_IPYTHON 967 # provided by the core module __version__ 968 self.distrel = _encode_distrel_bitmask(*(int(x) for x in sys.modules['IPython'].__version__.split('.'))) 969 970 elif _dist == PYE_PYPY: 971 # 972 # contained in the compile string 973 # 974 # e.g. '2.7.13 (c925e73810367cd960a32592dd7f728f436c125c, Dec 14 2017, 12:47:11)\n[PyPy 5.8.0 with GCC 7.2.1 20170915 (Red Hat 7.2.1-2)]' 975 # ^^^^^^ ^^^^^ ^^^ ^^^^^ 976 # 977 _c = sys.version 978 _cprep = re.sub( 979 r'^([0-9.]+).*\n.*PyPy *([0-9.]+) [^ ]+ ([^ ]+) +([0-9.]+).*$', r'\1@@\2@@\3@@\4', 980 _c, flags=re.MULTILINE) # @UndefinedVariable 981 try: 982 _python_version, _distrel, self.c_compiler, _c_compiler_version = _cprep.split('@@') 983 self.distrel = _encode_distrel_str_bitmask(_distrel) 984 except ValueError: 985 self.distrel = 0 986 _c_compiler_version = '' 987 _python_version = '' 988 989 990 if _forceall: 991 try: 992 self.c_compiler_version_tuple = tuple(int(i) for i in _c_compiler_version.split('.')) 993 except ValueError: 994 self.c_compiler_version_tuple = (0, 0, 0,) 995 996 self.c_libc_version = platform.libc_ver() # default is current instance itself 997 998 self.compiler = "Python" 999 # self.compiler_version = platform.python_version() 1000 # self.compiler_version = _python_version 1001 self.compiler_version_tuple = sys.version_info[:3] 1002 pass 1003 1004 # else: 1005 # self.compiler = "Python" 1006 # self.compiler_version = sys.version_info[:3] 1007 1008 elif _dist == PYE_IRONPYTHON: 1009 # 1010 # >>> platform.python_compiler() 1011 # '.NET 4.0.30319.42000 (64-bit)' 1012 # 1013 # The sys.version seems to be compatible to the python-syntax, but 1014 # in sync only with major and minor version. 1015 # The micro version seems to be independent from Python-Syntax/CPython. 1016 # Current version for simplicity just takes the whole version literally as the syntax version. 1017 # 1018 self.distrel = _encode_distrel_bitmask(*(int(x) for x in _syntaxrel_tuple[0:3])) 1019 1020 elif _dist == PYE_JYTHON: 1021 # 1022 # the distrel seems to be the same as sys.version 1023 # and platform.python_version_tuple / platform.python_version 1024 # 1025 self.distrel = _encode_distrel_bitmask(*(int(x) for x in _syntaxrel_tuple[0:3])) 1026 1027 # the compiler is defined by the jre 1028 # libc is empty 1029 # 1030 # >>> platform.python_compiler() -> variable JIT 1031 # 'java1.7.0_65 ( ==linux2 for targets )' 1032 if _forceall: 1033 # 1034 # extra value for the build release, due to it's importance for java-rte 1035 # 1036 _c = platform.python_compiler() # e.g. "str: java1.8.0_181" 1037 self.c_compiler, self.c_compiler_version = re.sub(r'^([^0-9]*)([0-9.]*)_([0-9]*).*$', r'\1:\2.\3', _c).split(':') 1038 self.c_compiler_version_tuple = tuple(int(i) for i in self.c_compiler_version.split('.')) 1039 self.c_libc_version = ('', (0, 0, 0, 0)) 1040 1041 self.compiler = "Java" 1042 # self.compiler_version = platform.python_compiler()[4:] 1043 # self.compiler_version_tuple = tuple(int(i) for i in self.c_compiler_version.split('.')) 1044 self.compiler_version_tuple = self.c_compiler_version_tuple 1045 1046 if _forceall and _dist in (PYE_CPYTHON, PYE_CYTHON, PYE_IPYTHON, PYE_IRONPYTHON): 1047 _c = platform.python_compiler() 1048 try: 1049 # e.g. 'GCC 7.3.1 20180303 (Red Hat 7.3.1-5)' 1050 self.c_compiler, self.c_compiler_version = re.sub(r'^([^ ]*)[^0-9]*([0-9.]*) .*$', r'\1:\2', _c).split(':') 1051 self.c_compiler_version_tuple = tuple(int(i) for i in self.c_compiler_version.split('.')) 1052 except: 1053 # SunOS 1054 self.c_compiler = 'C' 1055 self.c_compiler_version = '' 1056 self.c_compiler_version_tuple = (0, 0, 0,) 1057 1058 self.c_libc_version = platform.libc_ver() # default is current instance itself 1059 self.compiler = self.c_compiler 1060 self.compiler_version = self.c_compiler_version 1061 1062 # requires all of them to be set 1063 self.hexrelease = self.category | self.disttype | self.dist | self.distrel 1064 1065 return self.hexrelease
1066
1067 - def __str__(self):
1068 '' 1069 return self.pretty_format()
1070
1071 - def pretty_format(self, **kargs):
1072 """Creates printable string of formatted information about the Python implementation. 1073 1074 Args: 1075 kargs: 1076 forceall: 1077 Prints all available information:: 1078 1079 forceall := ( 1080 True # print all including the compiler of the interpreter 1081 | False # print the interpreter data only 1082 ) 1083 1084 layout: 1085 Defines the displayed layout/syntax:: 1086 1087 layout := ( 1088 str 1089 | repr 1090 | json 1091 ) 1092 1093 valuetype: 1094 Defines the representation of the values - where possible:: 1095 1096 valuetype := ( 1097 raw # original internal value 1098 | hex # as hex 1099 | sym # mapped to symbolic names 1100 ) 1101 1102 default := sym 1103 1104 Returns: 1105 Formatted string. 1106 1107 Raises: 1108 pass-through 1109 1110 """ 1111 _forceall = kargs.get('forceall', self.forceall) 1112 _valuetype = kargs.get('valuetype', self.valuetype) 1113 _layout = kargs.get('layout', 'str') 1114 1115 _hex = _valuetype == 'hex' 1116 _raw = _valuetype == 'raw' 1117 1118 def maptostr(r): 1119 if _hex: 1120 try: 1121 return str(hex(r)) 1122 except ValueError: 1123 return str(r) 1124 1125 if _raw: 1126 return str(r) 1127 else: 1128 try: 1129 return str(num2name[r]) 1130 except KeyError: 1131 return str(r)
1132 1133 if _layout == 'str': 1134 res = "" 1135 _format = "%-20s= %s\n" 1136 1137 res += _format % ("category", maptostr(self.category)) 1138 res += _format % ("disttype", maptostr(self.disttype)) 1139 res += _format % ("dist", maptostr(self.dist)) 1140 1141 if _raw or _hex: 1142 res += _format % ("distrel", maptostr(self.distrel)) 1143 else: 1144 res += _format % ("distrel", decode_pydist_32bit_to_tuple_str(self.distrel).distrel) 1145 1146 if _raw: 1147 res += _format % ("hexrelease", str(self.hexrelease)) 1148 else: 1149 res += _format % ("hexrelease", hex(self.hexrelease)) 1150 1151 if _forceall: 1152 res += _format % ("compiler", str(self.compiler)) 1153 res += _format % ("compiler_version", str('.'.join(str(i) for i in self.compiler_version_tuple))) 1154 if PYDIST & PYE_DIST == PYE_PYPY: 1155 res += _format % ("compiler", str(self.c_compiler)) 1156 res += _format % ("compiler_version", str('.'.join(str(i) for i in self.c_compiler_version_tuple))) 1157 1158 res += _format % ("implementation", str(sys.executable)) 1159 1160 elif _layout == 'repr': 1161 res = repr(self.get_json()) 1162 1163 # res = "{" 1164 # 1165 # _format = "\n%-20s= %s" 1166 # 1167 # try: 1168 # res += '"category": "' + maptostr(self.category) + '", ' 1169 # except KeyError: 1170 # res += '"category": "", ' 1171 # 1172 # try: 1173 # res += '"disttype": "' + maptostr(self.disttype) + '", ' 1174 # except KeyError: 1175 # res += '"disttype": "", ' 1176 # 1177 # try: 1178 # res += '"dist": "' + maptostr(self.dist) + '", ' 1179 # except KeyError: 1180 # res += '"dist": "", ' 1181 # 1182 # if _raw or _hex: 1183 # res += '"distrel": "' + maptostr(self.distrel) + '", ' 1184 # else: 1185 # res += '"distrel": "' + str(decode_pydist_32bit_to_tuple_str(self.distrel).distrel) + '", ' 1186 # 1187 # if _raw: 1188 # res += '"hexrelease": ' + str(self.hexrelease) + ', ' 1189 # else: 1190 # res += '"hexrelease": ' + str(self.hexrelease) + ', ' 1191 # 1192 # if self.forceall: 1193 # res += '"compiler": "' + str(self.compiler) + '", ' 1194 # res += '"compiler_version": "' + str('.'.join(str(i) for i in self.compiler_version_tuple)) + '", ' 1195 # if PYDIST & PYE_DIST == PYE_PYPY: 1196 # res += '"compiler": ' + str(self.c_compiler) + ', ' 1197 # res += '"compiler_version": "' + str('.'.join(str(i) for i in self.c_compiler_version_tuple)) + '", ' 1198 # 1199 # res += '"implementation": "' + str(sys.executable) + '", ' 1200 # 1201 # res += '}' 1202 1203 elif _layout == 'json': 1204 res = str(self.get_json()) 1205 return res
1206
1207 - def __getattr__(self, name):
1208 """Gets the selected attribute.""" 1209 return self.__dict__.get(name)
1210
1211 - def __setattr__(self, name, value):
1212 """Sets the selected attribute and synchronizes dependent.""" 1213 self.__dict__[name] = value 1214 if name != 'hexrelease': 1215 self.__dict__['hexrelease'] = self.get_hexrelease()
1216
1217 - def __getitem__(self, key):
1218 "" 1219 return self.__dict__[key]
1220
1221 - def __int__(self):
1222 """ The cast operator into the bitmask which is the *hexrelease*. 1223 The cache is used without new calculation if *self.hexrelease* 1224 is present, else created by calling *get_hexrelease*. 1225 For the forced calculation only use *get_hexrelease*. :: 1226 1227 int(self) == self-bitmask 1228 1229 Args: 1230 none 1231 1232 Returns: 1233 The resulting bitmask of self as numeric value. 1234 1235 Raises: 1236 1237 pass-through 1238 1239 """ 1240 if not self.hexrelease: 1241 self.hexrelease = self.get_hexrelease() 1242 return self.hexrelease
1243
1244 - def __iter__(self):
1245 """Iterates the non-private attribute names.""" 1246 for k in self.__dict__.keys(): 1247 if k[0] != '_': 1248 yield k
1249
1250 - def __setitem__(self, key, value):
1251 """Sets the selected attribute and synchronizes dependent.""" 1252 self.__dict__[key] = value 1253 if key != 'hexrelease': 1254 self.__dict__['hexrelease'] = self.get_hexrelease()
1255
1256 - def items(self):
1257 """Gets the list of key-value tupels.""" 1258 if self.forceall: 1259 for ix in ( 1260 'category', 1261 'disttype', 1262 'dist', 1263 'distrel', 1264 'hexrelease', 1265 'compiler', 1266 'compiler_version', 1267 'c_libc_version', 1268 'c_compiler', 1269 'c_compiler_version', 1270 ): 1271 yield (ix, self[ix]) 1272 else: 1273 for ix in ( 1274 'category', 1275 'disttype', 1276 'dist', 1277 'distrel', 1278 'hexrelease', 1279 ): 1280 yield (ix, self[ix])
1281
1282 - def keys(self):
1283 """Gets the list of attribute names.""" 1284 if self.forceall: 1285 for ix in ( 1286 'category', 1287 'disttype', 1288 'dist', 1289 'distrel', 1290 'hexrelease', 1291 'compiler', 1292 'compiler_version', 1293 'c_libc_version', 1294 'c_compiler', 1295 'c_compiler_version', 1296 ): 1297 yield ix 1298 else: 1299 for ix in ( 1300 'category', 1301 'disttype', 1302 'dist', 1303 'distrel', 1304 'hexrelease', 1305 ): 1306 yield ix
1307
1308 - def values(self):
1309 """Gets the list of attribute values.""" 1310 if self.forceall: 1311 for ix in ( 1312 'category', 1313 'disttype', 1314 'dist', 1315 'distrel', 1316 'hexrelease', 1317 'compiler', 1318 'compiler_version', 1319 'c_libc_version', 1320 'c_compiler', 1321 'c_compiler_version', 1322 ): 1323 yield self[ix] 1324 else: 1325 for ix in ( 1326 'category', 1327 'disttype', 1328 'dist', 1329 'distrel', 1330 'hexrelease', 1331 ): 1332 yield self[ix]
1333
1334 - def __eq__(self, other):
1335 """ Supports standard comparison with the types 1336 *PythonDist*, and *dict*. In case of 1337 a *dict* the attributes are used as keys literally. 1338 1339 Synchronizes the hex-value of the release, and compares it with 1340 the resulting value from *other*. 1341 1342 Args: 1343 other: 1344 The instannce to be compared. :: 1345 1346 other := ( 1347 <int-16bit-mask> # compare with hexversion 1348 | <dictionary>) # compare keys only 1349 | <tuple>) # compare key-index only 1350 | <instance-of-PythonDist> # compare both hexversions 1351 ) 1352 1353 Returns: 1354 True or False. 1355 1356 Raises: 1357 KeyError 1358 1359 AttributeError 1360 1361 """ 1362 1363 res = False 1364 1365 if type(other) is int: 1366 # some special type comparison 1367 # hex id of dist and/or distrel 1368 if self.hexrelease == other: 1369 return True 1370 return False 1371 1372 elif isinstance(other, PythonDist): 1373 return self.hexrelease == other.get_hexrelease() 1374 1375 elif isinstance(other, dict): 1376 # compare selected keys only 1377 res = True 1378 for k, v in other.items(): 1379 try: 1380 if k in ("osrel_sp", "wProductType", "wSuiteMask"): 1381 if self.disttype in ('nt', 'cygwin'): 1382 res &= self.__dict__[k] == v 1383 else: 1384 res = False 1385 elif k in ("distrel_version", "osrel_version",): 1386 res &= self.__dict__['distrel_version'][:len(v)] == v 1387 elif k == "distrel": 1388 res &= self.__dict__['distrel'].startswith(v) 1389 else: 1390 res &= self.__dict__[k] == v 1391 except KeyError: 1392 res = False 1393 1394 elif isinstance(other, tuple): 1395 # compare selected keys only 1396 1397 res = True 1398 self.osrel_sp = [] 1399 _myargs = list(other) 1400 if _myargs: 1401 res &= self.category == _myargs[0] 1402 _myargs.pop(0) 1403 if _myargs: 1404 res &= self.disttype == _myargs[0] 1405 _myargs.pop(0) 1406 if _myargs: 1407 res &= self.dist == _myargs[0] 1408 _myargs.pop(0) 1409 if _myargs: 1410 res &= self.distrel == _myargs[0] 1411 _myargs.pop(0) 1412 1413 try: 1414 # jython - 32bit is a long(unsigned int) 1415 if isinstance(other, long) and self.hexrelease == other: # @UndefinedVariable 1416 return True 1417 except NameError: 1418 pass 1419 1420 return res 1421
1422 - def __ne__(self, other):
1423 '' 1424 return not self.__eq__(other)
1425
1426 - def __ge__(self, other):
1427 """The *>=* operator for the resulting *hexversion*: :: 1428 1429 self-bitmask >= other-bitmask 1430 1431 Args: 1432 other: 1433 The bitmask for operations. :: 1434 1435 other := ( 1436 <int-16bit-mask> # compare with hexversion 1437 | <dictionary>) # compare keys only 1438 | <tuple>) # compare key-index only 1439 | <instance-of-PythonDist> # compare both hexversions 1440 ) 1441 1442 Returns: 1443 True or False. 1444 1445 Raises: 1446 1447 pass-through 1448 1449 """ 1450 1451 if not self.hexrelease: 1452 self.hexrelease = self.get_hexrelease() 1453 1454 if isinstance(other, int): 1455 return self.hexrelease >= other 1456 1457 elif isinstance(other, PythonDist): 1458 return self.hexrelease >= other.get_hexrelease() 1459 1460 elif isinstance(other, dict): 1461 # use other as init parameters - simply trust or pass exception 1462 return self.hexrelease >= PythonDist(**other).get_hexrelease() 1463 1464 elif isinstance(other, tuple): 1465 return self.hexrelease >= PythonDist(*other).get_hexrelease() 1466 1467 try: 1468 # jython - 32bit is a long(unsigned int) 1469 if isinstance(other, long): # @UndefinedVariable 1470 return self.hexrelease >= other 1471 except NameError: 1472 pass 1473 1474 raise PythonIDsError("type not supported: other = " + str(other))
1475
1476 - def __le__(self, other):
1477 """The *<=* operator for the resulting *hexversion*: :: 1478 1479 self-bitmask <= other-bitmask 1480 1481 Args: 1482 other: 1483 The bitmask for operations. :: 1484 1485 other := ( 1486 <int-16bit-mask> # compare with hexversion 1487 | <dictionary>) # compare keys only 1488 | <tuple>) # compare key-index only 1489 | <instance-of-PythonDist> # compare both hexversions 1490 ) 1491 1492 Returns: 1493 The resulting bitmask as numeric value. 1494 1495 Raises: 1496 1497 pass-through 1498 1499 """ 1500 if not self.hexrelease: 1501 self.hexrelease = self.get_hexrelease() 1502 1503 if isinstance(other, int): 1504 return self.hexrelease <= other 1505 1506 elif isinstance(other, PythonDist): 1507 return self.hexrelease <= other.get_hexrelease() 1508 1509 elif isinstance(other, dict): 1510 # use other as init parameters - simply trust or pass exception 1511 return self.hexrelease <= PythonDist(**other).get_hexrelease() 1512 1513 elif isinstance(other, tuple): 1514 return self.hexrelease <= PythonDist(*other).get_hexrelease() 1515 1516 try: 1517 # jython - 32bit is a long(unsigned int) 1518 if isinstance(other, long): # @UndefinedVariable 1519 return self.hexrelease <= other 1520 except NameError: 1521 pass 1522 1523 raise PythonIDsError("type not supported: other = " + str(other))
1524
1525 - def __gt__(self, other):
1526 """The *>* operator for the resulting *hexversion*: :: 1527 1528 self-bitmask > other-bitmask 1529 1530 Args: 1531 other: 1532 The bitmask for operations. :: 1533 1534 other := ( 1535 <int-16bit-mask> # compare with hexversion 1536 | <dictionary>) # compare keys only 1537 | <tuple>) # compare key-index only 1538 | <instance-of-PythonDist> # compare both hexversions 1539 ) 1540 1541 Returns: 1542 True or False. 1543 1544 Raises: 1545 1546 pass-through 1547 1548 """ 1549 if not self.hexrelease: 1550 self.hexrelease = self.get_hexrelease() 1551 1552 if isinstance(other, int): 1553 return self.hexrelease > other 1554 1555 elif isinstance(other, PythonDist): 1556 return self.hexrelease > other.get_hexrelease() 1557 1558 elif isinstance(other, dict): 1559 # use other as init parameters - simply trust or pass exception 1560 return self.hexrelease > PythonDist(**other).get_hexrelease() 1561 1562 elif isinstance(other, tuple): 1563 return self.hexrelease > PythonDist(*other).get_hexrelease() 1564 1565 try: 1566 # jython - 32bit is a long(unsigned int) 1567 if isinstance(other, long): # @UndefinedVariable 1568 return self.hexrelease > other 1569 except NameError: 1570 pass 1571 1572 raise PythonIDsError("type not supported: other = " + str(other))
1573
1574 - def __lt__(self, other):
1575 """The *<* operator for the resulting *hexversion*: :: 1576 1577 self-bitmask < other-bitmask 1578 1579 Args: 1580 other: 1581 The bitmask for operations. :: 1582 1583 other := ( 1584 <int-16bit-mask> # compare with hexversion 1585 | <dictionary>) # compare keys only 1586 | <tuple>) # compare key-index only 1587 | <instance-of-PythonDist> # compare both hexversions 1588 ) 1589 1590 Returns: 1591 True or False. 1592 1593 Raises: 1594 1595 pass-through 1596 1597 """ 1598 if not self.hexrelease: 1599 self.hexrelease = self.get_hexrelease() 1600 1601 if isinstance(other, int): 1602 return self.hexrelease < other 1603 1604 elif isinstance(other, PythonDist): 1605 return self.hexrelease < other.get_hexrelease() 1606 1607 elif isinstance(other, dict): 1608 # use other as init parameters - simply trust or pass exception 1609 return self.hexrelease < PythonDist(**other).get_hexrelease() 1610 1611 elif isinstance(other, tuple): 1612 return self.hexrelease < PythonDist(*other).get_hexrelease() 1613 1614 try: 1615 # jython - 32bit is a long(unsigned int) 1616 if isinstance(other, long): # @UndefinedVariable 1617 return self.hexrelease < other 1618 except NameError: 1619 pass 1620 1621 raise PythonIDsError("type not supported: other = " + str(other))
1622
1623 - def __repr__(self):
1624 """The standard representation. The contained attributes are represented as 1625 numeric 32bit-enums and values, for example: :: 1626 1627 res = {"category": 2147483648, "disttype": 0, "dist": 0, "distrel": 595591168, "hexrelease": 2743074816} 1628 1629 """ 1630 res = ( 1631 '{"category": 0x%08x, "disttype": 0x%08x, "dist": 0x%08x, ' 1632 '"distrel": 0x%08x, "hexrelease": 0x%08x') % ( 1633 self.category, 1634 self.disttype, 1635 self.dist, 1636 self.distrel, 1637 self.hexrelease, 1638 ) 1639 if self.forceall: 1640 res += ', "compiler": "%s"' % (self.compiler) 1641 res += ', "compiler_version": "%s"' % (self.compiler_version) 1642 if PYDIST & PYE_DIST == PYE_PYPY: 1643 res += ', "c_compiler": "%s"' % (self.c_compiler) 1644 res += ', "c_compiler_version": "%s"' % (self.c_compiler_version) 1645 1646 res += "}" 1647 1648 return res
1649
1650 - def __and__(self, other):
1651 """The *&* operator for the resulting *hexversion*: :: 1652 1653 self-bitmask & other-bitmask 1654 1655 Args: 1656 other: 1657 The bitmask for operations. :: 1658 1659 other := ( 1660 <int-16bit-mask> # compare with hexversion 1661 | <dictionary>) # compare keys only 1662 | <tuple>) # compare key-index only 1663 | <instance-of-PythonDist> # compare both hexversions 1664 ) 1665 1666 Returns: 1667 The resulting bitmask as numeric value. 1668 1669 Raises: 1670 1671 pass-through 1672 1673 """ 1674 1675 if not self.hexrelease: 1676 self.hexrelease = self.get_hexrelease() 1677 1678 if isinstance(other, int): 1679 return self.hexrelease & other 1680 1681 elif isinstance(other, PythonDist): 1682 return self.hexrelease & other.get_hexrelease() 1683 1684 elif isinstance(other, dict): 1685 # use other as init parameters - simply trust or pass exception 1686 return self.hexrelease & PythonDist(**other).get_hexrelease() 1687 1688 elif isinstance(other, tuple): 1689 return self.hexrelease & PythonDist(*other).get_hexrelease() 1690 1691 try: 1692 # jython - 32bit is a long(unsigned int) 1693 if isinstance(other, long): # @UndefinedVariable 1694 return self.hexrelease & other 1695 except NameError: 1696 pass 1697 1698 raise PythonIDsError("type not supported: other = " + str(other))
1699
1700 - def __iand__(self, other):
1701 """The in-place *&* operator for the resulting *hexversion*: :: 1702 1703 self-bitmask &= other-bitmask 1704 1705 Args: 1706 other: 1707 The bitmask for operations. :: 1708 1709 other := ( 1710 <int-16bit-mask> # compare with hexversion 1711 | <dictionary>) # compare keys only 1712 | <tuple>) # compare key-index only 1713 | <instance-of-PythonDist> # compare both hexversions 1714 ) 1715 1716 Returns: 1717 The resulting bitmask as numeric value. 1718 1719 Raises: 1720 1721 pass-through 1722 1723 """ 1724 if not self.hexrelease: 1725 self.hexrelease = self.get_hexrelease() 1726 1727 if isinstance(other, int): 1728 self.hexrelease &= other 1729 1730 elif isinstance(other, PythonDist): 1731 self.hexrelease &= other.get_hexrelease() 1732 1733 elif isinstance(other, dict): 1734 self.hexrelease &= PythonDist(**other).get_hexrelease() 1735 1736 elif isinstance(other, tuple): 1737 self.hexrelease &= PythonDist(*other).get_hexrelease() 1738 else: 1739 raise PythonIDsError("type not supported: other = " + str(other)) 1740 1741 try: 1742 # jython - 32bit is a long(unsigned int) 1743 if isinstance(other, long): # @UndefinedVariable 1744 self.hexrelease &= other 1745 except NameError: 1746 pass 1747 1748 self.category, self.disttype, self.dist, self.distrel = decode_pydist_32bit_to_tuple(self.hexrelease) 1749 return self
1750
1751 - def __ior__(self, other):
1752 """The in-place *|* operator for the resulting *hexversion*: :: 1753 1754 self-bitmask |= other-bitmask 1755 1756 Args: 1757 other: 1758 The bitmask for operations. :: 1759 1760 other := ( 1761 <int-16bit-mask> # compare with hexversion 1762 | <dictionary>) # compare keys only 1763 | <tuple>) # compare key-index only 1764 | <instance-of-PythonDist> # compare both hexversions 1765 ) 1766 1767 Returns: 1768 The resulting bitmask as numeric value. 1769 1770 Raises: 1771 1772 pass-through 1773 1774 """ 1775 if not self.hexrelease: 1776 self.hexrelease = self.get_hexrelease() 1777 1778 if isinstance(other, int): 1779 self.hexrelease |= other 1780 return self 1781 1782 elif isinstance(other, PythonDist): 1783 self.hexrelease |= other.get_hexrelease() 1784 return self 1785 1786 elif isinstance(other, dict): 1787 self.hexrelease |= PythonDist(**other).get_hexrelease() 1788 return self 1789 1790 elif isinstance(other, tuple): 1791 self.hexrelease |= PythonDist(*other).get_hexrelease() 1792 return self 1793 1794 try: 1795 # jython - 32bit is a long(unsigned int) 1796 if isinstance(other, long): # @UndefinedVariable 1797 self.hexrelease |= other 1798 return self 1799 except NameError: 1800 pass 1801 1802 raise PythonIDsError("type not supported: other = " + str(other))
1803
1804 - def __or__(self, other):
1805 """The *|* operator for the resulting *hexversion*: :: 1806 1807 self-bitmask | other-bitmask 1808 1809 Args: 1810 other: 1811 The bitmask for operations. :: 1812 1813 other := ( 1814 <int-16bit-mask> # compare with hexversion 1815 | <dictionary>) # compare keys only 1816 | <tuple>) # compare key-index only 1817 | <instance-of-PythonDist> # compare both hexversions 1818 ) 1819 1820 Returns: 1821 The resulting bitmask as numeric value. 1822 1823 Raises: 1824 1825 pass-through 1826 1827 """ 1828 if not self.hexrelease: 1829 self.hexrelease = self.get_hexrelease() 1830 1831 if isinstance(other, int): 1832 return self.hexrelease | other 1833 1834 elif isinstance(other, PythonDist): 1835 return self.hexrelease | other.get_hexrelease() 1836 1837 elif isinstance(other, dict): 1838 # use other as init parameters - simply trust or pass exception 1839 return self.hexrelease | PythonDist(**other).get_hexrelease() 1840 1841 elif isinstance(other, tuple): 1842 return self.hexrelease | PythonDist(*other).get_hexrelease() 1843 1844 try: 1845 # jython - 32bit is a long(unsigned int) 1846 if isinstance(other, long): # @UndefinedVariable 1847 return self.hexrelease | other 1848 except NameError: 1849 pass 1850 1851 raise PythonIDsError("type not supported: other = " + str(other))
1852
1853 - def __rand__(self, other):
1854 """The r-side *&* operator for the resulting *hexversion*: :: 1855 1856 other-bitmask & self-bitmask 1857 1858 Args: 1859 other: 1860 The bitmask for operations. :: 1861 1862 other := ( 1863 <int-16bit-mask> # compare with hexversion 1864 | <dictionary>) # compare keys only 1865 | <tuple>) # compare key-index only 1866 | <instance-of-PythonDist> # compare both hexversions 1867 ) 1868 1869 Returns: 1870 The resulting bitmask as numeric value. 1871 1872 Raises: 1873 1874 pass-through 1875 1876 """ 1877 return self.__and__(other)
1878
1879 - def __ror__(self, other):
1880 """The right-side *|* operator for the resulting *hexversion*: :: 1881 1882 other-bitmask | self-bitmask 1883 1884 Args: 1885 other: 1886 The bitmask for operations. :: 1887 1888 other := ( 1889 <int-16bit-mask> # compare with hexversion 1890 | <dictionary>) # compare keys only 1891 | <tuple>) # compare key-index only 1892 | <instance-of-PythonDist> # compare both hexversions 1893 ) 1894 1895 Returns: 1896 The resulting bitmask as numeric value. 1897 1898 Raises: 1899 1900 pass-through 1901 1902 """ 1903 return self.__or__(other)
1904
1905 - def get_hexrelease(self):
1906 """ Returns the dynamically calculated hex version 1907 resulting from current values of the member attributes. 1908 When not all present, uses the available stack attributes. 1909 Does not use cached values, nor stores the result. 1910 For the use and recreation of cached values call *__int__*. 1911 """ 1912 try: 1913 return self.category | self.disttype | self.dist | self.distrel 1914 except (TypeError, KeyError): 1915 # basically for bootstrap of __init__ only 1916 res = 0 1917 try: 1918 res |= self.category 1919 except: 1920 pass 1921 try: 1922 res |= self.disttype 1923 except: 1924 pass 1925 try: 1926 res |= self.dist 1927 except: 1928 pass 1929 try: 1930 res |= self.distrel 1931 except: 1932 pass 1933 return res
1934
1935 - def get_json(self, **kargs):
1936 """Returns an in-memory structure compatible to the package 'json'. 1937 1938 forceall: 1939 Includes all available information:: 1940 1941 forceall := ( 1942 True # including the compiler of the interpreter 1943 | False # the interpreter data only 1944 ) 1945 1946 valuetype: 1947 Defines the representation of the values - where possible:: 1948 1949 valuetype := ( 1950 raw # original internal value 1951 | sym # mapped to symbolic names 1952 # json and python do not define a native hex type 1953 ) 1954 1955 default := sym 1956 1957 Returns: 1958 Formatted string. 1959 1960 Raises: 1961 pass-through 1962 1963 """ 1964 res = {} 1965 _valuetype = kargs.get('valuetype', self.raw) 1966 def maptostr(r): 1967 if _valuetype == 'raw': 1968 return r 1969 else: 1970 try: 1971 return str(num2name[r]) 1972 except KeyError: 1973 return r
1974 1975 res["category"] = maptostr(self.category) 1976 res["disttype"] = maptostr(self.disttype) 1977 res["dist"] = maptostr(self.dist) 1978 res["distrel"] = maptostr(self.distrel) 1979 res["hexrelease"] = self.hexrelease 1980 1981 if self.forceall: 1982 res["compiler"] = str(self.compiler) 1983 res["compiler_version"] = str('.'.join(str(i) for i in self.compiler_version_tuple)) 1984 if PYDIST & PYE_DIST == PYE_PYPY: 1985 res["compiler"] = str(self.c_compiler) 1986 res["compiler_version"] = str('.'.join(str(i) for i in self.c_compiler_version_tuple)) 1987 1988 res["implementation"] = str(sys.executable) 1989 1990 return res 1991 1992 # 1993 # the default is with core attributes only - which almost for sure must not raise exceptions at all 1994 # 1995 PYDIST_DATA = PythonDist(forceall=True) #: Creates the object for the current runtime environment and scans the parameters. 1996 PYDIST_DATA.scan() 1997 1998 1999 PYDIST = PYDIST_DATA.get_hexrelease() #: Sets the hex value for fast access based on PYDIST_DATA, 2000 2001 if (PYDIST & PYE_DIST) == PYE_JYTHON: 2002 # Jython knows the type long - and casts to it from 32bit on 2003 isJython = True 2004 ISINT = (int, long,) # @UndefinedVariable 2005 ISNUM = (int, float, long,) # @UndefinedVariable 2006 2007 else: 2008 isJython = False 2009 ISINT = (int,) 2010 ISNUM = (int, float,) # @UndefinedVariable 2011