passagemath-objects 10.6.45__cp313-cp313-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 (280) hide show
  1. passagemath_objects/__init__.py +3 -0
  2. passagemath_objects-10.6.45.dist-info/METADATA +115 -0
  3. passagemath_objects-10.6.45.dist-info/RECORD +280 -0
  4. passagemath_objects-10.6.45.dist-info/WHEEL +5 -0
  5. passagemath_objects-10.6.45.dist-info/top_level.txt +3 -0
  6. passagemath_objects.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  7. sage/all__sagemath_objects.py +37 -0
  8. sage/arith/all__sagemath_objects.py +5 -0
  9. sage/arith/long.pxd +411 -0
  10. sage/arith/numerical_approx.cpython-313-x86_64-linux-musl.so +0 -0
  11. sage/arith/numerical_approx.pxd +35 -0
  12. sage/arith/numerical_approx.pyx +75 -0
  13. sage/arith/power.cpython-313-x86_64-linux-musl.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-313-x86_64-linux-musl.so +0 -0
  17. sage/categories/action.pxd +29 -0
  18. sage/categories/action.pyx +641 -0
  19. sage/categories/algebra_functor.py +745 -0
  20. sage/categories/all__sagemath_objects.py +33 -0
  21. sage/categories/basic.py +62 -0
  22. sage/categories/cartesian_product.py +295 -0
  23. sage/categories/category.py +3401 -0
  24. sage/categories/category_cy_helper.cpython-313-x86_64-linux-musl.so +0 -0
  25. sage/categories/category_cy_helper.pxd +8 -0
  26. sage/categories/category_cy_helper.pyx +322 -0
  27. sage/categories/category_singleton.cpython-313-x86_64-linux-musl.so +0 -0
  28. sage/categories/category_singleton.pxd +3 -0
  29. sage/categories/category_singleton.pyx +342 -0
  30. sage/categories/category_types.py +637 -0
  31. sage/categories/category_with_axiom.py +2876 -0
  32. sage/categories/covariant_functorial_construction.py +703 -0
  33. sage/categories/facade_sets.py +228 -0
  34. sage/categories/functor.cpython-313-x86_64-linux-musl.so +0 -0
  35. sage/categories/functor.pxd +7 -0
  36. sage/categories/functor.pyx +691 -0
  37. sage/categories/homset.py +1338 -0
  38. sage/categories/homsets.py +364 -0
  39. sage/categories/isomorphic_objects.py +73 -0
  40. sage/categories/map.cpython-313-x86_64-linux-musl.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-313-x86_64-linux-musl.so +0 -0
  44. sage/categories/morphism.pxd +14 -0
  45. sage/categories/morphism.pyx +895 -0
  46. sage/categories/objects.py +167 -0
  47. sage/categories/primer.py +1696 -0
  48. sage/categories/pushout.py +4834 -0
  49. sage/categories/quotients.py +64 -0
  50. sage/categories/realizations.py +200 -0
  51. sage/categories/sets_cat.py +3290 -0
  52. sage/categories/sets_with_partial_maps.py +52 -0
  53. sage/categories/subobjects.py +64 -0
  54. sage/categories/subquotients.py +21 -0
  55. sage/categories/with_realizations.py +311 -0
  56. sage/cpython/__init__.py +19 -0
  57. sage/cpython/_py2_random.py +619 -0
  58. sage/cpython/all.py +3 -0
  59. sage/cpython/atexit.cpython-313-x86_64-linux-musl.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-313-x86_64-linux-musl.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-313-x86_64-linux-musl.so +0 -0
  64. sage/cpython/cython_metaclass.h +117 -0
  65. sage/cpython/cython_metaclass.pxd +3 -0
  66. sage/cpython/cython_metaclass.pyx +130 -0
  67. sage/cpython/debug.cpython-313-x86_64-linux-musl.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-313-x86_64-linux-musl.so +0 -0
  70. sage/cpython/dict_del_by_value.pxd +9 -0
  71. sage/cpython/dict_del_by_value.pyx +191 -0
  72. sage/cpython/dict_internal.h +245 -0
  73. sage/cpython/getattr.cpython-313-x86_64-linux-musl.so +0 -0
  74. sage/cpython/getattr.pxd +9 -0
  75. sage/cpython/getattr.pyx +439 -0
  76. sage/cpython/pycore_long.h +97 -0
  77. sage/cpython/pycore_long.pxd +10 -0
  78. sage/cpython/python_debug.h +44 -0
  79. sage/cpython/python_debug.pxd +47 -0
  80. sage/cpython/pyx_visit.h +13 -0
  81. sage/cpython/string.cpython-313-x86_64-linux-musl.so +0 -0
  82. sage/cpython/string.pxd +76 -0
  83. sage/cpython/string.pyx +34 -0
  84. sage/cpython/string_impl.h +60 -0
  85. sage/cpython/type.cpython-313-x86_64-linux-musl.so +0 -0
  86. sage/cpython/type.pxd +2 -0
  87. sage/cpython/type.pyx +40 -0
  88. sage/cpython/wrapperdescr.pxd +67 -0
  89. sage/ext/all__sagemath_objects.py +3 -0
  90. sage/ext/ccobject.h +64 -0
  91. sage/ext/cplusplus.pxd +17 -0
  92. sage/ext/mod_int.h +30 -0
  93. sage/ext/mod_int.pxd +24 -0
  94. sage/ext/stdsage.pxd +39 -0
  95. sage/groups/all__sagemath_objects.py +1 -0
  96. sage/groups/group.cpython-313-x86_64-linux-musl.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-313-x86_64-linux-musl.so +0 -0
  100. sage/groups/old.pxd +14 -0
  101. sage/groups/old.pyx +219 -0
  102. sage/libs/all__sagemath_objects.py +3 -0
  103. sage/libs/gmp/__init__.py +1 -0
  104. sage/libs/gmp/all.pxd +6 -0
  105. sage/libs/gmp/binop.pxd +23 -0
  106. sage/libs/gmp/misc.pxd +8 -0
  107. sage/libs/gmp/mpf.pxd +88 -0
  108. sage/libs/gmp/mpn.pxd +57 -0
  109. sage/libs/gmp/mpq.pxd +57 -0
  110. sage/libs/gmp/mpz.pxd +202 -0
  111. sage/libs/gmp/pylong.cpython-313-x86_64-linux-musl.so +0 -0
  112. sage/libs/gmp/pylong.pxd +12 -0
  113. sage/libs/gmp/pylong.pyx +150 -0
  114. sage/libs/gmp/random.pxd +25 -0
  115. sage/libs/gmp/randomize.pxd +59 -0
  116. sage/libs/gmp/types.pxd +53 -0
  117. sage/libs/gmpxx.pxd +19 -0
  118. sage/misc/abstract_method.py +276 -0
  119. sage/misc/all__sagemath_objects.py +43 -0
  120. sage/misc/bindable_class.py +253 -0
  121. sage/misc/c3_controlled.cpython-313-x86_64-linux-musl.so +0 -0
  122. sage/misc/c3_controlled.pxd +2 -0
  123. sage/misc/c3_controlled.pyx +1402 -0
  124. sage/misc/cachefunc.cpython-313-x86_64-linux-musl.so +0 -0
  125. sage/misc/cachefunc.pxd +43 -0
  126. sage/misc/cachefunc.pyx +3781 -0
  127. sage/misc/call.py +188 -0
  128. sage/misc/classcall_metaclass.cpython-313-x86_64-linux-musl.so +0 -0
  129. sage/misc/classcall_metaclass.pxd +14 -0
  130. sage/misc/classcall_metaclass.pyx +599 -0
  131. sage/misc/constant_function.cpython-313-x86_64-linux-musl.so +0 -0
  132. sage/misc/constant_function.pyx +130 -0
  133. sage/misc/decorators.py +747 -0
  134. sage/misc/fast_methods.cpython-313-x86_64-linux-musl.so +0 -0
  135. sage/misc/fast_methods.pxd +20 -0
  136. sage/misc/fast_methods.pyx +351 -0
  137. sage/misc/flatten.py +90 -0
  138. sage/misc/fpickle.cpython-313-x86_64-linux-musl.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-313-x86_64-linux-musl.so +0 -0
  141. sage/misc/function_mangling.pxd +11 -0
  142. sage/misc/function_mangling.pyx +308 -0
  143. sage/misc/inherit_comparison.cpython-313-x86_64-linux-musl.so +0 -0
  144. sage/misc/inherit_comparison.pxd +5 -0
  145. sage/misc/inherit_comparison.pyx +105 -0
  146. sage/misc/instancedoc.cpython-313-x86_64-linux-musl.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-313-x86_64-linux-musl.so +0 -0
  149. sage/misc/lazy_attribute.pyx +607 -0
  150. sage/misc/lazy_format.py +135 -0
  151. sage/misc/lazy_import.cpython-313-x86_64-linux-musl.so +0 -0
  152. sage/misc/lazy_import.pyx +1299 -0
  153. sage/misc/lazy_import_cache.py +36 -0
  154. sage/misc/lazy_list.cpython-313-x86_64-linux-musl.so +0 -0
  155. sage/misc/lazy_list.pxd +19 -0
  156. sage/misc/lazy_list.pyx +1187 -0
  157. sage/misc/lazy_string.cpython-313-x86_64-linux-musl.so +0 -0
  158. sage/misc/lazy_string.pxd +7 -0
  159. sage/misc/lazy_string.pyx +546 -0
  160. sage/misc/misc.py +1066 -0
  161. sage/misc/misc_c.cpython-313-x86_64-linux-musl.so +0 -0
  162. sage/misc/misc_c.pxd +3 -0
  163. sage/misc/misc_c.pyx +766 -0
  164. sage/misc/namespace_package.py +37 -0
  165. sage/misc/nested_class.cpython-313-x86_64-linux-musl.so +0 -0
  166. sage/misc/nested_class.pxd +3 -0
  167. sage/misc/nested_class.pyx +394 -0
  168. sage/misc/persist.cpython-313-x86_64-linux-musl.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-313-x86_64-linux-musl.so +0 -0
  172. sage/misc/randstate.pxd +30 -0
  173. sage/misc/randstate.pyx +1059 -0
  174. sage/misc/repr.py +203 -0
  175. sage/misc/reset.cpython-313-x86_64-linux-musl.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-313-x86_64-linux-musl.so +0 -0
  178. sage/misc/sage_ostools.pyx +323 -0
  179. sage/misc/sage_timeit.py +275 -0
  180. sage/misc/sage_timeit_class.cpython-313-x86_64-linux-musl.so +0 -0
  181. sage/misc/sage_timeit_class.pyx +120 -0
  182. sage/misc/sage_unittest.py +637 -0
  183. sage/misc/sageinspect.py +2768 -0
  184. sage/misc/session.cpython-313-x86_64-linux-musl.so +0 -0
  185. sage/misc/session.pyx +392 -0
  186. sage/misc/superseded.py +557 -0
  187. sage/misc/test_nested_class.py +228 -0
  188. sage/misc/timing.py +264 -0
  189. sage/misc/unknown.py +222 -0
  190. sage/misc/verbose.py +253 -0
  191. sage/misc/weak_dict.cpython-313-x86_64-linux-musl.so +0 -0
  192. sage/misc/weak_dict.pxd +15 -0
  193. sage/misc/weak_dict.pyx +1231 -0
  194. sage/modules/all__sagemath_objects.py +1 -0
  195. sage/modules/module.cpython-313-x86_64-linux-musl.so +0 -0
  196. sage/modules/module.pxd +5 -0
  197. sage/modules/module.pyx +329 -0
  198. sage/rings/all__sagemath_objects.py +3 -0
  199. sage/rings/integer_fake.h +22 -0
  200. sage/rings/integer_fake.pxd +55 -0
  201. sage/sets/all__sagemath_objects.py +3 -0
  202. sage/sets/pythonclass.cpython-313-x86_64-linux-musl.so +0 -0
  203. sage/sets/pythonclass.pxd +9 -0
  204. sage/sets/pythonclass.pyx +247 -0
  205. sage/structure/__init__.py +4 -0
  206. sage/structure/all.py +30 -0
  207. sage/structure/category_object.cpython-313-x86_64-linux-musl.so +0 -0
  208. sage/structure/category_object.pxd +28 -0
  209. sage/structure/category_object.pyx +1087 -0
  210. sage/structure/coerce.cpython-313-x86_64-linux-musl.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-313-x86_64-linux-musl.so +0 -0
  214. sage/structure/coerce_actions.pxd +27 -0
  215. sage/structure/coerce_actions.pyx +988 -0
  216. sage/structure/coerce_dict.cpython-313-x86_64-linux-musl.so +0 -0
  217. sage/structure/coerce_dict.pxd +51 -0
  218. sage/structure/coerce_dict.pyx +1557 -0
  219. sage/structure/coerce_exceptions.py +23 -0
  220. sage/structure/coerce_maps.cpython-313-x86_64-linux-musl.so +0 -0
  221. sage/structure/coerce_maps.pxd +28 -0
  222. sage/structure/coerce_maps.pyx +718 -0
  223. sage/structure/debug_options.cpython-313-x86_64-linux-musl.so +0 -0
  224. sage/structure/debug_options.pxd +6 -0
  225. sage/structure/debug_options.pyx +54 -0
  226. sage/structure/dynamic_class.py +541 -0
  227. sage/structure/element.cpython-313-x86_64-linux-musl.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-313-x86_64-linux-musl.so +0 -0
  231. sage/structure/element_wrapper.pxd +12 -0
  232. sage/structure/element_wrapper.pyx +582 -0
  233. sage/structure/factorization.py +1422 -0
  234. sage/structure/factorization_integer.py +105 -0
  235. sage/structure/factory.cpython-313-x86_64-linux-musl.so +0 -0
  236. sage/structure/factory.pyx +786 -0
  237. sage/structure/formal_sum.py +489 -0
  238. sage/structure/gens_py.py +73 -0
  239. sage/structure/global_options.py +1743 -0
  240. sage/structure/indexed_generators.py +863 -0
  241. sage/structure/list_clone.cpython-313-x86_64-linux-musl.so +0 -0
  242. sage/structure/list_clone.pxd +65 -0
  243. sage/structure/list_clone.pyx +1867 -0
  244. sage/structure/list_clone_demo.cpython-313-x86_64-linux-musl.so +0 -0
  245. sage/structure/list_clone_demo.pyx +248 -0
  246. sage/structure/list_clone_timings.py +179 -0
  247. sage/structure/list_clone_timings_cy.cpython-313-x86_64-linux-musl.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-313-x86_64-linux-musl.so +0 -0
  250. sage/structure/mutability.pxd +21 -0
  251. sage/structure/mutability.pyx +348 -0
  252. sage/structure/nonexact.py +69 -0
  253. sage/structure/parent.cpython-313-x86_64-linux-musl.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-313-x86_64-linux-musl.so +0 -0
  257. sage/structure/parent_base.pxd +13 -0
  258. sage/structure/parent_base.pyx +44 -0
  259. sage/structure/parent_gens.cpython-313-x86_64-linux-musl.so +0 -0
  260. sage/structure/parent_gens.pxd +22 -0
  261. sage/structure/parent_gens.pyx +377 -0
  262. sage/structure/parent_old.cpython-313-x86_64-linux-musl.so +0 -0
  263. sage/structure/parent_old.pxd +25 -0
  264. sage/structure/parent_old.pyx +294 -0
  265. sage/structure/proof/__init__.py +1 -0
  266. sage/structure/proof/all.py +243 -0
  267. sage/structure/proof/proof.py +300 -0
  268. sage/structure/richcmp.cpython-313-x86_64-linux-musl.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-313-x86_64-linux-musl.so +0 -0
  272. sage/structure/sage_object.pxd +3 -0
  273. sage/structure/sage_object.pyx +988 -0
  274. sage/structure/sage_object_test.py +19 -0
  275. sage/structure/sequence.py +937 -0
  276. sage/structure/set_factories.py +1178 -0
  277. sage/structure/set_factories_example.py +527 -0
  278. sage/structure/support_view.py +179 -0
  279. sage/structure/test_factory.py +56 -0
  280. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,269 @@
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 stored in state->callbacks
168
+ // Note: In Python 3.14 the atexit_state struct changed - callbacks is now a PyObject* (PyList)
169
+
170
+ static PyObject* get_atexit_callbacks_list(PyObject *self) {
171
+ PyInterpreterState *interp = _PyInterpreterState_GET();
172
+ // Access the callbacks list directly from the interpreter state
173
+ // We return a new reference because Cython expects an owned reference
174
+ PyObject *callbacks = interp->atexit.callbacks;
175
+ Py_XINCREF(callbacks);
176
+ return callbacks;
177
+ }
178
+
179
+ // Dummy function for Python 3.14+ (never called)
180
+ static atexit_callback_struct** get_atexit_callbacks_array(PyObject *self) {
181
+ PyErr_SetString(PyExc_RuntimeError, "Python >= 3.14 has no atexit arrays");
182
+ return NULL;
183
+ }
184
+ #else
185
+ // Python < 3.14: atexit uses C array
186
+ static atexit_callback_struct** get_atexit_callbacks_array(PyObject *self) {
187
+ PyInterpreterState *interp = _PyInterpreterState_GET();
188
+ struct atexit_state state = interp->atexit;
189
+ // Cast from atexit_callback** to our struct type
190
+ return (atexit_callback_struct**)state.callbacks;
191
+ }
192
+
193
+ // Dummy function for Python < 3.14 (never called)
194
+ static PyObject* get_atexit_callbacks_list(PyObject *self) {
195
+ PyErr_SetString(PyExc_RuntimeError, "Python < 3.14 has no atexit lists");
196
+ return NULL;
197
+ }
198
+ #endif
199
+ """
200
+ # Declare both functions - they exist in all Python versions (one is dummy)
201
+ object get_atexit_callbacks_list(object module)
202
+
203
+ ctypedef struct atexit_callback_struct:
204
+ PyObject* func
205
+ PyObject* args
206
+ PyObject* kwargs
207
+ atexit_callback_struct** get_atexit_callbacks_array(object module) except NULL
208
+
209
+
210
+ def _get_exithandlers():
211
+ """Return list of exit handlers registered with the atexit module."""
212
+ cdef list exithandlers = []
213
+ cdef atexit_callback_struct ** callbacks
214
+ cdef atexit_callback_struct callback
215
+ cdef int idx
216
+ cdef object kwargs
217
+
218
+ # Python 3.14+ uses a PyList directly
219
+ if sys.version_info >= (3, 14):
220
+ callbacks_list = get_atexit_callbacks_list(atexit)
221
+ if callbacks_list is None:
222
+ return exithandlers
223
+ # callbacks is a list of tuples: [(func, args, kwargs), ...]
224
+ # Normalize kwargs to ensure it's always a dict (not None)
225
+ # Note: In Python 3.14+, atexit stores callbacks in LIFO order
226
+ # (most recently registered first), but we return them in FIFO
227
+ # order (registration order) for consistency with earlier versions
228
+ for item in reversed(callbacks_list):
229
+ func, args, kwargs = item
230
+ if kwargs is None:
231
+ kwargs = {}
232
+ exithandlers.append((func, args, kwargs))
233
+ else:
234
+ # Python < 3.14 uses C array
235
+ callbacks = get_atexit_callbacks_array(atexit)
236
+ for idx in range(atexit._ncallbacks()):
237
+ callback = callbacks[idx][0]
238
+ if callback.kwargs:
239
+ kwargs = <object>callback.kwargs
240
+ else:
241
+ kwargs = {}
242
+ exithandlers.append((<object>callback.func,
243
+ <object>callback.args,
244
+ kwargs))
245
+ return exithandlers
246
+
247
+
248
+ def _set_exithandlers(exithandlers):
249
+ """
250
+ Replace the list of exit handlers registered with the atexit module
251
+ with a new list.
252
+ """
253
+
254
+ # Clear the existing list
255
+ atexit._clear()
256
+
257
+ # We could do this more efficiently by directly rebuilding the array
258
+ # of atexit_callbacks, but this is much simpler
259
+ # Note: exithandlers is in registration order (FIFO).
260
+ # In Python 3.14+, atexit.register prepends to the list (LIFO),
261
+ # so registering in forward order gives us the correct execution order.
262
+ for callback in exithandlers:
263
+ atexit.register(callback[0], *callback[1], **callback[2])
264
+
265
+
266
+ def _clear_exithandlers():
267
+ """Clear the atexit module of all registered exit handlers."""
268
+
269
+ 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
+ # ****************************************************************************