Source code for pythonids.pythondist

# -*- coding: utf-8 -*-
"""*pythonids.pythondist* provides information about the Python implementation.

Raises 'pythonids.PythonIDsImplementationError' when implementation is not supported.
"""
#############################################
#
# See manuals for the detailed API.
#
#############################################

import sys
try:
    import platform
    import re

except:
    #
    # missing *platform* and/or *re* requires various special code-sections
    # possible supported are currently MicroPython and CircuitPython
    # see 'pythonids.implementation'
    #

    from pythonids import PythonIDsImplementationError
    try:
        raise PythonIDsImplementationError("use implementation module for: " + str(sys.implementation))  # @UndefinedVariable
    except:
        raise PythonIDsImplementationError("implementation is not supported")

from collections import namedtuple

import pythonids
from pythonids import PythonIDsError, ISSTR, decode_pysyntax_str_to_num


__author__ = 'Arno-Can Uestuensoez'
__license__ = "Artistic-License-2.0 + Forced-Fairplay-Constraints"
__copyright__ = "Copyright (C) 2010-2018 Arno-Can Uestuensoez" \
                " @Ingenieurbuero Arno-Can Uestuensoez"
__version__ = '0.1.35'
__uuid__ = "5624dc41-775a-4d17-ac42-14a0d5c41d1a"

__docformat__ = "restructuredtext en"


#
# the empty record
#
PYE_EMPTY = 0x00000000

#
# separation masks 
#
# the combined vector semantics os separation masks is separative,
# thus no hierarchical semantics
#

# category type bits - for structural integrity
PYE_CATEGORY = 0x80000000  # bit 31 only - constant 1 for Python

# syntax type bits
PYE_SYNTAXTYPE = 0x7f800000  # major + minor
PYE_SYNTAXTYPE_MAJOR = 0x70000000  # major
PYE_SYNTAXTYPE_MINOR = 0x0f800000  # minor

# distribution type bits
PYE_DIST = 0x007c0000  # dist enum

# distribution release version bits
PYE_DISTREL = 0x0003ffff  # major + minor + micro
PYE_DISTREL_MAJOR = 0x0003f000  # major
PYE_DISTREL_MINOR = 0x00000fc0  # minor
PYE_DISTREL_MICRO = 0x0000003f  # micro


#
# category: constant PYE_PYTHOPN
#
# : CPython is basically the reference implementation of the Python Foundation @python.org 
#
PYE_PYTHON = 0x80000000  # this value is ignored
PYE_PYTHON_PRETTY = 'Python'
PYE_PYTHON_NAME = 'python'

#
# disttype - the predefined values cover the major and minor version only
# see manual: pythonids/python_categorization.html#bit-mask-layout
#
PYE_PYTHON27 = 0x23800000  # Python2.7
PYE_PYTHON35 = 0x32800000  # Python3.5
PYE_PYTHON36 = 0x33000000  # Python3.6
PYE_PYTHON37 = 0x33800000  # Python3.7
PYE_PYTHON38 = 0x34000000  # Python3.8
PYE_PYTHON39 = 0x34800000  # Python3.9

#
# dist - the distribution may define it's own variant of the core reference syntax including another set of stdlibs
#

# : CPython is basically the reference implementation of the Python Foundation @python.org 
PYE_CPYTHON = 0x00040000  # nr: 1
PYE_CPYTHON_PRETTY = 'CPython'
PYE_CPYTHON_NAME = 'cpython'

# : The variant of MicroPython for tiney devices and IoT by Adafruit inc.
PYE_CIRCUITPYTHON = 0x00080000  # nr: 2
PYE_CIRCUITPYTHON_PRETTY = 'CircuitPython'
PYE_CIRCUITPYTHON_NAME = 'circuitpython'

# : Python with extensions compilation into C-like results 
PYE_CYTHON = 0x000c0000  # nr: 3
PYE_CYTHON_PRETTY = 'Cython'
PYE_CYTHON_NAME = 'cython'

# : Pynteractive Python with a smart command line interface too - beneath it's GUI capabilities.
PYE_IPYTHON = 0x00100000  # nr: 4
PYE_IPYTHON_PRETTY = 'iPython'
PYE_IPYTHON_NAME = 'ipython'

# : The Python variant specialized on .NET and mono runtime platforms - so basically targeting Windows environments
PYE_IRONPYTHON = 0x00140000  # nr: 5
PYE_IRONPYTHON_PRETTY = 'IronPython'
PYE_IRONPYTHON_NAME = 'ironpython'

# : Java JVM and JIT based Python
PYE_JYTHON = 0x00180000  # nr: 6
PYE_JYTHON_PRETTY = 'Jython'
PYE_JYTHON_NAME = 'jython'

# : The crowd funded variant of Python with a schedular, basically replacing a shell and OS by pure and only Python with optional C-plugins 
PYE_MICROPYTHON = 0x001c0000  # nr: 7
PYE_MICROPYTHON_PRETTY = 'MicroPython'
PYE_MICROPYTHON_NAME = 'micropython'

PYE_PYPY = 0x00200000  # nr: 8
PYE_PYPY_PRETTY = 'PyPy'
PYE_PYPY_NAME = 'pypy'

#
# Some reference values of 32bit hexrelease for test and validation.
# E.g. valid as:
#
#   pythonids.pydist.PythonDist.hexrelease
#
PYE_PYDIST_CPYTHON2715 = 0xa38421cf  #: CPython-2.7.15   - Python2.7
PYE_PYDIST_CPYTHON372 = 0xb38431c2  #: CPython-3.7.2    - Python3.7
PYE_PYDIST_IPYTHON550 = 0xA3905140  #: IPython-5.5.0    - Python2.7
PYE_PYDIST_IPYTHON560 = 0xA3905180  # IPython-5.6.0    - Python2.7
PYE_PYDIST_IRONPYTHON277 = 0xA39421C7  #: IRonPython-2.7.7 - Python2.7
PYE_PYDIST_IRONPYTHON279 = 0xA39421C9  #: IRonPython-2.7.9 - Python2.7
PYE_PYDIST_JYTHON270 = 0xA39821C0  #: Jython-2.7.0     - Python2.7
PYE_PYDIST_JYTHON271 = 0xA39821C1  #: Jython-2.7.1     - Python2.7
PYE_PYDIST_PYPY580 = 0xA3A05200  #: PyPy-5.8.0       - Python2.7
PYE_PYDIST_PYPY60027 = 0xA3A06000  #: PyPy-6.0.0       - Python2.7
PYE_PYDIST_PYPY60035 = 0xB2A06000  #: PyPy-6.0.0       - Python3.5
PYE_PYDIST_PYPY70036 = 0xB3207000  #: PyPy-7.0.0       - Python3.6

dist2num = {
    PYE_CIRCUITPYTHON: PYE_CIRCUITPYTHON,
    PYE_CIRCUITPYTHON_NAME: PYE_CIRCUITPYTHON,
    PYE_CIRCUITPYTHON_PRETTY: PYE_CIRCUITPYTHON,
    PYE_CPYTHON: PYE_CPYTHON,
    PYE_CPYTHON_NAME: PYE_CPYTHON,
    PYE_CPYTHON_PRETTY: PYE_CPYTHON,
    PYE_CYTHON: PYE_CYTHON,
    PYE_CYTHON_NAME: PYE_CYTHON,
    PYE_CYTHON_PRETTY: PYE_CYTHON,
    PYE_IPYTHON: PYE_IPYTHON,
    PYE_IPYTHON_NAME: PYE_IPYTHON,
    PYE_IPYTHON_PRETTY: PYE_IPYTHON,
    PYE_IRONPYTHON: PYE_IRONPYTHON,
    PYE_IRONPYTHON_NAME: PYE_IRONPYTHON,
    PYE_IRONPYTHON_PRETTY: PYE_IRONPYTHON,
    PYE_JYTHON: PYE_JYTHON,
    PYE_JYTHON_NAME: PYE_JYTHON,
    PYE_JYTHON_PRETTY: PYE_JYTHON,
    PYE_MICROPYTHON: PYE_MICROPYTHON,
    PYE_MICROPYTHON_NAME: PYE_MICROPYTHON,
    PYE_MICROPYTHON_PRETTY: PYE_MICROPYTHON,
    PYE_PYPY: PYE_PYPY,
    PYE_PYPY_NAME: PYE_PYPY,
    PYE_PYPY_PRETTY: PYE_PYPY,
    PYE_PYTHON: PYE_PYTHON,
    PYE_PYTHON_PRETTY: PYE_PYTHON,
    PYE_PYTHON_NAME: PYE_PYTHON,
    PYE_PYTHON27: PYE_PYTHON27,
    PYE_PYTHON35: PYE_PYTHON35,
    PYE_PYTHON36: PYE_PYTHON36,
    PYE_PYTHON37: PYE_PYTHON37,
    PYE_PYTHON38: PYE_PYTHON38,
    PYE_PYTHON39: PYE_PYTHON39,
}

num2name = {
    PYE_EMPTY: "",
    PYE_CPYTHON: PYE_CPYTHON_NAME,
    PYE_IPYTHON: PYE_IPYTHON_NAME,
    PYE_IRONPYTHON: PYE_IRONPYTHON_NAME,
    PYE_JYTHON: PYE_JYTHON_NAME,
    PYE_PYPY: PYE_PYPY_NAME,
    PYE_PYTHON: PYE_PYTHON_NAME,
    PYE_PYTHON27: "python2.7",
    PYE_PYTHON35: "python3.5",
    PYE_PYTHON36: "python3.6",
    PYE_PYTHON37: "python3.7",
    PYE_PYTHON38: "python3.8",
    PYE_PYTHON39: "python3.9",
}

num2pretty = {
    PYE_EMPTY: "",
    PYE_CPYTHON: PYE_CPYTHON_PRETTY,
    PYE_IPYTHON: PYE_IPYTHON_PRETTY,
    PYE_IRONPYTHON: PYE_IRONPYTHON_PRETTY,
    PYE_JYTHON: PYE_JYTHON_PRETTY,
    PYE_PYPY: PYE_PYPY_PRETTY,
    PYE_PYTHON: PYE_PYTHON_PRETTY,
    PYE_PYTHON27: "Python-2.7",
    PYE_PYTHON35: "Python-3.5",
    PYE_PYTHON36: "Python-3.6",
    PYE_PYTHON37: "Python-3.7",
    PYE_PYTHON38: "Python-3.8",
    PYE_PYTHON39: "Python-3.9",
}

#
# static parsers
#
SPLITVERS = re.compile(r'(?s)(^[0-9]+)[.]([0-9]*)[.]([0-9]*).*')
SPLITVERS2 = re.compile(r'(?s)(^[0-9]+)[.]([0-9]*).*')
STR2DISTREL = re.compile(r'([0-9.]*)[^0-9]*')

# : The corresponding *bash* environment names.
bash_map = {
    'category': "PYDIST_CATEGORY",
    'disttype': "PYDIST_DISTTYPE",
    'dist': "PYDIST_DIST",
    'distrel': "PYDIST_DISTREL",
    'hexrelease': "PYDIST_DISTREL_HEXVERSION",
    'compiler': "PYDIST_COMPILER",
    'compiler_version': "PYDIST_COMPILER_VERSION",
    'c_libc_version': "PYDIST_C_LIBC_VERSION",
    'c_compiler': "PYDIST_C_COMPILER",
    'c_compiler_version': "PYDIST_C_COMPILER_VERSION",
}

# : The mapping of attributes to values.
attribute_map = {
    'category': "category",
    'disttype': "disttype",
    'dist': "dist",
    'distrel': "distrel",
    'hexrelease': "hexrelease",
    'compiler': "compiler",
    'compiler_version': "compiler_version",
    'c_libc_version': "c_libc_version",
    'c_compiler': "c_compiler",
    'c_compiler_version': "c_compiler_version",
}


#: Named tuple for structured results. See *collections.namedtuple*.
PyDist = namedtuple('PyDist', ('category', 'disttype', 'dist', 'distrel')) 

#: Named tuple for structured results as sub-parts. See *collections.namedtuple*.
PyDistSegments = namedtuple('PyDistSegments', ('category', 'disttype', 'dist', 'distrel')) 

#: Named tuple for structured results as *str*. See *collections.namedtuple*.
PyDistStr = namedtuple('PyDistStr', ('category', 'disttype', 'dist', 'distrel')) 

[docs]class PythonDistError(PythonIDsError): pass
def _encode_distrel_bitmask(dx=0, dy=0, dz=0): # 32bit - dx.dy.dz return ( (dx & 63) << 12 # bit 17 - 12 - see version_info[0] | (dy & 63) << 6 # bit 11 - 6 - see version_info[1] | (dz & 63) # bit 5 - 0 - see version_info[2] ) def _encode_distrel_str_bitmask(sxyz=''): # 32bit res = STR2DISTREL.sub(r'\1', sxyz).split('.') # variable length if len(res) == 3: return ( (int(res[0]) & 63) << 12 # bit 17 - 12 - see version_info[0] | (int(res[1]) & 63) << 6 # bit 11 - 6 - see version_info[1] | (int(res[2]) & 63) # bit 5 - 0 - see version_info[2] ) elif len(res) == 2: return ( (int(res[0]) & 63) << 12 # bit 17 - 12 - see version_info[0] | (int(res[1]) & 63) << 6 # bit 11 - 6 - see version_info[1] ) elif len(res) == 1: return ( (int(res[0]) & 63) << 12 # bit 17 - 12 - see version_info[0] ) return () def _encode_disttype_bitmask(sma=0, smi=0): # 32bit return ( (sma & 7) << 28 # bit 30 - 28 - see version_info[0] | (smi & 31) << 23 # bit 27 - 23 - see version_info[1] ) def _encode_disttype_str_bitmask(sxy=''): # 32bit res = STR2DISTREL.sub(r'\1', sxy).split('.') # variable length if len(res) >= 2: return ( (int(res[0]) & 7) << 28 # bit 17 - 12 - see version_info[0] | (int(res[1]) & 31) << 23 # bit 11 - 6 - see version_info[1] ) elif len(res) == 1: return ( (int(res[0]) & 63) << 12 # bit 17 - 12 - see version_info[0] ) return ()
[docs]def decode_pydist_32bit_to_tuple_str(ddat=0): """ Decodes the 32bit hex representation of the Python distribution into a dict structure with str names and str representation of releases. Args: ddat: The 32bit value. Returns: Dictionary with components: :: result := { 'category': 'python', 'styntaxtype': <str-syntax-release>, 'dist': <dist-name>, 'distrel': <str-dist-release> } category: canonical str name str-syntax-release: string representation dist: canonical str name str-dist-release: string representation Raises: pass-through """ try: _syn = num2name[ddat & PYE_SYNTAXTYPE] except KeyError: _syn = '' try: _dis = num2name[ddat & PYE_DIST] except KeyError: _dis = '' if _dis or (ddat & PYE_DISTREL): _disrel = "%d.%d.%d" % ( (ddat & PYE_DISTREL_MAJOR) >> 12, (ddat & PYE_DISTREL_MINOR) >> 6, ddat & PYE_DISTREL_MICRO, ) else: _disrel = '' return PyDistStr( PYE_PYTHON_NAME, _syn, _dis, _disrel, )
[docs]def decode_pydist_32bit_to_tuple_segments(ddat=0): """ Decodes the 32bit hex representation of the Python distribution into a dict structure with str names and numeric release vectors. Args: ddat: The 32bit value. Returns: Nametupel with the components: :: PyDist = namedtuple('PyDist', ('category', 'disttype', 'dist', 'distrel')) result := PyDist( PYE_PYTHON, (<syntax-major>,<syntax-minor>), <32bit-dist>, (<dist-major>, <dist-minor>, <dist-micro>) ) PYE_PYTHON: 32bit-enum for category 32bit-syntax-release: 32bit-value for syntax release 32bit-dist: 32bit-enum for distribution 32bit-dist-release: 32bit-value for distribution release Dictionary with components: :: result := { 'category': 'python', 'styntaxtype': (<syntax-major>,<syntax-minor>), 'dist': <dist-name>, 'distrel': (<dist-major>, <dist-minor>, <dist-micro>) } category: canonical str name syntax-major: int value syntax-minor: int value dist: canonical str name dist-major: int value dist-minor: int value dist-micro: int value Raises: pass-through """ return PyDistSegments( PYE_PYTHON >> 31, # the only and one ( (ddat & PYE_SYNTAXTYPE_MAJOR) >> 28, (ddat & PYE_SYNTAXTYPE_MINOR) >> 23, ), (ddat & PYE_DIST) >> 18, ( (ddat & PYE_DISTREL_MAJOR) >> 12, (ddat & PYE_DISTREL_MINOR) >> 6, ddat & PYE_DISTREL_MICRO, ) )
[docs]def decode_pydist_32bit_to_tuple(ddat=0): """ Decodes the 32bit hex representation of the Python distribution into a flat tuple of numbers. Args: ddat: The 32bit value. Returns: Nametupel with the components: :: PyDist = namedtuple('PyDist', ('category', 'disttype', 'dist', 'distrel')) result := PyDist( PYE_PYTHON, <32bit-syntax-release>, <32bit-dist>, <32bit-dist-release> ) PYE_PYTHON: 32bit-enum for category 32bit-syntax-release: 32bit-value for syntax release 32bit-dist: 32bit-enum for distribution 32bit-dist-release: 32bit-value for distribution release Raises: pass-through """ return PyDist( ddat & PYE_CATEGORY, ddat & PYE_SYNTAXTYPE, ddat & PYE_DIST, ddat & PYE_DISTREL, )
[docs]def encode_pydist_to_32bit(d=0, dx=0, dy=0, dz=0, sma=0, smi=0): """ Encodes the Python distribution by calculating the 32bit integer bitmask for the provided Python distribution and syntax release information. Args: d: The numeric enum value of the distribution with original bit-positions. dx: The major distribution version number. dy: The minor distribution version number. dz: The micro distribution version number. sma: The major syntax version number. smi: The minor syntax version number. Returns: The 32bit bitmask. See `Python Distribution Categorization <python_categorization.html>`_. Raises: pass-through """ return ( PYE_PYTHON # here anything is category=Python | d # distribution enum in it's original bit positions | (dx & 63) << 12 # bit 17 - 12 - see version_info[0] | (dy & 63) << 6 # bit 11 - 6 - see version_info[1] | (dz & 63) # bit 5 - 0 - see version_info[2] | (sma & 7) << 28 # bit 30 - 28 - see version_info[0] | (smi & 31) << 23 # bit 27 - 23 - see version_info[1] )
[docs]def encode_pydist_segments_to_32bit(**kargs): """ Encodes the 32bit bitmask of the compressed platform information by the provided values of the sub fields. Non-provided values are set to *0*, and though ignored. This function is mainly designed and foreseen for cache preparation and test environments, though it inherently requires some of the systems performance. Thus do not use it within repetitive calls for performance critical large scale loops with small code sections. Args: kargs: category: The category. The only and one permitted is *Python*: :: category := ( PYE_PYTHON # enum | 'Python' # Pretty name | 'python' # key | 0 # None ) default := 0 dist: The dist: :: dist := ( PYE_CPYTHON | PYE_IPYTHON | PYE_IRONPYTHON | PYE_JYTHON | PYE_PYPY | PYE_CIRCUITPYTHON | PYE_MICROPYTHON | <known-name-of-dist> | 0 ) known-name-of-dist := "case insensitive name or pretty name of the distribution" 0 := None default:=0 distrel: The distrel: :: distrel := ( <int-val> | (<major>, <minor>, <micro>) | 0 ) int-val := the relative integer value of the distrel bits (<major>, <minor>, <micro>):= the tuple of the Python distribution release 0 := None default := 0 disttype: The disttype: :: disttype := ( <int-val> | (<major>, <minor>) | 0 ) int-val := the relative integer value of the disttype bits (<major>, <minor>) := the tuple of Python syntax version 0 := None default := 0 Returns: The 32bit compressed bitmask of the of the distribution. Raises: pass-through """ category = kargs.get('category', 0) if kargs.get('category'): category = 1 dist = kargs.get('dist', 0) try: if isinstance(dist, ISSTR): dist = dist2num[dist.lower()] except KeyError as e: # sys.stderr.write("ERROR: unknown dist: " + str(dist)) e += "\nERROR: unknown dist: %s\n" % (str(dist)) raise distrel = kargs.get('distrel', 0) if isinstance(distrel, (tuple, list)): distrel = distrel[0] << 12 | distrel[1] << 6 | distrel[2] elif isinstance(distrel, ISSTR): distrel = decode_pysyntax_str_to_num(distrel) disttype = kargs.get('disttype', 0) if isinstance(disttype, (tuple, list)): disttype = int(disttype[0]) << 5 | int(disttype[1]) elif isinstance(disttype, ISSTR): disttype = decode_pysyntax_str_to_num(disttype) disttype = int(disttype[0]) << 5 | int(disttype[1]) # ignore [3] return ( category << 31 | disttype << 23 | dist | distrel )
[docs]class PythonDist(object):
[docs] def __init__(self, *args, **kargs): """ Creates an empty object. The instance could be either initialized by the provided parameters, or remains empty - which is zero *0*. Provides *PythonDist.scan()* for the readout of the implementation information. The *scan()* is not called automatic. Each call of *scan()* replaces the previous values. Args: args: Optional positional parameters in the following order. The corresponding keyword-arguments dominate. :: *args := [category [, disttype [, dist [, distrel]]]] kargs: category: The registered *category* for initialization. default := 0 disttype: The registered *disttype* for initialization. default := 0 dist: The registered *dist* for initialization. default := 0 distrel: The registered *distrel* for initialization. default := 0 forceall: Controls the default for the scan of content: :: forceall := ( True # scan distribution and compiler | False # scan distribution only ) default := False valuetype: Defines the representation of the values - where possible:: valuetype := ( raw # original internal value | hex # as hex | sym # mapped to symbolic names ) default := sym Returns: Initial instance, optionally initialized by the provided parameters. Raises: PythonIDsError pass-through """ self.valuetype = kargs.get('valuetype', False) self.category = PYE_PYTHON # : the category ID self.disttype = 0 # : the type ID of the syntax self.hexrelease = 0 # : the resulting hex release self.dist = 0 # : the distribution ID self.distrel = 0 # : the release of the distribution self.compiler = '' self.compiler_version = 0 self.compiler_version_tuple = (0, 0, 0,) self.c_libc_version = 0 self.c_compiler = '' self.c_compiler_version = 0 self.forceall = kargs.get('forceall', False) # : control the optional part of the scan self.osrel_sp = [] if args: try: # 0 _x = args[0] try: # the category, currently only one: Python self.category = dist2num[_x] & PYE_CATEGORY except KeyError: raise PythonIDsError("'category' not registered: " + str(_x)) try: # 1 _x = args[1] try: # the syntax type of the distribution # defined by Python syntax version <major>.<minor> self.disttype = dist2num[_x] & PYE_SYNTAXTYPE except KeyError: if not type(_x) is int: # cannot map raise PythonIDsError("'disttype' not registered: " + str(_x)) self.dist = _x & PYE_SYNTAXTYPE try: # 2 _x = args[2] try: # the implementation, current supported: CPython, IPython, IronPython, Jython, PyPy self.dist = dist2num[_x] & PYE_DIST except KeyError: raise PythonIDsError("'dist' not registered: " + str(_x)) try: # 3 _x = args[3] try: # the release version <major>.<minor>.<micro> self.distrel = dist2num[_x] & PYE_DISTREL except KeyError: if not type(_x) is int: # cannot be mapped raise PythonIDsError("'distrel' not registered: " + str(_x)) # any release version is supported self.distrel = _x & PYE_DISTREL except KeyError: pass except KeyError: pass except KeyError: pass except KeyError: pass # keyword arguments dominate self.category = kargs.get('category', self.category) self.disttype = kargs.get('disttype', self.disttype) self.dist = kargs.get('dist', self.dist) self.distrel = kargs.get('distrel', self.distrel) self.hexrelease = self.get_hexrelease()
[docs] def get_distribution(self, rtype=PyDist): """ Reads out the distribution data into a tuple of selected type. Args: rtype: The return type: .. parsed-literal:: rtype := ( :ref:`PyDist <SPEC_PyDist_Class>` | :ref:`PyDistSegments <SPEC_PyDistSegments>` | :ref:`PyDistStr <SPEC_PyDistStr>` | tuple | <user-defined-tuple-type> ) default := :ref:`PyDist <SPEC_PyDist_Class>` Returns: Returns a tuple of the provided attributes: :: ( category, disttype, dist, distrel ) Raises: pass-through """ if rtype == PyDist: return PyDist( self.category, self.disttype, self.dist, self.distrel, ) elif rtype == PyDistStr: return PyDistStr( str(self.category), str(self.disttype), str(self.dist), str(self.distrel), ) elif rtype == PyDistSegments: return decode_pydist_32bit_to_tuple_segments(self.get_hexrelease()) else: # expect a pure tuple type return rtype( self.category, self.disttype, self.dist, self.distrel, )
[docs] def scan(self, forceall=None): """Scans local platform for attributes specifying the platform. Supports: :: CPython, iPython, IronPython, Jython, PyPy Args: forceall: Controls the scan content: :: forceall := ( True # scan distribution and compiler | False # scan distribution only ) default := None Returns: Superposes the following mandatory attributes by the scanned values: * The tuple of Python identifiers: :: category disttype dist distrel * Additional shortcuts prepared for direct processing: :: hexrelease * In addition the optional, but strongly supported attributes. These are scanned only in case of *forceall==True*. :: c_libc_version c_compiler c_compiler_version Returns the value of *hexrelease*. Raises: PythonDistError """ if forceall == None: _forceall = self.forceall else: _forceall = forceall # # syntax category # self.category = PYE_PYTHON # the only and one supported, contain it for pattern consistance # # reference syntax # # _syntaxrel = platform.python_version() _syntaxrel_tuple = platform.python_version_tuple() self.disttype = _encode_disttype_bitmask(int(_syntaxrel_tuple[0]), int(_syntaxrel_tuple[1])) # # distribution # _d = platform.python_implementation() try: _dist = self.dist = dist2num[_d] except KeyError: raise PythonDistError("Distribution is not supported: " + str(_d)) if _dist in (PYE_CPYTHON, PYE_IPYTHON,): # does not distinguish CPython and IPython - which is a interactive-addon # see docu: [ARTICLESTACKOFLOWIPYTHON]_ try: __IPYTHON__ # @UndefinedVariable # running under control of IPython addons except NameError: # the standard interpreter and the reference, thus syntaxrel == distrel try: self.distrel = _encode_distrel_bitmask(*(int(x) for x in _syntaxrel_tuple[0:3])) except ValueError: # handle pre-releases, e.g. '3.8.0a5' - these are basically not supported... # these are treated with their version numbers only by dropping any alpha, beta, etc. appendix # though the pythondist package targets production system components only self.distrel = _encode_distrel_bitmask(*(int(x) for x in ( _syntaxrel_tuple[0], _syntaxrel_tuple[1], re.sub(r'^([0-9]).*', r'\1', _syntaxrel_tuple[2]) ))) else: _dist = PYE_IPYTHON # provided by the core module __version__ self.distrel = _encode_distrel_bitmask(*(int(x) for x in sys.modules['IPython'].__version__.split('.'))) elif _dist == PYE_PYPY: # # contained in the compile string # # 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)]' # ^^^^^^ ^^^^^ ^^^ ^^^^^ # _c = sys.version _cprep = re.sub( r'^([0-9.]+).*\n.*PyPy *([0-9.]+) [^ ]+ ([^ ]+) +([0-9.]+).*$', r'\1@@\2@@\3@@\4', _c, flags=re.MULTILINE) # @UndefinedVariable try: _python_version, _distrel, self.c_compiler, _c_compiler_version = _cprep.split('@@') self.distrel = _encode_distrel_str_bitmask(_distrel) except ValueError: self.distrel = 0 _c_compiler_version = '' _python_version = '' if _forceall: try: self.c_compiler_version_tuple = tuple(int(i) for i in _c_compiler_version.split('.')) except ValueError: self.c_compiler_version_tuple = (0, 0, 0,) self.c_libc_version = platform.libc_ver() # default is current instance itself self.compiler = "Python" # self.compiler_version = platform.python_version() # self.compiler_version = _python_version self.compiler_version_tuple = sys.version_info[:3] pass # else: # self.compiler = "Python" # self.compiler_version = sys.version_info[:3] elif _dist == PYE_IRONPYTHON: # # >>> platform.python_compiler() # '.NET 4.0.30319.42000 (64-bit)' # # The sys.version seems to be compatible to the python-syntax, but # in sync only with major and minor version. # The micro version seems to be independent from Python-Syntax/CPython. # Current version for simplicity just takes the whole version literally as the syntax version. # self.distrel = _encode_distrel_bitmask(*(int(x) for x in _syntaxrel_tuple[0:3])) elif _dist == PYE_JYTHON: # # the distrel seems to be the same as sys.version # and platform.python_version_tuple / platform.python_version # self.distrel = _encode_distrel_bitmask(*(int(x) for x in _syntaxrel_tuple[0:3])) # the compiler is defined by the jre # libc is empty # # >>> platform.python_compiler() -> variable JIT # 'java1.7.0_65 ( ==linux2 for targets )' if _forceall: # # extra value for the build release, due to it's importance for java-rte # _c = platform.python_compiler() # e.g. "str: java1.8.0_181" self.c_compiler, self.c_compiler_version = re.sub(r'^([^0-9]*)([0-9.]*)_([0-9]*).*$', r'\1:\2.\3', _c).split(':') self.c_compiler_version_tuple = tuple(int(i) for i in self.c_compiler_version.split('.')) self.c_libc_version = ('', (0, 0, 0, 0)) self.compiler = "Java" # self.compiler_version = platform.python_compiler()[4:] # self.compiler_version_tuple = tuple(int(i) for i in self.c_compiler_version.split('.')) self.compiler_version_tuple = self.c_compiler_version_tuple if _forceall and _dist in (PYE_CPYTHON, PYE_CYTHON, PYE_IPYTHON, PYE_IRONPYTHON): _c = platform.python_compiler() try: # e.g. 'GCC 7.3.1 20180303 (Red Hat 7.3.1-5)' self.c_compiler, self.c_compiler_version = re.sub(r'^([^ ]*)[^0-9]*([0-9.]*) .*$', r'\1:\2', _c).split(':') self.c_compiler_version_tuple = tuple(int(i) for i in self.c_compiler_version.split('.')) except: # SunOS self.c_compiler = 'C' self.c_compiler_version = '' self.c_compiler_version_tuple = (0, 0, 0,) self.c_libc_version = platform.libc_ver() # default is current instance itself self.compiler = self.c_compiler self.compiler_version = self.c_compiler_version # requires all of them to be set self.hexrelease = self.category | self.disttype | self.dist | self.distrel return self.hexrelease
[docs] def __str__(self): '' return self.pretty_format()
def pretty_format(self, **kargs): """Creates printable string of formatted information about the Python implementation. Args: kargs: forceall: Prints all available information:: forceall := ( True # print all including the compiler of the interpreter | False # print the interpreter data only ) layout: Defines the displayed layout/syntax:: layout := ( str | repr | json ) valuetype: Defines the representation of the values - where possible:: valuetype := ( raw # original internal value | hex # as hex | sym # mapped to symbolic names ) default := sym Returns: Formatted string. Raises: pass-through """ _forceall = kargs.get('forceall', self.forceall) _valuetype = kargs.get('valuetype', self.valuetype) _layout = kargs.get('layout', 'str') _hex = _valuetype == 'hex' _raw = _valuetype == 'raw' def maptostr(r): if _hex: try: return str(hex(r)) except ValueError: return str(r) if _raw: return str(r) else: try: return str(num2name[r]) except KeyError: return str(r) if _layout == 'str': res = "" _format = "%-20s= %s\n" res += _format % ("category", maptostr(self.category)) res += _format % ("disttype", maptostr(self.disttype)) res += _format % ("dist", maptostr(self.dist)) if _raw or _hex: res += _format % ("distrel", maptostr(self.distrel)) else: res += _format % ("distrel", decode_pydist_32bit_to_tuple_str(self.distrel).distrel) if _raw: res += _format % ("hexrelease", str(self.hexrelease)) else: res += _format % ("hexrelease", hex(self.hexrelease)) if _forceall: res += _format % ("compiler", str(self.compiler)) res += _format % ("compiler_version", str('.'.join(str(i) for i in self.compiler_version_tuple))) if PYDIST & PYE_DIST == PYE_PYPY: res += _format % ("compiler", str(self.c_compiler)) res += _format % ("compiler_version", str('.'.join(str(i) for i in self.c_compiler_version_tuple))) res += _format % ("implementation", str(sys.executable)) elif _layout == 'repr': res = repr(self.get_json()) # res = "{" # # _format = "\n%-20s= %s" # # try: # res += '"category": "' + maptostr(self.category) + '", ' # except KeyError: # res += '"category": "", ' # # try: # res += '"disttype": "' + maptostr(self.disttype) + '", ' # except KeyError: # res += '"disttype": "", ' # # try: # res += '"dist": "' + maptostr(self.dist) + '", ' # except KeyError: # res += '"dist": "", ' # # if _raw or _hex: # res += '"distrel": "' + maptostr(self.distrel) + '", ' # else: # res += '"distrel": "' + str(decode_pydist_32bit_to_tuple_str(self.distrel).distrel) + '", ' # # if _raw: # res += '"hexrelease": ' + str(self.hexrelease) + ', ' # else: # res += '"hexrelease": ' + str(self.hexrelease) + ', ' # # if self.forceall: # res += '"compiler": "' + str(self.compiler) + '", ' # res += '"compiler_version": "' + str('.'.join(str(i) for i in self.compiler_version_tuple)) + '", ' # if PYDIST & PYE_DIST == PYE_PYPY: # res += '"compiler": ' + str(self.c_compiler) + ', ' # res += '"compiler_version": "' + str('.'.join(str(i) for i in self.c_compiler_version_tuple)) + '", ' # # res += '"implementation": "' + str(sys.executable) + '", ' # # res += '}' elif _layout == 'json': res = str(self.get_json()) return res
[docs] def __getattr__(self, name): """Gets the selected attribute.""" return self.__dict__.get(name)
[docs] def __setattr__(self, name, value): """Sets the selected attribute and synchronizes dependent.""" self.__dict__[name] = value if name != 'hexrelease': self.__dict__['hexrelease'] = self.get_hexrelease()
[docs] def __getitem__(self, key): "" return self.__dict__[key]
[docs] def __int__(self): """ The cast operator into the bitmask which is the *hexrelease*. The cache is used without new calculation if *self.hexrelease* is present, else created by calling *get_hexrelease*. For the forced calculation only use *get_hexrelease*. :: int(self) == self-bitmask Args: none Returns: The resulting bitmask of self as numeric value. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() return self.hexrelease
[docs] def __iter__(self): """Iterates the non-private attribute names.""" for k in self.__dict__.keys(): if k[0] != '_': yield k
[docs] def __setitem__(self, key, value): """Sets the selected attribute and synchronizes dependent.""" self.__dict__[key] = value if key != 'hexrelease': self.__dict__['hexrelease'] = self.get_hexrelease()
[docs] def items(self): """Gets the list of key-value tupels.""" if self.forceall: for ix in ( 'category', 'disttype', 'dist', 'distrel', 'hexrelease', 'compiler', 'compiler_version', 'c_libc_version', 'c_compiler', 'c_compiler_version', ): yield (ix, self[ix]) else: for ix in ( 'category', 'disttype', 'dist', 'distrel', 'hexrelease', ): yield (ix, self[ix])
[docs] def keys(self): """Gets the list of attribute names.""" if self.forceall: for ix in ( 'category', 'disttype', 'dist', 'distrel', 'hexrelease', 'compiler', 'compiler_version', 'c_libc_version', 'c_compiler', 'c_compiler_version', ): yield ix else: for ix in ( 'category', 'disttype', 'dist', 'distrel', 'hexrelease', ): yield ix
[docs] def values(self): """Gets the list of attribute values.""" if self.forceall: for ix in ( 'category', 'disttype', 'dist', 'distrel', 'hexrelease', 'compiler', 'compiler_version', 'c_libc_version', 'c_compiler', 'c_compiler_version', ): yield self[ix] else: for ix in ( 'category', 'disttype', 'dist', 'distrel', 'hexrelease', ): yield self[ix]
[docs] def __eq__(self, other): """ Supports standard comparison with the types *PythonDist*, and *dict*. In case of a *dict* the attributes are used as keys literally. Synchronizes the hex-value of the release, and compares it with the resulting value from *other*. Args: other: The instannce to be compared. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: True or False. Raises: KeyError AttributeError """ res = False if type(other) is int: # some special type comparison # hex id of dist and/or distrel if self.hexrelease == other: return True return False elif isinstance(other, PythonDist): return self.hexrelease == other.get_hexrelease() elif isinstance(other, dict): # compare selected keys only res = True for k, v in other.items(): try: if k in ("osrel_sp", "wProductType", "wSuiteMask"): if self.disttype in ('nt', 'cygwin'): res &= self.__dict__[k] == v else: res = False elif k in ("distrel_version", "osrel_version",): res &= self.__dict__['distrel_version'][:len(v)] == v elif k == "distrel": res &= self.__dict__['distrel'].startswith(v) else: res &= self.__dict__[k] == v except KeyError: res = False elif isinstance(other, tuple): # compare selected keys only res = True self.osrel_sp = [] _myargs = list(other) if _myargs: res &= self.category == _myargs[0] _myargs.pop(0) if _myargs: res &= self.disttype == _myargs[0] _myargs.pop(0) if _myargs: res &= self.dist == _myargs[0] _myargs.pop(0) if _myargs: res &= self.distrel == _myargs[0] _myargs.pop(0) try: # jython - 32bit is a long(unsigned int) if isinstance(other, long) and self.hexrelease == other: # @UndefinedVariable return True except NameError: pass return res
[docs] def __ne__(self, other): '' return not self.__eq__(other)
[docs] def __ge__(self, other): """The *>=* operator for the resulting *hexversion*: :: self-bitmask >= other-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: True or False. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() if isinstance(other, int): return self.hexrelease >= other elif isinstance(other, PythonDist): return self.hexrelease >= other.get_hexrelease() elif isinstance(other, dict): # use other as init parameters - simply trust or pass exception return self.hexrelease >= PythonDist(**other).get_hexrelease() elif isinstance(other, tuple): return self.hexrelease >= PythonDist(*other).get_hexrelease() try: # jython - 32bit is a long(unsigned int) if isinstance(other, long): # @UndefinedVariable return self.hexrelease >= other except NameError: pass raise PythonIDsError("type not supported: other = " + str(other))
[docs] def __le__(self, other): """The *<=* operator for the resulting *hexversion*: :: self-bitmask <= other-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: The resulting bitmask as numeric value. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() if isinstance(other, int): return self.hexrelease <= other elif isinstance(other, PythonDist): return self.hexrelease <= other.get_hexrelease() elif isinstance(other, dict): # use other as init parameters - simply trust or pass exception return self.hexrelease <= PythonDist(**other).get_hexrelease() elif isinstance(other, tuple): return self.hexrelease <= PythonDist(*other).get_hexrelease() try: # jython - 32bit is a long(unsigned int) if isinstance(other, long): # @UndefinedVariable return self.hexrelease <= other except NameError: pass raise PythonIDsError("type not supported: other = " + str(other))
[docs] def __gt__(self, other): """The *>* operator for the resulting *hexversion*: :: self-bitmask > other-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: True or False. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() if isinstance(other, int): return self.hexrelease > other elif isinstance(other, PythonDist): return self.hexrelease > other.get_hexrelease() elif isinstance(other, dict): # use other as init parameters - simply trust or pass exception return self.hexrelease > PythonDist(**other).get_hexrelease() elif isinstance(other, tuple): return self.hexrelease > PythonDist(*other).get_hexrelease() try: # jython - 32bit is a long(unsigned int) if isinstance(other, long): # @UndefinedVariable return self.hexrelease > other except NameError: pass raise PythonIDsError("type not supported: other = " + str(other))
[docs] def __lt__(self, other): """The *<* operator for the resulting *hexversion*: :: self-bitmask < other-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: True or False. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() if isinstance(other, int): return self.hexrelease < other elif isinstance(other, PythonDist): return self.hexrelease < other.get_hexrelease() elif isinstance(other, dict): # use other as init parameters - simply trust or pass exception return self.hexrelease < PythonDist(**other).get_hexrelease() elif isinstance(other, tuple): return self.hexrelease < PythonDist(*other).get_hexrelease() try: # jython - 32bit is a long(unsigned int) if isinstance(other, long): # @UndefinedVariable return self.hexrelease < other except NameError: pass raise PythonIDsError("type not supported: other = " + str(other))
[docs] def __repr__(self): """The standard representation. The contained attributes are represented as numeric 32bit-enums and values, for example: :: res = {"category": 2147483648, "disttype": 0, "dist": 0, "distrel": 595591168, "hexrelease": 2743074816} """ res = ( '{"category": 0x%08x, "disttype": 0x%08x, "dist": 0x%08x, ' '"distrel": 0x%08x, "hexrelease": 0x%08x') % ( self.category, self.disttype, self.dist, self.distrel, self.hexrelease, ) if self.forceall: res += ', "compiler": "%s"' % (self.compiler) res += ', "compiler_version": "%s"' % (self.compiler_version) if PYDIST & PYE_DIST == PYE_PYPY: res += ', "c_compiler": "%s"' % (self.c_compiler) res += ', "c_compiler_version": "%s"' % (self.c_compiler_version) res += "}" return res
[docs] def __and__(self, other): """The *&* operator for the resulting *hexversion*: :: self-bitmask & other-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: The resulting bitmask as numeric value. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() if isinstance(other, int): return self.hexrelease & other elif isinstance(other, PythonDist): return self.hexrelease & other.get_hexrelease() elif isinstance(other, dict): # use other as init parameters - simply trust or pass exception return self.hexrelease & PythonDist(**other).get_hexrelease() elif isinstance(other, tuple): return self.hexrelease & PythonDist(*other).get_hexrelease() try: # jython - 32bit is a long(unsigned int) if isinstance(other, long): # @UndefinedVariable return self.hexrelease & other except NameError: pass raise PythonIDsError("type not supported: other = " + str(other))
[docs] def __iand__(self, other): """The in-place *&* operator for the resulting *hexversion*: :: self-bitmask &= other-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: The resulting bitmask as numeric value. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() if isinstance(other, int): self.hexrelease &= other elif isinstance(other, PythonDist): self.hexrelease &= other.get_hexrelease() elif isinstance(other, dict): self.hexrelease &= PythonDist(**other).get_hexrelease() elif isinstance(other, tuple): self.hexrelease &= PythonDist(*other).get_hexrelease() else: raise PythonIDsError("type not supported: other = " + str(other)) try: # jython - 32bit is a long(unsigned int) if isinstance(other, long): # @UndefinedVariable self.hexrelease &= other except NameError: pass self.category, self.disttype, self.dist, self.distrel = decode_pydist_32bit_to_tuple(self.hexrelease) return self
[docs] def __ior__(self, other): """The in-place *|* operator for the resulting *hexversion*: :: self-bitmask |= other-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: The resulting bitmask as numeric value. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() if isinstance(other, int): self.hexrelease |= other return self elif isinstance(other, PythonDist): self.hexrelease |= other.get_hexrelease() return self elif isinstance(other, dict): self.hexrelease |= PythonDist(**other).get_hexrelease() return self elif isinstance(other, tuple): self.hexrelease |= PythonDist(*other).get_hexrelease() return self try: # jython - 32bit is a long(unsigned int) if isinstance(other, long): # @UndefinedVariable self.hexrelease |= other return self except NameError: pass raise PythonIDsError("type not supported: other = " + str(other))
[docs] def __or__(self, other): """The *|* operator for the resulting *hexversion*: :: self-bitmask | other-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: The resulting bitmask as numeric value. Raises: pass-through """ if not self.hexrelease: self.hexrelease = self.get_hexrelease() if isinstance(other, int): return self.hexrelease | other elif isinstance(other, PythonDist): return self.hexrelease | other.get_hexrelease() elif isinstance(other, dict): # use other as init parameters - simply trust or pass exception return self.hexrelease | PythonDist(**other).get_hexrelease() elif isinstance(other, tuple): return self.hexrelease | PythonDist(*other).get_hexrelease() try: # jython - 32bit is a long(unsigned int) if isinstance(other, long): # @UndefinedVariable return self.hexrelease | other except NameError: pass raise PythonIDsError("type not supported: other = " + str(other))
[docs] def __rand__(self, other): """The r-side *&* operator for the resulting *hexversion*: :: other-bitmask & self-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: The resulting bitmask as numeric value. Raises: pass-through """ return self.__and__(other)
[docs] def __ror__(self, other): """The right-side *|* operator for the resulting *hexversion*: :: other-bitmask | self-bitmask Args: other: The bitmask for operations. :: other := ( <int-16bit-mask> # compare with hexversion | <dictionary>) # compare keys only | <tuple>) # compare key-index only | <instance-of-PythonDist> # compare both hexversions ) Returns: The resulting bitmask as numeric value. Raises: pass-through """ return self.__or__(other)
[docs] def get_hexrelease(self): """ Returns the dynamically calculated hex version resulting from current values of the member attributes. When not all present, uses the available stack attributes. Does not use cached values, nor stores the result. For the use and recreation of cached values call *__int__*. """ try: return self.category | self.disttype | self.dist | self.distrel except (TypeError, KeyError): # basically for bootstrap of __init__ only res = 0 try: res |= self.category except: pass try: res |= self.disttype except: pass try: res |= self.dist except: pass try: res |= self.distrel except: pass return res
def get_json(self, **kargs): """Returns an in-memory structure compatible to the package 'json'. forceall: Includes all available information:: forceall := ( True # including the compiler of the interpreter | False # the interpreter data only ) valuetype: Defines the representation of the values - where possible:: valuetype := ( raw # original internal value | sym # mapped to symbolic names # json and python do not define a native hex type ) default := sym Returns: Formatted string. Raises: pass-through """ res = {} _valuetype = kargs.get('valuetype', self.raw) def maptostr(r): if _valuetype == 'raw': return r else: try: return str(num2name[r]) except KeyError: return r res["category"] = maptostr(self.category) res["disttype"] = maptostr(self.disttype) res["dist"] = maptostr(self.dist) res["distrel"] = maptostr(self.distrel) res["hexrelease"] = self.hexrelease if self.forceall: res["compiler"] = str(self.compiler) res["compiler_version"] = str('.'.join(str(i) for i in self.compiler_version_tuple)) if PYDIST & PYE_DIST == PYE_PYPY: res["compiler"] = str(self.c_compiler) res["compiler_version"] = str('.'.join(str(i) for i in self.c_compiler_version_tuple)) res["implementation"] = str(sys.executable) return res
# # the default is with core attributes only - which almost for sure must not raise exceptions at all # PYDIST_DATA = PythonDist(forceall=True) #: Creates the object for the current runtime environment and scans the parameters. PYDIST_DATA.scan() PYDIST = PYDIST_DATA.get_hexrelease() #: Sets the hex value for fast access based on PYDIST_DATA, if (PYDIST & PYE_DIST) == PYE_JYTHON: # Jython knows the type long - and casts to it from 32bit on isJython = True ISINT = (int, long,) # @UndefinedVariable ISNUM = (int, float, long,) # @UndefinedVariable else: isJython = False ISINT = (int,) ISNUM = (int, float,) # @UndefinedVariable