Exemple #1
0
def optimize():
    while True:
        finished = True
        ModuleRegistry.startTraversal()

        while True:
            current_module = ModuleRegistry.nextModule()

            if current_module is None:
                break

            if _progress:
                printLine(
                    """\
Optimizing module '{module_name}', {remaining:d} more modules to go \
after that. Memory usage {memory}:""".format(
                        module_name = current_module.getFullName(),
                        remaining   = ModuleRegistry.remainingCount(),
                        memory      = Utils.getHumanReadableProcessMemoryUsage()
                    )
                )

            if current_module.isPythonShlibModule():
                optimizeShlibModule(current_module)
            else:
                changed = optimizePythonModule(current_module)

                if changed:
                    finished = False

        if finished:
            break
Exemple #2
0
def _detectedShlibFile(filename, module_name):
    # That is not a shared library, but looks like one.
    if module_name == "__main__":
        return

    from nuitka import ModuleRegistry
    if ModuleRegistry.hasRootModule(module_name):
        return

    parts = module_name.split('.')
    if len(parts) == 1:
        package_name = None
        name = module_name
    else:
        package_name = '.'.join(parts[:-1])
        name = parts[-1]

    source_ref = SourceCodeReferences.fromFilename(
        filename = filename
    )

    shlib_module = PythonShlibModule(
        name         = name,
        package_name = package_name,
        source_ref   = source_ref
    )

    ModuleRegistry.addRootModule(shlib_module)
    ImportCache.addImportedModule(shlib_module)

    module_names.add(module_name)
Exemple #3
0
def _detectedShlibFile(filename, module_name):
    if Utils.python_version >= 300:
        filename = filename.decode("utf-8")

    # That is not a shared library, but looks like one.
    if module_name == "__main__":
        return

    parts = module_name.split('.')
    if len(parts) == 1:
        package_name = None
        name = module_name
    else:
        package_name = '.'.join(parts[:-1])
        name = parts[-1]

    source_ref = SourceCodeReferences.fromFilename(
        filename = filename
    )

    shlib_module = PythonShlibModule(
        name         = name,
        package_name = package_name,
        source_ref   = source_ref
    )

    from nuitka import ModuleRegistry
    ModuleRegistry.addRootModule(shlib_module)

    module_names.add(module_name)
Exemple #4
0
def _detectedShlibFile(filename, module_name, result):
    if Utils.python_version >= 300:
        filename = filename.decode("utf-8")

    parts = module_name.split(".")
    if len(parts) == 1:
        package_name = None
        name = module_name
    else:
        package_name = ".".join(parts[:-1])
        name = parts[-1]

    from nuitka.nodes.FutureSpecs import FutureSpec
    from nuitka.nodes.ModuleNodes import PythonShlibModule
    from nuitka import SourceCodeReferences

    source_ref = SourceCodeReferences.fromFilename(
        filename    = filename,
        future_spec = FutureSpec()
    )

    shlib_module = PythonShlibModule(
        package_name = package_name,
        name         = name,
        source_ref   = source_ref
    )

    from nuitka import ModuleRegistry
    ModuleRegistry.addRootModule(shlib_module)

    module_names.add(module_name)
Exemple #5
0
def makeOptimizationPass(initial_pass):
    """ Make a single pass for optimization, indication potential completion.

    """
    finished = True

    ModuleRegistry.startTraversal()

    if _progress:
        if initial_pass:
            printLine("Initial optimization pass.")
        else:
            printLine("Next global optimization pass.")

    while True:
        current_module = ModuleRegistry.nextModule()

        if current_module is None:
            break

        if _progress:
            _traceProgress(current_module)

        # The tag set is global, so it can react to changes without context.
        # pylint: disable=W0603
        global tag_set
        tag_set = TagSet()

        changed = optimizeModule(current_module)

        if changed:
            finished = False

    # Unregister collection traces from now unused code, dropping the trace
    # collections of functions no longer used.
    for current_module in ModuleRegistry.getDoneModules():
        if current_module.isCompiledPythonModule():
            for function in current_module.getUnusedFunctions():
                Variables.updateFromCollection(
                    old_collection = function.trace_collection,
                    new_collection = None
                )

                function.trace_collection = None

    for current_module in ModuleRegistry.getDoneModules():
        optimizeVariables(current_module)

    return finished
Exemple #6
0
def optimize():
    Graphs.startGraph()

    # First pass.
    if _progress:
        info("PASS 1:")

    makeOptimizationPass(False)
    VariableRegistry.considerCompletion()
    finished = makeOptimizationPass(False)

    # Demote to bytecode if now.
    for module in ModuleRegistry.getDoneUserModules():
        if module.isPythonShlibModule():
            continue

        if module.mode == "bytecode":
            demoteCompiledModuleToBytecode(module)

    # Second, endless pass.
    if _progress:
        info("PASS 2..:")

    while not finished:
        finished = makeOptimizationPass(True)

    Graphs.endGraph()
Exemple #7
0
def optimize(output_filename):
    Graphs.startGraph()

    # First pass.
    if _progress:
        info("PASS 1:")

    makeOptimizationPass(initial_pass=True)
    Variables.complete = True

    finished = makeOptimizationPass(initial_pass=False)

    if Options.isExperimental("check_xml_persistence"):
        _checkXMLPersistence()

    # Demote compiled modules to bytecode, now that imports had a chance to be resolved, and
    # dependencies were handled.
    for module in ModuleRegistry.getDoneUserModules():
        if module.isCompiledPythonModule() and module.mode == "bytecode":
            demoteCompiledModuleToBytecode(module)

    if _progress:
        info("PASS 2 ... :")

    # Second, "endless" pass.
    while not finished:
        finished = makeOptimizationPass(initial_pass=False)

    Graphs.endGraph(output_filename)
Exemple #8
0
def optimizeUncompiledPythonModule(module):
    if _progress:
        printLine(
            "Doing module dependency considerations for '{module_name}':".format(
                module_name = module.getFullName()
            )
        )

    for used_module_name in module.getUsedModules():
        used_module = ImportCache.getImportedModuleByName(used_module_name)
        ModuleRegistry.addUsedModule(used_module)

    package_name = module.getPackage()

    if package_name is not None:
        used_module = ImportCache.getImportedModuleByName(package_name)
        ModuleRegistry.addUsedModule(used_module)
Exemple #9
0
def optimizeUncompiledPythonModule(module):
    if _progress:
        info(
            "Doing module dependency considerations for '{module_name}':".format(
                module_name=module.getFullName()
            )
        )

    for used_module_name, used_module_path in module.getUsedModules():
        used_module = ImportCache.getImportedModuleByNameAndPath(
            used_module_name, used_module_path
        )
        ModuleRegistry.addUsedModule(used_module)

    package_name = module.getPackage()

    if package_name is not None:
        used_module = ImportCache.getImportedModuleByName(package_name)
        ModuleRegistry.addUsedModule(used_module)

    Plugins.considerImplicitImports(module=module, signal_change=signalChange)
Exemple #10
0
def _traceProgress(current_module):
    output = """\
Optimizing module '{module_name}', {remaining:d} more modules to go \
after that.""".format(
            module_name = current_module.getFullName(),
            remaining   = ModuleRegistry.remainingCount(),
    )

    if Options.isShowMemory():
        output += "Memory usage {memory}:".format(
            memory = MemoryUsage.getHumanReadableProcessMemoryUsage()
        )

    printLine(output)
Exemple #11
0
def _checkXMLPersistence():
    new_roots = ModuleRegistry.root_modules.__class__()  # @UndefinedVariable

    for module in tuple(ModuleRegistry.getDoneModules()):
        ModuleRegistry.root_modules.remove(module)

        if module.isPythonShlibModule():
            continue

        text = module.asXmlText()
        with open("out.xml", "w") as f:
            f.write(text)
        restored = restoreFromXML(text)
        retext = restored.asXmlText()
        with open("out2.xml", "w") as f:
            f.write(retext)

        assert module.getOutputFilename() == restored.getOutputFilename(), (
            module.getOutputFilename(),
            restored.getOutputFilename(),
        )

        # The variable versions give diffs.
        if True:  # To manually enable, pylint: disable=W0125
            import difflib

            diff = difflib.unified_diff(
                text.splitlines(), retext.splitlines(), "xml orig", "xml reloaded"
            )
            for line in diff:
                printLine(line)

        new_roots.add(restored)

    ModuleRegistry.root_modules = new_roots
    ModuleRegistry.startTraversal()
Exemple #12
0
def optimize():
    # This is somewhat complex with many cases, pylint: disable=R0912

    while True:
        finished = True

        ModuleRegistry.startTraversal()

        while True:
            current_module = ModuleRegistry.nextModule()

            if current_module is None:
                break

            if _progress:
                printLine(
                    """\
Optimizing module '{module_name}', {remaining:d} more modules to go \
after that. Memory usage {memory}:""".format(
                        module_name = current_module.getFullName(),
                        remaining   = ModuleRegistry.remainingCount(),
                        memory      = Utils.getHumanReadableProcessMemoryUsage()
                    )
                )

            if current_module.isPythonShlibModule():
                optimizeShlibModule(current_module)
            else:
                changed = optimizePythonModule(current_module)

                if changed:
                    finished = False

        # Unregister collection traces from now unused code.
        for current_module in ModuleRegistry.getDoneModules():
            if not current_module.isPythonShlibModule():
                for function in current_module.getUnusedFunctions():
                    VariableRegistry.updateFromCollection(
                        old_collection = function.constraint_collection,
                        new_collection = None
                    )

                    function.constraint_collection = None

        if not VariableRegistry.complete:
            VariableRegistry.complete = True

            finished = False

        for current_module in ModuleRegistry.getDoneModules():
            if not current_module.isPythonShlibModule():
                optimizeVariables(current_module)

        if finished:
            break
Exemple #13
0
def makeOptimizationPass(initial_pass):
    """ Make a single pass for optimization, indication potential completion.

    """
    # Controls complex optimization, pylint: disable=too-many-branches

    finished = True

    ModuleRegistry.startTraversal()

    if _progress:
        if initial_pass:
            info("Initial optimization pass.")
        else:
            info("Next global optimization pass.")

    while True:
        current_module = ModuleRegistry.nextModule()

        if current_module is None:
            break

        if _progress:
            _traceProgress(current_module)

        # The tag set is global, so it can react to changes without context.
        # pylint: disable=global-statement
        global tag_set
        tag_set = TagSet()

        changed = optimizeModule(current_module)

        if changed:
            finished = False

    # Unregister collection traces from now unused code, dropping the trace
    # collections of functions no longer used.
    for current_module in ModuleRegistry.getDoneModules():
        if current_module.isCompiledPythonModule():
            for function in current_module.getUnusedFunctions():
                Variables.updateVariablesFromCollection(
                    old_collection=function.trace_collection, new_collection=None
                )

                function.trace_collection = None

    for current_module in ModuleRegistry.getDoneModules():
        if current_module.isCompiledPythonModule():
            if optimizeVariables(current_module):
                finished = False

            used_functions = current_module.getUsedFunctions()

            for unused_function in current_module.getUnusedFunctions():
                unused_function.trace_collection = None

            used_functions = tuple(
                function
                for function in current_module.getFunctions()
                if function in used_functions
            )

            current_module.setFunctions(used_functions)

    if Variables.complete:
        if optimizeLocalsDictsHandles():
            finished = False

    return finished
Exemple #14
0
def optimize():
    # This is somewhat complex with many cases, pylint: disable=R0912

    # We maintain this globally to make it accessible, pylint: disable=W0603
    global graph

    if Options.shouldCreateGraph():

        try:
            from graphviz import Digraph  # pylint: disable=F0401,I0021
            graph = Digraph('G')
        except ImportError:
            warning("Cannot import graphviz module, no graphing capability.")

    while True:
        finished = True

        ModuleRegistry.startTraversal()

        while True:
            current_module = ModuleRegistry.nextModule()

            if current_module is None:
                break

            if _progress:
                printLine("""\
Optimizing module '{module_name}', {remaining:d} more modules to go \
after that. Memory usage {memory}:""".format(
                    module_name=current_module.getFullName(),
                    remaining=ModuleRegistry.remainingCount(),
                    memory=Utils.getHumanReadableProcessMemoryUsage()))

            if current_module.isPythonShlibModule():
                optimizeShlibModule(current_module)
            else:
                changed = optimizePythonModule(current_module)

                if changed:
                    finished = False

        # Unregister collection traces from now unused code.
        for current_module in ModuleRegistry.getDoneModules():
            if not current_module.isPythonShlibModule():
                for function in current_module.getUnusedFunctions():
                    VariableRegistry.updateFromCollection(
                        old_collection=function.constraint_collection,
                        new_collection=None)

                    function.constraint_collection = None

        if not VariableRegistry.complete:
            VariableRegistry.complete = True

            finished = False

        for current_module in ModuleRegistry.getDoneModules():
            if not current_module.isPythonShlibModule():
                optimizeVariables(current_module)

        if finished:
            break

    if graph is not None:
        graph.engine = "dot"
        graph.graph_attr["rankdir"] = "TB"
        graph.render("something.dot")

        printLine(graph.source)
Exemple #15
0
def optimize():
    # This is somewhat complex with many cases, pylint: disable=R0912

    # We maintain this globally to make it accessible, pylint: disable=W0603
    global graph

    if Options.shouldCreateGraph():

        try:
            from graphviz import Digraph # pylint: disable=F0401,I0021
            graph = Digraph('G')
        except ImportError:
            warning("Cannot import graphviz module, no graphing capability.")

    while True:
        finished = True

        ModuleRegistry.startTraversal()

        while True:
            current_module = ModuleRegistry.nextModule()

            if current_module is None:
                break

            if _progress:
                printLine(
                    """\
Optimizing module '{module_name}', {remaining:d} more modules to go \
after that. Memory usage {memory}:""".format(
                        module_name = current_module.getFullName(),
                        remaining   = ModuleRegistry.remainingCount(),
                        memory      = MemoryUsage.getHumanReadableProcessMemoryUsage()
                    )
                )

            if current_module.isPythonShlibModule():
                optimizeShlibModule(current_module)
            else:
                changed = optimizePythonModule(current_module)

                if changed:
                    finished = False

        # Unregister collection traces from now unused code.
        for current_module in ModuleRegistry.getDoneModules():
            if not current_module.isPythonShlibModule():
                for function in current_module.getUnusedFunctions():
                    VariableRegistry.updateFromCollection(
                        old_collection = function.constraint_collection,
                        new_collection = None
                    )

                    function.constraint_collection = None

        if VariableRegistry.considerCompletion():
            finished = False

        for current_module in ModuleRegistry.getDoneModules():
            if not current_module.isPythonShlibModule():
                optimizeVariables(current_module)

        if finished:
            break


    if graph is not None:
        graph.engine = "dot"
        graph.graph_attr["rankdir"] = "TB"
        graph.render("something.dot")

        printLine(graph.source)
Exemple #16
0
def makeOptimizationPass(initial_pass):
    """ Make a single pass for optimization, indication potential completion.

    """
    # Controls complex optimization, pylint: disable=too-many-branches

    finished = True

    ModuleRegistry.startTraversal()

    if _progress:
        if initial_pass:
            info("Initial optimization pass.")
        else:
            info("Next global optimization pass.")

    while True:
        current_module = ModuleRegistry.nextModule()

        if current_module is None:
            break

        if _progress:
            _traceProgress(current_module)

        # The tag set is global, so it can react to changes without context.
        # pylint: disable=global-statement
        global tag_set
        tag_set = TagSet()

        changed = optimizeModule(current_module)

        if changed:
            finished = False

    # Unregister collection traces from now unused code, dropping the trace
    # collections of functions no longer used.
    for current_module in ModuleRegistry.getDoneModules():
        if current_module.isCompiledPythonModule():
            for function in current_module.getUnusedFunctions():
                Variables.updateVariablesFromCollection(
                    old_collection = function.trace_collection,
                    new_collection = None
                )

                function.trace_collection = None

    for current_module in ModuleRegistry.getDoneModules():
        if current_module.isCompiledPythonModule():
            if optimizeVariables(current_module):
                finished = False

            used_functions = current_module.getUsedFunctions()

            for unused_function in current_module.getUnusedFunctions():
                unused_function.trace_collection = None

            used_functions = tuple(
                function
                for function in
                current_module.getFunctions()
                if function in used_functions
            )

            current_module.setFunctions(used_functions)

    return finished
Exemple #17
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 #18
0
def recurseTo(module_package, module_filename, module_relpath, module_kind,
             reason):
    from nuitka.tree import Building
    from nuitka.nodes.ModuleNodes import makeUncompiledPythonModule

    if not ImportCache.isImportedModuleByPath(module_relpath):
        module, source_ref, source_filename = Building.decideModuleTree(
            filename = module_filename,
            package  = module_package,
            is_top   = False,
            is_main  = False,
            is_shlib = module_kind == "shlib"
        )

        # Check if the module name is known. In order to avoid duplicates,
        # learn the new filename, and continue build if its not.
        if not ImportCache.isImportedModuleByName(module.getFullName()):
            debug(
                "Recurse to import '%s' from %s. (%s)",
                module.getFullName(),
                module_relpath,
                reason
            )

            if module_kind == "py" and source_filename is not None:
                try:
                    Building.createModuleTree(
                        module      = module,
                        source_ref  = source_ref,
                        source_code = readSourceCodeFromFilename(
                            module_name     = module.getFullName(),
                            source_filename = source_filename
                        ),
                        is_main     = False
                    )
                except (SyntaxError, IndentationError) as e:
                    if module_filename not in Importing.warned_about:
                        Importing.warned_about.add(module_filename)

                        warning(
                            """\
Cannot recurse to import module '%s' (%s) because of '%s'""",
                            module_relpath,
                            module_filename,
                            e.__class__.__name__
                        )

                    return None, False
                except Building.CodeTooComplexCode:
                    if module_filename not in Importing.warned_about:
                        Importing.warned_about.add(module_filename)

                        warning(
                            """\
Cannot recurse to import module '%s' (%s) because code is too complex.""",
                            module_relpath,
                            module_filename,
                        )


                        if Options.isStandaloneMode():
                            module = makeUncompiledPythonModule(
                                module_name   = module.getFullName(),
                                filename      = module_filename,
                                bytecode      = marshal.dumps(
                                    compile(
                                        readSourceCodeFromFilename(module.getFullName(), module_filename),
                                        module_filename,
                                        "exec"
                                    )
                                ),
                                is_package    = module.isCompiledPythonPackage(),
                                user_provided = True,
                                technical     = False
                            )

                            ModuleRegistry.addUncompiledModule(module)

                    return None, False

            ImportCache.addImportedModule(module)

            is_added = True
        else:
            module = ImportCache.getImportedModuleByName(
                module.getFullName()
            )

            is_added = False

        assert not module_relpath.endswith("/__init__.py"), module

        return module, is_added
    else:
        return ImportCache.getImportedModuleByPath(module_relpath), False
Exemple #19
0
def _recurseTo(module_package, module_filename, module_relpath, module_kind,
              reason):
    from nuitka.tree import Building
    from nuitka.nodes.ModuleNodes import makeUncompiledPythonModule

    module, source_ref, source_filename = Building.decideModuleTree(
        filename = module_filename,
        package  = module_package,
        is_top   = False,
        is_main  = False,
        is_shlib = module_kind == "shlib"
    )

    # Check if the module name is known. In order to avoid duplicates,
    # learn the new filename, and continue build if its not.
    if not ImportCache.isImportedModuleByName(module.getFullName()):
        logRecursion(
            "Recurse to import '%s' from '%s'. (%s)",
            module.getFullName(),
            module_relpath,
            reason
        )

        if module_kind == "py" and source_filename is not None:
            try:
                source_code = readSourceCodeFromFilename(
                    module_name     = module.getFullName(),
                    source_filename = source_filename
                )

                Building.createModuleTree(
                    module      = module,
                    source_ref  = source_ref,
                    source_code = source_code,
                    is_main     = False
                )
            except (SyntaxError, IndentationError) as e:
                if module_filename not in Importing.warned_about:
                    Importing.warned_about.add(module_filename)

                    warning(
                        """\
Cannot recurse to import module '%s' (%s) because of '%s'""",
                        module_relpath,
                        module_filename,
                        e.__class__.__name__
                    )

                return None, False
            except Building.CodeTooComplexCode:
                if module_filename not in Importing.warned_about:
                    Importing.warned_about.add(module_filename)

                    warning(
                        """\
Cannot recurse to import module '%s' (%s) because code is too complex.""",
                        module_relpath,
                        module_filename,
                    )

                    if Options.isStandaloneMode():
                        module = makeUncompiledPythonModule(
                            module_name   = module.getFullName(),
                            filename      = module_filename,
                            bytecode      = marshal.dumps(
                                compile(
                                    source_code,
                                    module_filename,
                                    "exec"
                                )
                            ),
                            is_package    = module.isCompiledPythonPackage(),
                            user_provided = True,
                            technical     = False
                        )

                        ModuleRegistry.addUncompiledModule(module)

                return None, False

        ImportCache.addImportedModule(module)

        is_added = True
    else:
        module = ImportCache.getImportedModuleByName(
            module.getFullName()
        )

        is_added = False

    return module, is_added
Exemple #20
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
        )

        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          = "Lives in plug-in directory."
            )

            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 ignored '%s'.",
                            plugin_filename
                        )

                        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 #21
0
def _recurseTo(module_package, module_filename, module_relpath, module_kind,
               reason):
    from nuitka.nodes.ModuleNodes import makeUncompiledPythonModule
    from nuitka.tree import Building

    module, source_ref, source_code = Building.decideModuleTree(
        filename=module_filename,
        package=module_package,
        is_top=False,
        is_main=False,
        is_shlib=module_kind == "shlib",
    )

    if Options.isShowInclusion():
        recursion_logger.info("Recurse to import '%s' from '%s'. (%s)" %
                              (module.getFullName(), module_relpath, reason))

    if source_code is not None:
        try:
            Building.createModuleTree(
                module=module,
                source_ref=source_ref,
                source_code=source_code,
                is_main=False,
            )
        except (SyntaxError, IndentationError) as e:
            if module_filename not in Importing.warned_about:
                Importing.warned_about.add(module_filename)

                recursion_logger.warning(
                    """\
Cannot follow import to module %r (%r) because of %r""" %
                    (module_relpath, module_filename, e.__class__.__name__))

            return None, False
        except Building.CodeTooComplexCode:
            if module_filename not in Importing.warned_about:
                Importing.warned_about.add(module_filename)

                recursion_logger.warning("""\
Cannot recurse to import module %r (%r) because code is too complex.""" % (
                    module_relpath,
                    module_filename,
                ))

                if Options.isStandaloneMode():
                    module = makeUncompiledPythonModule(
                        module_name=module.getFullName(),
                        filename=module_filename,
                        bytecode=marshal.dumps(
                            compile(source_code,
                                    module_filename,
                                    "exec",
                                    dont_inherit=True)),
                        is_package=module.isCompiledPythonPackage(),
                        user_provided=True,
                        technical=False,
                    )

                    ModuleRegistry.addUncompiledModule(module)

            return None, False

    ImportCache.addImportedModule(module)

    return module, True
Exemple #22
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)
Exemple #23
0
def _recurseTo(module_package, module_filename, module_relpath, module_kind, reason):
    from nuitka.tree import Building
    from nuitka.nodes.ModuleNodes import makeUncompiledPythonModule

    module, source_ref, source_filename = Building.decideModuleTree(
        filename=module_filename,
        package=module_package,
        is_top=False,
        is_main=False,
        is_shlib=module_kind == "shlib",
    )

    logRecursion(
        "Recurse to import '%s' from '%s'. (%s)",
        module.getFullName(),
        module_relpath,
        reason,
    )

    if module_kind == "py" and source_filename is not None:
        try:
            source_code = readSourceCodeFromFilename(
                module_name=module.getFullName(), source_filename=source_filename
            )

            Building.createModuleTree(
                module=module,
                source_ref=source_ref,
                source_code=source_code,
                is_main=False,
            )
        except (SyntaxError, IndentationError) as e:
            if module_filename not in Importing.warned_about:
                Importing.warned_about.add(module_filename)

                warning(
                    """\
Cannot recurse to import module '%s' (%s) because of '%s'""",
                    module_relpath,
                    module_filename,
                    e.__class__.__name__,
                )

            return None, False
        except Building.CodeTooComplexCode:
            if module_filename not in Importing.warned_about:
                Importing.warned_about.add(module_filename)

                warning(
                    """\
Cannot recurse to import module '%s' (%s) because code is too complex.""",
                    module_relpath,
                    module_filename,
                )

                if Options.isStandaloneMode():
                    module = makeUncompiledPythonModule(
                        module_name=module.getFullName(),
                        filename=module_filename,
                        bytecode=marshal.dumps(
                            compile(
                                source_code, module_filename, "exec", dont_inherit=True
                            )
                        ),
                        is_package=module.isCompiledPythonPackage(),
                        user_provided=True,
                        technical=False,
                    )

                    ModuleRegistry.addUncompiledModule(module)

            return None, False

    ImportCache.addImportedModule(module)

    return module, True
Exemple #24
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-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),
            )

    # 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),
                        )
Exemple #25
0
def optimize():
    Graphs.startGraph()

    # First pass.
    if _progress:
        info("PASS 1:")

    makeOptimizationPass(False)
    Variables.complete = True

    finished = makeOptimizationPass(False)

    if Options.isExperimental():
        new_roots = ModuleRegistry.root_modules.__class__()  # @UndefinedVariable

        for module in tuple(ModuleRegistry.getDoneModules()):
            ModuleRegistry.root_modules.remove(module)

            if module.isPythonShlibModule():
                continue

            text = module.asXmlText()
            open("out.xml", 'w').write(text)
            restored = restoreFromXML(text)
            retext = restored.asXmlText()
            open("out2.xml", 'w').write(retext)

            assert module.getOutputFilename() == restored.getOutputFilename(), \
               (module.getOutputFilename(),restored.getOutputFilename())

            # The variable versions give diffs.
            if False: # To manually enable, pylint: disable=W0125
                import difflib
                diff = difflib.unified_diff(
                    text.splitlines(),
                    retext.splitlines(),
                    "xml orig",
                    "xml reloaded"
                )
                for line in diff:
                    printLine(line)

            new_roots.add(restored)

        ModuleRegistry.root_modules = new_roots
        ModuleRegistry.startTraversal()

    # Demote to bytecode, now that imports had a chance to be resolved, and
    # dependencies were handled.
    for module in ModuleRegistry.getDoneUserModules():
        if module.isPythonShlibModule():
            continue

        if module.mode == "bytecode":
            demoteCompiledModuleToBytecode(module)

    if _progress:
        info("PASS 2 ... :")

    # Second, "endless" pass.
    while not finished:
        finished = makeOptimizationPass(True)

    Graphs.endGraph()
Exemple #26
0
def optimize():
    Graphs.startGraph()

    # First pass.
    if _progress:
        info("PASS 1:")

    makeOptimizationPass(False)
    Variables.complete = True

    finished = makeOptimizationPass(False)

    if Options.isExperimental():
        new_roots = ModuleRegistry.root_modules.__class__(
        )  # @UndefinedVariable

        for module in tuple(ModuleRegistry.getDoneModules()):
            ModuleRegistry.root_modules.remove(module)

            if module.isPythonShlibModule():
                continue

            text = module.asXmlText()
            open("out.xml", 'w').write(text)
            restored = restoreFromXML(text)
            retext = restored.asXmlText()
            open("out2.xml", 'w').write(retext)

            assert module.getOutputFilename() == restored.getOutputFilename(), \
               (module.getOutputFilename(),restored.getOutputFilename())

            # The variable versions give diffs.
            if False:  # To manually enable, pylint: disable=W0125
                import difflib
                diff = difflib.unified_diff(text.splitlines(),
                                            retext.splitlines(), "xml orig",
                                            "xml reloaded")
                for line in diff:
                    printLine(line)

            new_roots.add(restored)

        ModuleRegistry.root_modules = new_roots
        ModuleRegistry.startTraversal()

    # Demote to bytecode, now that imports had a chance to be resolved, and
    # dependencies were handled.
    for module in ModuleRegistry.getDoneUserModules():
        if module.isPythonShlibModule():
            continue

        if module.mode == "bytecode":
            demoteCompiledModuleToBytecode(module)

    if _progress:
        info("PASS 2 ... :")

    # Second, "endless" pass.
    while not finished:
        finished = makeOptimizationPass(True)

    Graphs.endGraph()
Exemple #27
0
def buildModule(
    module_name,
    module_filename,
    source_code,
    is_top,
    is_main,
    is_extension,
    is_fake,
    hide_syntax_error,
):
    # Many details to deal with, pylint: disable=too-many-branches,too-many-locals
    (
        main_added,
        is_package,
        is_namespace,
        source_ref,
        source_filename,
    ) = Importing.decideModuleSourceRef(
        filename=module_filename,
        module_name=module_name,
        is_main=is_main,
        is_fake=is_fake,
        logger=general,
    )

    if Options.hasPythonFlagPackageMode():
        if is_top and Options.shallMakeModule():
            optimization_logger.warning(
                "Python flag -m (package_mode) has no effect in module mode, it's only for executables."
            )
        elif is_main and not main_added:
            optimization_logger.warning(
                "Python flag -m (package_mode) only works on packages with '__main__.py'."
            )

    # Read source code if necessary. Might give a SyntaxError due to not being proper
    # encoded source.
    if source_filename is not None and not is_namespace and not is_extension:
        try:
            # For fake modules, source is provided directly.
            if source_code is None:
                source_code = readSourceCodeFromFilename(
                    module_name=module_name, source_filename=source_filename)
        except SyntaxError as e:
            # Avoid hiding our own syntax errors.
            if not hasattr(e, "generated_by_nuitka"):
                raise

            # Do not hide SyntaxError in main module.
            if not hide_syntax_error:
                raise

            module = _makeModuleBodyFromSyntaxError(
                exc=e,
                module_name=module_name,
                module_filename=module_filename)
            return module, True

        try:
            ast_tree = parseSourceCodeToAst(
                source_code=source_code,
                module_name=module_name,
                filename=source_filename,
                line_offset=0,
            )
        except (SyntaxError, IndentationError) as e:
            # Do not hide SyntaxError if asked not to.
            if not hide_syntax_error:
                raise

            module = _makeModuleBodyFromSyntaxError(
                exc=e,
                module_name=module_name,
                module_filename=module_filename)
            return module, True
        except CodeTooComplexCode:
            # Do not hide CodeTooComplexCode in main module.
            if is_main:
                raise

            module = _makeModuleBodyTooComplex(
                module_name=module_name,
                module_filename=module_filename,
                source_code=source_code,
                is_package=is_package,
            )
            return module, False
    else:
        ast_tree = None
        source_code = None

    module = _createModule(
        module_name=module_name,
        source_code=source_code,
        source_ref=source_ref,
        is_top=is_top,
        is_main=is_main,
        is_extension=is_extension,
        is_namespace=is_namespace,
        is_package=is_package,
        main_added=main_added,
    )

    if is_top:
        ModuleRegistry.addRootModule(module)

        OutputDirectories.setMainModule(module)

    if module.isCompiledPythonModule() and source_code is not None:
        createModuleTree(
            module=module,
            source_ref=source_ref,
            ast_tree=ast_tree,
            is_main=is_main,
        )

    return module, True
Exemple #28
0
def checkPluginSinglePath(plugin_filename, module_package):
    # Many branches, for the decision is very complex, pylint: disable=too-many-branches

    # The importing wants these to be unique.
    plugin_filename = os.path.abspath(plugin_filename)

    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 == "extension" and not Options.isStandaloneMode():
        recursion_logger.warning(
            "Cannot include '%s' unless using at least standalone mode." %
            module_name.asString())

    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 = recurseTo(
                signal_change=None,
                module_filename=plugin_filename,
                module_name=module_name,
                module_kind=module_kind,
                reason=reason,
            )

            if module:
                if Options.isShowInclusion():
                    recursion_logger.info("Included '%s' as '%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.isPythonExtensionModule():
                    if Options.isStandaloneMode():
                        ModuleRegistry.addRootModule(module)

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

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

    plugin_info = considerFilename(module_package=module_package,
                                   module_filename=plugin_filename)

    if plugin_info is not None:
        module, is_added = recurseTo(module_filename=plugin_info[0],
                                     module_relpath=plugin_info[1],
                                     module_package=module_package,
                                     module_kind="py",
                                     reason="Lives in plug-in directory.")

        if module:
            if not is_added:
                warning("Recursed to %s '%s' at '%s' twice.",
                        "package" if module.isPythonPackage() else "module",
                        module.getName(), plugin_info[0])

                if not isSameModulePath(module.getFilename(), plugin_info[0]):
                    warning("Duplicate ignored '%s'.", plugin_info[1])

                    return

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

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

                if Utils.isDir(package_filename):
                    # Must be a namespace package.
                    assert Utils.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.
                    useful = False
                else:
                    package_dir = Utils.dirname(package_filename)

                    # Real packages will always be included.
                    useful = True

                debug("Package directory %s", package_dir)

                for sub_path, sub_filename in Utils.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())
            else:
                # Modules should always be included.
                useful = True

            if useful:
                ModuleRegistry.addRootModule(module)

        else:
            warning("Failed to include module from '%s'.", plugin_info[0])
Exemple #30
0
def detectEarlyImports():
    # Cyclic dependency
    from nuitka import ModuleRegistry

    for module in _detectEarlyImports():
        ModuleRegistry.addUncompiledModule(module)
Exemple #31
0
def _checkPluginPath(plugin_filename, module_package):
    # Many branches, for the decision is very complex, pylint: disable=R0912

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

    plugin_info = considerFilename(
        module_package  = module_package,
        module_filename = plugin_filename
    )

    if plugin_info is not None:
        module, is_added = recurseTo(
            module_filename = plugin_info[0],
            module_relpath  = plugin_info[1],
            module_package  = module_package,
            module_kind     = "py",
            reason          = "Lives in plug-in directory."
        )

        if module:
            if not is_added:
                warning(
                    "Recursed to %s '%s' at '%s' twice.",
                    "package" if module.isPythonPackage() else "module",
                    module.getName(),
                    plugin_info[0]
                )

                if not isSameModulePath(module.getFilename(), plugin_info[0]):
                    warning(
                        "Duplicate ignored '%s'.",
                        plugin_info[1]
                    )

                    return

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

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

                if Utils.isDir(package_filename):
                    # Must be a namespace package.
                    assert Utils.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.
                    useful = False
                else:
                    package_dir = Utils.dirname(package_filename)

                    # Real packages will always be included.
                    useful = True

                debug(
                    "Package directory %s",
                    package_dir
                )


                for sub_path, sub_filename in Utils.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())
            else:
                # Modules should always be included.
                useful = True

            if useful:
                ModuleRegistry.addRootModule(module)

        else:
            warning("Failed to include module from '%s'.", plugin_info[0])
Exemple #32
0
def makeOptimizationPass():
    """Make a single pass for optimization, indication potential completion."""

    # Controls complex optimization

    finished = True

    ModuleRegistry.startTraversal()

    while True:
        current_module = ModuleRegistry.nextModule()

        if current_module is None:
            break

        _traceProgress(current_module)

        # The tag set is global, so it can react to changes without context.
        # pylint: disable=global-statement
        global tag_set
        tag_set = TagSet()

        changed = optimizeModule(current_module)

        if changed:
            finished = False

    # Unregister collection traces from now unused code, dropping the trace
    # collections of functions no longer used.
    for current_module in ModuleRegistry.getDoneModules():
        if current_module.isCompiledPythonModule():
            for unused_function in current_module.getUnusedFunctions():
                Variables.updateVariablesFromCollection(
                    old_collection=unused_function.trace_collection,
                    new_collection=None,
                    source_ref=unused_function.getSourceReference(),
                )

                unused_function.trace_collection = None

    for current_module in ModuleRegistry.getDoneModules():
        if current_module.isCompiledPythonModule():
            if optimizeVariables(current_module):
                finished = False

            used_functions = current_module.getUsedFunctions()

            for unused_function in current_module.getUnusedFunctions():
                unused_function.trace_collection = None

            used_functions = tuple(
                function for function in current_module.subnode_functions
                if function in used_functions)

            current_module.setChild("functions", used_functions)

    if Variables.complete:
        if optimizeLocalsDictsHandles():
            finished = False

    return finished