passagemath-objects 10.8.1a3__cp314-cp314-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 (283) hide show
  1. passagemath_objects/__init__.py +3 -0
  2. passagemath_objects-10.8.1a3.dist-info/DELVEWHEEL +2 -0
  3. passagemath_objects-10.8.1a3.dist-info/METADATA +114 -0
  4. passagemath_objects-10.8.1a3.dist-info/RECORD +283 -0
  5. passagemath_objects-10.8.1a3.dist-info/WHEEL +5 -0
  6. passagemath_objects-10.8.1a3.dist-info/top_level.txt +3 -0
  7. passagemath_objects.libs/libgmp-10-60021eeab4282b29024e43b2b1412b53.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.cp314-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.cp314-win_amd64.pyd +0 -0
  15. sage/arith/power.pxd +31 -0
  16. sage/arith/power.pyx +127 -0
  17. sage/categories/action.cp314-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 +292 -0
  24. sage/categories/category.py +3379 -0
  25. sage/categories/category_cy_helper.cp314-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.cp314-win_amd64.pyd +0 -0
  29. sage/categories/category_singleton.pxd +3 -0
  30. sage/categories/category_singleton.pyx +343 -0
  31. sage/categories/category_types.py +637 -0
  32. sage/categories/category_with_axiom.py +2889 -0
  33. sage/categories/covariant_functorial_construction.py +700 -0
  34. sage/categories/facade_sets.py +228 -0
  35. sage/categories/functor.cp314-win_amd64.pyd +0 -0
  36. sage/categories/functor.pxd +7 -0
  37. sage/categories/functor.pyx +659 -0
  38. sage/categories/homset.py +1289 -0
  39. sage/categories/homsets.py +364 -0
  40. sage/categories/isomorphic_objects.py +73 -0
  41. sage/categories/map.cp314-win_amd64.pyd +0 -0
  42. sage/categories/map.pxd +34 -0
  43. sage/categories/map.pyx +2106 -0
  44. sage/categories/morphism.cp314-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 +1695 -0
  49. sage/categories/pushout.py +4847 -0
  50. sage/categories/quotients.py +64 -0
  51. sage/categories/realizations.py +200 -0
  52. sage/categories/sets_cat.py +3305 -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 +22 -0
  58. sage/cpython/_py2_random.py +619 -0
  59. sage/cpython/all.py +3 -0
  60. sage/cpython/atexit.cp314-win_amd64.pyd +0 -0
  61. sage/cpython/atexit.pyx +269 -0
  62. sage/cpython/builtin_types.cp314-win_amd64.pyd +0 -0
  63. sage/cpython/builtin_types.pyx +7 -0
  64. sage/cpython/cython_metaclass.cp314-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.cp314-win_amd64.pyd +0 -0
  69. sage/cpython/debug.pyx +302 -0
  70. sage/cpython/dict_del_by_value.cp314-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 +80 -0
  74. sage/cpython/getattr.cp314-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.cp314-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.cp314-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.cp314-win_amd64.pyd +0 -0
  98. sage/groups/group.pxd +14 -0
  99. sage/groups/group.pyx +296 -0
  100. sage/groups/old.cp314-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.cp314-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.cp314-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.cp314-win_amd64.pyd +0 -0
  126. sage/misc/cachefunc.pxd +43 -0
  127. sage/misc/cachefunc.pyx +3801 -0
  128. sage/misc/call.py +188 -0
  129. sage/misc/classcall_metaclass.cp314-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.cp314-win_amd64.pyd +0 -0
  133. sage/misc/constant_function.pyx +130 -0
  134. sage/misc/decorators.py +739 -0
  135. sage/misc/fast_methods.cp314-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.cp314-win_amd64.pyd +0 -0
  140. sage/misc/fpickle.pyx +176 -0
  141. sage/misc/function_mangling.cp314-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.cp314-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.cp314-win_amd64.pyd +0 -0
  148. sage/misc/instancedoc.pyx +331 -0
  149. sage/misc/lazy_attribute.cp314-win_amd64.pyd +0 -0
  150. sage/misc/lazy_attribute.pyx +607 -0
  151. sage/misc/lazy_format.py +132 -0
  152. sage/misc/lazy_import.cp314-win_amd64.pyd +0 -0
  153. sage/misc/lazy_import.pxd +13 -0
  154. sage/misc/lazy_import.pyx +1307 -0
  155. sage/misc/lazy_import_cache.py +36 -0
  156. sage/misc/lazy_list.cp314-win_amd64.pyd +0 -0
  157. sage/misc/lazy_list.pxd +19 -0
  158. sage/misc/lazy_list.pyx +1187 -0
  159. sage/misc/lazy_string.cp314-win_amd64.pyd +0 -0
  160. sage/misc/lazy_string.pxd +7 -0
  161. sage/misc/lazy_string.pyx +546 -0
  162. sage/misc/misc.py +980 -0
  163. sage/misc/misc_c.cp314-win_amd64.pyd +0 -0
  164. sage/misc/misc_c.pxd +3 -0
  165. sage/misc/misc_c.pyx +765 -0
  166. sage/misc/namespace_package.py +37 -0
  167. sage/misc/nested_class.cp314-win_amd64.pyd +0 -0
  168. sage/misc/nested_class.pxd +3 -0
  169. sage/misc/nested_class.pyx +394 -0
  170. sage/misc/persist.cp314-win_amd64.pyd +0 -0
  171. sage/misc/persist.pyx +1279 -0
  172. sage/misc/prandom.py +418 -0
  173. sage/misc/randstate.cp314-win_amd64.pyd +0 -0
  174. sage/misc/randstate.pxd +31 -0
  175. sage/misc/randstate.pyx +1096 -0
  176. sage/misc/repr.py +203 -0
  177. sage/misc/reset.cp314-win_amd64.pyd +0 -0
  178. sage/misc/reset.pyx +196 -0
  179. sage/misc/sage_ostools.cp314-win_amd64.pyd +0 -0
  180. sage/misc/sage_ostools.pyx +323 -0
  181. sage/misc/sage_timeit.py +275 -0
  182. sage/misc/sage_timeit_class.cp314-win_amd64.pyd +0 -0
  183. sage/misc/sage_timeit_class.pyx +120 -0
  184. sage/misc/sage_unittest.py +639 -0
  185. sage/misc/sageinspect.py +2792 -0
  186. sage/misc/session.cp314-win_amd64.pyd +0 -0
  187. sage/misc/session.pyx +392 -0
  188. sage/misc/superseded.py +576 -0
  189. sage/misc/test_nested_class.py +228 -0
  190. sage/misc/timing.py +264 -0
  191. sage/misc/unknown.py +222 -0
  192. sage/misc/verbose.py +253 -0
  193. sage/misc/weak_dict.cp314-win_amd64.pyd +0 -0
  194. sage/misc/weak_dict.pxd +15 -0
  195. sage/misc/weak_dict.pyx +1197 -0
  196. sage/modules/all__sagemath_objects.py +1 -0
  197. sage/modules/module.cp314-win_amd64.pyd +0 -0
  198. sage/modules/module.pxd +5 -0
  199. sage/modules/module.pyx +329 -0
  200. sage/rings/all__sagemath_objects.py +3 -0
  201. sage/rings/integer_fake.h +22 -0
  202. sage/rings/integer_fake.pxd +55 -0
  203. sage/rings/integer_fake.pyi +8 -0
  204. sage/sets/all__sagemath_objects.py +3 -0
  205. sage/sets/pythonclass.cp314-win_amd64.pyd +0 -0
  206. sage/sets/pythonclass.pxd +9 -0
  207. sage/sets/pythonclass.pyx +247 -0
  208. sage/structure/__init__.py +13 -0
  209. sage/structure/all.py +30 -0
  210. sage/structure/category_object.cp314-win_amd64.pyd +0 -0
  211. sage/structure/category_object.pxd +28 -0
  212. sage/structure/category_object.pyx +1090 -0
  213. sage/structure/coerce.cp314-win_amd64.pyd +0 -0
  214. sage/structure/coerce.pxd +44 -0
  215. sage/structure/coerce.pyx +2113 -0
  216. sage/structure/coerce_actions.cp314-win_amd64.pyd +0 -0
  217. sage/structure/coerce_actions.pxd +27 -0
  218. sage/structure/coerce_actions.pyx +988 -0
  219. sage/structure/coerce_dict.cp314-win_amd64.pyd +0 -0
  220. sage/structure/coerce_dict.pxd +51 -0
  221. sage/structure/coerce_dict.pyx +1557 -0
  222. sage/structure/coerce_exceptions.py +23 -0
  223. sage/structure/coerce_maps.cp314-win_amd64.pyd +0 -0
  224. sage/structure/coerce_maps.pxd +24 -0
  225. sage/structure/coerce_maps.pyx +656 -0
  226. sage/structure/debug_options.cp314-win_amd64.pyd +0 -0
  227. sage/structure/debug_options.pxd +6 -0
  228. sage/structure/debug_options.pyx +54 -0
  229. sage/structure/dynamic_class.py +541 -0
  230. sage/structure/element.cp314-win_amd64.pyd +0 -0
  231. sage/structure/element.pxd +271 -0
  232. sage/structure/element.pyx +4584 -0
  233. sage/structure/element_wrapper.cp314-win_amd64.pyd +0 -0
  234. sage/structure/element_wrapper.pxd +12 -0
  235. sage/structure/element_wrapper.pyx +582 -0
  236. sage/structure/factorization.py +1457 -0
  237. sage/structure/factorization_integer.py +154 -0
  238. sage/structure/factory.cp314-win_amd64.pyd +0 -0
  239. sage/structure/factory.pyx +863 -0
  240. sage/structure/formal_sum.py +489 -0
  241. sage/structure/gens_py.py +73 -0
  242. sage/structure/global_options.py +1725 -0
  243. sage/structure/indexed_generators.py +863 -0
  244. sage/structure/list_clone.cp314-win_amd64.pyd +0 -0
  245. sage/structure/list_clone.pxd +65 -0
  246. sage/structure/list_clone.pyx +1867 -0
  247. sage/structure/list_clone_demo.cp314-win_amd64.pyd +0 -0
  248. sage/structure/list_clone_demo.pyx +248 -0
  249. sage/structure/list_clone_timings.py +179 -0
  250. sage/structure/list_clone_timings_cy.cp314-win_amd64.pyd +0 -0
  251. sage/structure/list_clone_timings_cy.pyx +86 -0
  252. sage/structure/mutability.cp314-win_amd64.pyd +0 -0
  253. sage/structure/mutability.pxd +21 -0
  254. sage/structure/mutability.pyx +346 -0
  255. sage/structure/nonexact.py +69 -0
  256. sage/structure/parent.cp314-win_amd64.pyd +0 -0
  257. sage/structure/parent.pxd +112 -0
  258. sage/structure/parent.pyx +3087 -0
  259. sage/structure/parent_base.cp314-win_amd64.pyd +0 -0
  260. sage/structure/parent_base.pxd +13 -0
  261. sage/structure/parent_base.pyx +35 -0
  262. sage/structure/parent_gens.cp314-win_amd64.pyd +0 -0
  263. sage/structure/parent_gens.pxd +22 -0
  264. sage/structure/parent_gens.pyx +374 -0
  265. sage/structure/parent_old.cp314-win_amd64.pyd +0 -0
  266. sage/structure/parent_old.pxd +24 -0
  267. sage/structure/parent_old.pyx +278 -0
  268. sage/structure/proof/__init__.py +1 -0
  269. sage/structure/proof/all.py +243 -0
  270. sage/structure/proof/proof.py +300 -0
  271. sage/structure/richcmp.cp314-win_amd64.pyd +0 -0
  272. sage/structure/richcmp.pxd +212 -0
  273. sage/structure/richcmp.pyx +494 -0
  274. sage/structure/sage_object.cp314-win_amd64.pyd +0 -0
  275. sage/structure/sage_object.pxd +3 -0
  276. sage/structure/sage_object.pyx +1088 -0
  277. sage/structure/sage_object_test.py +19 -0
  278. sage/structure/sequence.py +937 -0
  279. sage/structure/set_factories.py +1178 -0
  280. sage/structure/set_factories_example.py +527 -0
  281. sage/structure/support_view.py +164 -0
  282. sage/structure/test_factory.py +56 -0
  283. sage/structure/unique_representation.py +1443 -0
@@ -0,0 +1,439 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Variants of getattr()
4
+ """
5
+
6
+ from cpython.object cimport PyObject, PyTypeObject, Py_TYPE, descrgetfunc
7
+
8
+ from sage.cpython.string cimport bytes_to_str
9
+
10
+ cdef extern from "Python.h":
11
+ r"""
12
+ /* Coded in C because class internals need to be accessed. */
13
+ static PyObject*
14
+ instance_getattr(PyObject* obj, PyObject* name)
15
+ {
16
+ if (PyType_Check(obj)) {
17
+ return _PyType_Lookup((PyTypeObject*)obj, name);
18
+ }
19
+
20
+ PyObject** dptr = _PyObject_GetDictPtr(obj);
21
+ if (dptr == NULL) return NULL;
22
+ PyObject* dict = *dptr;
23
+ if (dict == NULL) return NULL;
24
+ return PyDict_GetItem(dict, name);
25
+ }
26
+ """
27
+
28
+ # Return the attribute "name" from "obj". This only looks up the
29
+ # attribute in the instance "obj" and not in obj.__class__.
30
+ # If "obj" is a class, this searches for the attribute in the base
31
+ # classes.
32
+ #
33
+ # Return a borrowed reference or NULL if the attribute was not found.
34
+ PyObject* instance_getattr(obj, name)
35
+
36
+ int PyDescr_IsData(PyObject*)
37
+
38
+
39
+ cdef class AttributeErrorMessage:
40
+ """
41
+ Try to emulate the standard Python :exc:`AttributeError` message.
42
+
43
+ .. NOTE::
44
+
45
+ The typical fate of an attribute error is being caught. Hence,
46
+ under normal circumstances, nobody will ever see the error
47
+ message. The idea for this class is to provide an object that
48
+ is fast to create and whose string representation is an attribute
49
+ error's message. That string representation is only created if
50
+ someone wants to see it.
51
+
52
+ EXAMPLES::
53
+
54
+ sage: 1.bla #indirect doctest
55
+ Traceback (most recent call last):
56
+ ...
57
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute 'bla'...
58
+ sage: x = polygen(ZZ, 'x')
59
+ sage: QQ[x].gen().bla # needs sage.libs.flint
60
+ Traceback (most recent call last):
61
+ ...
62
+ AttributeError: 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint' object has no attribute 'bla'...
63
+
64
+ ::
65
+
66
+ sage: from sage.cpython.getattr import AttributeErrorMessage
67
+ sage: AttributeErrorMessage(int(1), 'bla')
68
+ 'int' object has no attribute 'bla'
69
+
70
+ TESTS:
71
+
72
+ The error message used for the :exc:`AttributeError` is a unique object
73
+ and is changed inplace. This is for reasons of efficiency.
74
+ Hence, if one really needs the error message as a string, then one should
75
+ make a copy of its string representation before it changes. ::
76
+
77
+ sage: try:
78
+ ....: 1.__bla
79
+ ....: except AttributeError as exc:
80
+ ....: ElementError = exc
81
+ sage: ElementError
82
+ AttributeError('sage.rings.integer.Integer' object has no attribute '__bla'...)
83
+ sage: try:
84
+ ....: x.__bla
85
+ ....: except AttributeError as exc:
86
+ ....: ElementError2 = exc
87
+ sage: ElementError
88
+ AttributeError('sage.rings.polynomial...' object has no attribute '__bla'...)
89
+ sage: ElementError2.args[0] is ElementError.args[0]
90
+ True
91
+ sage: isinstance(ElementError.args[0], sage.cpython.getattr.AttributeErrorMessage)
92
+ True
93
+
94
+ AUTHOR:
95
+
96
+ - Simon King (2011-05-21)
97
+ """
98
+ def __init__(self, obj=None, name=""):
99
+ self.cls = type(obj)
100
+ self.name = name
101
+
102
+ def __repr__(self):
103
+ cls = bytes_to_str((<PyTypeObject*>self.cls).tp_name, 'utf-8',
104
+ 'replace')
105
+ # Go directly through tp_name since __name__ can be overridden--this is
106
+ # almost verbatim how CPython formats this message except we don't cut
107
+ # off the class name after 50 characters, and non-strings are displayed
108
+ # with their repr :)
109
+ return f"'{cls}' object has no attribute {self.name!r}"
110
+
111
+
112
+ cdef AttributeErrorMessage dummy_error_message = AttributeErrorMessage()
113
+
114
+
115
+ cpdef raw_getattr(obj, name):
116
+ """
117
+ Like ``getattr(obj, name)`` but without invoking the binding
118
+ behavior of descriptors under normal attribute access.
119
+ This can be used to easily get unbound methods or other
120
+ descriptors.
121
+
122
+ This ignores ``__getattribute__`` hooks but it does support
123
+ ``__getattr__``.
124
+
125
+ .. NOTE::
126
+
127
+ For Cython classes, ``__getattr__`` is actually implemented as
128
+ ``__getattribute__``, which means that it is not supported by
129
+ ``raw_getattr``.
130
+
131
+ EXAMPLES::
132
+
133
+ sage: class X:
134
+ ....: @property
135
+ ....: def prop(self):
136
+ ....: return 42
137
+ ....: def method(self):
138
+ ....: pass
139
+ ....: def __getattr__(self, name):
140
+ ....: return "magic " + name
141
+ sage: raw_getattr(X, "prop")
142
+ <property object at ...>
143
+ sage: raw_getattr(X, "method")
144
+ <function ...method at ...>
145
+ sage: raw_getattr(X, "attr")
146
+ Traceback (most recent call last):
147
+ ...
148
+ AttributeError: '...' object has no attribute 'attr'...
149
+ sage: x = X()
150
+ sage: raw_getattr(x, "prop")
151
+ <property object at ...>
152
+ sage: raw_getattr(x, "method")
153
+ <function ...method at ...>
154
+ sage: raw_getattr(x, "attr")
155
+ 'magic attr'
156
+ sage: x.__dict__["prop"] = 'no'
157
+ sage: x.__dict__["method"] = 'yes'
158
+ sage: x.__dict__["attr"] = 'ok'
159
+ sage: raw_getattr(x, "prop")
160
+ <property object at ...>
161
+ sage: raw_getattr(x, "method")
162
+ 'yes'
163
+ sage: raw_getattr(x, "attr")
164
+ 'ok'
165
+
166
+ The same tests with an inherited new-style class::
167
+
168
+ sage: class Y(X, object):
169
+ ....: pass
170
+ sage: raw_getattr(Y, "prop")
171
+ <property object at ...>
172
+ sage: raw_getattr(Y, "method")
173
+ <function ...method at ...>
174
+ sage: raw_getattr(Y, "attr")
175
+ Traceback (most recent call last):
176
+ ...
177
+ AttributeError: '...' object has no attribute 'attr'...
178
+ sage: y = Y()
179
+ sage: raw_getattr(y, "prop")
180
+ <property object at ...>
181
+ sage: raw_getattr(y, "method")
182
+ <function ...method at ...>
183
+ sage: raw_getattr(y, "attr")
184
+ 'magic attr'
185
+ sage: y.__dict__["prop"] = 'no'
186
+ sage: y.__dict__["method"] = 'yes'
187
+ sage: y.__dict__["attr"] = 'ok'
188
+ sage: raw_getattr(y, "prop")
189
+ <property object at ...>
190
+ sage: raw_getattr(y, "method")
191
+ 'yes'
192
+ sage: raw_getattr(y, "attr")
193
+ 'ok'
194
+ """
195
+ cdef PyObject* class_attr = NULL
196
+
197
+ try:
198
+ cls = obj.__class__
199
+ except AttributeError:
200
+ # Old-style classes don't have a __class__ (because these do
201
+ # not support metaclasses).
202
+ cls = None
203
+ else:
204
+ class_attr = instance_getattr(cls, name)
205
+
206
+ # We honor the order prescribed by the descriptor protocol:
207
+ # a data descriptor overrides instance attributes. In other
208
+ # cases, the instance attribute takes priority.
209
+ if class_attr is not NULL and PyDescr_IsData(class_attr):
210
+ return <object>class_attr
211
+
212
+ instance_attr = instance_getattr(obj, name)
213
+ if instance_attr is not NULL:
214
+ return <object>instance_attr
215
+ if class_attr is not NULL:
216
+ return <object>class_attr
217
+
218
+ if cls is not None:
219
+ try:
220
+ cls_getattr = cls.__getattr__
221
+ except AttributeError:
222
+ pass
223
+ else:
224
+ return cls_getattr(obj, name)
225
+
226
+ dummy_error_message.cls = type(obj)
227
+ dummy_error_message.name = name
228
+ raise AttributeError(dummy_error_message)
229
+
230
+
231
+ cpdef getattr_from_other_class(self, cls, name):
232
+ """
233
+ Emulate ``getattr(self, name)``, as if ``self`` was an instance of
234
+ ``cls``.
235
+
236
+ INPUT:
237
+
238
+ - ``self`` -- some object
239
+
240
+ - ``cls`` -- a new-style class
241
+
242
+ - ``name`` -- string
243
+
244
+ If ``self`` is an instance of cls, raises an :exc:`AttributeError`, to
245
+ avoid a double lookup. This function is intended to be called from
246
+ __getattr__, and so should not be called if name is an attribute
247
+ of ``self``.
248
+
249
+ EXAMPLES::
250
+
251
+ sage: from sage.cpython.getattr import getattr_from_other_class
252
+ sage: class A():
253
+ ....: def inc(self):
254
+ ....: return self + 1
255
+ ....:
256
+ ....: @staticmethod
257
+ ....: def greeting():
258
+ ....: print("Hello World!")
259
+ ....:
260
+ ....: @lazy_attribute
261
+ ....: def lazy_attribute(self):
262
+ ....: return repr(self)
263
+ sage: getattr_from_other_class(1, A, "inc")
264
+ <bound method A.inc of 1>
265
+ sage: getattr_from_other_class(1, A, "inc")()
266
+ 2
267
+
268
+ Static methods work::
269
+
270
+ sage: getattr_from_other_class(1, A, "greeting")()
271
+ Hello World!
272
+
273
+ Caveat: lazy attributes work with extension types only
274
+ if they allow attribute assignment or have a public attribute
275
+ ``_cached_methods`` of type ``<dict>``. This condition
276
+ is satisfied, e.g., by any class that is derived from
277
+ :class:`Parent`::
278
+
279
+ sage: getattr_from_other_class(1, A, "lazy_attribute")
280
+ Traceback (most recent call last):
281
+ ...
282
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute 'lazy_attribute'...
283
+
284
+ The integer ring is a parent, so, lazy attributes work::
285
+
286
+ sage: getattr_from_other_class(ZZ, A, "lazy_attribute")
287
+ 'Integer Ring'
288
+ sage: getattr_from_other_class(PolynomialRing(QQ, name='x', sparse=True).one(), A, "lazy_attribute")
289
+ '1'
290
+ sage: getattr_from_other_class(17, A, "lazy_attribute")
291
+ Traceback (most recent call last):
292
+ ...
293
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute 'lazy_attribute'...
294
+
295
+ In general, descriptors are not yet well supported, because they
296
+ often do not accept to be cheated with the type of their instance::
297
+
298
+ sage: A.__weakref__.__get__(1)
299
+ Traceback (most recent call last):
300
+ ...
301
+ TypeError: descriptor '__weakref__' for 'A' objects doesn't apply
302
+ to ...'sage.rings.integer.Integer' object
303
+
304
+ When this occurs, an :exc:`AttributeError` is raised::
305
+
306
+ sage: getattr_from_other_class(1, A, "__weakref__")
307
+ Traceback (most recent call last):
308
+ ...
309
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute '__weakref__'...
310
+
311
+ This was caught by :issue:`8296` for which we do a couple more tests::
312
+
313
+ sage: "__weakref__" in dir(A)
314
+ True
315
+ sage: 1.__weakref__
316
+ Traceback (most recent call last):
317
+ ...
318
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute '__weakref__'...
319
+
320
+ sage: n = 1
321
+ sage: ip = get_ipython() # not tested: only works in interactive shell
322
+ sage: ip.magic_psearch('n.N') # not tested: only works in interactive shell
323
+ n.N
324
+ sage: ip.magic_psearch('n.__weakref__') # not tested: only works in interactive shell
325
+
326
+ Caveat: When __call__ is not defined for instances, using
327
+ ``A.__call__`` yields the method ``__call__`` of the class. We use
328
+ a workaround but there is no guarantee for robustness.
329
+
330
+ sage: getattr_from_other_class(1, A, "__call__")
331
+ Traceback (most recent call last):
332
+ ...
333
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute '__call__'...
334
+
335
+ TESTS:
336
+
337
+ Check that we do not pick up special attributes from the ``type``
338
+ class, see :issue:`20686`::
339
+
340
+ sage: getattr_from_other_class(1, type, "__name__")
341
+ Traceback (most recent call last):
342
+ ...
343
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute '__name__'...
344
+
345
+ Non-strings as "name" are handled gracefully::
346
+
347
+ sage: getattr_from_other_class(1, type, None)
348
+ Traceback (most recent call last):
349
+ ...
350
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute None...
351
+ """
352
+ if not isinstance(cls, type):
353
+ raise TypeError(f"{cls!r} is not a type")
354
+
355
+ if isinstance(self, cls):
356
+ dummy_error_message.cls = type(self)
357
+ dummy_error_message.name = name
358
+ raise AttributeError(dummy_error_message)
359
+ cdef PyObject* attr = instance_getattr(cls, name)
360
+ if attr is NULL:
361
+ dummy_error_message.cls = type(self)
362
+ dummy_error_message.name = name
363
+ raise AttributeError(dummy_error_message)
364
+ attribute = <object>attr
365
+ # Check for a descriptor (__get__ in Python)
366
+ cdef descrgetfunc getter = Py_TYPE(attribute).tp_descr_get
367
+ if getter is NULL:
368
+ # Not a descriptor
369
+ return attribute
370
+ # Conditionally defined lazy_attributes don't work well with fake subclasses
371
+ # (a :exc:`TypeError` is raised if the lazy attribute is not defined).
372
+ # For the moment, we ignore that when this occurs.
373
+ # Other descriptors (including __weakref__) also break.
374
+ try:
375
+ return getter(attribute, self, cls)
376
+ except TypeError:
377
+ pass
378
+ dummy_error_message.cls = type(self)
379
+ dummy_error_message.name = name
380
+ raise AttributeError(dummy_error_message)
381
+
382
+
383
+ def dir_with_other_class(self, *cls):
384
+ r"""
385
+ Emulates ``dir(self)``, as if ``self`` was also an instance ``cls``,
386
+ right after ``caller_class`` in the method resolution order
387
+ (``self.__class__.mro()``)
388
+
389
+ EXAMPLES::
390
+
391
+ sage: class A():
392
+ ....: a = 1
393
+ ....: b = 2
394
+ ....: c = 3
395
+ sage: class B():
396
+ ....: b = 2
397
+ ....: c = 3
398
+ ....: d = 4
399
+ sage: x = A()
400
+ sage: x.c = 1; x.e = 1
401
+ sage: from sage.cpython.getattr import dir_with_other_class
402
+ sage: dir_with_other_class(x, B)
403
+ [..., 'a', 'b', 'c', 'd', 'e']
404
+ sage: class C():
405
+ ....: f = 6
406
+ sage: dir_with_other_class(x, B, C)
407
+ [..., 'a', 'b', 'c', 'd', 'e', 'f']
408
+
409
+ Check that objects without dicts are well handled::
410
+
411
+ sage: # needs sage.misc.cython
412
+ sage: cython("cdef class A:\n cdef public int a")
413
+ sage: cython("cdef class B:\n cdef public int b")
414
+ sage: x = A()
415
+ sage: x.a = 1
416
+ sage: hasattr(x,'__dict__')
417
+ False
418
+ sage: dir_with_other_class(x, B)
419
+ [..., 'a', 'b']
420
+
421
+ TESTS:
422
+
423
+ Check that :issue:`13043` is fixed::
424
+
425
+ sage: len(dir(RIF))==len(set(dir(RIF))) # needs sage.rings.real_interval_field
426
+ True
427
+ """
428
+ ret = set()
429
+ # This tries to emulate the standard dir function
430
+ # Is there a better way to call dir on self, while ignoring this
431
+ # __dir__? Using dir(super(A, self)) does not work since the
432
+ # attributes coming from subclasses of A will be ignored
433
+ ret.update(dir(self.__class__))
434
+ if hasattr(self, "__dict__"):
435
+ ret.update(list(self.__dict__))
436
+ for c in cls:
437
+ if not isinstance(self, c):
438
+ ret.update(dir(c))
439
+ return sorted(ret)
@@ -0,0 +1,97 @@
1
+ /* sage_setup: distribution = sagemath-objects
2
+ */
3
+ #include "Python.h"
4
+ #include <stdbool.h>
5
+
6
+ #if PY_VERSION_HEX >= 0x030C00A5
7
+ // For Python 3.12 compatibility
8
+ #define ob_digit(o) (((PyLongObject*)o)->long_value.ob_digit)
9
+ #else
10
+ #define ob_digit(o) (((PyLongObject*)o)->ob_digit)
11
+ #endif
12
+
13
+ #if PY_VERSION_HEX >= 0x030C00A7
14
+ // For Python 3.12 compatibility
15
+ // taken from cpython:Include/internal/pycore_long.h @ 3.12
16
+
17
+ /* Long value tag bits:
18
+ * 0-1: Sign bits value = (1-sign), ie. negative=2, positive=0, zero=1.
19
+ * 2: Reserved for immortality bit
20
+ * 3+ Unsigned digit count
21
+ */
22
+ #define SIGN_MASK 3
23
+ #define SIGN_ZERO 1
24
+ #define SIGN_NEGATIVE 2
25
+ #define NON_SIZE_BITS 3
26
+
27
+ static inline bool
28
+ _PyLong_IsZero(const PyLongObject *op)
29
+ {
30
+ return (op->long_value.lv_tag & SIGN_MASK) == SIGN_ZERO;
31
+ }
32
+
33
+ static inline bool
34
+ _PyLong_IsNegative(const PyLongObject *op)
35
+ {
36
+ return (op->long_value.lv_tag & SIGN_MASK) == SIGN_NEGATIVE;
37
+ }
38
+
39
+ static inline bool
40
+ _PyLong_IsPositive(const PyLongObject *op)
41
+ {
42
+ return (op->long_value.lv_tag & SIGN_MASK) == 0;
43
+ }
44
+
45
+ static inline Py_ssize_t
46
+ _PyLong_DigitCount(const PyLongObject *op)
47
+ {
48
+ assert(PyLong_Check(op));
49
+ return op->long_value.lv_tag >> NON_SIZE_BITS;
50
+ }
51
+
52
+ #define TAG_FROM_SIGN_AND_SIZE(sign, size) ((1 - (sign)) | ((size) << NON_SIZE_BITS))
53
+
54
+ static inline void
55
+ _PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size)
56
+ {
57
+ assert(size >= 0);
58
+ assert(-1 <= sign && sign <= 1);
59
+ assert(sign != 0 || size == 0);
60
+ op->long_value.lv_tag = TAG_FROM_SIGN_AND_SIZE(sign, (size_t)size);
61
+ }
62
+
63
+ #else
64
+ // fallback for < 3.12
65
+
66
+ static inline bool
67
+ _PyLong_IsZero(const PyLongObject *op)
68
+ {
69
+ return Py_SIZE(op) == 0;
70
+ }
71
+
72
+ static inline bool
73
+ _PyLong_IsNegative(const PyLongObject *op)
74
+ {
75
+ return Py_SIZE(op) < 0;
76
+ }
77
+
78
+ static inline bool
79
+ _PyLong_IsPositive(const PyLongObject *op)
80
+ {
81
+ return Py_SIZE(op) > 0;
82
+ }
83
+
84
+ static inline Py_ssize_t
85
+ _PyLong_DigitCount(const PyLongObject *op)
86
+ {
87
+ Py_ssize_t size = Py_SIZE(op);
88
+ return size < 0 ? -size : size;
89
+ }
90
+
91
+ static inline void
92
+ _PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size)
93
+ {
94
+ Py_SET_SIZE(op, sign < 0 ? -size : size);
95
+ }
96
+
97
+ #endif
@@ -0,0 +1,10 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ from cpython.longintrepr cimport py_long, digit
3
+
4
+ cdef extern from "pycore_long.h":
5
+ digit* ob_digit(py_long o)
6
+ bint _PyLong_IsZero(py_long o)
7
+ bint _PyLong_IsNegative(py_long o)
8
+ bint _PyLong_IsPositive(py_long o)
9
+ Py_ssize_t _PyLong_DigitCount(py_long o)
10
+ void _PyLong_SetSignAndDigitCount(py_long o, int sign, Py_ssize_t size)
@@ -0,0 +1,44 @@
1
+ /* sage_setup: distribution = sagemath-objects
2
+ */
3
+ /*
4
+ * Workaround to handle Python preprocessor macros: Translate defined /
5
+ * undefined into true / false
6
+ */
7
+
8
+
9
+ #include <Python.h>
10
+
11
+ #ifdef Py_DEBUG
12
+ #define SAGE_Py_DEBUG Py_DEBUG
13
+ #else
14
+ #define SAGE_Py_DEBUG 0
15
+ #endif
16
+
17
+ #ifdef Py_REF_DEBUG
18
+ #define SAGE_Py_REF_DEBUG Py_REF_DEBUG
19
+ #else
20
+ #define SAGE_Py_REF_DEBUG 0
21
+ #endif
22
+
23
+ #ifdef Py_TRACE_REFS
24
+ #define SAGE_Py_TRACE_REFS Py_TRACE_REFS
25
+ #define if_Py_TRACE_REFS_then_PyObject_INIT(obj, type) PyObject_INIT(obj, type)
26
+ #else
27
+ #define SAGE_Py_TRACE_REFS 0
28
+ #define if_Py_TRACE_REFS_then_PyObject_INIT(obj, type)
29
+ #endif
30
+
31
+ #ifdef PYMALLOC_DEBUG
32
+ #define SAGE_PYMALLOC_DEBUG PYMALLOC_DEBUG
33
+ #else
34
+ #define SAGE_PYMALLOC_DEBUG 0
35
+ #endif
36
+
37
+ #ifdef WITH_PYMALLOC
38
+ #define SAGE_WITH_PYMALLOC PYMALLOC_DEBUG
39
+ #else
40
+ #define SAGE_WITH_PYMALLOC 0
41
+ #endif
42
+
43
+
44
+
@@ -0,0 +1,47 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ # Python can be built with extensive debugging support. This file lets
3
+ # Sage know about which debugging options are enabled.
4
+ #
5
+ # To enable debugging, build Sage with the SAGE_DEBUG environment
6
+ # variable set to "yes":
7
+ #
8
+ # [user@localhost:~/sage-x.y.z] export SAGE_DEBUG=yes && make
9
+
10
+
11
+ from cpython.ref cimport PyObject, PyTypeObject
12
+
13
+ cdef extern from "python_debug.h":
14
+
15
+ # This is what is generally meant by "a debug build" of Python.
16
+ # Implies Py_REF_DEBUG, Py_TRACE_REFS, and PYMALLOC_DEBUG (if
17
+ # WITH_PYMALLOC is enabled). In addition, C assert()s are enabled.
18
+ cdef bint Py_DEBUG "SAGE_Py_DEBUG"
19
+
20
+ # Turn on aggregate reference counting. This arranges that extern
21
+ # _Py_RefTotal hold a count of all references, the sum of
22
+ # ob_refcnt across all objects. Also checks after every decref to
23
+ # verify that the refcount hasn't gone negative, and causes an
24
+ # immediate fatal error if it has.
25
+ cdef bint Py_REF_DEBUG "SAGE_Py_REF_DEBUG"
26
+
27
+ # Heavy reference debugging. Every PyObject grows two more
28
+ # pointers, to maintain a doubly-linked list of all live
29
+ # heap-allocated objects. Implies Py_REF_DEBUG.
30
+ cdef bint Py_TRACE_REFS "SAGE_Py_TRACE_REFS"
31
+
32
+ # Conditionally call PyObject_INIT() if Py_TRACE_REFS is
33
+ # enabled. This is necessary to initialize the aforementioned
34
+ # double-linked list.
35
+ void if_Py_TRACE_REFS_then_PyObject_INIT(PyObject *, PyTypeObject *)
36
+
37
+ # When this is enabled, calls to the PyObject_ memory routines are
38
+ # handled by Python's own small-object allocator, while calls to
39
+ # the PyMem_ memory routines are directed to the system malloc/
40
+ # realloc/free.
41
+ cdef bint WITH_PYMALLOC "SAGE_WITH_PYMALLOC"
42
+
43
+ # If this is also defined in addition to WITH_PYMALLOC, calls to
44
+ # both PyObject_ and PyMem_ memory routines are directed to a
45
+ # special debugging mode of Python's small-object
46
+ # allocator. Requires WITH_PYMALLOC.
47
+ cdef bint PYMALLOC_DEBUG "SAGE_PYMALLOC_DEBUG"
@@ -0,0 +1,13 @@
1
+ /* sage_setup: distribution = sagemath-objects
2
+ */
3
+ /* 3-argument version of Py_VISIT, easier to use from Cython */
4
+
5
+ #define Py_VISIT3(op, visit, arg) \
6
+ do { \
7
+ if (op) { \
8
+ int vret = visit((PyObject *)(op), arg); \
9
+ if (vret) \
10
+ return vret; \
11
+ } \
12
+ } while (0)
13
+
Binary file