Example #1
0
    def __init__(self, name, package_name, source_ref):
        ClosureGiverNodeBase.__init__(
            self,
            name        = name,
            code_prefix = "module",
            source_ref  = source_ref
        )

        PythonModuleMixin.__init__(
            self,
            name         = name,
            package_name = package_name
        )


        ChildrenHavingMixin.__init__(
            self,
            values = {
                "body" : None # delayed
            },
        )

        self.variables = set()

        # The list functions contained in that module.
        self.functions = OrderedSet()

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # SSA trace based information about the module.
        self.constraint_collection = None
Example #2
0
    def __init__(self, name, package_name, mode, source_ref):
        ClosureGiverNodeBase.__init__(
            self,
            name        = name,
            code_prefix = "module",
            source_ref  = source_ref
        )

        PythonModuleMixin.__init__(
            self,
            name         = name,
            package_name = package_name
        )

        ChildrenHavingMixin.__init__(
            self,
            values = {
                "body" : None, # delayed
                "functions" : (),
            },
        )

        self.mode = mode

        self.variables = {}

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # SSA trace based information about the module.
        self.trace_collection = None
Example #3
0
class TraceCollectionModule(CollectionStartpointMixin,
                            TraceCollectionBase):
    def __init__(self, module):
        CollectionStartpointMixin.__init__(self)

        TraceCollectionBase.__init__(
            self,
            owner  = module,
            name   = "module",
            parent = None
        )

        self.used_modules = OrderedSet()

    def onUsedModule(self, module_name):
        assert type(module_name) is str, module_name

        self.used_modules.add(module_name)

        if isImportedModuleByName(module_name):
            module = getImportedModuleByName(module_name)
            addUsedModule(module)

    def getUsedModules(self):
        return self.used_modules
Example #4
0
    def __init__(self, name, package_name, is_top, mode, future_spec, source_ref):
        PythonModuleBase.__init__(
            self, name=name, package_name=package_name, source_ref=source_ref
        )

        ClosureGiverNodeMixin.__init__(self, name=name, code_prefix="module")

        ChildrenHavingMixin.__init__(
            self, values={"body": None, "functions": ()}  # delayed
        )

        MarkNeedsAnnotationsMixin.__init__(self)

        EntryPointMixin.__init__(self)

        self.is_top = is_top

        self.mode = mode

        self.variables = {}

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # Often "None" until tree building finishes its part.
        self.future_spec = future_spec

        self.module_dict_name = "globals_%s" % (self.getCodeName(),)
        setLocalsDictType(self.module_dict_name, "module_dict")
Example #5
0
class TraceCollectionModule(CollectionStartpointMixin, TraceCollectionBase):
    def __init__(self, module):
        assert module.isCompiledPythonModule(), module

        CollectionStartpointMixin.__init__(self)

        TraceCollectionBase.__init__(
            self, owner=module, name="module:" + module.getFullName(), parent=None
        )

        self.used_modules = OrderedSet()

    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)

    def getUsedModules(self):
        return self.used_modules
Example #6
0
    def __init__(self, qt_plugins):
        self.webengine_done = False
        self.qt_plugins_dirs = None

        self.qt_plugins = OrderedSet(x.strip().lower()
                                     for x in qt_plugins.split(","))

        # Allow to specify none.
        if self.qt_plugins == set(["none"]):
            self.qt_plugins = set()
Example #7
0
def replaceRootModule(old, new):
    # Using global here, as this is really a singleton, in the form of a module,
    # pylint: disable=global-statement
    global root_modules
    new_root_modules = OrderedSet()

    for module in root_modules:
        new_root_modules.add(module if module is not old else new)

    root_modules = new_root_modules
Example #8
0
def startTraversal():
    # Using global here, as this is really a singleton, in the form of a module,
    # pylint: disable=W0603
    global active_modules, done_modules

    active_modules = OrderedSet(root_modules)
    done_modules = OrderedSet()

    for active_module in active_modules:
        active_module.startTraversal()
Example #9
0
def replaceRootModule(old, new):
    # Using global here, as this is really a singleton, in the form of a module,
    # pylint: disable=global-statement
    global root_modules
    new_root_modules = OrderedSet()

    for module in root_modules:
        new_root_modules.add(module if module is not old else new)

    root_modules = new_root_modules
Example #10
0
    def __init__(self, module):
        CollectionStartpointMixin.__init__(self)

        TraceCollectionBase.__init__(
            self,
            owner  = module,
            name   = "module",
            parent = None
        )

        self.used_modules = OrderedSet()
Example #11
0
    def __init__(self, module):
        assert module.isCompiledPythonModule(), module

        CollectionStartpointMixin.__init__(self)

        TraceCollectionBase.__init__(self,
                                     owner=module,
                                     name="module:" + module.getFullName(),
                                     parent=None)

        self.used_modules = OrderedSet()
Example #12
0
class VariableWriteExtractor(VisitorNoopMixin):
    """Extract variables written to."""

    def __init__(self):
        self.written_to = OrderedSet()

    def onEnterNode(self, node):
        if node.isStatementAssignmentVariable() or node.isStatementDelVariable():
            self.written_to.add(node.getVariable())

    def getResult(self):
        return self.written_to
Example #13
0
    def _readPyPIFile(self):
        """ Read the .pyi file if present and scan for dependencies. """

        if self.used_modules is None:
            pyi_filename = self.getPyIFilename()

            if os.path.exists(pyi_filename):
                pyi_deps = OrderedSet()

                for line in open(pyi_filename):
                    line = line.strip()

                    if line.startswith("import "):
                        imported = line[7:]

                        pyi_deps.add(imported)
                    elif line.startswith("from "):
                        parts = line.split(None, 3)
                        assert parts[0] == "from"
                        assert parts[2] == "import"

                        if parts[1] == "typing":
                            continue

                        pyi_deps.add(parts[1])

                        imported = parts[3]
                        if imported.startswith('('):
                            # No multiline imports please
                            assert imported.endswith(')')
                            imported = imported[1:-1]

                            assert imported

                        if imported == '*':
                            continue

                        for name in imported.split(','):
                            name = name.strip()

                            pyi_deps.add(parts[1] + '.' + name)

                if "typing" in pyi_deps:
                    pyi_deps.discard("typing")

                self.used_modules = tuple(
                    (pyi_dep, None)
                    for pyi_dep in
                    pyi_deps
                )
            else:
                self.used_modules = ()
Example #14
0
    def getModuleSpecificDllPaths(module_name):
        """Provide a list of directories, where DLLs should be searched for this package (or module).

        Args:
            module_name: name of a package or module, for which the DLL path addition applies.

        """
        result = OrderedSet()
        for plugin in getActivePlugins():
            for dll_path in plugin.getModuleSpecificDllPaths(module_name):
                result.add(dll_path)

        return result
Example #15
0
def getPluginsEnabled():
    """*tuple*, user enabled (standard) plugins (not including user plugins)

    Note:
        Do not use this outside of main binary, as other plugins, e.g.
        hinted compilation will activate plugins themselves and this
        will not be visible here.
    """
    result = OrderedSet()

    if options:
        for plugin_enabled in options.plugins_enabled:
            result.update(plugin_enabled.split(","))

    return tuple(result)
Example #16
0
class TraceCollectionPureFunction(TraceCollectionFunction):
    """Pure functions don't feed their parent."""

    __slots__ = ("used_functions",)

    def __init__(self, function_body):
        TraceCollectionFunction.__init__(self, parent=None, function_body=function_body)

        self.used_functions = OrderedSet()

    def getUsedFunctions(self):
        return self.used_functions

    def onUsedFunction(self, function_body):
        self.used_functions.add(function_body)
def onMissingTrust(operation, source_ref, *args):
    key = (operation, ) + args

    if key not in _missing_trust:
        _missing_trust[key] = OrderedSet()

    _missing_trust[key].add(source_ref)
Example #18
0
def buildOrderedSet(*producers):
    values = []

    for producer in producers:
        values.extend(producer)

    return OrderedSet(values)
Example #19
0
def getPluginsEnabled():
    """*tuple*, user enabled (standard) plugins (not including user plugins)

    Note:
        Do not use this outside of main binary, as plugins are allowed
        to activate plugins themselves and that will not be visible here.
    """
    result = OrderedSet()

    if options:
        for plugin_enabled in options.plugins_enabled:
            result.update(
                getPluginNameConsideringRenames(plugin_name)
                for plugin_name in plugin_enabled.split(","))

    return tuple(result)
Example #20
0
def getPluginsDisabled():
    """*tuple*, user disabled (standard) plugins.

    Note:
        Do not use this outside of main binary, as other plugins, e.g.
        hinted compilation will activate plugins themselves and this
        will not be visible here.
    """
    result = OrderedSet()

    if options:
        for plugin_disabled in options.plugins_disabled:
            result.update(
                getPluginNameConsideringRenames(plugin_name)
                for plugin_name in plugin_disabled.split(","))

    return tuple(result)
def _getPackageFiles(module, *packages):
    """Yield all (!) filenames in given package(s).

    Notes:
        This should be required in rare occasions only. The one example I know
        is 'dns' when used by package 'eventlet'. Eventlet imports dns modules
        only to replace them with 'green' (i.e. non-blocking) counterparts.
    Args:
        module: module object
        packages: package name(s) - str or tuple
    Yields:
        Tuples of paths (source, dest)
    """

    file_list = []
    item_set = OrderedSet()

    file_dirs = []

    for package in packages:
        pkg_base, pkg_dir = get_package_paths(package)  # read package folders
        if pkg_dir:
            filename_start = len(pkg_base)  # position of package name in dir
            # read out the filenames
            pkg_files = getFileList(
                pkg_dir, ignore_dirs=("__pycache__",), ignore_suffixes=(".pyc",)
            )
            file_dirs.append(pkg_dir)
            for f in pkg_files:
                file_list.append((filename_start, f))  # append to file list

    if not file_list:  #  safeguard for unexpected cases
        msg = "No files or folders found for '%s' in packages(s) '%r' (%r)." % (
            module.getFullName(),
            packages,
            file_dirs,
        )
        NuitkaPluginDataFileCollector.warning(msg)

    for filename_start, f in file_list:  # re-read the collected filenames
        target = f[filename_start:]  # make part of name
        item_set.add((f, target))

    for f in item_set:
        yield f
Example #22
0
def detectBinaryPathDLLsWindowsDependencyWalker(
    is_main_executable,
    source_dir,
    original_dir,
    binary_filename,
    package_name,
    use_cache,
    update_cache,
):
    # This is the caching mechanism and plugin handling for DLL imports.
    if use_cache or update_cache:
        cache_filename = _getCacheFilename(
            dependency_tool="depends.exe",
            is_main_executable=is_main_executable,
            source_dir=source_dir,
            original_dir=original_dir,
            binary_filename=binary_filename,
        )

        if use_cache:
            with withFileLock():
                if not os.path.exists(cache_filename):
                    use_cache = False

        if use_cache:
            result = OrderedSet()

            for line in getFileContentByLine(cache_filename):
                line = line.strip()

                result.add(line)

            return result

    if Options.isShowProgress():
        general.info("Analysing dependencies of '%s'." % binary_filename)

    scan_dirs = getScanDirectories(package_name, original_dir)

    result = detectDLLsWithDependencyWalker(binary_filename, scan_dirs)

    if update_cache:
        putTextFileContents(filename=cache_filename, contents=result)

    return result
Example #23
0
class DetectUsedModules(VisitorNoopMixin):
    def __init__(self):
        self.used_modules = OrderedSet()

    def onEnterNode(self, node):
        try:
            self._onEnterNode(node)
        except Exception:
            general.my_print(
                "Problem with %r at %s"
                % (node, node.getSourceReference().getAsString())
            )
            raise

    def _onEnterNode(self, node):
        if node.isExpressionBuiltinImport():

            for (
                used_module_name,
                used_module_filename,
                finding,
                level,
            ) in node.getUsedModules():
                self.used_modules.add(
                    (
                        used_module_name,
                        used_module_filename,
                        finding,
                        level,
                        node.source_ref,
                    )
                )
        elif (
            node.isExpressionImportModuleHard()
            or node.isExpressionImportModuleNameHard()
            or node.isExpressionImportModuleFixed()
        ):
            used_module_name, used_module_filename, finding = node.getUsedModule()
            self.used_modules.add(
                (used_module_name, used_module_filename, finding, 0, node.source_ref)
            )

    def getUsedModules(self):
        return self.used_modules
Example #24
0
    def __init__(self, module):
        assert module.isCompiledPythonModule(), module

        CollectionStartpointMixin.__init__(self)

        TraceCollectionBase.__init__(
            self, owner=module, name="module:" + module.getFullName(), parent=None
        )

        self.used_modules = OrderedSet()
Example #25
0
    def _readPyPIFile(self):
        """ Read the .pyi file if present and scan for dependencies. """

        if self.used_modules is None:
            pyi_filename = self.getPyIFilename()

            if os.path.exists(pyi_filename):
                pyi_deps = OrderedSet()

                for line in getFileContentByLine(pyi_filename):
                    line = line.strip()

                    if line.startswith("import "):
                        imported = line[7:]

                        pyi_deps.add(imported)
                    elif line.startswith("from "):
                        parts = line.split(None, 3)
                        assert parts[0] == "from"
                        assert parts[2] == "import"

                        if parts[1] == "typing":
                            continue

                        pyi_deps.add(parts[1])

                        imported = parts[3]
                        if imported.startswith("("):
                            # No multiline imports please
                            assert imported.endswith(")")
                            imported = imported[1:-1]

                            assert imported

                        if imported == "*":
                            continue

                        for name in imported.split(","):
                            name = name.strip()

                            pyi_deps.add(parts[1] + "." + name)

                if "typing" in pyi_deps:
                    pyi_deps.discard("typing")

                self.used_modules = tuple((pyi_dep, None) for pyi_dep in pyi_deps)
            else:
                self.used_modules = ()
Example #26
0
    def __init__(self, name, package_name, is_top, mode, future_spec, source_ref):
        PythonModuleBase.__init__(
            self,
            name         = name,
            package_name = package_name,
            source_ref   = source_ref
        )

        ClosureGiverNodeMixin.__init__(
            self,
            name        = name,
            code_prefix = "module"
        )

        ChildrenHavingMixin.__init__(
            self,
            values = {
                "body" : None, # delayed
                "functions" : (),
            },
        )

        MarkNeedsAnnotationsMixin.__init__(self)

        EntryPointMixin.__init__(self)

        self.is_top = is_top

        self.mode = mode

        self.variables = {}

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # Often "None" until tree building finishes its part.
        self.future_spec = future_spec

        self.module_dict_name = "globals_%s" % (
            self.getCodeName(),
        )
        setLocalsDictType(self.module_dict_name, "module_dict")
Example #27
0
    def __init__(self, name, package_name, mode, source_ref):
        ClosureGiverNodeBase.__init__(
            self,
            name        = name,
            code_prefix = "module",
            source_ref  = source_ref
        )

        PythonModuleMixin.__init__(
            self,
            name         = name,
            package_name = package_name
        )

        ChildrenHavingMixin.__init__(
            self,
            values = {
                "body" : None # delayed
            },
        )

        self.mode = mode

        self.variables = {}

        # The list functions contained in that module.
        self.functions = OrderedSet()

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # SSA trace based information about the module.
        self.constraint_collection = None

        self.code_object = CodeObjectSpec(
            code_name     = "<module>" if self.isMainModule() else self.getName(),
            code_kind     = "Module",
            arg_names     = (),
            kw_only_count = 0,
            has_stardict  = False,
            has_starlist  = False,
        )
Example #28
0
    def __init__(self, name, package_name, source_ref):
        ClosureGiverNodeBase.__init__(self,
                                      name=name,
                                      code_prefix="module",
                                      source_ref=source_ref)

        PythonModuleMixin.__init__(self, name=name, package_name=package_name)

        ChildrenHavingMixin.__init__(
            self,
            values={
                "body": None  # delayed
            },
        )

        self.variables = set()

        # The list functions contained in that module.
        self.functions = OrderedSet()

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # SSA trace based information about the module.
        self.constraint_collection = None
Example #29
0
def _loadUncompiledModuleFromCache(module_name, is_package, source_code,
                                   source_ref):
    result = makeUncompiledPythonModule(
        module_name=module_name,
        filename=source_ref.getFilename(),
        bytecode=demoteSourceCodeToBytecode(
            module_name=module_name,
            source_code=source_code,
            filename=source_ref.getFilename(),
        ),
        user_provided=False,
        technical=False,
        is_package=is_package,
    )

    used_modules = OrderedSet()

    for used_module_name, line_number in getCachedImportedModulesNames(
            module_name=module_name, source_code=source_code):
        _module_name, module_filename, finding = Importing.locateModule(
            module_name=used_module_name,
            parent_package=None,
            level=0,
        )

        assert _module_name == used_module_name

        used_modules.add((
            used_module_name,
            module_filename,
            finding,
            0,
            source_ref.atLineNumber(line_number),
        ))

    # assert not is_package, (module_name, used_modules, result, result.getCompileTimeFilename())

    result.setUsedModules(used_modules)

    return result
Example #30
0
    def __init__(self, name, package_name, source_ref):
        ClosureGiverNodeBase.__init__(self,
                                      name=name,
                                      code_prefix="module",
                                      source_ref=source_ref)

        PythonModuleMixin.__init__(self, name=name, package_name=package_name)

        ChildrenHavingMixin.__init__(
            self,
            values={
                "body": None  # delayed
            },
        )

        self.variables = {}

        # The list functions contained in that module.
        self.functions = OrderedSet()

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # SSA trace based information about the module.
        self.constraint_collection = None

        self.code_object = CodeObjectSpec(
            code_name="<module>" if self.isMainModule() else self.getName(),
            code_kind="Module",
            arg_names=(),
            kw_only_count=0,
            has_stardict=False,
            has_starlist=False,
        )
Example #31
0
class ConstraintCollectionModule(CollectionStartpointMixin,
                                 ConstraintCollectionBase,
                                 VariableUsageTrackingMixin):
    def __init__(self, module):
        CollectionStartpointMixin.__init__(self)

        ConstraintCollectionBase.__init__(self,
                                          owner=module,
                                          name="module",
                                          parent=None)

        self.used_modules = OrderedSet()

    def onUsedModule(self, module_name):
        self.used_modules.add(module_name)

        if isImportedModuleByName(module_name):
            module = getImportedModuleByName(module_name)
            addUsedModule(module)

    def getUsedModules(self):
        return self.used_modules
Example #32
0
class TraceCollectionModule(CollectionStartpointMixin, TraceCollectionBase):
    def __init__(self, module):
        CollectionStartpointMixin.__init__(self)

        TraceCollectionBase.__init__(self,
                                     owner=module,
                                     name="module",
                                     parent=None)

        self.used_modules = OrderedSet()

    def onUsedModule(self, module_name):
        assert type(module_name) is str, module_name

        self.used_modules.add(module_name)

        if isImportedModuleByName(module_name):
            module = getImportedModuleByName(module_name)
            addUsedModule(module)

    def getUsedModules(self):
        return self.used_modules
Example #33
0
def _getPackageSpecificDLLDirectories(package_name):
    scan_dirs = OrderedSet()

    if package_name is not None:
        package_dir = locateModule(module_name=package_name,
                                   parent_package=None,
                                   level=0)[1]

        if os.path.isdir(package_dir):
            scan_dirs.add(package_dir)
            scan_dirs.update(
                getSubDirectories(package_dir, ignore_dirs=("__pycache__", )))

        scan_dirs.update(Plugins.getModuleSpecificDllPaths(package_name))

    return scan_dirs
Example #34
0
def _getLdLibraryPath(package_name, python_rpath, original_dir):
    key = package_name, python_rpath, original_dir

    if key not in _ld_library_cache:

        ld_library_path = OrderedSet()
        if python_rpath:
            ld_library_path.add(python_rpath)

        ld_library_path.update(_getPackageSpecificDLLDirectories(package_name))
        if original_dir is not None:
            ld_library_path.add(original_dir)

        _ld_library_cache[key] = ld_library_path

    return _ld_library_cache[key]
Example #35
0
def _locateStaticLinkLibrary(dll_name):
    # singleton, pylint: disable=global-statement
    #
    global _ldconf_paths

    if _ldconf_paths is None:
        _ldconf_paths = OrderedSet()

        for conf_filemame in getFileList("/etc/ld.so.conf.d", only_suffixes=".conf"):
            for conf_line in getFileContentByLine(conf_filemame):
                conf_line = conf_line.split("#", 1)[0]
                conf_line = conf_line.strip()

                if os.path.exists(conf_line):
                    _ldconf_paths.add(conf_line)

    for ld_config_path in _ldconf_paths:
        candidate = os.path.join(ld_config_path, "lib%s.a" % dll_name)

        if os.path.exists(candidate):
            return candidate

    return None
Example #36
0
def getPackageSpecificDLLDirectories(package_name):
    scan_dirs = OrderedSet()

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

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

        if os.path.isdir(package_dir):
            scan_dirs.add(package_dir)
            scan_dirs.update(
                getSubDirectories(package_dir, ignore_dirs=("__pycache__", )))

        scan_dirs.update(Plugins.getModuleSpecificDllPaths(package_name))

    return scan_dirs
Example #37
0
class ConstraintCollectionModule(CollectionStartpointMixin,
                                 ConstraintCollectionBase,
                                 VariableUsageTrackingMixin):
    def __init__(self, module):
        CollectionStartpointMixin.__init__(self)

        ConstraintCollectionBase.__init__(
            self,
            owner  = module,
            name   = "module",
            parent = None
        )

        self.used_modules = OrderedSet()

    def onUsedModule(self, module_name):
        self.used_modules.add(module_name)

        if isImportedModuleByName(module_name):
            module = getImportedModuleByName(module_name)
            addUsedModule(module)

    def getUsedModules(self):
        return self.used_modules
Example #38
0
    def run(self):
        wheel_logger.info("Specified packages: %s." %
                          self.distribution.packages,
                          style="blue")
        wheel_logger.info("Specified modules: %s." %
                          self.distribution.py_modules,
                          style="blue")

        self.compile_packages = self.distribution.packages or []
        self.py_modules = self.distribution.py_modules or []

        # Determine
        self.script_module_names = OrderedSet()
        if self.distribution.entry_points is not None:
            for group, script_specs in self.distribution.entry_points.items():
                for script_spec in script_specs:
                    try:
                        script_module_name = (script_spec.split(
                            "=", 1)[1].strip().split(":")[0])
                    except Exception as e:  # Catch all the things, pylint: disable=broad-except
                        wheel_logger.info(
                            "Problem parsing '%s' script specification in '%s' due to %s"
                            % (script_spec, group, e))

                    self.script_module_names.add(
                        ModuleName(script_module_name))

        if not self.compile_packages and not self.py_modules:
            wheel_logger.sysexit(
                "No modules or packages specified, aborting. Did you provide packages in 'setup.cfg' or 'setup.py'?"
            )

        # Python2 does not allow super on this old style class.
        distutils.command.build.build.run(self)

        self._build(os.path.abspath(self.build_lib))
Example #39
0
    def getExtraLinkLibraries(cls):
        if cls.extra_link_libraries is None:
            cls.extra_link_libraries = OrderedSet()

            for plugin in getActivePlugins():
                value = plugin.getExtraLinkLibraries()

                if value is not None:
                    if isinstance(value, basestring):
                        cls.extra_link_libraries.add(value)
                    else:
                        for library_name in value:
                            cls.extra_link_libraries.add(library_name)

        return cls.extra_link_libraries
Example #40
0
def getPackageFiles(module, packages, folders_only):
    """Yield all (!) filenames in given package(s).

    Notes:
        This should be required in rare occasions only. The one example I know
        is 'dns' when used by package 'eventlet'. Eventlet imports dns modules
        only to replace them with 'green' (i.e. non-blocking) counterparts.
    Args:
        module: module object
        packages: package name(s) - str or tuple
        folders_only: (bool) indicate, whether just the folder structure should
            be generated. In that case, an empty file named DUMMY will be
            placed in each of these folders.
    Yields:
        Tuples of paths (source, dest), if folders_only is False,
        else tuples (_createEmptyDirNone, dest).
    """

    # TODO: Maybe use isinstance(basestring) for this
    if not hasattr(packages, "__getitem__"):  # so should be a string type
        packages = (packages, )

    file_list = []
    item_set = OrderedSet()

    file_dirs = []

    for package in packages:
        pkg_base, pkg_dir = get_package_paths(package)  # read package folders
        if pkg_dir:
            filename_start = len(pkg_base)  # position of package name in dir
            # read out the filenames
            pkg_files = getFileList(pkg_dir,
                                    ignore_dirs=("__pycache__", ),
                                    ignore_suffixes=(".pyc", ))
            file_dirs.append(pkg_dir)
            for f in pkg_files:
                file_list.append((filename_start, f))  # append to file list

    if not file_list:  #  safeguard for unexpected cases
        msg = "No files or folders found for '%s' in packages(s) '%r' (%r)." % (
            module.getFullName(),
            packages,
            file_dirs,
        )
        NuitkaPluginDataFileCollector.warning(msg)

    for filename_start, f in file_list:  # re-read the collected filenames
        target = f[filename_start:]  # make part of name
        if folders_only is False:  # normal case: indeed copy the files
            item_set.add((f, target))
        else:  # just create the empty folder structure
            item_set.add((_createEmptyDirNone, target))

    for f in item_set:
        yield f
Example #41
0
class PythonModule(PythonModuleMixin, ChildrenHavingMixin,
                   ClosureGiverNodeBase):
    """ Module

        The module is the only possible root of a tree. When there are many
        modules they form a forest.
    """

    kind = "PYTHON_MODULE"

    named_children = (
        "body",
    )

    checkers = {
        "body": checkStatementsSequenceOrNone
    }

    def __init__(self, name, package_name, source_ref):
        ClosureGiverNodeBase.__init__(
            self,
            name        = name,
            code_prefix = "module",
            source_ref  = source_ref
        )

        PythonModuleMixin.__init__(
            self,
            name         = name,
            package_name = package_name
        )


        ChildrenHavingMixin.__init__(
            self,
            values = {
                "body" : None # delayed
            },
        )

        self.variables = set()

        # The list functions contained in that module.
        self.functions = OrderedSet()

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # SSA trace based information about the module.
        self.constraint_collection = None

    def getDetails(self):
        return {
            "filename" : self.source_ref.getFilename(),
            "package"  : self.package_name,
            "name"     : self.name
        }

    def asXml(self):
        result = super(PythonModule, self).asXml()

        for function_body in self.active_functions:
            result.append(function_body.asXml())

        return result

    getBody = ChildrenHavingMixin.childGetter("body")
    setBody = ChildrenHavingMixin.childSetter("body")

    @staticmethod
    def isPythonModule():
        return True

    def getParent(self):
        assert False

    def getParentVariableProvider(self):
        return None

    def getVariables(self):
        return self.variables

    def getFilename(self):
        return self.source_ref.getFilename()

    def getVariableForAssignment(self, variable_name):
        return self.getProvidedVariable(variable_name)

    def getVariableForReference(self, variable_name):
        return self.getProvidedVariable(variable_name)

    def getVariableForClosure(self, variable_name):
        return self.getProvidedVariable(
            variable_name = variable_name
        )

    def createProvidedVariable(self, variable_name):
        result = Variables.ModuleVariable(
            module        = self,
            variable_name = variable_name
        )

        assert result not in self.variables
        self.variables.add(result)

        return result

    @staticmethod
    def getContainingClassDictCreation():
        return None

    def isEarlyClosure(self):
        # Modules should immediately closure variables on use.
        # pylint: disable=R0201
        return True

    def getCodeName(self):
        def r(match):
            c = match.group()
            if c == '.':
                return '$'
            else:
                return "$$%d$" % ord(c)

        return "".join(
            re.sub("[^a-zA-Z0-9_]", r ,c)
            for c in
            self.getFullName()
        )

    def addFunction(self, function_body):
        assert function_body not in self.functions

        self.functions.add(function_body)

    def getFunctions(self):
        return self.functions

    def startTraversal(self):
        self.active_functions = OrderedSet()

    def addUsedFunction(self, function_body):
        assert function_body in self.functions

        assert function_body.isExpressionFunctionBody()

        if function_body not in self.active_functions:
            self.active_functions.add(function_body)

    def getUsedFunctions(self):
        return self.active_functions

    def getUnusedFunctions(self):
        for function in self.functions:
            if function not in self.active_functions:
                yield function

    def addCrossUsedFunction(self, function_body):
        if function_body not in self.cross_used_functions:
            self.cross_used_functions.add(function_body)

    def getCrossUsedFunctions(self):
        return self.cross_used_functions

    def getOutputFilename(self):
        main_filename = self.getFilename()

        if main_filename.endswith(".py"):
            result = main_filename[:-3]
        else:
            result = main_filename

        # There are some characters that somehow are passed to shell, by
        # Scons or unknown, so lets avoid them for now.
        return result.replace(')',"").replace('(',"")

    # TODO: Can't really use locals for modules, this should probably be made
    # sure to not be used.
    @staticmethod
    def getLocalsMode():
        return "copy"

    def computeModule(self):
        old_collection = self.constraint_collection

        self.constraint_collection = ConstraintCollectionModule()

        module_body = self.getBody()

        if module_body is not None:
            result = module_body.computeStatementsSequence(
                constraint_collection = self.constraint_collection
            )

            if result is not module_body:
                self.setBody(result)

        new_modules = self.attemptRecursion()

        for new_module in new_modules:
            self.constraint_collection.signalChange(
                source_ref = new_module.getSourceReference(),
                tags       = "new_code",
                message    = "Recursed to module package."
            )

        self.constraint_collection.updateFromCollection(old_collection)


    def getTraceCollections(self):
        yield self.constraint_collection

        for function in self.getUsedFunctions():
            yield function.constraint_collection

    def hasUnclearLocals(self):
        for collection in self.getTraceCollections():
            if collection.hasUnclearLocals():
                return True

        return False
Example #42
0
class CompiledPythonModule(PythonModuleMixin, ChildrenHavingMixin,
                           ClosureGiverNodeBase):
    """ Compiled Python Module

    """

    kind = "COMPILED_PYTHON_MODULE"

    named_children = (
        "body",
        "functions"
    )

    checkers = {
        "body": checkStatementsSequenceOrNone
    }

    def __init__(self, name, package_name, mode, source_ref):
        ClosureGiverNodeBase.__init__(
            self,
            name        = name,
            code_prefix = "module",
            source_ref  = source_ref
        )

        PythonModuleMixin.__init__(
            self,
            name         = name,
            package_name = package_name
        )

        ChildrenHavingMixin.__init__(
            self,
            values = {
                "body" : None, # delayed
                "functions" : (),
            },
        )

        self.mode = mode

        self.variables = {}

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # SSA trace based information about the module.
        self.trace_collection = None

    def getDetails(self):
        return {
            "filename" : self.source_ref.getFilename(),
            "package"  : self.package_name,
            "name"     : self.name
        }

    def getDetailsForDisplay(self):
        result = self.getDetails()

        result["code_flags"] = ','.join(self.source_ref.getFutureSpec().asFlags())

        return result

    @classmethod
    def fromXML(cls, provider, source_ref, **args):
        # Modules are not having any provider.
        assert provider is None


        assert False


    def asGraph(self, computation_counter):
        from graphviz import Digraph # @UnresolvedImport pylint: disable=F0401,I0021

        graph = Digraph("cluster_%d" % computation_counter, comment = "Graph for %s" % self.getName())
        graph.body.append("style=filled")
        graph.body.append("color=lightgrey")
        graph.body.append("label=Iteration_%d" % computation_counter)


        def makeTraceNodeName(variable_trace):
            return "%d/ %s %s %s" % (
                computation_counter,
                variable_trace.getVariable(),
                variable_trace.getVersion(),
                variable_trace.__class__.__name__
            )

        for function_body in self.active_functions:
            trace_collection = function_body.trace_collection

            for (_variable, _version), variable_trace in trace_collection.getVariableTracesAll().items():
                node = makeTraceNodeName(variable_trace)

                previous = variable_trace.getPrevious()

                if variable_trace.hasDefiniteUsages():
                    graph.attr("node", style = "filled", color = "blue")
                elif variable_trace.hasPotentialUsages():
                    graph.attr("node", style = "filled", color = "yellow")
                else:
                    graph.attr("node", style = "filled", color = "red")

                graph.node(node)

                if type(previous) is tuple:
                    for previous in previous:
                        graph.edge(makeTraceNodeName(previous), node)
                elif previous is not None:
                    graph.edge(makeTraceNodeName(previous), node)

        return graph

    getBody = ChildrenHavingMixin.childGetter("body")
    setBody = ChildrenHavingMixin.childSetter("body")

    getFunctions = ChildrenHavingMixin.childGetter("functions")
    setFunctions = ChildrenHavingMixin.childSetter("functions")

    @staticmethod
    def isCompiledPythonModule():
        return True

    def getParent(self):
        assert False

    def getParentVariableProvider(self):
        return None

    def hasVariableName(self, variable_name):
        return variable_name in self.variables or variable_name in self.temp_variables

    def getVariables(self):
        return self.variables.values()

    def getFilename(self):
        return self.source_ref.getFilename()

    def getVariableForAssignment(self, variable_name):
        return self.getProvidedVariable(variable_name)

    def getVariableForReference(self, variable_name):
        return self.getProvidedVariable(variable_name)

    def getVariableForClosure(self, variable_name):
        return self.getProvidedVariable(
            variable_name = variable_name
        )

    def createProvidedVariable(self, variable_name):
        assert variable_name not in self.variables

        result = Variables.ModuleVariable(
            module        = self,
            variable_name = variable_name
        )

        self.variables[variable_name] = result

        return result

    @staticmethod
    def getContainingClassDictCreation():
        return None

    def isEarlyClosure(self):
        # Modules should immediately closure variables on use.
        # pylint: disable=R0201
        return True

    def getCodeName(self):
        # For code name of modules, we need to translate to C identifiers,
        # removing characters illegal for that.

        return encodePythonIdentifierToC(self.getFullName())

    def addFunction(self, function_body):
        functions = self.getFunctions()
        assert function_body not in functions
        functions += (function_body,)
        self.setFunctions(functions)

    def startTraversal(self):
        self.active_functions = OrderedSet()

    def addUsedFunction(self, function_body):
        assert function_body in self.getFunctions()

        assert function_body.isExpressionFunctionBody() or \
               function_body.isExpressionClassBody() or \
               function_body.isExpressionGeneratorObjectBody() or \
               function_body.isExpressionCoroutineObjectBody()

        if function_body not in self.active_functions:
            self.active_functions.add(function_body)

    def getUsedFunctions(self):
        return self.active_functions

    def getUnusedFunctions(self):
        for function in self.getFunctions():
            if function not in self.active_functions:
                yield function

    def addCrossUsedFunction(self, function_body):
        if function_body not in self.cross_used_functions:
            self.cross_used_functions.add(function_body)

    def getCrossUsedFunctions(self):
        return self.cross_used_functions

    def getFunctionFromCodeName(self, code_name):
        for function in self.getFunctions():
            if function.getCodeName() == code_name:
                return function

    def getOutputFilename(self):
        main_filename = self.getFilename()

        if main_filename.endswith(".py"):
            result = main_filename[:-3]
        else:
            result = main_filename

        # There are some characters that somehow are passed to shell, by
        # Scons or unknown, so lets avoid them for now.
        return result.replace(')',"").replace('(',"")

    # TODO: Can't really use locals for modules, this should probably be made
    # sure to not be used.
    @staticmethod
    def getLocalsMode():
        return "copy"

    def computeModule(self):
        old_collection = self.trace_collection

        self.trace_collection = TraceCollectionModule(self)

        module_body = self.getBody()

        if module_body is not None:
            result = module_body.computeStatementsSequence(
                trace_collection = self.trace_collection
            )

            if result is not module_body:
                self.setBody(result)

        new_modules = self.attemptRecursion()

        for new_module in new_modules:
            self.trace_collection.signalChange(
                source_ref = new_module.getSourceReference(),
                tags       = "new_code",
                message    = "Recursed to module package."
            )

        self.trace_collection.updateFromCollection(old_collection)

    def getTraceCollections(self):
        yield self.trace_collection

        for function in self.getUsedFunctions():
            yield function.trace_collection
Example #43
0
def _findModuleInPath2(module_name, search_path):
    """ This is out own module finding low level implementation.

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

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

    considered = set()

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

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

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

                package_file_name = "__init__" + suffix

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

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

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

    if _debug_module_finding:
        print("Candidates", candidates)

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

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

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

    # Nothing found.
    raise ImportError
Example #44
0
class CompiledPythonModule(
    ChildrenHavingMixin,
    ClosureGiverNodeMixin,
    MarkNeedsAnnotationsMixin,
    EntryPointMixin,
    PythonModuleBase,
):
    """ Compiled Python Module

    """

    # This one has a few indicators, pylint: disable=too-many-instance-attributes

    kind = "COMPILED_PYTHON_MODULE"

    named_children = ("body", "functions")

    checkers = {"body": checkStatementsSequenceOrNone}

    def __init__(self, name, package_name, is_top, mode, future_spec, source_ref):
        PythonModuleBase.__init__(
            self, name=name, package_name=package_name, source_ref=source_ref
        )

        ClosureGiverNodeMixin.__init__(self, name=name, code_prefix="module")

        ChildrenHavingMixin.__init__(
            self, values={"body": None, "functions": ()}  # delayed
        )

        MarkNeedsAnnotationsMixin.__init__(self)

        EntryPointMixin.__init__(self)

        self.is_top = is_top

        self.mode = mode

        self.variables = {}

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # Often "None" until tree building finishes its part.
        self.future_spec = future_spec

        self.module_dict_name = "globals_%s" % (self.getCodeName(),)
        setLocalsDictType(self.module_dict_name, "module_dict")

    def getDetails(self):
        return {
            "filename": self.source_ref.getFilename(),
            "package": self.package_name,
            "name": self.name,
        }

    def getDetailsForDisplay(self):
        result = self.getDetails()

        if self.future_spec is not None:
            result["code_flags"] = ",".join(self.future_spec.asFlags())

        return result

    @classmethod
    def fromXML(cls, provider, source_ref, **args):
        # Modules are not having any provider, must not be used,
        assert False

    def getFutureSpec(self):
        return self.future_spec

    def isTopModule(self):
        return self.is_top

    def asGraph(self, graph, desc):
        graph = graph.add_subgraph(
            name="cluster_%s" % desc, comment="Graph for %s" % self.getName()
        )

        #        graph.body.append("style=filled")
        #        graph.body.append("color=lightgrey")
        #        graph.body.append("label=Iteration_%d" % desc)

        def makeTraceNodeName(variable, version, variable_trace):
            return "%s/ %s %s %s" % (
                desc,
                variable.getName(),
                version,
                variable_trace.__class__.__name__,
            )

        for function_body in self.active_functions:
            trace_collection = function_body.trace_collection

            node_names = {}

            for (
                (variable, version),
                variable_trace,
            ) in trace_collection.getVariableTracesAll().items():
                node_name = makeTraceNodeName(variable, version, variable_trace)

                node_names[variable_trace] = node_name

            for (
                (variable, version),
                variable_trace,
            ) in trace_collection.getVariableTracesAll().items():
                node_name = node_names[variable_trace]

                previous = variable_trace.getPrevious()

                attrs = {"style": "filled"}

                if variable_trace.hasDefiniteUsages():
                    attrs["color"] = "blue"
                elif variable_trace.hasPotentialUsages():
                    attrs["color"] = "yellow"
                else:
                    attrs["color"] = "red"

                graph.add_node(node_name, **attrs)

                if type(previous) is tuple:
                    for prev_trace in previous:
                        graph.add_edge(node_names[prev_trace], node_name)

                        assert prev_trace is not variable_trace

                elif previous is not None:
                    assert previous is not variable_trace
                    graph.add_edge(node_names[previous], node_name)

        return graph

    getBody = ChildrenHavingMixin.childGetter("body")
    setBody = ChildrenHavingMixin.childSetter("body")

    getFunctions = ChildrenHavingMixin.childGetter("functions")
    setFunctions = ChildrenHavingMixin.childSetter("functions")

    @staticmethod
    def isCompiledPythonModule():
        return True

    def getParent(self):
        # We have never have a parent
        return None

    def getParentVariableProvider(self):
        # We have never have a provider
        return None

    def hasVariableName(self, variable_name):
        return variable_name in self.variables or variable_name in self.temp_variables

    def getVariables(self):
        return self.variables.values()

    def getFilename(self):
        return self.source_ref.getFilename()

    def getVariableForAssignment(self, variable_name):
        return self.getProvidedVariable(variable_name)

    def getVariableForReference(self, variable_name):
        return self.getProvidedVariable(variable_name)

    def getVariableForClosure(self, variable_name):
        return self.getProvidedVariable(variable_name=variable_name)

    def createProvidedVariable(self, variable_name):
        assert variable_name not in self.variables

        result = Variables.ModuleVariable(module=self, variable_name=variable_name)

        self.variables[variable_name] = result

        return result

    @staticmethod
    def getContainingClassDictCreation():
        return None

    @staticmethod
    def isEarlyClosure():
        # Modules should immediately closure variables on use.
        return True

    def getEntryPoint(self):
        return self

    def getCodeName(self):
        # For code name of modules, we need to translate to C identifiers,
        # removing characters illegal for that.

        return encodePythonIdentifierToC(self.getFullName())

    def addFunction(self, function_body):
        functions = self.getFunctions()
        assert function_body not in functions
        functions += (function_body,)
        self.setFunctions(functions)

    def startTraversal(self):
        self.active_functions = OrderedSet()

    def addUsedFunction(self, function_body):
        assert function_body in self.getFunctions()

        assert (
            function_body.isExpressionFunctionBody()
            or function_body.isExpressionClassBody()
            or function_body.isExpressionGeneratorObjectBody()
            or function_body.isExpressionCoroutineObjectBody()
            or function_body.isExpressionAsyncgenObjectBody()
        )

        result = function_body not in self.active_functions
        if result:
            self.active_functions.add(function_body)

        return result

    def getUsedFunctions(self):
        return self.active_functions

    def getUnusedFunctions(self):
        for function in self.getFunctions():
            if function not in self.active_functions:
                yield function

    def addCrossUsedFunction(self, function_body):
        if function_body not in self.cross_used_functions:
            self.cross_used_functions.add(function_body)

    def getCrossUsedFunctions(self):
        return self.cross_used_functions

    def getFunctionFromCodeName(self, code_name):
        for function in self.getFunctions():
            if function.getCodeName() == code_name:
                return function

    def getOutputFilename(self):
        main_filename = self.getFilename()

        if main_filename.endswith(".py"):
            result = main_filename[:-3]
        elif main_filename.endswith(".pyw"):
            result = main_filename[:-4]
        else:
            result = main_filename

        # There are some characters that somehow are passed to shell, by
        # Scons or unknown, so lets avoid them for now.
        return result.replace(")", "").replace("(", "")

    def computeModule(self):
        old_collection = self.trace_collection

        self.trace_collection = TraceCollectionModule(self)

        module_body = self.getBody()

        if module_body is not None:
            result = module_body.computeStatementsSequence(
                trace_collection=self.trace_collection
            )

            if result is not module_body:
                self.setBody(result)

        new_modules = self.attemptRecursion()

        for new_module in new_modules:
            self.trace_collection.signalChange(
                source_ref=new_module.getSourceReference(),
                tags="new_code",
                message="Recursed to module package.",
            )

        self.trace_collection.updateVariablesFromCollection(old_collection)

    def getTraceCollections(self):
        yield self.trace_collection

        for function in self.getUsedFunctions():
            yield function.trace_collection

    def isUnoptimized(self):
        # Modules don't do this, pylint: disable=no-self-use
        return False

    def getLocalVariables(self):
        # Modules don't do this, pylint: disable=no-self-use
        return ()

    def getUserLocalVariables(self):
        # Modules don't do this, pylint: disable=no-self-use
        return ()

    def getOutlineLocalVariables(self):
        outlines = self.getTraceCollection().getOutlineFunctions()

        if outlines is None:
            return ()

        result = []

        for outline in outlines:
            result.extend(outline.getUserLocalVariables())

        return tuple(result)

    def hasClosureVariable(self, variable):
        # Modules don't do this, pylint: disable=no-self-use,unused-argument
        return False

    def removeUserVariable(self, variable):
        outlines = self.getTraceCollection().getOutlineFunctions()

        for outline in outlines:
            user_locals = outline.getUserLocalVariables()

            if variable in user_locals:
                outline.removeUserVariable(variable)
                break

    @staticmethod
    def getFunctionLocalsScope():
        """ Modules have no locals scope. """
        return None

    def getModuleDictScope(self):
        return getLocalsDictHandle(self.module_dict_name)
Example #45
0
 def startTraversal(self):
     self.active_functions = OrderedSet()
Example #46
0
class CompiledPythonModule(PythonModuleMixin, ChildrenHavingMixin,
                           ClosureGiverNodeBase):
    """ Compiled Python Module

    """

    kind = "COMPILED_PYTHON_MODULE"

    named_children = (
        "body",
    )

    checkers = {
        "body": checkStatementsSequenceOrNone
    }

    def __init__(self, name, package_name, source_ref):
        ClosureGiverNodeBase.__init__(
            self,
            name        = name,
            code_prefix = "module",
            source_ref  = source_ref
        )

        PythonModuleMixin.__init__(
            self,
            name         = name,
            package_name = package_name
        )

        ChildrenHavingMixin.__init__(
            self,
            values = {
                "body" : None # delayed
            },
        )

        self.variables = {}

        # The list functions contained in that module.
        self.functions = OrderedSet()

        self.active_functions = OrderedSet()
        self.cross_used_functions = OrderedSet()

        # SSA trace based information about the module.
        self.constraint_collection = None

        self.code_object = CodeObjectSpec(
            code_name     = "<module>" if self.isMainModule() else self.getName(),
            code_kind     = "Module",
            arg_names     = (),
            kw_only_count = 0,
            has_stardict  = False,
            has_starlist  = False,
        )

    def getCodeObject(self):
        return self.code_object

    def getDetails(self):
        return {
            "filename" : self.source_ref.getFilename(),
            "package"  : self.package_name,
            "name"     : self.name
        }

    def asXml(self):
        result = super(CompiledPythonModule, self).asXml()

        for function_body in self.active_functions:
            result.append(function_body.asXml())

        return result

    def asGraph(self, computation_counter):
        from graphviz import Digraph # @UnresolvedImport pylint: disable=F0401,I0021

        graph = Digraph("cluster_%d" % computation_counter, comment = "Graph for %s" % self.getName())
        graph.body.append("style=filled")
        graph.body.append("color=lightgrey")
        graph.body.append("label=Iteration_%d" % computation_counter)


        def makeTraceNodeName(variable_trace):
            return "%d/ %s %s %s" % (
                computation_counter,
                variable_trace.getVariable(),
                variable_trace.getVersion(),
                variable_trace.__class__.__name__
            )

        for function_body in self.active_functions:
            constraint_collection = function_body.constraint_collection

            for (_variable, _version), variable_trace in constraint_collection.getVariableTracesAll().items():
                node = makeTraceNodeName(variable_trace)

                previous = variable_trace.getPrevious()

                if variable_trace.hasDefiniteUsages():
                    graph.attr("node", style = "filled", color = "blue")
                elif variable_trace.hasPotentialUsages():
                    graph.attr("node", style = "filled", color = "yellow")
                else:
                    graph.attr("node", style = "filled", color = "red")

                graph.node(node)

                if type(previous) is tuple:
                    for previous in previous:
                        graph.edge(makeTraceNodeName(previous), node)
                elif previous is not None:
                    graph.edge(makeTraceNodeName(previous), node)

        return graph

    getBody = ChildrenHavingMixin.childGetter("body")
    setBody = ChildrenHavingMixin.childSetter("body")

    @staticmethod
    def isCompiledPythonModule():
        return True

    def getParent(self):
        assert False

    def getParentVariableProvider(self):
        return None

    def hasVariableName(self, variable_name):
        return variable_name in self.variables or variable_name in self.temp_variables

    def getVariables(self):
        return self.variables.values()

    def getFilename(self):
        return self.source_ref.getFilename()

    def getVariableForAssignment(self, variable_name):
        return self.getProvidedVariable(variable_name)

    def getVariableForReference(self, variable_name):
        return self.getProvidedVariable(variable_name)

    def getVariableForClosure(self, variable_name):
        return self.getProvidedVariable(
            variable_name = variable_name
        )

    def createProvidedVariable(self, variable_name):
        assert variable_name not in self.variables

        result = Variables.ModuleVariable(
            module        = self,
            variable_name = variable_name
        )

        self.variables[variable_name] = result

        return result

    @staticmethod
    def getContainingClassDictCreation():
        return None

    def isEarlyClosure(self):
        # Modules should immediately closure variables on use.
        # pylint: disable=R0201
        return True

    def getCodeName(self):
        def r(match):
            c = match.group()
            if c == '.':
                return '$'
            else:
                return "$$%d$" % ord(c)

        return "".join(
            re.sub("[^a-zA-Z0-9_]", r ,c)
            for c in
            self.getFullName()
        )

    def addFunction(self, function_body):
        assert function_body not in self.functions

        self.functions.add(function_body)

    def getFunctions(self):
        return self.functions

    def startTraversal(self):
        self.active_functions = OrderedSet()

    def addUsedFunction(self, function_body):
        assert function_body in self.functions

        assert function_body.isExpressionFunctionBody() or \
               function_body.isExpressionClassBody() or \
               function_body.isExpressionGeneratorObjectBody() or \
               function_body.isExpressionCoroutineObjectBody()

        if function_body not in self.active_functions:
            self.active_functions.add(function_body)

    def getUsedFunctions(self):
        return self.active_functions

    def getUnusedFunctions(self):
        for function in self.functions:
            if function not in self.active_functions:
                yield function

    def addCrossUsedFunction(self, function_body):
        if function_body not in self.cross_used_functions:
            self.cross_used_functions.add(function_body)

    def getCrossUsedFunctions(self):
        return self.cross_used_functions

    def getOutputFilename(self):
        main_filename = self.getFilename()

        if main_filename.endswith(".py"):
            result = main_filename[:-3]
        else:
            result = main_filename

        # There are some characters that somehow are passed to shell, by
        # Scons or unknown, so lets avoid them for now.
        return result.replace(')',"").replace('(',"")

    # TODO: Can't really use locals for modules, this should probably be made
    # sure to not be used.
    @staticmethod
    def getLocalsMode():
        return "copy"

    def computeModule(self):
        old_collection = self.constraint_collection

        self.constraint_collection = ConstraintCollectionModule(self)

        module_body = self.getBody()

        if module_body is not None:
            result = module_body.computeStatementsSequence(
                constraint_collection = self.constraint_collection
            )

            if result is not module_body:
                self.setBody(result)

        new_modules = self.attemptRecursion()

        for new_module in new_modules:
            self.constraint_collection.signalChange(
                source_ref = new_module.getSourceReference(),
                tags       = "new_code",
                message    = "Recursed to module package."
            )

        self.constraint_collection.updateFromCollection(old_collection)


    def getTraceCollections(self):
        yield self.constraint_collection

        for function in self.getUsedFunctions():
            yield function.constraint_collection