Exemple #1
0
def diffRecursive(dir1, dir2):
    done = set()

    result = False

    for path1, filename in listDir(dir1):
        path2 = os.path.join(dir2, filename)

        done.add(path1)

        # Skip these binary files and scons build database of course.
        if filename.endswith((".o", ".os", ".obj", ".dblite")):
            continue

        # Skip
        if filename == ".sconsign":
            continue

        if not os.path.exists(path2):
            sys.exit("Only in %s: %s" % (dir1, filename))

        if os.path.isdir(path1):
            r = diffRecursive(path1, path2)
            if r:
                result = True
        elif os.path.isfile(path1):
            fromdate = time.ctime(os.stat(path1).st_mtime)
            todate = time.ctime(os.stat(path2).st_mtime)

            diff = difflib.unified_diff(
                a            = readSource(path1).splitlines(),
                b            = readSource(path2).splitlines(),
                fromfile     = path1,
                tofile       = path2,
                fromfiledate = fromdate,
                tofiledate   = todate,
                n            = 3
            )

            diff_list = list(diff)

            if diff_list :
                for line in diff_list :
                    my_print(line)

                result = True
        else:
            assert False, path1

    for path1, filename in listDir(dir2):
        path2 = os.path.join(dir2, filename)

        if path1 in done:
            continue

        if not os.path.exists(path1):
            sys.exit("Only in %s: %s" % (dir2, filename))

    return result
Exemple #2
0
    def _getNumpyCoreBinaries(numpy_dir):
        """Return any binaries in numpy package.

        Notes:
            This covers the special cases like MKL binaries.

        Returns:
            tuple of abspaths of binaries.
        """
        numpy_core_dir = os.path.join(numpy_dir, "core")

        # first look in numpy/.libs for binaries
        libdir = os.path.join(numpy_dir, ".libs" if not isMacOS() else ".dylibs")
        if os.path.isdir(libdir):
            for full_path, filename in listDir(libdir):
                yield full_path, filename

        # Then look for libraries in numpy.core package path
        # should already return the MKL files in ordinary cases
        re_anylib = re.compile(r"\w+\.(?:dll|so|dylib)", re.IGNORECASE)

        for full_path, filename in listDir(numpy_core_dir):
            if not re_anylib.match(filename):
                continue

            yield full_path, filename

        # Also look for MKL libraries in folder "above" numpy.
        # This should meet the layout of Anaconda installs.
        base_prefix = getSystemPrefixPath()

        if isWin32Windows():
            lib_dir = os.path.join(base_prefix, "Library", "bin")
        else:
            lib_dir = os.path.join(base_prefix, "lib")

        if os.path.isdir(lib_dir):
            re_mkllib = re.compile(r"^(?:lib)?mkl\w+\.(?:dll|so|dylib)", re.IGNORECASE)

            for full_path, filename in listDir(lib_dir):
                if isWin32Windows():
                    if not (
                        filename.startswith(("libi", "libm", "mkl"))
                        and filename.endswith(".dll")
                    ):
                        continue
                else:
                    if not re_mkllib.match(filename):
                        continue

                yield full_path, filename
Exemple #3
0
def detectPthImportedPackages():
    if not hasattr(sys.modules["site"], "getsitepackages"):
        return ()

    pth_imports = set()

    for prefix in sys.modules["site"].getsitepackages():
        if not os.path.isdir(prefix):
            continue

        for path, filename in listDir(prefix):
            if filename.endswith(".pth"):
                try:
                    for line in getFileContentByLine(path, "rU"):
                        if line.startswith("import "):
                            if ";" in line:
                                line = line[:line.find(";")]

                            for part in line[7:].split(","):
                                pth_imports.add(part.strip())
                except OSError:
                    warning(
                        "Python installation problem, cannot read file '%s'.")

    return tuple(sorted(pth_imports))
Exemple #4
0
def compileAndCompareWith(nuitka):
    if "PYTHONHASHSEED" not in os.environ:
        os.environ["PYTHONHASHSEED"] = '0'

    base_dir = os.path.join("..", "..")

    for package in PACKAGE_LIST:
        package = package.replace('/', os.path.sep)

        source_dir = os.path.join(base_dir, package)

        for path, filename in listDir(source_dir):
            if not filename.endswith(".py"):
                continue

            if filename.startswith(".#"):
                continue

            path = os.path.join(source_dir, filename)

            if filename != "__init__.py":
                my_print("Compiling '%s'." % path)

                target = filename.replace(".py", ".build")

                target_dir = os.path.join(tmp_dir, target)

                removeDirectory(
                    path = target_dir,
                    ignore_errors = False
                )

                command = [
                    nuitka,
                    "--module",
                    "--recurse-none",
                    "--plugin-enable=pylint-warnings",
                    "--output-dir=%s"% tmp_dir,
                    "--no-pyi-file",
                    path
                ]
                command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split()

                result = subprocess.call(
                    command
                )

                if result != 0:
                    sys.exit(result)

                diffRecursive(os.path.join(package, target), target_dir)

                shutil.rmtree(target_dir)

                if os.name == "nt":
                    target_filename = filename.replace(".py", ".pyd")
                else:
                    target_filename = filename.replace(".py", ".so")

                os.unlink(os.path.join(tmp_dir, target_filename))
Exemple #5
0
def checkPluginPath(plugin_filename, module_package):
    debug(
        "Checking top level plug-in path %s %s",
        plugin_filename,
        module_package
    )

    plugin_info = considerFilename(
        module_filename = plugin_filename
    )

    if plugin_info is not None:
        # File or package makes a difference, handle that
        if os.path.isfile(plugin_info[0]) or \
           Importing.isPackageDir(plugin_info[0]):
            _checkPluginPath(plugin_filename, module_package)
        elif os.path.isdir(plugin_info[0]):
            for sub_path, sub_filename in listDir(plugin_info[0]):
                assert sub_filename != "__init__.py"

                if Importing.isPackageDir(sub_path) or \
                   sub_path.endswith(".py"):
                    _checkPluginPath(sub_path, None)
        else:
            warning("Failed to include module from '%s'.", plugin_info[0])
    else:
        warning("Failed to recurse to directory '%s'.", plugin_filename)
Exemple #6
0
    def _packagePmw(self, pmw_path):
        # From the "__init__.py" of Pwm:
        def _hasLoader(dirname):  # @ReservedAssignment
            # Only accept Pmw_V_R_P with single digits, since ordering will
            # not work correctly with multiple digits (for example, Pmw_10_0
            # will be before Pmw_9_9).
            if re.search("^Pmw_[0-9]_[0-9](_[0-9])?$", dirname) is not None:
                for suffix in (".py", ".pyc", ".pyo"):
                    path = os.path.join(pmw_path, dirname, "lib", "PmwLoader" + suffix)
                    if os.path.isfile(path):
                        return 1
            return 0

        # This mimics the scan the __init__.py does.
        candidates = []
        for _fullpath, candidate in listDir(pmw_path):
            if _hasLoader(candidate):
                candidates.append(candidate)

        candidates.sort()
        candidates.reverse()

        if not candidates:
            sys.exit("Error, cannot find any Pmw versions.")

        candidate = os.path.join(pmw_path, candidates[0], "lib")
        version = candidates[0][4:].replace("_", ".")

        return self._packagePmw2(candidate, version)
Exemple #7
0
    def _packagePmw(self, pmw_path):
        # From the "__init__.py" of Pwm:
        def _hasLoader(dirname):  # @ReservedAssignment
            # Only accept Pmw_V_R_P with single digits, since ordering will
            # not work correctly with multiple digits (for example, Pmw_10_0
            # will be before Pmw_9_9).
            if re.search("^Pmw_[0-9]_[0-9](_[0-9])?$", dirname) is not None:
                for suffix in (".py", ".pyc", ".pyo"):
                    path = os.path.join(pmw_path, dirname, "lib",
                                        "PmwLoader" + suffix)
                    if os.path.isfile(path):
                        return 1
            return 0

        # This mimicks the scan the __init__.py does.
        candidates = []
        for _fullpath, candidate in listDir(pmw_path):
            if _hasLoader(candidate):
                candidates.append(candidate)

        candidates.sort()
        candidates.reverse()

        if not candidates:
            sys.exit("Error, cannot find any Pmw versions.")

        candidate = os.path.join(pmw_path, candidates[0], "lib")
        version = candidates[0][4:].replace('_', '.')

        return self._packagePmw2(candidate, version)
Exemple #8
0
def getModuleImportableFilesHash(full_name):
    package_name = full_name.getPackageName()

    paths = getPackageSearchPath(None)

    if package_name is not None:
        paths += getPackageSearchPath(package_name)

    all_suffixes = getAllModuleSuffixes()

    result_hash = hashlib.md5()

    for count, path in enumerate(paths):
        if not os.path.isdir(path):
            continue

        for fullname, filename in listDir(path):
            if isPackageDir(fullname) or filename.endswith(all_suffixes):
                entry = "%s:%s" % (count, filename)

                if str is not bytes:
                    entry = entry.encode("utf8")

                result_hash.update(entry)

    return result_hash.hexdigest()
Exemple #9
0
def detectPthImportedPackages():
    if not hasattr(sys.modules["site"], "getsitepackages"):
        return ()

    # TODO: Move hard import config to elsewhere.
    from nuitka.nodes.ImportNodes import isHardModuleWithoutSideEffect

    pth_imports = set()

    for prefix in sys.modules["site"].getsitepackages():
        if not os.path.isdir(prefix):
            continue

        for path, filename in listDir(prefix):
            if filename.endswith(".pth"):
                try:
                    for line in getFileContentByLine(path, "rU"):
                        if line.startswith("import "):
                            if ";" in line:
                                line = line[:line.find(";")]

                            for part in line[7:].split(","):
                                pth_import = part.strip()

                                if not isHardModuleWithoutSideEffect(
                                        pth_import):
                                    pth_imports.add(pth_import)
                except OSError:
                    recursion_logger.warning(
                        "Python installation problem, cannot read file '%s'.")

    return tuple(sorted(pth_imports))
Exemple #10
0
def checkPluginPath(plugin_filename, module_package):
    plugin_filename = os.path.normpath(plugin_filename)

    if Options.isShowInclusion():
        recursion_logger.info("Checking top level plug-in path %s %s" %
                              (plugin_filename, module_package))

    plugin_info = considerFilename(module_filename=plugin_filename)

    if plugin_info is not None:
        # File or package makes a difference, handle that
        if os.path.isfile(plugin_info[0]) or Importing.isPackageDir(
                plugin_info[0]):
            checkPluginSinglePath(plugin_filename,
                                  module_package=module_package)
        elif os.path.isdir(plugin_info[0]):
            for sub_path, sub_filename in listDir(plugin_info[0]):
                assert sub_filename != "__init__.py"

                if Importing.isPackageDir(sub_path) or sub_path.endswith(
                        ".py"):
                    checkPluginSinglePath(sub_path, module_package=None)
        else:
            recursion_logger.warning("Failed to include module from %r." %
                                     plugin_info[0])
    else:
        recursion_logger.warning("Failed to recurse to directory %r." %
                                 plugin_filename)
Exemple #11
0
def getScanDirectories(package_name, original_dir):
    # Many cases, pylint: disable=too-many-branches

    cache_key = package_name, original_dir

    if cache_key in _scan_dir_cache:
        return _scan_dir_cache[cache_key]

    scan_dirs = [sys.prefix]

    if package_name is not None:
        scan_dirs.extend(_getPackageSpecificDLLDirectories(package_name))

    if original_dir is not None:
        scan_dirs.append(original_dir)
        scan_dirs.extend(getSubDirectories(original_dir))

    if (Utils.isWin32Windows() and package_name is not None
            and package_name.isBelowNamespace("win32com")):
        pywin32_dir = getPyWin32Dir()

        if pywin32_dir is not None:
            scan_dirs.append(pywin32_dir)

    for path_dir in os.environ["PATH"].split(";"):
        if not os.path.isdir(path_dir):
            continue

        if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"])):
            continue
        if areSamePaths(path_dir,
                        os.path.join(os.environ["SYSTEMROOT"], "System32")):
            continue
        if areSamePaths(path_dir,
                        os.path.join(os.environ["SYSTEMROOT"], "SysWOW64")):
            continue

        scan_dirs.append(path_dir)

    result = []

    # Remove directories that hold no DLLs.
    for scan_dir in scan_dirs:
        sys.stdout.flush()

        # These are useless, but plenty.
        if os.path.basename(scan_dir) == "__pycache__":
            continue

        scan_dir = getDirectoryRealPath(scan_dir)

        # No DLLs, no use.
        if not any(entry[1].lower().endswith(".dll")
                   for entry in listDir(scan_dir)):
            continue

        result.append(os.path.realpath(scan_dir))

    _scan_dir_cache[cache_key] = result
    return result
Exemple #12
0
    def considerDataFiles(self, module):
        # Many cases to deal with, pylint: disable=too-many-branches

        module_name = module.getFullName()
        module_folder = module.getCompileTimeDirectory()

        if module_name in self.known_data_files:
            for target_dir, filename in self.known_data_files[module_name]:
                source_path = os.path.join(module_folder, filename)

                if os.path.isfile(source_path):
                    if target_dir is None:
                        target_dir = module_name.asPath()

                    yield (
                        source_path,
                        os.path.normpath(os.path.join(target_dir, filename)),
                    )

        if module_name in self.known_data_dirs:
            data_dirs = self.known_data_dirs[module_name]

            if type(data_dirs) is not tuple:
                data_dirs = (data_dirs, )

            for data_dir in data_dirs:
                yield makeIncludedDataDirectory(
                    os.path.join(module_folder, data_dir),
                    os.path.join(module_name.asPath(), data_dir),
                    "package data for %r" % module_name.asString(),
                )

        if module_name in self.known_data_dir_structure:
            empty_dirs = self.known_data_dir_structure[module_name]

            yield _getSubDirectoryFolders(module, empty_dirs)

        if module_name in self.generated_data_files:
            for target_dir, filename, func in self.generated_data_files[
                    module_name]:
                if target_dir is None:
                    target_dir = module_name.replace(".", os.path.sep)

                yield (func,
                       os.path.normpath(os.path.join(target_dir, filename)))

        if module_name == "lib2to3.pgen2":
            # TODO: Support patterns of files in known_data_files as
            # that would cover this.
            for source_path, filename in listDir(
                    os.path.join(module_folder, "..")):
                if not filename.endswith(".pickle"):
                    continue

                yield makeIncludedDataFile(
                    source_path,
                    os.path.join("lib2to3", filename),
                    "package data for %r" % module_name.asString(),
                )
Exemple #13
0
def cleanSourceDirectory(source_dir):
    extensions = (".bin", ".c", ".cpp", ".exp", ".h", ".lib", ".manifest",
                  ".o", ".obj", ".os", ".rc", ".res", ".S")

    if os.path.isdir(source_dir):
        for path, _filename in listDir(source_dir):
            if hasFilenameExtension(path, extensions):
                deleteFile(path, must_exist=True)
    else:
        makePath(source_dir)
Exemple #14
0
def cleanSconsDirectory(source_dir):
    """Clean scons build directory."""

    extensions = (
        ".bin",
        ".c",
        ".cpp",
        ".exp",
        ".h",
        ".lib",
        ".manifest",
        ".o",
        ".obj",
        ".os",
        ".rc",
        ".res",
        ".S",
        ".txt",
        ".const",
        ".gcda",
        ".pgd",
        ".pgc",
    )

    def check(path):
        if hasFilenameExtension(path, extensions):
            deleteFile(path, must_exist=True)

    if os.path.isdir(source_dir):
        for path, _filename in listDir(source_dir):
            check(path)

        static_dir = os.path.join(source_dir, "static_src")

        if os.path.exists(static_dir):
            for path, _filename in listDir(static_dir):
                check(path)

        plugins_dir = os.path.join(source_dir, "plugins")

        if os.path.exists(plugins_dir):
            for path, _filename in listDir(plugins_dir):
                check(path)
Exemple #15
0
def scanConstFiles(build_dir):
    result = []

    for fullpath, filename in listDir(build_dir):
        if not filename.endswith(".const"):
            continue

        result.append((fullpath, filename))

    return result
Exemple #16
0
def getScanDirectories(package_name, original_dir):
    cache_key = package_name, original_dir

    if cache_key in _scan_dir_cache:
        return _scan_dir_cache[cache_key]

    scan_dirs = [sys.prefix]

    if package_name is not None:
        from nuitka.importing.Importing import findModule

        package_dir = findModule(None, package_name, None, 0, False)[1]

        if os.path.isdir(package_dir):
            scan_dirs.append(package_dir)
            scan_dirs.extend(getSubDirectories(package_dir))

    if original_dir is not None:
        scan_dirs.append(original_dir)
        scan_dirs.extend(getSubDirectories(original_dir))

    for path_dir in os.environ["PATH"].split(";"):
        if not os.path.isdir(path_dir):
            continue

        if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"])):
            continue
        if areSamePaths(path_dir,
                        os.path.join(os.environ["SYSTEMROOT"], "System32")):
            continue
        if areSamePaths(path_dir,
                        os.path.join(os.environ["SYSTEMROOT"], "SysWOW64")):
            continue

        scan_dirs.append(path_dir)

    result = []

    # Remove directories that hold no DLLs.
    for scan_dir in scan_dirs:
        sys.stdout.flush()

        # These are useless, but plenty.
        if os.path.basename(scan_dir) == "__pycache__":
            continue

        # No DLLs, no use.
        if not any(entry[1].lower().endswith(".dll")
                   for entry in listDir(scan_dir)):
            continue

        result.append(scan_dir)

    _scan_dir_cache[cache_key] = result
    return result
Exemple #17
0
    def _getScipyCoreBinaries(scipy_dir):
        """Return binaries from the extra-dlls folder (Windows only)."""

        for dll_dir_name in ("extra_dll", ".libs"):
            dll_dir_path = os.path.join(scipy_dir, dll_dir_name)

            if os.path.isdir(dll_dir_path):
                for source_path, source_filename in listDir(dll_dir_path):
                    if source_filename.lower().endswith(".dll"):
                        yield source_path, os.path.join(
                            "scipy", dll_dir_name, source_filename
                        )
Exemple #18
0
def detectEarlyImports():
    encoding_names = [
        filename[:-3] for _path, filename in listDir(
            os.path.dirname(sys.modules["encodings"].__file__))
        if filename.endswith(".py") if "__init__" not in filename
    ]

    if Utils.getOS() != "Windows":
        for encoding_name in ("mbcs", "cp65001", "oem"):
            if encoding_name in encoding_names:
                encoding_names.remove(encoding_name)

    import_code = ';'.join("import encodings.%s" % encoding_name
                           for encoding_name in encoding_names)

    import_code += ";import locale;"

    # For Python3 we patch inspect without knowing if it is used.
    if python_version >= 300:
        import_code += "import inspect;"

    result = _detectImports(command=import_code,
                            user_provided=False,
                            technical=True)

    if Options.shallFreezeAllStdlib():
        stdlib_modules = set()

        # Scan the standard library paths (multiple in case of virtualenv.
        for stdlib_dir in getStandardLibraryPaths():
            for module_name in scanStandardLibraryPath(stdlib_dir):
                stdlib_modules.add(module_name)

        import_code = "imports = " + repr(sorted(stdlib_modules)) + '\n'\
                      "for imp in imports:\n" \
                      "    try:\n" \
                      "        __import__(imp)\n" \
                      "    except (ImportError, SyntaxError):\n" \
                      "        pass\n"

        early_names = [module.getFullName() for module in result]

        result += [
            module for module in _detectImports(
                command=import_code, user_provided=False, technical=False)
            if module.getFullName() not in early_names
        ]

    debug("Finished detecting early imports.")

    return result
Exemple #19
0
def runPy2dsc(filename, new_name):
    check_call(["py2dsc", new_name])

    # Fixup for py2dsc not taking our custom suffix into account, so we need
    # to rename it ourselves.
    before_deb_name = filename[:-7].lower().replace("-", "_")
    after_deb_name = before_deb_name.replace("rc", "~rc")

    os.rename(
        "deb_dist/%s.orig.tar.gz" % before_deb_name,
        "deb_dist/%s+ds.orig.tar.gz" % after_deb_name,
    )

    check_call(["rm -f deb_dist/*_source*"], shell=True)

    # Remove the now useless input, py2dsc has copied it, and we don't
    # publish it.
    os.unlink(new_name)

    # Assert that the unpacked directory is there and find it. Otherwise fail badly.

    entry = None
    for fullname, entry in listDir("deb_dist"):
        if (
            os.path.isdir(fullname)
            and entry.startswith("nuitka")
            and not entry.endswith(".orig")
        ):
            break

    if entry is None:
        assert False

    # Import the "debian" directory from above. It's not in the original tar and
    # overrides fully what py2dsc did.
    check_call(["rm -r deb_dist/%s/debian/*" % entry], shell=True)

    check_call(
        [
            "rsync",
            "-a",
            "--exclude",
            "pbuilder-hookdir",
            "../debian/",
            "deb_dist/%s/debian/" % entry,
        ]
    )

    check_call(["rm deb_dist/*.dsc deb_dist/*.debian.tar.xz"], shell=True)

    return entry
Exemple #20
0
    def considerDataFiles(self, module):
        # This is considering many options, pylint: disable=too-many-branches

        module_name = module.getFullName()
        module_folder = module.getCompileTimeDirectory()

        if module_name in self.known_data_files:
            for target_dir, filename in self.known_data_files[module_name]:
                source_path = os.path.join(module_folder, filename)

                if os.path.isfile(source_path):
                    if target_dir is None:
                        target_dir = module_name.asPath()

                    yield (
                        source_path,
                        os.path.normpath(os.path.join(target_dir, filename)),
                    )

        if module_name in self.known_data_folders:
            func, subdir, folders_only = self.known_data_folders[module_name]

            if folders_only:
                yield func(module, subdir, folders_only)
            else:
                for item in func(module, subdir, folders_only):
                    yield item

        if module_name in self.generated_data_files:
            for target_dir, filename, func in self.generated_data_files[
                    module_name]:
                if target_dir is None:
                    target_dir = module_name.replace(".", os.path.sep)

                yield (func,
                       os.path.normpath(os.path.join(target_dir, filename)))

        if module_name == "lib2to3.pgen2":
            for source_path, filename in listDir(
                    os.path.join(module_folder, "..")):
                if not filename.endswith(".pickle"):
                    continue

                yield (source_path,
                       os.path.normpath(os.path.join("lib2to3", filename)))
Exemple #21
0
def checkPluginPath(plugin_filename, module_package):
    plugin_filename = os.path.normpath(plugin_filename)

    debug("Checking top level plug-in path %s %s", plugin_filename, module_package)

    plugin_info = considerFilename(module_filename=plugin_filename)

    if plugin_info is not None:
        # File or package makes a difference, handle that
        if os.path.isfile(plugin_info[0]) or Importing.isPackageDir(plugin_info[0]):
            checkPluginSinglePath(plugin_filename, module_package)
        elif os.path.isdir(plugin_info[0]):
            for sub_path, sub_filename in listDir(plugin_info[0]):
                assert sub_filename != "__init__.py"

                if Importing.isPackageDir(sub_path) or sub_path.endswith(".py"):
                    checkPluginSinglePath(sub_path, None)
        else:
            warning("Failed to include module from '%s'.", plugin_info[0])
    else:
        warning("Failed to recurse to directory '%s'.", plugin_filename)
    def considerDataFiles(self, module):
        module_name = module.getFullName()
        module_folder = module.getCompileTimeDirectory()

        if module_name in known_data_files:
            for target_dir, filename in known_data_files[module_name]:
                source_path = os.path.join(module_folder, filename)

                if os.path.isfile(source_path):
                    if target_dir is None:
                        target_dir = module_name.replace(".", os.path.sep)

                    yield (
                        source_path,
                        os.path.normpath(os.path.join(target_dir, filename)),
                    )

        if module_name in known_data_folders:
            func, subdir, folders_only = known_data_folders[module_name]
            for item in func(module, subdir, folders_only):
                yield item

        if module_name in generated_data_files:
            for target_dir, filename, func in generated_data_files[
                    module_name]:
                if target_dir is None:
                    target_dir = module_name.replace(".", os.path.sep)

                yield (func,
                       os.path.normpath(os.path.join(target_dir, filename)))

        if module_name == "lib2to3.pgen2":
            for source_path, filename in listDir(
                    os.path.join(module_folder, "..")):
                if not filename.endswith(".pickle"):
                    continue

                yield (source_path,
                       os.path.normpath(os.path.join("lib2to3", filename)))
Exemple #23
0
def getModuleImportableFilesHash(full_name):
    """Calculate hash value of packages importable for a module of this name."""
    package_name = full_name.getPackageName()

    paths = getPackageSearchPath(None)

    if package_name is not None:
        paths += getPackageSearchPath(package_name)

    all_suffixes = getAllModuleSuffixes()

    result_hash = Hash()

    for path in paths:
        if not os.path.isdir(path):
            continue

        for fullname, filename in listDir(path):
            if isPackageDir(fullname) or filename.endswith(all_suffixes):
                result_hash.updateFromValues(filename, b"\0")

    return result_hash.asHexDigest()
Exemple #24
0
def runPy2dsc(filename, new_name):
    assert os.system("py2dsc " + new_name) == 0

    # Fixup for py2dsc not taking our custom suffix into account, so we need
    # to rename it ourselves.
    before_deb_name = filename[:-7].lower().replace("-", "_")
    after_deb_name = before_deb_name.replace("rc", "~rc")

    assert (os.system(
        "mv 'deb_dist/%s.orig.tar.gz' 'deb_dist/%s+ds.orig.tar.gz'" %
        (before_deb_name, after_deb_name)) == 0)

    assert os.system("rm -f deb_dist/*_source*") == 0

    # Remove the now useless input, py2dsc has copied it, and we don't
    # publish it.
    os.unlink(new_name)

    # Assert that the unpacked directory is there and find it. Otherwise fail badly.

    entry = None
    for fullname, entry in listDir("deb_dist"):
        if (os.path.isdir(fullname) and entry.startswith("nuitka")
                and not entry.endswith(".orig")):
            break

    if entry is None:
        assert False

    # Import the "debian" directory from above. It's not in the original tar and
    # overrides fully what py2dsc did.
    assert os.system("rm -r deb_dist/%s/debian/*" % entry) == 0
    assert (os.system(
        "rsync -a --exclude pbuilder-hookdir ../debian/ deb_dist/%s/debian/" %
        entry) == 0)

    assert os.system("rm deb_dist/*.dsc deb_dist/*.debian.tar.xz") == 0

    return entry
Exemple #25
0
    def _packagePmw(self, pmw_path):
        self.info("Packaging Pmw into single module fpor freezing.")

        # Algorithm is from the "__init__.py" of Pwm:

        def _hasLoader(dirname):
            # Only accept Pmw_V_R_P with single digits, since ordering will
            # not work correctly with multiple digits (for example, Pmw_10_0
            # will be before Pmw_9_9).
            if re.search("^Pmw_[0-9]_[0-9](_[0-9])?$", dirname) is not None:
                for suffix in (".py", ".pyc", ".pyo"):
                    path = os.path.join(pmw_path, dirname, "lib",
                                        "PmwLoader" + suffix)
                    if os.path.isfile(path):
                        return 1
            return 0

        # This mimics the scan the __init__.py does.
        candidates = []
        for _fullpath, candidate in listDir(pmw_path):
            if _hasLoader(candidate):
                candidates.append(candidate)

        candidates.sort()
        candidates.reverse()

        if not candidates:
            self.sysexit("Error, cannot find any Pmw versions.")

        self.info("Found the following Pmw version candidates %s." %
                  ",".join(candidates))

        candidate = os.path.join(pmw_path, candidates[0], "lib")
        version = candidates[0][4:].replace("_", ".")

        self.info("Picked version %s." % version)

        return self._packagePmw2(candidate, version)
Exemple #26
0
def cleanSourceDirectory(source_dir):
    extensions = (
        ".bin",
        ".c",
        ".cpp",
        ".exp",
        ".h",
        ".lib",
        ".manifest",
        ".o",
        ".obj",
        ".os",
        ".rc",
        ".res",
        ".S",
        ".txt",
    )

    if os.path.isdir(source_dir):
        for path, _filename in listDir(source_dir):
            if hasFilenameExtension(path, extensions):
                deleteFile(path, must_exist=True)
    else:
        makePath(source_dir)
Exemple #27
0
def detectPthImportedPackages():
    if not hasattr(sys.modules["site"], "getsitepackages"):
        return ()

    pth_imports = set()

    for prefix in sys.modules["site"].getsitepackages():
        if not os.path.isdir(prefix):
            continue

        for path, filename in listDir(prefix):
            if filename.endswith(".pth"):
                try:
                    for line in getFileContentByLine(path, "rU"):
                        if line.startswith("import "):
                            if ";" in line:
                                line = line[: line.find(";")]

                            for part in line[7:].split(","):
                                pth_imports.add(part.strip())
                except OSError:
                    warning("Python installation problem, cannot read file '%s'.")

    return tuple(sorted(pth_imports))
Exemple #28
0
def executePASS1():
    my_print("PASS 1: Compiling from compiler running from .py files.")

    base_dir = os.path.join("..", "..")

    for package in PACKAGE_LIST:
        package = package.replace('/', os.path.sep)

        source_dir = os.path.join(base_dir, package)
        target_dir = package

        removeDirectory(
            path = target_dir,
            ignore_errors = False
        )

        os.mkdir(target_dir)

        for path, filename in listDir(target_dir):
            if filename.endswith(".so"):
                os.unlink(path)

        for path, filename in listDir(source_dir):
            if not filename.endswith(".py"):
                continue

            if filename.startswith(".#"):
                continue

            if filename != "__init__.py":
                my_print("Compiling '%s'." % path)

                command = [
                    os.environ["PYTHON"],
                    nuitka_main_path,
                    "--module",
                    "--plugin-enable=pylint-warnings",
                    "--output-dir=%s" % target_dir,
                    "--no-pyi-file",
                    path
                ]
                command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split()

                result = subprocess.call(
                    command
                )

                if result != 0:
                    sys.exit(result)
            else:
                shutil.copyfile(path, os.path.join(target_dir, filename))


    my_print("Compiling '%s'." % nuitka_main_path)

    shutil.copyfile(nuitka_main_path, "nuitka-runner.py")

    command = [
        os.environ["PYTHON"],
        nuitka_main_path,
        "--nofollow-imports",
        "--plugin-enable=pylint-warnings",
        "--output-dir=.",
        "--python-flag=-S",
        "nuitka-runner.py"
    ]
    command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split()

    result = subprocess.call(
        command
    )

    if result != 0:
        sys.exit(result)

    shutil.move("nuitka-runner" + exe_suffix, "nuitka" + exe_suffix)

    scons_inline_copy_path = os.path.join(
        base_dir,
        "nuitka",
        "build",
        "inline_copy"
    )

    if os.path.exists(scons_inline_copy_path):
        shutil.copytree(
            scons_inline_copy_path,
            os.path.join("nuitka", "build", "inline_copy")
        )

    shutil.copyfile(
        os.path.join(base_dir, "nuitka", "build", "SingleExe.scons"),
        os.path.join("nuitka", "build", "SingleExe.scons")
    )
    shutil.copytree(
        os.path.join(base_dir, "nuitka", "build", "static_src"),
        os.path.join("nuitka", "build", "static_src")
    )
    shutil.copytree(
        os.path.join(base_dir, "nuitka", "build", "include"),
        os.path.join("nuitka", "build", "include")
    )
Exemple #29
0
def _detectBinaryPathDLLsWindows(is_main_executable, source_dir, original_dir,
                                 binary_filename, package_name):
    # This is complex, as it also includes the caching mechanism
    # pylint: disable=too-many-locals

    result = set()

    cache_filename = _getCacheFilename(is_main_executable, source_dir,
                                       original_dir, binary_filename)

    if os.path.exists(cache_filename
                      ) and not Options.shallNotUseDependsExeCachedResults():
        for line in open(cache_filename):
            line = line.strip()

            result.add(line)

        return result

    # User query should only happen once if at all.
    with _withLock():
        depends_exe = getDependsExePath()

    scan_dirs = [sys.prefix]

    if package_name is not None:
        from nuitka.importing.Importing import findModule

        package_dir = findModule(None, package_name, None, 0, False)[1]

        if os.path.isdir(package_dir):
            scan_dirs.append(package_dir)
            scan_dirs.extend(getSubDirectories(package_dir))

    if original_dir is not None:
        scan_dirs.append(original_dir)
        scan_dirs.extend(getSubDirectories(original_dir))

    with _withLock():
        # The search order by default prefers the system directory, where a
        # wrong "PythonXX.dll" might be living.
        with open(binary_filename + ".dwp", 'w') as dwp_file:
            dwp_file.write(
                """\
KnownDLLs
%(original_dirs)s
SysPath
32BitSysDir
16BitSysDir
OSDir
AppPath
SxS
""" % {
                    "original_dirs":
                    '\n'.join("UserDir %s" % dirname for dirname in scan_dirs
                              if not os.path.basename(dirname) == "__pycache__"
                              if any(entry[1].lower().endswith(".dll")
                                     for entry in listDir(dirname))),
                })

        # Starting the process while locked, so file handles are not duplicated.
        depends_exe_process = subprocess.Popen(
            (depends_exe, "-c", "-ot%s" % binary_filename + ".depends",
             "-d:%s" % binary_filename + ".dwp", "-f1", "-pa1", "-ps1",
             binary_filename))

    # TODO: Exit code should be checked.
    depends_exe_process.wait()

    # Opening the result under lock, so it is not getting locked by new processes.
    with _withLock():
        _parseDependsExeOutput(binary_filename + ".depends", result)

    deleteFile(binary_filename + ".depends", must_exist=True)
    deleteFile(binary_filename + ".dwp", must_exist=True)

    if not Options.shallNotStoreDependsExeCachedResults():
        with open(cache_filename, 'w') as cache_file:
            for dll_filename in result:
                print(dll_filename, file=cache_file)

    return result
Exemple #30
0
def detectEarlyImports():
    encoding_names = [
        filename[:-3] for _path, filename in listDir(
            os.path.dirname(sys.modules["encodings"].__file__))
        if filename.endswith(".py") if "__init__" not in filename
    ]

    if Utils.getOS() != "Windows":
        for encoding_name in ("mbcs", "cp65001", "oem"):
            if encoding_name in encoding_names:
                encoding_names.remove(encoding_name)

    import_code = ';'.join("import encodings.%s" % encoding_name
                           for encoding_name in encoding_names)

    import_code += ";import locale;"

    # For Python3 we patch inspect without knowing if it is used.
    if python_version >= 300:
        import_code += "import inspect;"

    result = _detectImports(command=import_code,
                            user_provided=False,
                            technical=True)

    if Options.shallFreezeAllStdlib():
        stdlib_modules = set()

        # Scan the standard library paths (multiple in case of virtualenv.
        for stdlib_dir in getStandardLibraryPaths():
            for module_name in scanStandardLibraryPath(stdlib_dir):
                stdlib_modules.add(module_name)

        # Put here ones that should be imported first.
        first_ones = ("Tkinter", )

        # We have to fight zombie modules in this, some things, e.g. Tkinter
        # on newer Python 2.7, comes back after failure without a second error
        # being raised, leading to other issues. So we fight it after each
        # module that was tried, and prevent re-try by adding a meta path
        # based loader that will never load it again, and remove it from the
        # "sys.modules" over and over, once it sneaks back. The root cause is
        # that extension modules sometimes only raise an error when first
        # imported, not the second time around.
        # Otherwise this just makes imports of everything so we can see where
        # it comes from and what it requires.

        import_code = """
imports = %r

failed = set()

class ImportBlocker(object):
    def find_module(self, fullname, path = None):
        if fullname in failed:
            return self

        return None

    def load_module(self, name):
        raise ImportError("%%s has failed before" %% name)

sys.meta_path.insert(0, ImportBlocker())

for imp in imports:
    try:
        __import__(imp)
    except (ImportError, SyntaxError):
        failed.add(imp)

    for fail in failed:
        if fail in sys.modules:
            del sys.modules[fail]
""" % sorted(stdlib_modules, key=lambda name: (name not in first_ones, name))

        early_names = [module.getFullName() for module in result]

        result += [
            module for module in _detectImports(
                command=import_code, user_provided=False, technical=False)
            if module.getFullName() not in early_names
        ]

    debug("Finished detecting early imports.")

    return result
Exemple #31
0
def _findModuleInPath2(module_name, search_path):
    """ This is out own module finding low level implementation.

        Just the full module name and search path are given. This is then
        tasked to raise "ImportError" or return a path if it finds it, or
        None, if it is a built-in.
    """
    # We have many branches here, because there are a lot of cases to try.
    # pylint: disable=too-many-branches

    # We may have to decide between package and module, therefore build
    # a list of candidates.
    candidates = oset.OrderedSet()

    considered = set()

    for entry in search_path:
        # Don't try again, just with an entry of different casing or complete
        # duplicate.
        if os.path.normcase(entry) in considered:
            continue
        considered.add(os.path.normcase(entry))

        package_directory = os.path.join(entry, module_name)

        # First, check for a package with an init file, that would be the
        # first choice.
        if os.path.isdir(package_directory):
            for suffix in (".py", ".pyc"):
                package_file_name = "__init__" + suffix

                file_path = os.path.join(package_directory, package_file_name)

                if os.path.isfile(file_path):
                    candidates.add(
                        (entry, 1, package_directory)
                    )
                    break
            else:
                if python_version >= 330:
                    candidates.add(
                        (entry, 2, package_directory)
                    )

        # Then, check out suffixes of all kinds.
        for suffix, _mode, _type in imp.get_suffixes():
            file_path = os.path.join(entry, module_name + suffix)
            if os.path.isfile(file_path):
                candidates.add(
                    (entry, 1, file_path)
                )
                break

    if _debug_module_finding:
        print("Candidates", candidates)

    if candidates:
        # Ignore lower priority matches from package directories without
        # "__init__.py" file.
        min_prio = min(candidate[1] for candidate in candidates)
        candidates = [
            candidate
            for candidate in
            candidates
            if candidate[1] == min_prio
        ]

        # On case sensitive systems, no resolution needed.
        if case_sensitive:
            return candidates[0][2]
        else:
            for candidate in candidates:
                for fullname, _filename in listDir(candidate[0]):
                    if fullname == candidate[2]:
                        return candidate[2]

            # Only exact case matches matter, all candidates were ignored,
            # lets just fall through to raising the import error.

    # Nothing found.
    raise ImportError
Exemple #32
0
def diffRecursive(dir1, dir2):
    # Complex in nature, pylint: disable=too-many-branches

    done = set()

    result = False

    for path1, filename in listDir(dir1):
        if "cache-" in path1:
            continue

        path2 = os.path.join(dir2, filename)

        done.add(path1)

        # Skip these binary files and scons build database of course.
        # TODO: Temporary ignore ".bin", until we have something better than marshal which behaves
        # differently in compiled Nuitka:
        if filename.endswith(
            (
                ".o",
                ".os",
                ".obj",
                ".dblite",
                ".tmp",
                ".sconsign",
                ".txt",
                ".bin",
                ".const",
                ".exp",
            )
        ):
            continue

        if not os.path.exists(path2):
            my_print("Only in %s: %s" % (dir1, filename))
            result = False
            continue

        if os.path.isdir(path1):
            r = diffRecursive(path1, path2)
            if r:
                result = True
        elif os.path.isfile(path1):
            fromdate = time.ctime(os.stat(path1).st_mtime)
            todate = time.ctime(os.stat(path2).st_mtime)

            diff = difflib.unified_diff(
                a=readSource(path1).splitlines(),
                b=readSource(path2).splitlines(),
                fromfile=path1,
                tofile=path2,
                fromfiledate=fromdate,
                tofiledate=todate,
                n=3,
            )

            diff_list = list(diff)

            if diff_list:
                for line in diff_list:
                    try:
                        my_print(line)
                    except UnicodeEncodeError:
                        my_print(repr(line))

                result = True
        else:
            assert False, path1

    for path1, filename in listDir(dir2):
        if "cache-" in path1:
            continue

        path2 = os.path.join(dir2, filename)

        if path1 in done:
            continue

        if not os.path.exists(path1):
            my_print("Only in %s: %s" % (dir2, filename))
            result = False
            continue

    return result
Exemple #33
0
def _findModuleInPath2(module_name, search_path):
    """ This is out own module finding low level implementation.

        Just the full module name and search path are given. This is then
        tasked to raise "ImportError" or return a path if it finds it, or
        None, if it is a built-in.
    """
    # We have many branches here, because there are a lot of cases to try.
    # pylint: disable=too-many-branches,too-many-locals

    # We may have to decide between package and module, therefore build
    # a list of candidates.
    candidates = OrderedSet()

    considered = set()

    for entry in search_path:
        # Don't try again, just with an entry of different casing or complete
        # duplicate.
        if os.path.normcase(entry) in considered:
            continue
        considered.add(os.path.normcase(entry))

        package_directory = os.path.join(entry, module_name)

        # First, check for a package with an init file, that would be the
        # first choice.
        if os.path.isdir(package_directory):
            for suffix, _mode, mtype in imp.get_suffixes():
                if mtype == imp.C_EXTENSION:
                    continue

                package_file_name = "__init__" + suffix

                file_path = os.path.join(package_directory, package_file_name)

                if os.path.isfile(file_path):
                    candidates.add((entry, 1, package_directory))
                    break
            else:
                if python_version >= 300:
                    candidates.add((entry, 2, package_directory))

        # Then, check out suffixes of all kinds.
        for suffix, _mode, _type in imp.get_suffixes():
            file_path = os.path.join(entry, module_name + suffix)
            if os.path.isfile(file_path):
                candidates.add((entry, 1, file_path))
                break

    if _debug_module_finding:
        print("Candidates", candidates)

    if candidates:
        # Ignore lower priority matches from package directories without
        # "__init__.py" file.
        min_prio = min(candidate[1] for candidate in candidates)
        candidates = [candidate for candidate in candidates if candidate[1] == min_prio]

        # On case sensitive systems, no resolution needed.
        if case_sensitive:
            return candidates[0][2]
        else:
            for candidate in candidates:
                for fullname, _filename in listDir(candidate[0]):
                    if fullname == candidate[2]:
                        return candidate[2]

            # Only exact case matches matter, all candidates were ignored,
            # lets just fall through to raising the import error.

    # Nothing found.
    raise ImportError
Exemple #34
0
def executePASS1():
    my_print("PASS 1: Compiling from compiler running from .py files.")

    base_dir = os.path.join("..", "..")

    for package in PACKAGE_LIST:
        package = package.replace('/', os.path.sep)

        source_dir = os.path.join(base_dir, package)
        target_dir = package

        removeDirectory(
            path = target_dir,
            ignore_errors = False
        )

        os.mkdir(target_dir)

        for path, filename in listDir(target_dir):
            if filename.endswith(".so"):
                os.unlink(path)

        for path, filename in listDir(source_dir):
            if not filename.endswith(".py"):
                continue

            if filename.startswith(".#"):
                continue

            if filename != "__init__.py":
                my_print("Compiling '%s'." % path)

                command = [
                    os.environ["PYTHON"],
                    nuitka_main_path,
                    "--module",
                    "--recurse-none",
                    "--plugin-enable=pylint-warnings",
                    "--output-dir=%s" % target_dir,
                    "--no-pyi-file",
                    path
                ]
                command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split()

                result = subprocess.call(
                    command
                )

                if result != 0:
                    sys.exit(result)
            else:
                shutil.copyfile(path, os.path.join(target_dir, filename))


    my_print("Compiling '%s'." % nuitka_main_path)

    shutil.copyfile(nuitka_main_path, "nuitka-runner.py")

    command = [
        os.environ["PYTHON"],
        nuitka_main_path,
        "--recurse-none",
        "--plugin-enable=pylint-warnings",
        "--output-dir=.",
        "--python-flag=-S",
        "nuitka-runner.py"
    ]
    command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split()

    result = subprocess.call(
        command
    )

    if result != 0:
        sys.exit(result)

    shutil.move("nuitka-runner.exe", "nuitka.exe")

    scons_inline_copy_path = os.path.join(
        base_dir,
        "nuitka",
        "build",
        "inline_copy"
    )

    if os.path.exists(scons_inline_copy_path):
        shutil.copytree(
            scons_inline_copy_path,
            os.path.join("nuitka", "build", "inline_copy")
        )

    shutil.copy(
        os.path.join(base_dir, "nuitka", "build", "SingleExe.scons"),
        os.path.join("nuitka", "build", "SingleExe.scons")
    )
    shutil.copytree(
        os.path.join(base_dir, "nuitka", "build", "static_src"),
        os.path.join("nuitka", "build", "static_src")
    )
    shutil.copytree(
        os.path.join(base_dir, "nuitka", "build", "include"),
        os.path.join("nuitka", "build", "include")
    )
Exemple #35
0
def compileAndCompareWith(nuitka):
    if "PYTHONHASHSEED" not in os.environ:
        os.environ["PYTHONHASHSEED"] = "0"

    base_dir = os.path.join("..", "..")

    for package in PACKAGE_LIST:
        package = package.replace("/", os.path.sep)

        source_dir = os.path.join(base_dir, package)

        for path, filename in listDir(source_dir):
            if not filename.endswith(".py"):
                continue

            if filename.startswith(".#"):
                continue

            path = os.path.join(source_dir, filename)

            if filename != "__init__.py":
                my_print("Compiling '%s'." % path)

                target = filename.replace(".py", ".build")

                target_dir = os.path.join(tmp_dir, target)

                removeDirectory(path=target_dir, ignore_errors=False)

                command = [
                    nuitka,
                    "--module",
                    "--plugin-enable=pylint-warnings",
                    "--output-dir=%s" % tmp_dir,
                    "--no-pyi-file",
                    path,
                ]
                command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split()

                my_print("Command: ", " ".join(command))
                result = subprocess.call(command)

                if result != 0:
                    sys.exit(result)

                has_diff = diffRecursive(os.path.join(package, target),
                                         target_dir)

                # TODO: Temporary, until we have something better than marshal which behaves
                # differently in compiled Nuitka:
                if has_diff and filename not in (
                        "Contexts.py",
                        "Whitelisting.py",
                        "ImplicitImports.py",
                ):
                    sys.exit("There were differences!")

                shutil.rmtree(target_dir)

                if os.name == "nt":
                    target_filename = filename.replace(".py", ".pyd")
                else:
                    target_filename = filename.replace(".py", ".so")

                os.unlink(os.path.join(tmp_dir, target_filename))
Exemple #36
0
def compileAndCompareWith(nuitka):
    if "PYTHONHASHSEED" not in os.environ:
        os.environ["PYTHONHASHSEED"] = '0'

    base_dir = os.path.join("..", "..")

    for package in PACKAGE_LIST:
        package = package.replace('/', os.path.sep)

        source_dir = os.path.join(base_dir, package)

        for path, filename in listDir(source_dir):
            if not filename.endswith(".py"):
                continue

            if filename.startswith(".#"):
                continue

            path = os.path.join(source_dir, filename)

            if filename != "__init__.py":
                my_print("Compiling '%s'." % path)

                target = filename.replace(".py", ".build")

                target_dir = os.path.join(tmp_dir, target)

                removeDirectory(
                    path = target_dir,
                    ignore_errors = False
                )

                command = [
                    nuitka,
                    "--module",
                    "--plugin-enable=pylint-warnings",
                    "--output-dir=%s"% tmp_dir,
                    "--no-pyi-file",
                    path
                ]
                command += os.environ.get("NUITKA_EXTRA_OPTIONS", "").split()

                result = subprocess.call(
                    command
                )

                if result != 0:
                    sys.exit(result)

                has_diff = diffRecursive(os.path.join(package, target), target_dir)

                if has_diff:
                    sys.exit("There were differences!")

                shutil.rmtree(target_dir)

                if os.name == "nt":
                    target_filename = filename.replace(".py", ".pyd")
                else:
                    target_filename = filename.replace(".py", ".so")

                os.unlink(os.path.join(tmp_dir, target_filename))
Exemple #37
0
def checkPluginSinglePath(plugin_filename, module_package):
    # Many branches, for the decision is very complex, pylint: disable=too-many-branches

    debug("Checking detail plug-in path '%s' '%s':", plugin_filename, module_package)

    module_name, module_kind = Importing.getModuleNameAndKindFromFilename(
        plugin_filename
    )

    if module_kind is not None:
        decision, reason = decideRecursion(
            module_filename=plugin_filename,
            module_name=module_name,
            module_package=module_package,
            module_kind=module_kind,
            extra_recursion=True,
        )

        if decision:
            module_relpath = relpath(plugin_filename)

            module, is_added = recurseTo(
                module_filename=plugin_filename,
                module_relpath=module_relpath,
                module_package=module_package,
                module_kind=module_kind,
                reason=reason,
            )

            if module:
                if not is_added:
                    warning(
                        "Recursed to %s '%s' at '%s' twice.",
                        "package" if module.isCompiledPythonPackage() else "module",
                        module.getName(),
                        plugin_filename,
                    )

                    if not isSameModulePath(module.getFilename(), plugin_filename):
                        warning(
                            "Duplicate '%s' of '%s' ignored .",
                            plugin_filename,
                            module.getFilename(),
                        )

                        return

                debug(
                    "Recursed to %s %s %s",
                    module.getName(),
                    module.getPackage(),
                    module,
                )

                ImportCache.addImportedModule(module)

                if module.isCompiledPythonPackage():
                    package_filename = module.getFilename()

                    if os.path.isdir(package_filename):
                        # Must be a namespace package.
                        assert python_version >= 300

                        package_dir = package_filename

                        # Only include it, if it contains actual modules, which will
                        # recurse to this one and find it again.
                    else:
                        package_dir = os.path.dirname(package_filename)

                        # Real packages will always be included.
                        ModuleRegistry.addRootModule(module)

                    debug("Package directory %s", package_dir)

                    for sub_path, sub_filename in listDir(package_dir):
                        if sub_filename in ("__init__.py", "__pycache__"):
                            continue

                        assert sub_path != plugin_filename

                        if Importing.isPackageDir(sub_path) or sub_path.endswith(".py"):
                            checkPluginSinglePath(sub_path, module.getFullName())

                elif module.isCompiledPythonModule():
                    ModuleRegistry.addRootModule(module)

            else:
                warning("Failed to include module from '%s'.", plugin_filename)
Exemple #38
0
def _checkPluginPath(plugin_filename, module_package):
    # Many branches, for the decision is very complex, pylint: disable=too-many-branches

    debug("Checking detail plug-in path '%s' '%s':", plugin_filename,
          module_package)

    module_name, module_kind = Importing.getModuleNameAndKindFromFilename(
        plugin_filename)

    if module_kind is not None:
        decision, reason = decideRecursion(module_filename=plugin_filename,
                                           module_name=module_name,
                                           module_package=module_package,
                                           module_kind=module_kind,
                                           extra_recursion=True)

        if decision:
            module_relpath = relpath(plugin_filename)

            module, is_added = recurseTo(module_filename=plugin_filename,
                                         module_relpath=module_relpath,
                                         module_package=module_package,
                                         module_kind="py",
                                         reason=reason)

            if module:
                if not is_added:
                    warning(
                        "Recursed to %s '%s' at '%s' twice.", "package"
                        if module.isCompiledPythonPackage() else "module",
                        module.getName(), plugin_filename)

                    if not isSameModulePath(module.getFilename(),
                                            plugin_filename):
                        warning("Duplicate '%s' of '%s' ignored .",
                                plugin_filename, module.getFilename())

                        return

                debug("Recursed to %s %s %s", module.getName(),
                      module.getPackage(), module)

                ImportCache.addImportedModule(module)

                if module.isCompiledPythonPackage():
                    package_filename = module.getFilename()

                    if os.path.isdir(package_filename):
                        # Must be a namespace package.
                        assert python_version >= 330

                        package_dir = package_filename

                        # Only include it, if it contains actual modules, which will
                        # recurse to this one and find it again.
                    else:
                        package_dir = os.path.dirname(package_filename)

                        # Real packages will always be included.
                        ModuleRegistry.addRootModule(module)

                    debug("Package directory %s", package_dir)

                    for sub_path, sub_filename in listDir(package_dir):
                        if sub_filename in ("__init__.py", "__pycache__"):
                            continue

                        assert sub_path != plugin_filename

                        if Importing.isPackageDir(sub_path) or \
                           sub_path.endswith(".py"):
                            _checkPluginPath(sub_path, module.getFullName())

                elif module.isCompiledPythonModule():
                    ModuleRegistry.addRootModule(module)

            else:
                warning("Failed to include module from '%s'.", plugin_filename)
Exemple #39
0
def _findModuleInPath2(package_name, module_name, search_path):
    """This is out own module finding low level implementation.

    Just the full module name and search path are given. This is then
    tasked to raise "ImportError" or return a path if it finds it, or
    None, if it is a built-in.
    """
    # We have many branches here, because there are a lot of cases to try.
    # pylint: disable=too-many-branches,too-many-locals

    # We may have to decide between package and module, therefore build
    # a list of candidates.
    candidates = OrderedSet()

    considered = set()

    # Higher values are lower priority.
    priority_map = {
        imp.PY_COMPILED:
        3,
        imp.PY_SOURCE:
        0 if Options.shallPreferSourcecodeOverExtensionModules() else 2,
        imp.C_EXTENSION:
        1,
    }

    for count, entry in enumerate(search_path):
        # Don't try again, just with an entry of different casing or complete
        # duplicate.
        if os.path.normcase(entry) in considered:
            continue
        considered.add(os.path.normcase(entry))

        package_directory = os.path.join(entry, module_name.asPath())

        # First, check for a package with an init file, that would be the
        # first choice.
        if os.path.isdir(package_directory):
            found = False

            for suffix, _mode, mtype in imp.get_suffixes():
                if mtype == imp.C_EXTENSION:
                    continue

                package_file_name = "__init__" + suffix

                file_path = os.path.join(package_directory, package_file_name)

                if os.path.isfile(file_path):
                    candidates.add(
                        ImportScanFinding(
                            found_in=entry,
                            priority=priority_map[mtype],
                            full_path=package_directory,
                            search_order=count,
                        ))
                    found = True

            if not found and python_version >= 0x300:
                candidates.add(
                    ImportScanFinding(
                        found_in=entry,
                        priority=10,
                        full_path=package_directory,
                        search_order=count + len(search_path),
                    ))

        # Then, check out suffixes of all kinds, but only for one directory.
        last_mtype = 0
        for suffix, _mode, mtype in imp.get_suffixes():
            # Use first match per kind only.
            if mtype == last_mtype:
                continue

            full_path = os.path.join(entry, module_name + suffix)

            if os.path.isfile(full_path):
                candidates.add(
                    ImportScanFinding(
                        found_in=entry,
                        priority=priority_map[mtype],
                        full_path=full_path,
                        search_order=count,
                    ))
                last_mtype = mtype

    if _debug_module_finding:
        print("Candidates:", candidates)

    if candidates:
        # Sort by priority, with entries from same path element coming first, then desired type.
        candidates = sorted(candidates,
                            key=lambda c: (c.search_order, c.priority))

        # On case sensitive systems, no resolution needed.
        if case_sensitive:
            _reportCandidates(
                module_name=package_name.getChildNamed(module_name)
                if package_name is not None else module_name,
                candidate=candidates[0],
                candidates=candidates,
            )
            return candidates[0].full_path
        else:
            for candidate in candidates:
                for fullname, _filename in listDir(candidate[0]):
                    if fullname == candidate.full_path:
                        _reportCandidates(module_name, candidate, candidates)
                        return candidate.full_path

            # Only exact case matches matter, all candidates were ignored,
            # lets just fall through to raising the import error.

    # Nothing found.
    raise ImportError