passagemath-objects 10.6.41__cp312-cp312-win_amd64.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 (281) hide show
  1. passagemath_objects/__init__.py +3 -0
  2. passagemath_objects-10.6.41.dist-info/DELVEWHEEL +2 -0
  3. passagemath_objects-10.6.41.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.41.dist-info/RECORD +281 -0
  5. passagemath_objects-10.6.41.dist-info/WHEEL +5 -0
  6. passagemath_objects-10.6.41.dist-info/top_level.txt +3 -0
  7. passagemath_objects.libs/libgmp-10-79b4110c7ea2b760f16cfef97e8a8a34.dll +0 -0
  8. sage/all__sagemath_objects.py +46 -0
  9. sage/arith/all__sagemath_objects.py +5 -0
  10. sage/arith/long.pxd +411 -0
  11. sage/arith/numerical_approx.cp312-win_amd64.pyd +0 -0
  12. sage/arith/numerical_approx.pxd +35 -0
  13. sage/arith/numerical_approx.pyx +75 -0
  14. sage/arith/power.cp312-win_amd64.pyd +0 -0
  15. sage/arith/power.pxd +31 -0
  16. sage/arith/power.pyx +127 -0
  17. sage/categories/action.cp312-win_amd64.pyd +0 -0
  18. sage/categories/action.pxd +29 -0
  19. sage/categories/action.pyx +641 -0
  20. sage/categories/algebra_functor.py +745 -0
  21. sage/categories/all__sagemath_objects.py +33 -0
  22. sage/categories/basic.py +71 -0
  23. sage/categories/cartesian_product.py +295 -0
  24. sage/categories/category.py +3401 -0
  25. sage/categories/category_cy_helper.cp312-win_amd64.pyd +0 -0
  26. sage/categories/category_cy_helper.pxd +8 -0
  27. sage/categories/category_cy_helper.pyx +322 -0
  28. sage/categories/category_singleton.cp312-win_amd64.pyd +0 -0
  29. sage/categories/category_singleton.pxd +3 -0
  30. sage/categories/category_singleton.pyx +342 -0
  31. sage/categories/category_types.py +637 -0
  32. sage/categories/category_with_axiom.py +2885 -0
  33. sage/categories/covariant_functorial_construction.py +703 -0
  34. sage/categories/facade_sets.py +228 -0
  35. sage/categories/functor.cp312-win_amd64.pyd +0 -0
  36. sage/categories/functor.pxd +7 -0
  37. sage/categories/functor.pyx +691 -0
  38. sage/categories/homset.py +1338 -0
  39. sage/categories/homsets.py +364 -0
  40. sage/categories/isomorphic_objects.py +73 -0
  41. sage/categories/map.cp312-win_amd64.pyd +0 -0
  42. sage/categories/map.pxd +34 -0
  43. sage/categories/map.pyx +2112 -0
  44. sage/categories/morphism.cp312-win_amd64.pyd +0 -0
  45. sage/categories/morphism.pxd +14 -0
  46. sage/categories/morphism.pyx +895 -0
  47. sage/categories/objects.py +167 -0
  48. sage/categories/primer.py +1696 -0
  49. sage/categories/pushout.py +4834 -0
  50. sage/categories/quotients.py +64 -0
  51. sage/categories/realizations.py +200 -0
  52. sage/categories/sets_cat.py +3228 -0
  53. sage/categories/sets_with_partial_maps.py +52 -0
  54. sage/categories/subobjects.py +64 -0
  55. sage/categories/subquotients.py +21 -0
  56. sage/categories/with_realizations.py +311 -0
  57. sage/cpython/__init__.py +28 -0
  58. sage/cpython/_py2_random.py +619 -0
  59. sage/cpython/all.py +3 -0
  60. sage/cpython/atexit.cp312-win_amd64.pyd +0 -0
  61. sage/cpython/atexit.pyx +269 -0
  62. sage/cpython/builtin_types.cp312-win_amd64.pyd +0 -0
  63. sage/cpython/builtin_types.pyx +7 -0
  64. sage/cpython/cython_metaclass.cp312-win_amd64.pyd +0 -0
  65. sage/cpython/cython_metaclass.h +117 -0
  66. sage/cpython/cython_metaclass.pxd +3 -0
  67. sage/cpython/cython_metaclass.pyx +130 -0
  68. sage/cpython/debug.cp312-win_amd64.pyd +0 -0
  69. sage/cpython/debug.pyx +302 -0
  70. sage/cpython/dict_del_by_value.cp312-win_amd64.pyd +0 -0
  71. sage/cpython/dict_del_by_value.pxd +9 -0
  72. sage/cpython/dict_del_by_value.pyx +191 -0
  73. sage/cpython/dict_internal.h +245 -0
  74. sage/cpython/getattr.cp312-win_amd64.pyd +0 -0
  75. sage/cpython/getattr.pxd +9 -0
  76. sage/cpython/getattr.pyx +439 -0
  77. sage/cpython/pycore_long.h +97 -0
  78. sage/cpython/pycore_long.pxd +10 -0
  79. sage/cpython/python_debug.h +44 -0
  80. sage/cpython/python_debug.pxd +47 -0
  81. sage/cpython/pyx_visit.h +13 -0
  82. sage/cpython/string.cp312-win_amd64.pyd +0 -0
  83. sage/cpython/string.pxd +76 -0
  84. sage/cpython/string.pyx +34 -0
  85. sage/cpython/string_impl.h +60 -0
  86. sage/cpython/type.cp312-win_amd64.pyd +0 -0
  87. sage/cpython/type.pxd +2 -0
  88. sage/cpython/type.pyx +40 -0
  89. sage/cpython/wrapperdescr.pxd +67 -0
  90. sage/ext/all__sagemath_objects.py +3 -0
  91. sage/ext/ccobject.h +64 -0
  92. sage/ext/cplusplus.pxd +17 -0
  93. sage/ext/mod_int.h +30 -0
  94. sage/ext/mod_int.pxd +24 -0
  95. sage/ext/stdsage.pxd +39 -0
  96. sage/groups/all__sagemath_objects.py +1 -0
  97. sage/groups/group.cp312-win_amd64.pyd +0 -0
  98. sage/groups/group.pxd +14 -0
  99. sage/groups/group.pyx +322 -0
  100. sage/groups/old.cp312-win_amd64.pyd +0 -0
  101. sage/groups/old.pxd +14 -0
  102. sage/groups/old.pyx +219 -0
  103. sage/libs/all__sagemath_objects.py +3 -0
  104. sage/libs/gmp/__init__.py +1 -0
  105. sage/libs/gmp/all.pxd +6 -0
  106. sage/libs/gmp/binop.pxd +23 -0
  107. sage/libs/gmp/misc.pxd +8 -0
  108. sage/libs/gmp/mpf.pxd +88 -0
  109. sage/libs/gmp/mpn.pxd +57 -0
  110. sage/libs/gmp/mpq.pxd +57 -0
  111. sage/libs/gmp/mpz.pxd +202 -0
  112. sage/libs/gmp/pylong.cp312-win_amd64.pyd +0 -0
  113. sage/libs/gmp/pylong.pxd +12 -0
  114. sage/libs/gmp/pylong.pyx +150 -0
  115. sage/libs/gmp/random.pxd +25 -0
  116. sage/libs/gmp/randomize.pxd +59 -0
  117. sage/libs/gmp/types.pxd +53 -0
  118. sage/libs/gmpxx.pxd +19 -0
  119. sage/misc/abstract_method.py +276 -0
  120. sage/misc/all__sagemath_objects.py +43 -0
  121. sage/misc/bindable_class.py +253 -0
  122. sage/misc/c3_controlled.cp312-win_amd64.pyd +0 -0
  123. sage/misc/c3_controlled.pxd +2 -0
  124. sage/misc/c3_controlled.pyx +1402 -0
  125. sage/misc/cachefunc.cp312-win_amd64.pyd +0 -0
  126. sage/misc/cachefunc.pxd +43 -0
  127. sage/misc/cachefunc.pyx +3781 -0
  128. sage/misc/call.py +188 -0
  129. sage/misc/classcall_metaclass.cp312-win_amd64.pyd +0 -0
  130. sage/misc/classcall_metaclass.pxd +14 -0
  131. sage/misc/classcall_metaclass.pyx +599 -0
  132. sage/misc/constant_function.cp312-win_amd64.pyd +0 -0
  133. sage/misc/constant_function.pyx +130 -0
  134. sage/misc/decorators.py +747 -0
  135. sage/misc/fast_methods.cp312-win_amd64.pyd +0 -0
  136. sage/misc/fast_methods.pxd +20 -0
  137. sage/misc/fast_methods.pyx +351 -0
  138. sage/misc/flatten.py +90 -0
  139. sage/misc/fpickle.cp312-win_amd64.pyd +0 -0
  140. sage/misc/fpickle.pyx +177 -0
  141. sage/misc/function_mangling.cp312-win_amd64.pyd +0 -0
  142. sage/misc/function_mangling.pxd +11 -0
  143. sage/misc/function_mangling.pyx +308 -0
  144. sage/misc/inherit_comparison.cp312-win_amd64.pyd +0 -0
  145. sage/misc/inherit_comparison.pxd +5 -0
  146. sage/misc/inherit_comparison.pyx +105 -0
  147. sage/misc/instancedoc.cp312-win_amd64.pyd +0 -0
  148. sage/misc/instancedoc.pyx +331 -0
  149. sage/misc/lazy_attribute.cp312-win_amd64.pyd +0 -0
  150. sage/misc/lazy_attribute.pyx +607 -0
  151. sage/misc/lazy_format.py +135 -0
  152. sage/misc/lazy_import.cp312-win_amd64.pyd +0 -0
  153. sage/misc/lazy_import.pyx +1299 -0
  154. sage/misc/lazy_import_cache.py +36 -0
  155. sage/misc/lazy_list.cp312-win_amd64.pyd +0 -0
  156. sage/misc/lazy_list.pxd +19 -0
  157. sage/misc/lazy_list.pyx +1187 -0
  158. sage/misc/lazy_string.cp312-win_amd64.pyd +0 -0
  159. sage/misc/lazy_string.pxd +7 -0
  160. sage/misc/lazy_string.pyx +546 -0
  161. sage/misc/misc.py +1066 -0
  162. sage/misc/misc_c.cp312-win_amd64.pyd +0 -0
  163. sage/misc/misc_c.pxd +3 -0
  164. sage/misc/misc_c.pyx +766 -0
  165. sage/misc/namespace_package.py +37 -0
  166. sage/misc/nested_class.cp312-win_amd64.pyd +0 -0
  167. sage/misc/nested_class.pxd +3 -0
  168. sage/misc/nested_class.pyx +394 -0
  169. sage/misc/persist.cp312-win_amd64.pyd +0 -0
  170. sage/misc/persist.pyx +1251 -0
  171. sage/misc/prandom.py +418 -0
  172. sage/misc/randstate.cp312-win_amd64.pyd +0 -0
  173. sage/misc/randstate.pxd +30 -0
  174. sage/misc/randstate.pyx +1059 -0
  175. sage/misc/repr.py +203 -0
  176. sage/misc/reset.cp312-win_amd64.pyd +0 -0
  177. sage/misc/reset.pyx +196 -0
  178. sage/misc/sage_ostools.cp312-win_amd64.pyd +0 -0
  179. sage/misc/sage_ostools.pyx +323 -0
  180. sage/misc/sage_timeit.py +276 -0
  181. sage/misc/sage_timeit_class.cp312-win_amd64.pyd +0 -0
  182. sage/misc/sage_timeit_class.pyx +120 -0
  183. sage/misc/sage_unittest.py +637 -0
  184. sage/misc/sageinspect.py +2768 -0
  185. sage/misc/session.cp312-win_amd64.pyd +0 -0
  186. sage/misc/session.pyx +392 -0
  187. sage/misc/superseded.py +557 -0
  188. sage/misc/test_nested_class.py +228 -0
  189. sage/misc/timing.py +264 -0
  190. sage/misc/unknown.py +222 -0
  191. sage/misc/verbose.py +253 -0
  192. sage/misc/weak_dict.cp312-win_amd64.pyd +0 -0
  193. sage/misc/weak_dict.pxd +15 -0
  194. sage/misc/weak_dict.pyx +1231 -0
  195. sage/modules/all__sagemath_objects.py +1 -0
  196. sage/modules/module.cp312-win_amd64.pyd +0 -0
  197. sage/modules/module.pxd +5 -0
  198. sage/modules/module.pyx +329 -0
  199. sage/rings/all__sagemath_objects.py +3 -0
  200. sage/rings/integer_fake.h +22 -0
  201. sage/rings/integer_fake.pxd +55 -0
  202. sage/sets/all__sagemath_objects.py +3 -0
  203. sage/sets/pythonclass.cp312-win_amd64.pyd +0 -0
  204. sage/sets/pythonclass.pxd +9 -0
  205. sage/sets/pythonclass.pyx +247 -0
  206. sage/structure/__init__.py +13 -0
  207. sage/structure/all.py +30 -0
  208. sage/structure/category_object.cp312-win_amd64.pyd +0 -0
  209. sage/structure/category_object.pxd +28 -0
  210. sage/structure/category_object.pyx +1087 -0
  211. sage/structure/coerce.cp312-win_amd64.pyd +0 -0
  212. sage/structure/coerce.pxd +44 -0
  213. sage/structure/coerce.pyx +2107 -0
  214. sage/structure/coerce_actions.cp312-win_amd64.pyd +0 -0
  215. sage/structure/coerce_actions.pxd +27 -0
  216. sage/structure/coerce_actions.pyx +988 -0
  217. sage/structure/coerce_dict.cp312-win_amd64.pyd +0 -0
  218. sage/structure/coerce_dict.pxd +51 -0
  219. sage/structure/coerce_dict.pyx +1557 -0
  220. sage/structure/coerce_exceptions.py +23 -0
  221. sage/structure/coerce_maps.cp312-win_amd64.pyd +0 -0
  222. sage/structure/coerce_maps.pxd +28 -0
  223. sage/structure/coerce_maps.pyx +718 -0
  224. sage/structure/debug_options.cp312-win_amd64.pyd +0 -0
  225. sage/structure/debug_options.pxd +6 -0
  226. sage/structure/debug_options.pyx +54 -0
  227. sage/structure/dynamic_class.py +541 -0
  228. sage/structure/element.cp312-win_amd64.pyd +0 -0
  229. sage/structure/element.pxd +272 -0
  230. sage/structure/element.pyx +4772 -0
  231. sage/structure/element_wrapper.cp312-win_amd64.pyd +0 -0
  232. sage/structure/element_wrapper.pxd +12 -0
  233. sage/structure/element_wrapper.pyx +582 -0
  234. sage/structure/factorization.py +1422 -0
  235. sage/structure/factorization_integer.py +105 -0
  236. sage/structure/factory.cp312-win_amd64.pyd +0 -0
  237. sage/structure/factory.pyx +786 -0
  238. sage/structure/formal_sum.py +489 -0
  239. sage/structure/gens_py.py +73 -0
  240. sage/structure/global_options.py +1743 -0
  241. sage/structure/indexed_generators.py +863 -0
  242. sage/structure/list_clone.cp312-win_amd64.pyd +0 -0
  243. sage/structure/list_clone.pxd +65 -0
  244. sage/structure/list_clone.pyx +1867 -0
  245. sage/structure/list_clone_demo.cp312-win_amd64.pyd +0 -0
  246. sage/structure/list_clone_demo.pyx +248 -0
  247. sage/structure/list_clone_timings.py +179 -0
  248. sage/structure/list_clone_timings_cy.cp312-win_amd64.pyd +0 -0
  249. sage/structure/list_clone_timings_cy.pyx +86 -0
  250. sage/structure/mutability.cp312-win_amd64.pyd +0 -0
  251. sage/structure/mutability.pxd +21 -0
  252. sage/structure/mutability.pyx +348 -0
  253. sage/structure/nonexact.py +69 -0
  254. sage/structure/parent.cp312-win_amd64.pyd +0 -0
  255. sage/structure/parent.pxd +112 -0
  256. sage/structure/parent.pyx +3093 -0
  257. sage/structure/parent_base.cp312-win_amd64.pyd +0 -0
  258. sage/structure/parent_base.pxd +13 -0
  259. sage/structure/parent_base.pyx +44 -0
  260. sage/structure/parent_gens.cp312-win_amd64.pyd +0 -0
  261. sage/structure/parent_gens.pxd +22 -0
  262. sage/structure/parent_gens.pyx +377 -0
  263. sage/structure/parent_old.cp312-win_amd64.pyd +0 -0
  264. sage/structure/parent_old.pxd +25 -0
  265. sage/structure/parent_old.pyx +294 -0
  266. sage/structure/proof/__init__.py +1 -0
  267. sage/structure/proof/all.py +243 -0
  268. sage/structure/proof/proof.py +300 -0
  269. sage/structure/richcmp.cp312-win_amd64.pyd +0 -0
  270. sage/structure/richcmp.pxd +213 -0
  271. sage/structure/richcmp.pyx +495 -0
  272. sage/structure/sage_object.cp312-win_amd64.pyd +0 -0
  273. sage/structure/sage_object.pxd +3 -0
  274. sage/structure/sage_object.pyx +988 -0
  275. sage/structure/sage_object_test.py +19 -0
  276. sage/structure/sequence.py +937 -0
  277. sage/structure/set_factories.py +1178 -0
  278. sage/structure/set_factories_example.py +527 -0
  279. sage/structure/support_view.py +179 -0
  280. sage/structure/test_factory.py +56 -0
  281. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,331 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Dynamic documentation for instances of classes
4
+
5
+ The functionality in this module allows to define specific docstrings
6
+ of *instances* of a class, which are different from the class docstring.
7
+ A typical use case is given by cached methods: the documentation of a
8
+ cached method should not be the documentation of the class
9
+ :class:`CachedMethod`; it should be the documentation of the underlying
10
+ method.
11
+
12
+ In order to use this, define a class docstring as usual. Also define a
13
+ method ``def _instancedoc_(self)`` which should return the docstring of
14
+ the instance ``self``. Finally, add the decorator ``@instancedoc`` to
15
+ the class.
16
+
17
+ .. WARNING::
18
+
19
+ Since the ``__doc__`` attribute is never inherited, the decorator
20
+ ``@instancedoc`` must be added to all subclasses of the class
21
+ defining ``_instancedoc_``. Doing it on the base class is not
22
+ sufficient.
23
+
24
+ EXAMPLES::
25
+
26
+ sage: from sage.misc.instancedoc import instancedoc
27
+ sage: @instancedoc
28
+ ....: class X():
29
+ ....: "Class docstring"
30
+ ....: def _instancedoc_(self):
31
+ ....: return "Instance docstring"
32
+ sage: X.__doc__
33
+ 'Class docstring'
34
+ sage: X().__doc__
35
+ 'Instance docstring'
36
+
37
+ For a Cython ``cdef class``, a decorator cannot be used. Instead, call
38
+ :func:`instancedoc` as a function after defining the class::
39
+
40
+ sage: cython( # needs sage.misc.cython
41
+ ....: '''
42
+ ....: from sage.misc.instancedoc import instancedoc
43
+ ....: cdef class Y:
44
+ ....: "Class docstring"
45
+ ....: def _instancedoc_(self):
46
+ ....: return "Instance docstring"
47
+ ....: instancedoc(Y)
48
+ ....: ''')
49
+ sage: Y.__doc__ # needs sage.misc.cython
50
+ 'File:...\nClass docstring'
51
+ sage: Y().__doc__ # needs sage.misc.cython
52
+ 'Instance docstring'
53
+
54
+ One can still add a custom ``__doc__`` attribute on a particular
55
+ instance::
56
+
57
+ sage: obj = X()
58
+ sage: obj.__doc__ = "Very special doc"
59
+ sage: print(obj.__doc__)
60
+ Very special doc
61
+
62
+ This normally does not work on extension types::
63
+
64
+ sage: Y().__doc__ = "Very special doc" # needs sage.misc.cython
65
+ Traceback (most recent call last):
66
+ ...
67
+ AttributeError: attribute '__doc__' of 'Y' objects is not writable
68
+
69
+ This is an example involving a metaclass, where the instances are
70
+ classes. In this case, the ``_instancedoc_`` from the metaclass is only
71
+ used if the instance of the metaclass (the class) does not have a
72
+ docstring::
73
+
74
+ sage: @instancedoc
75
+ ....: class Meta(type):
76
+ ....: "Metaclass doc"
77
+ ....: def _instancedoc_(self):
78
+ ....: return "Docstring for {}".format(self)
79
+ sage: class T(metaclass=Meta):
80
+ ....: pass
81
+ sage: print(T.__doc__)
82
+ Docstring for <class '__main__.T'>
83
+ sage: class U(metaclass=Meta):
84
+ ....: "Special doc for U"
85
+ sage: print(U.__doc__)
86
+ Special doc for U
87
+
88
+ TESTS:
89
+
90
+ Check that inheritance works (after passing the subclass to
91
+ :func:`instancedoc`)::
92
+
93
+ sage: @instancedoc
94
+ ....: class A():
95
+ ....: "Class A docstring"
96
+ ....: def _instancedoc_(self):
97
+ ....: return "Instance docstring"
98
+ sage: class B(A):
99
+ ....: "Class B docstring"
100
+ sage: B.__doc__
101
+ 'Class B docstring'
102
+ sage: B().__doc__ # Ideally, this would return the instance docstring
103
+ 'Class B docstring'
104
+ sage: B = instancedoc(B)
105
+ sage: B.__doc__
106
+ 'Class B docstring'
107
+ sage: B().__doc__
108
+ 'Instance docstring'
109
+ """
110
+
111
+ # ****************************************************************************
112
+ # Copyright (C) 2017 Jeroen Demeyer <J.Demeyer@UGent.be>
113
+ #
114
+ # This program is free software: you can redistribute it and/or modify
115
+ # it under the terms of the GNU General Public License as published by
116
+ # the Free Software Foundation, either version 2 of the License, or
117
+ # (at your option) any later version.
118
+ # https://www.gnu.org/licenses/
119
+ # ****************************************************************************
120
+
121
+ from cpython.object cimport PyObject, PyTypeObject
122
+
123
+ cdef extern from *:
124
+ cdef int PyDict_SetItemString(PyObject*, const char*, object) except -1
125
+ cdef void PyType_Modified(PyTypeObject*)
126
+
127
+ cdef inline PyTypeObject* TypeObject(cls) except NULL:
128
+ if not isinstance(cls, type):
129
+ raise TypeError(f"expected type, got {cls!r}")
130
+ return <PyTypeObject*>cls
131
+
132
+
133
+ cdef class InstanceDocDescriptor:
134
+ """
135
+ Descriptor for dynamic documentation, to be installed as the
136
+ ``__doc__`` attribute.
137
+
138
+ INPUT:
139
+
140
+ - ``classdoc`` -- string; class documentation
141
+
142
+ - ``instancedoc`` -- (method) documentation for an instance
143
+
144
+ - ``attr`` -- string (default: ``__doc__``); attribute name to use
145
+ for custom docstring on the instance
146
+
147
+ EXAMPLES::
148
+
149
+ sage: from sage.misc.instancedoc import InstanceDocDescriptor
150
+ sage: def instancedoc(self):
151
+ ....: return "Instance doc"
152
+ sage: docattr = InstanceDocDescriptor("Class doc", instancedoc)
153
+ sage: class Z():
154
+ ....: __doc__ = InstanceDocDescriptor("Class doc", instancedoc)
155
+ sage: Z.__doc__
156
+ 'Class doc'
157
+ sage: Z().__doc__
158
+ 'Instance doc'
159
+
160
+ We can still override the ``__doc__`` attribute of the instance::
161
+
162
+ sage: obj = Z()
163
+ sage: obj.__doc__ = "Custom doc"
164
+ sage: obj.__doc__
165
+ 'Custom doc'
166
+ sage: del obj.__doc__
167
+ sage: obj.__doc__
168
+ 'Instance doc'
169
+ """
170
+ cdef classdoc
171
+ cdef instancedoc
172
+ cdef attr
173
+
174
+ def __init__(self, classdoc, instancedoc, attr='__doc__'):
175
+ """
176
+ TESTS::
177
+
178
+ sage: from sage.misc.instancedoc import InstanceDocDescriptor
179
+ sage: InstanceDocDescriptor(None, None)
180
+ <sage.misc.instancedoc.InstanceDocDescriptor object at ...>
181
+ """
182
+ self.classdoc = classdoc
183
+ self.instancedoc = instancedoc
184
+ self.attr = intern(attr)
185
+
186
+ def __get__(self, obj, typ):
187
+ """
188
+ TESTS::
189
+
190
+ sage: from sage.misc.instancedoc import InstanceDocDescriptor
191
+ sage: def instancedoc(self):
192
+ ....: return "Doc for {!r}".format(self)
193
+ sage: descr = InstanceDocDescriptor("Class doc", instancedoc)
194
+ sage: descr.__get__(None, object)
195
+ 'Class doc'
196
+ sage: descr.__get__(42, type(42))
197
+ 'Doc for 42'
198
+ """
199
+ if obj is None:
200
+ return self.classdoc
201
+
202
+ # First, try the attribute self.attr (typically __doc__)
203
+ # on the instance
204
+ try:
205
+ objdict = obj.__dict__
206
+ except AttributeError:
207
+ pass
208
+ else:
209
+ doc = objdict.get(self.attr)
210
+ if doc is not None:
211
+ return doc
212
+
213
+ return self.instancedoc(obj)
214
+
215
+ def __set__(self, obj, value):
216
+ """
217
+ TESTS::
218
+
219
+ sage: from sage.misc.instancedoc import InstanceDocDescriptor
220
+ sage: def instancedoc(self):
221
+ ....: return "Doc for {!r}".format(self)
222
+ sage: descr = InstanceDocDescriptor("Class doc", instancedoc)
223
+ sage: class X(): pass
224
+ sage: obj = X()
225
+ sage: descr.__set__(obj, "Custom doc")
226
+ sage: obj.__doc__
227
+ 'Custom doc'
228
+
229
+ sage: descr.__set__([], "Custom doc")
230
+ Traceback (most recent call last):
231
+ ...
232
+ AttributeError: attribute '__doc__' of 'list' objects is not writable
233
+ sage: descr.__set__(object, "Custom doc")
234
+ Traceback (most recent call last):
235
+ ...
236
+ AttributeError: attribute '__doc__' of 'type' objects is not writable
237
+ """
238
+ try:
239
+ obj.__dict__[self.attr] = value
240
+ except (AttributeError, TypeError):
241
+ raise AttributeError(f"attribute '{self.attr}' of '{type(obj).__name__}' objects is not writable")
242
+
243
+ def __delete__(self, obj):
244
+ """
245
+ TESTS::
246
+
247
+ sage: from sage.misc.instancedoc import InstanceDocDescriptor
248
+ sage: def instancedoc(self):
249
+ ....: return "Doc for {!r}".format(self)
250
+ sage: descr = InstanceDocDescriptor("Class doc", instancedoc)
251
+ sage: class X(): pass
252
+ sage: obj = X()
253
+ sage: obj.__doc__ = "Custom doc"
254
+ sage: descr.__delete__(obj)
255
+ sage: print(obj.__doc__)
256
+ None
257
+ sage: descr.__delete__(obj)
258
+ Traceback (most recent call last):
259
+ ...
260
+ AttributeError: 'X' object has no attribute '__doc__'...
261
+
262
+ sage: descr.__delete__([])
263
+ Traceback (most recent call last):
264
+ ...
265
+ AttributeError: attribute '__doc__' of 'list' objects is not writable
266
+ sage: descr.__delete__(object)
267
+ Traceback (most recent call last):
268
+ ...
269
+ AttributeError: attribute '__doc__' of 'type' objects is not writable
270
+ """
271
+ try:
272
+ del obj.__dict__[self.attr]
273
+ except (AttributeError, TypeError):
274
+ raise AttributeError(f"attribute '{self.attr}' of '{type(obj).__name__}' objects is not writable")
275
+ except KeyError:
276
+ raise AttributeError(f"'{type(obj).__name__}' object has no attribute '{self.attr}'")
277
+
278
+
279
+ def instancedoc(cls):
280
+ """
281
+ Add support for ``_instancedoc_`` to the class ``cls``.
282
+
283
+ Typically, this will be used as decorator.
284
+
285
+ INPUT:
286
+
287
+ - ``cls`` -- a new-style class
288
+
289
+ OUTPUT: ``cls``
290
+
291
+ .. WARNING::
292
+
293
+ ``instancedoc`` mutates the given class. So you are *not* supposed
294
+ to use it as ``newcls = instancedoc(cls)`` because that would
295
+ mutate ``cls`` (and ``newcls`` would be the same object as ``cls``)
296
+
297
+ TESTS:
298
+
299
+ We get a useful error message if ``_instancedoc_`` is not defined::
300
+
301
+ sage: from sage.misc.instancedoc import instancedoc
302
+ sage: class X(): pass
303
+ sage: instancedoc(X)
304
+ Traceback (most recent call last):
305
+ ...
306
+ TypeError: instancedoc requires <class '__main__.X'> to have an '_instancedoc_' attribute
307
+
308
+ This does not work on old-style classes or things which are not a
309
+ class at all::
310
+
311
+ sage: instancedoc(7)
312
+ Traceback (most recent call last):
313
+ ...
314
+ TypeError: expected type, got 7
315
+
316
+ sage: class OldStyle: pass
317
+ sage: instancedoc(OldStyle)
318
+ Traceback (most recent call last):
319
+ ...
320
+ TypeError: instancedoc requires <class '__main__.OldStyle'> to have an '_instancedoc_' attribute
321
+ """
322
+ cdef PyTypeObject* tp = TypeObject(cls)
323
+ try:
324
+ instdoc = cls._instancedoc_
325
+ except AttributeError:
326
+ raise TypeError(f"instancedoc requires {cls!r} to have an '_instancedoc_' attribute")
327
+ docattr = InstanceDocDescriptor(cls.__doc__, instdoc)
328
+ PyDict_SetItemString(tp.tp_dict, "__doc__", docattr)
329
+ tp.tp_doc = NULL
330
+ PyType_Modified(tp)
331
+ return cls