passagemath-objects 10.6.47__cp311-cp311-macosx_13_0_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.
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.47.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.47.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.47.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.47.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-311-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-311-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-311-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-311-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-311-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-311-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-311-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-311-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-311-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-311-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-311-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-311-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-311-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-311-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-311-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-311-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-311-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-311-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-311-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-311-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-311-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-311-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-311-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-311-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-311-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-311-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-311-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-311-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-311-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-311-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-311-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-311-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-311-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-311-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-311-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-311-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-311-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-311-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-311-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-311-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-311-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-311-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-311-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-311-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-311-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-311-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,37 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Utility functions for namespace packages in Sage
4
+ """
5
+ from importlib import import_module
6
+
7
+
8
+ def install_doc(package, doc):
9
+ """
10
+ Install the docstring ``doc`` to the package.
11
+
12
+ TESTS:
13
+
14
+ sage: from sage.misc.namespace_package import install_doc
15
+ sage: install_doc('sage', 'hello')
16
+ sage: from inspect import getdoc
17
+ sage: getdoc(sage)
18
+ 'hello'
19
+ """
20
+ pkg = import_module(package)
21
+ pkg.__doc__ = doc # enable sage.package?
22
+ pkg.getdoc = lambda: doc # enable help(sage.package)
23
+
24
+
25
+ def install_dict(package, dic):
26
+ """
27
+ Install ``dic`` to the ``__dict__`` of the package.
28
+
29
+ TESTS:
30
+
31
+ sage: from sage.misc.namespace_package import install_dict
32
+ sage: install_dict('sage', {'greeting': 'hello'})
33
+ sage: sage.greeting
34
+ 'hello'
35
+ """
36
+ pkg = import_module(package)
37
+ pkg.__dict__.update(dic)
@@ -0,0 +1,3 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ cdef class NestedClassMetaclass(type):
3
+ pass
@@ -0,0 +1,394 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Fixing pickle for nested classes
4
+
5
+ As of Python 2.7, names for nested classes are set by Python in a way which is
6
+ incompatible with the pickling of such classes (pickling by name)::
7
+
8
+ sage: class A:
9
+ ....: class B:
10
+ ....: pass
11
+ sage: A.B.__name__
12
+ 'B'
13
+
14
+ instead of more natural ``'A.B'``. Furthermore upon pickling *and* unpickling a
15
+ class with name ``'A.B'`` in a module ``mod``, the standard cPickle module
16
+ searches for ``'A.B'`` in ``mod.__dict__`` instead of looking up ``'A'`` and
17
+ then ``'B'`` in the result. See: https://groups.google.com/forum/#!topic/sage-devel/bHBV9KWAt64
18
+
19
+ This module provides two utilities to workaround this issue:
20
+
21
+ - :func:`nested_pickle` "fixes" recursively the name of the subclasses of a
22
+ class and inserts their fullname ``'A.B'`` in ``mod.__dict__``
23
+
24
+ - :class:`NestedClassMetaclass` is a metaclass ensuring that
25
+ :func:`nested_pickle` is called on a class upon creation.
26
+
27
+ See also :mod:`sage.misc.test_nested_class`.
28
+
29
+ .. NOTE::
30
+
31
+ In Python 3, nested classes, like any class for that matter, have
32
+ ``__qualname__`` and the standard pickle module uses it for pickling and
33
+ unpickling. Thus the pickle module searches for ``'A.B'`` first by looking
34
+ up ``'A'`` in ``mod``, and then ``'B'`` in the result. So there is no
35
+ pickling problem for nested classes in Python 3, and the two utilities are
36
+ not really necessary. However, :class:`NestedClassMetaclass` is used widely
37
+ in Sage and affects behaviors of Sage objects in other respects than in
38
+ pickling and unpickling. Hence we keep :class:`NestedClassMetaclass` even
39
+ with Python 3, for now. This module will be removed when we eventually drop
40
+ support for Python 2.
41
+
42
+ EXAMPLES::
43
+
44
+ sage: from sage.misc.nested_class import A1, nested_pickle
45
+
46
+ sage: A1.A2.A3.__name__
47
+ 'A3'
48
+ sage: A1.A2.A3
49
+ <class 'sage.misc.nested_class.A1.A2.A3'>
50
+
51
+ sage: nested_pickle(A1)
52
+ <class 'sage.misc.nested_class.A1'>
53
+
54
+ sage: A1.A2
55
+ <class 'sage.misc.nested_class.A1.A2'>
56
+
57
+ sage: A1.A2.A3
58
+ <class 'sage.misc.nested_class.A1.A2.A3'>
59
+ sage: A1.A2.A3.__name__
60
+ 'A1.A2.A3'
61
+
62
+ sage: sage.misc.nested_class.__dict__['A1.A2'] is A1.A2
63
+ True
64
+ sage: sage.misc.nested_class.__dict__['A1.A2.A3'] is A1.A2.A3
65
+ True
66
+
67
+ All of this is not perfect. In the following scenario::
68
+
69
+ sage: class A1:
70
+ ....: class A2:
71
+ ....: pass
72
+ sage: class B1:
73
+ ....: A2 = A1.A2
74
+
75
+ sage: nested_pickle(A1)
76
+ <class '__main__.A1'>
77
+ sage: nested_pickle(B1)
78
+ <class '__main__.B1'>
79
+ sage: A1.A2
80
+ <class '__main__.A1.A2'>
81
+ sage: B1.A2
82
+ <class '__main__.A1.A2'>
83
+
84
+ The name for ``'A1.A2'`` could potentially be set to ``'B1.A2'``. But that will work anyway.
85
+ """
86
+
87
+ import sys
88
+ cdef dict sys_modules = sys.modules
89
+
90
+
91
+ __all__ = ['modify_for_nested_pickle', 'nested_pickle',
92
+ 'NestedClassMetaclass', 'MainClass'
93
+ # Comment out to silence Sphinx warning about nested classes.
94
+ # , 'SubClass', 'CopiedClass', 'A1'
95
+ ]
96
+
97
+ cpdef modify_for_nested_pickle(cls, str name_prefix, module, first_run=True):
98
+ r"""
99
+ Modify the subclasses of the given class to be picklable, by
100
+ giving them a mangled name and putting the mangled name in the
101
+ module namespace.
102
+
103
+ INPUT:
104
+
105
+ - ``cls`` -- the class to modify
106
+
107
+ - ``name_prefix`` -- the prefix to prepend to the class name
108
+
109
+ - ``module`` -- the module object to modify with the mangled name
110
+
111
+ - ``first_run`` -- boolean (default: ``True``); whether or not
112
+ this function is run for the first time on ``cls``
113
+
114
+ NOTE:
115
+
116
+ This function would usually not be directly called. It is internally used
117
+ in :class:`NestedClassMetaclass`.
118
+
119
+ EXAMPLES::
120
+
121
+ sage: from sage.misc.nested_class import *
122
+ sage: class A():
123
+ ....: class B():
124
+ ....: pass
125
+ sage: module = sys.modules['__main__']
126
+ sage: A.B.__name__
127
+ 'B'
128
+ sage: getattr(module, 'A.B', 'Not found')
129
+ 'Not found'
130
+ sage: modify_for_nested_pickle(A, 'A', module)
131
+ sage: A.B.__name__
132
+ 'A.B'
133
+ sage: getattr(module, 'A.B', 'Not found')
134
+ <class '__main__.A.B'>
135
+
136
+ Here we demonstrate the effect of the ``first_run`` argument::
137
+
138
+ sage: modify_for_nested_pickle(A, 'X', module)
139
+ sage: A.B.__name__ # nothing changed
140
+ 'A.B'
141
+ sage: modify_for_nested_pickle(A, 'X', module, first_run=False)
142
+ sage: A.B.__name__
143
+ 'X.A.B'
144
+
145
+ Note that the class is now found in the module under both its old and
146
+ its new name::
147
+
148
+ sage: getattr(module, 'A.B', 'Not found')
149
+ <class '__main__.A.B'>
150
+ sage: getattr(module, 'X.A.B', 'Not found')
151
+ <class '__main__.A.B'>
152
+
153
+ TESTS:
154
+
155
+ The following is a real life example, that was enabled by the internal
156
+ use of the``first_run`` in :issue:`9107`::
157
+
158
+ sage: cython_code = [
159
+ ....: "from sage.structure.unique_representation import UniqueRepresentation",
160
+ ....: "class A1(UniqueRepresentation):",
161
+ ....: " class B1(UniqueRepresentation):",
162
+ ....: " class C1: pass",
163
+ ....: " class B2:",
164
+ ....: " class C2: pass"]
165
+ sage: import os
166
+ sage: cython(os.linesep.join(cython_code)) # needs sage.misc.cython
167
+
168
+ Before :issue:`9107`, the name of ``A1.B1.C1`` would have been wrong::
169
+
170
+ sage: # needs sage.misc.cython
171
+ sage: A1.B1.C1.__name__
172
+ 'A1.B1.C1'
173
+ sage: A1.B2.C2.__name__
174
+ 'A1.B2.C2'
175
+ sage: A_module = sys.modules[A1.__module__]
176
+ sage: getattr(A_module, 'A1.B1.C1', 'Not found').__name__
177
+ 'A1.B1.C1'
178
+ sage: getattr(A_module, 'A1.B2.C2', 'Not found').__name__
179
+ 'A1.B2.C2'
180
+ """
181
+ cdef str name, dotted_name
182
+ cdef str mod_name = module.__name__
183
+ cdef str cls_name = cls.__name__+'.'
184
+ cdef str v_name
185
+ if first_run:
186
+ for (name, v) in cls.__dict__.items():
187
+ if isinstance(v, NestedClassMetaclass):
188
+ v_name = v.__name__
189
+ if v_name == name and v.__module__ == mod_name and getattr(module, v_name, None) is not v:
190
+ # OK, probably this is a nested class.
191
+ dotted_name = name_prefix + '.' + v_name
192
+ setattr(module, dotted_name, v)
193
+ modify_for_nested_pickle(v, name_prefix, module, False)
194
+ v.__name__ = dotted_name
195
+ elif isinstance(v, type):
196
+ v_name = v.__name__
197
+ if v_name == name and v.__module__ == mod_name and getattr(module, v_name, None) is not v:
198
+ # OK, probably this is a nested class.
199
+ dotted_name = name_prefix + '.' + v_name
200
+ setattr(module, dotted_name, v)
201
+ modify_for_nested_pickle(v, dotted_name, module)
202
+ v.__name__ = dotted_name
203
+ else:
204
+ for (name, v) in cls.__dict__.items():
205
+ if isinstance(v, type):
206
+ v_name = v.__name__
207
+ if v_name == cls_name + name and v.__module__ == mod_name:
208
+ # OK, probably this is a nested class.
209
+ dotted_name = name_prefix + '.' + v_name
210
+ setattr(module, dotted_name, v)
211
+ modify_for_nested_pickle(v, name_prefix, module, False)
212
+ v.__name__ = dotted_name
213
+
214
+
215
+ def nested_pickle(cls):
216
+ r"""
217
+ This decorator takes a class that potentially contains nested classes.
218
+ For each such nested class, its name is modified to a new illegal
219
+ identifier, and that name is set in the module. For example, if
220
+ you have::
221
+
222
+ sage: from sage.misc.nested_class import nested_pickle
223
+ sage: module = sys.modules['__main__']
224
+ sage: class A():
225
+ ....: class B:
226
+ ....: pass
227
+ sage: nested_pickle(A)
228
+ <class '__main__.A'>
229
+
230
+ then the name of class ``'B'`` will be modified to ``'A.B'``, and the ``'A.B'``
231
+ attribute of the module will be set to class ``'B'``::
232
+
233
+ sage: A.B.__name__
234
+ 'A.B'
235
+ sage: getattr(module, 'A.B', 'Not found')
236
+ <class '__main__.A.B'>
237
+
238
+ In Python 2.6, decorators work with classes; then ``@nested_pickle``
239
+ should work as a decorator::
240
+
241
+ sage: @nested_pickle # todo: not implemented
242
+ ....: class A2():
243
+ ....: class B:
244
+ ....: pass
245
+ sage: A2.B.__name__ # todo: not implemented
246
+ 'A2.B'
247
+ sage: getattr(module, 'A2.B', 'Not found') # todo: not implemented
248
+ <class __main__.A2.B at ...>
249
+
250
+ EXAMPLES::
251
+
252
+ sage: from sage.misc.nested_class import *
253
+ sage: loads(dumps(MainClass.NestedClass())) # indirect doctest
254
+ <sage.misc.nested_class.MainClass.NestedClass object at 0x...>
255
+ """
256
+ modify_for_nested_pickle(cls, cls.__name__, sys_modules[cls.__module__])
257
+ return cls
258
+
259
+
260
+ cdef class NestedClassMetaclass(type):
261
+ r"""
262
+ A metaclass for nested pickling.
263
+
264
+ Check that one can use a metaclass to ensure nested_pickle is called on any
265
+ derived subclass::
266
+
267
+ sage: from sage.misc.nested_class import NestedClassMetaclass
268
+ sage: class ASuperClass(object, metaclass=NestedClassMetaclass):
269
+ ....: pass
270
+ sage: class A3(ASuperClass):
271
+ ....: class B():
272
+ ....: pass
273
+ sage: A3.B.__name__
274
+ 'A3.B'
275
+ sage: getattr(sys.modules['__main__'], 'A3.B', 'Not found')
276
+ <class '__main__.A3.B'>
277
+ """
278
+ def __init__(self, *args):
279
+ r"""
280
+ This invokes the nested_pickle on construction.
281
+
282
+ EXAMPLES::
283
+
284
+ sage: from sage.misc.nested_class import NestedClassMetaclass
285
+ sage: class A(object, metaclass=NestedClassMetaclass):
286
+ ....: class B():
287
+ ....: pass
288
+ sage: A.B
289
+ <class '__main__.A.B'>
290
+ sage: getattr(sys.modules['__main__'], 'A.B', 'Not found')
291
+ <class '__main__.A.B'>
292
+ """
293
+ modify_for_nested_pickle(self, self.__name__, sys_modules[self.__module__])
294
+
295
+
296
+ class MainClass(object, metaclass=NestedClassMetaclass):
297
+ r"""
298
+ A simple class to test nested_pickle.
299
+
300
+ EXAMPLES::
301
+
302
+ sage: from sage.misc.nested_class import *
303
+ sage: loads(dumps(MainClass()))
304
+ <sage.misc.nested_class.MainClass object at 0x...>
305
+ """
306
+
307
+ class NestedClass():
308
+ r"""
309
+ EXAMPLES::
310
+
311
+ sage: from sage.misc.nested_class import *
312
+ sage: loads(dumps(MainClass.NestedClass()))
313
+ <sage.misc.nested_class.MainClass.NestedClass object at 0x...>
314
+ """
315
+
316
+ class NestedSubClass():
317
+ r"""
318
+ EXAMPLES::
319
+
320
+ sage: from sage.misc.nested_class import *
321
+ sage: loads(dumps(MainClass.NestedClass.NestedSubClass()))
322
+ <sage.misc.nested_class.MainClass.NestedClass.NestedSubClass object at 0x...>
323
+ sage: getattr(sage.misc.nested_class, 'MainClass.NestedClass.NestedSubClass')
324
+ <class 'sage.misc.nested_class.MainClass.NestedClass.NestedSubClass'>
325
+ sage: MainClass.NestedClass.NestedSubClass.__name__
326
+ 'MainClass.NestedClass.NestedSubClass'
327
+ """
328
+ def dummy(self, x, *args, r=(1, 2, 3.4), **kwds):
329
+ """
330
+ A dummy method to demonstrate the embedding of
331
+ method signature for nested classes.
332
+
333
+ TESTS::
334
+
335
+ sage: from sage.misc.nested_class import MainClass
336
+ sage: print(MainClass.NestedClass.NestedSubClass.dummy.__doc__)
337
+ NestedSubClass.dummy(self, x, *args, r=(1, 2, 3.4), **kwds)
338
+ File: ...sage/misc/nested_class.pyx (starting at line ...)
339
+ <BLANKLINE>
340
+ A dummy method to demonstrate the embedding of
341
+ method signature for nested classes.
342
+ ...
343
+ """
344
+ pass
345
+
346
+
347
+ class SubClass(MainClass):
348
+ r"""
349
+ A simple class to test nested_pickle.
350
+
351
+ EXAMPLES::
352
+
353
+ sage: from sage.misc.nested_class import SubClass
354
+ sage: loads(dumps(SubClass.NestedClass()))
355
+ <sage.misc.nested_class.MainClass.NestedClass object at 0x...>
356
+ sage: loads(dumps(SubClass()))
357
+ <sage.misc.nested_class.SubClass object at 0x...>
358
+ """
359
+ pass
360
+
361
+
362
+ nested_pickle(SubClass)
363
+
364
+
365
+ def _provide_SubClass():
366
+ return SubClass
367
+
368
+
369
+ class CopiedClass():
370
+ r"""
371
+ A simple class to test nested_pickle.
372
+
373
+ EXAMPLES::
374
+
375
+ sage: from sage.misc.nested_class import CopiedClass
376
+ sage: loads(dumps(CopiedClass.NestedClass()))
377
+ <sage.misc.nested_class.MainClass.NestedClass object at 0x...>
378
+ sage: loads(dumps(CopiedClass.NestedSubClass()))
379
+ <sage.misc.nested_class.MainClass.NestedClass.NestedSubClass object at 0x...>
380
+ """
381
+ NestedClass = MainClass.NestedClass
382
+ NestedSubClass = MainClass.NestedClass.NestedSubClass
383
+ SubClass = _provide_SubClass()
384
+
385
+
386
+ nested_pickle(CopiedClass)
387
+
388
+
389
+ # Further classes for recursive tests
390
+
391
+ class A1:
392
+ class A2:
393
+ class A3:
394
+ pass
Binary file