Nuitka-winsvc 1.8.6__cp312-cp312-win_amd64.whl → 1.9.3__cp312-cp312-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {Nuitka_winsvc-1.8.6.dist-info → Nuitka_winsvc-1.9.3.dist-info}/METADATA +1 -1
- {Nuitka_winsvc-1.8.6.dist-info → Nuitka_winsvc-1.9.3.dist-info}/RECORD +212 -203
- {Nuitka_winsvc-1.8.6.dist-info → Nuitka_winsvc-1.9.3.dist-info}/WHEEL +1 -1
- nuitka/BytecodeCaching.py +4 -1
- nuitka/HardImportRegistry.py +348 -0
- nuitka/MainControl.py +45 -25
- nuitka/OptionParsing.py +31 -20
- nuitka/Options.py +47 -16
- nuitka/Progress.py +32 -2
- nuitka/PythonFlavors.py +1 -1
- nuitka/PythonVersions.py +61 -0
- nuitka/Tracing.py +25 -12
- nuitka/TreeXML.py +5 -5
- nuitka/Variables.py +15 -24
- nuitka/Version.py +16 -6
- nuitka/__main__.py +15 -0
- nuitka/__past__.py +15 -17
- nuitka/build/Backend.scons +44 -35
- nuitka/build/CCompilerVersion.scons +10 -9
- nuitka/build/Onefile.scons +11 -26
- nuitka/build/SconsCaching.py +2 -0
- nuitka/build/SconsCompilerSettings.py +72 -22
- nuitka/build/SconsHacks.py +1 -0
- nuitka/build/SconsInterface.py +5 -0
- nuitka/build/SconsSpawn.py +16 -3
- nuitka/build/SconsUtils.py +11 -12
- nuitka/build/include/nuitka/checksum_tools.h +0 -4
- nuitka/build/include/nuitka/compiled_asyncgen.h +1 -1
- nuitka/build/include/nuitka/compiled_coroutine.h +1 -1
- nuitka/build/include/nuitka/compiled_frame.h +7 -4
- nuitka/build/include/nuitka/compiled_function.h +13 -3
- nuitka/build/include/nuitka/compiled_generator.h +1 -1
- nuitka/build/include/nuitka/constants.h +2 -0
- nuitka/build/include/nuitka/environment_variables.h +45 -0
- nuitka/build/include/nuitka/exceptions.h +32 -4
- nuitka/build/include/nuitka/filesystem_paths.h +6 -1
- nuitka/build/include/nuitka/freelists.h +11 -1
- nuitka/build/include/nuitka/helper/dictionaries.h +1 -1
- nuitka/build/include/nuitka/helper/import_hard.h +3 -0
- nuitka/build/include/nuitka/helpers.h +2 -0
- nuitka/build/include/nuitka/importing.h +3 -0
- nuitka/build/include/nuitka/prelude.h +17 -6
- nuitka/build/include/nuitka/unfreezing.h +1 -1
- nuitka/build/inline_copy/bin/scons.py +14 -0
- nuitka/build/inline_copy/tqdm/tqdm/__init__.py +2 -2
- nuitka/build/inline_copy/tqdm/tqdm/utils.py +14 -8
- nuitka/build/inline_copy/zlib/LICENSE +22 -0
- nuitka/build/inline_copy/zlib/crc32.c +1049 -0
- nuitka/build/inline_copy/zlib/crc32.h +9446 -0
- nuitka/build/inline_copy/zlib/zconf.h +551 -0
- nuitka/build/inline_copy/zlib/zlib.h +1938 -0
- nuitka/build/inline_copy/zlib/zutil.h +275 -0
- nuitka/build/static_src/CompiledAsyncgenType.c +41 -41
- nuitka/build/static_src/CompiledCodeHelpers.c +14 -7
- nuitka/build/static_src/CompiledCoroutineType.c +60 -51
- nuitka/build/static_src/CompiledFrameType.c +12 -12
- nuitka/build/static_src/CompiledFunctionType.c +149 -28
- nuitka/build/static_src/CompiledGeneratorType.c +64 -65
- nuitka/build/static_src/CompiledGeneratorTypeUncompiledIntegration.c +1 -1
- nuitka/build/static_src/CompiledMethodType.c +5 -3
- nuitka/build/static_src/HelperEnvironmentVariables.c +120 -0
- nuitka/build/static_src/HelpersAttributes.c +1 -1
- nuitka/build/static_src/HelpersBuiltin.c +1 -1
- nuitka/build/static_src/HelpersChecksumTools.c +19 -4
- nuitka/build/static_src/HelpersComparisonEq.c +4 -4
- nuitka/build/static_src/HelpersComparisonNe.c +4 -4
- nuitka/build/static_src/HelpersConstantsBlob.c +40 -23
- nuitka/build/static_src/HelpersDictionaries.c +3 -1
- nuitka/build/static_src/HelpersDictionariesGenerated.c +9 -9
- nuitka/build/static_src/HelpersFilesystemPaths.c +12 -2
- nuitka/build/static_src/HelpersImport.c +29 -1
- nuitka/build/static_src/HelpersImportHard.c +19 -0
- nuitka/build/static_src/HelpersOperationInplaceAddUtils.c +5 -4
- nuitka/build/static_src/HelpersPythonPgo.c +5 -5
- nuitka/build/static_src/HelpersSafeStrings.c +2 -1
- nuitka/build/static_src/HelpersStrings.c +12 -10
- nuitka/build/static_src/HelpersTypes.c +1 -1
- nuitka/build/static_src/InspectPatcher.c +3 -2
- nuitka/build/static_src/MainProgram.c +182 -214
- nuitka/build/static_src/MetaPathBasedLoader.c +36 -23
- nuitka/build/static_src/MetaPathBasedLoaderImportlibMetadataDistribution.c +4 -2
- nuitka/build/static_src/MetaPathBasedLoaderResourceReaderFiles.c +38 -2
- nuitka/build/static_src/OnefileBootstrap.c +124 -93
- nuitka/code_generation/CodeGeneration.py +4 -2
- nuitka/code_generation/CodeObjectCodes.py +5 -1
- nuitka/code_generation/ConstantCodes.py +4 -0
- nuitka/code_generation/Contexts.py +111 -3
- nuitka/code_generation/DictCodes.py +5 -5
- nuitka/code_generation/FunctionCodes.py +4 -2
- nuitka/code_generation/GlobalConstants.py +10 -0
- nuitka/code_generation/ImportCodes.py +69 -33
- nuitka/code_generation/ModuleCodes.py +4 -1
- nuitka/code_generation/Namify.py +6 -5
- nuitka/code_generation/YieldCodes.py +3 -3
- nuitka/code_generation/templates/CodeTemplatesModules.py +61 -95
- nuitka/code_generation/templates_c/HelperDictionaryCopy.c.j2 +3 -3
- nuitka/code_generation/templates_c/HelperOperationComparisonUnicode.c.j2 +2 -2
- nuitka/distutils/DistutilCommands.py +3 -0
- nuitka/finalizations/FinalizeMarkups.py +1 -1
- nuitka/freezer/DependsExe.py +2 -1
- nuitka/freezer/DllDependenciesPosix.py +11 -1
- nuitka/freezer/IncludedEntryPoints.py +54 -16
- nuitka/freezer/Onefile.py +7 -3
- nuitka/freezer/Standalone.py +39 -17
- nuitka/importing/Importing.py +195 -62
- nuitka/importing/PreloadedPackages.py +2 -1
- nuitka/importing/Recursion.py +98 -27
- nuitka/importing/StandardLibrary.py +7 -4
- nuitka/nodes/BuiltinOpenNodes.py +28 -1
- nuitka/nodes/BuiltinRangeNodes.py +2 -2
- nuitka/nodes/BuiltinSumNodes.py +1 -1
- nuitka/nodes/ChildrenHavingMixins.py +326 -2
- nuitka/nodes/HardImportNodesGenerated.py +141 -38
- nuitka/nodes/ImportHardNodes.py +0 -8
- nuitka/nodes/ImportNodes.py +267 -361
- nuitka/nodes/IterationHandles.py +36 -17
- nuitka/nodes/LocalsScopes.py +3 -1
- nuitka/nodes/NodeBases.py +8 -14
- nuitka/nodes/OperatorNodes.py +9 -9
- nuitka/nodes/OutlineNodes.py +3 -3
- nuitka/nodes/PackageMetadataNodes.py +19 -9
- nuitka/nodes/SliceNodes.py +1 -1
- nuitka/nodes/VariableAssignNodes.py +25 -15
- nuitka/nodes/VariableRefNodes.py +7 -7
- nuitka/nodes/YieldNodes.py +2 -2
- nuitka/nodes/shapes/BuiltinTypeShapes.py +81 -6
- nuitka/nodes/shapes/ShapeMixins.py +21 -0
- nuitka/nodes/shapes/StandardShapes.py +9 -3
- nuitka/optimizations/OptimizeBuiltinCalls.py +1 -1
- nuitka/optimizations/TraceCollections.py +75 -0
- nuitka/pgo/PGO.py +14 -6
- nuitka/plugins/PluginBase.py +83 -11
- nuitka/plugins/Plugins.py +78 -35
- nuitka/plugins/standard/AntiBloatPlugin.py +46 -1
- nuitka/plugins/standard/ConsiderPyLintAnnotationsPlugin.py +1 -1
- nuitka/plugins/standard/DelvewheelPlugin.py +2 -1
- nuitka/plugins/standard/DillPlugin.py +3 -99
- nuitka/plugins/standard/DllFilesPlugin.py +45 -0
- nuitka/plugins/standard/GiPlugin.py +23 -10
- nuitka/plugins/standard/GlfwPlugin.py +1 -0
- nuitka/plugins/standard/ImplicitImports.py +267 -15
- nuitka/plugins/standard/KivyPlugin.py +1 -0
- nuitka/plugins/standard/MatplotlibPlugin.py +43 -25
- nuitka/plugins/standard/OptionsNannyPlugin.py +5 -6
- nuitka/plugins/standard/PkgResourcesPlugin.py +1 -1
- nuitka/plugins/standard/PmwPlugin.py +1 -1
- nuitka/plugins/standard/PySidePyQtPlugin.py +37 -20
- nuitka/plugins/standard/TkinterPlugin.py +44 -30
- nuitka/plugins/standard/TransformersPlugin.py +3 -1
- nuitka/plugins/standard/standard.nuitka-package.config.yml +522 -86
- nuitka/plugins/standard/stdlib3.nuitka-package.config.yml +8 -1
- nuitka/reports/CompilationReportReader.py +53 -0
- nuitka/reports/LicenseReport.rst.j2 +4 -4
- nuitka/reports/Reports.py +129 -47
- nuitka/specs/HardImportSpecs.py +6 -0
- nuitka/tools/data_composer/DataComposer.py +29 -17
- nuitka/tools/onefile_compressor/OnefileCompressor.py +173 -110
- nuitka/tools/podman/__main__.py +17 -2
- nuitka/tools/scanning/DisplayPackageDLLs.py +11 -2
- nuitka/tools/scanning/DisplayPackageData.py +1 -1
- nuitka/tools/specialize/CTypeDescriptions.py +36 -27
- nuitka/tools/specialize/SpecializeC.py +1 -1
- nuitka/tools/specialize/SpecializePython.py +16 -0
- nuitka/tools/testing/Common.py +3 -4
- nuitka/tools/testing/OutputComparison.py +23 -0
- nuitka/tools/testing/SearchModes.py +2 -2
- nuitka/tools/testing/compare_with_cpython/__main__.py +13 -4
- nuitka/tools/testing/measure_construct_performance/__main__.py +2 -5
- nuitka/tools/watch/__main__.py +194 -56
- nuitka/tree/Building.py +8 -2
- nuitka/tree/ComplexCallHelperFunctions.py +45 -15
- nuitka/tree/ReformulationAssignmentStatements.py +18 -12
- nuitka/tree/ReformulationCallExpressions.py +1 -1
- nuitka/tree/ReformulationClasses.py +11 -5
- nuitka/tree/ReformulationClasses3.py +30 -12
- nuitka/tree/ReformulationComparisonExpressions.py +4 -2
- nuitka/tree/ReformulationContractionExpressions.py +19 -11
- nuitka/tree/ReformulationDictionaryCreation.py +9 -3
- nuitka/tree/ReformulationExecStatements.py +6 -6
- nuitka/tree/ReformulationForLoopStatements.py +5 -5
- nuitka/tree/ReformulationFunctionStatements.py +6 -2
- nuitka/tree/ReformulationImportStatements.py +7 -2
- nuitka/tree/ReformulationLambdaExpressions.py +1 -1
- nuitka/tree/ReformulationMatchStatements.py +3 -1
- nuitka/tree/ReformulationNamespacePackages.py +7 -3
- nuitka/tree/ReformulationPrintStatements.py +1 -1
- nuitka/tree/ReformulationSequenceCreation.py +18 -6
- nuitka/tree/ReformulationWithStatements.py +8 -8
- nuitka/tree/ReformulationYieldExpressions.py +2 -2
- nuitka/tree/SourceHandling.py +27 -5
- nuitka/tree/VariableClosure.py +11 -1
- nuitka/utils/AppDirs.py +2 -2
- nuitka/utils/CStrings.py +39 -3
- nuitka/utils/CommandLineOptions.py +42 -1
- nuitka/utils/Distributions.py +305 -38
- nuitka/utils/Download.py +27 -8
- nuitka/utils/FileOperations.py +103 -20
- nuitka/utils/Hashing.py +2 -3
- nuitka/utils/Importing.py +60 -3
- nuitka/utils/InstalledPythons.py +31 -36
- nuitka/utils/Jinja2.py +11 -5
- nuitka/utils/ModuleNames.py +11 -3
- nuitka/utils/ReExecute.py +7 -0
- nuitka/utils/SharedLibraries.py +38 -14
- nuitka/utils/SlotMetaClasses.py +55 -0
- nuitka/utils/Utils.py +10 -0
- nuitka/utils/Yaml.py +9 -1
- nuitka/build/inline_copy/tqdm/tqdm/_tqdm_gui.py +0 -9
- nuitka/build/inline_copy/tqdm/tqdm/gui.py +0 -191
- {Nuitka_winsvc-1.8.6.data → Nuitka_winsvc-1.9.3.data}/scripts/nuitka-run.bat +0 -0
- {Nuitka_winsvc-1.8.6.data → Nuitka_winsvc-1.9.3.data}/scripts/nuitka.bat +0 -0
- {Nuitka_winsvc-1.8.6.dist-info → Nuitka_winsvc-1.9.3.dist-info}/LICENSE.txt +0 -0
- {Nuitka_winsvc-1.8.6.dist-info → Nuitka_winsvc-1.9.3.dist-info}/entry_points.txt +0 -0
- {Nuitka_winsvc-1.8.6.dist-info → Nuitka_winsvc-1.9.3.dist-info}/top_level.txt +0 -0
nuitka/utils/FileOperations.py
CHANGED
|
@@ -30,15 +30,16 @@ import glob
|
|
|
30
30
|
import os
|
|
31
31
|
import shutil
|
|
32
32
|
import stat
|
|
33
|
+
import sys
|
|
33
34
|
import tempfile
|
|
34
35
|
import time
|
|
35
36
|
from contextlib import contextmanager
|
|
36
37
|
|
|
37
38
|
from nuitka.__past__ import ( # pylint: disable=redefined-builtin
|
|
38
39
|
PermissionError,
|
|
39
|
-
WindowsError,
|
|
40
40
|
basestring,
|
|
41
41
|
raw_input,
|
|
42
|
+
unicode,
|
|
42
43
|
)
|
|
43
44
|
from nuitka.PythonVersions import python_version
|
|
44
45
|
from nuitka.Tracing import (
|
|
@@ -51,7 +52,13 @@ from nuitka.Tracing import (
|
|
|
51
52
|
|
|
52
53
|
from .Importing import importFromInlineCopy
|
|
53
54
|
from .ThreadedExecutor import RLock, getThreadIdent
|
|
54
|
-
from .Utils import
|
|
55
|
+
from .Utils import (
|
|
56
|
+
isLinux,
|
|
57
|
+
isMacOS,
|
|
58
|
+
isWin32OrPosixWindows,
|
|
59
|
+
isWin32Windows,
|
|
60
|
+
raiseWindowsError,
|
|
61
|
+
)
|
|
55
62
|
|
|
56
63
|
# Locking seems to be only required for Windows mostly, but we can keep
|
|
57
64
|
# it for all.
|
|
@@ -259,7 +266,9 @@ def getDirectoryRealPath(path):
|
|
|
259
266
|
path with symlinks resolved
|
|
260
267
|
|
|
261
268
|
Notes:
|
|
262
|
-
Workaround for Windows symlink is applied.
|
|
269
|
+
Workaround for Windows symlink is applied. This function is not recursive
|
|
270
|
+
at all with older Python, i.e. only the last part, the directory itself
|
|
271
|
+
is being resolved there.
|
|
263
272
|
|
|
264
273
|
"""
|
|
265
274
|
path = os.path.realpath(path)
|
|
@@ -272,6 +281,45 @@ def getDirectoryRealPath(path):
|
|
|
272
281
|
return path
|
|
273
282
|
|
|
274
283
|
|
|
284
|
+
def getFilenameRealPath(path):
|
|
285
|
+
"""Get os.path.realpath with Python2 and Windows symlink workaround applied.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
path: path to get realpath of
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
path with symlinks resolved
|
|
292
|
+
|
|
293
|
+
Notes:
|
|
294
|
+
Workaround for Windows symlinks are applied, this works recursive and
|
|
295
|
+
assumes that the path given itself is a file and not a directory, and
|
|
296
|
+
doesn't handle file symlinks at the end on older Python currently, but
|
|
297
|
+
we shouldn't deal with those.
|
|
298
|
+
"""
|
|
299
|
+
path = os.path.realpath(path)
|
|
300
|
+
|
|
301
|
+
# Attempt to resolve Windows symlinks older Python
|
|
302
|
+
if os.name == "nt":
|
|
303
|
+
path = path.strip(os.path.sep)
|
|
304
|
+
|
|
305
|
+
if os.path.sep in path:
|
|
306
|
+
dirname = os.path.dirname(path)
|
|
307
|
+
filename = os.path.basename(path)
|
|
308
|
+
|
|
309
|
+
if dirname:
|
|
310
|
+
dirname = getDirectoryRealPath(dirname)
|
|
311
|
+
|
|
312
|
+
# Drive letters do not get slashes from "os.path.join", so
|
|
313
|
+
# we inject this here and normalize the path afterwards to
|
|
314
|
+
# remove any duplication added.
|
|
315
|
+
if os.path.sep not in dirname:
|
|
316
|
+
dirname = dirname + os.path.sep
|
|
317
|
+
|
|
318
|
+
return os.path.normpath(os.path.join(dirname, filename))
|
|
319
|
+
|
|
320
|
+
return path
|
|
321
|
+
|
|
322
|
+
|
|
275
323
|
def listDir(path):
|
|
276
324
|
"""Give a sorted listing of a path.
|
|
277
325
|
|
|
@@ -293,8 +341,28 @@ def listDir(path):
|
|
|
293
341
|
"""
|
|
294
342
|
real_path = getDirectoryRealPath(path)
|
|
295
343
|
|
|
344
|
+
# The "os.listdir" output needs to be unicode paths, or else it can be unusable
|
|
345
|
+
# for Python2 on Windows at least. We try to go back on the result.
|
|
346
|
+
if str is bytes and type(real_path) is str:
|
|
347
|
+
real_path = unicode(real_path)
|
|
348
|
+
|
|
349
|
+
def _tryDecodeToStr(value):
|
|
350
|
+
if str is bytes:
|
|
351
|
+
if type(value) is unicode:
|
|
352
|
+
# File system paths, that should be usable for names of modules,
|
|
353
|
+
# as Python2 code objects will e.g. hate unicode values.
|
|
354
|
+
|
|
355
|
+
# spell-checker: ignore getfilesystemencoding
|
|
356
|
+
try:
|
|
357
|
+
return value.decode(sys.getfilesystemencoding())
|
|
358
|
+
except UnicodeDecodeError:
|
|
359
|
+
return value
|
|
360
|
+
else:
|
|
361
|
+
return value
|
|
362
|
+
|
|
296
363
|
return sorted(
|
|
297
|
-
|
|
364
|
+
(_tryDecodeToStr(os.path.join(path, filename)), _tryDecodeToStr(filename))
|
|
365
|
+
for filename in os.listdir(real_path)
|
|
298
366
|
)
|
|
299
367
|
|
|
300
368
|
|
|
@@ -577,11 +645,19 @@ def deleteFile(path, must_exist):
|
|
|
577
645
|
raise OSError("Does not exist", path)
|
|
578
646
|
|
|
579
647
|
|
|
580
|
-
def
|
|
581
|
-
"""
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
648
|
+
def searchPrefixPath(path, element):
|
|
649
|
+
"""Search element and return prefix in path, if any."""
|
|
650
|
+
|
|
651
|
+
while path:
|
|
652
|
+
if os.path.normcase(os.path.basename(path)) == os.path.normcase(element):
|
|
653
|
+
return path
|
|
654
|
+
|
|
655
|
+
new_path = os.path.dirname(path)
|
|
656
|
+
if new_path == path:
|
|
657
|
+
break
|
|
658
|
+
path = new_path
|
|
659
|
+
|
|
660
|
+
return None
|
|
585
661
|
|
|
586
662
|
|
|
587
663
|
def getFilenameExtension(path):
|
|
@@ -977,6 +1053,10 @@ def isFilenameBelowPath(path, filename, consider_short=True):
|
|
|
977
1053
|
filename = getExternalUsePath(filename)
|
|
978
1054
|
path = getExternalUsePath(path)
|
|
979
1055
|
|
|
1056
|
+
if isWin32Windows():
|
|
1057
|
+
if getWindowsDrive(path) != getWindowsDrive(filename):
|
|
1058
|
+
return False
|
|
1059
|
+
|
|
980
1060
|
result = os.path.relpath(filename, path).split(os.path.sep)[0] != ".."
|
|
981
1061
|
|
|
982
1062
|
return result
|
|
@@ -1021,10 +1101,7 @@ def getWindowsShortPathName(filename):
|
|
|
1021
1101
|
if ctypes.GetLastError() == 5:
|
|
1022
1102
|
return filename
|
|
1023
1103
|
|
|
1024
|
-
|
|
1025
|
-
ctypes.GetLastError(), ctypes.FormatError(ctypes.GetLastError())
|
|
1026
|
-
)
|
|
1027
|
-
|
|
1104
|
+
raiseWindowsError("getWindowsShortPathName for %s" % filename)
|
|
1028
1105
|
if output_buf_size >= needed:
|
|
1029
1106
|
# Short paths should be ASCII. Don't return unicode without a need,
|
|
1030
1107
|
# as e.g. Scons hates that in environment variables.
|
|
@@ -1068,10 +1145,7 @@ def getWindowsLongPathName(filename):
|
|
|
1068
1145
|
if ctypes.GetLastError() == 5:
|
|
1069
1146
|
return filename
|
|
1070
1147
|
|
|
1071
|
-
|
|
1072
|
-
ctypes.GetLastError(), ctypes.FormatError(ctypes.GetLastError())
|
|
1073
|
-
)
|
|
1074
|
-
|
|
1148
|
+
raiseWindowsError("getWindowsLongPathName for %s" % filename)
|
|
1075
1149
|
if output_buf_size >= needed:
|
|
1076
1150
|
return output_buf.value
|
|
1077
1151
|
else:
|
|
@@ -1097,6 +1171,8 @@ def getExternalUsePath(filename, only_dirname=False):
|
|
|
1097
1171
|
|
|
1098
1172
|
if os.name == "nt":
|
|
1099
1173
|
if filename not in _external_use_path_cache:
|
|
1174
|
+
filename = getFilenameRealPath(filename)
|
|
1175
|
+
|
|
1100
1176
|
asked_filename = filename
|
|
1101
1177
|
|
|
1102
1178
|
if only_dirname:
|
|
@@ -1202,6 +1278,10 @@ def getLinkTarget(filename):
|
|
|
1202
1278
|
return is_link, filename
|
|
1203
1279
|
|
|
1204
1280
|
|
|
1281
|
+
# Late import and optional to be there.
|
|
1282
|
+
atomicwrites = None
|
|
1283
|
+
|
|
1284
|
+
|
|
1205
1285
|
def replaceFileAtomic(source_path, dest_path):
|
|
1206
1286
|
"""
|
|
1207
1287
|
Move ``src`` to ``dst``. If ``dst`` exists, it will be silently
|
|
@@ -1216,9 +1296,12 @@ def replaceFileAtomic(source_path, dest_path):
|
|
|
1216
1296
|
if python_version >= 0x300:
|
|
1217
1297
|
os.replace(source_path, dest_path)
|
|
1218
1298
|
else:
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1299
|
+
global atomicwrites # singleton, pylint: disable=global-statement
|
|
1300
|
+
|
|
1301
|
+
if atomicwrites is None:
|
|
1302
|
+
atomicwrites = importFromInlineCopy("atomicwrites", must_exist=True)
|
|
1303
|
+
|
|
1304
|
+
atomicwrites.replace_atomic(source_path, dest_path)
|
|
1222
1305
|
|
|
1223
1306
|
|
|
1224
1307
|
def resolveShellPatternToFilenames(pattern):
|
nuitka/utils/Hashing.py
CHANGED
|
@@ -21,10 +21,9 @@ Offers support for hashing incrementally and files esp. without having
|
|
|
21
21
|
to read their contents.
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
import hashlib
|
|
25
24
|
from binascii import crc32
|
|
26
25
|
|
|
27
|
-
from nuitka.__past__ import unicode
|
|
26
|
+
from nuitka.__past__ import md5, unicode
|
|
28
27
|
|
|
29
28
|
from .FileOperations import openTextFile
|
|
30
29
|
|
|
@@ -64,7 +63,7 @@ class HashBase(object):
|
|
|
64
63
|
|
|
65
64
|
class Hash(HashBase):
|
|
66
65
|
def __init__(self):
|
|
67
|
-
self.hash =
|
|
66
|
+
self.hash = md5()
|
|
68
67
|
|
|
69
68
|
def updateFromBytes(self, value):
|
|
70
69
|
self.hash.update(value)
|
nuitka/utils/Importing.py
CHANGED
|
@@ -26,6 +26,7 @@ import sys
|
|
|
26
26
|
from nuitka.PythonVersions import python_version
|
|
27
27
|
from nuitka.Tracing import general
|
|
28
28
|
|
|
29
|
+
from .ModuleNames import ModuleName
|
|
29
30
|
from .Utils import withNoDeprecationWarning
|
|
30
31
|
|
|
31
32
|
|
|
@@ -163,7 +164,7 @@ def _importFromFolder(logger, module_name, path, must_exist, message):
|
|
|
163
164
|
del sys.path[0]
|
|
164
165
|
|
|
165
166
|
|
|
166
|
-
def importFromInlineCopy(module_name, must_exist):
|
|
167
|
+
def importFromInlineCopy(module_name, must_exist, delete_module=False):
|
|
167
168
|
"""Import a module from the inline copy stage."""
|
|
168
169
|
|
|
169
170
|
folder_name = os.path.normpath(
|
|
@@ -181,7 +182,7 @@ def importFromInlineCopy(module_name, must_exist):
|
|
|
181
182
|
elif python_version < 0x360 and os.path.exists(candidate_35):
|
|
182
183
|
folder_name = candidate_35
|
|
183
184
|
|
|
184
|
-
|
|
185
|
+
module = _importFromFolder(
|
|
185
186
|
module_name=module_name,
|
|
186
187
|
path=folder_name,
|
|
187
188
|
must_exist=must_exist,
|
|
@@ -189,6 +190,11 @@ def importFromInlineCopy(module_name, must_exist):
|
|
|
189
190
|
logger=general,
|
|
190
191
|
)
|
|
191
192
|
|
|
193
|
+
if delete_module and module_name in sys.modules:
|
|
194
|
+
del sys.modules[module_name]
|
|
195
|
+
|
|
196
|
+
return module
|
|
197
|
+
|
|
192
198
|
|
|
193
199
|
_compile_time_modules = {}
|
|
194
200
|
|
|
@@ -224,7 +230,30 @@ def isBuiltinModuleName(module_name):
|
|
|
224
230
|
else:
|
|
225
231
|
import _imp
|
|
226
232
|
|
|
227
|
-
|
|
233
|
+
result = _imp.is_builtin(module_name) or _imp.is_frozen(module_name)
|
|
234
|
+
|
|
235
|
+
# Some frozen modules are not actually in that list, e.g.
|
|
236
|
+
# "importlib._bootstrap_external" on Python3.10 doesn't report to
|
|
237
|
+
# "_imp.is_frozen()" above, so we check if it's already loaded and from the
|
|
238
|
+
# "FrozenImporter" by name.
|
|
239
|
+
if result is False and module_name in sys.modules:
|
|
240
|
+
module = sys.modules[module_name]
|
|
241
|
+
|
|
242
|
+
if hasattr(module, "__loader__"):
|
|
243
|
+
loader = module.__loader__
|
|
244
|
+
|
|
245
|
+
try:
|
|
246
|
+
result = loader.__name__ == "FrozenImporter"
|
|
247
|
+
except AttributeError:
|
|
248
|
+
pass
|
|
249
|
+
|
|
250
|
+
return result
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# Have a set for quicker lookups, and we cannot have "__main__" in there.
|
|
254
|
+
builtin_module_names = set(
|
|
255
|
+
module_name for module_name in sys.builtin_module_names if module_name != "__main__"
|
|
256
|
+
)
|
|
228
257
|
|
|
229
258
|
|
|
230
259
|
def getModuleFilenameSuffixes():
|
|
@@ -251,3 +280,31 @@ def getModuleFilenameSuffixes():
|
|
|
251
280
|
yield suffix, "PY_SOURCE"
|
|
252
281
|
for suffix in importlib.machinery.BYTECODE_SUFFIXES:
|
|
253
282
|
yield suffix, "PY_COMPILED"
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def getModuleNameAndKindFromFilenameSuffix(module_filename):
|
|
286
|
+
"""Given a filename, decide the module name and kind.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
module_name - file path of the module
|
|
290
|
+
Returns:
|
|
291
|
+
Tuple with the name of the module basename, and the kind of the
|
|
292
|
+
module derived from the file suffix. Can be None, None if is is not a
|
|
293
|
+
known file suffix.
|
|
294
|
+
Notes:
|
|
295
|
+
This doesn't handle packages at all.
|
|
296
|
+
"""
|
|
297
|
+
if module_filename.endswith(".py"):
|
|
298
|
+
return ModuleName(os.path.basename(module_filename)[:-3]), "py"
|
|
299
|
+
|
|
300
|
+
if module_filename.endswith(".pyc"):
|
|
301
|
+
return ModuleName(os.path.basename(module_filename)[:-4]), "pyc"
|
|
302
|
+
|
|
303
|
+
for suffix in getSharedLibrarySuffixes():
|
|
304
|
+
if module_filename.endswith(suffix):
|
|
305
|
+
return (
|
|
306
|
+
ModuleName(os.path.basename(module_filename)[: -len(suffix)]),
|
|
307
|
+
"extension",
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return None, None
|
nuitka/utils/InstalledPythons.py
CHANGED
|
@@ -20,9 +20,12 @@
|
|
|
20
20
|
import os
|
|
21
21
|
import sys
|
|
22
22
|
|
|
23
|
-
from nuitka.__past__ import WindowsError # pylint: disable=I0021,redefined-builtin
|
|
24
23
|
from nuitka.containers.OrderedSets import OrderedSet
|
|
25
|
-
from nuitka.
|
|
24
|
+
from nuitka.PythonFlavors import isAnacondaPython, isMSYS2MingwPython
|
|
25
|
+
from nuitka.PythonVersions import (
|
|
26
|
+
getInstalledPythonRegistryPaths,
|
|
27
|
+
python_version_str,
|
|
28
|
+
)
|
|
26
29
|
|
|
27
30
|
from .Execution import (
|
|
28
31
|
NuitkaCalledProcessError,
|
|
@@ -55,11 +58,34 @@ class InstalledPython(object):
|
|
|
55
58
|
return int(major) * 256 + int(minor) * 16
|
|
56
59
|
|
|
57
60
|
def isAnacondaPython(self):
|
|
58
|
-
|
|
61
|
+
if self.python_exe == sys.executable:
|
|
62
|
+
return isAnacondaPython()
|
|
63
|
+
|
|
64
|
+
# TODO: May not yet work really.
|
|
59
65
|
return os.path.exists(
|
|
60
66
|
os.path.join(os.path.dirname(self.python_exe), "..", "conda-meta")
|
|
61
67
|
)
|
|
62
68
|
|
|
69
|
+
def isMSYS2MingwPython(self):
|
|
70
|
+
if self.python_exe == sys.executable:
|
|
71
|
+
return isMSYS2MingwPython()
|
|
72
|
+
|
|
73
|
+
# TODO: May not yet work really.
|
|
74
|
+
return (
|
|
75
|
+
os.path.exists(
|
|
76
|
+
os.path.join(os.path.dirname(self.python_exe), "..", "..", "msys2.ini")
|
|
77
|
+
)
|
|
78
|
+
and os.path.basename(os.path.dirname(self.python_exe)) == "mingw64"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def getPreferredPackageType(self):
|
|
82
|
+
if self.isAnacondaPython():
|
|
83
|
+
return "conda"
|
|
84
|
+
elif self.isMSYS2MingwPython():
|
|
85
|
+
return "pacman"
|
|
86
|
+
else:
|
|
87
|
+
return "pip"
|
|
88
|
+
|
|
63
89
|
# Necessary for Python 2.7, otherwise SyntaxError is given on exec.
|
|
64
90
|
@staticmethod
|
|
65
91
|
def _exec(code, context):
|
|
@@ -124,38 +150,6 @@ class InstalledPython(object):
|
|
|
124
150
|
_installed_pythons = {}
|
|
125
151
|
|
|
126
152
|
|
|
127
|
-
def getInstalledPythonRegistryPaths(python_version):
|
|
128
|
-
"""Yield all Pythons as found in the Windows registry."""
|
|
129
|
-
# Windows only code, pylint: disable=I0021,import-error,undefined-variable
|
|
130
|
-
if str is bytes:
|
|
131
|
-
import _winreg as winreg # pylint: disable=I0021,import-error,no-name-in-module
|
|
132
|
-
else:
|
|
133
|
-
import winreg # pylint: disable=I0021,import-error,no-name-in-module
|
|
134
|
-
|
|
135
|
-
for hkey_branch in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER):
|
|
136
|
-
for arch_key in (0, winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY):
|
|
137
|
-
for suffix in "", "-32", "-arm64":
|
|
138
|
-
try:
|
|
139
|
-
key = winreg.OpenKey(
|
|
140
|
-
hkey_branch,
|
|
141
|
-
r"SOFTWARE\Python\PythonCore\%s%s\InstallPath"
|
|
142
|
-
% (python_version, suffix),
|
|
143
|
-
0,
|
|
144
|
-
winreg.KEY_READ | arch_key,
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
install_dir = os.path.normpath(winreg.QueryValue(key, ""))
|
|
148
|
-
except WindowsError:
|
|
149
|
-
pass
|
|
150
|
-
else:
|
|
151
|
-
candidate = os.path.normpath(
|
|
152
|
-
os.path.join(install_dir, "python.exe")
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
if os.path.exists(candidate):
|
|
156
|
-
yield candidate
|
|
157
|
-
|
|
158
|
-
|
|
159
153
|
def _getPythonInstallPathsWindows(python_version):
|
|
160
154
|
"""Find Python installation on Windows.
|
|
161
155
|
|
|
@@ -181,7 +175,7 @@ def _getPythonInstallPathsWindows(python_version):
|
|
|
181
175
|
|
|
182
176
|
seen.add(candidate)
|
|
183
177
|
|
|
184
|
-
for candidate in getInstalledPythonRegistryPaths(python_version
|
|
178
|
+
for candidate in getInstalledPythonRegistryPaths(python_version):
|
|
185
179
|
if candidate not in seen:
|
|
186
180
|
seen.add(candidate)
|
|
187
181
|
yield candidate
|
|
@@ -211,6 +205,7 @@ def findPythons(python_version):
|
|
|
211
205
|
result.add(InstalledPython(python_exe=candidate, python_version=python_version))
|
|
212
206
|
|
|
213
207
|
_installed_pythons[python_version] = result
|
|
208
|
+
|
|
214
209
|
return result
|
|
215
210
|
|
|
216
211
|
|
nuitka/utils/Jinja2.py
CHANGED
|
@@ -43,6 +43,7 @@ def unlikely_or_likely_from(value):
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
_jinja2 = None
|
|
46
|
+
_markupsafe = None
|
|
46
47
|
|
|
47
48
|
# For pkg resources, we need to keep a reference, after we delete it from
|
|
48
49
|
# "sys.modules" again.
|
|
@@ -51,20 +52,25 @@ _loaded_pkg_resources = None
|
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
def getJinja2Package():
|
|
54
|
-
global _jinja2, _loaded_pkg_resources # singleton package using a cache, pylint: disable=global-statement
|
|
55
|
+
global _jinja2, _markupsafe, _loaded_pkg_resources # singleton package using a cache, pylint: disable=global-statement
|
|
55
56
|
|
|
56
57
|
# Import dependencies, sadly we get to manage this ourselves.
|
|
57
|
-
|
|
58
|
+
if _markupsafe is None:
|
|
59
|
+
_markupsafe = importFromInlineCopy("markupsafe", must_exist=True)
|
|
58
60
|
|
|
59
61
|
# Newer Jinja2 may not use it, but we load it and remove it, so it
|
|
60
62
|
# does not interfere with anything else.
|
|
61
63
|
if "pkg_resources" not in sys.modules:
|
|
62
|
-
_loaded_pkg_resources
|
|
64
|
+
if _loaded_pkg_resources is None:
|
|
65
|
+
_loaded_pkg_resources = importFromInlineCopy(
|
|
66
|
+
"pkg_resources", must_exist=False
|
|
67
|
+
)
|
|
63
68
|
|
|
64
|
-
_jinja2
|
|
69
|
+
if _jinja2 is None:
|
|
70
|
+
_jinja2 = importFromInlineCopy("jinja2", must_exist=True)
|
|
65
71
|
|
|
66
72
|
# Unload if it was us loading it, as the inline copy is incomplete.
|
|
67
|
-
if _loaded_pkg_resources is not None:
|
|
73
|
+
if _loaded_pkg_resources is not None and "pkg_resources" in sys.modules:
|
|
68
74
|
del sys.modules["pkg_resources"]
|
|
69
75
|
|
|
70
76
|
return _jinja2
|
nuitka/utils/ModuleNames.py
CHANGED
|
@@ -86,7 +86,7 @@ class ModuleName(str):
|
|
|
86
86
|
return ModuleName(module_name)
|
|
87
87
|
|
|
88
88
|
def __repr__(self):
|
|
89
|
-
return "<ModuleName %s>" % str(self)
|
|
89
|
+
return "<ModuleName '%s'>" % str(self)
|
|
90
90
|
|
|
91
91
|
def asString(self):
|
|
92
92
|
"""Get a simply str value.
|
|
@@ -225,6 +225,13 @@ class ModuleName(str):
|
|
|
225
225
|
else:
|
|
226
226
|
return ModuleName(parent_new)
|
|
227
227
|
|
|
228
|
+
def getChildNameFromPackage(self, package_name):
|
|
229
|
+
"""Get child a module name part for a name in the package."""
|
|
230
|
+
assert self.hasNamespace(package_name)
|
|
231
|
+
|
|
232
|
+
submodule_name_str = str(self)[len(str(package_name)) + 1 :]
|
|
233
|
+
return ModuleName(submodule_name_str)
|
|
234
|
+
|
|
228
235
|
def matchesToShellPattern(self, pattern):
|
|
229
236
|
"""Match a module name to a list of patterns
|
|
230
237
|
|
|
@@ -290,9 +297,10 @@ Do not use %(func_name)s on ModuleName objects, use e.g.
|
|
|
290
297
|
.hasNamespace(),
|
|
291
298
|
.getBasename(),
|
|
292
299
|
.getTopLevelPackageName()
|
|
293
|
-
.hasOneOfNamespaces
|
|
300
|
+
.hasOneOfNamespaces()
|
|
294
301
|
|
|
295
|
-
Check API documentation of nuitka.utils.ModuleNames.ModuleName
|
|
302
|
+
Check API documentation of nuitka.utils.ModuleNames.ModuleName for more
|
|
303
|
+
variations.
|
|
296
304
|
''')
|
|
297
305
|
""" % {
|
|
298
306
|
"func_name": _func_name
|
nuitka/utils/ReExecute.py
CHANGED
|
@@ -73,6 +73,9 @@ def reExecuteNuitka(pgo_filename):
|
|
|
73
73
|
if sys.version_info >= (3, 7) and sys.flags.utf8_mode:
|
|
74
74
|
args += ["-X", "utf8"]
|
|
75
75
|
|
|
76
|
+
if sys.version_info >= (3, 11):
|
|
77
|
+
args += ["-X", "frozen_modules=off"]
|
|
78
|
+
|
|
76
79
|
if "nuitka.__main__" in sys.modules:
|
|
77
80
|
our_filename = sys.modules["nuitka.__main__"].__file__
|
|
78
81
|
else:
|
|
@@ -110,6 +113,10 @@ def reExecuteNuitka(pgo_filename):
|
|
|
110
113
|
# Note: As side effect, this might modify the "sys.path" too.
|
|
111
114
|
os.environ["NUITKA_PTH_IMPORTED"] = repr(detectPthImportedPackages())
|
|
112
115
|
|
|
116
|
+
user_site = getattr(sys.modules["site"], "USER_SITE")
|
|
117
|
+
if user_site is not None:
|
|
118
|
+
os.environ["NUITKA_USER_SITE"] = repr(user_site)
|
|
119
|
+
|
|
113
120
|
os.environ["NUITKA_PYTHONPATH"] = repr(sys.path)
|
|
114
121
|
|
|
115
122
|
# In some environments, initial "sys.path" does not contain enough to load
|
nuitka/utils/SharedLibraries.py
CHANGED
|
@@ -44,7 +44,13 @@ from .FileOperations import (
|
|
|
44
44
|
makeContainingPath,
|
|
45
45
|
withMadeWritableFileMode,
|
|
46
46
|
)
|
|
47
|
-
from .Utils import
|
|
47
|
+
from .Utils import (
|
|
48
|
+
isAlpineLinux,
|
|
49
|
+
isLinux,
|
|
50
|
+
isMacOS,
|
|
51
|
+
isWin32Windows,
|
|
52
|
+
raiseWindowsError,
|
|
53
|
+
)
|
|
48
54
|
from .WindowsResources import (
|
|
49
55
|
RT_MANIFEST,
|
|
50
56
|
VsFixedFileInfoStructure,
|
|
@@ -115,6 +121,8 @@ def locateDLL(dll_name):
|
|
|
115
121
|
left = left[: left.rfind(b" (")]
|
|
116
122
|
|
|
117
123
|
if python_version >= 0x300:
|
|
124
|
+
# spell-checker: ignore getfilesystemencoding
|
|
125
|
+
|
|
118
126
|
left = left.decode(sys.getfilesystemencoding())
|
|
119
127
|
right = right.decode(sys.getfilesystemencoding())
|
|
120
128
|
|
|
@@ -147,7 +155,7 @@ def _removeSxsFromDLL(filename):
|
|
|
147
155
|
filename: Filename to remove SxS manifests from
|
|
148
156
|
"""
|
|
149
157
|
# There may be more files that need this treatment, these are from scans
|
|
150
|
-
# with the "find_sxs_modules" tool.
|
|
158
|
+
# with the "find_sxs_modules" tool. spell-checker: ignore winxpgui
|
|
151
159
|
if os.path.normcase(os.path.basename(filename)) not in (
|
|
152
160
|
"sip.pyd",
|
|
153
161
|
"win32ui.pyd",
|
|
@@ -207,7 +215,7 @@ def _getDLLVersionWindows(filename):
|
|
|
207
215
|
# This cannot really fail anymore.
|
|
208
216
|
assert success
|
|
209
217
|
|
|
210
|
-
# Look for
|
|
218
|
+
# Look for code pages
|
|
211
219
|
VerQueryValueA = ctypes.windll.version.VerQueryValueA
|
|
212
220
|
VerQueryValueA.argtypes = (
|
|
213
221
|
ctypes.wintypes.LPCVOID,
|
|
@@ -233,6 +241,7 @@ def _getDLLVersionWindows(filename):
|
|
|
233
241
|
return (ms >> 16) & 0xFFFF, ms & 0xFFFF, (ls >> 16) & 0xFFFF, ls & 0xFFFF
|
|
234
242
|
|
|
235
243
|
|
|
244
|
+
# spell-checker: ignore readelf
|
|
236
245
|
_readelf_usage = "The 'readelf' is used to analyse dependencies on ELF using systems and required to be found."
|
|
237
246
|
|
|
238
247
|
|
|
@@ -244,6 +253,7 @@ def _getSharedLibraryRPATHElf(filename):
|
|
|
244
253
|
)
|
|
245
254
|
|
|
246
255
|
for line in output.split(b"\n"):
|
|
256
|
+
# spell-checker: ignore RUNPATH
|
|
247
257
|
if b"RPATH" in line or b"RUNPATH" in line:
|
|
248
258
|
result = line[line.find(b"[") + 1 : line.rfind(b"]")]
|
|
249
259
|
|
|
@@ -258,10 +268,19 @@ def _getSharedLibraryRPATHElf(filename):
|
|
|
258
268
|
_otool_output_cache = {}
|
|
259
269
|
|
|
260
270
|
|
|
271
|
+
def _getMacOSArchOption():
|
|
272
|
+
macos_target_arch = getMacOSTargetArch()
|
|
273
|
+
|
|
274
|
+
if macos_target_arch != "universal":
|
|
275
|
+
return ("-arch", macos_target_arch)
|
|
276
|
+
else:
|
|
277
|
+
return ()
|
|
278
|
+
|
|
279
|
+
|
|
261
280
|
def _getOToolCommandOutput(otool_option, filename):
|
|
262
281
|
filename = os.path.abspath(filename)
|
|
263
282
|
|
|
264
|
-
command = ("otool", otool_option, filename)
|
|
283
|
+
command = ("otool",) + _getMacOSArchOption() + (otool_option, filename)
|
|
265
284
|
|
|
266
285
|
if otool_option == "-L":
|
|
267
286
|
cache_key = command, os.environ.get("DYLD_LIBRARY_PATH")
|
|
@@ -474,6 +493,7 @@ def getPyWin32Dir():
|
|
|
474
493
|
Notes:
|
|
475
494
|
This is needed for standalone mode only.
|
|
476
495
|
"""
|
|
496
|
+
# spell-checker: ignore pywin32
|
|
477
497
|
|
|
478
498
|
for path_element in sys.path:
|
|
479
499
|
if not path_element:
|
|
@@ -653,6 +673,8 @@ def copyDllFile(source_path, dist_dir, dest_path, executable):
|
|
|
653
673
|
)
|
|
654
674
|
|
|
655
675
|
if isMacOS():
|
|
676
|
+
# spell-checker: ignore xattr
|
|
677
|
+
|
|
656
678
|
executeToolChecked(
|
|
657
679
|
logger=postprocessing_logger,
|
|
658
680
|
command=("xattr", "-c", target_filename),
|
|
@@ -689,10 +711,7 @@ def getWindowsRunningProcessModuleFilename(handle):
|
|
|
689
711
|
|
|
690
712
|
res = GetModuleFileName(handle, buf, MAX_PATH)
|
|
691
713
|
if res == 0:
|
|
692
|
-
|
|
693
|
-
raise WindowsError(
|
|
694
|
-
ctypes.GetLastError(), ctypes.FormatError(ctypes.GetLastError())
|
|
695
|
-
)
|
|
714
|
+
raiseWindowsError("getWindowsRunningProcessModuleFilename")
|
|
696
715
|
|
|
697
716
|
return os.path.normcase(buf.value)
|
|
698
717
|
|
|
@@ -726,10 +745,7 @@ def _getWindowsRunningProcessModuleHandles():
|
|
|
726
745
|
)
|
|
727
746
|
|
|
728
747
|
if not res:
|
|
729
|
-
|
|
730
|
-
raise WindowsError(
|
|
731
|
-
ctypes.GetLastError(), ctypes.FormatError(ctypes.GetLastError())
|
|
732
|
-
)
|
|
748
|
+
raiseWindowsError("getWindowsRunningProcessModuleHandles")
|
|
733
749
|
|
|
734
750
|
return tuple(handle for handle in handles if handle is not None)
|
|
735
751
|
|
|
@@ -782,10 +798,18 @@ Error, needs 'nm' on your system, to detect exported DLL symbols."""
|
|
|
782
798
|
|
|
783
799
|
|
|
784
800
|
def getDllExportedSymbols(logger, filename):
|
|
785
|
-
if isLinux():
|
|
801
|
+
if isLinux or isMacOS():
|
|
802
|
+
if isLinux():
|
|
803
|
+
command = ("nm", "-D", filename)
|
|
804
|
+
elif isMacOS():
|
|
805
|
+
command = ("nm", "-gU", filename) + _getMacOSArchOption()
|
|
806
|
+
else:
|
|
807
|
+
# Need to add e.g. FreeBSD here.
|
|
808
|
+
assert False
|
|
809
|
+
|
|
786
810
|
output = executeToolChecked(
|
|
787
811
|
logger=logger,
|
|
788
|
-
command=
|
|
812
|
+
command=command,
|
|
789
813
|
absence_message=_nm_usage,
|
|
790
814
|
)
|
|
791
815
|
|