def _find_to_build(self): """ Helper for _build Returns list containing bool (is_package) and module_names Algorithm for finding distinct packages: 1) Take minimum package 2) Find related packages that start with this name 3) Add this to the list to return, then repeat steps 1 & 2 until no more packages exist """ builds = [] # Namespace packages can use / rather than dots. py_packages = [ ModuleName(m.replace("/", ".")) for m in sorted(set(self.compile_packages)) ] py_modules = [ModuleName(m) for m in sorted(set(self.py_modules))] for script_module_name in self.script_module_names: script_module_filename = locateModule( module_name=script_module_name, parent_package=None, level=0)[1] # Decide package or module. ( _main_added, is_package, _is_namespace, _source_ref, _source_filename, ) = decideModuleSourceRef( filename=script_module_filename, module_name=script_module_name, is_main=False, is_fake=False, logger=wheel_logger, ) if is_package: py_packages.append(script_module_name) else: py_modules.append(script_module_name) # Plain modules if they are not in packages to build. builds.extend((False, current_module) for current_module in py_modules if not current_module.hasOneOfNamespaces(py_packages)) while py_packages: current_package = min(py_packages) py_packages = [ p for p in py_packages if not p.hasNamespace(current_package) ] builds.append((True, current_package)) return builds
def main(): module_name = ModuleName(sys.argv[1]) setMainScriptDirectory(os.getcwd()) my_print(" ".join( locateModule(module_name=module_name, parent_package=None, level=0)))
def attemptRecursion(self): # Make sure the package is recursed to if any package_name = self.module_name.getPackageName() if package_name is None: return () # Return the list of newly added modules. package = getModuleByName(package_name) if package_name is not None and package is None: _package_name, package_filename, finding = locateModule( module_name=package_name, parent_package=None, level=0, ) # If we can't find the package for Python3.3 that is semi-OK, it might be in a # namespace package, these have no init code. if python_version >= 0x300 and not package_filename: return () if package_name == "uniconvertor.app.modules": return () assert package_filename is not None, (package_name, finding) _package_name, package_kind = getModuleNameAndKindFromFilename( package_filename ) # assert _package_name == self.package_name, (package_filename, _package_name, self.package_name) decision, _reason = decideRecursion( module_filename=package_filename, module_name=package_name, module_kind=package_kind, ) if decision is not None: package = recurseTo( signal_change=self.trace_collection.signalChange if hasattr(self, "trace_collection") else None, module_name=package_name, module_filename=package_filename, module_kind="py", reason="Containing package of '%s'." % self.getFullName(), ) if package: from nuitka.ModuleRegistry import addUsedModule addUsedModule( package, using_module=self, usage_tag="package", reason="Containing package of '%s'." % self.getFullName(), source_ref=self.source_ref, )
def _attemptFollow(self): found_module_name, found_module_filename, finding = locateModule( module_name=self.module_name, parent_package=None, level=0, ) if self.finding == "not-found": while True: module_name = found_module_filename.getPackageName() if module_name is None: break found_module_name, found_module_filename, finding = locateModule( module_name=module_name, parent_package=None, level=0, ) if self.finding != "not-found": break return found_module_name, found_module_filename, finding
def locateModule(module_name): """Provide a filename / -path for a to-be-imported module. Args: importing: module object that asked for it (tracing only) module_name: (str or ModuleName) full name of module Returns: filename for module """ from nuitka.importing.Importing import locateModule _module_name, module_filename, _finding = locateModule( module_name=ModuleName(module_name), parent_package=None, level=0) return module_filename
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
def __init__(self, module_name, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.module_name = ModuleName(module_name) self.finding = None self.module_filename = None _module_name, self.module_filename, self.finding = locateModule( module_name=self.module_name, parent_package=None, level=0, ) # Expect to find them and to match the name of course. assert self.finding != "not-found", self.module_name assert _module_name == self.module_name
def _attemptFollow(self, module_name): # Complex stuff, pylint: disable=too-many-branches parent_module = self.getParentModule() parent_package = parent_module.getFullName() if not parent_module.isCompiledPythonPackage(): parent_package = parent_package.getPackageName() level = self.subnode_level if level is None: level = 0 if parent_module.getFutureSpec().isAbsoluteImport( ) else -1 elif not level.isCompileTimeConstant(): return else: level = level.getCompileTimeConstant() # TODO: Catch this as a static error maybe. if type(level) not in (int, long): return None, None module_name, module_filename, self.finding = locateModule( module_name=resolveModuleName(module_name), parent_package=parent_package, level=level, ) if self.finding != "not-found": self.used_modules = [(module_name, module_filename, self.finding, level)] import_list = self.subnode_fromlist if import_list is not None: if import_list.isCompileTimeConstant(): import_list = import_list.getCompileTimeConstant() if type(import_list) not in (tuple, list): import_list = None if (module_filename is not None and import_list and isPackageDir(module_filename)): for import_item in import_list: if import_item == "*": continue ( name_import_module_name, name_import_module_filename, name_import_finding, ) = locateModule( module_name=ModuleName(import_item), parent_package=module_name, level=1, # Relative import ) if name_import_module_filename is not None: self.used_modules.append(( name_import_module_name, name_import_module_filename, name_import_finding, 1, )) return module_filename else: module_name = resolveModuleName(module_name) while True: module_name = module_name.getPackageName() if module_name is None: break module_name_found, module_filename, finding = locateModule( module_name=module_name, parent_package=parent_package, level=level, ) if module_filename is not None: self.used_modules = [(module_name_found, module_filename, finding, level)] return None
def _build(self, build_lib): # High complexity, pylint: disable=too-many-branches,too-many-locals # Nuitka wants the main package by filename, probably we should stop # needing that. old_dir = os.getcwd() os.chdir(build_lib) if self.distribution.package_dir and "" in self.distribution.package_dir: main_package_dir = self.distribution.package_dir.get("") else: main_package_dir = os.path.abspath(old_dir) # Search in the build directory preferably. setMainScriptDirectory(main_package_dir) for is_package, module_name in self._find_to_build(): module_name, main_filename, finding = locateModule( module_name=module_name, parent_package=None, level=0, ) package = module_name.getPackageName() # Check expectations, e.g. do not compile built-in modules. assert finding == "absolute", finding if package is not None: output_dir = os.path.join(build_lib, package.asPath()) else: output_dir = build_lib command = [ sys.executable, "-m", "nuitka", "--module", "--enable-plugin=pylint-warnings", "--output-dir=%s" % output_dir, "--nofollow-import-to=*.tests", "--remove-output", ] if is_package: command.append("--include-package=%s" % module_name) else: command.append("--include-module=%s" % module_name) toml_filename = os.environ.get("NUITKA_TOML_FILE") if toml_filename: # Import toml parser like "build" module does. try: from tomli import loads as toml_loads except ImportError: from toml import loads as toml_loads # Cannot use FileOperations.getFileContents() here, because of non-Nuitka process # pylint: disable=unspecified-encoding with open(toml_filename) as toml_file: toml_options = toml_loads(toml_file.read()) for option, value in toml_options.get("nuitka", {}).items(): command.extend(self._parseOptionsEntry(option, value)) # Process any extra options from setuptools if "nuitka" in self.distribution.command_options: for option, value in self.distribution.command_options[ "nuitka"].items(): command.extend(self._parseOptionsEntry(option, value)) command.append(main_filename) # Adding traces for clarity wheel_logger.info( "Building: '%s' with command %r" % (module_name.asString(), command), style="blue", ) check_call(command, cwd=build_lib) wheel_logger.info("Finished compilation of '%s'." % module_name.asString(), style="green") for root, _, filenames in os.walk(build_lib): for filename in filenames: fullpath = os.path.join(root, filename) if fullpath.lower().endswith( (".py", ".pyw", ".pyc", ".pyo")): os.unlink(fullpath) self.build_lib = build_lib os.chdir(old_dir)
def _build(self, build_lib): # High complexity, pylint: disable=too-many-branches,too-many-locals # Nuitka wants the main package by filename, probably we should stop # needing that. old_dir = os.getcwd() os.chdir(build_lib) # Search in the build directory preferably. setMainScriptDirectory(os.path.abspath(old_dir)) for is_package, module_name in self._find_to_build(): module_name, main_filename, finding = locateModule( module_name=module_name, parent_package=None, level=0, ) package = module_name.getPackageName() # Check expectations, e.g. do not compile built-in modules. assert finding == "absolute", finding if package is not None: output_dir = os.path.join(build_lib, package.asPath()) else: output_dir = build_lib command = [ sys.executable, "-m", "nuitka", "--module", "--enable-plugin=pylint-warnings", "--output-dir=%s" % output_dir, "--nofollow-import-to=*.tests", "--remove-output", ] if is_package: command.append("--include-package=%s" % module_name) else: command.append("--include-module=%s" % module_name) # Process any extra options from setuptools if "nuitka" in self.distribution.command_options: for option, value in self.distribution.command_options[ "nuitka"].items(): option = "--" + option.lstrip("-") if (type(value) is tuple and len(value) == 2 and value[0] == "setup.py"): value = value[1] if value is None: command.append(option) elif isinstance(value, bool): option = "--" + ("no" if not value else "") + option.lstrip("-") command.append(option) elif isinstance(value, Iterable) and not isinstance( value, (unicode, bytes, str)): for val in value: command.append("%s=%s" % (option, val)) else: command.append("%s=%s" % (option, value)) command.append(main_filename) # Adding traces for clarity wheel_logger.info( "Building: '%s' with command %r" % (module_name.asString(), command), style="blue", ) check_call(command, cwd=build_lib) wheel_logger.info("Finished compilation of '%s'." % module_name.asString(), style="green") for root, _, filenames in os.walk(build_lib): for filename in filenames: fullpath = os.path.join(root, filename) if fullpath.lower().endswith( (".py", ".pyw", ".pyc", ".pyo")): os.unlink(fullpath) self.build_lib = build_lib os.chdir(old_dir)