Esempio n. 1
0
    def _reportImplicitImports(implicit_imports, signal_change):
        from nuitka.importing import Recursion
        from nuitka.importing.Importing import getModuleNameAndKindFromFilename

        for full_name, module_filename in implicit_imports:
            _module_name2, module_kind = getModuleNameAndKindFromFilename(
                module_filename)

            # This will get back to all other plugins allowing them to inhibit it though.
            decision, reason = Recursion.decideRecursion(
                module_filename=module_filename,
                module_name=full_name,
                module_kind=module_kind,
            )

            if decision:
                imported_module, added_flag = Recursion.recurseTo(
                    module_package=full_name.getPackageName(),
                    module_filename=module_filename,
                    module_relpath=relpath(module_filename),
                    module_kind=module_kind,
                    reason=reason,
                )

                addUsedModule(imported_module)

                if added_flag:
                    signal_change(
                        "new_code",
                        imported_module.getSourceReference(),
                        "Recursed to module.",
                    )
Esempio n. 2
0
    def _consider(self, trace_collection, module_filename, module_package):
        assert module_package is None or (
            type(module_package) is ModuleName
            and module_package != ""), repr(module_package)

        module_filename = os.path.normpath(module_filename)

        module_name, module_kind = getModuleNameAndKindFromFilename(
            module_filename)

        if module_kind is not None:
            module_fullpath = ModuleName.makeModuleNameInPackage(
                module_name, module_package)

            decision, reason = decideRecursion(
                module_filename=module_filename,
                module_name=module_fullpath,
                module_kind=module_kind,
            )

            if decision:
                module_relpath = relpath(module_filename)

                imported_module, added_flag = recurseTo(
                    module_package=module_package,
                    module_filename=module_filename,
                    module_relpath=module_relpath,
                    module_kind=module_kind,
                    reason=reason,
                )

                if added_flag:
                    trace_collection.signalChange(
                        "new_code",
                        imported_module.getSourceReference(),
                        "Recursed to module.",
                    )

                return imported_module
            elif decision is False and module_kind == "py":
                uncompiled_module = getUncompiledModule(
                    module_fullpath, module_filename)

                if uncompiled_module is not None:
                    return uncompiled_module
            elif decision is None and module_kind == "py":
                if (module_filename not in self._warned_about
                        and module_fullpath not in getModuleIgnoreList()):
                    self._warned_about.add(module_filename)

                    inclusion_logger.warning("""\
Not recursing to '%(full_path)s' (%(filename)s), please specify \
--nofollow-imports (do not warn), \
--follow-imports (recurse to all), \
--nofollow-import-to=%(full_path)s (ignore it), \
--follow-import-to=%(full_path)s (recurse to it) to change.""" % {
                        "full_path": module_fullpath,
                        "filename": module_filename
                    })
Esempio n. 3
0
    def attemptRecursion(self):
        # Make sure the package is recursed to.

        # Return the list of newly added modules.
        result = []

        if self.package_name is not None and self.package is None:
            self.package = getModuleByName(self.package_name)

        if self.package_name is not None and self.package is None:
            package_package, package_filename, finding = findModule(
                importing=self,
                module_name=self.package_name,
                parent_package=None,
                level=1,
                warn=python_version < 330)

            # TODO: Temporary, if we can't find the package for Python3.3 that
            # is semi-OK, maybe.
            if python_version >= 330 and not package_filename:
                return []

            if self.package_name == "uniconvertor.app.modules":
                return []

            assert package_filename is not None, (self.package_name, finding)

            _package_name, package_kind = getModuleNameAndKindFromFilename(
                package_filename)
            # assert _package_name == self.package_name, (package_filename, _package_name, self.package_name)

            decision, _reason = decideRecursion(
                module_filename=package_filename,
                module_name=self.package_name,
                module_package=package_package,
                module_kind=package_kind)

            if decision is not None:
                self.package, is_added = recurseTo(
                    module_package=package_package,
                    module_filename=package_filename,
                    module_relpath=relpath(package_filename),
                    module_kind="py",
                    reason="Containing package of recursed module '%s'." %
                    self.getFullName(),
                )

                if is_added:
                    result.append(self.package)

        if self.package:
            from nuitka.ModuleRegistry import addUsedModule

            addUsedModule(self.package)

            #            print "Recursed to package", self.package_name
            result.extend(self.package.attemptRecursion())

        return result
Esempio n. 4
0
def considerFilename(module_filename):
    module_filename = os.path.normpath(module_filename)

    if os.path.isdir(module_filename):
        module_filename = os.path.abspath(module_filename)

        module_name = os.path.basename(module_filename)
        module_relpath = relpath(module_filename)

        return module_filename, module_relpath, module_name
    elif module_filename.endswith(".py"):
        module_name = os.path.basename(module_filename)[:-3]
        module_relpath = relpath(module_filename)

        return module_filename, module_relpath, module_name
    else:
        return None
Esempio n. 5
0
def _addIncludedDataFilesFromFileOptions():
    for pattern, src, dest, arg in getShallIncludeDataFiles():
        filenames = resolveShellPatternToFilenames(pattern)

        if not filenames:
            options_logger.warning(
                "No matching data file to be included for '%s'." % pattern)

        for filename in filenames:
            file_reason = "specified data file '%s' on command line" % arg

            if src is None:
                rel_path = dest

                if rel_path.endswith(("/", os.path.sep)):
                    rel_path = os.path.join(rel_path,
                                            os.path.basename(filename))
            else:
                rel_path = os.path.join(dest, relpath(filename, src))

            yield makeIncludedDataFile(filename,
                                       rel_path,
                                       file_reason,
                                       tracer=options_logger,
                                       tags="user")

    for src, dest in getShallIncludeDataDirs():
        filenames = getFileList(src)

        if not filenames:
            options_logger.warning("No files in directory '%s.'" % src)

        for filename in filenames:
            relative_filename = relpath(filename, src)

            file_reason = "specified data dir %r on command line" % src

            rel_path = os.path.join(dest, relative_filename)

            yield makeIncludedDataFile(filename,
                                       rel_path,
                                       file_reason,
                                       tracer=options_logger,
                                       tags="user")
Esempio n. 6
0
    def _consider(self, trace_collection, module_filename, module_package):
        assert module_package is None or \
              (type(module_package) is str and module_package != ""), repr(module_package)

        module_filename = os.path.normpath(module_filename)

        module_name, module_kind = getModuleNameAndKindFromFilename(module_filename)

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

            if decision:
                module_relpath = relpath(module_filename)

                imported_module, added_flag = recurseTo(
                    module_package  = module_package,
                    module_filename = module_filename,
                    module_relpath  = module_relpath,
                    module_kind     = module_kind,
                    reason          = reason
                )

                if added_flag:
                    trace_collection.signalChange(
                        "new_code",
                        imported_module.getSourceReference(),
                        "Recursed to module."
                    )

                return imported_module
            elif decision is None and module_kind == "py":
                if module_package is None:
                    module_fullpath = module_name
                else:
                    module_fullpath = module_package + '.' + module_name

                if module_filename not in self._warned_about and \
                   module_fullpath not in getModuleWhiteList():
                    self._warned_about.add(module_filename)

                    warning(
                        """\
Not recursing to '%(full_path)s' (%(filename)s), please specify \
--recurse-none (do not warn), \
--recurse-all (recurse to all), \
--recurse-not-to=%(full_path)s (ignore it), \
--recurse-to=%(full_path)s (recurse to it) to change.""" % {
                            "full_path" : module_fullpath,
                            "filename"  : module_filename
                        }
                    )
Esempio n. 7
0
    def onUsedModule(self, module_name, module_relpath):
        assert type(module_name) is str, module_name

        # TODO: Make users provide this through a method that has already
        # done this.
        module_relpath = relpath(module_relpath)

        self.used_modules.add((module_name, module_relpath))

        module = getImportedModuleByNameAndPath(module_name, module_relpath)
        addUsedModule(module)
Esempio n. 8
0
    def onUsedModule(self, module_name, module_relpath):
        assert type(module_name) is str, module_name

        # TODO: Make users provide this through a method that has already
        # done this.
        module_relpath = relpath(module_relpath)

        self.used_modules.add((module_name, module_relpath))

        module = getImportedModuleByNameAndPath(module_name, module_relpath)
        addUsedModule(module)
Esempio n. 9
0
def considerFilename(module_filename):
    module_filename = os.path.normpath(module_filename)

    if os.path.isdir(module_filename):
        module_filename = os.path.abspath(module_filename)

        module_name = os.path.basename(module_filename)
        module_relpath = relpath(module_filename)

        return module_filename, module_relpath, module_name
    elif module_filename.endswith(".py"):
        module_name = os.path.basename(module_filename)[:-3]
        module_relpath = relpath(module_filename)

        return module_filename, module_relpath, module_name
    elif module_filename.endswith(".pyw"):
        module_name = os.path.basename(module_filename)[:-4]
        module_relpath = relpath(module_filename)

        return module_filename, module_relpath, module_name
    else:
        return None
Esempio n. 10
0
    def recurseTo(module_package, module_filename, module_kind, reason,
                  signal_change):
        from nuitka.importing import Recursion

        imported_module, added_flag = Recursion.recurseTo(
            module_package=module_package,
            module_filename=module_filename,
            module_relpath=relpath(module_filename),
            module_kind=module_kind,
            reason=reason)

        addUsedModule(imported_module)

        if added_flag:
            signal_change("new_code", imported_module.getSourceReference(),
                          "Recursed to module.")
Esempio n. 11
0
def addImportedModule(imported_module):
    module_filename = relpath(imported_module.getFilename())

    if os.path.basename(module_filename) == "__init__.py":
        module_filename = os.path.dirname(module_filename)

    key = (module_filename, imported_module.getFullName())

    if key in imported_modules:
        assert imported_module is imported_modules[key], key
    else:
        Plugins.onModuleDiscovered(imported_module)

    imported_modules[key] = imported_module
    imported_by_name[imported_module.getFullName()] = imported_module

    # We don't expect that to happen.
    assert not imported_module.isMainModule()
Esempio n. 12
0
def addImportedModule(imported_module):
    module_filename = relpath(imported_module.getFilename())

    if os.path.basename(module_filename) == "__init__.py":
        module_filename = os.path.dirname(module_filename)

    key = (module_filename, imported_module.getFullName())

    if key in imported_modules:
        assert imported_module is imported_modules[key], key
    else:
        Plugins.onModuleDiscovered(imported_module)

    imported_modules[key] = imported_module
    imported_by_name[imported_module.getFullName()] = imported_module

    # We don't expect that to happen.
    assert not imported_module.isMainModule()
Esempio n. 13
0
    def attemptRecursion(self):
        # Make sure the package is recursed to.

        # Return the list of newly added modules.
        result = []

        if self.package_name is not None and self.package is None:
            self.package = getModuleByName(self.package_name)

        if self.package_name is not None and self.package is None:
            package_package, package_filename, finding = findModule(
                importing=self,
                module_name=self.package_name,
                parent_package=None,
                level=1,
                warn=python_version < 300,
            )

            # TODO: Temporary, if we can't find the package for Python3.3 that
            # is semi-OK, maybe.
            if python_version >= 300 and not package_filename:
                return []

            if self.package_name == "uniconvertor.app.modules":
                return []

            assert package_filename is not None, (self.package_name, finding)

            _package_name, package_kind = getModuleNameAndKindFromFilename(
                package_filename
            )
            # assert _package_name == self.package_name, (package_filename, _package_name, self.package_name)

            decision, _reason = decideRecursion(
                module_filename=package_filename,
                module_name=self.package_name,
                module_package=package_package,
                module_kind=package_kind,
            )

            if decision is not None:
                self.package, is_added = recurseTo(
                    module_package=package_package,
                    module_filename=package_filename,
                    module_relpath=relpath(package_filename),
                    module_kind="py",
                    reason="Containing package of recursed module '%s'."
                    % self.getFullName(),
                )

                if is_added:
                    result.append(self.package)

        if self.package:
            from nuitka.ModuleRegistry import addUsedModule

            addUsedModule(self.package)

            #            print "Recursed to package", self.package_name
            result.extend(self.package.attemptRecursion())

        return result
Esempio n. 14
0
def checkPluginSinglePath(plugin_filename, module_package):
    # Many branches, for the decision is very complex, pylint: disable=too-many-branches

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

    module_name, module_kind = Importing.getModuleNameAndKindFromFilename(
        plugin_filename)

    module_name = ModuleName.makeModuleNameInPackage(module_name,
                                                     module_package)

    if module_kind is not None:
        decision, reason = decideRecursion(
            module_filename=plugin_filename,
            module_name=module_name,
            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:
                    recursion_logger.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):
                        recursion_logger.warning(
                            "Duplicate '%s' of '%s' ignored ." % (
                                plugin_filename,
                                module.getFilename(),
                            ))

                        return

                if Options.isShowInclusion():
                    recursion_logger.info("Recursed to '%s' %s" % (
                        module.getFullName(),
                        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 >= 0x300

                        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)

                    if Options.isShowInclusion():
                        recursion_logger.info("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) and not os.path.exists(sub_path +
                                                                 ".py"):
                            checkPluginSinglePath(
                                sub_path, module_package=module.getFullName())
                        elif sub_path.endswith(".py"):
                            checkPluginSinglePath(
                                sub_path, module_package=module.getFullName())

                elif module.isCompiledPythonModule():
                    ModuleRegistry.addRootModule(module)
                elif module.isPythonShlibModule():
                    if Options.isStandaloneMode():
                        ModuleRegistry.addRootModule(module)

            else:
                recursion_logger.warning(
                    "Failed to include module from '%s'." % plugin_filename)
Esempio n. 15
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)
Esempio n. 16
0
    def _consider(self, trace_collection, module_filename, module_package):
        assert module_package is None or (
            type(module_package) is str and module_package != ""
        ), repr(module_package)

        module_filename = os.path.normpath(module_filename)

        module_name, module_kind = getModuleNameAndKindFromFilename(module_filename)

        if module_kind is not None:
            if module_package is None:
                module_fullpath = module_name
            else:
                module_fullpath = module_package + "." + module_name

            decision, reason = decideRecursion(
                module_filename=module_filename,
                module_name=module_name,
                module_package=module_package,
                module_kind=module_kind,
            )

            if decision:
                module_relpath = relpath(module_filename)

                imported_module, added_flag = recurseTo(
                    module_package=module_package,
                    module_filename=module_filename,
                    module_relpath=module_relpath,
                    module_kind=module_kind,
                    reason=reason,
                )

                if added_flag:
                    trace_collection.signalChange(
                        "new_code",
                        imported_module.getSourceReference(),
                        "Recursed to module.",
                    )

                return imported_module
            elif decision is False and module_kind == "py":
                uncompiled_module = getUncompiledModule(
                    module_fullpath, module_filename
                )

                if uncompiled_module is not None:
                    return uncompiled_module
            elif decision is None and module_kind == "py":
                if (
                    module_filename not in self._warned_about
                    and module_fullpath not in getModuleWhiteList()
                ):
                    self._warned_about.add(module_filename)

                    warning(
                        """\
Not recursing to '%(full_path)s' (%(filename)s), please specify \
--nofollow-imports (do not warn), \
--follow-imports (recurse to all), \
--nofollow-import-to=%(full_path)s (ignore it), \
--follow-import-to=%(full_path)s (recurse to it) to change."""
                        % {"full_path": module_fullpath, "filename": module_filename}
                    )
Esempio n. 17
0
def copyDataFiles(dist_dir):
    """Copy the data files needed for standalone distribution.

    Args:
        dist_dir: The distribution folder under creation
    Notes:
        This is for data files only, not DLLs or even extension modules,
        those must be registered as entry points, and would not go through
        necessary handling if provided like this.
    """

    # Many details to deal with, pylint: disable=too-many-branches,too-many-locals

    for pattern, dest, arg in Options.getShallIncludeDataFiles():
        filenames = resolveShellPatternToFilenames(pattern)

        if not filenames:
            inclusion_logger.warning("No match data file to be included: %r" %
                                     pattern)

        for filename in filenames:
            file_reason = "specified data file %r on command line" % arg

            rel_path = dest

            if rel_path.endswith(("/", os.path.sep)):
                rel_path = os.path.join(rel_path, os.path.basename(filename))

            _handleDataFile(
                dist_dir,
                inclusion_logger,
                makeIncludedDataFile(filename, rel_path, file_reason),
            )

    for src, dest in Options.getShallIncludeDataDirs():
        filenames = getFileList(src)

        if not filenames:
            inclusion_logger.warning("No files in directory" % src)

        for filename in filenames:
            relative_filename = relpath(filename, src)

            file_reason = "specified data dir %r on command line" % src

            rel_path = os.path.join(dest, relative_filename)

            _handleDataFile(
                dist_dir,
                inclusion_logger,
                makeIncludedDataFile(filename, rel_path, file_reason),
            )

    # Cyclic dependency
    from nuitka import ModuleRegistry

    for module in ModuleRegistry.getDoneModules():
        for plugin, included_datafile in Plugins.considerDataFiles(module):
            _handleDataFile(dist_dir=dist_dir,
                            tracer=plugin,
                            included_datafile=included_datafile)

    for module in ModuleRegistry.getDoneModules():
        if module.isCompiledPythonPackage(
        ) or module.isUncompiledPythonPackage():
            package_name = module.getFullName()

            match, reason = package_name.matchesToShellPatterns(
                patterns=Options.getShallIncludePackageData())

            if match:
                package_directory = module.getCompileTimeDirectory()

                pkg_filenames = getFileList(
                    package_directory,
                    ignore_dirs=("__pycache__", ),
                    ignore_suffixes=(".py", ".pyw", ".pyc", ".pyo", ".dll") +
                    getSharedLibrarySuffixes(),
                )

                if pkg_filenames:
                    file_reason = "package '%s' %s" % (package_name, reason)

                    for pkg_filename in pkg_filenames:
                        rel_path = os.path.join(
                            package_name.asPath(),
                            os.path.relpath(pkg_filename, package_directory),
                        )

                        _handleDataFile(
                            dist_dir,
                            inclusion_logger,
                            makeIncludedDataFile(pkg_filename, rel_path,
                                                 file_reason),
                        )
Esempio n. 18
0
def parseArgs():
    """Parse the command line arguments

    :meta private:
    """
    # singleton with many cases checking the options right away.
    # pylint: disable=global-statement,too-many-branches,too-many-locals,too-many-statements
    global is_nuitka_run, options, positional_args, extra_args, is_debug, is_nondebug
    global is_fullcompat, is_report_missing, is_verbose

    if os.name == "nt":
        # Windows store Python's don't allow looking at the python, catch that.
        try:
            with openTextFile(sys.executable, "rb"):
                pass
        except OSError:
            Tracing.general.sysexit(
                "Error, the Python from Windows store is not supported, check the User Manual of Nuitka ."
            )

    is_nuitka_run, options, positional_args, extra_args = parseOptions(
        logger=Tracing.options_logger)

    is_debug = _isDebug()
    is_nondebug = not is_debug
    is_fullcompat = _isFullCompat()

    # TODO: Have dedicated option for it.
    is_report_missing = is_debug

    if options.quiet or int(os.environ.get("NUITKA_QUIET", "0")):
        Tracing.setQuiet()

    if not shallDumpBuiltTreeXML():
        Tracing.options_logger.info("Used command line options: %s" %
                                    " ".join(sys.argv[1:]))

    if os.environ.get("NUITKA_REEXECUTION") and not isAllowedToReexecute():
        Tracing.general.sysexit(
            "Error, not allowed to re-execute, but that has happened.")

    if options.progress_bar:
        Progress.enableProgressBar()

    if options.verbose_output:
        Tracing.optimization_logger.setFileHandle(
            # Can only have unbuffered binary IO in Python3, therefore not disabling buffering here.
            openTextFile(options.verbose_output, "w", encoding="utf8"))

        options.verbose = True

    is_verbose = options.verbose

    Tracing.optimization_logger.is_quiet = not options.verbose

    if options.show_inclusion_output:
        Tracing.inclusion_logger.setFileHandle(
            # Can only have unbuffered binary IO in Python3, therefore not disabling buffering here.
            openTextFile(options.show_inclusion_output, "w", encoding="utf8"))

        options.show_inclusion = True

    Tracing.progress_logger.is_quiet = not options.show_progress

    # Onefile implies standalone build.
    if options.is_onefile:
        options.is_standalone = True

    # Standalone implies no_site build
    if options.is_standalone:
        options.python_flags.insert(0, "no_site")

    # Provide a tempdir spec implies onefile tempdir, even on Linux.
    if options.onefile_tempdir_spec:
        options.is_onefile_tempdir = True

        if os.path.normpath(options.onefile_tempdir_spec) == ".":
            Tracing.options_logger.sysexit("""\
Error, using '.' as a value for '--onefile-tempdir-spec' is not supported,
you cannot unpack the onefile payload into the same directory as the binary,
as that would overwrite it and cause locking issues as well.""")

        if options.onefile_tempdir_spec.count("%") % 2 != 0:
            Tracing.options_logger.warning(
                """Unmatched '%%' is suspicious for '--onefile-tempdir-spec' and may
not do what you want it to do: '%s'""" % options.onefile_tempdir_spec)

        if options.onefile_tempdir_spec.count("%") == 0:
            Tracing.options_logger.warning(
                """Not using any variables for '--onefile-tempdir-spec' should only be
done if your program absolutely needs to be in the same path always: '%s'""" %
                options.onefile_tempdir_spec)

        if os.path.isabs(options.onefile_tempdir_spec):
            Tracing.options_logger.warning(
                """Using an absolute path should be avoided unless you are targeting a
very well known environment: '%s'""" % options.onefile_tempdir_spec)
        elif relpath(options.onefile_tempdir_spec):
            Tracing.options_logger.warning(
                """Using an relative path above the executable should be avoided unless you are targeting a
very well known environment: '%s'""" % options.onefile_tempdir_spec)

    # Standalone mode implies an executable, not importing "site" module, which is
    # only for this machine, recursing to all modules, and even including the
    # standard library.
    if options.is_standalone:
        if options.module_mode:
            Tracing.options_logger.sysexit("""\
Error, conflicting options, cannot make standalone module, only executable.

Modules are supposed to be imported to an existing Python installation, therefore it
makes no sense to include a Python runtime.""")

    for any_case_module in getShallFollowModules():
        if any_case_module.startswith("."):
            bad = True
        else:
            for char in "/\\:":
                if char in any_case_module:
                    bad = True
                    break
            else:
                bad = False

        if bad:
            Tracing.options_logger.sysexit("""\
Error, '--follow-import-to' takes only module names or patterns, not directory path '%s'."""
                                           % any_case_module)

    for no_case_module in getShallFollowInNoCase():
        if no_case_module.startswith("."):
            bad = True
        else:
            for char in "/\\:":
                if char in no_case_module:
                    bad = True
                    break
            else:
                bad = False

        if bad:
            Tracing.options_logger.sysexit("""\
Error, '--nofollow-import-to' takes only module names or patterns, not directory path '%s'."""
                                           % no_case_module)

    scons_python = getPythonPathForScons()

    if scons_python is not None and not os.path.isfile(scons_python):
        Tracing.options_logger.sysexit(
            "Error, no such Python binary %r, should be full path." %
            scons_python)

    if options.output_filename is not None and (
        (isStandaloneMode() and not isOnefileMode()) or shallMakeModule()):
        Tracing.options_logger.sysexit("""\
Error, may only specify output filename for acceleration and onefile mode,
but not for module mode where filenames are mandatory, and not for
standalone where there is a sane default used inside the dist folder.""")

    if isLinux():
        if len(getIconPaths()) > 1:
            Tracing.options_logger.sysexit(
                "Error, can only use one icon file on Linux.")

    if isMacOS():
        if len(getIconPaths()) > 1:
            Tracing.options_logger.sysexit(
                "Error, can only use one icon file on macOS.")

    for icon_path in getIconPaths():
        if "#" in icon_path and isWin32Windows():
            icon_path, icon_index = icon_path.rsplit("#", 1)

            if not icon_index.isdigit() or int(icon_index) < 0:
                Tracing.options_logger.sysexit(
                    "Error, icon number in %r not valid." %
                    (icon_path + "#" + icon_index))

        if not os.path.exists(icon_path):
            Tracing.options_logger.sysexit(
                "Error, icon path %r does not exist." % icon_path)

        if getWindowsIconExecutablePath():
            Tracing.options_logger.sysexit(
                "Error, can only use icons from template executable or from icon files, but not both."
            )

    icon_exe_path = getWindowsIconExecutablePath()
    if icon_exe_path is not None and not os.path.exists(icon_exe_path):
        Tracing.options_logger.sysexit("Error, icon path %r does not exist." %
                                       icon_exe_path)

    try:
        file_version = getWindowsFileVersion()
    except Exception:  # Catch all the things, don't want any interface, pylint: disable=broad-except
        Tracing.options_logger.sysexit(
            "Error, file version must be a tuple of up to 4 integer values.")

    try:
        product_version = getWindowsProductVersion()
    except Exception:  # Catch all the things, don't want any interface, pylint: disable=broad-except
        Tracing.options_logger.sysexit(
            "Error, product version must be a tuple of up to 4 integer values."
        )

    if getWindowsCompanyName() == "":
        Tracing.options_logger.sysexit(
            """Error, empty string is not an acceptable company name.""")

    if getWindowsProductName() == "":
        Tracing.options_logger.sysexit(
            """Error, empty string is not an acceptable product name.""")

    splash_screen_filename = getWindowsSplashScreen()

    if splash_screen_filename is not None:
        if not os.path.isfile(splash_screen_filename):
            Tracing.options_logger.sysexit(
                "Error, specified splash screen image '%s' does not exist." %
                splash_screen_filename)

    if file_version or product_version or getWindowsVersionInfoStrings():
        if not (file_version or product_version) and getWindowsCompanyName():
            Tracing.options_logger.sysexit(
                "Error, company name and file or product version need to be given when any version information is given."
            )

    if isOnefileMode() and not hasOnefileSupportedOS():
        Tracing.options_logger.sysexit("Error, unsupported OS for onefile %r" %
                                       getOS())

    if options.follow_none and options.follow_all:
        Tracing.options_logger.sysexit(
            "Conflicting options '--follow-imports' and '--nofollow-imports' given."
        )

    for module_pattern in getShallIncludePackageData():
        if (module_pattern.startswith("-") or "/" in module_pattern
                or "\\" in module_pattern):
            Tracing.options_logger.sysexit(
                "Error, '--include-package-data' needs module name or pattern as an argument, not %r."
                % module_pattern)

    for module_pattern in getShallFollowModules():
        if (module_pattern.startswith("-") or "/" in module_pattern
                or "\\" in module_pattern):
            Tracing.options_logger.sysexit(
                "Error, '--follow-import-to' options needs module name or pattern as an argument, not %r."
                % module_pattern)
    for module_pattern in getShallFollowInNoCase():
        if (module_pattern.startswith("-") or "/" in module_pattern
                or "\\" in module_pattern):
            Tracing.options_logger.sysexit(
                "Error, '--nofollow-import-to' options needs module name or pattern as an argument, not %r."
                % module_pattern)

    for data_file in options.data_files:
        if "=" not in data_file:
            Tracing.options_logger.sysexit(
                "Error, malformed data file description, must specify relative target path separated with '='."
            )

        if data_file.count("=") == 1:
            src, dst = data_file.split("=", 1)

            filenames = resolveShellPatternToFilenames(src)

            if len(filenames) > 1 and not dst.endswith(("/", os.path.sep)):
                Tracing.options_logger.sysexit(
                    "Error, pattern '%s' matches more than one file, but target has no trailing slash, not a directory."
                    % src)
        else:
            src, dst, pattern = data_file.split("=", 2)

            filenames = resolveShellPatternToFilenames(
                os.path.join(src, pattern))

        if not filenames:
            Tracing.options_logger.sysexit(
                "Error, '%s' does not match any files." % src)

        if os.path.isabs(dst):
            Tracing.options_logger.sysexit(
                "Error, must specify relative target path for data file, not absolute path '%s'."
                % data_file)

    for data_dir in options.data_dirs:
        if "=" not in data_dir:
            Tracing.options_logger.sysexit(
                "Error, malformed data dir description, must specify relative target path with '=' separating it."
            )

        src, dst = data_dir.split("=", 1)

        if os.path.isabs(dst):
            Tracing.options_logger.sysexit(
                "Error, must specify relative target path for data dir, not %r as in %r."
                % (dst, data_dir))

        if not os.path.isdir(src):
            Tracing.options_logger.sysexit(
                "Error, must specify existing source data directory, not %r as in %r."
                % (dst, data_dir))

    for pattern in getShallFollowExtraFilePatterns():
        if os.path.isdir(pattern):
            Tracing.options_logger.sysexit(
                "Error, pattern %r given to '--include-plugin-files' cannot be a directory name."
                % pattern)

    if options.static_libpython == "yes" and getSystemStaticLibPythonPath(
    ) is None:
        Tracing.options_logger.sysexit(
            "Error, static libpython is not found or not supported for this Python installation."
        )

    if shallUseStaticLibPython() and getSystemStaticLibPythonPath() is None:
        Tracing.options_logger.sysexit(
            """Error, usable static libpython is not found for this Python installation. You \
might be missing required packages. Disable with --static-libpython=no" if you don't \
want to install it.""")

    if isApplePython():
        if isStandaloneMode():
            Tracing.options_logger.sysexit(
                "Error, for standalone mode, Apple Python from macOS is not supported, use e.g. CPython instead."
            )

        if str is bytes:
            Tracing.options_logger.sysexit(
                "Error, Apple Python 2.7 from macOS is not usable as per Apple decision, use e.g. CPython 2.7 instead."
            )

    if isStandaloneMode() and isLinux(
    ) and getExecutablePath("patchelf") is None:
        Tracing.options_logger.sysexit(
            "Error, standalone mode on Linux requires 'patchelf' to be installed. Use 'apt/dnf/yum install patchelf' first."
        )

    pgo_executable = getPgoExecutable()
    if pgo_executable and not isPathExecutable(pgo_executable):
        Tracing.options_logger.sysexit(
            "Error, path '%s' to binary to use for PGO is not executable." %
            pgo_executable)
Esempio n. 19
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)
Esempio n. 20
0
def copyDllsUsed(source_dir, dist_dir, standalone_entry_points):
    # This is complex, because we also need to handle OS specifics.

    used_dlls = _detectUsedDLLs(
        source_dir=source_dir,
        standalone_entry_points=standalone_entry_points,
        use_cache=not Options.shallNotUseDependsExeCachedResults()
        and Options.getWindowsDependencyTool() != "depends.exe",
        update_cache=not Options.shallNotStoreDependsExeCachedResults()
        and Options.getWindowsDependencyTool() != "depends.exe",
    )

    duplicate_dlls = _removeDuplicateDlls(used_dlls=used_dlls)

    dll_map = _copyDllsUsed(dist_dir=dist_dir, used_dlls=used_dlls)

    # TODO: This belongs inside _copyDllsUsed
    if Utils.isMacOS():
        # For macOS, the binary and the DLLs needs to be changed to reflect
        # the relative DLL location in the ".dist" folder.
        for standalone_entry_point in standalone_entry_points:
            _fixupBinaryDLLPathsMacOS(
                binary_filename=standalone_entry_point.dest_path,
                package_name=standalone_entry_point.package_name,
                dll_map=dll_map,
                duplicate_dlls=duplicate_dlls,
                original_location=standalone_entry_point.source_path,
            )

        for original_path, package_name, dll_filename in dll_map:
            _fixupBinaryDLLPathsMacOS(
                binary_filename=os.path.join(dist_dir, dll_filename),
                package_name=package_name,
                dll_map=dll_map,
                duplicate_dlls=duplicate_dlls,
                original_location=original_path,
            )

    # Remove or update rpath settings.
    if Utils.getOS() == "Linux":
        # For Linux, the "rpath" of libraries may be an issue and must be
        # removed.
        for standalone_entry_point in standalone_entry_points[1:]:
            count = relpath(path=standalone_entry_point.dest_path,
                            start=dist_dir).count(os.path.sep)

            rpath = os.path.join("$ORIGIN", *([".."] * count))
            setSharedLibraryRPATH(standalone_entry_point.dest_path, rpath)

        for _original_path, _package_name, dll_filename in dll_map:
            setSharedLibraryRPATH(os.path.join(dist_dir, dll_filename),
                                  "$ORIGIN")

    if Utils.isMacOS():
        setSharedLibraryRPATH(standalone_entry_points[0].dest_path, "$ORIGIN")

        addMacOSCodeSignature(filenames=[
            standalone_entry_point.dest_path
            for standalone_entry_point in standalone_entry_points
        ] + [
            os.path.join(dist_dir, dll_filename)
            for _original_path, _package_name, dll_filename in dll_map
        ])

    Plugins.onCopiedDLLs(dist_dir=dist_dir, used_dlls=used_dlls)