passagemath-objects 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.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.

Potentially problematic release.


This version of passagemath-objects might be problematic. Click here for more details.

Files changed (279) hide show
  1. passagemath_objects-10.6.31rc3.dist-info/METADATA +114 -0
  2. passagemath_objects-10.6.31rc3.dist-info/RECORD +279 -0
  3. passagemath_objects-10.6.31rc3.dist-info/WHEEL +5 -0
  4. passagemath_objects-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_objects.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  6. sage/all__sagemath_objects.py +37 -0
  7. sage/arith/all__sagemath_objects.py +5 -0
  8. sage/arith/long.pxd +411 -0
  9. sage/arith/numerical_approx.cpython-314-x86_64-linux-musl.so +0 -0
  10. sage/arith/numerical_approx.pxd +35 -0
  11. sage/arith/numerical_approx.pyx +75 -0
  12. sage/arith/power.cpython-314-x86_64-linux-musl.so +0 -0
  13. sage/arith/power.pxd +31 -0
  14. sage/arith/power.pyx +127 -0
  15. sage/categories/action.cpython-314-x86_64-linux-musl.so +0 -0
  16. sage/categories/action.pxd +29 -0
  17. sage/categories/action.pyx +641 -0
  18. sage/categories/algebra_functor.py +745 -0
  19. sage/categories/all__sagemath_objects.py +33 -0
  20. sage/categories/basic.py +62 -0
  21. sage/categories/cartesian_product.py +295 -0
  22. sage/categories/category.py +3401 -0
  23. sage/categories/category_cy_helper.cpython-314-x86_64-linux-musl.so +0 -0
  24. sage/categories/category_cy_helper.pxd +8 -0
  25. sage/categories/category_cy_helper.pyx +322 -0
  26. sage/categories/category_singleton.cpython-314-x86_64-linux-musl.so +0 -0
  27. sage/categories/category_singleton.pxd +3 -0
  28. sage/categories/category_singleton.pyx +342 -0
  29. sage/categories/category_types.py +637 -0
  30. sage/categories/category_with_axiom.py +2876 -0
  31. sage/categories/covariant_functorial_construction.py +703 -0
  32. sage/categories/facade_sets.py +228 -0
  33. sage/categories/functor.cpython-314-x86_64-linux-musl.so +0 -0
  34. sage/categories/functor.pxd +7 -0
  35. sage/categories/functor.pyx +691 -0
  36. sage/categories/homset.py +1338 -0
  37. sage/categories/homsets.py +364 -0
  38. sage/categories/isomorphic_objects.py +73 -0
  39. sage/categories/map.cpython-314-x86_64-linux-musl.so +0 -0
  40. sage/categories/map.pxd +34 -0
  41. sage/categories/map.pyx +2112 -0
  42. sage/categories/morphism.cpython-314-x86_64-linux-musl.so +0 -0
  43. sage/categories/morphism.pxd +14 -0
  44. sage/categories/morphism.pyx +895 -0
  45. sage/categories/objects.py +167 -0
  46. sage/categories/primer.py +1696 -0
  47. sage/categories/pushout.py +4834 -0
  48. sage/categories/quotients.py +64 -0
  49. sage/categories/realizations.py +200 -0
  50. sage/categories/sets_cat.py +3228 -0
  51. sage/categories/sets_with_partial_maps.py +52 -0
  52. sage/categories/subobjects.py +64 -0
  53. sage/categories/subquotients.py +21 -0
  54. sage/categories/with_realizations.py +311 -0
  55. sage/cpython/__init__.py +19 -0
  56. sage/cpython/_py2_random.py +619 -0
  57. sage/cpython/all.py +3 -0
  58. sage/cpython/atexit.cpython-314-x86_64-linux-musl.so +0 -0
  59. sage/cpython/atexit.pyx +262 -0
  60. sage/cpython/builtin_types.cpython-314-x86_64-linux-musl.so +0 -0
  61. sage/cpython/builtin_types.pyx +7 -0
  62. sage/cpython/cython_metaclass.cpython-314-x86_64-linux-musl.so +0 -0
  63. sage/cpython/cython_metaclass.h +117 -0
  64. sage/cpython/cython_metaclass.pxd +3 -0
  65. sage/cpython/cython_metaclass.pyx +130 -0
  66. sage/cpython/debug.cpython-314-x86_64-linux-musl.so +0 -0
  67. sage/cpython/debug.pyx +302 -0
  68. sage/cpython/dict_del_by_value.cpython-314-x86_64-linux-musl.so +0 -0
  69. sage/cpython/dict_del_by_value.pxd +9 -0
  70. sage/cpython/dict_del_by_value.pyx +191 -0
  71. sage/cpython/dict_internal.h +245 -0
  72. sage/cpython/getattr.cpython-314-x86_64-linux-musl.so +0 -0
  73. sage/cpython/getattr.pxd +9 -0
  74. sage/cpython/getattr.pyx +439 -0
  75. sage/cpython/pycore_long.h +97 -0
  76. sage/cpython/pycore_long.pxd +10 -0
  77. sage/cpython/python_debug.h +44 -0
  78. sage/cpython/python_debug.pxd +47 -0
  79. sage/cpython/pyx_visit.h +13 -0
  80. sage/cpython/string.cpython-314-x86_64-linux-musl.so +0 -0
  81. sage/cpython/string.pxd +76 -0
  82. sage/cpython/string.pyx +34 -0
  83. sage/cpython/string_impl.h +60 -0
  84. sage/cpython/type.cpython-314-x86_64-linux-musl.so +0 -0
  85. sage/cpython/type.pxd +2 -0
  86. sage/cpython/type.pyx +40 -0
  87. sage/cpython/wrapperdescr.pxd +67 -0
  88. sage/ext/all__sagemath_objects.py +3 -0
  89. sage/ext/ccobject.h +64 -0
  90. sage/ext/cplusplus.pxd +17 -0
  91. sage/ext/mod_int.h +30 -0
  92. sage/ext/mod_int.pxd +24 -0
  93. sage/ext/stdsage.pxd +39 -0
  94. sage/groups/all__sagemath_objects.py +1 -0
  95. sage/groups/group.cpython-314-x86_64-linux-musl.so +0 -0
  96. sage/groups/group.pxd +14 -0
  97. sage/groups/group.pyx +322 -0
  98. sage/groups/old.cpython-314-x86_64-linux-musl.so +0 -0
  99. sage/groups/old.pxd +14 -0
  100. sage/groups/old.pyx +219 -0
  101. sage/libs/all__sagemath_objects.py +3 -0
  102. sage/libs/gmp/__init__.py +1 -0
  103. sage/libs/gmp/all.pxd +6 -0
  104. sage/libs/gmp/binop.pxd +23 -0
  105. sage/libs/gmp/misc.pxd +8 -0
  106. sage/libs/gmp/mpf.pxd +88 -0
  107. sage/libs/gmp/mpn.pxd +57 -0
  108. sage/libs/gmp/mpq.pxd +57 -0
  109. sage/libs/gmp/mpz.pxd +202 -0
  110. sage/libs/gmp/pylong.cpython-314-x86_64-linux-musl.so +0 -0
  111. sage/libs/gmp/pylong.pxd +12 -0
  112. sage/libs/gmp/pylong.pyx +150 -0
  113. sage/libs/gmp/random.pxd +25 -0
  114. sage/libs/gmp/randomize.pxd +59 -0
  115. sage/libs/gmp/types.pxd +53 -0
  116. sage/libs/gmpxx.pxd +19 -0
  117. sage/misc/abstract_method.py +276 -0
  118. sage/misc/all__sagemath_objects.py +43 -0
  119. sage/misc/bindable_class.py +253 -0
  120. sage/misc/c3_controlled.cpython-314-x86_64-linux-musl.so +0 -0
  121. sage/misc/c3_controlled.pxd +2 -0
  122. sage/misc/c3_controlled.pyx +1402 -0
  123. sage/misc/cachefunc.cpython-314-x86_64-linux-musl.so +0 -0
  124. sage/misc/cachefunc.pxd +43 -0
  125. sage/misc/cachefunc.pyx +3781 -0
  126. sage/misc/call.py +188 -0
  127. sage/misc/classcall_metaclass.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/misc/classcall_metaclass.pxd +14 -0
  129. sage/misc/classcall_metaclass.pyx +599 -0
  130. sage/misc/constant_function.cpython-314-x86_64-linux-musl.so +0 -0
  131. sage/misc/constant_function.pyx +128 -0
  132. sage/misc/decorators.py +747 -0
  133. sage/misc/fast_methods.cpython-314-x86_64-linux-musl.so +0 -0
  134. sage/misc/fast_methods.pxd +20 -0
  135. sage/misc/fast_methods.pyx +351 -0
  136. sage/misc/flatten.py +90 -0
  137. sage/misc/fpickle.cpython-314-x86_64-linux-musl.so +0 -0
  138. sage/misc/fpickle.pyx +177 -0
  139. sage/misc/function_mangling.cpython-314-x86_64-linux-musl.so +0 -0
  140. sage/misc/function_mangling.pxd +11 -0
  141. sage/misc/function_mangling.pyx +308 -0
  142. sage/misc/inherit_comparison.cpython-314-x86_64-linux-musl.so +0 -0
  143. sage/misc/inherit_comparison.pxd +5 -0
  144. sage/misc/inherit_comparison.pyx +105 -0
  145. sage/misc/instancedoc.cpython-314-x86_64-linux-musl.so +0 -0
  146. sage/misc/instancedoc.pyx +331 -0
  147. sage/misc/lazy_attribute.cpython-314-x86_64-linux-musl.so +0 -0
  148. sage/misc/lazy_attribute.pyx +607 -0
  149. sage/misc/lazy_format.py +135 -0
  150. sage/misc/lazy_import.cpython-314-x86_64-linux-musl.so +0 -0
  151. sage/misc/lazy_import.pyx +1299 -0
  152. sage/misc/lazy_import_cache.py +36 -0
  153. sage/misc/lazy_list.cpython-314-x86_64-linux-musl.so +0 -0
  154. sage/misc/lazy_list.pxd +19 -0
  155. sage/misc/lazy_list.pyx +1187 -0
  156. sage/misc/lazy_string.cpython-314-x86_64-linux-musl.so +0 -0
  157. sage/misc/lazy_string.pxd +7 -0
  158. sage/misc/lazy_string.pyx +546 -0
  159. sage/misc/misc.py +1066 -0
  160. sage/misc/misc_c.cpython-314-x86_64-linux-musl.so +0 -0
  161. sage/misc/misc_c.pxd +3 -0
  162. sage/misc/misc_c.pyx +766 -0
  163. sage/misc/namespace_package.py +37 -0
  164. sage/misc/nested_class.cpython-314-x86_64-linux-musl.so +0 -0
  165. sage/misc/nested_class.pxd +3 -0
  166. sage/misc/nested_class.pyx +394 -0
  167. sage/misc/persist.cpython-314-x86_64-linux-musl.so +0 -0
  168. sage/misc/persist.pyx +1251 -0
  169. sage/misc/prandom.py +418 -0
  170. sage/misc/randstate.cpython-314-x86_64-linux-musl.so +0 -0
  171. sage/misc/randstate.pxd +30 -0
  172. sage/misc/randstate.pyx +1059 -0
  173. sage/misc/repr.py +203 -0
  174. sage/misc/reset.cpython-314-x86_64-linux-musl.so +0 -0
  175. sage/misc/reset.pyx +196 -0
  176. sage/misc/sage_ostools.cpython-314-x86_64-linux-musl.so +0 -0
  177. sage/misc/sage_ostools.pyx +323 -0
  178. sage/misc/sage_timeit.py +265 -0
  179. sage/misc/sage_timeit_class.cpython-314-x86_64-linux-musl.so +0 -0
  180. sage/misc/sage_timeit_class.pyx +120 -0
  181. sage/misc/sage_unittest.py +637 -0
  182. sage/misc/sageinspect.py +2768 -0
  183. sage/misc/session.cpython-314-x86_64-linux-musl.so +0 -0
  184. sage/misc/session.pyx +392 -0
  185. sage/misc/superseded.py +557 -0
  186. sage/misc/test_nested_class.py +228 -0
  187. sage/misc/timing.py +256 -0
  188. sage/misc/unknown.py +222 -0
  189. sage/misc/verbose.py +253 -0
  190. sage/misc/weak_dict.cpython-314-x86_64-linux-musl.so +0 -0
  191. sage/misc/weak_dict.pxd +15 -0
  192. sage/misc/weak_dict.pyx +1231 -0
  193. sage/modules/all__sagemath_objects.py +1 -0
  194. sage/modules/module.cpython-314-x86_64-linux-musl.so +0 -0
  195. sage/modules/module.pxd +5 -0
  196. sage/modules/module.pyx +329 -0
  197. sage/rings/all__sagemath_objects.py +3 -0
  198. sage/rings/integer_fake.h +22 -0
  199. sage/rings/integer_fake.pxd +55 -0
  200. sage/sets/all__sagemath_objects.py +3 -0
  201. sage/sets/pythonclass.cpython-314-x86_64-linux-musl.so +0 -0
  202. sage/sets/pythonclass.pxd +9 -0
  203. sage/sets/pythonclass.pyx +247 -0
  204. sage/structure/__init__.py +4 -0
  205. sage/structure/all.py +30 -0
  206. sage/structure/category_object.cpython-314-x86_64-linux-musl.so +0 -0
  207. sage/structure/category_object.pxd +28 -0
  208. sage/structure/category_object.pyx +1087 -0
  209. sage/structure/coerce.cpython-314-x86_64-linux-musl.so +0 -0
  210. sage/structure/coerce.pxd +44 -0
  211. sage/structure/coerce.pyx +2107 -0
  212. sage/structure/coerce_actions.cpython-314-x86_64-linux-musl.so +0 -0
  213. sage/structure/coerce_actions.pxd +27 -0
  214. sage/structure/coerce_actions.pyx +988 -0
  215. sage/structure/coerce_dict.cpython-314-x86_64-linux-musl.so +0 -0
  216. sage/structure/coerce_dict.pxd +51 -0
  217. sage/structure/coerce_dict.pyx +1557 -0
  218. sage/structure/coerce_exceptions.py +23 -0
  219. sage/structure/coerce_maps.cpython-314-x86_64-linux-musl.so +0 -0
  220. sage/structure/coerce_maps.pxd +28 -0
  221. sage/structure/coerce_maps.pyx +718 -0
  222. sage/structure/debug_options.cpython-314-x86_64-linux-musl.so +0 -0
  223. sage/structure/debug_options.pxd +6 -0
  224. sage/structure/debug_options.pyx +54 -0
  225. sage/structure/dynamic_class.py +541 -0
  226. sage/structure/element.cpython-314-x86_64-linux-musl.so +0 -0
  227. sage/structure/element.pxd +272 -0
  228. sage/structure/element.pyx +4772 -0
  229. sage/structure/element_wrapper.cpython-314-x86_64-linux-musl.so +0 -0
  230. sage/structure/element_wrapper.pxd +12 -0
  231. sage/structure/element_wrapper.pyx +582 -0
  232. sage/structure/factorization.py +1422 -0
  233. sage/structure/factorization_integer.py +105 -0
  234. sage/structure/factory.cpython-314-x86_64-linux-musl.so +0 -0
  235. sage/structure/factory.pyx +786 -0
  236. sage/structure/formal_sum.py +489 -0
  237. sage/structure/gens_py.py +73 -0
  238. sage/structure/global_options.py +1743 -0
  239. sage/structure/indexed_generators.py +863 -0
  240. sage/structure/list_clone.cpython-314-x86_64-linux-musl.so +0 -0
  241. sage/structure/list_clone.pxd +65 -0
  242. sage/structure/list_clone.pyx +1867 -0
  243. sage/structure/list_clone_demo.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/structure/list_clone_demo.pyx +248 -0
  245. sage/structure/list_clone_timings.py +179 -0
  246. sage/structure/list_clone_timings_cy.cpython-314-x86_64-linux-musl.so +0 -0
  247. sage/structure/list_clone_timings_cy.pyx +86 -0
  248. sage/structure/mutability.cpython-314-x86_64-linux-musl.so +0 -0
  249. sage/structure/mutability.pxd +21 -0
  250. sage/structure/mutability.pyx +348 -0
  251. sage/structure/nonexact.py +69 -0
  252. sage/structure/parent.cpython-314-x86_64-linux-musl.so +0 -0
  253. sage/structure/parent.pxd +112 -0
  254. sage/structure/parent.pyx +3093 -0
  255. sage/structure/parent_base.cpython-314-x86_64-linux-musl.so +0 -0
  256. sage/structure/parent_base.pxd +13 -0
  257. sage/structure/parent_base.pyx +44 -0
  258. sage/structure/parent_gens.cpython-314-x86_64-linux-musl.so +0 -0
  259. sage/structure/parent_gens.pxd +22 -0
  260. sage/structure/parent_gens.pyx +377 -0
  261. sage/structure/parent_old.cpython-314-x86_64-linux-musl.so +0 -0
  262. sage/structure/parent_old.pxd +25 -0
  263. sage/structure/parent_old.pyx +294 -0
  264. sage/structure/proof/__init__.py +1 -0
  265. sage/structure/proof/all.py +243 -0
  266. sage/structure/proof/proof.py +300 -0
  267. sage/structure/richcmp.cpython-314-x86_64-linux-musl.so +0 -0
  268. sage/structure/richcmp.pxd +213 -0
  269. sage/structure/richcmp.pyx +495 -0
  270. sage/structure/sage_object.cpython-314-x86_64-linux-musl.so +0 -0
  271. sage/structure/sage_object.pxd +3 -0
  272. sage/structure/sage_object.pyx +988 -0
  273. sage/structure/sage_object_test.py +19 -0
  274. sage/structure/sequence.py +937 -0
  275. sage/structure/set_factories.py +1178 -0
  276. sage/structure/set_factories_example.py +527 -0
  277. sage/structure/support_view.py +179 -0
  278. sage/structure/test_factory.py +56 -0
  279. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,262 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+
3
+ """Utilities for interfacing with the standard library's atexit module."""
4
+
5
+ # ****************************************************************************
6
+ # Copyright (C) 2017 Erik M. Bray <erik.bray@lri.fr>
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ # https://www.gnu.org/licenses/
13
+ # ****************************************************************************
14
+
15
+ import atexit
16
+
17
+
18
+ __all__ = ['restore_atexit']
19
+
20
+
21
+ cdef class restore_atexit:
22
+ r"""
23
+ Context manager that restores the state of the atexit module to its
24
+ previous state when exiting the context.
25
+
26
+ INPUT:
27
+
28
+ - ``run`` -- boolean (default: ``False``); if ``True``, when exiting the
29
+ context (but before restoring the old exit functions), run all
30
+ atexit functions which were added inside the context
31
+
32
+ - ``clear`` -- boolean (default: equal to ``run``); if ``True``, clear
33
+ already registered atexit handlers upon entering the context
34
+
35
+ .. WARNING::
36
+
37
+ The combination ``run=True`` and ``clear=False`` will cause
38
+ already-registered exit functions to be run twice: once when
39
+ exiting the context and again when exiting Python.
40
+
41
+ EXAMPLES:
42
+
43
+ For this example we will wrap the entire example with
44
+ ``restore_atexit(clear=True)`` so as to start with a fresh atexit
45
+ module state for the sake of the example.
46
+
47
+ Note that the function ``atexit._run_exitfuncs()`` runs all registered
48
+ handlers, and then clears the list of handlers, so we can use it to test
49
+ manipulation of the ``atexit`` state::
50
+
51
+ sage: import atexit
52
+ sage: from sage.cpython.atexit import restore_atexit
53
+ sage: def handler(*args, **kwargs):
54
+ ....: import sys
55
+ ....: # see https://github.com/sagemath/sage/issues/25270#comment:56
56
+ ....: sys.stdout.write(str((args, kwargs)))
57
+ ....: sys.stdout.write('\n')
58
+ sage: atexit.register(handler, 1, 2, c=3)
59
+ <function handler at 0x...>
60
+ sage: atexit.register(handler, 4, 5, d=6)
61
+ <function handler at 0x...>
62
+ sage: with restore_atexit(clear=True):
63
+ ....: atexit._run_exitfuncs() # Should be none registered
64
+ ....: atexit.register(handler, 1, 2, c=3)
65
+ ....: with restore_atexit():
66
+ ....: atexit._run_exitfuncs() # Run just registered handler
67
+ ....: atexit._run_exitfuncs() # Handler should be run again
68
+ <function handler at 0x...>
69
+ ((1, 2), {'c': 3})
70
+ ((1, 2), {'c': 3})
71
+
72
+ We test the ``run`` option::
73
+
74
+ sage: with restore_atexit(run=True):
75
+ ....: # this handler is run when exiting the context
76
+ ....: _ = atexit.register(handler, 7, 8, e=9)
77
+ ((7, 8), {'e': 9})
78
+ sage: with restore_atexit(clear=False, run=True):
79
+ ....: # original handlers are run when exiting the context
80
+ ....: pass
81
+ ((4, 5), {'d': 6})
82
+ ((1, 2), {'c': 3})
83
+
84
+ The original handlers are still in place::
85
+
86
+ sage: atexit._run_exitfuncs()
87
+ ((4, 5), {'d': 6})
88
+ ((1, 2), {'c': 3})
89
+
90
+ TESTS::
91
+
92
+ sage: from sage.cpython.atexit import (_get_exithandlers,
93
+ ....: _clear_exithandlers)
94
+ sage: atexit.register(handler, 1, 2, c=3)
95
+ <function handler at 0x...>
96
+ sage: atexit.register(handler, 4, 5, d=6)
97
+ <function handler at 0x...>
98
+ sage: print("Initial exit handlers:\n{}".format(_get_exithandlers()))
99
+ Initial exit handlers:
100
+ [(<function handler at 0x...>, (1, 2), {'c': 3}),
101
+ (<function handler at 0x...>, (4, 5), {'d': 6})]
102
+
103
+ sage: with restore_atexit():
104
+ ....: pass
105
+ sage: print("After restore_atexit:\n{}".format(_get_exithandlers()))
106
+ After restore_atexit:
107
+ [(<function handler at 0x...>, (1, 2), {'c': 3}),
108
+ (<function handler at 0x...>, (4, 5), {'d': 6})]
109
+
110
+ sage: with restore_atexit(clear=True):
111
+ ....: print("Exit handlers in context manager: {}".format(
112
+ ....: _get_exithandlers()))
113
+ Exit handlers in context manager: []
114
+
115
+ sage: print("After restore_atexit with clear=True:\n{}".format(
116
+ ....: _get_exithandlers()))
117
+ After restore_atexit with clear=True:
118
+ [(<function handler at 0x...>, (1, 2), {'c': 3}),
119
+ (<function handler at 0x...>, (4, 5), {'d': 6})]
120
+ sage: _clear_exithandlers()
121
+ sage: _get_exithandlers()
122
+ []
123
+ """
124
+
125
+ cdef list _exithandlers
126
+ cdef bint _clear, _run
127
+
128
+ def __init__(self, *, run=False, clear=None):
129
+ self._clear = self._run = run
130
+ if clear is not None:
131
+ self._clear = clear
132
+ self._exithandlers = None
133
+
134
+ def __enter__(self):
135
+ self._exithandlers = _get_exithandlers()
136
+ if self._clear:
137
+ _clear_exithandlers()
138
+
139
+ return self
140
+
141
+ def __exit__(self, *exc):
142
+ if self._run:
143
+ atexit._run_exitfuncs()
144
+ _set_exithandlers(self._exithandlers)
145
+
146
+ from cpython.ref cimport PyObject
147
+ import sys
148
+
149
+ # Implement a uniform interface for getting atexit callbacks
150
+ cdef extern from *:
151
+ """
152
+ #ifndef Py_BUILD_CORE
153
+ #define Py_BUILD_CORE
154
+ #endif
155
+ #undef _PyGC_FINALIZED
156
+ #include "internal/pycore_interp.h"
157
+ #include "internal/pycore_pystate.h"
158
+
159
+ // Always define this struct for Cython's use
160
+ typedef struct {
161
+ PyObject *func;
162
+ PyObject *args;
163
+ PyObject *kwargs;
164
+ } atexit_callback_struct;
165
+
166
+ #if PY_VERSION_HEX >= 0x030e0000
167
+ // Python 3.14+: atexit uses a PyList
168
+ static PyObject* get_atexit_callbacks_list(PyObject *self) {
169
+ PyInterpreterState *interp = _PyInterpreterState_GET();
170
+ struct atexit_state state = interp->atexit;
171
+ return state.callbacks;
172
+ }
173
+
174
+ // Dummy function for Python 3.14+ (never called)
175
+ static atexit_callback_struct** get_atexit_callbacks_array(PyObject *self) {
176
+ return NULL;
177
+ }
178
+ #else
179
+ // Python < 3.14: atexit uses C array
180
+ static atexit_callback_struct** get_atexit_callbacks_array(PyObject *self) {
181
+ PyInterpreterState *interp = _PyInterpreterState_GET();
182
+ struct atexit_state state = interp->atexit;
183
+ // Cast from atexit_callback** to our struct type
184
+ return (atexit_callback_struct**)state.callbacks;
185
+ }
186
+
187
+ // Dummy function for Python < 3.14 (never called)
188
+ static PyObject* get_atexit_callbacks_list(PyObject *self) {
189
+ return NULL;
190
+ }
191
+ #endif
192
+ """
193
+ # Declare both functions - they exist in all Python versions (one is dummy)
194
+ PyObject* get_atexit_callbacks_list(object module)
195
+
196
+ ctypedef struct atexit_callback_struct:
197
+ PyObject* func
198
+ PyObject* args
199
+ PyObject* kwargs
200
+ atexit_callback_struct** get_atexit_callbacks_array(object module)
201
+
202
+
203
+ def _get_exithandlers():
204
+ """Return list of exit handlers registered with the atexit module."""
205
+ cdef list exithandlers = []
206
+ cdef atexit_callback_struct ** callbacks
207
+ cdef atexit_callback_struct callback
208
+ cdef int idx
209
+ cdef object kwargs
210
+
211
+ # Python 3.14+ uses a PyList directly
212
+ if sys.version_info >= (3, 14):
213
+ callbacks_list = <object>get_atexit_callbacks_list(atexit)
214
+ if callbacks_list is None:
215
+ return exithandlers
216
+ # callbacks is a list of tuples: [(func, args, kwargs), ...]
217
+ # Normalize kwargs to ensure it's always a dict (not None)
218
+ # Note: In Python 3.14+, atexit stores callbacks in LIFO order
219
+ # (most recently registered first), but we return them in FIFO
220
+ # order (registration order) for consistency with earlier versions
221
+ for item in reversed(callbacks_list):
222
+ func, args, kwargs = item
223
+ if kwargs is None:
224
+ kwargs = {}
225
+ exithandlers.append((func, args, kwargs))
226
+ else:
227
+ # Python < 3.14 uses C array
228
+ callbacks = get_atexit_callbacks_array(atexit)
229
+ for idx in range(atexit._ncallbacks()):
230
+ callback = callbacks[idx][0]
231
+ if callback.kwargs:
232
+ kwargs = <object>callback.kwargs
233
+ else:
234
+ kwargs = {}
235
+ exithandlers.append((<object>callback.func,
236
+ <object>callback.args,
237
+ kwargs))
238
+ return exithandlers
239
+
240
+
241
+ def _set_exithandlers(exithandlers):
242
+ """
243
+ Replace the list of exit handlers registered with the atexit module
244
+ with a new list.
245
+ """
246
+
247
+ # Clear the existing list
248
+ atexit._clear()
249
+
250
+ # We could do this more efficiently by directly rebuilding the array
251
+ # of atexit_callbacks, but this is much simpler
252
+ # Note: exithandlers is in registration order (FIFO).
253
+ # In Python 3.14+, atexit.register prepends to the list (LIFO),
254
+ # so registering in forward order gives us the correct execution order.
255
+ for callback in exithandlers:
256
+ atexit.register(callback[0], *callback[1], **callback[2])
257
+
258
+
259
+ def _clear_exithandlers():
260
+ """Clear the atexit module of all registered exit handlers."""
261
+
262
+ atexit._clear()
@@ -0,0 +1,7 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ from cpython.object cimport PyTypeObject
3
+
4
+ cdef extern from *:
5
+ PyTypeObject PyWrapperDescr_Type
6
+
7
+ wrapper_descriptor = <type>(&PyWrapperDescr_Type)
@@ -0,0 +1,117 @@
1
+ /* sage_setup: distribution = sagemath-objects
2
+ */
3
+ /*****************************************************************************
4
+ * Copyright (C) 2015 Jeroen Demeyer <jdemeyer@cage.ugent.be>
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 2 of the License, or
9
+ * (at your option) any later version.
10
+ * https://www.gnu.org/licenses/
11
+ *****************************************************************************/
12
+
13
+ /* Tuple (None, None, None), initialized as needed */
14
+ static PyObject* NoneNoneNone;
15
+
16
+ /* All args flags of a PyMethod */
17
+ #define METH_ALLARGS (METH_VARARGS|METH_KEYWORDS|METH_NOARGS|METH_O)
18
+
19
+ /* Given an unbound method "desc" (this is not checked!) with only a
20
+ * single "self" argument, call "desc(self)" without checking "self".
21
+ * This can in particular be used to call any method as class or
22
+ * static method. */
23
+ static CYTHON_INLINE PyObject* PyMethodDescr_CallSelf(PyMethodDescrObject* desc, PyObject* self)
24
+ {
25
+ PyMethodDef* meth = desc->d_method;
26
+
27
+ /* This must be a METH_NOARGS method */
28
+ if (meth == NULL || (meth->ml_flags & METH_ALLARGS) != METH_NOARGS)
29
+ {
30
+ PyErr_SetString(PyExc_TypeError,
31
+ "PyMethodDescr_CallSelf requires a method without arguments");
32
+ return NULL;
33
+ }
34
+
35
+ return meth->ml_meth(self, NULL);
36
+ }
37
+
38
+ /*
39
+ * This function calls PyType_Ready(t) and then calls
40
+ * t.__getmetaclass__(None) (if that method exists) which should
41
+ * return the metaclass for t. Then type(t) is set to this metaclass
42
+ * and metaclass.__init__(t, None, None, None) is called.
43
+ */
44
+ static CYTHON_INLINE int Sage_PyType_Ready(PyTypeObject* t)
45
+ {
46
+ int r = PyType_Ready(t);
47
+ if (r < 0)
48
+ return r;
49
+
50
+ // Cython 3 sets Py_TPFLAGS_HEAPTYPE before calling PyType_Ready,
51
+ // and resets just after the call. We need to reset it earlier,
52
+ // since otherwise the call to metaclass.__init__ below may have
53
+ // illegal memory accesses.
54
+ // See also:
55
+ // https://github.com/cython/cython/issues/3603
56
+ t->tp_flags &= ~Py_TPFLAGS_HEAPTYPE;
57
+
58
+ /* Set or get metaclass (the type of t) */
59
+ PyTypeObject* metaclass;
60
+
61
+ PyObject* getmetaclass;
62
+ getmetaclass = PyObject_GetAttrString((PyObject*)t, "__getmetaclass__");
63
+ if (getmetaclass)
64
+ {
65
+ /* Call getmetaclass with self=None */
66
+ metaclass = (PyTypeObject*)(PyMethodDescr_CallSelf((PyMethodDescrObject*)getmetaclass, Py_None));
67
+ Py_DECREF(getmetaclass);
68
+ if (!metaclass)
69
+ return -1;
70
+
71
+ if (!PyType_Check(metaclass))
72
+ {
73
+ PyErr_SetString(PyExc_TypeError,
74
+ "__getmetaclass__ did not return a type");
75
+ return -1;
76
+ }
77
+
78
+ /* Now, set t.__class__ to metaclass */
79
+ Py_SET_TYPE(t, metaclass);
80
+ PyType_Modified(t);
81
+ }
82
+ else
83
+ {
84
+ /* No __getmetaclass__ method: read metaclass... */
85
+ PyErr_Clear();
86
+ metaclass = Py_TYPE(t);
87
+ }
88
+
89
+ /* Now call metaclass.__init__(t, None, None, None) unless
90
+ * we would be calling type.__init__ */
91
+ initproc init = metaclass->tp_init;
92
+ if (init == NULL || init == PyType_Type.tp_init)
93
+ return 0;
94
+
95
+ /* Safety check: since we didn't call tp_new of metaclass,
96
+ * we cannot safely call tp_init if the size of the structure
97
+ * differs. */
98
+ if (metaclass->tp_basicsize != PyType_Type.tp_basicsize)
99
+ {
100
+ PyErr_SetString(PyExc_TypeError,
101
+ "metaclass is not compatible with 'type' (you cannot use cdef attributes in Cython metaclasses)");
102
+ return -1;
103
+ }
104
+
105
+ /* Initialize a tuple (None, None, None) */
106
+ if (!NoneNoneNone)
107
+ {
108
+ NoneNoneNone = PyTuple_Pack(3, Py_None, Py_None, Py_None);
109
+ if (!NoneNoneNone) return -1;
110
+ }
111
+ return init((PyObject*)t, NoneNoneNone, NULL);
112
+ }
113
+
114
+
115
+ /* Use the above function in Cython code instead of the default
116
+ * PyType_Ready() function */
117
+ #define PyType_Ready(t) Sage_PyType_Ready(t)
@@ -0,0 +1,3 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ cdef extern from "cython_metaclass.h":
3
+ PyMethodDescr_CallSelf(desc, self)
@@ -0,0 +1,130 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Metaclasses for Cython extension types
4
+
5
+ Cython does not support metaclasses, but this module can be used to
6
+ implement metaclasses for extension types.
7
+
8
+ .. WARNING::
9
+
10
+ This module has many caveats and you can easily get segfaults if you
11
+ make a mistake. It relies on undocumented Python and Cython
12
+ behaviour, so things might break in future versions.
13
+
14
+ How to use
15
+ ==========
16
+
17
+ To enable this metaclass mechanism, you need to put
18
+ ``cimport sage.cpython.cython_metaclass`` in your module (in the ``.pxd``
19
+ file if you are using one).
20
+
21
+ In the extension type (a.k.a. ``cdef class``) for which you want to
22
+ define a metaclass, define a method ``__getmetaclass__`` with a single
23
+ unused argument, and turn off the Cython directive
24
+ ``always_allow_keywords``. This method should return a type to be used as
25
+ metaclass:
26
+
27
+ .. code-block:: cython
28
+
29
+ cimport cython
30
+ cimport sage.cpython.cython_metaclass
31
+ cdef class MyCustomType():
32
+ @cython.always_allow_keywords(False)
33
+ def __getmetaclass__(_):
34
+ from foo import MyMetaclass
35
+ return MyMetaclass
36
+
37
+ .. WARNING::
38
+
39
+ ``__getmetaclass__`` must be defined as an ordinary method taking a
40
+ single argument, but this argument should not be used in the
41
+ method (it will be ``None``).
42
+
43
+ When a type ``cls`` is being constructed with metaclass ``meta``,
44
+ then ``meta.__init__(cls, None, None, None)`` is called from Cython.
45
+ In Python, this would be ``meta.__init__(cls, name, bases, dict)``.
46
+
47
+ .. WARNING::
48
+
49
+ The ``__getmetaclass__`` method is called while the type is being
50
+ created during the import of the module. Therefore,
51
+ ``__getmetaclass__`` should not refer to any global objects,
52
+ including the type being created or other types defined or imported
53
+ in the module (unless you are very careful). Note that non-imported
54
+ ``cdef`` functions are not Python objects, so those are safe to call.
55
+
56
+ The same warning applies to the ``__init__`` method of the
57
+ metaclass.
58
+
59
+ .. WARNING::
60
+
61
+ The ``__new__`` method of the metaclass (including the ``__cinit__``
62
+ method for Cython extension types) is never called if you're using
63
+ this from Cython. In particular, the metaclass cannot have any
64
+ attributes or virtual methods.
65
+
66
+ EXAMPLES::
67
+
68
+ sage: cython( # needs sage.misc.cython
69
+ ....: '''
70
+ ....: cimport cython
71
+ ....: cimport sage.cpython.cython_metaclass
72
+ ....: cdef class MyCustomType():
73
+ ....: @cython.always_allow_keywords(False)
74
+ ....: def __getmetaclass__(_):
75
+ ....: class MyMetaclass(type):
76
+ ....: def __init__(*args):
77
+ ....: print("Calling MyMetaclass.__init__{}".format(args))
78
+ ....: return MyMetaclass
79
+ ....:
80
+ ....: cdef class MyDerivedType(MyCustomType):
81
+ ....: pass
82
+ ....: ''')
83
+ Calling MyMetaclass.__init__(<class '...MyCustomType'>, None, None, None)
84
+ Calling MyMetaclass.__init__(<class '...MyDerivedType'>, None, None, None)
85
+ sage: MyCustomType.__class__ # needs sage.misc.cython
86
+ <class '...MyMetaclass'>
87
+ sage: class MyPythonType(MyDerivedType): # needs sage.misc.cython
88
+ ....: pass
89
+ Calling MyMetaclass.__init__(<class '...MyPythonType'>, 'MyPythonType', (<class '...MyDerivedType'>,), {...})
90
+
91
+ Implementation
92
+ ==============
93
+
94
+ All this is implemented by defining
95
+
96
+ .. code-block:: c
97
+
98
+ #define PyTypeReady(t) Sage_PyType_Ready(t)
99
+
100
+ and then implementing the function ``Sage_PyType_Ready(t)`` which first
101
+ calls ``PyType_Ready(t)`` and then handles the metaclass stuff.
102
+
103
+ TESTS:
104
+
105
+ Check that a proper exception is raised if ``__getmetaclass__``
106
+ returns a non-type::
107
+
108
+ sage: cython( # needs sage.misc.cython
109
+ ....: '''
110
+ ....: cimport cython
111
+ ....: cimport sage.cpython.cython_metaclass
112
+ ....: cdef class MyCustomType():
113
+ ....: @cython.always_allow_keywords(False)
114
+ ....: def __getmetaclass__(_):
115
+ ....: return 2
116
+ ....: ''')
117
+ Traceback (most recent call last):
118
+ ...
119
+ TypeError: __getmetaclass__ did not return a type
120
+ """
121
+
122
+ # ****************************************************************************
123
+ # Copyright (C) 2015 Jeroen Demeyer <jdemeyer@cage.ugent.be>
124
+ #
125
+ # This program is free software: you can redistribute it and/or modify
126
+ # it under the terms of the GNU General Public License as published by
127
+ # the Free Software Foundation, either version 2 of the License, or
128
+ # (at your option) any later version.
129
+ # https://www.gnu.org/licenses/
130
+ # ****************************************************************************