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/Distributions.py
CHANGED
|
@@ -17,58 +17,141 @@
|
|
|
17
17
|
#
|
|
18
18
|
""" Tools for accessing distributions and resolving package names for them. """
|
|
19
19
|
|
|
20
|
+
import os
|
|
21
|
+
|
|
22
|
+
from nuitka.__past__ import unicode
|
|
20
23
|
from nuitka.containers.OrderedSets import OrderedSet
|
|
24
|
+
from nuitka.Options import isExperimental
|
|
21
25
|
from nuitka.PythonFlavors import isAnacondaPython
|
|
22
26
|
from nuitka.PythonVersions import python_version
|
|
23
27
|
|
|
28
|
+
from .FileOperations import searchPrefixPath
|
|
29
|
+
from .Importing import getModuleNameAndKindFromFilenameSuffix
|
|
24
30
|
from .ModuleNames import ModuleName, checkModuleName
|
|
31
|
+
from .Utils import isLinux
|
|
25
32
|
|
|
26
33
|
_package_to_distribution = None
|
|
27
34
|
|
|
28
35
|
|
|
36
|
+
def getDistributionFiles(distribution):
|
|
37
|
+
if hasattr(distribution, "files"):
|
|
38
|
+
for filename in distribution.files or ():
|
|
39
|
+
filename = filename.as_posix()
|
|
40
|
+
|
|
41
|
+
yield filename
|
|
42
|
+
else:
|
|
43
|
+
record_data = _getDistributionMetadataFileContents(distribution, "RECORD")
|
|
44
|
+
|
|
45
|
+
if record_data is not None:
|
|
46
|
+
for line in record_data.splitlines():
|
|
47
|
+
filename = line.split(",", 1)[0]
|
|
48
|
+
|
|
49
|
+
yield filename
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _getDistributionMetadataFileContents(distribution, filename):
|
|
53
|
+
try:
|
|
54
|
+
if hasattr(distribution, "read_text"):
|
|
55
|
+
result = distribution.read_text(filename)
|
|
56
|
+
else:
|
|
57
|
+
result = "\n".join(distribution.get_metadata_lines(filename))
|
|
58
|
+
|
|
59
|
+
return result
|
|
60
|
+
except (FileNotFoundError, KeyError):
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
|
|
29
64
|
def getDistributionTopLevelPackageNames(distribution):
|
|
30
65
|
"""Returns the top level package names for a distribution."""
|
|
31
|
-
top_level_txt = distribution
|
|
66
|
+
top_level_txt = _getDistributionMetadataFileContents(distribution, "top_level.txt")
|
|
32
67
|
|
|
33
|
-
if top_level_txt:
|
|
34
|
-
result = top_level_txt.
|
|
35
|
-
result = [dirname.replace("/", ".") for dirname in result]
|
|
68
|
+
if top_level_txt is not None:
|
|
69
|
+
result = [dirname.replace("/", ".") for dirname in top_level_txt.splitlines()]
|
|
36
70
|
else:
|
|
71
|
+
# If the file is not present, fall back to scanning all files in the
|
|
72
|
+
# distribution.
|
|
37
73
|
result = OrderedSet()
|
|
38
74
|
|
|
39
|
-
for filename in distribution
|
|
40
|
-
filename = filename.as_posix()
|
|
41
|
-
|
|
42
|
-
if not filename.endswith(".py"):
|
|
43
|
-
continue
|
|
44
|
-
|
|
75
|
+
for filename in getDistributionFiles(distribution):
|
|
45
76
|
if filename.startswith("."):
|
|
46
77
|
continue
|
|
47
78
|
|
|
48
|
-
|
|
79
|
+
first_path_element, _, remainder = filename.partition("/")
|
|
49
80
|
|
|
50
|
-
|
|
81
|
+
if first_path_element.endswith("dist-info"):
|
|
82
|
+
continue
|
|
83
|
+
if first_path_element == "__pycache__":
|
|
84
|
+
continue
|
|
85
|
+
|
|
86
|
+
if remainder:
|
|
87
|
+
module_name = ModuleName(first_path_element)
|
|
88
|
+
else:
|
|
89
|
+
module_name, _kind = getModuleNameAndKindFromFilenameSuffix(
|
|
90
|
+
first_path_element
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Ignore top level files that are not modules.
|
|
94
|
+
if module_name is None:
|
|
95
|
+
continue
|
|
96
|
+
|
|
97
|
+
result.add(module_name)
|
|
98
|
+
|
|
99
|
+
result = OrderedSet(
|
|
100
|
+
package_name.asString()
|
|
101
|
+
for package_name in result
|
|
102
|
+
if not any(
|
|
103
|
+
package_name.isBelowNamespace(other_package_name)
|
|
104
|
+
for other_package_name in result
|
|
105
|
+
)
|
|
106
|
+
)
|
|
51
107
|
|
|
52
108
|
if not result:
|
|
53
|
-
result = (distribution
|
|
109
|
+
result = (getDistributionName(distribution),)
|
|
54
110
|
|
|
55
111
|
return tuple(result)
|
|
56
112
|
|
|
57
113
|
|
|
114
|
+
def _get_pkg_resource_distributions():
|
|
115
|
+
"""Small replacement of distributions() of importlib.metadata that uses pkg_resources"""
|
|
116
|
+
|
|
117
|
+
# Prepare "site" for the "pip" module to find what it wants.
|
|
118
|
+
import site
|
|
119
|
+
|
|
120
|
+
if _user_site_directory is not None:
|
|
121
|
+
site.USER_SITE = _user_site_directory
|
|
122
|
+
|
|
123
|
+
# pip and vendored pkg_resources are optional of course, but of course very
|
|
124
|
+
# omnipresent generally, so we don't handle failure here.
|
|
125
|
+
|
|
126
|
+
# pylint: disable=I0021,no-name-in-module
|
|
127
|
+
from pip._vendor import pkg_resources
|
|
128
|
+
|
|
129
|
+
return lambda: pkg_resources.working_set
|
|
130
|
+
|
|
131
|
+
|
|
58
132
|
def _initPackageToDistributionName():
|
|
59
133
|
try:
|
|
134
|
+
if isExperimental("force-pkg-resources-metadata"):
|
|
135
|
+
raise ImportError
|
|
136
|
+
|
|
60
137
|
try:
|
|
61
138
|
from importlib.metadata import distributions
|
|
62
139
|
except ImportError:
|
|
63
140
|
from importlib_metadata import distributions
|
|
64
|
-
except ImportError:
|
|
65
|
-
return {}
|
|
66
141
|
|
|
67
|
-
|
|
142
|
+
except (ImportError, SyntaxError):
|
|
143
|
+
try:
|
|
144
|
+
distributions = _get_pkg_resource_distributions()
|
|
145
|
+
except ImportError:
|
|
146
|
+
# No pip installed, not very many distributions in that case.
|
|
147
|
+
distributions = lambda: ()
|
|
68
148
|
|
|
149
|
+
# Cyclic dependency
|
|
69
150
|
result = {}
|
|
70
151
|
|
|
71
152
|
for distribution in distributions():
|
|
153
|
+
distribution_name = getDistributionName(distribution)
|
|
154
|
+
|
|
72
155
|
for package_name in getDistributionTopLevelPackageNames(distribution):
|
|
73
156
|
# Protect against buggy packages.
|
|
74
157
|
if not checkModuleName(package_name):
|
|
@@ -79,13 +162,23 @@ def _initPackageToDistributionName():
|
|
|
79
162
|
if package_name not in result:
|
|
80
163
|
result[package_name] = set()
|
|
81
164
|
|
|
165
|
+
# Skip duplicates, e.g. user package vs. site package installation.
|
|
166
|
+
if any(
|
|
167
|
+
distribution_name == getDistributionName(dist)
|
|
168
|
+
for dist in result[package_name]
|
|
169
|
+
):
|
|
170
|
+
continue
|
|
171
|
+
|
|
82
172
|
result[package_name].add(distribution)
|
|
83
173
|
|
|
84
174
|
return result
|
|
85
175
|
|
|
86
176
|
|
|
87
177
|
def getDistributionsFromModuleName(module_name):
|
|
88
|
-
"""Get the distribution
|
|
178
|
+
"""Get the distribution names associated with a module name.
|
|
179
|
+
|
|
180
|
+
This can be more than one in case of namespace modules.
|
|
181
|
+
"""
|
|
89
182
|
|
|
90
183
|
# Cached result, pylint: disable=global-statement
|
|
91
184
|
|
|
@@ -93,54 +186,228 @@ def getDistributionsFromModuleName(module_name):
|
|
|
93
186
|
if _package_to_distribution is None:
|
|
94
187
|
_package_to_distribution = _initPackageToDistributionName()
|
|
95
188
|
|
|
189
|
+
# Go upwards until we find something, such that contained module names are
|
|
190
|
+
# usable too.
|
|
191
|
+
while (
|
|
192
|
+
module_name not in _package_to_distribution
|
|
193
|
+
and module_name.getPackageName() is not None
|
|
194
|
+
):
|
|
195
|
+
module_name = module_name.getPackageName()
|
|
196
|
+
|
|
96
197
|
return tuple(
|
|
97
198
|
sorted(
|
|
98
199
|
_package_to_distribution.get(module_name, ()),
|
|
99
|
-
key=
|
|
200
|
+
key=getDistributionName,
|
|
100
201
|
)
|
|
101
202
|
)
|
|
102
203
|
|
|
103
204
|
|
|
205
|
+
def getDistributionFromModuleName(module_name):
|
|
206
|
+
"""Get the distribution name associated with a module name."""
|
|
207
|
+
distributions = getDistributionsFromModuleName(module_name)
|
|
208
|
+
|
|
209
|
+
if not distributions:
|
|
210
|
+
return None
|
|
211
|
+
elif len(distributions) == 1:
|
|
212
|
+
return distributions[0]
|
|
213
|
+
else:
|
|
214
|
+
return min(distributions, key=lambda dist: len(getDistributionName(dist)))
|
|
215
|
+
|
|
216
|
+
|
|
104
217
|
def getDistribution(distribution_name):
|
|
105
218
|
"""Get a distribution by name."""
|
|
219
|
+
assert isValidDistributionName(distribution_name), distribution_name
|
|
220
|
+
|
|
106
221
|
try:
|
|
222
|
+
if isExperimental("force-pkg-resources-metadata"):
|
|
223
|
+
raise ImportError
|
|
224
|
+
|
|
107
225
|
if python_version >= 0x380:
|
|
108
226
|
from importlib import metadata
|
|
109
227
|
else:
|
|
110
228
|
import importlib_metadata as metadata
|
|
111
229
|
except ImportError:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
except metadata.PackageNotFoundError:
|
|
117
|
-
# If not found, lets assume package name was given, and resolve to
|
|
118
|
-
# the distribution.
|
|
119
|
-
dists = getDistributionsFromModuleName(distribution_name)
|
|
120
|
-
|
|
121
|
-
if len(dists) == 1:
|
|
122
|
-
return dists[0]
|
|
230
|
+
from pip._vendor.pkg_resources import (
|
|
231
|
+
DistributionNotFound,
|
|
232
|
+
get_distribution,
|
|
233
|
+
)
|
|
123
234
|
|
|
124
|
-
|
|
235
|
+
try:
|
|
236
|
+
return get_distribution(distribution_name)
|
|
237
|
+
except DistributionNotFound:
|
|
238
|
+
return None
|
|
239
|
+
else:
|
|
240
|
+
try:
|
|
241
|
+
return metadata.distribution(distribution_name)
|
|
242
|
+
except metadata.PackageNotFoundError:
|
|
243
|
+
return None
|
|
125
244
|
|
|
126
245
|
|
|
127
|
-
|
|
246
|
+
_distribution_to_installer = {}
|
|
128
247
|
|
|
129
248
|
|
|
130
249
|
def isDistributionCondaPackage(distribution_name):
|
|
131
250
|
if not isAnacondaPython():
|
|
132
251
|
return False
|
|
133
252
|
|
|
134
|
-
|
|
253
|
+
return getDistributionInstallerName(distribution_name) == "conda"
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def isDistributionPipPackage(distribution_name):
|
|
257
|
+
return getDistributionInstallerName(distribution_name) == "pip"
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def isDistributionPoetryPackage(distribution_name):
|
|
261
|
+
return getDistributionInstallerName(distribution_name).startswith("poetry")
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def isDistributionSystemPackage(distribution_name):
|
|
265
|
+
result = (
|
|
266
|
+
not isDistributionPipPackage(distribution_name)
|
|
267
|
+
and not isDistributionPoetryPackage(distribution_name)
|
|
268
|
+
and not isDistributionCondaPackage(distribution_name)
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
# This should only ever happen on Linux, lets know when it does happen
|
|
272
|
+
# elsewhere, since that is most probably a bug in our installer detection on
|
|
273
|
+
# non-Linux as well.
|
|
274
|
+
if result:
|
|
275
|
+
assert isLinux(), (
|
|
276
|
+
distribution_name,
|
|
277
|
+
getDistributionInstallerName(distribution_name),
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
return result
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
_pdm_dir_cache = {}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def isPdmPackageInstallation(distribution):
|
|
287
|
+
distribution_path = getattr(distribution, "_path")
|
|
288
|
+
if distribution_path is None:
|
|
289
|
+
return False
|
|
290
|
+
|
|
291
|
+
site_packages_path = searchPrefixPath(str(distribution_path), "site-packages")
|
|
292
|
+
if site_packages_path is None:
|
|
293
|
+
return False
|
|
294
|
+
|
|
295
|
+
candidate = os.path.join(site_packages_path, "..", "..", "pyvenv.cfg")
|
|
296
|
+
|
|
297
|
+
result = _pdm_dir_cache.get(candidate)
|
|
298
|
+
if result is None:
|
|
299
|
+
_pdm_dir_cache[candidate] = os.path.exists(candidate)
|
|
300
|
+
|
|
301
|
+
return _pdm_dir_cache[candidate]
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def getDistributionInstallerName(distribution_name):
|
|
305
|
+
"""Get the installer name from a distribution object.
|
|
306
|
+
|
|
307
|
+
We might care of pip, anaconda, Debian, or whatever installed a
|
|
308
|
+
package.
|
|
309
|
+
"""
|
|
310
|
+
if distribution_name not in _distribution_to_installer:
|
|
135
311
|
distribution = getDistribution(distribution_name)
|
|
136
312
|
|
|
137
313
|
if distribution is None:
|
|
138
|
-
|
|
314
|
+
if distribution_name == "Pip":
|
|
315
|
+
_distribution_to_installer[distribution_name] = "default"
|
|
316
|
+
else:
|
|
317
|
+
_distribution_to_installer[distribution_name] = "not_found"
|
|
139
318
|
else:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
_distribution_to_conda_package[distribution_name] = (
|
|
143
|
-
installer_txt.upper() == "CONDA"
|
|
319
|
+
installer_name = _getDistributionMetadataFileContents(
|
|
320
|
+
distribution, "INSTALLER"
|
|
144
321
|
)
|
|
145
322
|
|
|
146
|
-
|
|
323
|
+
if installer_name:
|
|
324
|
+
_distribution_to_installer[
|
|
325
|
+
distribution_name
|
|
326
|
+
] = installer_name.strip().lower()
|
|
327
|
+
elif isAnacondaPython():
|
|
328
|
+
_distribution_to_installer[distribution_name] = "conda"
|
|
329
|
+
elif isPdmPackageInstallation(distribution):
|
|
330
|
+
return "pip"
|
|
331
|
+
else:
|
|
332
|
+
if hasattr(distribution, "_path"):
|
|
333
|
+
distribution_path_parts = str(getattr(distribution, "_path")).split(
|
|
334
|
+
"/"
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
if (
|
|
338
|
+
"dist-packages" in distribution_path_parts
|
|
339
|
+
and "local" not in distribution_path_parts
|
|
340
|
+
):
|
|
341
|
+
_distribution_to_installer[distribution_name] = "Debian"
|
|
342
|
+
else:
|
|
343
|
+
_distribution_to_installer[distribution_name] = "Unknown"
|
|
344
|
+
else:
|
|
345
|
+
_distribution_to_installer[distribution_name] = "Unknown"
|
|
346
|
+
|
|
347
|
+
return _distribution_to_installer[distribution_name]
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def isValidDistributionName(distribution_name):
|
|
351
|
+
return type(distribution_name) in (str, unicode)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def getDistributionName(distribution):
|
|
355
|
+
"""Get the distribution name from a distribution object.
|
|
356
|
+
|
|
357
|
+
We use importlib.metadata and pkg_resources version tuples interchangeable
|
|
358
|
+
and this is to abstract the difference is how to look up the name from
|
|
359
|
+
one.
|
|
360
|
+
"""
|
|
361
|
+
|
|
362
|
+
if hasattr(distribution, "metadata"):
|
|
363
|
+
result = distribution.metadata["Name"]
|
|
364
|
+
else:
|
|
365
|
+
result = distribution.project_name
|
|
366
|
+
|
|
367
|
+
assert isValidDistributionName(result), distribution
|
|
368
|
+
return result
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def getDistributionVersion(distribution):
|
|
372
|
+
"""Get the distribution version string from a distribution object.
|
|
373
|
+
|
|
374
|
+
We use importlib.metadata and pkg_resources version tuples interchangeable
|
|
375
|
+
and this is to abstract the difference is how to look up the version from
|
|
376
|
+
one.
|
|
377
|
+
"""
|
|
378
|
+
# Avoiding use of public interface for pkg_resources, pylint: disable=protected-access
|
|
379
|
+
if hasattr(distribution, "metadata"):
|
|
380
|
+
return distribution.metadata["Version"]
|
|
381
|
+
else:
|
|
382
|
+
return distribution._version
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def getDistributionLicense(distribution):
|
|
386
|
+
"""Get the distribution license from a distribution object."""
|
|
387
|
+
|
|
388
|
+
license_name = distribution.metadata["License"]
|
|
389
|
+
|
|
390
|
+
if not license_name or license_name == "UNKNOWN":
|
|
391
|
+
for classifier in (
|
|
392
|
+
value
|
|
393
|
+
for (key, value) in distribution.metadata.items()
|
|
394
|
+
if "Classifier" in key
|
|
395
|
+
):
|
|
396
|
+
parts = [part.strip() for part in classifier.split("::")]
|
|
397
|
+
if not parts:
|
|
398
|
+
continue
|
|
399
|
+
|
|
400
|
+
if parts[0] == "License":
|
|
401
|
+
license_name = parts[-1]
|
|
402
|
+
break
|
|
403
|
+
|
|
404
|
+
return license_name
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
# User site directory if any
|
|
408
|
+
_user_site_directory = None
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def setUserSiteDirectory(user_site_directory):
|
|
412
|
+
global _user_site_directory # singleton, pylint: disable=global-statement
|
|
413
|
+
_user_site_directory = user_site_directory
|
nuitka/utils/Download.py
CHANGED
|
@@ -24,6 +24,7 @@ import os
|
|
|
24
24
|
|
|
25
25
|
from nuitka import Tracing
|
|
26
26
|
from nuitka.__past__ import urlretrieve
|
|
27
|
+
from nuitka.Progress import withNuitkaDownloadProgressBar
|
|
27
28
|
|
|
28
29
|
from .AppDirs import getCacheDir
|
|
29
30
|
from .FileOperations import (
|
|
@@ -34,11 +35,23 @@ from .FileOperations import (
|
|
|
34
35
|
)
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
def getDownload(url, download_path):
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
def getDownload(name, url, download_path):
|
|
39
|
+
# requests api, spell-checker: ignore reporthook
|
|
40
|
+
|
|
41
|
+
with withNuitkaDownloadProgressBar(desc="Download %s" % name) as reporthook:
|
|
42
|
+
try:
|
|
43
|
+
try:
|
|
44
|
+
urlretrieve(url, download_path, reporthook=reporthook)
|
|
45
|
+
except Exception: # Any kind of error, pylint: disable=broad-except
|
|
46
|
+
urlretrieve(
|
|
47
|
+
url.replace("https://", "http://"),
|
|
48
|
+
download_path,
|
|
49
|
+
reporthook=reporthook,
|
|
50
|
+
)
|
|
51
|
+
except KeyboardInterrupt:
|
|
52
|
+
deleteFile(download_path, must_exist=False)
|
|
53
|
+
|
|
54
|
+
raise
|
|
42
55
|
|
|
43
56
|
|
|
44
57
|
def getDownloadCacheDir():
|
|
@@ -46,6 +59,7 @@ def getDownloadCacheDir():
|
|
|
46
59
|
|
|
47
60
|
|
|
48
61
|
def getCachedDownload(
|
|
62
|
+
name,
|
|
49
63
|
url,
|
|
50
64
|
binary,
|
|
51
65
|
flatten,
|
|
@@ -99,7 +113,11 @@ Fully automatic, cached. Proceed and download"""
|
|
|
99
113
|
Tracing.general.info("Downloading '%s'." % url)
|
|
100
114
|
|
|
101
115
|
try:
|
|
102
|
-
getDownload(
|
|
116
|
+
getDownload(
|
|
117
|
+
name=name,
|
|
118
|
+
url=url,
|
|
119
|
+
download_path=download_path,
|
|
120
|
+
)
|
|
103
121
|
except Exception as e: # Any kind of error, pylint: disable=broad-except
|
|
104
122
|
Tracing.general.sysexit(
|
|
105
123
|
"Failed to download '%s' due to '%s'. Contents should manually be copied to '%s'."
|
|
@@ -150,10 +168,10 @@ def getCachedDownloadedMinGW64(target_arch, assume_yes_for_downloads):
|
|
|
150
168
|
# Large URLs, pylint: disable=line-too-long
|
|
151
169
|
|
|
152
170
|
if target_arch == "x86_64":
|
|
153
|
-
url = "https://github.com/brechtsanders/winlibs_mingw/releases/download/
|
|
171
|
+
url = "https://github.com/brechtsanders/winlibs_mingw/releases/download/13.2.0-16.0.6-11.0.1-msvcrt-r1/winlibs-x86_64-posix-seh-gcc-13.2.0-llvm-16.0.6-mingw-w64msvcrt-11.0.1-r1.zip"
|
|
154
172
|
binary = r"mingw64\bin\gcc.exe"
|
|
155
173
|
elif target_arch == "x86":
|
|
156
|
-
url = "https://github.com/brechtsanders/winlibs_mingw/releases/download/
|
|
174
|
+
url = "https://github.com/brechtsanders/winlibs_mingw/releases/download/13.2.0-16.0.6-11.0.1-msvcrt-r1/winlibs-i686-posix-dwarf-gcc-13.2.0-llvm-16.0.6-mingw-w64msvcrt-11.0.1-r1.zip"
|
|
157
175
|
binary = r"mingw32\bin\gcc.exe"
|
|
158
176
|
elif target_arch == "arm64":
|
|
159
177
|
url = None
|
|
@@ -164,6 +182,7 @@ def getCachedDownloadedMinGW64(target_arch, assume_yes_for_downloads):
|
|
|
164
182
|
return None
|
|
165
183
|
|
|
166
184
|
gcc_binary = getCachedDownload(
|
|
185
|
+
name="mingw64",
|
|
167
186
|
url=url,
|
|
168
187
|
is_arch_specific=target_arch,
|
|
169
188
|
specificity=url.rsplit("/", 2)[1],
|