passagemath-objects 10.6.44__cp314-cp314t-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_objects/__init__.py +3 -0
  3. passagemath_objects-10.6.44.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.44.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.44.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.44.dist-info/top_level.txt +3 -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-314t-darwin.so +0 -0
  11. sage/arith/numerical_approx.pxd +35 -0
  12. sage/arith/numerical_approx.pyx +75 -0
  13. sage/arith/power.cpython-314t-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-314t-darwin.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-314t-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-314t-darwin.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-314t-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  122. sage/misc/c3_controlled.pxd +2 -0
  123. sage/misc/c3_controlled.pyx +1402 -0
  124. sage/misc/cachefunc.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  132. sage/misc/constant_function.pyx +130 -0
  133. sage/misc/decorators.py +747 -0
  134. sage/misc/fast_methods.cpython-314t-darwin.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-314t-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-314t-darwin.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-314t-darwin.so +0 -0
  144. sage/misc/inherit_comparison.pxd +5 -0
  145. sage/misc/inherit_comparison.pyx +105 -0
  146. sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  166. sage/misc/nested_class.pxd +3 -0
  167. sage/misc/nested_class.pyx +394 -0
  168. sage/misc/persist.cpython-314t-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-314t-darwin.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-314t-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  208. sage/structure/category_object.pxd +28 -0
  209. sage/structure/category_object.pyx +1087 -0
  210. sage/structure/coerce.cpython-314t-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-314t-darwin.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-314t-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-314t-darwin.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-314t-darwin.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-314t-darwin.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-314t-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-314t-darwin.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,6 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ cdef class DebugOptions_class:
3
+ cdef public bint unique_parent_warnings
4
+ cdef public bint refine_category_hash_check
5
+
6
+ cdef DebugOptions_class debug
@@ -0,0 +1,54 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Debug options for the :mod:`sage.structure` modules
4
+
5
+ EXAMPLES::
6
+
7
+ sage: from sage.structure.debug_options import debug
8
+ sage: debug.unique_parent_warnings
9
+ False
10
+ sage: debug.refine_category_hash_check
11
+ True
12
+ """
13
+
14
+ #*****************************************************************************
15
+ # Copyright (C) 2013 Robert Bradshaw <robertwb@gmail.com>
16
+ # William Stein <wstein@gmail.com>
17
+ # Volker Braun <vbraun.name@gmail.com>
18
+ #
19
+ # Distributed under the terms of the GNU General Public License (GPL)
20
+ # as published by the Free Software Foundation; either version 2 of
21
+ # the License, or (at your option) any later version.
22
+ # http://www.gnu.org/licenses/
23
+ #*****************************************************************************
24
+
25
+
26
+ cdef class DebugOptions_class:
27
+ def __cinit__(self):
28
+ """
29
+ Initializer for the debug options.
30
+
31
+ TESTS::
32
+
33
+ sage: from sage.structure.debug_options import debug
34
+ sage: type(debug)
35
+ <... 'sage.structure.debug_options.DebugOptions_class'>
36
+ """
37
+ self.unique_parent_warnings = False
38
+ # This one will be enabled during doctests
39
+ self.refine_category_hash_check = False
40
+
41
+
42
+ cdef DebugOptions_class debug = DebugOptions_class()
43
+
44
+ # Since "debug" is declared with cdef, it can only be cimported at
45
+ # the Cython level, not imported in plain Python. So we add it to the
46
+ # globals manually. However this will make the variable out of sync
47
+ # if some user modifies the object, which is inevitable.
48
+ # See https://github.com/cython/cython/issues/3959#issuecomment-753455240
49
+ # and https://github.com/cython/cython/issues/656
50
+ # Note that ``_this_module`` could not be ``globals()``
51
+ # because Sage is compiled with the old_style_globals option.
52
+ import sage.structure.debug_options as _this_module
53
+ _this_module.debug = debug
54
+ del _this_module
@@ -0,0 +1,541 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Dynamic classes
4
+
5
+ .. RUBRIC:: Why dynamic classes?
6
+
7
+ The short answer:
8
+
9
+ - Multiple inheritance is a powerful tool for constructing new classes
10
+ by combining preexisting building blocks.
11
+ - There is a combinatorial explosion in the number of potentially
12
+ useful classes that can be produced this way.
13
+ - The implementation of standard mathematical constructions calls for
14
+ producing such combinations automatically.
15
+ - Dynamic classes, i.e. classes created on the fly by the Python
16
+ interpreter, are a natural mean to achieve this.
17
+
18
+ The long answer:
19
+
20
+ Say we want to construct a new class ``MyPermutation`` for
21
+ permutations in a given set `S` (in Sage, `S` will be modelled by a
22
+ parent, but we won't discuss this point here). First, we have to
23
+ choose a data structure for the permutations, typically among the
24
+ following:
25
+
26
+ - Stored by cycle type
27
+ - Stored by code
28
+ - Stored in list notation
29
+ - C arrays of short ints (for small permutations)
30
+ - python lists of ints (for huge permutations)
31
+ - ...
32
+ - Stored by reduced word
33
+ - Stored as a function
34
+ - ...
35
+
36
+ Luckily, the Sage library provides (or will provide) classes
37
+ implementing each of those data structures. Those classes all share a
38
+ common interface (or possibly a common abstract base class). So we can
39
+ just derive our class from the chosen one::
40
+
41
+ class MyPermutation(PermutationCycleType):
42
+ ...
43
+
44
+ Then we may want to further choose a specific memory behavior (unique
45
+ representation, copy-on-write) which (hopefully) can again be achieved
46
+ by inheritance::
47
+
48
+ class MyPermutation(UniqueRepresentation, PermutationCycleType):
49
+ ...
50
+
51
+ Finally, we may want to endow the permutations in `S` with further
52
+ operations coming from the (algebraic) structure of `S`:
53
+
54
+ - group operations
55
+ - or just monoid operations (for a subset of permutations not stable by inverse)
56
+ - poset operations (for left/right/Bruhat order)
57
+ - word operations (searching for substrings, patterns, ...)
58
+
59
+ Or any combination thereof. Now, our class typically looks like::
60
+
61
+ class MyPermutation(UniqueRepresentation, PermutationCycleType, PosetElement, GroupElement):
62
+ ...
63
+
64
+ Note the combinatorial explosion in the potential number of classes
65
+ which can be created this way.
66
+
67
+
68
+ In practice, such classes will be used in mathematical constructions
69
+ like::
70
+
71
+ SymmetricGroup(5).subset(... TODO: find a good example in the context above ...)
72
+
73
+ In such a construction, the structure of the result, and therefore the
74
+ operations on its elements can only be determined at execution
75
+ time. Let us take another standard construction::
76
+
77
+ A = cartesian_product( B, C )
78
+
79
+ Depending on the structure of `B` and `C`, and possibly on further
80
+ options passed down by the user, `A` may be:
81
+
82
+ - an enumerated set
83
+ - a group
84
+ - an algebra
85
+ - a poset
86
+ - ...
87
+
88
+ Or any combination thereof.
89
+
90
+ Hardcoding classes for all potential combinations would be at best
91
+ tedious. Furthermore, this would require a cumbersome mechanism to
92
+ lookup the appropriate class depending on the desired combination.
93
+
94
+ Instead, one may use the ability of Python to create new classes
95
+ dynamically::
96
+
97
+ type("class name", tuple of base classes, dictionary of methods)
98
+
99
+ This paradigm is powerful, but there are some technicalities to
100
+ address. The purpose of this library is to standardize its use within
101
+ Sage, and in particular to ensure that the constructed classes are
102
+ reused whenever possible (unique representation), and can be pickled.
103
+
104
+ .. RUBRIC:: Combining dynamic classes and Cython classes
105
+
106
+ Cython classes cannot inherit from a dynamic class (there might be
107
+ some partial support for this in the future). On the other hand, such
108
+ an inheritance can be partially emulated using :meth:`__getattr__`. See
109
+ ``sage.categories.examples.semigroups_cython`` for an example.
110
+ """
111
+
112
+ # ****************************************************************************
113
+ # Copyright (C) 2008-2009 Nicolas M. Thiery <nthiery at users.sf.net>
114
+ #
115
+ # This program is free software: you can redistribute it and/or modify
116
+ # it under the terms of the GNU General Public License as published by
117
+ # the Free Software Foundation, either version 2 of the License, or
118
+ # (at your option) any later version.
119
+ # https://www.gnu.org/licenses/
120
+ # ****************************************************************************
121
+
122
+ import copyreg
123
+
124
+ from sage.misc.cachefunc import weak_cached_function
125
+ from sage.misc.classcall_metaclass import ClasscallMetaclass
126
+ from sage.misc.inherit_comparison import InheritComparisonMetaclass, InheritComparisonClasscallMetaclass
127
+
128
+
129
+ def dynamic_class(name, bases, cls=None, reduction=None, doccls=None,
130
+ prepend_cls_bases=True, cache=True):
131
+ r"""
132
+ INPUT:
133
+
134
+ - ``name`` -- string
135
+ - ``bases`` -- tuple of classes
136
+ - ``cls`` -- a class or ``None``
137
+ - ``reduction`` -- tuple or ``None``
138
+ - ``doccls`` -- a class or ``None``
139
+ - ``prepend_cls_bases`` -- boolean (default: ``True``)
140
+ - ``cache`` -- boolean or ``'ignore_reduction'`` (default: ``True``)
141
+
142
+ Constructs dynamically a new class ``C`` with name ``name``, and
143
+ bases ``bases``. If ``cls`` is provided, then its methods will be
144
+ inserted into ``C``, and its bases will be prepended to ``bases``
145
+ (unless ``prepend_cls_bases`` is ``False``).
146
+
147
+ The module, documentation and source introspection is taken from
148
+ ``doccls``, or ``cls`` if ``doccls`` is ``None``, or ``bases[0]``
149
+ if both are ``None`` (therefore ``bases`` should be non empty if
150
+ ``cls`` is ``None``).
151
+
152
+ The constructed class can safely be pickled (assuming the
153
+ arguments themselves can).
154
+
155
+ Unless ``cache`` is ``False``, the result is cached, ensuring unique
156
+ representation of dynamic classes.
157
+
158
+ See :mod:`sage.structure.dynamic_class` for a discussion of the
159
+ dynamic classes paradigm, and its relevance to Sage.
160
+
161
+ EXAMPLES:
162
+
163
+ To setup the stage, we create a class Foo with some methods,
164
+ cached methods, and lazy attributes, and a class Bar::
165
+
166
+ sage: from sage.misc.lazy_attribute import lazy_attribute
167
+ sage: from sage.misc.cachefunc import cached_function
168
+ sage: from sage.structure.dynamic_class import dynamic_class
169
+ sage: class Foo():
170
+ ....: "The Foo class"
171
+ ....: def __init__(self, x):
172
+ ....: self._x = x
173
+ ....: @cached_method
174
+ ....: def f(self):
175
+ ....: return self._x^2
176
+ ....: def g(self):
177
+ ....: return self._x^2
178
+ ....: @lazy_attribute
179
+ ....: def x(self):
180
+ ....: return self._x
181
+ sage: class Bar:
182
+ ....: def bar(self):
183
+ ....: return self._x^2
184
+
185
+ We now create a class FooBar which is a copy of Foo, except that it
186
+ also inherits from Bar::
187
+
188
+ sage: FooBar = dynamic_class("FooBar", (Bar,), Foo)
189
+ sage: x = FooBar(3)
190
+ sage: x.f()
191
+ 9
192
+ sage: x.f() is x.f()
193
+ True
194
+ sage: x.x
195
+ 3
196
+ sage: x.bar()
197
+ 9
198
+ sage: FooBar.__name__
199
+ 'FooBar'
200
+ sage: FooBar.__module__
201
+ '__main__'
202
+
203
+ sage: Foo.__bases__
204
+ (<class 'object'>,)
205
+ sage: FooBar.__bases__
206
+ (<class '__main__.Bar'>,)
207
+ sage: Foo.mro()
208
+ [<class '__main__.Foo'>, <class 'object'>]
209
+ sage: FooBar.mro()
210
+ [<class '__main__.FooBar'>, <class '__main__.Bar'>, <class 'object'>]
211
+
212
+ If all the base classes have a zero ``__dictoffset__``, the dynamic
213
+ class also has a zero ``__dictoffset__``. This means that the
214
+ instances of the class don't have a ``__dict__``
215
+ (see :issue:`23435`)::
216
+
217
+ sage: dyn = dynamic_class("dyn", (Integer,))
218
+ sage: dyn.__dictoffset__
219
+ 0
220
+
221
+ .. RUBRIC:: Pickling
222
+
223
+ Dynamic classes are pickled by construction. Namely, upon
224
+ unpickling, the class will be reconstructed by recalling
225
+ dynamic_class with the same arguments::
226
+
227
+ sage: type(FooBar).__reduce__(FooBar)
228
+ (<function dynamic_class at ...>, ('FooBar', (<class '__main__.Bar'>,), <class '__main__.Foo'>, None, None))
229
+
230
+ Technically, this is achieved by using a metaclass, since the
231
+ Python pickling protocol for classes is to pickle by name::
232
+
233
+ sage: type(FooBar)
234
+ <class 'sage.structure.dynamic_class.DynamicMetaclass'>
235
+
236
+ The following (meaningless) example illustrates how to customize
237
+ the result of the reduction::
238
+
239
+ sage: BarFoo = dynamic_class('BarFoo', (Foo,), Bar, reduction = (str, (3,)))
240
+ sage: type(BarFoo).__reduce__(BarFoo)
241
+ (<class 'str'>, (3,))
242
+ sage: loads(dumps(BarFoo))
243
+ '3'
244
+
245
+ .. RUBRIC:: Caching
246
+
247
+ By default, the built class is cached::
248
+
249
+ sage: dynamic_class("FooBar", (Bar,), Foo) is FooBar
250
+ True
251
+ sage: dynamic_class("FooBar", (Bar,), Foo, cache=True) is FooBar
252
+ True
253
+
254
+ and the result depends on the reduction::
255
+
256
+ sage: dynamic_class('BarFoo', (Foo,), Bar, reduction = (str, (3,))) is BarFoo
257
+ True
258
+ sage: dynamic_class('BarFoo', (Foo,), Bar, reduction = (str, (2,))) is BarFoo
259
+ False
260
+
261
+ With ``cache=False``, a new class is created each time::
262
+
263
+ sage: FooBar1 = dynamic_class("FooBar", (Bar,), Foo, cache=False); FooBar1
264
+ <class '__main__.FooBar'>
265
+ sage: FooBar2 = dynamic_class("FooBar", (Bar,), Foo, cache=False); FooBar2
266
+ <class '__main__.FooBar'>
267
+ sage: FooBar1 is FooBar
268
+ False
269
+ sage: FooBar2 is FooBar1
270
+ False
271
+
272
+ With ``cache="ignore_reduction"``, the class does not depend on
273
+ the reduction::
274
+
275
+ sage: BarFoo = dynamic_class('BarFoo', (Foo,), Bar, reduction = (str, (3,)), cache='ignore_reduction')
276
+ sage: dynamic_class('BarFoo', (Foo,), Bar, reduction = (str, (2,)), cache='ignore_reduction') is BarFoo
277
+ True
278
+
279
+ In particular, the reduction used is that provided upon creating the
280
+ first class::
281
+
282
+ sage: dynamic_class('BarFoo', (Foo,), Bar, reduction = (str, (2,)), cache='ignore_reduction')._reduction
283
+ (<class 'str'>, (3,))
284
+
285
+ .. WARNING::
286
+
287
+ The behaviour upon creating several dynamic classes from the
288
+ same data but with different values for ``cache`` option is
289
+ currently left unspecified. In other words, for a given
290
+ application, it is recommended to consistently use the same
291
+ value for that option.
292
+
293
+ TESTS::
294
+
295
+ sage: import __main__
296
+ sage: __main__.Foo = Foo
297
+ sage: __main__.Bar = Bar
298
+ sage: x = FooBar(3)
299
+ sage: x.__dict__ # Breaks without the __dict__ deletion in dynamic_class_internal
300
+ {'_x': 3}
301
+
302
+ sage: type(FooBar).__reduce__(FooBar)
303
+ (<function dynamic_class at ...>, ('FooBar', (<class '__main__.Bar'>,), <class '__main__.Foo'>, None, None))
304
+ sage: import pickle
305
+ sage: pickle.loads(pickle.dumps(FooBar)) == FooBar
306
+ True
307
+
308
+ We check that introspection works reasonably::
309
+
310
+ sage: sage.misc.sageinspect.sage_getdoc(FooBar)
311
+ 'The Foo class\n'
312
+
313
+ Finally, we check that classes derived from UniqueRepresentation
314
+ are handled gracefully (despite them also using a metaclass)::
315
+
316
+ sage: FooUnique = dynamic_class("Foo", (Bar, UniqueRepresentation))
317
+ sage: loads(dumps(FooUnique)) is FooUnique
318
+ True
319
+ """
320
+ bases = tuple(bases)
321
+ try:
322
+ name = str(name)
323
+ except UnicodeEncodeError:
324
+ pass
325
+ assert isinstance(name, str)
326
+ # assert(cls is None or issubtype(type(cls), type) or type(cls) is classobj)
327
+ if cache is True:
328
+ return dynamic_class_internal(name, bases, cls, reduction, doccls, prepend_cls_bases)
329
+ elif cache is False:
330
+ # bypass the cached method
331
+ return dynamic_class_internal.f(name, bases, cls, reduction, doccls, prepend_cls_bases)
332
+ else: # cache = "ignore_reduction"
333
+ result = dynamic_class_internal(name, bases, cls, False, doccls, prepend_cls_bases)
334
+ if result._reduction is False:
335
+ result._reduction = reduction
336
+ return result
337
+
338
+
339
+ @weak_cached_function
340
+ def dynamic_class_internal(name, bases, cls=None, reduction=None, doccls=None, prepend_cls_bases=True):
341
+ r"""
342
+ See sage.structure.dynamic_class.dynamic_class? for indirect doctests.
343
+
344
+ TESTS::
345
+
346
+ sage: Foo1 = sage.structure.dynamic_class.dynamic_class_internal("Foo", (object,))
347
+ sage: Foo2 = sage.structure.dynamic_class.dynamic_class_internal("Foo", (object,), doccls = sage.structure.dynamic_class.TestClass)
348
+ sage: Foo3 = sage.structure.dynamic_class.dynamic_class_internal("Foo", (object,), cls = sage.structure.dynamic_class.TestClass)
349
+ sage: all(Foo.__name__ == 'Foo' for Foo in [Foo1, Foo2, Foo3])
350
+ True
351
+ sage: all(Foo.__bases__ == (object,) for Foo in [Foo1, Foo2, Foo3])
352
+ True
353
+ sage: Foo1.__module__ == object.__module__
354
+ True
355
+ sage: Foo2.__module__ == sage.structure.dynamic_class.TestClass.__module__
356
+ True
357
+ sage: Foo3.__module__ == sage.structure.dynamic_class.TestClass.__module__
358
+ True
359
+ sage: Foo1.__doc__ == object.__doc__
360
+ True
361
+ sage: Foo2.__doc__ == sage.structure.dynamic_class.TestClass.__doc__
362
+ True
363
+ sage: Foo3.__doc__ == sage.structure.dynamic_class.TestClass.__doc__
364
+ True
365
+
366
+ We check that introspection works reasonably::
367
+
368
+ sage: from sage.misc.sageinspect import sage_getfile, sage_getsourcelines
369
+ sage: sage_getfile(Foo2)
370
+ '.../sage/structure/dynamic_class.py'
371
+ sage: sage_getfile(Foo3)
372
+ '.../sage/structure/dynamic_class.py'
373
+ sage: sage_getsourcelines(Foo2)
374
+ (['class TestClass:...'], ...)
375
+ sage: sage_getsourcelines(Foo3)
376
+ (['class TestClass:...'], ...)
377
+ sage: sage_getsourcelines(Foo2())
378
+ (['class TestClass:...'], ...)
379
+ sage: sage_getsourcelines(Foo3())
380
+ (['class TestClass:...'], ...)
381
+ sage: sage_getsourcelines(Foo3().bla)
382
+ ([' def bla():...'], ...)
383
+
384
+ We check that :issue:`21895` has been resolved::
385
+
386
+ sage: C1 = sage.structure.dynamic_class.dynamic_class_internal("C1", (Morphism, UniqueRepresentation))
387
+ sage: type(C1)
388
+ <class 'sage.structure.dynamic_class.DynamicInheritComparisonClasscallMetaclass'>
389
+ sage: C2 = sage.structure.dynamic_class.dynamic_class_internal("C2", (UniqueRepresentation, Morphism))
390
+ sage: type(C2)
391
+ <class 'sage.structure.dynamic_class.DynamicInheritComparisonClasscallMetaclass'>
392
+
393
+ We check that :issue:`28392` has been resolved::
394
+
395
+ sage: class A:
396
+ ....: pass
397
+ sage: Foo1 = sage.structure.dynamic_class.dynamic_class("Foo", (), A)
398
+ sage: "__weakref__" in Foo1.__dict__
399
+ False
400
+ sage: "__dict__" in Foo1.__dict__
401
+ False
402
+ """
403
+ if reduction is None:
404
+ reduction = (dynamic_class, (name, bases, cls, reduction, doccls))
405
+ if cls is not None:
406
+ methods = dict(cls.__dict__)
407
+ # Anything else that should not be kept?
408
+ for key in ["__dict__", "__weakref__"]:
409
+ if key in methods:
410
+ del methods[key]
411
+ if prepend_cls_bases:
412
+ cls_bases = cls.__bases__
413
+ all_bases = set()
414
+ for base in bases:
415
+ if isinstance(base, type):
416
+ all_bases.update(base.mro())
417
+ cls_bases = tuple(b for b in cls_bases if b not in all_bases)
418
+ bases = cls_bases + bases
419
+ else:
420
+ methods = {}
421
+ if doccls is None:
422
+ if cls is not None:
423
+ doccls = cls
424
+ else:
425
+ assert bases != ()
426
+ doccls = bases[0]
427
+ methods['_reduction'] = reduction
428
+ # HACK: _doccls is a 1-element tuple to avoid __classget__
429
+ # or trouble with binding behaviour...
430
+ methods['_doccls'] = (doccls,)
431
+ methods['__doc__'] = doccls.__doc__
432
+ methods['__module__'] = doccls.__module__
433
+
434
+ # If none of the bases have a __dict__, the new class shouldn't
435
+ # have one either.
436
+ # NOTE: we need the isinstance(b, type) check to exclude old-style
437
+ # classes.
438
+ if all(isinstance(b, type) and not b.__dictoffset__ for b in bases):
439
+ methods['__slots__'] = ()
440
+
441
+ metaclass = DynamicMetaclass
442
+ # The metaclass of a class must derive from the metaclasses of its
443
+ # bases. The following handles the case where one of the base
444
+ # classes is a known Sage metaclass. This approach won't scale
445
+ # well if we start using metaclasses seriously in Sage.
446
+ for base in bases:
447
+ if isinstance(base, ClasscallMetaclass):
448
+ if not issubclass(metaclass, ClasscallMetaclass):
449
+ if metaclass is DynamicMetaclass:
450
+ metaclass = DynamicClasscallMetaclass
451
+ elif metaclass is DynamicInheritComparisonMetaclass:
452
+ metaclass = DynamicInheritComparisonClasscallMetaclass
453
+ else:
454
+ raise NotImplementedError("No subclass of %r known that inherits from ClasscallMetaclass" % (metaclass,))
455
+ if isinstance(base, InheritComparisonMetaclass):
456
+ if not issubclass(metaclass, InheritComparisonMetaclass):
457
+ if metaclass is DynamicMetaclass:
458
+ metaclass = DynamicInheritComparisonMetaclass
459
+ elif metaclass is DynamicClasscallMetaclass:
460
+ metaclass = DynamicInheritComparisonClasscallMetaclass
461
+ else:
462
+ raise NotImplementedError("No subclass of %r known that inherits from InheritComparisonMetaclass" % (metaclass,))
463
+ return metaclass(name, bases, methods)
464
+
465
+
466
+ class DynamicMetaclass(type):
467
+ """
468
+ A metaclass implementing an appropriate reduce-by-construction method
469
+ """
470
+ def _sage_src_lines_(self):
471
+ r"""
472
+ Get the source lines of the dynamic class. This defers to the
473
+ source lines of the ``_doccls`` attribute, which is set when
474
+ the dynamic class is constructed.
475
+
476
+ EXAMPLES::
477
+
478
+ sage: from sage.misc.sageinspect import sage_getsourcelines
479
+ sage: from sage.structure.dynamic_class import dynamic_class
480
+ sage: C = dynamic_class("SomeClass", [object], doccls=Integer)
481
+ sage: sage_getsourcelines(C)[0][0]
482
+ 'cdef class Integer(sage.structure.element.EuclideanDomainElement):\n'
483
+ """
484
+ try:
485
+ # HACK: _doccls is a 1-element tuple to avoid __classget__
486
+ # or trouble with binding behaviour...
487
+ doccls = self._doccls[0]
488
+ except AttributeError:
489
+ raise NotImplementedError("no _doccls found")
490
+ from sage.misc.sageinspect import sage_getsourcelines
491
+ return sage_getsourcelines(doccls)
492
+
493
+ def __reduce__(self):
494
+ """
495
+ See :func:`sage.structure.dynamic_class.dynamic_class` for
496
+ non-trivial tests.
497
+
498
+ TESTS::
499
+
500
+ sage: class Foo: pass
501
+ sage: class DocClass: pass
502
+ sage: C = sage.structure.dynamic_class.dynamic_class_internal("bla", (object,), Foo, doccls = DocClass)
503
+ sage: type(C).__reduce__(C)
504
+ (<function dynamic_class at ...>,
505
+ ('bla', (<class 'object'>,), <class '__main__.Foo'>, None, <class '__main__.DocClass'>))
506
+ sage: C = sage.structure.dynamic_class.dynamic_class_internal("bla", (object,), Foo, doccls = DocClass, reduction = "blah")
507
+ sage: type(C).__reduce__(C)
508
+ 'blah'
509
+ """
510
+ return self._reduction
511
+
512
+
513
+ class DynamicClasscallMetaclass(DynamicMetaclass, ClasscallMetaclass):
514
+ pass
515
+
516
+
517
+ class DynamicInheritComparisonMetaclass(DynamicMetaclass, InheritComparisonMetaclass):
518
+ pass
519
+
520
+
521
+ class DynamicInheritComparisonClasscallMetaclass(DynamicMetaclass, InheritComparisonClasscallMetaclass):
522
+ pass
523
+
524
+
525
+ # This registers the appropriate reduction methods (see Issue #5985)
526
+ for M in [DynamicMetaclass,
527
+ DynamicClasscallMetaclass,
528
+ DynamicInheritComparisonMetaclass,
529
+ DynamicInheritComparisonClasscallMetaclass]:
530
+ copyreg.pickle(M, M.__reduce__)
531
+
532
+
533
+ class TestClass:
534
+ """
535
+ A class used for checking that introspection works
536
+ """
537
+ def bla():
538
+ """
539
+ bla ...
540
+ """
541
+ pass