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
@@ -284,6 +284,7 @@ from .PackageResourceCodes import (
284
284
  generateImportlibMetadataEntryPointValueCode,
285
285
  generateImportlibMetadataSelectableGroupsValueCode,
286
286
  generateImportlibMetadataVersionCallCode,
287
+ generateImportlibResourcesFilesCallCode,
287
288
  generateImportlibResourcesReadBinaryCallCode,
288
289
  generateImportlibResourcesReadTextCallCode,
289
290
  generateOsListdirCallCode,
@@ -887,6 +888,7 @@ addExpressionDispatchDict(
887
888
  "EXPRESSION_PKG_RESOURCES_ENTRY_POINT_VALUE_REF": generatePkgResourcesEntryPointValueCode,
888
889
  "EXPRESSION_IMPORTLIB_RESOURCES_READ_BINARY_REF": generateImportModuleNameHardCode,
889
890
  "EXPRESSION_IMPORTLIB_RESOURCES_READ_TEXT_REF": generateImportModuleNameHardCode,
891
+ "EXPRESSION_IMPORTLIB_RESOURCES_FILES_REF": generateImportModuleNameHardCode,
890
892
  "EXPRESSION_IMPORTLIB_METADATA_VERSION_REF": generateImportModuleNameHardCode,
891
893
  "EXPRESSION_IMPORTLIB_METADATA_BACKPORT_VERSION_REF": generateImportModuleNameHardCode,
892
894
  "EXPRESSION_IMPORTLIB_METADATA_DISTRIBUTION_REF": generateImportModuleNameHardCode,
@@ -922,6 +924,8 @@ addExpressionDispatchDict(
922
924
  "EXPRESSION_PKG_RESOURCES_RESOURCE_STREAM_CALL": generatePkgResourcesResourceStreamCallCode,
923
925
  "EXPRESSION_IMPORTLIB_RESOURCES_READ_BINARY_CALL": generateImportlibResourcesReadBinaryCallCode,
924
926
  "EXPRESSION_IMPORTLIB_RESOURCES_READ_TEXT_CALL": generateImportlibResourcesReadTextCallCode,
927
+ "EXPRESSION_IMPORTLIB_RESOURCES_FILES_CALL": generateImportlibResourcesFilesCallCode,
928
+ "EXPRESSION_IMPORTLIB_RESOURCES_FILES_CALL_FIXED": generateImportlibResourcesFilesCallCode,
925
929
  "EXPRESSION_IMPORTLIB_METADATA_VERSION_CALL": generateImportlibMetadataVersionCallCode,
926
930
  "EXPRESSION_IMPORTLIB_METADATA_BACKPORT_VERSION_CALL": generateImportlibMetadataBackportVersionCallCode,
927
931
  "EXPRESSION_IMPORTLIB_METADATA_BACKPORT_DISTRIBUTION_CALL": generateImportlibMetadataDistributionCallCode,
@@ -527,10 +527,17 @@ def setupFunctionLocalVariables(
527
527
  context=context, variable=variable
528
528
  )
529
529
 
530
+ # Delay cell variable initialization for outlines to their own code.
531
+ if (
532
+ variable_c_type is CTypeCellObject
533
+ and variable.owner.isExpressionOutlineFunctionBase()
534
+ ):
535
+ init_value = "NULL"
536
+ else:
537
+ init_value = variable_c_type.getInitValue(None)
538
+
530
539
  variable_declaration = context.variable_storage.addVariableDeclarationTop(
531
- variable_c_type.c_type,
532
- variable_code_name,
533
- variable_c_type.getInitValue(None),
540
+ variable_c_type.c_type, variable_code_name, init_value
534
541
  )
535
542
 
536
543
  context.setVariableType(variable, variable_declaration)
@@ -778,6 +785,14 @@ def generateFunctionOutlineCode(to_name, expression, emit, context):
778
785
  if expression.isExpressionOutlineFunctionBase():
779
786
  context = PythonFunctionOutlineContext(parent=context, outline=expression)
780
787
 
788
+ for variable in expression.getUserLocalVariables():
789
+ variable_declaration = getLocalVariableDeclaration(
790
+ context=context, variable=variable, variable_trace=None
791
+ )
792
+
793
+ if variable_declaration.getCType() is CTypeCellObject:
794
+ emit("%s = Nuitka_Cell_Empty();" % variable_declaration)
795
+
781
796
  # Need to set return target, to assign to_name from.
782
797
 
783
798
  return_target = context.allocateLabel("outline_result")
@@ -34,7 +34,7 @@ def getConstantDefaultPopulation():
34
34
  be constructed through code.
35
35
  """
36
36
 
37
- # Lots of cases, pylint: disable=too-many-branches
37
+ # Lots of cases, pylint: disable=too-many-branches,too-many-statements
38
38
 
39
39
  # Note: Can't work with set here, because we need to put in some values that
40
40
  # cannot be hashed.
@@ -196,8 +196,15 @@ def getConstantDefaultPopulation():
196
196
  result.append("register")
197
197
 
198
198
  if python_version >= 0x370:
199
+ # New class method
199
200
  result.append("__class_getitem__")
200
201
 
202
+ if python_version >= 0x370:
203
+ # Reconfiguring stdout
204
+ result.append("reconfigure")
205
+ result.append("encoding")
206
+ result.append("line_buffering")
207
+
201
208
  if python_version >= 0x3A0:
202
209
  result.append("__match_args__")
203
210
 
@@ -27,6 +27,7 @@ from .CallCodes import (
27
27
  )
28
28
  from .CodeHelpers import (
29
29
  decideConversionCheckNeeded,
30
+ generateChildExpressionCode,
30
31
  generateChildExpressionsCode,
31
32
  withObjectCodeTemporaryAssignment,
32
33
  )
@@ -91,6 +92,13 @@ def generatePkgResourcesDistributionValueCode(to_name, expression, emit, context
91
92
  for kw_name in kw_names
92
93
  ]
93
94
 
95
+ # Standalone mode, has a different location.
96
+ if "location" not in kw_names:
97
+ kw_names += ("location",)
98
+ dict_value_names.append(
99
+ 'LOOKUP_BUILTIN_STR("__nuitka_binary_dir")',
100
+ )
101
+
94
102
  getCallCodeKwSplit(
95
103
  to_name=result_name,
96
104
  called_name=distribution_class_name,
@@ -725,6 +733,38 @@ def generateImportlibResourcesReadTextCallCode(to_name, expression, emit, contex
725
733
  )
726
734
 
727
735
 
736
+ def generateImportlibResourcesFilesCallCode(to_name, expression, emit, context):
737
+ package_name = generateChildExpressionCode(
738
+ expression=expression.getPackageNameUsed(),
739
+ child_name="package_name",
740
+ emit=emit,
741
+ context=context,
742
+ )
743
+
744
+ with withObjectCodeTemporaryAssignment(
745
+ to_name, "files_value", expression, emit, context
746
+ ) as result_name:
747
+ files_function = context.allocateTempName("files_function", unique=True)
748
+
749
+ getImportModuleNameHardCode(
750
+ to_name=files_function,
751
+ module_name="importlib.resources",
752
+ import_name="files",
753
+ needs_check=False,
754
+ emit=emit,
755
+ context=context,
756
+ )
757
+
758
+ getCallCodePosArgsQuick(
759
+ to_name=result_name,
760
+ called_name=files_function,
761
+ expression=expression,
762
+ arg_names=(package_name,),
763
+ emit=emit,
764
+ context=context,
765
+ )
766
+
767
+
728
768
  def generatePkgResourcesResourceStreamCallCode(to_name, expression, emit, context):
729
769
  package_name, resource_name = generateChildExpressionsCode(
730
770
  expression=expression, emit=emit, context=context
@@ -332,15 +332,9 @@ PyObject *modulecode_%(module_identifier)s(PyObject *module, struct Nuitka_MetaP
332
332
  #endif
333
333
 
334
334
  /* The constants only used by this module are created now. */
335
- #ifdef _NUITKA_TRACE
336
- PRINT_STRING("%(module_name)s: Calling createModuleConstants().\n");
337
- #endif
335
+ NUITKA_PRINT_TRACE("%(module_name)s: Calling createModuleConstants().\n");
338
336
  createModuleConstants();
339
337
 
340
- /* The code objects used by this module are created now. */
341
- #ifdef _NUITKA_TRACE
342
- PRINT_STRING("%(module_name)s: Calling createModuleCodeObjects().\n");
343
- #endif
344
338
  createModuleCodeObjects();
345
339
 
346
340
  init_done = true;
@@ -18,6 +18,7 @@
18
18
  """DLL dependency scan methods for macOS. """
19
19
 
20
20
  import os
21
+ import re
21
22
  import sys
22
23
 
23
24
  from nuitka.containers.OrderedDicts import OrderedDict
@@ -146,7 +147,7 @@ def _resolveBinaryPathDLLsMacOS(
146
147
  original_dir, binary_filename, paths, package_specific_dirs, package_name
147
148
  ):
148
149
  # Quite a few variations to consider
149
- # pylint: disable=too-many-branches,too-many-locals
150
+ # pylint: disable=too-many-branches,too-many-locals,too-many-statements
150
151
 
151
152
  had_self = False
152
153
 
@@ -204,6 +205,22 @@ def _resolveBinaryPathDLLsMacOS(
204
205
  if candidate is not None and os.path.exists(candidate):
205
206
  resolved_path = candidate
206
207
 
208
+ # Sometimes self-dependencies are on a numbered version, but deployed is
209
+ # one version without it. The macOS just ignores that, and so we do.
210
+ if not os.path.exists(resolved_path):
211
+ match = re.match(r"^(.*)\.\d+\.dylib$", resolved_path)
212
+
213
+ if match:
214
+ candidate = match.group(1) + ".dylib"
215
+
216
+ if os.path.exists(candidate):
217
+ resolved_path = candidate
218
+ else:
219
+ candidate = os.path.join(original_dir, os.path.basename(candidate))
220
+
221
+ if os.path.exists(candidate):
222
+ resolved_path = candidate
223
+
207
224
  if not os.path.exists(resolved_path):
208
225
  acceptable, plugin_name = Plugins.isAcceptableMissingDLL(
209
226
  package_name=package_name,
@@ -49,7 +49,6 @@ from nuitka.utils.FileOperations import (
49
49
  isRelativePath,
50
50
  makePath,
51
51
  openTextFile,
52
- putTextFileContents,
53
52
  relpath,
54
53
  resolveShellPatternToFilenames,
55
54
  )
@@ -251,10 +250,10 @@ def makeIncludedDataDirectory(
251
250
  def makeIncludedGeneratedDataFile(data, dest_path, reason, tracer, tags):
252
251
  assert isRelativePath(dest_path), dest_path
253
252
 
254
- # Handle lists of bytes here already by converting to single bytes value.
255
- if type(data) is list:
256
- if str is not bytes and all(type(element) is bytes for element in data):
257
- data = b"\n".join(data)
253
+ if type(data) is str and str is not bytes:
254
+ data = data.encode("utf8")
255
+
256
+ assert type(data) is bytes, type(data)
258
257
 
259
258
  return IncludedDataFile(
260
259
  kind="data_blob",
@@ -520,11 +519,8 @@ def _handleDataFile(included_datafile):
520
519
  dest_path = os.path.join(dist_dir, included_datafile.dest_path)
521
520
  makePath(os.path.dirname(dest_path))
522
521
 
523
- if type(included_datafile.data) is bytes:
524
- with openTextFile(filename=dest_path, mode="wb") as output_file:
525
- output_file.write(included_datafile.data)
526
- else:
527
- putTextFileContents(filename=dest_path, contents=included_datafile.data)
522
+ with openTextFile(filename=dest_path, mode="wb") as output_file:
523
+ output_file.write(included_datafile.data)
528
524
  elif included_datafile.kind == "data_file":
529
525
  dest_path = os.path.join(dist_dir, included_datafile.dest_path)
530
526
 
@@ -23,6 +23,9 @@ from nuitka.__past__ import unicode
23
23
  from nuitka.PythonVersions import python_version
24
24
  from nuitka.utils.ModuleNames import ModuleName
25
25
 
26
+ # spell-checker: ignore Tkdnd gdbm cookielib htmlentitydefs CGIHTTPServer Tkconstants
27
+ # spell-checker: ignore tkinter_tkfiledialog tkinter_tksimpledialog xmlrpclib
28
+
26
29
  _six_moves = {
27
30
  "six.moves.builtins": "__builtin__" if python_version < 0x300 else "builtins",
28
31
  "six.moves.configparser": "ConfigParser"
@@ -117,6 +120,9 @@ _six_moves = {
117
120
  if python_version < 0x300
118
121
  else "xmlrpc.server",
119
122
  "six.moves.winreg": "_winreg" if python_version < 0x300 else "winreg",
123
+ "six.moves.urllib.request": "urllib2"
124
+ if python_version < 0x300
125
+ else "urllib.request",
120
126
  }
121
127
 
122
128
 
@@ -34,8 +34,6 @@ from nuitka.utils.FileOperations import listDir
34
34
  from nuitka.utils.Importing import getSharedLibrarySuffixes
35
35
  from nuitka.utils.ModuleNames import ModuleName
36
36
 
37
- from .Importing import locateModule
38
-
39
37
 
40
38
  def _recurseTo(module_name, module_filename, module_kind):
41
39
  from nuitka.tree import Building
@@ -61,7 +59,7 @@ def recurseTo(
61
59
  module_name,
62
60
  module_filename,
63
61
  module_kind,
64
- using_module,
62
+ using_module_name,
65
63
  source_ref,
66
64
  reason,
67
65
  ):
@@ -77,7 +75,7 @@ def recurseTo(
77
75
  module_filename=module_filename,
78
76
  module_name=module_name,
79
77
  module_kind=module_kind,
80
- using_module=using_module,
78
+ using_module_name=using_module_name,
81
79
  source_ref=source_ref,
82
80
  )
83
81
 
@@ -96,18 +94,26 @@ def recurseTo(
96
94
  _recursion_decision_cache = {}
97
95
 
98
96
 
99
- def decideRecursion(module_filename, module_name, module_kind, extra_recursion=False):
100
- key = module_filename, module_name, module_kind, extra_recursion
97
+ def decideRecursion(
98
+ using_module_name, module_filename, module_name, module_kind, extra_recursion=False
99
+ ):
100
+ key = using_module_name, module_filename, module_name, module_kind, extra_recursion
101
101
 
102
102
  if key not in _recursion_decision_cache:
103
103
  _recursion_decision_cache[key] = _decideRecursion(
104
- module_filename, module_name, module_kind, extra_recursion
104
+ using_module_name,
105
+ module_filename,
106
+ module_name,
107
+ module_kind,
108
+ extra_recursion,
105
109
  )
106
110
 
107
111
  return _recursion_decision_cache[key]
108
112
 
109
113
 
110
- def _decideRecursion(module_filename, module_name, module_kind, extra_recursion):
114
+ def _decideRecursion(
115
+ using_module_name, module_filename, module_name, module_kind, extra_recursion
116
+ ):
111
117
  # Many branches, which make decisions immediately, by returning
112
118
  # pylint: disable=too-many-branches,too-many-return-statements
113
119
  if module_name == "__main__":
@@ -123,6 +129,7 @@ def _decideRecursion(module_filename, module_name, module_kind, extra_recursion)
123
129
  return False, "Main program is already included in package mode."
124
130
 
125
131
  plugin_decision = Plugins.onModuleEncounter(
132
+ using_module_name=using_module_name,
126
133
  module_filename=module_filename,
127
134
  module_name=module_name,
128
135
  module_kind=module_kind,
@@ -292,6 +299,7 @@ the compiled result, and therefore asking to include them makes no sense.
292
299
 
293
300
  if module_kind is not None:
294
301
  decision, reason = decideRecursion(
302
+ using_module_name=None,
295
303
  module_filename=plugin_filename,
296
304
  module_name=module_name,
297
305
  module_kind=module_kind,
@@ -304,7 +312,7 @@ the compiled result, and therefore asking to include them makes no sense.
304
312
  module_filename=plugin_filename,
305
313
  module_name=module_name,
306
314
  module_kind=module_kind,
307
- using_module=None,
315
+ using_module_name=None,
308
316
  source_ref=None,
309
317
  reason=reason,
310
318
  )
@@ -376,53 +384,6 @@ def checkPluginFilenamePattern(pattern):
376
384
  )
377
385
 
378
386
 
379
- def _addParentPackageUsages(using_module, module_name, signal_change, source_ref):
380
- for parent_package_name in module_name.getParentPackageNames():
381
- (
382
- _parent_package_name,
383
- parent_package_filename,
384
- package_module_kind,
385
- finding,
386
- ) = locateModule(module_name=parent_package_name, parent_package=None, level=0)
387
-
388
- if parent_package_filename is None:
389
- recursion_logger.sysexit(
390
- "Error, failed to locate parent package file for '%s' parent of '%s' (used by '%s') module (%s)"
391
- % (
392
- parent_package_name,
393
- module_name,
394
- using_module.getFullName(),
395
- finding,
396
- )
397
- )
398
-
399
- assert _parent_package_name == parent_package_name
400
-
401
- _decision, reason = decideRecursion(
402
- module_filename=parent_package_filename,
403
- module_name=parent_package_name,
404
- module_kind=package_module_kind,
405
- )
406
-
407
- used_package_module = recurseTo(
408
- signal_change=signal_change,
409
- module_name=parent_package_name,
410
- module_filename=parent_package_filename,
411
- module_kind=package_module_kind,
412
- using_module=using_module,
413
- source_ref=source_ref,
414
- reason=reason,
415
- )
416
-
417
- addUsedModule(
418
- module=used_package_module,
419
- using_module=using_module,
420
- usage_tag="package",
421
- reason=reason,
422
- source_ref=source_ref,
423
- )
424
-
425
-
426
387
  def considerUsedModules(module, signal_change):
427
388
  for used_module in module.getUsedModules():
428
389
  if used_module.finding == "not-found":
@@ -439,26 +400,20 @@ def considerUsedModules(module, signal_change):
439
400
 
440
401
  try:
441
402
  decision, reason = decideRecursion(
403
+ using_module_name=module.getFullName(),
442
404
  module_filename=used_module.filename,
443
405
  module_name=used_module.module_name,
444
406
  module_kind=used_module.module_kind,
445
407
  )
446
408
 
447
409
  if decision:
448
- _addParentPackageUsages(
449
- using_module=module,
450
- module_name=used_module.module_name,
451
- signal_change=signal_change,
452
- source_ref=used_module.source_ref,
453
- )
454
-
455
410
  new_module = recurseTo(
456
411
  signal_change=signal_change,
457
412
  module_name=used_module.module_name,
458
413
  module_filename=used_module.filename,
459
414
  module_kind=used_module.module_kind,
460
415
  source_ref=used_module.source_ref,
461
- using_module=module,
416
+ using_module_name=module.module_name,
462
417
  reason=reason,
463
418
  )
464
419
 
@@ -471,9 +426,10 @@ def considerUsedModules(module, signal_change):
471
426
  )
472
427
  except NuitkaForbiddenImportEncounter as e:
473
428
  recursion_logger.sysexit(
474
- "Error, forbidden import of '%s' in module '%s' at '%s' encountered."
429
+ "Error, forbidden import of '%s' (intending to avoid '%s') in module '%s' at '%s' encountered."
475
430
  % (
476
- e,
431
+ e.args[0],
432
+ e.args[1],
477
433
  module.getFullName(),
478
434
  used_module.source_ref.getAsString(),
479
435
  )
@@ -483,6 +439,6 @@ def considerUsedModules(module, signal_change):
483
439
  Plugins.considerImplicitImports(module=module, signal_change=signal_change)
484
440
  except NuitkaForbiddenImportEncounter as e:
485
441
  recursion_logger.sysexit(
486
- "Error, forbidden import of '%s' done implicitly by module '%s'."
487
- % (e, module.getFullName())
442
+ "Error, forbidden import of '%s' (intending to avoid '%s') done implicitly by module '%s'."
443
+ % (e.args[0], e.args[1], module.getFullName())
488
444
  )
@@ -34,16 +34,23 @@ work on, and let them decide and do the heavy lifting of optimization
34
34
  and annotation is happening in the nodes that implement these compute slots.
35
35
  """
36
36
 
37
+ from nuitka.__past__ import unicode
38
+
37
39
  from .AttributeLookupNodes import ExpressionAttributeLookup
38
40
  from .ChildrenHavingMixins import (
39
41
  ChildHavingExpressionMixin,
40
42
  ChildrenExpressionBuiltinGetattrMixin,
41
- ChildrenExpressionBuiltinHasattrMixin,
42
43
  ChildrenExpressionBuiltinSetattrMixin,
43
44
  )
44
45
  from .ExpressionBases import ExpressionBase
46
+ from .ExpressionBasesGenerated import ExpressionBuiltinHasattrBase
47
+ from .ExpressionShapeMixins import (
48
+ ExpressionBoolShapeExactMixin,
49
+ ExpressionNoneShapeExactMixin,
50
+ )
45
51
  from .NodeMakingHelpers import (
46
52
  makeCompileTimeConstantReplacementNode,
53
+ makeRaiseExceptionReplacementExpression,
47
54
  wrapExpressionWithNodeSideEffects,
48
55
  )
49
56
  from .StatementBasesGenerated import (
@@ -202,7 +209,9 @@ attribute '%s' to mere attribute lookup"""
202
209
  return self, None, None
203
210
 
204
211
 
205
- class ExpressionBuiltinSetattr(ChildrenExpressionBuiltinSetattrMixin, ExpressionBase):
212
+ class ExpressionBuiltinSetattr(
213
+ ExpressionNoneShapeExactMixin, ChildrenExpressionBuiltinSetattrMixin, ExpressionBase
214
+ ):
206
215
  """Built-in "setattr".
207
216
 
208
217
  Typical code like this: setattr(source, attribute, value)
@@ -210,13 +219,13 @@ class ExpressionBuiltinSetattr(ChildrenExpressionBuiltinSetattrMixin, Expression
210
219
 
211
220
  kind = "EXPRESSION_BUILTIN_SETATTR"
212
221
 
213
- named_children = ("expression", "attribute", "value")
222
+ named_children = ("expression", "name", "value")
214
223
 
215
224
  def __init__(self, expression, name, value, source_ref):
216
225
  ChildrenExpressionBuiltinSetattrMixin.__init__(
217
226
  self,
218
227
  expression=expression,
219
- attribute=name,
228
+ name=name,
220
229
  value=value,
221
230
  )
222
231
 
@@ -240,17 +249,12 @@ class ExpressionBuiltinSetattr(ChildrenExpressionBuiltinSetattrMixin, Expression
240
249
  return self, None, None
241
250
 
242
251
 
243
- class ExpressionBuiltinHasattr(ChildrenExpressionBuiltinHasattrMixin, ExpressionBase):
252
+ class ExpressionBuiltinHasattr(ExpressionBuiltinHasattrBase):
244
253
  kind = "EXPRESSION_BUILTIN_HASATTR"
245
254
 
246
- named_children = ("expression", "attribute")
255
+ named_children = ("expression", "name")
247
256
 
248
- def __init__(self, expression, name, source_ref):
249
- ChildrenExpressionBuiltinHasattrMixin.__init__(
250
- self, expression=expression, attribute=name
251
- )
252
-
253
- ExpressionBase.__init__(self, source_ref)
257
+ auto_compute_handling = "wait_constant:name,raise"
254
258
 
255
259
  def computeExpression(self, trace_collection):
256
260
  # We do at least for compile time constants optimization here, but more
@@ -258,7 +262,7 @@ class ExpressionBuiltinHasattr(ChildrenExpressionBuiltinHasattrMixin, Expression
258
262
  source = self.subnode_expression
259
263
 
260
264
  if source.isCompileTimeConstant():
261
- attribute = self.subnode_attribute
265
+ attribute = self.subnode_name
262
266
 
263
267
  attribute_name = attribute.getStringValue()
264
268
 
@@ -292,8 +296,42 @@ class ExpressionBuiltinHasattr(ChildrenExpressionBuiltinHasattrMixin, Expression
292
296
 
293
297
  return self, None, None
294
298
 
299
+ def computeExpressionConstantName(self, trace_collection):
300
+ attribute_name = self.subnode_name.getCompileTimeConstant()
301
+
302
+ if type(attribute_name) not in (str, unicode):
303
+ result = makeRaiseExceptionReplacementExpression(
304
+ expression=self,
305
+ exception_type="TypeError",
306
+ exception_value="attribute name must be string",
307
+ )
308
+
309
+ return (
310
+ result,
311
+ "new_raise",
312
+ "Call to hasattr with non-str type %s attribute name"
313
+ % type(attribute_name),
314
+ )
315
+
316
+ if str is not unicode:
317
+ attribute_name = attribute_name.encode()
318
+
319
+ result = ExpressionAttributeCheck(
320
+ expression=self.subnode_expression,
321
+ attribute_name=attribute_name,
322
+ source_ref=self.source_ref,
323
+ )
295
324
 
296
- class ExpressionAttributeCheck(ChildHavingExpressionMixin, ExpressionBase):
325
+ return trace_collection.computedExpressionResult(
326
+ expression=result,
327
+ change_tags="new_expression",
328
+ change_desc="Built-in 'hasattr' with constant attribute name.",
329
+ )
330
+
331
+
332
+ class ExpressionAttributeCheck(
333
+ ExpressionBoolShapeExactMixin, ChildHavingExpressionMixin, ExpressionBase
334
+ ):
297
335
  kind = "EXPRESSION_ATTRIBUTE_CHECK"
298
336
 
299
337
  named_children = ("expression",)
@@ -330,15 +368,30 @@ class ExpressionAttributeCheck(ChildHavingExpressionMixin, ExpressionBase):
330
368
  "Attribute check has been pre-computed to '%s'." % has_attribute,
331
369
  )
332
370
 
333
- # Attribute check is implemented by getting an attribute.
334
- if source.mayRaiseExceptionAttributeLookup(BaseException, self.attribute_name):
371
+ # Attribute check does not raise is implemented by getting an attribute.
372
+ if self.mayRaiseExceptionOperation():
335
373
  trace_collection.onExceptionRaiseExit(BaseException)
336
374
 
337
375
  return self, None, None
338
376
 
339
- @staticmethod
340
- def mayRaiseException(exception_type):
341
- return False
377
+ def mayRaiseException(self, exception_type):
378
+ return (
379
+ self.subnode_expression.mayRaiseException(exception_type)
380
+ or self.mayRaiseExceptionOperation()
381
+ )
382
+
383
+ if str is bytes:
384
+
385
+ @staticmethod
386
+ def mayRaiseExceptionOperation():
387
+ return False
388
+
389
+ else:
390
+
391
+ def mayRaiseExceptionOperation(self):
392
+ return self.subnode_expression.mayRaiseExceptionAttributeLookup(
393
+ BaseException, self.attribute_name
394
+ )
342
395
 
343
396
  def getAttributeName(self):
344
397
  return self.attribute_name