示例#1
0
def run_in_syspy(f):
    """
    Decorator to run a function in the system python

    :param f:
    :return:
    """
    fname = f.__name__
    code_lines = inspect.getsource(f).splitlines()

    code = dedent("\n".join(code_lines[1:]))  # strip this decorator

    # add call to the function and print it's result
    code += dedent("""\n
        import sys
        args = sys.argv[1:]
        result = {fname}(*args)
        print("%r" % result)
    """).format(fname=fname)

    env = os.environ
    python = findsyspy()
    logger.debug("Create function for system python\n%s" % code)

    def call_f(*args):
        cmd = [python, '-c', code] + list(args)
        output = subprocess.check_output(cmd, env=env).decode('utf-8')
        result = ast.literal_eval(output)
        return result

    return call_f
示例#2
0
    def load_module(self, name):
        """
        Only lets modules in allowed_modules be loaded, others
        will get an ImportError
        """

        # Get the name relative to SITEDIR ..
        filepath = self.module_info[1]
        fullname = splitext( \
            relpath(filepath, self.sitedir) \
            )[0].replace(os.sep, '.')

        modulename = filename_to_module(fullname)
        if modulename not in allowed_modules:
            if remember_blocks:
                blocked_imports.add(fullname)
            if log_blocks:
                raise ImportError("Vext blocked import of '%s'" % modulename)
            else:
                # Standard error message
                raise ImportError("No module named %s" % modulename)

        if name not in sys.modules:
            try:
                logger.debug("load_module %s %s", name, self.module_info)
                module = imp.load_module(name, *self.module_info)
            except Exception as e:
                logger.debug(e)
                raise
            sys.modules[fullname] = module

        return sys.modules[fullname]
示例#3
0
def check_sysdeps(vext_files):
    """
    Check that imports in 'test_imports' succeed
    otherwise display message in 'install_hints'
    """

    @run_in_syspy
    def run(*modules):
        result = {}
        for m in modules:
            if m:
                try:
                    __import__(m)
                    result[m] = True
                except ImportError:
                    result[m] = False
        return result

    success = True
    for vext_file in vext_files:
        with open(vext_file) as f:
            vext = open_spec(f)
            install_hint = " ".join(vext.get('install_hints', ['System dependencies not found']))

            modules = vext.get('test_import', '')
            logger.debug("%s test imports of: %s", vext_file, modules)
            result = run(*modules)
            if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
                for k, v in result.items():
                    logger.debug("%s: %s", k, v)
            if not all(result.values()):
                success = False
                print(install_hint)
    return success
示例#4
0
    def load_module(self, name):
        """
        Only lets modules in allowed_modules be loaded, others
        will get an ImportError
        """

        # Get the name relative to SITEDIR ..
        filepath = self.module_info[1]
        fullname = splitext( \
            relpath(filepath, self.sitedir) \
            )[0].replace(os.sep, '.')

        modulename = filename_to_module(fullname)
        if modulename not in allowed_modules:
            if remember_blocks:
                blocked_imports.add(fullname)
            if log_blocks:
                raise ImportError("Vext blocked import of '%s'" % modulename)
            else:
                # Standard error message
                raise ImportError("No module named %s" % modulename)

        if name not in sys.modules:
            try:
                logger.debug("load_module %s %s", name, self.module_info)
                module = imp.load_module(name, *self.module_info)
            except Exception as e:
                logger.debug(e)
                raise
            sys.modules[fullname] = module

        return sys.modules[fullname]
示例#5
0
def check_sysdeps(vext_files):
    """
    Check that imports in 'test_imports' succeed
    otherwise display message in 'install_hints'
    """

    @run_in_syspy
    def run(*modules):
        result = {}
        for m in modules:
            if m:
                try:
                    __import__(m)
                    result[m] = True
                except ImportError:
                    result[m] = False
        return result

    success = True
    for vext_file in vext_files:
        with open(vext_file) as f:
            vext = open_spec(f)
            install_hint = " ".join(vext.get('install_hints', ['System dependencies not found']))

            modules = vext.get('test_import', '')
            logger.debug("%s test imports of: %s", vext_file, modules)
            result = run(*modules)
            if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
                for k, v in result.items():
                    logger.debug("%s: %s", k, v)
            if not all(result.values()):
                success = False
                print(install_hint)
    return success
    def __init__(self, path_entry):
        self.path_entry = path_entry

        sitedir = getsyssitepackages()
        if path_entry in (sitedir, GatekeeperFinder.PATH_TRIGGER):
            logger.debug("handle entry %s", path_entry)
            return
        else:
            logger.debug("not handling entry %s", path_entry)
            raise ImportError()
示例#7
0
    def __init__(self, path_entry):
        self.path_entry = path_entry

        sitedir = getsyssitepackages()
        if path_entry in (sitedir, GatekeeperFinder.PATH_TRIGGER):
            logger.debug("handle entry %s", path_entry)
            return
        else:
            logger.debug("not handling entry %s", path_entry)
            raise ImportError()
def in_venv():
    """
    :return: True if in running from a virtualenv

    Has to detect the case where the python binary is run
    directly, so VIRTUAL_ENV may not be set
    """
    global _in_venv
    if _in_venv is not None:
        return _in_venv

    if not (os.path.isfile(ORIG_PREFIX_TXT) or os.path.isfile(PY_VENV_CFG)):
        logger.debug("in_venv no orig_prefix_txt [%s]", ORIG_PREFIX_TXT)
        logger.debug("in_venv no py_venv_cfg [%s]", PY_VENV_CFG)
        # TODO - check this is actually valid !
        _in_venv = False
        return _in_venv

    if 'VIRTUAL_ENV' in os.environ:
        logger.debug("in_venv VIRTUAL_ENV set.")
        _in_venv = True
    else:
        # Find first python in path ... if its not this one,
        # ...we are in a different python
        python = basename(sys.executable)
        for p in os.environ['PATH'].split(os.pathsep):
            py_path = join(p, python)
            if isfile(py_path):
                logger.debug("in_venv py_at [%s] return: %s", (py_path, sys.executable != py_path))
                _in_venv = sys.executable != py_path
                break

    return _in_venv
示例#9
0
    def __init__(self, path_entry):
        self.path_entry = path_entry
        try:
            # Wrap in exception handler in case something in a .pth file causes an exception.
            sitedir = getsyssitepackages()
        except Exception as e:
            sys.stderr.write(
                "Vext disabled:  There was an issue getting the system site packages.\n"
            )
            raise ImportError()

        if path_entry in (sitedir, GatekeeperFinder.PATH_TRIGGER):
            logger.debug("handle entry %s", path_entry)
            return
        else:
            logger.debug("not handling entry %s", path_entry)
            raise ImportError()
示例#10
0
def getsyssitepackages():
    """
    :return: list of site-packages from system python
    """
    global _syssitepackages
    if not _syssitepackages:
        if not in_venv():
            _syssitepackages = get_python_lib()
            return _syssitepackages

        @run_in_syspy
        def run(*args):
            import site
            return site.getsitepackages()

        output = run()
        _syssitepackages = output
        logger.debug("system site packages: %s", _syssitepackages)
    return _syssitepackages
示例#11
0
def getsyssitepackages():
    """
    :return: list of site-packages from system python
    """
    global _syssitepackages
    if not _syssitepackages:
        if not in_venv():
            _syssitepackages = get_python_lib()
            return _syssitepackages

        @run_in_syspy
        def run(*args):
            import site
            return site.getsitepackages()

        output = run()
        _syssitepackages = output
        logger.debug("system site packages: %s", _syssitepackages)
    return _syssitepackages
示例#12
0
def in_venv():
    """
    :return: True if in running from a virtualenv

    Has to detect the case where the python binary is run
    directly, so VIRTUAL_ENV may not be set
    """
    global _in_venv
    if _in_venv is not None:
        return _in_venv

    if not os.path.isfile(orig_prefix):
        logger.debug("in_venv no orig_prefix [%s]", orig_prefix)
        # TODO - check this is actually valid !
        _in_venv = False
        return _in_venv

    if 'VIRTUAL_ENV' in os.environ:
        logger.debug("in_venv VIRTUAL_ENV set.")
        _in_venv = True
    else:
        # Find first python in path ... if its not this one,
        # ...we are in a different python
        python = basename(sys.executable)
        for p in os.environ['PATH'].split(os.pathsep):
            py_path = join(p, python)
            if isfile(py_path):
                logger.debug("in_venv py_at [%s] return: %s", (py_path, sys.executable != py_path))
                _in_venv = sys.executable != py_path
                break

    return _in_venv
示例#13
0
def install_vexts(vext_files, verify=True):
    """
    copy vext_file to sys.prefix + '/share/vext/specs'

    (PIP7 seems to remove data_files so we recreate something similar here)
    """
    if verify and not check_sysdeps(vext_files):
        return

    spec_dir = join(prefix, 'share/vext/specs')
    try:
        makedirs(spec_dir)
    except OSError:
        pass

    for vext_file in vext_files:
        dest = normpath(join(spec_dir, basename(vext_file)))
        try:
            logger.debug("%s > %s" % (vext_file, dest))
            copyfile(vext_file, dest)
            yield vext_file, dest
        except IOError as e:
            logger.error("Could not copy %s %r" % (vext_file, e))
示例#14
0
def install_vexts(vext_files, verify=True):
    """
    copy vext_file to sys.prefix + '/share/vext/specs'

    (PIP7 seems to remove data_files so we recreate something similar here)
    """
    if verify and not check_sysdeps(vext_files):
        return

    spec_dir = join(prefix, 'share/vext/specs')
    try:
        makedirs(spec_dir)
    except OSError as e:
        if not isdir(spec_dir):
            logger.error("Error making spec directory [%s]: %r" % (spec_dir, e))

    for vext_file in vext_files:
        dest = normpath(join(spec_dir, basename(vext_file)))
        try:
            logger.debug("%s > %s" % (vext_file, dest))
            copyfile(vext_file, dest)
            yield vext_file, dest
        except IOError as e:
            logger.error("Could not copy %s %r" % (vext_file, e))
示例#15
0
def load_specs():
    bad_specs = set()
    last_error = None

    for fn in spec_files():
        logger.debug("load spec: %s", fn)
        if fn in bad_specs:
            # Don't try and load the same bad spec twice
            continue

        try:
            spec = open_spec(open(fn))

            for module in spec['modules']:
                logger.debug("allow module: %s", module)
                allowed_modules.add(module)

            for path_name in spec.get('extra_paths', []):
                extra_path = get_extra_path(path_name)
                if isdir(extra_path):
                    os.environ['PATH'] += env_t(os.pathsep + extra_path)
                    sys.path.append(extra_path)
                    added_dirs.add(extra_path)
                else:
                    logger.warn("Skipped adding nonexistant path: {0}".format(
                        extra_path))

            sys_sitedirs = getsyssitepackages()
            for sys_sitedir in sys_sitedirs:
                with fixup_paths():
                    for pth in [pth for pth in spec['pths'] or [] if pth]:
                        try:
                            logger.debug("open pth: %s", pth)
                            pth_file = join(sys_sitedir, pth)
                            addpackage(sys_sitedir, pth_file, added_dirs)
                            init_path()  # TODO
                        except IOError as e:
                            # Path files are optional..
                            logging.debug('No pth found at %s', pth_file)
                            pass

        except Exception as e:
            bad_specs.add(fn)
            err_msg = 'error loading spec %s: %s' % (fn, e)
            if last_error != err_msg:
                logging.error(err_msg)
            last_error = err_msg

    if bad_specs:
        raise VextError('Error loading spec files: %s' % ', '.join(bad_specs))
示例#16
0
def load_specs():
    bad_specs = set()
    last_error = None

    for fn in spec_files():
        logger.debug("load spec: %s", fn)
        if fn in bad_specs:
            # Don't try and load the same bad spec twice
            continue

        try:
            spec = open_spec(open(fn))

            for module in spec['modules']:
                logger.debug("allow module: %s", module)
                allowed_modules.add(module)

            for path_name in spec.get('extra_paths', []):
                extra_path = get_extra_path(path_name)
                if isdir(extra_path):
                    os.environ['PATH'] += env_t(os.pathsep + extra_path)
                    sys.path.append(extra_path)
                    added_dirs.add(extra_path)
                else:
                    logger.warn("Could not add extra path: {0}".format(extra_path))

            sys_sitedirs = getsyssitepackages()
            for sys_sitedir in sys_sitedirs:
                for pth in [pth for pth in spec['pths'] or [] if pth]:
                    try:
                        logger.debug("open pth: %s", pth)
                        pth_file = join(sys_sitedir, pth)
                        addpackage(sys_sitedir, pth_file, added_dirs)
                        init_path()  # TODO
                    except IOError as e:
                        # Path files are optional..
                        logging.debug('No pth found at %s', pth_file)
                        pass

        except Exception as e:
            bad_specs.add(fn)
            err_msg = 'error loading spec %s: %s' % (fn, e)
            if last_error != err_msg:
                logging.error(err_msg)
            last_error = err_msg

    if bad_specs:
        raise VextError('Error loading spec files: %s' % ', '.join(bad_specs))
示例#17
0
    def find_module(self, fullname, path=None):
        # TODO Need lots of unit tests around this
        module = sys.modules.get(fullname)
        if module and hasattr(module, "load_module"):
            # After reload module can be missing load_module
            return module

        sitedirs = getsyssitepackages()
        # Check paths other than system sitepackages first
        other_paths = [
            p for p in sys.path
            if p not in sitedirs + [GatekeeperFinder.PATH_TRIGGER, '.']
        ]
        try:
            for other_path in other_paths:
                try:
                    module_info = imp.find_module(fullname, [other_path])
                    if module_info:
                        logger.debug("found module %s in other path [%s]",
                                     fullname, other_path)
                        return
                except ImportError:
                    continue
            else:
                raise ImportError()
        except ImportError:
            try:
                # Now check if in site packages and needs gatekeeping
                for sitedir in sitedirs:
                    try:
                        module_info = imp.find_module(
                            fullname, [sitedir, self.path_entry])
                        if module_info:
                            logger.debug(
                                "found module %s in sitedir or subdirectory [%s]",
                                fullname, sitedir)
                            return GateKeeperLoader(module_info, sitedir)
                    except ImportError:
                        logger.debug("%s not found in: %s", fullname,
                                     os.pathsep.join(other_paths))
                        continue
            except ImportError:
                ### TODO
                # Need to debug why this catch is needed, removing it stops things working...
                # something is subtly weird here.
                return
示例#18
0
 def installed_packages(self):
     """ :return: list of installed packages """
     packages = []
     CMDLINE = [sys.executable, "-mpip", "freeze"]
     try:
         for package in subprocess.check_output(CMDLINE) \
                 .decode('utf-8'). \
                 splitlines():
             for comparator in ["==", ">=", "<=", "<", ">"]:
                 if comparator in package:
                     # installed package names usually look like Pillow==2.8.1
                     # ignore others, like external packages that pip show
                     # won't understand
                     name = package.partition(comparator)[0]
                     packages.append(name)
     except RuntimeError as e:
         if logger.isEnabledFor(logging.DEBUG):
             logger.debug("Exception checking existing packages.")
             logger.debug("cmdline: %s", CMDLINE)
             ex_type, ex, tb = sys.exc_info()
             traceback.print_tb(tb)
             logger.debug()
     return packages
示例#19
0
    def find_module(self, fullname, path=None):
        # TODO Need lots of unit tests around this
        if fullname in sys.modules:
            return sys.modules[fullname]

        sitedirs = getsyssitepackages()
        # Check paths other than system sitepackages first
        other_paths = [p for p in sys.path if p not in sitedirs + [GatekeeperFinder.PATH_TRIGGER, '.']]
        try:
            for other_path in other_paths:
                try:
                    module_info = imp.find_module(fullname, [other_path])
                    if module_info:
                        logger.debug("found module %s in other path [%s]", fullname, other_path)
                        return
                except ImportError:
                    continue
            else:
                raise ImportError()
        except ImportError:
            try:
                # Now check if in site packages and needs gatekeeping
                for sitedir in sitedirs:
                    try:
                        module_info = imp.find_module(fullname, [sitedir, self.path_entry])
                        if module_info:
                            logger.debug("found module %s in sitedir or subdirectory [%s]", fullname, sitedir)
                            return GateKeeperLoader(module_info, sitedir)
                    except ImportError:
                        logger.debug("%s not found in: %s", fullname, os.pathsep.join(other_paths))
                        continue
            except ImportError:
                ### TODO
                # Need to debug why this catch is needed, removing it stops things working...
                # something is subtly weird here.
                return
示例#20
0
    def run(self):
        """
        Need to find any pre-existing vext contained in dependent packages
        and install them

        example:

        you create a setup.py with install_requires["vext.gi"]:

        - vext.gi gets installed using bdist_egg
        - vext itself is now called with bdist_egg and we end up here

        Vext now needs to find and install .vext files in vext.gi
        [or any other files that depend on vext]

        :return:
        """
        logger.debug("vext InstallLib [started]")

        # Find packages that depend on vext and check for .vext files...

        logger.debug("find_vext_files")
        vext_files = self.find_vext_files()
        logger.debug("manually_install_vext: ", vext_files)
        self.manually_install_vext(vext_files)
        logger.debug("enable vext")
        self.enable_vext()
        logger.debug("install_lib.run")
        install_lib.run(self)
        logger.debug("vext InstallLib [finished]")