Nuitka-winsvc 1.6.6__cp310-cp310-win_amd64.whl → 1.7.5__cp310-cp310-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.
Files changed (84) hide show
  1. {Nuitka_winsvc-1.6.6.dist-info → Nuitka_winsvc-1.7.5.dist-info}/METADATA +1 -1
  2. {Nuitka_winsvc-1.6.6.dist-info → Nuitka_winsvc-1.7.5.dist-info}/RECORD +84 -81
  3. nuitka/Builtins.py +7 -1
  4. nuitka/MainControl.py +4 -0
  5. nuitka/OptionParsing.py +5 -3
  6. nuitka/Options.py +17 -2
  7. nuitka/Serialization.py +28 -5
  8. nuitka/Version.py +2 -2
  9. nuitka/build/Backend.scons +16 -3
  10. nuitka/build/CCompilerVersion.scons +1 -1
  11. nuitka/build/DataComposerInterface.py +15 -9
  12. nuitka/build/Onefile.scons +1 -1
  13. nuitka/build/SconsCompilerSettings.py +1 -0
  14. nuitka/build/SconsProgress.py +11 -2
  15. nuitka/build/SconsSpawn.py +15 -15
  16. nuitka/build/include/nuitka/builtins.h +2 -0
  17. nuitka/build/include/nuitka/filesystem_paths.h +4 -0
  18. nuitka/build/include/nuitka/helper/attributes.h +3 -0
  19. nuitka/build/include/nuitka/helper/import_hard.h +6 -0
  20. nuitka/build/include/nuitka/helpers.h +1 -1
  21. nuitka/build/include/nuitka/safe_string_ops.h +10 -3
  22. nuitka/build/static_src/CompiledCodeHelpers.c +0 -200
  23. nuitka/build/static_src/HelpersAttributes.c +185 -8
  24. nuitka/build/static_src/HelpersFilesystemPaths.c +528 -7
  25. nuitka/build/static_src/HelpersImportHard.c +38 -0
  26. nuitka/build/static_src/HelpersSafeStrings.c +6 -278
  27. nuitka/build/static_src/MainProgram.c +273 -73
  28. nuitka/build/static_src/MetaPathBasedLoaderResourceReaderFiles.c +6 -0
  29. nuitka/build/static_src/OnefileBootstrap.c +19 -36
  30. nuitka/build/static_src/OnefileSplashScreen.cpp +1 -0
  31. nuitka/code_generation/AttributeCodes.py +42 -23
  32. nuitka/code_generation/CodeGeneration.py +4 -0
  33. nuitka/code_generation/FunctionCodes.py +18 -3
  34. nuitka/code_generation/GlobalConstants.py +8 -1
  35. nuitka/code_generation/PackageResourceCodes.py +40 -0
  36. nuitka/code_generation/templates/CodeTemplatesModules.py +1 -7
  37. nuitka/freezer/DllDependenciesMacOS.py +18 -1
  38. nuitka/freezer/IncludedDataFiles.py +6 -10
  39. nuitka/importing/ImportResolving.py +6 -0
  40. nuitka/importing/Recursion.py +24 -68
  41. nuitka/nodes/AttributeNodes.py +72 -19
  42. nuitka/nodes/ChildrenHavingMixins.py +203 -234
  43. nuitka/nodes/ExpressionBasesGenerated.py +136 -0
  44. nuitka/nodes/HardImportNodesGenerated.py +94 -0
  45. nuitka/nodes/ImportHardNodes.py +3 -3
  46. nuitka/nodes/ImportNodes.py +14 -4
  47. nuitka/nodes/ModuleNodes.py +4 -2
  48. nuitka/nodes/PackageMetadataNodes.py +12 -10
  49. nuitka/nodes/PackageResourceNodes.py +115 -0
  50. nuitka/nodes/TypeNodes.py +5 -1
  51. nuitka/plugins/PluginBase.py +32 -8
  52. nuitka/plugins/Plugins.py +44 -7
  53. nuitka/plugins/standard/AntiBloatPlugin.py +166 -72
  54. nuitka/plugins/standard/DataFilesPlugin.py +10 -0
  55. nuitka/plugins/standard/DllFilesPlugin.py +1 -2
  56. nuitka/plugins/standard/MatplotlibPlugin.py +24 -22
  57. nuitka/plugins/standard/MultiprocessingPlugin.py +5 -12
  58. nuitka/plugins/standard/OptionsNannyPlugin.py +2 -2
  59. nuitka/plugins/standard/PySidePyQtPlugin.py +18 -6
  60. nuitka/plugins/standard/PywebViewPlugin.py +4 -2
  61. nuitka/plugins/standard/TkinterPlugin.py +3 -0
  62. nuitka/plugins/standard/TransformersPlugin.py +11 -1
  63. nuitka/plugins/standard/TrioPlugin.py +6 -66
  64. nuitka/plugins/standard/standard.nuitka-package.config.yml +367 -21
  65. nuitka/plugins/standard/stdlib3.nuitka-package.config.yml +16 -4
  66. nuitka/specs/HardImportSpecs.py +6 -0
  67. nuitka/tools/data_composer/DataComposer.py +25 -27
  68. nuitka/tools/general/find_module/FindModuleCode.py +5 -2
  69. nuitka/tools/podman/Podman.py +53 -0
  70. nuitka/tools/podman/__init__.py +18 -0
  71. nuitka/tools/podman/__main__.py +255 -0
  72. nuitka/tools/specialize/SpecializePython.py +37 -3
  73. nuitka/tools/testing/RuntimeTracing.py +4 -0
  74. nuitka/tree/Building.py +1 -1
  75. nuitka/tree/ReformulationFunctionStatements.py +137 -10
  76. nuitka/utils/Execution.py +11 -1
  77. nuitka/utils/ModuleNames.py +1 -1
  78. nuitka/utils/SharedLibraries.py +7 -7
  79. {Nuitka_winsvc-1.6.6.data → Nuitka_winsvc-1.7.5.data}/scripts/nuitka-run.bat +0 -0
  80. {Nuitka_winsvc-1.6.6.data → Nuitka_winsvc-1.7.5.data}/scripts/nuitka.bat +0 -0
  81. {Nuitka_winsvc-1.6.6.dist-info → Nuitka_winsvc-1.7.5.dist-info}/LICENSE.txt +0 -0
  82. {Nuitka_winsvc-1.6.6.dist-info → Nuitka_winsvc-1.7.5.dist-info}/WHEEL +0 -0
  83. {Nuitka_winsvc-1.6.6.dist-info → Nuitka_winsvc-1.7.5.dist-info}/entry_points.txt +0 -0
  84. {Nuitka_winsvc-1.6.6.dist-info → Nuitka_winsvc-1.7.5.dist-info}/top_level.txt +0 -0
@@ -28,10 +28,12 @@ it being used.
28
28
 
29
29
  import ast
30
30
  import functools
31
+ import imp
31
32
  import inspect
32
33
  import os
33
34
  import sys
34
35
 
36
+ from nuitka import Options
35
37
  from nuitka.__past__ import getMetaClassBase
36
38
  from nuitka.containers.Namedtuples import makeNamedtupleClass
37
39
  from nuitka.containers.OrderedSets import OrderedSet
@@ -61,7 +63,10 @@ from nuitka.Options import (
61
63
  shallShowExecutedCommands,
62
64
  )
63
65
  from nuitka.PythonFlavors import isAnacondaPython, isDebianPackagePython
64
- from nuitka.PythonVersions import getSupportedPythonVersions, python_version
66
+ from nuitka.PythonVersions import (
67
+ getTestExecutionPythonVersions,
68
+ python_version,
69
+ )
65
70
  from nuitka.Tracing import plugins_logger
66
71
  from nuitka.utils.Distributions import isDistributionCondaPackage
67
72
  from nuitka.utils.Execution import NuitkaCalledProcessError, check_output
@@ -84,6 +89,10 @@ _warned_unused_plugins = set()
84
89
  # TODO: Could share data cache with meta data nodes
85
90
  _package_versions = {}
86
91
 
92
+ # Populated during plugin instance creation from their tags given by
93
+ # "getEvaluationConditionControlTags" value.
94
+ control_tags = {}
95
+
87
96
 
88
97
  def _convertVersionToTuple(version_str):
89
98
  def numberize(v):
@@ -418,10 +427,13 @@ class NuitkaPluginBase(getMetaClassBase("Plugin")):
418
427
  # Virtual method, pylint: disable=no-self-use,unused-argument
419
428
  return ()
420
429
 
421
- def onModuleEncounter(self, module_name, module_filename, module_kind):
430
+ def onModuleEncounter(
431
+ self, using_module_name, module_name, module_filename, module_kind
432
+ ):
422
433
  """Help decide whether to include a module.
423
434
 
424
435
  Args:
436
+ using_module_name: module that does this (can be None if user)
425
437
  module_name: full module name
426
438
  module_filename: filename
427
439
  module_kind: one of "py", "extension" (shared library)
@@ -432,7 +444,7 @@ class NuitkaPluginBase(getMetaClassBase("Plugin")):
432
444
  return None
433
445
 
434
446
  def onModuleRecursion(
435
- self, module_name, module_filename, module_kind, using_module, source_ref
447
+ self, module_name, module_filename, module_kind, using_module_name, source_ref
436
448
  ):
437
449
  """React to recursion to a module coming up.
438
450
 
@@ -440,7 +452,7 @@ class NuitkaPluginBase(getMetaClassBase("Plugin")):
440
452
  module_name: full module name
441
453
  module_filename: filename
442
454
  module_kind: one of "py", "extension" (shared library)
443
- using_module: module object that does the usage (None if it is a user choice)
455
+ using_module_name: name of module that does the usage (None if it is a user choice)
444
456
  source_ref: code making the import (None if it is a user choice)
445
457
  Returns:
446
458
  None
@@ -1066,9 +1078,12 @@ except ImportError:
1066
1078
  ).key
1067
1079
 
1068
1080
  def onFunctionBodyParsing(self, module_name, function_name, body):
1069
- """Provide a different function body for the function of that module."""
1081
+ """Provide a different function body for the function of that module.
1082
+
1083
+ Should return a boolean, indicating if any actual change was done.
1084
+ """
1070
1085
  # Virtual method, pylint: disable=no-self-use,unused-argument
1071
- return None
1086
+ return False
1072
1087
 
1073
1088
  def getCacheContributionValues(self, module_name):
1074
1089
  """Provide values that represent the include of a plugin on the compilation.
@@ -1095,7 +1110,11 @@ except ImportError:
1095
1110
  """Provide package version of a distribution."""
1096
1111
  return _getPackageVersion(distribution_name)
1097
1112
 
1098
- def evaluateCondition(self, full_name, condition, control_tags=()):
1113
+ def getEvaluationConditionControlTags(self):
1114
+ # Virtual method, pylint: disable=no-self-use
1115
+ return {}
1116
+
1117
+ def evaluateCondition(self, full_name, condition):
1099
1118
  # Note: Caching makes no sense yet, this should all be very fast and
1100
1119
  # cache themselves. TODO: Allow plugins to contribute their own control
1101
1120
  # tag values during creation and during certain actions.
@@ -1125,6 +1144,8 @@ except ImportError:
1125
1144
  "no_asserts": hasPythonFlagNoAsserts(),
1126
1145
  "no_docstrings": hasPythonFlagNoDocStrings(),
1127
1146
  "no_annotations": hasPythonFlagNoAnnotations(),
1147
+ # Querying package properties
1148
+ "has_builtin_module": imp.is_builtin,
1128
1149
  }
1129
1150
  )
1130
1151
 
@@ -1137,7 +1158,7 @@ except ImportError:
1137
1158
  }
1138
1159
  )
1139
1160
 
1140
- versions = getSupportedPythonVersions()
1161
+ versions = getTestExecutionPythonVersions()
1141
1162
 
1142
1163
  for version in versions:
1143
1164
  big, major = version.split(".")
@@ -1154,6 +1175,9 @@ except ImportError:
1154
1175
  try:
1155
1176
  result = eval(condition, context)
1156
1177
  except Exception as e: # Catch all the things, pylint: disable=broad-except
1178
+ if Options.is_debug:
1179
+ raise
1180
+
1157
1181
  self.sysexit(
1158
1182
  "Error, failed to evaluate condition '%s' in this context, exception was '%s'."
1159
1183
  % (condition, e)
nuitka/plugins/Plugins.py CHANGED
@@ -57,7 +57,7 @@ from nuitka.utils.ModuleNames import (
57
57
  pre_module_load_trigger_name,
58
58
  )
59
59
 
60
- from .PluginBase import NuitkaPluginBase
60
+ from .PluginBase import NuitkaPluginBase, control_tags
61
61
 
62
62
  # Maps plugin name to plugin instances.
63
63
  active_plugins = OrderedDict()
@@ -127,12 +127,30 @@ def _addActivePlugin(plugin_class, args, force=False):
127
127
 
128
128
  active_plugins[plugin_name] = plugin_instance
129
129
 
130
+ is_gui_toolkit_plugin = getattr(plugin_class, "plugin_gui_toolkit", False)
131
+
130
132
  # Singleton, pylint: disable=global-statement
131
133
  global has_active_gui_toolkit_plugin
132
- has_active_gui_toolkit_plugin = has_active_gui_toolkit_plugin or getattr(
133
- plugin_class, "plugin_gui_toolkit", False
134
+ has_active_gui_toolkit_plugin = (
135
+ has_active_gui_toolkit_plugin or is_gui_toolkit_plugin
134
136
  )
135
137
 
138
+ # Do GUI toolkit exclusion control tags generically. You may have two of
139
+ # them and we don't want them to override each other.
140
+ if is_gui_toolkit_plugin:
141
+ for binding_name in getGUIBindingNames():
142
+ is_matching = binding_name.lower() == plugin_class.binding_name.lower()
143
+
144
+ tag_name = "use_%s" % binding_name.lower()
145
+
146
+ # Set if matching, set to False only if not matching and not already set.
147
+ if is_matching:
148
+ control_tags[tag_name] = True
149
+ elif is_matching not in control_tags:
150
+ control_tags[tag_name] = False
151
+
152
+ control_tags.update(plugin_instance.getEvaluationConditionControlTags())
153
+
136
154
 
137
155
  def getActivePlugins():
138
156
  """Return list of active plugins.
@@ -146,6 +164,7 @@ def getActivePlugins():
146
164
 
147
165
 
148
166
  def getActiveQtPlugin():
167
+ """Get active Qt plugin name."""
149
168
  for plugin_name in getQtPluginNames():
150
169
  if hasActivePlugin(plugin_name):
151
170
  if hasActivePlugin(plugin_name):
@@ -154,6 +173,16 @@ def getActiveQtPlugin():
154
173
  return None
155
174
 
156
175
 
176
+ def getActiveQtPluginBindingName():
177
+ """Get active Qt plugin binding name."""
178
+ plugin_name = getActiveQtPlugin()
179
+
180
+ if plugin_name is None:
181
+ return None
182
+ else:
183
+ return getPluginClass(plugin_name).binding_name
184
+
185
+
157
186
  def getQtBindingNames():
158
187
  return ("PySide", "PySide2", "PySide6", "PyQt4", "PyQt5", "PyQt6")
159
188
 
@@ -162,6 +191,10 @@ def getOtherGUIBindingNames():
162
191
  return ("wx", "tkinter", "Tkinter")
163
192
 
164
193
 
194
+ def getGUIBindingNames():
195
+ return getQtBindingNames() + getOtherGUIBindingNames()
196
+
197
+
165
198
  def getQtPluginNames():
166
199
  return tuple(qt_binding_name.lower() for qt_binding_name in getQtBindingNames())
167
200
 
@@ -428,6 +461,7 @@ class Plugins(object):
428
461
 
429
462
  # This will get back to all other plugins allowing them to inhibit it though.
430
463
  decision, reason = Recursion.decideRecursion(
464
+ using_module_name=module.getFullName(),
431
465
  module_filename=module_filename,
432
466
  module_name=full_name,
433
467
  module_kind=module_kind,
@@ -439,7 +473,7 @@ class Plugins(object):
439
473
  module_name=full_name,
440
474
  module_filename=module_filename,
441
475
  module_kind=module_kind,
442
- using_module=module,
476
+ using_module_name=module.module_name,
443
477
  source_ref=module.getSourceReference(),
444
478
  reason=reason,
445
479
  )
@@ -969,12 +1003,13 @@ class Plugins(object):
969
1003
  return bytecode
970
1004
 
971
1005
  @staticmethod
972
- def onModuleEncounter(module_name, module_filename, module_kind):
1006
+ def onModuleEncounter(using_module_name, module_name, module_filename, module_kind):
973
1007
  result = None
974
1008
  deciding_plugins = []
975
1009
 
976
1010
  for plugin in getActivePlugins():
977
1011
  must_recurse = plugin.onModuleEncounter(
1012
+ using_module_name=using_module_name,
978
1013
  module_name=module_name,
979
1014
  module_filename=module_filename,
980
1015
  module_kind=module_kind,
@@ -1002,14 +1037,14 @@ class Plugins(object):
1002
1037
 
1003
1038
  @staticmethod
1004
1039
  def onModuleRecursion(
1005
- module_name, module_filename, module_kind, using_module, source_ref
1040
+ module_name, module_filename, module_kind, using_module_name, source_ref
1006
1041
  ):
1007
1042
  for plugin in getActivePlugins():
1008
1043
  plugin.onModuleRecursion(
1009
1044
  module_name=module_name,
1010
1045
  module_filename=module_filename,
1011
1046
  module_kind=module_kind,
1012
- using_module=using_module,
1047
+ using_module_name=using_module_name,
1013
1048
  source_ref=source_ref,
1014
1049
  )
1015
1050
 
@@ -1281,6 +1316,8 @@ class Plugins(object):
1281
1316
  module_name = provider.getParentModule().getFullName()
1282
1317
 
1283
1318
  for plugin in getActivePlugins():
1319
+ # TODO: Could record what functions got modified by what plugin
1320
+ # and in what way checking the return value
1284
1321
  plugin.onFunctionBodyParsing(
1285
1322
  module_name=module_name,
1286
1323
  function_name=function_name,
@@ -33,7 +33,7 @@ from nuitka.plugins.PluginBase import NuitkaPluginBase
33
33
  from nuitka.utils.ModuleNames import ModuleName
34
34
  from nuitka.utils.Yaml import getYamlPackageConfiguration
35
35
 
36
- # spell-checker: ignore dask,numba
36
+ # spell-checker: ignore dask,numba,statsmodels,matplotlib
37
37
 
38
38
  _mode_choices = ("error", "warning", "nofollow", "allow")
39
39
 
@@ -86,47 +86,66 @@ class NuitkaPluginAntiBloat(NuitkaPluginBase):
86
86
  self.control_tags = OrderedDict()
87
87
 
88
88
  if noinclude_setuptools_mode != "allow":
89
- self.handled_modules["setuptools"] = noinclude_setuptools_mode
90
- self.handled_modules["setuptools_scm"] = noinclude_setuptools_mode
89
+ self.handled_modules["setuptools"] = noinclude_setuptools_mode, "setuptools"
90
+ self.handled_modules["setuptools_scm"] = (
91
+ noinclude_setuptools_mode,
92
+ "setuptools",
93
+ )
91
94
  else:
92
95
  self.control_tags["use_setuptools"] = True
93
96
 
94
97
  if noinclude_pytest_mode != "allow":
95
- self.handled_modules["_pytest"] = noinclude_pytest_mode
96
- self.handled_modules["pytest"] = noinclude_pytest_mode
97
- self.handled_modules["py"] = noinclude_pytest_mode
98
- self.handled_modules["nose2"] = noinclude_pytest_mode
99
- self.handled_modules["nose"] = noinclude_pytest_mode
98
+ self.handled_modules["_pytest"] = noinclude_pytest_mode, "pytest"
99
+ self.handled_modules["pytest"] = noinclude_pytest_mode, "pytest"
100
+ self.handled_modules["py"] = noinclude_pytest_mode, "pytest"
101
+ self.handled_modules["nose2"] = noinclude_pytest_mode, "pytest"
102
+ self.handled_modules["nose"] = noinclude_pytest_mode, "pytest"
103
+ self.handled_modules["statsmodels.tools._testing"] = (
104
+ noinclude_pytest_mode,
105
+ "pytest",
106
+ )
100
107
  else:
101
108
  self.control_tags["use_pytest"] = True
102
109
 
103
110
  if noinclude_unittest_mode != "allow":
104
- self.handled_modules["unittest"] = noinclude_unittest_mode
105
- self.handled_modules["doctest"] = noinclude_unittest_mode
111
+ self.handled_modules["unittest"] = noinclude_unittest_mode, "unittest"
112
+ self.handled_modules["doctest"] = noinclude_unittest_mode, "unittest"
106
113
  else:
107
114
  self.control_tags["use_unittest"] = True
108
115
 
109
116
  if noinclude_ipython_mode != "allow":
110
- self.handled_modules["IPython"] = noinclude_ipython_mode
117
+ self.handled_modules["IPython"] = noinclude_ipython_mode, "IPython"
118
+ self.handled_modules["matplotlib_inline.backend_inline"] = (
119
+ noinclude_ipython_mode,
120
+ "IPython",
121
+ )
111
122
  else:
112
123
  self.control_tags["use_ipython"] = True
113
124
 
114
125
  if noinclude_dask_mode != "allow":
115
- self.handled_modules["dask"] = noinclude_dask_mode
126
+ self.handled_modules["dask"] = noinclude_dask_mode, "dask"
127
+ self.handled_modules["distributed"] = noinclude_dask_mode, "dask"
116
128
  else:
117
129
  self.control_tags["use_dask"] = True
118
130
 
119
131
  if noinclude_numba_mode != "allow":
120
- self.handled_modules["numba"] = noinclude_numba_mode
121
- self.handled_modules["sparse"] = noinclude_numba_mode
132
+ self.handled_modules["numba"] = noinclude_numba_mode, "numba"
133
+ self.handled_modules["sparse"] = noinclude_numba_mode, "numba"
134
+ self.handled_modules["stumpy"] = noinclude_numba_mode, "numba"
135
+ self.handled_modules["pandas.core._numba.kernels"] = (
136
+ noinclude_numba_mode,
137
+ "numba",
138
+ )
122
139
  else:
123
140
  self.control_tags["use_numba"] = True
124
141
 
125
142
  for custom_choice in custom_choices:
126
- if ":" not in custom_choice:
143
+ if custom_choice.count(":") != 1:
127
144
  self.sysexit(
128
- "Error, malformed value '%s' for '--noinclude-custom-mode' used."
129
- % custom_choice
145
+ """\
146
+ Error, malformed value '%s' for '--noinclude-custom-mode' used. It has to be of \
147
+ form 'module_name:[%s]'."""
148
+ % (custom_choice, "|".join(_mode_choices))
130
149
  )
131
150
 
132
151
  module_name, mode = custom_choice.rsplit(":", 1)
@@ -137,19 +156,40 @@ class NuitkaPluginAntiBloat(NuitkaPluginBase):
137
156
  % (mode, custom_choice)
138
157
  )
139
158
 
140
- self.handled_modules[ModuleName(module_name)] = mode
159
+ self.handled_modules[ModuleName(module_name)] = mode, module_name
141
160
 
142
161
  if mode == "allow":
143
162
  self.control_tags["use_%s" % module_name] = True
144
163
 
164
+ self.handled_module_namespaces = {}
165
+
166
+ for handled_module_name, (
167
+ mode,
168
+ intended_module_name,
169
+ ) in self.handled_modules.items():
170
+ if mode == "warning":
171
+ if intended_module_name not in self.handled_module_namespaces:
172
+ self.handled_module_namespaces[intended_module_name] = set()
173
+ self.handled_module_namespaces[intended_module_name].add(
174
+ handled_module_name
175
+ )
176
+
145
177
  self.warnings_given = set()
146
178
 
179
+ def getEvaluationConditionControlTags(self):
180
+ return self.control_tags
181
+
147
182
  def getCacheContributionValues(self, module_name):
148
183
  config = self.config.get(module_name, section="anti-bloat")
149
184
 
150
185
  if config:
151
186
  yield str(config)
152
187
 
188
+ # TODO: Until we can change the evaluation to tell us exactly what
189
+ # control tag values were used, we have to make this one. We sort
190
+ # the values, to try and have order changes in code not matter.
191
+ yield str(tuple(sorted(self.handled_modules.items())))
192
+
153
193
  @classmethod
154
194
  def addPluginCommandLineOptions(cls, group):
155
195
  group.add_option(
@@ -382,10 +422,7 @@ which can and should be a top level package and then one choice, "error",
382
422
  def onModuleSourceCode(self, module_name, source_code):
383
423
  for anti_bloat_config in self.config.get(module_name, section="anti-bloat"):
384
424
  if self.evaluateCondition(
385
- full_name=module_name,
386
- condition=anti_bloat_config.get("when", "True"),
387
- # Allow disabling config for a module with matching control tags.
388
- control_tags=self.control_tags,
425
+ full_name=module_name, condition=anti_bloat_config.get("when", "True")
389
426
  ):
390
427
  source_code = self._onModuleSourceCode(
391
428
  module_name=module_name,
@@ -414,79 +451,105 @@ which can and should be a top level package and then one choice, "error",
414
451
  function_name,
415
452
  )
416
453
 
417
- if replace_code is not None:
418
- if not context_ready:
419
- exec(context_code, context)
420
- context_ready = True
454
+ if replace_code is None:
455
+ return False
421
456
 
422
- try:
423
- replacement = eval(replace_code, context)
424
- except Exception as e: # pylint: disable=broad-except
425
- self.sysexit(
426
- "Error, cannot evaluate code '%s' in '%s' due to: %s"
427
- % (replace_code, context_code, e)
428
- )
457
+ if not context_ready:
458
+ exec(context_code, context)
459
+ context_ready = True
429
460
 
430
- # Single node is required, extract the generated module body with
431
- # single expression only statement value or a function body.
432
- replacement = ast.parse(replacement).body[0]
433
-
434
- if type(replacement) is ast.Expr:
435
- if type(replacement.value) is ast.Lambda:
436
- body[:] = [ast.Return(replacement.value.body)]
437
- else:
438
- body[:] = [ast.Return(replacement.value)]
439
- elif type(replacement) is ast.Raise:
440
- body[:] = [replacement]
461
+ try:
462
+ replacement = eval(replace_code, context)
463
+ except Exception as e: # pylint: disable=broad-except
464
+ self.sysexit(
465
+ "Error, cannot evaluate code '%s' in '%s' due to: %s"
466
+ % (replace_code, context_code, e)
467
+ )
468
+
469
+ # Single node is required, extract the generated module body with
470
+ # single expression only statement value or a function body.
471
+ replacement = ast.parse(replacement).body[0]
472
+
473
+ if type(replacement) is ast.Expr:
474
+ if type(replacement.value) is ast.Lambda:
475
+ body[:] = [ast.Return(replacement.value.body)]
441
476
  else:
442
- body[:] = replacement.body
477
+ body[:] = [ast.Return(replacement.value)]
478
+ elif type(replacement) is ast.Raise:
479
+ body[:] = [replacement]
480
+ else:
481
+ body[:] = replacement.body
443
482
 
444
- if self.show_changes:
445
- self.info(
446
- "Updated module '%s' function '%s'."
447
- % (module_name.asString(), function_name)
448
- )
483
+ if self.show_changes:
484
+ self.info(
485
+ "Updated module '%s' function '%s'."
486
+ % (module_name.asString(), function_name)
487
+ )
488
+
489
+ return True
449
490
 
450
491
  def onFunctionBodyParsing(self, module_name, function_name, body):
492
+ result = False
493
+
451
494
  config = self.config.get(module_name, section="anti-bloat")
452
495
 
453
496
  if config:
454
497
  for anti_bloat_config in config:
455
- self._onFunctionBodyParsing(
498
+ if self._onFunctionBodyParsing(
456
499
  module_name=module_name,
457
500
  anti_bloat_config=anti_bloat_config,
458
501
  function_name=function_name,
459
502
  body=body,
460
- )
503
+ ):
504
+ result = True
505
+
506
+ return result
461
507
 
462
508
  def onModuleRecursion(
463
- self, module_name, module_filename, module_kind, using_module, source_ref
509
+ self, module_name, module_filename, module_kind, using_module_name, source_ref
464
510
  ):
465
- for handled_module_name, mode in self.handled_modules.items():
511
+ # This will allow "unittest.mock" to pass these things.
512
+ if module_name == "unittest.mock" and module_name not in self.handled_modules:
513
+ return
514
+
515
+ for handled_module_name, (
516
+ mode,
517
+ intended_module_name,
518
+ ) in self.handled_modules.items():
519
+ # This will ignore internal usages. In case of error, e.g. above unittest
520
+ # could cause them to happen.
521
+ if using_module_name is not None and using_module_name.hasNamespace(
522
+ handled_module_name
523
+ ):
524
+ return
525
+
466
526
  if module_name.hasNamespace(handled_module_name):
467
527
  # Make sure the compilation aborts or warns if asked to
468
528
  if mode == "error":
469
- raise NuitkaForbiddenImportEncounter(module_name)
470
- if mode == "warning" and (
471
- (
472
- using_module is None
473
- or not using_module.getFullName().hasNamespace(
474
- handled_module_name
475
- )
529
+ raise NuitkaForbiddenImportEncounter(
530
+ module_name, intended_module_name
476
531
  )
477
- and source_ref is not None
478
- ):
532
+ if mode == "warning" and source_ref is not None:
533
+ if using_module_name.hasOneOfNamespaces(
534
+ self.handled_module_namespaces[intended_module_name]
535
+ ):
536
+ continue
537
+
479
538
  key = (
480
- handled_module_name,
481
- using_module,
539
+ module_name,
540
+ using_module_name,
482
541
  source_ref.getLineNumber(),
483
542
  )
543
+
484
544
  if key not in self.warnings_given:
485
545
  self.warning(
486
- "Undesirable import of '%s' in '%s' (at '%s') encountered. It may slow down compilation."
546
+ """\
547
+ Undesirable import of '%s' (intending to avoid '%s') in \
548
+ '%s' (at '%s') encountered. It may slow down compilation."""
487
549
  % (
488
550
  handled_module_name,
489
- using_module.getFullName(),
551
+ intended_module_name,
552
+ using_module_name,
490
553
  source_ref.getAsString(),
491
554
  ),
492
555
  mnemonic="unwanted-module",
@@ -494,26 +557,57 @@ which can and should be a top level package and then one choice, "error",
494
557
 
495
558
  self.warnings_given.add(key)
496
559
 
497
- def onModuleEncounter(self, module_name, module_filename, module_kind):
498
- for handled_module_name, mode in self.handled_modules.items():
560
+ def onModuleEncounter(
561
+ self, using_module_name, module_name, module_filename, module_kind
562
+ ):
563
+ for handled_module_name, (
564
+ mode,
565
+ intended_module_name,
566
+ ) in self.handled_modules.items():
499
567
  if module_name.hasNamespace(handled_module_name):
500
568
  # Either issue a warning, or pretend the module doesn't exist for standalone or
501
569
  # at least will not be included.
502
570
  if mode == "nofollow":
503
571
  if self.show_changes:
504
572
  self.info(
505
- "Forcing import of '%s' to not be followed." % module_name
573
+ "Forcing import of '%s' (intending to avoid '%s') to not be followed."
574
+ % (module_name, intended_module_name)
506
575
  )
507
576
  return (
508
577
  False,
509
- "user requested to not follow '%s' import" % module_name,
578
+ "user requested to not follow '%s' (intending to avoid '%s') import"
579
+ % (module_name, intended_module_name),
510
580
  )
511
581
 
582
+ if using_module_name is not None:
583
+ config = self.config.get(using_module_name, section="anti-bloat")
584
+
585
+ if config:
586
+ for anti_bloat_config in config:
587
+ match, reason = module_name.matchesToShellPatterns(
588
+ anti_bloat_config.get("no-auto-follow", ())
589
+ )
590
+
591
+ if match:
592
+ if self.evaluateCondition(
593
+ full_name=module_name,
594
+ condition=anti_bloat_config.get("when", "True"),
595
+ ):
596
+
597
+ return (
598
+ False,
599
+ "according to yaml 'no-auto-follow' configuration of '%s' and '%s'"
600
+ % (using_module_name, reason),
601
+ )
602
+
512
603
  # Do not provide an opinion about it.
513
604
  return None
514
605
 
515
606
  def decideCompilation(self, module_name):
516
- for handled_module_name, mode in self.handled_modules.items():
607
+ for handled_module_name, (
608
+ mode,
609
+ _intended_module_name,
610
+ ) in self.handled_modules.items():
517
611
  if mode != "bytecode":
518
612
  continue
519
613
 
@@ -23,9 +23,11 @@ import os
23
23
  import pkgutil
24
24
 
25
25
  from nuitka import Options
26
+ from nuitka.code_generation.ConstantCodes import addDistributionMetadataValue
26
27
  from nuitka.containers.OrderedSets import OrderedSet
27
28
  from nuitka.plugins.PluginBase import NuitkaPluginBase
28
29
  from nuitka.PythonFlavors import isDebianPackagePython
30
+ from nuitka.utils.Distributions import getDistribution
29
31
  from nuitka.utils.FileOperations import (
30
32
  changeFilenameExtension,
31
33
  getFileList,
@@ -168,6 +170,14 @@ class NuitkaPluginDataFileCollector(NuitkaPluginBase):
168
170
  tags="config",
169
171
  )
170
172
 
173
+ distribution_names = data_file_config.get("include-metadata", ())
174
+
175
+ for distribution_name in distribution_names:
176
+ distribution = getDistribution(distribution_name)
177
+
178
+ if distribution is not None:
179
+ addDistributionMetadataValue(distribution_name, distribution)
180
+
171
181
  def considerDataFiles(self, module):
172
182
  full_name = module.getFullName()
173
183
 
@@ -157,8 +157,7 @@ class NuitkaPluginDllFiles(NuitkaPluginBase):
157
157
  def _handleDllConfigByCode(self, dll_config, full_name, dest_path, count):
158
158
  # The "when" is at that level too for these.
159
159
  if not self.evaluateCondition(
160
- full_name=full_name,
161
- condition=dll_config.get("when", "True"),
160
+ full_name=full_name, condition=dll_config.get("when", "True")
162
161
  ):
163
162
  return
164
163