def onModuleEncounter(self, module_filename, module_name, module_kind): # Make sure if module_name.isBelowNamespace("webview.platforms"): if isWin32Windows(): result = module_name in ( "webview.platforms.winforms", "webview.platforms.edgechromium", "webview.platforms.edgehtml", "webview.platforms.mshtml", "webview.platforms.cef", ) reason = "Platforms package of webview used on '%s'." % getOS() elif isMacOS(): result = module_name == "webview.platforms.cocoa" reason = "Platforms package of webview used on '%s'." % getOS() elif getActiveQtPlugin() is not None: result = module_name = "webview.platforms.qt" reason = ("Platforms package of webview used due to '%s'." % getActiveQtPlugin()) else: result = module_name = "webview.platforms.gtk" reason = ( "Platforms package of webview used on '%s' without Qt plugin enabled." % getOS()) return result, reason
def _expandProjectArg(arg, filename_arg, for_eval): def wrap(value): if for_eval: return repr(value) else: return value values = { "OS": wrap(getOS()), "Arch": wrap(getArchitecture()), "Flavor": wrap(_getPythonFlavor()), "Version": getNuitkaVersion(), "Commercial": wrap(getCommercialVersion()), "MAIN_DIRECTORY": wrap(os.path.dirname(filename_arg) or "."), } if isLinux(): dist_info = getLinuxDistribution() else: dist_info = "N/A", "N/A", "0" values["Linux_Distribution_Name"] = dist_info[0] values["Linux_Distribution_Base"] = dist_info[1] or dist_info[0] values["Linux_Distribution_Version"] = dist_info[2] if getOS() == "Windows": values["WindowsRelease"] = getWindowsRelease() arg = arg.format(**values) return arg
def considerExtraDlls(self, dist_dir, module): full_name = module.getFullName() if full_name == "uuid" and getOS() == "Linux": uuid_dll_path = locateDLL("uuid") dist_dll_path = os.path.join(dist_dir, os.path.basename(uuid_dll_path)) shutil.copy(uuid_dll_path, dist_dll_path) return ((uuid_dll_path, dist_dll_path, None), ) elif full_name == "iptc" and getOS() == "Linux": import iptc.util # pylint: disable=I0021,import-error xtwrapper_dll = iptc.util.find_library("xtwrapper")[0] xtwrapper_dll_path = xtwrapper_dll._name # pylint: disable=protected-access dist_dll_path = os.path.join(dist_dir, os.path.basename(xtwrapper_dll_path)) shutil.copy(xtwrapper_dll_path, dist_dll_path) return ((xtwrapper_dll_path, dist_dll_path, None), ) return ()
def _getVersionInformationValues(): # TODO: Might be nice if we could delay version information computation # until it's actually used. yield getNuitkaVersion() yield "Commercial: %s" % getCommercialVersion() yield "Python: %s" % sys.version.split("\n", 1)[0] yield "Flavor: %s" % _getPythonFlavor() yield "Executable: %s" % sys.executable yield "OS: %s" % getOS() yield "Arch: %s" % getArchitecture() if isLinux(): dist_name, dist_base, dist_version = getLinuxDistribution() if dist_base is not None: yield "Distribution: %s (based on %s) %s" % ( dist_name, dist_base, dist_version, ) else: yield "Distribution: %s %s" % (dist_name, dist_version) if getOS() == "Windows": yield "WindowsRelease: %s" % getWindowsRelease()
def packDistFolderToOnefile(dist_dir, binary_filename): """Pack distribution to onefile, i.e. a single file that is directly executable.""" if getOS() == "Linux": packDistFolderToOnefileLinux(dist_dir, binary_filename) elif getOS() == "Windows": packDistFolderToOnefileWindows(dist_dir) else: general.warning("Onefile mode is not yet available on '%s'." % getOS())
def packDistFolderToOnefile(dist_dir, binary_filename): """Pack distribution to onefile, i.e. a single file that is directly executable.""" if getOS() == "Linux": packDistFolderToOnefileLinux(dist_dir, binary_filename) elif getOS() == "Windows": packDistFolderToOnefileWindows(dist_dir) else: postprocessing_logger.sysexit( "Onefile mode is not yet available on %r." % getOS() )
def packDistFolderToOnefile(dist_dir, binary_filename): """Pack distribution to onefile, i.e. a single file that is directly executable.""" onefile_output_filename = getResultFullpath(onefile=True) if getOS() == "Windows" or Options.isExperimental("onefile-bootstrap"): packDistFolderToOnefileBootstrap(onefile_output_filename, dist_dir) elif getOS() == "Linux": packDistFolderToOnefileLinux(onefile_output_filename, dist_dir, binary_filename) else: postprocessing_logger.sysexit( "Onefile mode is not yet available on %r." % getOS() ) Plugins.onOnefileFinished(onefile_output_filename)
def shallUseStaticLibPython(): """*bool* = "--static-libpython=yes|auto" Notes: Currently only Anaconda on non-Windows can do this and MSYS2. """ if options.static_libpython == "auto": if isWin32Windows() and os.path.exists( os.path.join(sys.prefix, "etc/config.site")): return True # For Anaconda default to trying static lib python library, which # normally is just not available or if it is even unusable. if (os.path.exists(os.path.join(sys.prefix, "conda-meta")) and not isWin32Windows() and not getOS() == "Darwin"): return True options.static_libpython = "no" if getSystemStaticLibPythonPath() is not None: Tracing.options_logger.info( "Detected static libpython as existing, consider using '--static-libpython=yes'." ) return options.static_libpython == "yes"
def _cleanupClangFormat(filename): """ Call clang-format on a given filename to format C code. Args: filename: What file to re-format. """ # Using global here, as this is really a singleton, in # the form of a module, pylint: disable=global-statement global warned_clang_format clang_format_path = getExecutablePath("clang-format-7") # Extra ball on Windows, check default installation PATH too. if not clang_format_path and getOS() == "Windows": with withEnvironmentPathAdded( "PATH", r"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\Llvm\8.0.0\bin", ): with withEnvironmentPathAdded("PATH", r"C:\Program Files\LLVM\bin"): clang_format_path = getExecutablePath("clang-format") if clang_format_path: subprocess.call([ clang_format_path, "-i", "-style={BasedOnStyle: llvm, IndentWidth: 4, ColumnLimit: 120}", filename, ]) else: if not warned_clang_format: warning("Need to install LLVM for C files format.") warned_clang_format = True
def _cleanupClangFormat(filename): # Using global here, as this is really a singleton, in # the form of a module, pylint: disable=global-statement global warned_clang_format clang_format_path = getExecutablePath("clang-format") # Extra ball on Windows, check default installation PATH too. if not clang_format_path and getOS() == "Windows": with withEnvironmentPathAdded("PATH", r"C:\Program Files\LLVM\bin"): clang_format_path = getExecutablePath("clang-format") if clang_format_path: subprocess.call( [ clang_format_path, "-i", "-style={BasedOnStyle: llvm, IndentWidth: 4, ColumnLimit: 120}", filename, ] ) else: if not warned_clang_format: warning("Need to install LLVM for C files format.") warned_clang_format = True
def _runOnefileScons(quiet): source_dir = OutputDirectories.getSourceDirectoryPath(onefile=True) SconsInterface.cleanSconsDirectory(source_dir) asBoolStr = SconsInterface.asBoolStr options = { "result_name": OutputDirectories.getResultBasepath(onefile=True), "result_exe": OutputDirectories.getResultFullpath(onefile=True), "source_dir": source_dir, "debug_mode": asBoolStr(Options.is_debug), "unstripped_mode": asBoolStr(Options.isUnstripped()), "experimental": ",".join(Options.getExperimentalIndications()), "trace_mode": asBoolStr(Options.shallTraceExecution()), "target_arch": getArchitecture(), "python_prefix": sys.prefix, "nuitka_src": SconsInterface.getSconsDataPath(), "compiled_exe": OutputDirectories.getResultFullpath(onefile=False), } SconsInterface.setCommonOptions(options) onefile_env_values = {} if Options.isWindowsOnefileTempDirMode() or getOS() != "Windows": onefile_env_values["ONEFILE_TEMP_SPEC"] = Options.getWindowsOnefileTempDirSpec( use_default=True ) else: # Merge version information if possible, to avoid collisions, or deep nesting # in file system. product_version = version_resources["ProductVersion"] file_version = version_resources["FileVersion"] if product_version != file_version: effective_version = "%s-%s" % (product_version, file_version) else: effective_version = file_version onefile_env_values["ONEFILE_COMPANY"] = version_resources["CompanyName"] onefile_env_values["ONEFILE_PRODUCT"] = version_resources["ProductName"] onefile_env_values["ONEFILE_VERSION"] = effective_version with withEnvironmentVarsOverriden(onefile_env_values): result = SconsInterface.runScons( options=options, quiet=quiet, scons_filename="WindowsOnefile.scons" ) # Exit if compilation failed. if not result: scons_logger.sysexit("Error, one file bootstrap build for Windows failed.") if Options.isRemoveBuildDir(): general.info("Removing onefile build directory %r." % source_dir) removeDirectory(path=source_dir, ignore_errors=False) assert not os.path.exists(source_dir) else: general.info("Keeping onefile build directory %r." % source_dir)
def getResultFullpath(onefile): """Get the final output binary result full path.""" result = getResultBasepath(onefile=onefile) if Options.shallMakeModule(): result += getSharedLibrarySuffix(preferred=True) else: output_filename = Options.getOutputFilename() if Options.isOnefileMode() and output_filename is not None: if onefile: result = output_filename else: result = os.path.join( getStandaloneDirectoryPath(), os.path.basename(output_filename), ) elif output_filename is not None: result = output_filename elif getOS() == "Windows": result += ".exe" elif (not Options.isStandaloneMode() or onefile and not Options.shallCreateAppBundle()): result += ".bin" return result
def getNumpyCoreBinaries(module): """Return any binaries in numpy/core and/or numpy/.libs. Notes: This covers the special cases like MKL binaries. Returns: tuple of abspaths of binaries. """ numpy_dir = module.getCompileTimeDirectory() numpy_core_dir = os.path.join(numpy_dir, "core") base_prefix = getSystemPrefixPath() binaries = [] # first look in numpy/.libs for binaries libdir = os.path.join(numpy_dir, ".libs" if getOS() != "Darwin" else ".dylibs") suffix_start = len(libdir) + 1 if os.path.isdir(libdir): dlls_pkg = os.listdir(libdir) binaries += [[os.path.join(libdir, f), suffix_start] for f in dlls_pkg] # then look for libraries in numpy.core package path # should already return the MKL files in ordinary cases re_anylib = re.compile(r"\w+\.(?:dll|so|dylib)", re.IGNORECASE) dlls_pkg = [f for f in os.listdir(numpy_core_dir) if re_anylib.match(f)] binaries += [[os.path.join(numpy_core_dir, f), suffix_start] for f in dlls_pkg] # Also look for MKL libraries in folder "above" numpy. # This should meet the layout of Anaconda installs. if isWin32Windows(): lib_dir = os.path.join(base_prefix, "Library", "bin") suffix_start = len(lib_dir) + 1 else: lib_dir = os.path.join(base_prefix, "lib") suffix_start = len(lib_dir) + 1 if not os.path.isdir(lib_dir): return binaries re_mkllib = re.compile(r"^(?:lib)?mkl\w+\.(?:dll|so|dylib)", re.IGNORECASE) for f in os.listdir(lib_dir): if isWin32Windows(): if not (f.startswith( ("libi", "libm", "mkl")) and f.endswith(".dll")): continue else: if not re_mkllib.match(f): continue binaries.append([os.path.join(lib_dir, f), suffix_start]) return binaries
def checkOnefileReadiness(assume_yes_for_downloads): if getOS() == "Linux": app_image_path = _getAppImageToolPath( for_operation=False, assume_yes_for_downloads=assume_yes_for_downloads ) return app_image_path is not None else: return hasOnefileSupportedOS()
def checkPythonVersionFromCode(source_code): # There is a lot of cases to consider, pylint: disable=too-many-branches shebang = getShebangFromSource(source_code) if shebang is not None: binary, _args = parseShebang(shebang) if getOS() != "Windows": try: if os.path.samefile(sys.executable, binary): return True except OSError: # Might not exist pass basename = os.path.basename(binary) # Not sure if we should do that. if basename == "python": result = python_version < 0x300 elif basename == "python3": result = python_version > 0x300 elif basename == "python2": result = python_version < 0x300 elif basename == "python2.7": result = python_version < 0x300 elif basename == "python2.6": result = python_version < 0x270 elif basename == "python3.2": result = 0x330 > python_version >= 0x300 elif basename == "python3.3": result = 0x340 > python_version >= 0x330 elif basename == "python3.4": result = 0x350 > python_version >= 0x340 elif basename == "python3.5": result = 0x360 > python_version >= 0x350 elif basename == "python3.6": result = 0x370 > python_version >= 0x360 elif basename == "python3.7": result = 0x380 > python_version >= 0x370 elif basename == "python3.8": result = 0x390 > python_version >= 0x380 elif basename == "python3.9": result = 0x3A0 > python_version >= 0x390 else: result = None if result is False: general.sysexit("""\ The program you compiled wants to be run with: %s. Nuitka is currently running with Python version '%s', which seems to not match that. Nuitka cannot guess the Python version of your source code. You therefore might want to specify: '%s -m nuitka'. That will make use the correct Python version for Nuitka. """ % (shebang, python_version_str, binary))
def checkPythonVersionFromCode(source_code): # There is a lot of cases to consider, pylint: disable=too-many-branches shebang = getShebangFromSource(source_code) if shebang is not None: binary, _args = parseShebang(shebang) if getOS() != "Windows": try: if os.path.samefile(sys.executable, binary): return True except OSError: # Might not exist pass basename = os.path.basename(binary) # Not sure if we should do that. if basename == "python": result = python_version < 300 elif basename == "python3": result = python_version > 300 elif basename == "python2": result = python_version < 300 elif basename == "python2.7": result = python_version < 300 elif basename == "python2.6": result = python_version < 270 elif basename == "python3.2": result = 330 > python_version >= 300 elif basename == "python3.3": result = 340 > python_version >= 330 elif basename == "python3.4": result = 350 > python_version >= 340 elif basename == "python3.5": result = 360 > python_version >= 350 elif basename == "python3.6": result = 370 > python_version >= 360 else: result = None if result is False: sys.exit( """\ The program you compiled wants to be run with: %s. Nuitka is currently running with Python version '%s', which seems to not match that. Nuitka cannot guess the Python version of your source code. You therefore might want to specify: '%s -m nuitka'. That will make use the correct Python version for Nuitka. """ % (shebang, python_version_str, binary) )
def relpath(path): """ Relative path, if possible. """ try: return os.path.relpath(path) except ValueError: # On Windows, paths on different devices prevent it to work. Use that # full path then. if getOS() == "Windows": return os.path.abspath(path) raise
def considerExtraDlls(self, dist_dir, module): full_name = module.getFullName() if getOS() == "Linux" and full_name == "uuid": uuid_dll_path = locateDLL("uuid") dist_dll_path = joinpath(dist_dir, basename(uuid_dll_path)) shutil.copy(uuid_dll_path, dist_dir) return ((dist_dll_path, None), ) return ()
def _pickCompressor(): if Options.isExperimental("zstd"): try: from zstd import ZSTD_compress # pylint: disable=I0021,import-error except ImportError: general.warning( "Onefile mode cannot compress without 'zstd' module on '%s'." % getOS() ) else: return b"Y", lambda data: ZSTD_compress(data, 9, getJobLimit()) else: return b"X", lambda data: data
def _getCcacheGuessedPaths(python_prefix): if isWin32Windows(): # Search the compiling Python, the Scons Python (likely the same, but not necessarily) # and then Anaconda, if an environment variable present from activated, or installed in # CI like Github actions. for python_dir in _getPythonDirCandidates(python_prefix): yield os.path.join(python_dir, "bin", "ccache.exe") yield os.path.join(python_dir, "scripts", "ccache.exe") elif getOS() == "Darwin": # For macOS, we might find Homebrew ccache installed but not in PATH. yield "/usr/local/opt/ccache"
def considerExtraDlls(self, dist_dir, module): full_name = module.getFullName() if full_name == "uuid" and getOS() == "Linux": uuid_dll_path = locateDLL("uuid") dist_dll_path = os.path.join(dist_dir, os.path.basename(uuid_dll_path)) shutil.copy(uuid_dll_path, dist_dll_path) return ((uuid_dll_path, dist_dll_path, None),) return ()
def packDistFolderToOnefileWindows(dist_dir): general.warning("Onefile mode is experimental on '%s'." % getOS()) postprocessing_logger.info( "Creating single file from dist folder, this may take a while.") onefile_output_filename = getResultFullpath(onefile=True) # First need to create the bootstrap binary for unpacking. _runOnefileScons(quiet=not Options.isShowScons()) # Make sure to copy the resources from the created binary to the bootstrap binary, these # are icons and version information. copyResourcesFromFileToFile( source_filename=getResultFullpath(onefile=False), target_filename=onefile_output_filename, resource_kinds=(RT_ICON, RT_GROUP_ICON, RT_VERSION), ) # Now need to append to payload it, potentially compressing it. compression_indicator, compressor = _pickCompressor() with open(onefile_output_filename, "ab") as output_file: # Seeking to end of file seems necessary on Python2 at least, maybe it's # just that tell reports wrong value initially. output_file.seek(0, 2) start_pos = output_file.tell() output_file.write(b"KA" + compression_indicator) # Move the binary to start immediately to the start position start_binary = getResultFullpath(onefile=False) file_list = getFileList(dist_dir) file_list.remove(start_binary) file_list.insert(0, start_binary) for filename_full in file_list: filename_relative = os.path.relpath(filename_full, dist_dir) filename_encoded = filename_relative.encode("utf-16le") + b"\0\0" output_file.write(filename_encoded) with open(filename_full, "rb") as input_file: compressed = compressor(input_file.read()) output_file.write(struct.pack("Q", len(compressed))) output_file.write(compressed) # Using empty filename as a terminator. output_file.write(b"\0\0") output_file.write(struct.pack("Q", start_pos))
def autoformat(filename, abort=False): filename = os.path.normpath(filename) my_print("Consider", filename, end=": ") old_code = getFileContents(filename) is_python = _isPythonFile(filename) is_c = filename.endswith((".c", ".h")) # Some parts of Nuitka must not be re-formatted with black or clang-format # as they have different intentions. if _shouldNotFormatCode(filename): is_python = is_c = False # Work on a temporary copy tmp_filename = filename + ".tmp" shutil.copy(filename, tmp_filename) try: if is_python: _cleanupPyLintComments(tmp_filename, abort) _cleanupImportSortOrder(tmp_filename) if is_python: black_call = _getPythonBinaryCall("black") subprocess.call(black_call + ["-q", tmp_filename]) elif is_c: _cleanupClangFormat(filename) else: _cleanupTrailingWhitespace(tmp_filename) if getOS() == "Windows": _cleanupWindowsNewlines(tmp_filename) changed = False if old_code != getFileContents(tmp_filename): my_print("Updated.") renameFile(tmp_filename, filename) changed = True else: my_print("OK.") return changed finally: if os.path.exists(tmp_filename): os.unlink(tmp_filename)
def getImplicitImports(self, module): # Dealing with OpenGL is a bit detailed, pylint: disable=too-many-branches if module.getFullName() == "OpenGL": opengl_infos = self.queryRuntimeInformationSingle( setup_codes="import OpenGL.plugins", value= "[(f.name, f.import_path) for f in OpenGL.plugins.FormatHandler.all()]", ) # TODO: Filter by name. for _name, import_path in opengl_infos: yield ModuleName(import_path).getPackageName() for line in getFileContentByLine(module.getCompileTimeFilename()): if line.startswith("PlatformPlugin("): os_part, plugin_name_part = line[15:-1].split(",") os_part = os_part.strip("' ") plugin_name_part = plugin_name_part.strip(") '") plugin_name_part = plugin_name_part[:plugin_name_part. rfind(".")] if os_part == "nt": if getOS() == "Windows": yield plugin_name_part elif os_part.startswith("linux"): if isLinux(): yield plugin_name_part elif os_part.startswith("darwin"): if isMacOS(): yield plugin_name_part elif os_part.startswith(("posix", "osmesa", "egl")): if getOS() != "Windows": yield plugin_name_part else: self.sysexit( "Undetected OS, please report bug for '%s'." % os_part)
def checkPythonVersionFromCode(source_code): # There is a lot of cases to consider, pylint: disable=R0912 shebang = getShebangFromSource(source_code) if shebang is not None: binary, _args = parseShebang(shebang) if getOS() != "Windows": try: if os.path.samefile(sys.executable, binary): return True except OSError: # Might not exist pass basename = os.path.basename(binary) # Not sure if we should do that. if basename == "python": result = python_version < 300 elif basename == "python3": result = python_version > 300 elif basename == "python2": result = python_version < 300 elif basename == "python2.7": result = python_version < 300 elif basename == "python2.6": result = python_version < 270 elif basename == "python3.2": result = python_version < 330 and python_version >= 300 elif basename == "python3.3": result = python_version < 340 and python_version >= 330 elif basename == "python3.4": result = python_version < 350 and python_version >= 340 elif basename == "python3.5": result = python_version < 360 and python_version >= 350 elif basename == "python3.6": result = python_version < 370 and python_version >= 360 else: result = None if result is False and Options.getIntendedPythonVersion() is None: sys.exit("""\ The program you compiled wants to be run with: %s. Nuitka is currently running with Python version '%s', which seems to not match that. Nuitka cannot guess the Python version of your source code. You therefore might want to specify '--python-version=' to make it clear. """ % (shebang, python_version_str))
def shallUseStaticLibPython(): """*bool* = derived from `sys.prefix` and `os.name` Notes: Currently only Anaconda on non-Windows can do this. """ if isWin32Windows() and os.path.exists( os.path.join(sys.prefix, "etc/config.site")): return True # For Anaconda default to trying static lib python library, which # normally is just not available or if it is even unusable. return (os.path.exists(os.path.join(sys.prefix, "conda-meta")) and not isWin32Windows() and not getOS() == "Darwin")
def getIconPaths(): """*list of str*, values of "--windows-icon-from-ico" and "--linux-onefile-icon """ result = options.icon_path # Check if Linux icon requirement is met. if getOS() == "Linux" and not result and isOnefileMode(): default_icon = "/usr/share/pixmaps/python.xpm" if os.path.exists(default_icon): result.append(default_icon) else: Tracing.general.sysexit("""\ Error, the default icon %r does not exist, making --linux-onefile-icon required.""" % default_icon) return result
def getResultFullpath(): """Get the final output binary result full path.""" result = getResultBasepath() if Options.shallMakeModule(): result += getSharedLibrarySuffix(preferred=True) else: if Options.getOutputFilename() is not None: result = Options.getOutputFilename() elif getOS() == "Windows": result += ".exe" elif not Options.isStandaloneMode(): result += ".bin" return result
def commentArgs(): default_reference_mode = ("runtime" if shallMakeModule() or isStandaloneMode() else "original") if getFileReferenceMode() is None: options.file_reference_mode = default_reference_mode else: if options.file_reference_mode != default_reference_mode: Tracing.options_logger.warning( "Using non-default file reference mode %r rather than %r may cause runtime issues." % (getFileReferenceMode(), default_reference_mode)) else: Tracing.options_logger.info( "Using default file reference mode %r need not be specified." % default_reference_mode) if getOS() != "Windows": if (getWindowsIconExecutablePath() or shallAskForWindowsAdminRights() or shallAskForWindowsUIAccessRights() or getWindowsCompanyName() or getWindowsProductName() or getWindowsProductVersion() or getWindowsFileVersion()): Tracing.options_logger.warning( "Using Windows specific options has no effect.") if isOnefileMode(): standalone_mode = "onefile" elif isStandaloneMode(): standalone_mode = "standalone" else: standalone_mode = None if options.recurse_all and standalone_mode: if standalone_mode: Tracing.options_logger.info( "Recursing all is the default for %s mode and need not be specified." % standalone_mode) if options.recurse_none and standalone_mode: if standalone_mode: Tracing.options_logger.warning( "Recursing none is unlikely to work for %s mode and should not be specified." % standalone_mode)
def getStandardLibraryPaths(): """ Get the standard library paths. """ # Using the function object to cache its result, avoiding global variable # usage. if not hasattr(getStandardLibraryPaths, "result"): os_filename = os.__file__ if os_filename.endswith(".pyc"): os_filename = os_filename[:-1] os_path = os.path.normcase(os.path.dirname(os_filename)) stdlib_paths = set([os_path]) # Happens for virtualenv situation, some modules will come from the link # this points to. if os.path.islink(os_filename): os_filename = os.readlink(os_filename) stdlib_paths.add(os.path.normcase(os.path.dirname(os_filename))) # Another possibility is "orig-prefix.txt" file near the os.py, which # points to the original install. orig_prefix_filename = os.path.join(os_path, "orig-prefix.txt") if os.path.isfile(orig_prefix_filename): # Scan upwards, until we find a "bin" folder, with "activate" to # locate the structural path to be added. We do not know for sure # if there is a sub-directory under "lib" to use or not. So we try # to detect it. search = os_path lib_part = "" while os.path.splitdrive(search)[1] not in (os.path.sep, ""): if os.path.isfile(os.path.join( search, "bin/activate")) or os.path.isfile( os.path.join(search, "scripts/activate")): break lib_part = os.path.join(os.path.basename(search), lib_part) search = os.path.dirname(search) assert search and lib_part with open(orig_prefix_filename) as f: stdlib_paths.add( os.path.normcase(os.path.join(f.read(), lib_part))) # And yet another possibility, for macOS Homebrew created virtualenv # at least is a link ".Python", which points to the original install. python_link_filename = os.path.join(os_path, "..", ".Python") if os.path.islink(python_link_filename): stdlib_paths.add( os.path.normcase( os.path.join(os.readlink(python_link_filename), "lib"))) for stdlib_path in set(stdlib_paths): candidate = os.path.join(stdlib_path, "lib-tk") if os.path.isdir(candidate): stdlib_paths.add(candidate) if getOS() == "Windows": import _ctypes stdlib_paths.add(os.path.dirname(_ctypes.__file__)) getStandardLibraryPaths.result = [ os.path.normcase(os.path.normpath(stdlib_path)) for stdlib_path in stdlib_paths ] return getStandardLibraryPaths.result
def getImplicitImports(self, module): # Many variables, branches, due to the many cases, pylint: disable=too-many-branches,too-many-statements full_name = module.getFullName() if module.isPythonShlibModule(): for used_module in module.getUsedModules(): yield used_module[0], False # TODO: Move this out to some kind of configuration format. elements = full_name.split(".") if elements[0] in ("PyQt4", "PyQt5"): if python_version < 300: yield "atexit", True # These are alternatives now: # TODO: One day it should avoid including both. yield "sip", False if elements[0] == "PyQt5": yield "PyQt5.sip", False child = elements[1] if len(elements) > 1 else None if child in ( "QtGui", "QtAssistant", "QtDBus", "QtDeclarative", "QtSql", "QtDesigner", "QtHelp", "QtNetwork", "QtScript", "QtQml", "QtScriptTools", "QtSvg", "QtTest", "QtWebKit", "QtOpenGL", "QtXml", "QtXmlPatterns", "QtPrintSupport", "QtNfc", "QtWebKitWidgets", "QtBluetooth", "QtMultimediaWidgets", "QtQuick", "QtWebChannel", "QtWebSockets", "QtX11Extras", "_QOpenGLFunctions_2_0", "_QOpenGLFunctions_2_1", "_QOpenGLFunctions_4_1_Core", ): yield elements[0] + ".QtCore", True if child in ( "QtDeclarative", "QtWebKit", "QtXmlPatterns", "QtQml", "QtPrintSupport", "QtWebKitWidgets", "QtMultimedia", "QtMultimediaWidgets", "QtQuick", "QtQuickWidgets", "QtWebSockets", ): yield elements[0] + ".QtNetwork", True if child == "QtScriptTools": yield elements[0] + ".QtScript", True if child in ( "QtWidgets", "QtDeclarative", "QtDesigner", "QtHelp", "QtScriptTools", "QtSvg", "QtTest", "QtWebKit", "QtPrintSupport", "QtWebKitWidgets", "QtMultimedia", "QtMultimediaWidgets", "QtOpenGL", "QtQuick", "QtQuickWidgets", "QtSql", "_QOpenGLFunctions_2_0", "_QOpenGLFunctions_2_1", "_QOpenGLFunctions_4_1_Core", ): yield elements[0] + ".QtGui", True if full_name in ( "PyQt5.QtDesigner", "PyQt5.QtHelp", "PyQt5.QtTest", "PyQt5.QtPrintSupport", "PyQt5.QtSvg", "PyQt5.QtOpenGL", "PyQt5.QtWebKitWidgets", "PyQt5.QtMultimediaWidgets", "PyQt5.QtQuickWidgets", "PyQt5.QtSql", ): yield "PyQt5.QtWidgets", True if full_name in ("PyQt5.QtPrintSupport",): yield "PyQt5.QtSvg", True if full_name in ("PyQt5.QtWebKitWidgets",): yield "PyQt5.QtWebKit", True yield "PyQt5.QtPrintSupport", True if full_name in ("PyQt5.QtMultimediaWidgets",): yield "PyQt5.QtMultimedia", True if full_name in ("PyQt5.QtQuick", "PyQt5.QtQuickWidgets"): yield "PyQt5.QtQml", True if full_name in ("PyQt5.QtQuickWidgets", "PyQt5.QtQml"): yield "PyQt5.QtQuick", True if full_name == "PyQt5.Qt": yield "PyQt5.QtCore", True yield "PyQt5.QtDBus", True yield "PyQt5.QtGui", True yield "PyQt5.QtNetwork", True yield "PyQt5.QtNetworkAuth", False yield "PyQt5.QtSensors", False yield "PyQt5.QtSerialPort", False yield "PyQt5.QtMultimedia", True yield "PyQt5.QtQml", False yield "PyQt5.QtWidgets", True elif full_name == "sip" and python_version < 300: yield "enum", False elif full_name == "PySide.QtDeclarative": yield "PySide.QtGui", True elif full_name == "PySide.QtHelp": yield "PySide.QtGui", True elif full_name == "PySide.QtOpenGL": yield "PySide.QtGui", True elif full_name == "PySide.QtScriptTools": yield "PySide.QtScript", True yield "PySide.QtGui", True elif full_name == "PySide.QtSql": yield "PySide.QtGui", True elif full_name == "PySide.QtSvg": yield "PySide.QtGui", True elif full_name == "PySide.QtTest": yield "PySide.QtGui", True elif full_name == "PySide.QtUiTools": yield "PySide.QtGui", True yield "PySide.QtXml", True elif full_name == "PySide.QtWebKit": yield "PySide.QtGui", True elif full_name == "PySide.phonon": yield "PySide.QtGui", True elif full_name == "lxml.etree": yield "gzip", True yield "lxml._elementpath", True elif full_name == "gtk._gtk": yield "pangocairo", True yield "pango", True yield "cairo", True yield "gio", True yield "atk", True elif full_name == "atk": yield "gobject", True elif full_name == "gtkunixprint": yield "gobject", True yield "cairo", True yield "gtk", True elif full_name == "pango": yield "gobject", True elif full_name == "pangocairo": yield "pango", True yield "cairo", True elif full_name == "reportlab.rl_config": yield "reportlab.rl_settings", True elif full_name == "socket": yield "_socket", False elif full_name == "ctypes": yield "_ctypes", True elif full_name == "gi._gi": yield "gi._error", True elif full_name == "gi._gi_cairo": yield "cairo", True elif full_name == "cairo._cairo": yield "gi._gobject", False elif full_name in ("Tkinter", "tkinter"): yield "_tkinter", False elif full_name in ( "cryptography.hazmat.bindings._openssl", "cryptography.hazmat.bindings._constant_time", "cryptography.hazmat.bindings._padding", ): yield "_cffi_backend", True elif full_name.startswith("cryptography._Cryptography_cffi_"): yield "_cffi_backend", True elif full_name == "bcrypt._bcrypt": yield "_cffi_backend", True elif full_name == "nacl._sodium": yield "_cffi_backend", True elif full_name == "_dbus_glib_bindings": yield "_dbus_bindings", True elif full_name == "_mysql": yield "_mysql_exceptions", True elif full_name == "lxml.objectify": yield "lxml.etree", True elif full_name == "_yaml": yield "yaml", True elif full_name == "apt_inst": yield "apt_pkg", True elif full_name == "numpy.core": yield "numpy.core._dtype_ctypes", False elif full_name == "scipy.special": yield "scipy.special._ufuncs_cxx", False elif full_name == "scipy.linalg": yield "scipy.linalg.cython_blas", False yield "scipy.linalg.cython_lapack", False elif full_name == "PIL._imagingtk": yield "PIL._tkinter_finder", True elif full_name == "pkg_resources.extern": if self.pkg_utils_externals is None: for line in getFileContentByLine(module.getCompileTimeFilename()): if line.startswith("names"): line = line.split("=")[-1].strip() parts = line.split(",") self.pkg_utils_externals = [part.strip("' ") for part in parts] break else: self.pkg_utils_externals = () for pkg_util_external in self.pkg_utils_externals: yield "pkg_resources._vendor." + pkg_util_external, False elif full_name == "pkg_resources._vendor.packaging": yield "pkg_resources._vendor.packaging.version", True yield "pkg_resources._vendor.packaging.specifiers", True yield "pkg_resources._vendor.packaging.requirements", True elif full_name == "uvloop.loop": yield "uvloop._noop", True elif full_name == "fitz.fitz": yield "fitz._fitz", True elif full_name == "pandas._libs": yield "pandas._libs.tslibs.np_datetime", False yield "pandas._libs.tslibs.nattype", False elif full_name == "pandas.core.window": yield "pandas._libs.skiplist", False elif full_name == "zmq.backend": yield "zmq.backend.cython", True elif full_name == "OpenGL": if self.opengl_plugins is None: self.opengl_plugins = [] for line in getFileContentByLine(module.getCompileTimeFilename()): if line.startswith("PlatformPlugin("): os_part, plugin_name_part = line[15:-1].split(",") os_part = os_part.strip("' ") plugin_name_part = plugin_name_part.strip(") '") plugin_name_part = plugin_name_part[ : plugin_name_part.rfind(".") ] if os_part == "nt": if getOS() == "Windows": self.opengl_plugins.append(plugin_name_part) elif os_part.startswith("linux"): if getOS() == "Linux": self.opengl_plugins.append(plugin_name_part) elif os_part.startswith("darwin"): if getOS() == "Darwin": self.opengl_plugins.append(plugin_name_part) elif os_part.startswith(("posix", "osmesa", "egl")): if getOS() != "Windows": self.opengl_plugins.append(plugin_name_part) else: assert False, os_part for opengl_plugin in self.opengl_plugins: yield opengl_plugin, True elif full_name == "Cryptodome.Util._raw_api": for module_name in ( "_raw_aes", "_raw_aesni", "_raw_arc2", "_raw_blowfish", "_raw_cast", "_raw_cbc", "_raw_cfb", "_raw_ctr", "_raw_des", "_raw_des3", "_raw_ecb", "_raw_ocb", "_raw_ofb", ): yield "Cryptodome.Cipher." + module_name, True elif full_name == "Cryptodome.Util.strxor": yield "Cryptodome.Util._strxor", True elif full_name == "Cryptodome.Util._cpu_features": yield "Cryptodome.Util._cpuid_c", True elif full_name == "Cryptodome.Hash.BLAKE2s": yield "Cryptodome.Hash._BLAKE2s", True elif full_name == "Cryptodome.Hash.SHA1": yield "Cryptodome.Hash._SHA1", True elif full_name == "Cryptodome.Hash.SHA256": yield "Cryptodome.Hash._SHA256", True elif full_name == "Cryptodome.Hash.MD5": yield "Cryptodome.Hash._MD5", True elif full_name == "Cryptodome.Protocol.KDF": yield "Cryptodome.Cipher._Salsa20", True yield "Cryptodome.Protocol._scrypt", True elif full_name == "Cryptodome.Cipher._mode_gcm": yield "Cryptodome.Hash._ghash_portable", True elif full_name == "pycparser.c_parser": yield "pycparser.yacctab", True yield "pycparser.lextab", True
def main(): goHome() parser = OptionParser() parser.add_option( "--upload", action="store_true", dest="upload", default=False, help="""\ Upload to http://nuitka.net/apidoc requires access rights and is done by the official servers automatically only. Without this, create the local html folder only. Default is %default.""", ) options, _positional_args = parser.parse_args() shutil.rmtree("html", ignore_errors=True) doxygen_path = getExecutablePath("doxygen") # Extra ball on Windows, check default installation PATH too. if not doxygen_path and getOS() == "Windows": with withEnvironmentPathAdded("PATH", r"C:\Program Files\Doxygen\bin"): doxygen_path = getExecutablePath("doxygen") if not doxygen_path: sys.exit("Error, need to install Doxygen and add it to PATH for this to work.") try: import doxypypy # @UnusedImport pylint: disable=I0021,unused-import,unused-variable except ImportError: sys.exit("Error, needs to install doxypypy into this Python.") with withTemporaryFile(suffix=".doxyfile", delete=False) as doxy_file: doxy_config = getFileContents("doc/Doxyfile.template") with withTemporaryFile( suffix=".bat" if getOS() == "Windows" else ".sh", delete=False ) as doxy_batch_file: if getOS() == "Windows": doxy_batch_file.write( "%s -m doxypypy.doxypypy -a -c %%1" % sys.executable ) else: doxy_batch_file.write( "#!/bin/sh\nexec '%s' -m doxypypy.doxypypy -a -c $1" % sys.executable ) doxy_batch_filename = doxy_batch_file.name doxy_config = doxy_config.replace("%DOXYPYPY%", doxy_batch_filename) doxy_file.write(doxy_config) doxy_filename = doxy_file.name print("Running doxygen:") try: subprocess.check_call([doxygen_path, doxy_filename]) finally: os.unlink(doxy_filename) os.unlink(doxy_batch_filename) # Update the repository on the web site. if options.upload: assert ( os.system( "rsync -avz --delete html/ --chown www-data [email protected]:/var/www/apidoc/" ) == 0 ) print("Finished.")
def getStandardLibraryPaths(): """ Get the standard library paths. """ # Using the function object to cache its result, avoiding global variable # usage. if not hasattr(getStandardLibraryPaths, "result"): os_filename = os.__file__ if os_filename.endswith(".pyc"): os_filename = os_filename[:-1] os_path = os.path.normcase(os.path.dirname(os_filename)) stdlib_paths = set([os_path]) # Happens for virtualenv situation, some modules will come from the link # this points to. if os.path.islink(os_filename): os_filename = os.readlink(os_filename) # @UndefinedVariable stdlib_paths.add(os.path.normcase(os.path.dirname(os_filename))) # Another possibility is "orig-prefix.txt" file near the os.py, which # points to the original install. orig_prefix_filename = os.path.join(os_path, "orig-prefix.txt") if os.path.isfile(orig_prefix_filename): # Scan upwards, until we find a "bin" folder, with "activate" to # locate the structural path to be added. We do not know for sure # if there is a sub-directory under "lib" to use or not. So we try # to detect it. search = os_path lib_part = "" while os.path.splitdrive(search)[1] not in (os.path.sep, ""): if os.path.isfile( os.path.join(search, "bin/activate") ) or os.path.isfile(os.path.join(search, "scripts/activate")): break lib_part = os.path.join(os.path.basename(search), lib_part) search = os.path.dirname(search) assert search and lib_part with open(orig_prefix_filename) as f: stdlib_paths.add(os.path.normcase(os.path.join(f.read(), lib_part))) # And yet another possibility, for macOS Homebrew created virtualenv # at least is a link ".Python", which points to the original install. python_link_filename = os.path.join(os_path, "..", ".Python") if os.path.islink(python_link_filename): stdlib_paths.add( os.path.normcase( os.path.join( os.readlink(python_link_filename), "lib" # @UndefinedVariable ) ) ) for stdlib_path in set(stdlib_paths): candidate = os.path.join(stdlib_path, "lib-tk") if os.path.isdir(candidate): stdlib_paths.add(candidate) if getOS() == "Windows": import _ctypes stdlib_paths.add(os.path.dirname(_ctypes.__file__)) getStandardLibraryPaths.result = [ os.path.normcase(os.path.normpath(stdlib_path)) for stdlib_path in stdlib_paths ] return getStandardLibraryPaths.result
parser.add_option_group(codegen_group) output_group = OptionGroup(parser, "Output choices") output_group.add_option( "-o", action="store", dest="output_filename", metavar="FILENAME", default=None, help="""\ Specify how the executable should be named. For extension modules there is no choice, also not for standalone mode and using it will be an error. This may include path information that needs to exist though. Defaults to '%s' on this platform. """ % "<program_name>" + (".exe" if getOS() == "Windows" else ".bin"), ) output_group.add_option( "--output-dir", action="store", dest="output_dir", metavar="DIRECTORY", default="", help="""\ Specify where intermediate and final output files should be put. The DIRECTORY will be populated with C files, object files, etc. Defaults to current directory. """, )
def getImplicitImports(self, module): # Many variables, branches, due to the many cases, pylint: disable=too-many-branches,too-many-statements full_name = module.getFullName() if module.isPythonShlibModule(): for used_module in module.getUsedModules(): yield used_module[0], False # TODO: Move this out to some kind of configuration format. elements = full_name.split('.') if elements[0] in ("PyQt4", "PyQt5"): if python_version < 300: yield "atexit", True # These are alternatives now: # TODO: One day it should avoid including both. yield "sip", False if elements[0] == "PyQt5": yield "PyQt5.sip", False child = elements[1] if len(elements) > 1 else None if child in ("QtGui", "QtAssistant", "QtDBus", "QtDeclarative", "QtSql", "QtDesigner", "QtHelp", "QtNetwork", "QtScript", "QtQml", "QtScriptTools", "QtSvg", "QtTest", "QtWebKit", "QtOpenGL", "QtXml", "QtXmlPatterns", "QtPrintSupport", "QtNfc", "QtWebKitWidgets", "QtBluetooth", "QtMultimediaWidgets", "QtQuick", "QtWebChannel", "QtWebSockets", "QtX11Extras", "_QOpenGLFunctions_2_0", "_QOpenGLFunctions_2_1", "_QOpenGLFunctions_4_1_Core"): yield elements[0] + ".QtCore", True if child in ("QtDeclarative", "QtWebKit", "QtXmlPatterns", "QtQml", "QtPrintSupport", "QtWebKitWidgets", "QtMultimedia", "QtMultimediaWidgets", "QtQuick", "QtQuickWidgets", "QtWebSockets"): yield elements[0] + ".QtNetwork", True if child == "QtScriptTools": yield elements[0] + ".QtScript", True if child in ("QtWidgets", "QtDeclarative", "QtDesigner", "QtHelp", "QtScriptTools", "QtSvg", "QtTest", "QtWebKit", "QtPrintSupport", "QtWebKitWidgets", "QtMultimedia", "QtMultimediaWidgets", "QtOpenGL", "QtQuick", "QtQuickWidgets", "QtSql", "_QOpenGLFunctions_2_0", "_QOpenGLFunctions_2_1", "_QOpenGLFunctions_4_1_Core"): yield elements[0] + ".QtGui", True if full_name in ("PyQt5.QtDesigner", "PyQt5.QtHelp", "PyQt5.QtTest", "PyQt5.QtPrintSupport", "PyQt5.QtSvg", "PyQt5.QtOpenGL", "PyQt5.QtWebKitWidgets", "PyQt5.QtMultimediaWidgets", "PyQt5.QtQuickWidgets", "PyQt5.QtSql"): yield "PyQt5.QtWidgets", True if full_name in ("PyQt5.QtPrintSupport", ): yield "PyQt5.QtSvg", True if full_name in ("PyQt5.QtWebKitWidgets", ): yield "PyQt5.QtWebKit", True yield "PyQt5.QtPrintSupport", True if full_name in ("PyQt5.QtMultimediaWidgets", ): yield "PyQt5.QtMultimedia", True if full_name in ("PyQt5.QtQuick", "PyQt5.QtQuickWidgets"): yield "PyQt5.QtQml", True if full_name in ("PyQt5.QtQuickWidgets", "PyQt5.QtQml"): yield "PyQt5.QtQuick", True if full_name == "PyQt5.Qt": yield "PyQt5.QtCore", True yield "PyQt5.QtDBus", True yield "PyQt5.QtGui", True yield "PyQt5.QtNetwork", True yield "PyQt5.QtNetworkAuth", False yield "PyQt5.QtSensors", False yield "PyQt5.QtSerialPort", False yield "PyQt5.QtMultimedia", True yield "PyQt5.QtQml", False yield "PyQt5.QtWidgets", True elif full_name == "sip" and python_version < 300: yield "enum", False elif full_name == "PySide.QtDeclarative": yield "PySide.QtGui", True elif full_name == "PySide.QtHelp": yield "PySide.QtGui", True elif full_name == "PySide.QtOpenGL": yield "PySide.QtGui", True elif full_name == "PySide.QtScriptTools": yield "PySide.QtScript", True yield "PySide.QtGui", True elif full_name == "PySide.QtSql": yield "PySide.QtGui", True elif full_name == "PySide.QtSvg": yield "PySide.QtGui", True elif full_name == "PySide.QtTest": yield "PySide.QtGui", True elif full_name == "PySide.QtUiTools": yield "PySide.QtGui", True yield "PySide.QtXml", True elif full_name == "PySide.QtWebKit": yield "PySide.QtGui", True elif full_name == "PySide.phonon": yield "PySide.QtGui", True elif full_name == "lxml.etree": yield "gzip", True yield "lxml._elementpath", True elif full_name == "gtk._gtk": yield "pangocairo", True yield "pango", True yield "cairo", True yield "gio", True yield "atk", True elif full_name == "atk": yield "gobject", True elif full_name == "gtkunixprint": yield "gobject", True yield "cairo", True yield "gtk", True elif full_name == "pango": yield "gobject", True elif full_name == "pangocairo": yield "pango", True yield "cairo", True elif full_name == "reportlab.rl_config": yield "reportlab.rl_settings", True elif full_name == "socket": yield "_socket", False elif full_name == "ctypes": yield "_ctypes", True elif full_name == "gi._gi": yield "gi._error", True elif full_name == "gi._gi_cairo": yield "cairo", True elif full_name == "cairo._cairo": yield "gi._gobject", False elif full_name in ("Tkinter", "tkinter"): yield "_tkinter", False elif full_name in ("cryptography.hazmat.bindings._openssl", "cryptography.hazmat.bindings._constant_time", "cryptography.hazmat.bindings._padding"): yield "_cffi_backend", True elif full_name.startswith("cryptography._Cryptography_cffi_"): yield "_cffi_backend", True elif full_name == "bcrypt._bcrypt": yield "_cffi_backend", True elif full_name == "nacl._sodium": yield "_cffi_backend", True elif full_name == "_dbus_glib_bindings": yield "_dbus_bindings", True elif full_name == "_mysql": yield "_mysql_exceptions", True elif full_name == "lxml.objectify": yield "lxml.etree", True elif full_name == "_yaml": yield "yaml", True elif full_name == "apt_inst": yield "apt_pkg", True elif full_name == "PIL._imagingtk": yield "PIL._tkinter_finder", True elif full_name == "pkg_resources.extern": if self.pkg_utils_externals is None: for line in open(module.getCompileTimeFilename()): if line.startswith("names"): line = line.split('=')[-1].strip() parts = line.split(',') self.pkg_utils_externals = [ part.strip("' ") for part in parts ] break else: self.pkg_utils_externals = () for pkg_util_external in self.pkg_utils_externals: yield "pkg_resources._vendor." + pkg_util_external, False elif full_name == "pkg_resources._vendor.packaging": yield "pkg_resources._vendor.packaging.version", True yield "pkg_resources._vendor.packaging.specifiers", True yield "pkg_resources._vendor.packaging.requirements", True elif full_name == "uvloop.loop": yield "uvloop._noop", True elif full_name == "fitz.fitz": yield "fitz._fitz", True elif full_name == "pandas._libs": yield "pandas._libs.tslibs.np_datetime", False yield "pandas._libs.tslibs.nattype", False elif full_name == "pandas.core.window": yield "pandas._libs.skiplist", False elif full_name == "zmq.backend": yield "zmq.backend.cython", True elif full_name == "OpenGL": if self.opengl_plugins is None: self.opengl_plugins = [] for line in open(module.getCompileTimeFilename()): if line.startswith("PlatformPlugin("): os_part, plugin_name_part = line[15:-1].split(',') os_part = os_part.strip("' ") plugin_name_part = plugin_name_part.strip(") '") plugin_name_part = plugin_name_part[:plugin_name_part. rfind('.')] if os_part == "nt": if getOS() == "Windows": self.opengl_plugins.append(plugin_name_part) elif os_part.startswith("linux"): if getOS() == "Linux": self.opengl_plugins.append(plugin_name_part) elif os_part.startswith("darwin"): if getOS() == "MacOS": self.opengl_plugins.append(plugin_name_part) elif os_part.startswith(("posix", "osmesa", "egl")): if getOS() != "Windows": self.opengl_plugins.append(plugin_name_part) else: assert False, os_part for opengl_plugin in self.opengl_plugins: yield opengl_plugin, True