"""
**python msys system wrapper**

User should used this module (and avoid used of specific system functionality) to get cross-system portability
on their entity file operations.

To determinate the os depending implementation to use, this module checks the os field from the system item of
the entity

-----------
"""

from myrrh.core.services.system import AbcRuntime, _mlib_

from . import mimportlib

__mlib__ = "AbcSysConfig"


class AbcSysConfig(AbcRuntime):
    __frameworkpath__ = "mpython.msysconfig"

    __all__ = [
        "get_config_h_filename",
        "get_config_var",
        "get_config_vars",
        "get_makefile_filename",
        "get_path",
        "get_path_names",
        "get_paths",
        "get_platform",
        "get_python_version",
        "get_scheme_names",
        "parse_config_h",
    ]

    _INSTALL_SCHEMES = {
        "posix_prefix": {
            "stdlib": "{installed_base}/lib/python{py_version_short}",
            "platstdlib": "{platbase}/lib/python{py_version_short}",
            "purelib": "{base}/lib/python{py_version_short}/site-packages",
            "platlib": "{platbase}/lib/python{py_version_short}/site-packages",
            "include": "{installed_base}/include/python{py_version_short}{abiflags}",
            "platinclude": "{installed_platbase}/include/python{py_version_short}{abiflags}",
            "scripts": "{base}/bin",
            "data": "{base}",
        },
        "posix_home": {
            "stdlib": "{installed_base}/lib/python",
            "platstdlib": "{base}/lib/python",
            "purelib": "{base}/lib/python",
            "platlib": "{base}/lib/python",
            "include": "{installed_base}/include/python",
            "platinclude": "{installed_base}/include/python",
            "scripts": "{base}/bin",
            "data": "{base}",
        },
        "nt": {
            "stdlib": "{installed_base}/Lib",
            "platstdlib": "{base}/Lib",
            "purelib": "{base}/Lib/site-packages",
            "platlib": "{base}/Lib/site-packages",
            "include": "{installed_base}/Include",
            "platinclude": "{installed_base}/Include",
            "scripts": "{base}/Scripts",
            "data": "{base}",
        },
        "nt_user": {
            "stdlib": "{userbase}/Python{py_version_nodot}",
            "platstdlib": "{userbase}/Python{py_version_nodot}",
            "purelib": "{userbase}/Python{py_version_nodot}/site-packages",
            "platlib": "{userbase}/Python{py_version_nodot}/site-packages",
            "include": "{userbase}/Python{py_version_nodot}/Include",
            "scripts": "{userbase}/Python{py_version_nodot}/Scripts",
            "data": "{userbase}",
        },
        "posix_user": {
            "stdlib": "{userbase}/lib/python{py_version_short}",
            "platstdlib": "{userbase}/lib/python{py_version_short}",
            "purelib": "{userbase}/lib/python{py_version_short}/site-packages",
            "platlib": "{userbase}/lib/python{py_version_short}/site-packages",
            "include": "{userbase}/include/python{py_version_short}",
            "scripts": "{userbase}/bin",
            "data": "{userbase}",
        },
        "osx_framework_user": {
            "stdlib": "{userbase}/lib/python",
            "platstdlib": "{userbase}/lib/python",
            "purelib": "{userbase}/lib/python/site-packages",
            "platlib": "{userbase}/lib/python/site-packages",
            "include": "{userbase}/include",
            "scripts": "{userbase}/bin",
            "data": "{userbase}",
        },
    }

    _SCHEME_KEYS = (
        "stdlib",
        "platstdlib",
        "purelib",
        "platlib",
        "include",
        "scripts",
        "data",
    )

    os = mimportlib.module_property("os")
    io = mimportlib.module_property("io")
    sys = mimportlib.module_property("sys")

    def __init__(self, system=None):
        os = self.os
        sys = self.sys

        # FIXME don't rely on sys.version here, its format is an implementation detail
        # of CPython, use sys.version_info or sys.hexversion
        self._PY_VERSION = sys.version.split()[0]
        self._PY_VERSION_SHORT = "%d.%d" % sys.version_info[:2]
        self._PY_VERSION_SHORT_NO_DOT = "%d%d" % sys.version_info[:2]
        self._PREFIX = os.path.normpath(sys.prefix)
        self._BASE_PREFIX = os.path.normpath(sys.base_prefix)
        self._EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
        self._BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
        self._CONFIG_VARS = None
        self._USER_BASE = None
        self._PROJECT_BASE = self._safe_realpath(os.getcwd())
        if os.name == "nt" and self._PROJECT_BASE.lower().endswith(("\\pcbuild\\win32", "\\pcbuild\\amd64")):
            self._PROJECT_BASE = self._safe_realpath(os.path.join(self._PROJECT_BASE, os.path.pardir, os.path.pardir))

        # set for cross builds
        if "_PYTHON_PROJECT_BASE" in os.environ:
            self._PROJECT_BASE = self._safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])

        self._sys_home = getattr(sys, "_home", None)
        if self._sys_home and os.name == "nt" and self._sys_home.lower().endswith(("\\pcbuild\\win32", "\\pcbuild\\amd64")):
            self._sys_home = os.path.dirname(os.path.dirname(self._sys_home))

        self._PYTHON_BUILD = self.is_python_build(True)

        if self._PYTHON_BUILD:
            for scheme in ("posix_prefix", "posix_home"):
                self._INSTALL_SCHEMES[scheme]["include"] = "{srcdir}/Include"
                self._INSTALL_SCHEMES[scheme]["platinclude"] = "{projectbase}/."

        self.__default_scheme = self._get_default_scheme()

    def _safe_realpath(self, path):
        realpath = self.os.path.realpath
        try:
            return realpath(path)
        except OSError:
            return path

    def _is_python_source_dir(self, d):
        os = self.os
        for fn in ("Setup.dist", "Setup.local"):
            if os.path.isfile(os.path.join(d, "Modules", fn)):
                return True
        return False

    def is_python_build(self, check_home=False):
        if check_home and self._sys_home:
            return self._is_python_source_dir(self._sys_home)
        return self._is_python_source_dir(self._PROJECT_BASE)

    def _subst_vars(self, s, local_vars):
        os = self.os
        try:
            return s.format(**local_vars)
        except KeyError:
            try:
                return s.format(**os.environ)
            except KeyError as var:
                raise AttributeError("{%s}" % var)

    def _extend_dict(self, target_dict, other_dict):
        target_keys = target_dict.keys()
        for key, value in other_dict.items():
            if key in target_keys:
                continue
            target_dict[key] = value

    def _expand_vars(self, scheme, vars):
        os = self.os
        res = {}
        if vars is None:
            vars = {}
        self._extend_dict(vars, self.get_config_vars())

        for key, value in self._INSTALL_SCHEMES[scheme].items():
            if os.name in ("posix", "nt"):
                value = os.path.expanduser(value)
            res[key] = os.path.normpath(self._subst_vars(value, vars))
        return res

    def _get_default_scheme(self):
        os = self.os
        if os.name == "posix":
            # the default scheme for posix is posix_prefix
            return "posix_prefix"
        return os.name

    def _getuserbase(self):
        os = self.os
        sys = self.sys
        env_base = os.environ.get("PYTHONUSERBASE", None)

        def joinuser(*args):
            return os.path.expanduser(os.path.join(*args))

        if os.name == "nt":
            base = os.environ.get("APPDATA") or "~"
            if env_base:
                return env_base
            else:
                return joinuser(base, "Python")

        if sys.platform == "darwin":
            framework = self.get_config_var("PYTHONFRAMEWORK")
            if framework:
                if env_base:
                    return env_base
                else:
                    return joinuser("~", "Library", framework, "%d.%d" % sys.version_info[:2])

        if env_base:
            return env_base
        else:
            return joinuser("~", ".local")

    def _parse_makefile(self, filename, vars=None):
        """Parse a Makefile-style file.

        A dictionary containing name/value pairs is returned.  If an
        optional dictionary is passed in as the second argument, it is
        used instead of a new dictionary.
        """
        # Regexes needed for parsing Makefile (and similar syntaxes,
        # like old-style Setup files).
        open = self.io.open
        os = self.os
        import re

        _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
        _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
        _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")

        if vars is None:
            vars = {}
        done = {}
        notdone = {}

        with open(filename, errors="surrogateescape") as f:
            lines = f.readlines()

        for line in lines:
            if line.startswith("#") or line.strip() == "":
                continue
            m = _variable_rx.match(line)
            if m:
                n, v = m.group(1, 2)
                v = v.strip()
                # `$$' is a literal `$' in make
                tmpv = v.replace("$$", "")

                if "$" in tmpv:
                    notdone[n] = v
                else:
                    try:
                        v = int(v)
                    except ValueError:
                        # insert literal `$'
                        done[n] = v.replace("$$", "$")
                    else:
                        done[n] = v

        # do variable interpolation here
        variables = list(notdone.keys())

        # Variables with a 'PY_' prefix in the makefile. These need to
        # be made available without that prefix through sysconfig.
        # Special care is needed to ensure that variable expansion works, even
        # if the expansion uses the name without a prefix.
        renamed_variables = ("CFLAGS", "LDFLAGS", "CPPFLAGS")

        while len(variables) > 0:
            for name in tuple(variables):
                value = notdone[name]
                m1 = _findvar1_rx.search(value)
                m2 = _findvar2_rx.search(value)
                if m1 and m2:
                    m = m1 if m1.start() < m2.start() else m2
                else:
                    m = m1 if m1 else m2
                if m is not None:
                    n = m.group(1)
                    found = True
                    if n in done:
                        item = str(done[n])
                    elif n in notdone:
                        # get it on a subsequent round
                        found = False
                    elif n in os.environ:
                        # do it like make: fall back to environment
                        item = os.environ[n]

                    elif n in renamed_variables:
                        if name.startswith("PY_") and name[3:] in renamed_variables:
                            item = ""

                        elif "PY_" + n in notdone:
                            found = False

                        else:
                            item = str(done["PY_" + n])

                    else:
                        done[n] = item = ""

                    if found:
                        after = value[m.end() :]
                        value = value[: m.start()] + item + after
                        if "$" in after:
                            notdone[name] = value
                        else:
                            try:
                                value = int(value)
                            except ValueError:
                                done[name] = value.strip()
                            else:
                                done[name] = value
                            variables.remove(name)

                            if name.startswith("PY_") and name[3:] in renamed_variables:
                                name = name[3:]
                                if name not in done:
                                    done[name] = value

                else:
                    # bogus variable reference (e.g. "prefix=$/opt/python");
                    # just drop it since we can't deal
                    done[name] = value
                    variables.remove(name)

        # strip spurious spaces
        for k, v in done.items():
            if isinstance(v, str):
                done[k] = v.strip()

        # save the results in the global dictionary
        vars.update(done)
        return vars

    def get_makefile_filename(self):
        """Return the path of the Makefile."""
        sys = self.sys
        os = self.os
        if self._PYTHON_BUILD:
            return os.path.join(self._sys_home or self._PROJECT_BASE, "Makefile")
        if hasattr(sys, "abiflags"):
            config_dir_name = "config-%s%s" % (self._PY_VERSION_SHORT, sys.abiflags)
        else:
            config_dir_name = "config"
        if hasattr(sys.implementation, "_multiarch"):
            config_dir_name += "-%s" % sys.implementation._multiarch
        return os.path.join(self.get_path("stdlib"), config_dir_name, "Makefile")

    def _get_sysconfigdata_name(self):
        sys = self.sys
        os = self.os
        return os.environ.get(
            "_PYTHON_SYSCONFIGDATA_NAME",
            "_sysconfigdata_{abi}_{platform}_{multiarch}".format(
                abi=sys.abiflags,
                platform=sys.platform,
                multiarch=getattr(sys.implementation, "_multiarch", ""),
            ),
        )

    def _generate_posix_vars(self):
        """Generate the Python module containing build-time variables."""
        import pprint

        sys = self.sys
        os = self.os
        vars = {}
        # load the installed Makefile:
        makefile = self.get_makefile_filename()
        try:
            self._parse_makefile(makefile, vars)
        except OSError as e:
            msg = "invalid Python installation: unable to open %s" % makefile
            if hasattr(e, "strerror"):
                msg = msg + " (%s)" % e.strerror
            raise OSError(msg)
        # load the installed pyconfig.h:
        config_h = self.get_config_h_filename()
        try:
            with open(config_h) as f:
                self.parse_config_h(f, vars)
        except OSError as e:
            msg = "invalid Python installation: unable to open %s" % config_h
            if hasattr(e, "strerror"):
                msg = msg + " (%s)" % e.strerror
            raise OSError(msg)
        # On AIX, there are wrong paths to the linker scripts in the Makefile
        # -- these paths are relative to the Python source, but when installed
        # the scripts are in another directory.
        if self._PYTHON_BUILD:
            vars["BLDSHARED"] = vars["LDSHARED"]

        # There's a chicken-and-egg situation on OS X with regards to the
        # _sysconfigdata module after the changes introduced by #15298:
        # get_config_vars() is called by get_platform() as part of the
        # `make pybuilddir.txt` target -- which is a precursor to the
        # _sysconfigdata.py module being constructed.  Unfortunately,
        # get_config_vars() eventually calls _init_posix(), which attempts
        # to import _sysconfigdata, which we won't have built yet.  In order
        # for _init_posix() to work, if we're on Darwin, just mock up the
        # _sysconfigdata module manually and populate it with the build vars.
        # This is more than sufficient for ensuring the subsequent call to
        # get_platform() succeeds.
        name = self._get_sysconfigdata_name()
        if "darwin" in sys.platform:
            import types

            module = types.ModuleType(name)
            module.build_time_vars = vars
            sys.modules[name] = module

        pybuilddir = "build/lib.%s-%s" % (self.get_platform(), self._PY_VERSION_SHORT)
        if hasattr(sys, "gettotalrefcount"):
            pybuilddir += "-pydebug"
        os.makedirs(pybuilddir, exist_ok=True)
        destfile = os.path.join(pybuilddir, name + ".py")

        with open(destfile, "w", encoding="utf8") as f:
            f.write("# system configuration generated and used by" " the sysconfig module\n")
            f.write("build_time_vars = ")
            pprint.pprint(vars, stream=f)

        # Create file used for sys.path fixup -- see Modules/getpathb.c
        with open("pybuilddir.txt", "w", encoding="ascii") as f:
            f.write(pybuilddir)

    def _init_posix(self, vars):
        """Initialize the module as appropriate for POSIX systems."""
        # _sysconfigdata is generated at build time, see _generate_posix_vars()
        # name = self._get_sysconfigdata_name()
        # _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
        # build_time_vars = _temp.build_time_vars
        # vars.update(build_time_vars)

    def _init_non_posix(self, vars):
        """Initialize the module as appropriate for NT"""
        os = self.os
        sys = self.sys
        get_path = self.get_path
        _PY_VERSION_SHORT_NO_DOT = self._PY_VERSION_SHORT_NO_DOT
        _safe_realpath = self._safe_realpath
        # set basic install directories
        vars["LIBDEST"] = get_path("stdlib")
        vars["BINLIBDEST"] = get_path("platstdlib")
        vars["INCLUDEPY"] = get_path("include")
        vars["EXT_SUFFIX"] = ".pyd"
        vars["EXE"] = ".exe"
        vars["VERSION"] = _PY_VERSION_SHORT_NO_DOT
        try:
            executable = sys._executable
        except AttributeError:
            executable = "no_python_on target"
        vars["BINDIR"] = os.path.dirname(_safe_realpath(executable))

    #
    # public APIs
    #

    def parse_config_h(self, fp, vars=None):
        """Parse a config.h-style file.

        A dictionary containing name/value pairs is returned.  If an
        optional dictionary is passed in as the second argument, it is
        used instead of a new dictionary.
        """
        if vars is None:
            vars = {}
        import re

        define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
        undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")

        while True:
            line = fp.readline()
            if not line:
                break
            m = define_rx.match(line)
            if m:
                n, v = m.group(1, 2)
                try:
                    v = int(v)
                except ValueError:
                    pass
                vars[n] = v
            else:
                m = undef_rx.match(line)
                if m:
                    vars[m.group(1)] = 0
        return vars

    def get_config_h_filename(self):
        """Return the path of pyconfig.h."""
        os = self.os
        _PYTHON_BUILD = self._PYTHON_BUILD
        _sys_home = self._sys_home
        _PROJECT_BASE = self._PROJECT_BASE
        get_path = self.get_path
        if _PYTHON_BUILD:
            if os.name == "nt":
                inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
            else:
                inc_dir = _sys_home or _PROJECT_BASE
        else:
            inc_dir = get_path("platinclude")
        return os.path.join(inc_dir, "pyconfig.h")

    def get_scheme_names(self):
        _INSTALL_SCHEMES = self._INSTALL_SCHEMES
        """Return a tuple containing the schemes names."""
        return tuple(sorted(_INSTALL_SCHEMES))

    def get_path_names(self):
        """Return a tuple containing the paths names."""
        return self._SCHEME_KEYS

    def get_paths(self, scheme=None, vars=None, expand=True):
        """Return a mapping containing an install scheme.

        ``scheme`` is the install scheme name. If not provided, it will
        return the default scheme for the current platform.
        """
        if scheme is None:
            scheme = self.__default_scheme

        if expand:
            return self._expand_vars(scheme, vars)
        else:
            return self._INSTALL_SCHEMES[scheme]

    def get_path(self, name, scheme=None, vars=None, expand=True):
        """Return a path corresponding to the scheme.

        ``scheme`` is the install scheme name.
        """
        if scheme is None:
            scheme = self.__default_scheme
        return self.get_paths(scheme, vars, expand)[name]

    def get_config_vars(self, *args):
        """With no arguments, return a dictionary of all configuration
        variables relevant for the current platform.

        On Unix, this means every variable defined in Python's installed Makefile;
        On Windows it's a much smaller set.

        With arguments, return a list of values that result from looking up
        each argument in the configuration variable dictionary.
        """
        _CONFIG_VARS = self._CONFIG_VARS
        sys = self.sys
        os = self.os
        if _CONFIG_VARS is None:
            self._CONFIG_VARS = {}
            _CONFIG_VARS = self._CONFIG_VARS
            # Normalized versions of prefix and exec_prefix are handy to have;
            # in fact, these are the standard versions used most places in the
            # Distutils.
            _CONFIG_VARS["prefix"] = self._PREFIX
            _CONFIG_VARS["exec_prefix"] = self._EXEC_PREFIX
            _CONFIG_VARS["py_version"] = self._PY_VERSION
            _CONFIG_VARS["py_version_short"] = self._PY_VERSION_SHORT
            _CONFIG_VARS["py_version_nodot"] = self._PY_VERSION_SHORT_NO_DOT
            _CONFIG_VARS["installed_base"] = self._BASE_PREFIX
            _CONFIG_VARS["base"] = self._PREFIX
            _CONFIG_VARS["installed_platbase"] = self._BASE_EXEC_PREFIX
            _CONFIG_VARS["platbase"] = self._EXEC_PREFIX
            _CONFIG_VARS["projectbase"] = self._PROJECT_BASE
            try:
                _CONFIG_VARS["abiflags"] = sys.abiflags
            except AttributeError:
                # sys.abiflags may not be defined on all platforms.
                _CONFIG_VARS["abiflags"] = ""

            if os.name == "nt":
                self._init_non_posix(_CONFIG_VARS)
            if os.name == "posix":
                self._init_posix(_CONFIG_VARS)
            # For backward compatibility, see issue19555
            SO = _CONFIG_VARS.get("EXT_SUFFIX")
            if SO is not None:
                _CONFIG_VARS["SO"] = SO
            # Setting 'userbase' is done below the call to the
            # init function to enable using 'get_config_var' in
            # the init-function.
            _CONFIG_VARS["userbase"] = self._getuserbase()

            # Always convert srcdir to an absolute path
            srcdir = _CONFIG_VARS.get("srcdir", self._PROJECT_BASE)
            if os.name == "posix":
                if self._PYTHON_BUILD:
                    # If srcdir is a relative path (typically '.' or '..')
                    # then it should be interpreted relative to the directory
                    # containing Makefile.
                    base = os.path.dirname(self.get_makefile_filename())
                    srcdir = os.path.join(base, srcdir)
                else:
                    # srcdir is not meaningful since the installation is
                    # spread about the filesystem.  We choose the
                    # directory containing the Makefile since we know it
                    # exists.
                    srcdir = os.path.dirname(self.get_makefile_filename())
            _CONFIG_VARS["srcdir"] = self._safe_realpath(srcdir)

            # OS X platforms require special customization to handle
            # multi-architecture, multi-os-version installers
            if sys.platform == "darwin":
                from . import _mosx_support

                _osx_support = _mlib_(_mosx_support)(self)
                _osx_support.customize_config_vars(_CONFIG_VARS)

        if args:
            vals = []
            for name in args:
                vals.append(_CONFIG_VARS.get(name))
            return vals
        else:
            return _CONFIG_VARS

    def get_config_var(self, name):
        """Return the value of a single variable using the dictionary returned by
        'get_config_vars()'.

        Equivalent to get_config_vars().get(name)
        """
        if name == "SO":
            import warnings

            warnings.warn("SO is deprecated, use EXT_SUFFIX", DeprecationWarning, 2)
        return self.get_config_vars().get(name)

    def get_platform(self):
        """Return a string that identifies the current platform.

        This is used mainly to distinguish platform-specific build directories and
        platform-specific built distributions.  Typically includes the OS name
        and version and the architecture (as supplied by 'os.uname()'),
        although the exact information included depends on the OS; eg. for IRIX
        the architecture isn't particularly important (IRIX only runs on SGI
        hardware), but for Linux the kernel version isn't particularly
        important.

        Examples of returned values:
           linux-i586
           linux-alpha (?)
           solaris-2.6-sun4u
           irix-5.3
           irix64-6.2

        Windows will return one of:
           win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
           win-ia64 (64bit Windows on Itanium)
           win32 (all others - specifically, sys.platform is returned)

        For other non-POSIX platforms, currently just returns 'sys.platform'.
        """
        sys = self.sys
        os = self.os
        if os.name == "nt":
            # sniff sys.version for architecture.
            prefix = " bit ("
            i = sys.version.find(prefix)
            if i == -1:
                return sys.platform
            j = sys.version.find(")", i)
            look = sys.version[i + len(prefix) : j].lower()
            if look == "amd64":
                return "win-amd64"
            if look == "itanium":
                return "win-ia64"
            return sys.platform

        if os.name != "posix" or not hasattr(os, "uname"):
            # XXX what about the architecture? NT is Intel or Alpha
            return sys.platform

        # Set for cross builds explicitly
        if "_PYTHON_HOST_PLATFORM" in os.environ:
            return os.environ["_PYTHON_HOST_PLATFORM"]

        # Try to distinguish various flavours of Unix
        osname, host, release, version, machine = os.uname()

        # Convert the OS name to lowercase, remove '/' characters
        # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
        osname = osname.lower().replace("/", "")
        machine = machine.replace(" ", "_")
        machine = machine.replace("/", "-")

        if osname[:5] == "linux":
            # At least on Linux/Intel, 'machine' is the processor --
            # i386, etc.
            # XXX what about Alpha, SPARC, etc?
            return "%s-%s" % (osname, machine)
        elif osname[:5] == "sunos":
            if release[0] >= "5":  # SunOS 5 == Solaris 2
                osname = "solaris"
                release = "%d.%s" % (int(release[0]) - 3, release[2:])
                # We can't use "platform.architecture()[0]" because a
                # bootstrap problem. We use a dict to get an error
                # if some suspicious happens.
                bitness = {2147483647: "32bit", 9223372036854775807: "64bit"}
                machine += ".%s" % bitness[sys.maxsize]
            # fall through to standard osname-release-machine representation
        elif osname[:4] == "irix":  # could be "irix64"!
            return "%s-%s" % (osname, release)
        elif osname[:3] == "aix":
            return "%s-%s.%s" % (osname, version, release)
        elif osname[:6] == "cygwin":
            osname = "cygwin"
            import re

            rel_re = re.compile(r"[\d.]+")
            m = rel_re.match(release)
            if m:
                release = m.group()
        elif osname[:6] == "darwin":
            from . import _mosx_support

            _osx_support = _mlib_(_mosx_support)(self)
            osname, release, machine = _osx_support.get_platform_osx(self.get_config_vars(), osname, release, machine)

        return "%s-%s-%s" % (osname, release, machine)

    def get_python_version(self):
        return self._PY_VERSION_SHORT

    def _print_dict(self, title, data):
        for index, (key, value) in enumerate(sorted(data.items())):
            if index == 0:
                print("%s: " % (title))
            print('\t%s = "%s"' % (key, value))

    def _main(self):
        """Display all information sysconfig detains."""
        # if '--generate-posix-vars' in sys.argv:
        #    self._generate_posix_vars()
        #    return
        print('Platform: "%s"' % self.get_platform())
        print('Python version: "%s"' % self.get_python_version())
        print('Current installation scheme: "%s"' % self._get_default_scheme())
        print()
        self._print_dict("Paths", self.get_paths())
        print()
        self._print_dict("Variables", self.get_config_vars())
