Cython 3.2.0b2__py3-none-any.whl → 3.2.1__py3-none-any.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.
Cython/Compiler/Code.py CHANGED
@@ -402,7 +402,7 @@ class AbstractUtilityCode:
402
402
 
403
403
  requires = None
404
404
 
405
- def put_code(self, output):
405
+ def put_code(self, globalstate: "GlobalState", used_by=None) -> None:
406
406
  pass
407
407
 
408
408
  def get_tree(self, **kwargs):
@@ -463,7 +463,7 @@ class UtilityCodeBase(AbstractUtilityCode):
463
463
  # section title
464
464
  r'^%(C)s{5,30} \s* (?P<name> (?:\w|\.)+ ) \s* %(C)s{5,30} |'
465
465
  # section tags and dependencies
466
- r'^%(C)s+ @(?P<tag> \w+) \s* : \s* (?P<value> (?: \w|[.:] )+ )'
466
+ r'^%(C)s+ @(?P<tag> .+)'
467
467
  ) % {'C': re.escape(line_comment_char)}, re.VERBOSE).match
468
468
 
469
469
  @classmethod
@@ -496,8 +496,8 @@ class UtilityCodeBase(AbstractUtilityCode):
496
496
 
497
497
  if tags:
498
498
  all_tags = utility[2]
499
- for name, values in tags.items():
500
- all_tags.setdefault(name, set()).update(values)
499
+ for tag_name, tag_values in tags.items():
500
+ all_tags.setdefault(tag_name, set()).update(tag_values)
501
501
 
502
502
  @classmethod
503
503
  def load_utilities_from_file(cls, path):
@@ -528,26 +528,38 @@ class UtilityCodeBase(AbstractUtilityCode):
528
528
 
529
529
  for lineno, line in enumerate(all_lines):
530
530
  m = match_special(line)
531
- if m:
532
- if m.group('name'):
533
- cls._add_utility(utility, name, type, lines, begin_lineno, tags)
534
-
535
- begin_lineno = lineno + 1
536
- del lines[:]
537
- tags.clear()
538
-
539
- name = m.group('name')
540
- mtype = match_type(name)
541
- if mtype:
542
- name, type = mtype.groups()
543
- else:
544
- type = 'impl'
545
- utility = utilities[name]
531
+ if m is None:
532
+ lines.append(rstrip(strip_comments(line)))
533
+ elif m.group('name'):
534
+ cls._add_utility(utility, name, type, lines, begin_lineno, tags)
535
+
536
+ begin_lineno = lineno + 1
537
+ del lines[:]
538
+ tags.clear()
539
+
540
+ name = m.group('name')
541
+ mtype = match_type(name)
542
+ if mtype:
543
+ name, type = mtype.groups()
546
544
  else:
547
- tags[m.group('tag')].add(m.group('value'))
548
- lines.append('') # keep line number correct
545
+ type = 'impl'
546
+ utility = utilities[name]
549
547
  else:
550
- lines.append(rstrip(strip_comments(line)))
548
+ tag_value = m.group('tag')
549
+ if ':' not in tag_value:
550
+ raise RuntimeError(f"Found invalid tag '{tag_value}' in utility section {name}.{type}")
551
+
552
+ tag_name, _, tag_value = tag_value.partition(':')
553
+ tag_name = tag_name.rstrip()
554
+ tag_value = tag_value.strip()
555
+
556
+ if tag_name not in ('requires', 'substitute', 'proto_block'):
557
+ raise RuntimeError(f"Found unknown tag name '{tag_name}' in utility section {name}.{type}")
558
+ if not re.match(r'\S+$', tag_value):
559
+ raise RuntimeError(f"Found invalid tag value '{tag_value}' in utility section {name}.{type}")
560
+
561
+ tags[tag_name].add(tag_value)
562
+ lines.append('') # keep line number correct
551
563
 
552
564
  if utility is None:
553
565
  raise ValueError("Empty utility code file")
@@ -726,6 +738,8 @@ class UtilityCode(UtilityCodeBase):
726
738
  self.file = file
727
739
  self.export = export
728
740
  self.shared_utility_functions = self.parse_export_functions(export) if export else []
741
+ if export:
742
+ self._validate_suitable_for_sharing()
729
743
 
730
744
  # cached for use in hash and eq
731
745
  self._parts_tuple = tuple(getattr(self, part, None) for part in self.code_parts)
@@ -812,8 +826,14 @@ class UtilityCode(UtilityCodeBase):
812
826
  self.specialize_list.append(s)
813
827
  return s
814
828
 
829
+ def _validate_suitable_for_sharing(self):
830
+ code_string = getattr(self, "impl")
831
+ if not code_string: return
832
+ assert "NAMED_CGLOBAL(moddict_cname)" not in code_string, \
833
+ f"moddict_cname should not be shared: {self}"
834
+
815
835
  @cython.final
816
- def _put_code_section(self, writer: "CCodeWriter", output: "GlobalState", code_type: str):
836
+ def _put_code_section(self, writer: "CCodeWriter", output: "GlobalState", code_type: str, used_by=None):
817
837
  code_string = getattr(self, code_type)
818
838
  if not code_string:
819
839
  return
@@ -822,8 +842,10 @@ class UtilityCode(UtilityCodeBase):
822
842
 
823
843
  code_string, result_is_module_specific = process_utility_ccode(self, output, code_string)
824
844
 
825
- code_type_name = code_type if code_type != 'impl' else ''
826
- writer.putln(f"/* {self.name}{'.' if code_type_name else ''}{code_type_name} */")
845
+ used_by = f" (used by {used_by})" if used_by else ''
846
+ name = f"{self.name}.{code_type}" if code_type != 'impl' else self.name
847
+
848
+ writer.putln(f"/* {name}{used_by} */")
827
849
 
828
850
  if can_be_reused and not result_is_module_specific:
829
851
  # can be reused across modules
@@ -848,36 +870,36 @@ class UtilityCode(UtilityCodeBase):
848
870
  code.putln(f'static {shared.ret}(*{shared.name})({shared.params}); /*proto*/')
849
871
  code.putln()
850
872
 
851
- def put_code(self, output: "GlobalState") -> None:
873
+ def put_code(self, globalstate: "GlobalState", used_by=None) -> None:
852
874
  has_shared_utility_code = bool(
853
- self.shared_utility_functions and output.module_node.scope.context.shared_utility_qualified_name
875
+ self.shared_utility_functions and globalstate.module_node.scope.context.shared_utility_qualified_name
854
876
  )
855
877
 
856
878
  if self.requires and not has_shared_utility_code:
857
879
  for dependency in self.requires:
858
- output.use_utility_code(dependency)
880
+ globalstate.use_utility_code(dependency, used_by=self.name)
859
881
 
860
882
  if has_shared_utility_code:
861
- self._put_shared_function_declarations(output[self.proto_block])
862
- output.shared_utility_functions.extend(self.shared_utility_functions)
883
+ self._put_shared_function_declarations(globalstate[self.proto_block])
884
+ globalstate.shared_utility_functions.extend(self.shared_utility_functions)
863
885
 
864
886
  if self.proto:
865
- self._put_code_section(output[self.proto_block], output, 'proto')
887
+ self._put_code_section(globalstate[self.proto_block], globalstate, 'proto', used_by=used_by)
866
888
  if not has_shared_utility_code:
867
- self._put_code_section(output[self.proto_block], output, 'export')
889
+ self._put_code_section(globalstate[self.proto_block], globalstate, 'export')
868
890
  if self.impl and not has_shared_utility_code:
869
- self._put_code_section(output['utility_code_def'], output, 'impl')
891
+ self._put_code_section(globalstate['utility_code_def'], globalstate, 'impl', used_by=used_by)
870
892
  if self.cleanup and Options.generate_cleanup_code:
871
- self._put_code_section(output['cleanup_globals'], output, 'cleanup')
893
+ self._put_code_section(globalstate['cleanup_globals'], globalstate, 'cleanup')
872
894
  if self.module_state_decls:
873
- self._put_code_section(output['module_state_contents'], output, 'module_state_decls')
895
+ self._put_code_section(globalstate['module_state_contents'], globalstate, 'module_state_decls')
874
896
  if self.module_state_traverse:
875
- self._put_code_section(output['module_state_traverse_contents'], output, 'module_state_traverse')
897
+ self._put_code_section(globalstate['module_state_traverse_contents'], globalstate, 'module_state_traverse')
876
898
  if self.module_state_clear:
877
- self._put_code_section(output['module_state_clear_contents'], output, 'module_state_clear')
899
+ self._put_code_section(globalstate['module_state_clear_contents'], globalstate, 'module_state_clear')
878
900
 
879
901
  if self.init:
880
- self._put_init_code_section(output)
902
+ self._put_init_code_section(globalstate)
881
903
 
882
904
 
883
905
  def add_macro_processor(*macro_names, regex=None, is_module_specific=False, _last_macro_processor = [None]):
@@ -1076,9 +1098,9 @@ class LazyUtilityCode(UtilityCodeBase):
1076
1098
  def __init__(self, callback):
1077
1099
  self.callback = callback
1078
1100
 
1079
- def put_code(self, globalstate):
1101
+ def put_code(self, globalstate: "GlobalState", used_by=None) -> None:
1080
1102
  utility = self.callback(globalstate.rootwriter)
1081
- globalstate.use_utility_code(utility)
1103
+ globalstate.use_utility_code(utility, used_by=used_by)
1082
1104
 
1083
1105
 
1084
1106
  class FunctionState:
@@ -2459,7 +2481,7 @@ class GlobalState:
2459
2481
  # Utility code state
2460
2482
  #
2461
2483
 
2462
- def use_utility_code(self, utility_code):
2484
+ def use_utility_code(self, utility_code, used_by=None):
2463
2485
  """
2464
2486
  Adds code to the C file. utility_code should
2465
2487
  a) implement __eq__/__hash__ for the purpose of knowing whether the same
@@ -2470,7 +2492,7 @@ class GlobalState:
2470
2492
  """
2471
2493
  if utility_code and utility_code not in self.utility_codes:
2472
2494
  self.utility_codes.add(utility_code)
2473
- utility_code.put_code(self)
2495
+ utility_code.put_code(self, used_by=used_by)
2474
2496
 
2475
2497
  def use_entry_utility_code(self, entry):
2476
2498
  if entry is None:
@@ -2479,6 +2501,10 @@ class GlobalState:
2479
2501
  self.use_utility_code(entry.utility_code)
2480
2502
  if entry.utility_code_definition:
2481
2503
  self.use_utility_code(entry.utility_code_definition)
2504
+ from . import PyrexTypes
2505
+ for tp in PyrexTypes.get_all_subtypes(entry.type):
2506
+ if hasattr(tp, "entry") and tp.entry is not entry:
2507
+ self.use_entry_utility_code(tp.entry)
2482
2508
 
2483
2509
 
2484
2510
  def funccontext_property(func):
@@ -2968,7 +2994,7 @@ class CCodeWriter:
2968
2994
  elif entry.type.is_pyobject:
2969
2995
  self.put(" = NULL")
2970
2996
  self.putln(";")
2971
- self.funcstate.scope.use_entry_utility_code(entry)
2997
+ self.globalstate.use_entry_utility_code(entry)
2972
2998
 
2973
2999
  def put_temp_declarations(self, func_context: FunctionState):
2974
3000
  for name, type, manage_ref, static in func_context.temps_allocated:
@@ -25,12 +25,16 @@ class CythonScope(ModuleScope):
25
25
  cname='<error>')
26
26
  entry.in_cinclude = True
27
27
 
28
+ cy_pymutex_type = get_cy_pymutex_type()
28
29
  entry = self.declare_type(
29
30
  "pymutex", cy_pymutex_type, None,
30
31
  cname="__Pyx_Locks_PyMutex")
32
+ entry.utility_code_definition = cy_pymutex_type.get_decl_utility_code()
33
+ cy_pythread_type_lock_type = get_cy_pythread_type_lock_type()
31
34
  entry = self.declare_type(
32
35
  "pythread_type_lock", cy_pythread_type_lock_type, None,
33
36
  cname="__Pyx_Locks_PyThreadTypeLock")
37
+ entry.utility_code_definition = cy_pythread_type_lock_type.get_decl_utility_code()
34
38
 
35
39
  def is_cpp(self):
36
40
  # Allow C++ utility code in C++ contexts.
@@ -76,6 +76,9 @@ class NotConstant:
76
76
  not_a_constant = NotConstant()
77
77
  constant_value_not_set = object()
78
78
 
79
+ def _type_to_itself(tp):
80
+ return tp, tp
81
+
79
82
  # error messages when coercing from key[0] to key[1]
80
83
  coercion_error_dict = {
81
84
  # string related errors
@@ -94,9 +97,9 @@ coercion_error_dict = {
94
97
  (PyrexTypes.c_uchar_ptr_type, unicode_type): "Cannot convert 'char*' to unicode implicitly, decoding required",
95
98
  (PyrexTypes.c_const_uchar_ptr_type, unicode_type): (
96
99
  "Cannot convert 'char*' to unicode implicitly, decoding required"),
97
- (PyrexTypes.cy_pymutex_type, PyrexTypes.cy_pymutex_type): (
100
+ _type_to_itself(PyrexTypes.get_cy_pymutex_type()): (
98
101
  "cython.pymutex cannot be copied"),
99
- (PyrexTypes.cy_pythread_type_lock_type, PyrexTypes.cy_pythread_type_lock_type): (
102
+ _type_to_itself(PyrexTypes.get_cy_pythread_type_lock_type()): (
100
103
  "cython.pythread_type_lock cannot be copied"),
101
104
  }
102
105
 
@@ -9167,9 +9170,12 @@ class ListNode(SequenceNode):
9167
9170
  else:
9168
9171
  if len(self.args) < len(dst_type.scope.var_entries):
9169
9172
  warning(self.pos, "Too few members for '%s'" % dst_type, 1)
9170
- for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
9173
+ for i, (arg, coerced_arg, member) in enumerate(zip(self.original_args, self.args, dst_type.scope.var_entries)):
9171
9174
  if isinstance(arg, CoerceToPyTypeNode):
9172
9175
  arg = arg.arg
9176
+ elif member.type.is_struct_or_union and coerced_arg.is_dict_literal:
9177
+ # For struct assignments, use the coerced dict directly, not a struct type call etc.
9178
+ arg = coerced_arg
9173
9179
  self.args[i] = arg.coerce_to(member.type, env)
9174
9180
  self.type = dst_type
9175
9181
  elif dst_type.is_ctuple:
@@ -518,7 +518,6 @@ def get_copy_new_utility(pos, from_memview, to_memview):
518
518
  func_cname=copy_c_or_fortran_cname(to_memview),
519
519
  dtype_is_object=int(to_memview.dtype.is_pyobject),
520
520
  ),
521
- requires=[copy_contents_new_utility],
522
521
  )
523
522
 
524
523
 
@@ -847,12 +846,7 @@ overlapping_utility = load_memview_c_utility("OverlappingSlices")
847
846
  refcount_utility = load_memview_c_utility("MemviewRefcount")
848
847
  slice_init_utility = load_memview_c_utility("MemviewSliceInit")
849
848
  memviewslice_declare_code = load_memview_c_utility("MemviewSliceStruct", context=template_context)
850
-
851
- copy_contents_new_utility = load_memview_c_utility(
852
- "MemviewSliceCopyTemplate",
853
- context=template_context,
854
- # Requires general memoryview code - dependency is added below.
855
- )
849
+ copy_contents_new_utility = load_memview_c_utility("MemviewSliceCopy")
856
850
 
857
851
 
858
852
  @Utils.cached_function
@@ -887,7 +881,6 @@ def _get_memoryview_shared_utility_code(shared_utility_qualified_name):
887
881
  memviewslice_declare_code,
888
882
  refcount_utility,
889
883
  atomic_utility,
890
- copy_contents_new_utility,
891
884
  ],
892
885
  )
893
886
 
@@ -161,7 +161,7 @@ class SharedUtilityExporter:
161
161
  shared_utility_qualified_name = EncodedString(self.scope.context.shared_utility_qualified_name)
162
162
  import_func = f"__Pyx_ImportFunction_{Naming.cyversion}"
163
163
  _generate_import_code(
164
- code, self.pos, imports, shared_utility_qualified_name, import_func, "void (*{name})(void)")
164
+ code, self.pos, imports, shared_utility_qualified_name, import_func, "void (**{name})(void)")
165
165
 
166
166
  def _generate_exports(self, shared_utility_functions: Sequence[Code.SharedFunctionDecl]):
167
167
  if self.has_shared_exports(shared_utility_functions):
@@ -285,7 +285,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
285
285
 
286
286
  self.body.analyse_declarations(env)
287
287
 
288
- if env.find_shared_usages_of_type(lambda tp: tp is PyrexTypes.cy_pymutex_type):
288
+ cy_pymutex_type = PyrexTypes.get_cy_pymutex_type()
289
+ if env.find_shared_usages_of_type(cy_pymutex_type):
289
290
  # Be very suspicious of cython locks that are shared.
290
291
  # They have the potential to cause ABI issues.
291
292
  self.scope.use_utility_code(
@@ -362,30 +363,33 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
362
363
  h_code_start.put_h_guard(h_guard)
363
364
  h_code_start.putln("")
364
365
  h_code_start.putln('#include "Python.h"')
365
- self.generate_type_header_code(h_types, h_code_start)
366
+ self.generate_type_header_code(h_types, h_code_main)
366
367
  if options.capi_reexport_cincludes:
367
- self.generate_includes(env, [], h_code_start)
368
- h_code_start.putln("")
368
+ self.generate_includes(env, [], h_code_main)
369
+ h_code_main.putln("")
369
370
  api_guard = self.api_name(Naming.api_guard_prefix, env)
370
- h_code_start.putln("#ifndef %s" % api_guard)
371
- h_code_start.putln("")
372
- self.generate_extern_c_macro_definition(h_code_start, env.is_cpp())
373
- h_code_start.putln("")
374
- self.generate_dl_import_macro(h_code_start)
371
+ h_code_main.putln("#ifndef %s" % api_guard)
372
+ h_code_main.putln("")
373
+ self.generate_extern_c_macro_definition(h_code_main, env.is_cpp())
374
+ h_code_main.putln("")
375
+ self.generate_dl_import_macro(h_code_main)
375
376
  if h_extension_types:
376
377
  h_code_main.putln("")
377
378
  for entry in h_extension_types:
378
379
  self.generate_cclass_header_code(entry.type, h_code_main)
379
380
  if i_code:
380
381
  self.generate_cclass_include_code(entry.type, i_code)
382
+ globalstate.use_entry_utility_code(entry)
381
383
  if h_funcs:
382
384
  h_code_main.putln("")
383
385
  for entry in h_funcs:
384
386
  self.generate_public_declaration(entry, h_code_main, i_code)
387
+ globalstate.use_entry_utility_code(entry)
385
388
  if h_vars:
386
389
  h_code_main.putln("")
387
390
  for entry in h_vars:
388
391
  self.generate_public_declaration(entry, h_code_main, i_code)
392
+ globalstate.use_entry_utility_code(entry)
389
393
  h_code_main.putln("")
390
394
  h_code_main.putln("#endif /* !%s */" % api_guard)
391
395
  h_code_main.putln("")
@@ -452,7 +456,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
452
456
 
453
457
  h_code = Code.CCodeWriter()
454
458
  c_code_config = generate_c_code_config(env, options)
455
- Code.GlobalState(h_code, self, c_code_config)
459
+ globalstate = Code.GlobalState(h_code, self, c_code_config)
460
+ globalstate.initialize_main_h_code() # in-case utility code is used in the header
456
461
  h_code.put_generated_by()
457
462
  api_guard = self.api_name(Naming.api_guard_prefix, env)
458
463
  h_code.put_h_guard(api_guard)
@@ -480,6 +485,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
480
485
  h_code.putln("static PyTypeObject *%s = 0;" % type.typeptr_cname)
481
486
  h_code.putln("#define %s (*%s)" % (
482
487
  type.typeobj_cname, type.typeptr_cname))
488
+ h_code.globalstate.use_entry_utility_code(entry)
483
489
  if api_funcs:
484
490
  h_code.putln("")
485
491
  for entry in api_funcs:
@@ -487,6 +493,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
487
493
  cname = env.mangle(Naming.func_prefix_api, entry.name)
488
494
  h_code.putln("static %s = 0;" % type.declaration_code(cname))
489
495
  h_code.putln("#define %s %s" % (entry.name, cname))
496
+ h_code.globalstate.use_entry_utility_code(entry)
490
497
  if api_vars:
491
498
  h_code.putln("")
492
499
  for entry in api_vars:
@@ -494,6 +501,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
494
501
  cname = env.mangle(Naming.varptr_prefix_api, entry.name)
495
502
  h_code.putln("static %s = 0;" % type.declaration_code(cname))
496
503
  h_code.putln("#define %s (*%s)" % (entry.name, cname))
504
+ h_code.globalstate.use_entry_utility_code(entry)
497
505
  if api_vars:
498
506
  put_utility_code("VoidPtrImport", "ImportExport.c")
499
507
  if api_funcs:
@@ -1012,6 +1020,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
1012
1020
 
1013
1021
  env.use_utility_code(UtilityCode.load_cached("FastTypeChecks", "ModuleSetupCode.c"))
1014
1022
  env.use_utility_code(UtilityCode.load("GetRuntimeVersion", "ModuleSetupCode.c"))
1023
+ env.use_utility_code(UtilityCode.load_cached("AddModuleRef", "ModuleSetupCode.c"))
1015
1024
  if has_np_pythran(env):
1016
1025
  env.use_utility_code(UtilityCode.load_cached("PythranConversion", "CppSupport.cpp"))
1017
1026
 
@@ -1109,6 +1118,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
1109
1118
  self.generate_cpp_class_definition(entry, code)
1110
1119
  elif type.is_extension_type:
1111
1120
  self.generate_objstruct_definition(type, code)
1121
+ if getattr(type, "scope", None):
1122
+ for var_entry in type.scope.var_entries:
1123
+ code.globalstate.use_entry_utility_code(var_entry)
1112
1124
 
1113
1125
  def generate_gcc33_hack(self, env, code):
1114
1126
  # Workaround for spurious warning generation in gcc 3.3
@@ -1447,7 +1459,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
1447
1459
  decl = attr_type.cpp_optional_declaration_code(attr.cname)
1448
1460
  else:
1449
1461
  decl = attr_type.declaration_code(attr.cname)
1450
- type.scope.use_entry_utility_code(attr)
1462
+ code.globalstate.use_entry_utility_code(attr)
1451
1463
  code.putln("%s;" % decl)
1452
1464
  code.putln(footer)
1453
1465
  if type.objtypedef_cname is not None:
@@ -1526,7 +1538,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
1526
1538
  code.putln(";")
1527
1539
  if entry.cname != cname:
1528
1540
  code.putln("#define %s (*%s)" % (entry.cname, cname))
1529
- env.use_entry_utility_code(entry)
1541
+ code.globalstate.use_entry_utility_code(entry)
1530
1542
 
1531
1543
  def generate_cfunction_declarations(self, env, code, definition):
1532
1544
  for entry in env.cfunc_entries:
@@ -4204,6 +4216,7 @@ def generate_cfunction_declaration(entry, env, code, definition):
4204
4216
  storage_class,
4205
4217
  modifiers,
4206
4218
  header))
4219
+ code.globalstate.use_entry_utility_code(entry)
4207
4220
 
4208
4221
  #------------------------------------------------------------------------------------
4209
4222
  #
Cython/Compiler/Nodes.py CHANGED
@@ -2989,6 +2989,7 @@ class CFuncDefNode(FuncDefNode):
2989
2989
  if preprocessor_guard:
2990
2990
  code.globalstate.parts['module_declarations'].putln("#endif")
2991
2991
  code.putln("%s%s%s {" % (storage_class, modifiers, header))
2992
+ code.globalstate.use_entry_utility_code(self.entry)
2992
2993
 
2993
2994
  def generate_argument_declarations(self, env, code):
2994
2995
  scope = self.local_scope
@@ -9030,11 +9031,12 @@ class CriticalSectionStatNode(TryFinallyStatNode):
9030
9031
  return super().analyse_declarations(env)
9031
9032
 
9032
9033
  def analyse_expressions(self, env):
9034
+ cy_pymutex_type = PyrexTypes.get_cy_pymutex_type()
9033
9035
  mutex_count = 0
9034
9036
  for i, arg in enumerate(self.args):
9035
9037
  arg = arg.analyse_expressions(env)
9036
- if (arg.type is PyrexTypes.cy_pymutex_type or (
9037
- arg.type.is_ptr and arg.type.base_type is PyrexTypes.cy_pymutex_type)):
9038
+ if (arg.type == cy_pymutex_type or (
9039
+ arg.type.is_ptr and arg.type.base_type == cy_pymutex_type)):
9038
9040
  mutex_count += 1
9039
9041
  self.is_pymutex_critical_section = True
9040
9042
  elif arg.type.is_pyobject:
@@ -9189,7 +9191,7 @@ class CythonLockStatNode(TryFinallyStatNode):
9189
9191
  return super().analyse_expressions(env)
9190
9192
 
9191
9193
  def generate_execution_code(self, code):
9192
- code.globalstate.use_utility_code(self.arg.type.get_utility_code())
9194
+ code.globalstate.use_utility_code(self.arg.type.get_usage_utility_code())
9193
9195
 
9194
9196
  code.mark_pos(self.pos)
9195
9197
  code.begin_block()
@@ -832,8 +832,7 @@ class MemoryViewSliceType(PyrexType):
832
832
  copy_func_type, pos=pos, defining=1,
833
833
  cname=copy_cname)
834
834
 
835
- utility = MemoryView.get_copy_new_utility(pos, self, to_memview)
836
- env.use_utility_code(utility)
835
+ entry.utility_code_definition = MemoryView.get_copy_new_utility(pos, self, to_memview)
837
836
 
838
837
  MemoryView.use_cython_array_utility_code(env)
839
838
 
@@ -3822,9 +3821,9 @@ class ToPyStructUtilityCode(AbstractUtilityCode):
3822
3821
  def __hash__(self):
3823
3822
  return hash(self.header)
3824
3823
 
3825
- def put_code(self, output):
3826
- code = output['utility_code_def']
3827
- proto = output['utility_code_proto']
3824
+ def put_code(self, globalstate, used_by=None):
3825
+ code = globalstate['utility_code_def']
3826
+ proto = globalstate['utility_code_proto']
3828
3827
 
3829
3828
  code.enter_cfunc_scope(self.env.global_scope())
3830
3829
  code.putln("%s {" % self.header)
@@ -4947,9 +4946,10 @@ class CythonLockType(PyrexType):
4947
4946
  # Singleton, cannot be copied.
4948
4947
  return src_type is self._special_assignable_reference_type
4949
4948
 
4950
- def get_utility_code(self):
4951
- # It doesn't seem like a good way to associate utility code with a type actually exists
4952
- # so we just have to do it in as many places as possible.
4949
+ def get_decl_utility_code(self):
4950
+ return UtilityCode.load_cached(f"{self.cname_part}Decl", "Synchronization.c")
4951
+
4952
+ def get_usage_utility_code(self):
4953
4953
  return UtilityCode.load_cached(self.cname_part, "Synchronization.c")
4954
4954
 
4955
4955
  def needs_explicit_construction(self, scope):
@@ -4964,7 +4964,7 @@ class CythonLockType(PyrexType):
4964
4964
 
4965
4965
  def generate_explicit_construction(self, code, entry, extra_access_code=""):
4966
4966
  code.globalstate.use_utility_code(
4967
- self.get_utility_code()
4967
+ self.get_usage_utility_code()
4968
4968
  )
4969
4969
  code.putln(f"__Pyx_Locks_{self.cname_part}_Init({extra_access_code}{entry.cname});")
4970
4970
 
@@ -4992,7 +4992,7 @@ class CythonLockType(PyrexType):
4992
4992
  pos=None,
4993
4993
  defining=1,
4994
4994
  cname=f"__Pyx_Locks_{self.cname_part}_Lock",
4995
- utility_code=self.get_utility_code())
4995
+ utility_code=self.get_usage_utility_code())
4996
4996
  scope.declare_cfunction(
4997
4997
  "release",
4998
4998
  CFuncType(c_void_type, [CFuncTypeArg("self", self_type, None)],
@@ -5000,7 +5000,7 @@ class CythonLockType(PyrexType):
5000
5000
  pos=None,
5001
5001
  defining=1,
5002
5002
  cname=f"__Pyx_Locks_{self.cname_part}_Unlock",
5003
- utility_code=self.get_utility_code())
5003
+ utility_code=self.get_usage_utility_code())
5004
5004
  # Don't define a "locked" function because we can't do this with Py_Mutex
5005
5005
  # (which is the preferred implementation)
5006
5006
 
@@ -5012,6 +5012,14 @@ class CythonLockType(PyrexType):
5012
5012
  def create_from_py_utility_code(self, env):
5013
5013
  return False
5014
5014
 
5015
+ def __eq__(self, other):
5016
+ if type(other) is not type(self):
5017
+ return NotImplemented
5018
+ return other.cname_part == self.cname_part
5019
+
5020
+ def __hash__(self):
5021
+ return hash(self.cname_part)
5022
+
5015
5023
 
5016
5024
  rank_to_type_name = (
5017
5025
  "char", # 0
@@ -5143,8 +5151,12 @@ cython_memoryview_type = CStructOrUnionType("__pyx_memoryview_obj", "struct",
5143
5151
  memoryviewslice_type = CStructOrUnionType("memoryviewslice", "struct",
5144
5152
  None, 1, "__Pyx_memviewslice")
5145
5153
 
5146
- cy_pymutex_type = CythonLockType("PyMutex")
5147
- cy_pythread_type_lock_type = CythonLockType("PyThreadTypeLock")
5154
+ # Don't declare these as globals - it interferes with our ability to check if it's
5155
+ # used in a particular scope.
5156
+ def get_cy_pymutex_type():
5157
+ return CythonLockType("PyMutex")
5158
+ def get_cy_pythread_type_lock_type():
5159
+ return CythonLockType("PyThreadTypeLock")
5148
5160
 
5149
5161
  fixed_sign_int_types = {
5150
5162
  "bint": (1, c_bint_type),
Cython/Compiler/Symtab.py CHANGED
@@ -1236,7 +1236,7 @@ class Scope:
1236
1236
  # e.g. slot, function, method
1237
1237
  return f"{Naming.modulestateglobal_cname}->{cname}"
1238
1238
 
1239
- def find_shared_usages_of_type(self, type_check_predicate, _seen_scopes=None):
1239
+ def find_shared_usages_of_type(self, type_to_find, _seen_scopes=None):
1240
1240
  if _seen_scopes is None:
1241
1241
  _seen_scopes = set()
1242
1242
  include_all_entries = not self.is_module_scope
@@ -1244,17 +1244,31 @@ class Scope:
1244
1244
  if not (include_all_entries or entry.defined_in_pxd or entry.visibility == "public" or entry.api):
1245
1245
  continue
1246
1246
  entry_subtypes = PyrexTypes.get_all_subtypes(entry.type)
1247
- if any(type_check_predicate(sub_tp) for sub_tp in entry_subtypes):
1247
+ if any(type_to_find == sub_tp for sub_tp in entry_subtypes):
1248
1248
  return True
1249
1249
  type_scope = getattr(entry.type, "scope", None)
1250
1250
  if type_scope is None or type_scope in _seen_scopes:
1251
1251
  continue
1252
1252
  _seen_scopes.add(type_scope)
1253
- if type_scope.find_shared_usages_of_type(type_check_predicate, _seen_scopes):
1253
+ if type_scope.find_shared_usages_of_type(type_to_find, _seen_scopes):
1254
1254
  return True
1255
1255
  return False
1256
1256
 
1257
1257
 
1258
+ class PreImportScope(Scope):
1259
+
1260
+ namespace_cname = Naming.preimport_cname
1261
+
1262
+ def __init__(self):
1263
+ Scope.__init__(self, Options.pre_import, None, None)
1264
+
1265
+ def declare_builtin(self, name, pos):
1266
+ entry = self.declare(name, name, py_object_type, pos, 'private')
1267
+ entry.is_variable = True
1268
+ entry.is_pyglobal = True
1269
+ return entry
1270
+
1271
+
1258
1272
  class BuiltinScope(Scope):
1259
1273
  # The builtin namespace.
1260
1274
 
@@ -1777,6 +1791,9 @@ class ModuleScope(Scope):
1777
1791
  self.utility_code_list.append(entry.utility_code)
1778
1792
  if entry.utility_code_definition:
1779
1793
  self.utility_code_list.append(entry.utility_code_definition)
1794
+ for tp in PyrexTypes.get_all_subtypes(entry.type):
1795
+ if hasattr(tp, "entry") and tp.entry is not entry:
1796
+ self.use_entry_utility_code(tp.entry)
1780
1797
 
1781
1798
  def declare_c_class(self, name, pos, defining=0, implementing=0,
1782
1799
  module_name=None, base_type=None, objstruct_cname=None,
@@ -201,7 +201,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
201
201
  self.tree = tree
202
202
  return tree
203
203
 
204
- def put_code(self, output):
204
+ def put_code(self, globalstate, used_by=None):
205
205
  pass
206
206
 
207
207
  @classmethod
Cython/Debugger/Cygdb.py CHANGED
@@ -50,9 +50,11 @@ def make_command_file(path_to_debug_info, prefix_code='',
50
50
  try:
51
51
  # Activate virtualenv, if we were launched from one
52
52
  import os
53
+ import sys
53
54
  virtualenv = os.getenv('VIRTUAL_ENV')
54
55
  if virtualenv:
55
- path_to_activate_this_py = os.path.join(virtualenv, 'bin', 'activate_this.py')
56
+ scripts_dir = 'Scripts' if sys.platform == "win32" else 'bin'
57
+ path_to_activate_this_py = os.path.join(virtualenv, scripts_dir, 'activate_this.py')
56
58
  print("gdb command file: Activating virtualenv: %s; path_to_activate_this_py: %s" % (
57
59
  virtualenv, path_to_activate_this_py))
58
60
  with open(path_to_activate_this_py) as f:
@@ -60,7 +62,7 @@ def make_command_file(path_to_debug_info, prefix_code='',
60
62
  from Cython.Debugger import libcython, libpython
61
63
  except Exception as ex:
62
64
  from traceback import print_exc
63
- print("There was an error in Python code originating from the file ''' + str(__file__) + '''")
65
+ print("There was an error in Python code originating from the file " + ''' + repr(__file__) + ''')
64
66
  print("It used the Python interpreter " + str(sys.executable))
65
67
  print_exc()
66
68
  exit(1)