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.
- passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.44.dist-info/METADATA +115 -0
- passagemath_objects-10.6.44.dist-info/RECORD +280 -0
- passagemath_objects-10.6.44.dist-info/WHEEL +6 -0
- passagemath_objects-10.6.44.dist-info/top_level.txt +3 -0
- sage/all__sagemath_objects.py +37 -0
- sage/arith/all__sagemath_objects.py +5 -0
- sage/arith/long.pxd +411 -0
- sage/arith/numerical_approx.cpython-314t-darwin.so +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cpython-314t-darwin.so +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cpython-314t-darwin.so +0 -0
- sage/categories/action.pxd +29 -0
- sage/categories/action.pyx +641 -0
- sage/categories/algebra_functor.py +745 -0
- sage/categories/all__sagemath_objects.py +33 -0
- sage/categories/basic.py +62 -0
- sage/categories/cartesian_product.py +295 -0
- sage/categories/category.py +3401 -0
- sage/categories/category_cy_helper.cpython-314t-darwin.so +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cpython-314t-darwin.so +0 -0
- sage/categories/category_singleton.pxd +3 -0
- sage/categories/category_singleton.pyx +342 -0
- sage/categories/category_types.py +637 -0
- sage/categories/category_with_axiom.py +2876 -0
- sage/categories/covariant_functorial_construction.py +703 -0
- sage/categories/facade_sets.py +228 -0
- sage/categories/functor.cpython-314t-darwin.so +0 -0
- sage/categories/functor.pxd +7 -0
- sage/categories/functor.pyx +691 -0
- sage/categories/homset.py +1338 -0
- sage/categories/homsets.py +364 -0
- sage/categories/isomorphic_objects.py +73 -0
- sage/categories/map.cpython-314t-darwin.so +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2106 -0
- sage/categories/morphism.cpython-314t-darwin.so +0 -0
- sage/categories/morphism.pxd +14 -0
- sage/categories/morphism.pyx +895 -0
- sage/categories/objects.py +167 -0
- sage/categories/primer.py +1696 -0
- sage/categories/pushout.py +4834 -0
- sage/categories/quotients.py +64 -0
- sage/categories/realizations.py +200 -0
- sage/categories/sets_cat.py +3290 -0
- sage/categories/sets_with_partial_maps.py +52 -0
- sage/categories/subobjects.py +64 -0
- sage/categories/subquotients.py +21 -0
- sage/categories/with_realizations.py +311 -0
- sage/cpython/__init__.py +19 -0
- sage/cpython/_py2_random.py +619 -0
- sage/cpython/all.py +3 -0
- sage/cpython/atexit.cpython-314t-darwin.so +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cpython-314t-darwin.so +0 -0
- sage/cpython/cython_metaclass.h +117 -0
- sage/cpython/cython_metaclass.pxd +3 -0
- sage/cpython/cython_metaclass.pyx +130 -0
- sage/cpython/debug.cpython-314t-darwin.so +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cpython-314t-darwin.so +0 -0
- sage/cpython/dict_del_by_value.pxd +9 -0
- sage/cpython/dict_del_by_value.pyx +191 -0
- sage/cpython/dict_internal.h +245 -0
- sage/cpython/getattr.cpython-314t-darwin.so +0 -0
- sage/cpython/getattr.pxd +9 -0
- sage/cpython/getattr.pyx +439 -0
- sage/cpython/pycore_long.h +97 -0
- sage/cpython/pycore_long.pxd +10 -0
- sage/cpython/python_debug.h +44 -0
- sage/cpython/python_debug.pxd +47 -0
- sage/cpython/pyx_visit.h +13 -0
- sage/cpython/string.cpython-314t-darwin.so +0 -0
- sage/cpython/string.pxd +76 -0
- sage/cpython/string.pyx +34 -0
- sage/cpython/string_impl.h +60 -0
- sage/cpython/type.cpython-314t-darwin.so +0 -0
- sage/cpython/type.pxd +2 -0
- sage/cpython/type.pyx +40 -0
- sage/cpython/wrapperdescr.pxd +67 -0
- sage/ext/all__sagemath_objects.py +3 -0
- sage/ext/ccobject.h +64 -0
- sage/ext/cplusplus.pxd +17 -0
- sage/ext/mod_int.h +30 -0
- sage/ext/mod_int.pxd +24 -0
- sage/ext/stdsage.pxd +39 -0
- sage/groups/all__sagemath_objects.py +1 -0
- sage/groups/group.cpython-314t-darwin.so +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cpython-314t-darwin.so +0 -0
- sage/groups/old.pxd +14 -0
- sage/groups/old.pyx +219 -0
- sage/libs/all__sagemath_objects.py +3 -0
- sage/libs/gmp/__init__.py +1 -0
- sage/libs/gmp/all.pxd +6 -0
- sage/libs/gmp/binop.pxd +23 -0
- sage/libs/gmp/misc.pxd +8 -0
- sage/libs/gmp/mpf.pxd +88 -0
- sage/libs/gmp/mpn.pxd +57 -0
- sage/libs/gmp/mpq.pxd +57 -0
- sage/libs/gmp/mpz.pxd +202 -0
- sage/libs/gmp/pylong.cpython-314t-darwin.so +0 -0
- sage/libs/gmp/pylong.pxd +12 -0
- sage/libs/gmp/pylong.pyx +150 -0
- sage/libs/gmp/random.pxd +25 -0
- sage/libs/gmp/randomize.pxd +59 -0
- sage/libs/gmp/types.pxd +53 -0
- sage/libs/gmpxx.pxd +19 -0
- sage/misc/abstract_method.py +276 -0
- sage/misc/all__sagemath_objects.py +43 -0
- sage/misc/bindable_class.py +253 -0
- sage/misc/c3_controlled.cpython-314t-darwin.so +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cpython-314t-darwin.so +0 -0
- sage/misc/cachefunc.pxd +43 -0
- sage/misc/cachefunc.pyx +3781 -0
- sage/misc/call.py +188 -0
- sage/misc/classcall_metaclass.cpython-314t-darwin.so +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cpython-314t-darwin.so +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cpython-314t-darwin.so +0 -0
- sage/misc/fast_methods.pxd +20 -0
- sage/misc/fast_methods.pyx +351 -0
- sage/misc/flatten.py +90 -0
- sage/misc/fpickle.cpython-314t-darwin.so +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cpython-314t-darwin.so +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cpython-314t-darwin.so +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_string.pxd +7 -0
- sage/misc/lazy_string.pyx +546 -0
- sage/misc/misc.py +1066 -0
- sage/misc/misc_c.cpython-314t-darwin.so +0 -0
- sage/misc/misc_c.pxd +3 -0
- sage/misc/misc_c.pyx +766 -0
- sage/misc/namespace_package.py +37 -0
- sage/misc/nested_class.cpython-314t-darwin.so +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cpython-314t-darwin.so +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cpython-314t-darwin.so +0 -0
- sage/misc/randstate.pxd +30 -0
- sage/misc/randstate.pyx +1059 -0
- sage/misc/repr.py +203 -0
- sage/misc/reset.cpython-314t-darwin.so +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +275 -0
- sage/misc/sage_timeit_class.cpython-314t-darwin.so +0 -0
- sage/misc/sage_timeit_class.pyx +120 -0
- sage/misc/sage_unittest.py +637 -0
- sage/misc/sageinspect.py +2768 -0
- sage/misc/session.cpython-314t-darwin.so +0 -0
- sage/misc/session.pyx +392 -0
- sage/misc/superseded.py +557 -0
- sage/misc/test_nested_class.py +228 -0
- sage/misc/timing.py +264 -0
- sage/misc/unknown.py +222 -0
- sage/misc/verbose.py +253 -0
- sage/misc/weak_dict.cpython-314t-darwin.so +0 -0
- sage/misc/weak_dict.pxd +15 -0
- sage/misc/weak_dict.pyx +1231 -0
- sage/modules/all__sagemath_objects.py +1 -0
- sage/modules/module.cpython-314t-darwin.so +0 -0
- sage/modules/module.pxd +5 -0
- sage/modules/module.pyx +329 -0
- sage/rings/all__sagemath_objects.py +3 -0
- sage/rings/integer_fake.h +22 -0
- sage/rings/integer_fake.pxd +55 -0
- sage/sets/all__sagemath_objects.py +3 -0
- sage/sets/pythonclass.cpython-314t-darwin.so +0 -0
- sage/sets/pythonclass.pxd +9 -0
- sage/sets/pythonclass.pyx +247 -0
- sage/structure/__init__.py +4 -0
- sage/structure/all.py +30 -0
- sage/structure/category_object.cpython-314t-darwin.so +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cpython-314t-darwin.so +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_dict.pxd +51 -0
- sage/structure/coerce_dict.pyx +1557 -0
- sage/structure/coerce_exceptions.py +23 -0
- sage/structure/coerce_maps.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cpython-314t-darwin.so +0 -0
- sage/structure/debug_options.pxd +6 -0
- sage/structure/debug_options.pyx +54 -0
- sage/structure/dynamic_class.py +541 -0
- sage/structure/element.cpython-314t-darwin.so +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cpython-314t-darwin.so +0 -0
- sage/structure/element_wrapper.pxd +12 -0
- sage/structure/element_wrapper.pyx +582 -0
- sage/structure/factorization.py +1422 -0
- sage/structure/factorization_integer.py +105 -0
- sage/structure/factory.cpython-314t-darwin.so +0 -0
- sage/structure/factory.pyx +786 -0
- sage/structure/formal_sum.py +489 -0
- sage/structure/gens_py.py +73 -0
- sage/structure/global_options.py +1743 -0
- sage/structure/indexed_generators.py +863 -0
- sage/structure/list_clone.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_demo.pyx +248 -0
- sage/structure/list_clone_timings.py +179 -0
- sage/structure/list_clone_timings_cy.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cpython-314t-darwin.so +0 -0
- sage/structure/mutability.pxd +21 -0
- sage/structure/mutability.pyx +348 -0
- sage/structure/nonexact.py +69 -0
- sage/structure/parent.cpython-314t-darwin.so +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cpython-314t-darwin.so +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cpython-314t-darwin.so +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cpython-314t-darwin.so +0 -0
- sage/structure/parent_old.pxd +25 -0
- sage/structure/parent_old.pyx +294 -0
- sage/structure/proof/__init__.py +1 -0
- sage/structure/proof/all.py +243 -0
- sage/structure/proof/proof.py +300 -0
- sage/structure/richcmp.cpython-314t-darwin.so +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cpython-314t-darwin.so +0 -0
- sage/structure/sage_object.pxd +3 -0
- sage/structure/sage_object.pyx +988 -0
- sage/structure/sage_object_test.py +19 -0
- sage/structure/sequence.py +937 -0
- sage/structure/set_factories.py +1178 -0
- sage/structure/set_factories_example.py +527 -0
- sage/structure/support_view.py +179 -0
- sage/structure/test_factory.py +56 -0
- sage/structure/unique_representation.py +1359 -0
sage/cpython/debug.pyx
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
"""
|
|
3
|
+
Various functions to debug Python internals
|
|
4
|
+
"""
|
|
5
|
+
# ****************************************************************************
|
|
6
|
+
# Copyright (C) 2017 Jeroen Demeyer <jdemeyer@cage.ugent.be>
|
|
7
|
+
#
|
|
8
|
+
# This program is free software: you can redistribute it and/or modify
|
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
|
10
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
11
|
+
# (at your option) any later version.
|
|
12
|
+
# https://www.gnu.org/licenses/
|
|
13
|
+
# ****************************************************************************
|
|
14
|
+
|
|
15
|
+
from cpython.object cimport (PyObject, PyTypeObject, Py_TYPE,
|
|
16
|
+
descrgetfunc, descrsetfunc)
|
|
17
|
+
|
|
18
|
+
cdef extern from "Python.h":
|
|
19
|
+
# Helper to get a pointer to an object's __dict__ slot, if any
|
|
20
|
+
PyObject** _PyObject_GetDictPtr(obj)
|
|
21
|
+
|
|
22
|
+
from sage.cpython.getattr cimport AttributeErrorMessage
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Determine subtype_traverse, subtype_clear, subtype_dealloc functions
|
|
26
|
+
# for type_debug(). These are the default tp_traverse, tp_clear and
|
|
27
|
+
# tp_dealloc functions for heap types (= Python classes).
|
|
28
|
+
cdef:
|
|
29
|
+
X = type("X", (), {}) # heap type
|
|
30
|
+
void* subtype_traverse "subtype_traverse" = (<PyTypeObject*>X).tp_traverse
|
|
31
|
+
void* subtype_clear "subtype_clear" = (<PyTypeObject*>X).tp_clear
|
|
32
|
+
void* subtype_dealloc "subtype_dealloc" = (<PyTypeObject*>X).tp_dealloc
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def shortrepr(obj, max=50):
|
|
36
|
+
"""
|
|
37
|
+
Return ``repr(obj)`` bounded to ``max`` characters. If the string
|
|
38
|
+
is too long, it is truncated and ``~~~`` is added to the end.
|
|
39
|
+
|
|
40
|
+
EXAMPLES::
|
|
41
|
+
|
|
42
|
+
sage: from sage.cpython.debug import shortrepr
|
|
43
|
+
sage: print(shortrepr("Hello world!"))
|
|
44
|
+
'Hello world!'
|
|
45
|
+
sage: print(shortrepr("Hello world!" * 4))
|
|
46
|
+
'Hello world!Hello world!Hello world!Hello world!'
|
|
47
|
+
sage: print(shortrepr("Hello world!" * 5))
|
|
48
|
+
'Hello world!Hello world!Hello world!Hello worl~~~
|
|
49
|
+
"""
|
|
50
|
+
r = repr(obj)
|
|
51
|
+
if len(r) > max:
|
|
52
|
+
r = r[:max-3] + "~~~"
|
|
53
|
+
return r
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
cdef object _no_default = object() # Unique object
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def getattr_debug(obj, name, default=_no_default):
|
|
60
|
+
r"""
|
|
61
|
+
A re-implementation of ``getattr()`` with lots of debugging info.
|
|
62
|
+
|
|
63
|
+
This will correctly use ``__getattr__`` if needed. On the other
|
|
64
|
+
hand, it assumes a generic (not overridden) implementation of
|
|
65
|
+
``__getattribute__``. Note that Cython implements ``__getattr__``
|
|
66
|
+
for a cdef class using ``__getattribute__``, so this will not
|
|
67
|
+
detect a ``__getattr__`` in that case.
|
|
68
|
+
|
|
69
|
+
INPUT:
|
|
70
|
+
|
|
71
|
+
- ``obj`` -- the object whose attribute is requested
|
|
72
|
+
|
|
73
|
+
- ``name`` -- string; the name of the attribute
|
|
74
|
+
|
|
75
|
+
- ``default`` -- default value to return if attribute was not found
|
|
76
|
+
|
|
77
|
+
EXAMPLES::
|
|
78
|
+
|
|
79
|
+
sage: _ = getattr_debug(list, "reverse") # not tested - broken in python 3.12
|
|
80
|
+
getattr_debug(obj=<class 'list'>, name='reverse'):
|
|
81
|
+
type(obj) = <class 'type'>
|
|
82
|
+
object has __dict__ slot (<class 'dict'>)
|
|
83
|
+
did not find 'reverse' in MRO classes
|
|
84
|
+
found 'reverse' in object __dict__
|
|
85
|
+
returning <method 'reverse' of 'list' objects> (<class 'method_descriptor'>)
|
|
86
|
+
sage: _ = getattr_debug([], "reverse")
|
|
87
|
+
getattr_debug(obj=[], name='reverse'):
|
|
88
|
+
type(obj) = <class 'list'>
|
|
89
|
+
object does not have __dict__ slot
|
|
90
|
+
found 'reverse' in dict of <class 'list'>
|
|
91
|
+
got <method 'reverse' of 'list' objects> (<class 'method_descriptor'>)
|
|
92
|
+
attribute is ordinary descriptor (has __get__)
|
|
93
|
+
calling __get__()
|
|
94
|
+
returning <built-in method reverse of list object at 0x... (<class 'builtin_function_or_method'>)
|
|
95
|
+
sage: _ = getattr_debug([], "__doc__")
|
|
96
|
+
getattr_debug(obj=[], name='__doc__'):
|
|
97
|
+
type(obj) = <class 'list'>
|
|
98
|
+
object does not have __dict__ slot
|
|
99
|
+
found '__doc__' in dict of <class 'list'>
|
|
100
|
+
got ... 'str'>)
|
|
101
|
+
returning ... 'str'>)
|
|
102
|
+
sage: _ = getattr_debug(gp(1), "log") # needs sage.libs.pari
|
|
103
|
+
getattr_debug(obj=1, name='log'):
|
|
104
|
+
type(obj) = <class 'sage.interfaces.gp.GpElement'>
|
|
105
|
+
object has __dict__ slot (<class 'dict'>)
|
|
106
|
+
did not find 'log' in MRO classes
|
|
107
|
+
object __dict__ does not have 'log'
|
|
108
|
+
calling __getattr__()
|
|
109
|
+
returning log (<class 'sage.interfaces.expect.FunctionElement'>)
|
|
110
|
+
sage: from ipywidgets import IntSlider
|
|
111
|
+
sage: _ = getattr_debug(IntSlider(), "value")
|
|
112
|
+
getattr_debug(obj=IntSlider(value=0), name='value'):
|
|
113
|
+
type(obj) = <class 'ipywidgets.widgets.widget_int.IntSlider'>
|
|
114
|
+
object has __dict__ slot (<class 'dict'>)
|
|
115
|
+
found 'value' in dict of <class 'ipywidgets.widgets.widget_int._Int'>
|
|
116
|
+
got <traitlets.traitlets.CInt object at ... (<class 'traitlets.traitlets.CInt'>)
|
|
117
|
+
attribute is data descriptor (has __get__ and __set__)
|
|
118
|
+
ignoring __dict__ because we have a data descriptor
|
|
119
|
+
calling __get__()
|
|
120
|
+
returning 0 (<class 'int'>)
|
|
121
|
+
sage: _ = getattr_debug(1, "foo")
|
|
122
|
+
Traceback (most recent call last):
|
|
123
|
+
...
|
|
124
|
+
AttributeError: 'sage.rings.integer.Integer' object has no attribute 'foo'...
|
|
125
|
+
sage: _ = getattr_debug(1, "foo", "xyz")
|
|
126
|
+
getattr_debug(obj=1, name='foo'):
|
|
127
|
+
type(obj) = <class 'sage.rings.integer.Integer'>
|
|
128
|
+
object does not have __dict__ slot
|
|
129
|
+
did not find 'foo' in MRO classes
|
|
130
|
+
class does not have __getattr__
|
|
131
|
+
attribute not found
|
|
132
|
+
returning default 'xyz'
|
|
133
|
+
"""
|
|
134
|
+
if default is not _no_default:
|
|
135
|
+
try:
|
|
136
|
+
return getattr_debug(obj, name)
|
|
137
|
+
except AttributeError:
|
|
138
|
+
print(f" returning default {shortrepr(default)}")
|
|
139
|
+
return default
|
|
140
|
+
|
|
141
|
+
name = str(name)
|
|
142
|
+
print(f"getattr_debug(obj={shortrepr(obj)}, name={name!r}):")
|
|
143
|
+
print(f" type(obj) = {type(obj)}")
|
|
144
|
+
|
|
145
|
+
cdef object attr = None
|
|
146
|
+
cdef object dct = None
|
|
147
|
+
|
|
148
|
+
cdef PyObject** dictptr = _PyObject_GetDictPtr(obj)
|
|
149
|
+
if dictptr is not NULL:
|
|
150
|
+
if dictptr[0] is not NULL:
|
|
151
|
+
dct = <object>(dictptr[0])
|
|
152
|
+
print(f" object has __dict__ slot ({type(dct)})")
|
|
153
|
+
else:
|
|
154
|
+
print(" object has uninitialized __dict__ slot")
|
|
155
|
+
else:
|
|
156
|
+
print(" object does not have __dict__ slot")
|
|
157
|
+
|
|
158
|
+
cdef descrgetfunc get = NULL
|
|
159
|
+
cdef descrsetfunc set = NULL
|
|
160
|
+
|
|
161
|
+
# Look for name in dicts of types in MRO
|
|
162
|
+
cdef bint attr_in_class = False
|
|
163
|
+
for cls in type(obj).__mro__:
|
|
164
|
+
if name in cls.__dict__:
|
|
165
|
+
attr = cls.__dict__[name]
|
|
166
|
+
print(f" found {name!r} in dict of {cls}")
|
|
167
|
+
print(f" got {shortrepr(attr)} ({type(attr)})")
|
|
168
|
+
|
|
169
|
+
get = Py_TYPE(attr).tp_descr_get
|
|
170
|
+
set = Py_TYPE(attr).tp_descr_set
|
|
171
|
+
if get is not NULL:
|
|
172
|
+
if set is not NULL:
|
|
173
|
+
print(" attribute is data descriptor (has __get__ and __set__)")
|
|
174
|
+
if dct is not None:
|
|
175
|
+
print(" ignoring __dict__ because we have a data descriptor")
|
|
176
|
+
print(" calling __get__()")
|
|
177
|
+
attr = get(attr, obj, type(obj))
|
|
178
|
+
print(f" returning {shortrepr(attr)} ({type(attr)})")
|
|
179
|
+
return attr
|
|
180
|
+
else:
|
|
181
|
+
print(" attribute is ordinary descriptor (has __get__)")
|
|
182
|
+
attr_in_class = True
|
|
183
|
+
break
|
|
184
|
+
|
|
185
|
+
if not attr_in_class:
|
|
186
|
+
print(f" did not find {name!r} in MRO classes")
|
|
187
|
+
|
|
188
|
+
if dct is not None:
|
|
189
|
+
if name in dct:
|
|
190
|
+
attr = dct[name]
|
|
191
|
+
print(f" found {name!r} in object __dict__")
|
|
192
|
+
print(f" returning {shortrepr(attr)} ({type(attr)})")
|
|
193
|
+
return attr
|
|
194
|
+
else:
|
|
195
|
+
print(f" object __dict__ does not have {name!r}")
|
|
196
|
+
|
|
197
|
+
if attr_in_class:
|
|
198
|
+
if get is not NULL:
|
|
199
|
+
print(" calling __get__()")
|
|
200
|
+
attr = get(attr, obj, type(obj))
|
|
201
|
+
print(f" returning {shortrepr(attr)} ({type(attr)})")
|
|
202
|
+
return attr
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
tpgetattr = type(obj).__getattr__
|
|
206
|
+
except AttributeError:
|
|
207
|
+
print(" class does not have __getattr__")
|
|
208
|
+
else:
|
|
209
|
+
print(" calling __getattr__()")
|
|
210
|
+
attr = tpgetattr(obj, name)
|
|
211
|
+
print(f" returning {shortrepr(attr)} ({type(attr)})")
|
|
212
|
+
return attr
|
|
213
|
+
|
|
214
|
+
print(" attribute not found")
|
|
215
|
+
raise AttributeError(AttributeErrorMessage(obj, name))
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def type_debug(cls):
|
|
219
|
+
"""
|
|
220
|
+
Print all internals of the type ``cls``.
|
|
221
|
+
|
|
222
|
+
EXAMPLES::
|
|
223
|
+
|
|
224
|
+
sage: type_debug(object) # random
|
|
225
|
+
<class 'object'> (0x7fc57da7f040)
|
|
226
|
+
ob_refcnt: 9739
|
|
227
|
+
ob_type: <class 'type'>
|
|
228
|
+
tp_name: object
|
|
229
|
+
tp_basicsize: 16
|
|
230
|
+
tp_itemsize: 0
|
|
231
|
+
tp_dictoffset: 0
|
|
232
|
+
tp_weaklistoffset: 0
|
|
233
|
+
tp_base (__base__): NULL
|
|
234
|
+
tp_bases (__bases__): tuple:
|
|
235
|
+
tp_mro (__mro__): tuple:
|
|
236
|
+
<class 'object'>
|
|
237
|
+
tp_dict (__dict__): dict:
|
|
238
|
+
'__setattr__': <slot wrapper '__setattr__' of 'object' objects>
|
|
239
|
+
'__reduce_ex__': <method '__reduce_ex__' of 'object' objects>
|
|
240
|
+
'__new__': <built-in method __new__ of type object at 0x7fc57da7f040>
|
|
241
|
+
'__reduce__': <method '__reduce__' of 'object' objects>
|
|
242
|
+
'__str__': <slot wrapper '__str__' of 'object' objects>
|
|
243
|
+
'__format__': <method '__format__' of 'object' objects>
|
|
244
|
+
'__getattribute__': <slot wrapper '__getattribute__' of 'object' objects>
|
|
245
|
+
'__class__': <attribute '__class__' of 'object' objects>
|
|
246
|
+
'__delattr__': <slot wrapper '__delattr__' of 'object' objects>
|
|
247
|
+
'__subclasshook__': <method '__subclasshook__' of 'object' objects>
|
|
248
|
+
'__repr__': <slot wrapper '__repr__' of 'object' objects>
|
|
249
|
+
'__hash__': <slot wrapper '__hash__' of 'object' objects>
|
|
250
|
+
'__sizeof__': <method '__sizeof__' of 'object' objects>
|
|
251
|
+
'__doc__': 'The most base type'
|
|
252
|
+
'__init__': <slot wrapper '__init__' of 'object' objects>
|
|
253
|
+
tp_alloc: PyType_GenericAlloc
|
|
254
|
+
tp_new (__new__): 0x7fc57d7594f0
|
|
255
|
+
tp_init (__init__): 0x7fc57d758ee0
|
|
256
|
+
tp_dealloc (__dealloc__): 0x7fc57d757010
|
|
257
|
+
tp_free: PyObject_Del
|
|
258
|
+
tp_repr (__repr__): 0x7fc57d75b990
|
|
259
|
+
tp_print: NULL
|
|
260
|
+
tp_hash (__hash__): _Py_HashPointer
|
|
261
|
+
tp_call (__call__): NULL
|
|
262
|
+
tp_str (__str__): 0x7fc57d757020
|
|
263
|
+
tp_compare (__cmp__): NULL
|
|
264
|
+
tp_richcompare (__richcmp__): NULL
|
|
265
|
+
tp_getattr (__getattribute__): NULL
|
|
266
|
+
tp_setattr (__setattribute__): NULL
|
|
267
|
+
tp_getattro (__getattribute__): PyObject_GenericGetAttr
|
|
268
|
+
tp_setattro (__setattribute__): PyObject_GenericSetAttr
|
|
269
|
+
tp_iter (__iter__): NULL
|
|
270
|
+
tp_iternext (__next__): NULL
|
|
271
|
+
tp_descr_get (__get__): NULL
|
|
272
|
+
tp_descr_set (__set__): NULL
|
|
273
|
+
tp_cache: NULL
|
|
274
|
+
tp_weaklist: NULL
|
|
275
|
+
tp_traverse: NULL
|
|
276
|
+
tp_clear: NULL
|
|
277
|
+
tp_is_gc: NULL
|
|
278
|
+
tp_as_number: NULL
|
|
279
|
+
tp_as_sequence: NULL
|
|
280
|
+
tp_as_mapping: NULL
|
|
281
|
+
tp_as_buffer: NULL
|
|
282
|
+
tp_flags:
|
|
283
|
+
HAVE_GETCHARBUFFER
|
|
284
|
+
HAVE_SEQUENCE_IN
|
|
285
|
+
HAVE_INPLACEOPS
|
|
286
|
+
HAVE_RICHCOMPARE
|
|
287
|
+
HAVE_WEAKREFS
|
|
288
|
+
HAVE_ITER
|
|
289
|
+
HAVE_CLASS
|
|
290
|
+
BASETYPE
|
|
291
|
+
READY
|
|
292
|
+
HAVE_INDEX
|
|
293
|
+
HAVE_VERSION_TAG
|
|
294
|
+
VALID_VERSION_TAG
|
|
295
|
+
tp_version_tag: 2
|
|
296
|
+
sage: type_debug(None)
|
|
297
|
+
Traceback (most recent call last):
|
|
298
|
+
...
|
|
299
|
+
TypeError: None is not a type
|
|
300
|
+
"""
|
|
301
|
+
if not isinstance(cls, type):
|
|
302
|
+
raise TypeError(f"{cls!r} is not a type")
|
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
from cpython.object cimport PyObject
|
|
3
|
+
cdef extern from "Python.h":
|
|
4
|
+
ctypedef struct PyDictObject
|
|
5
|
+
|
|
6
|
+
cdef int del_dictitem_by_exact_value(PyDictObject *mp, PyObject *value, Py_hash_t hash) except -1
|
|
7
|
+
|
|
8
|
+
cdef extern from "Python.h":
|
|
9
|
+
PyObject* PyDict_GetItemWithError(dict op, object key) except? NULL
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
"""
|
|
3
|
+
Delete item from PyDict by exact value and hash
|
|
4
|
+
|
|
5
|
+
Beware that the implementation of the routine here relies on implementation
|
|
6
|
+
details of CPython's dict that go beyond the published API.
|
|
7
|
+
|
|
8
|
+
AUTHORS:
|
|
9
|
+
|
|
10
|
+
- Nils Bruin (2017-05)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# ****************************************************************************
|
|
14
|
+
# Copyright (C) 2017 Nils Bruin <nbruin@sfu.ca>
|
|
15
|
+
#
|
|
16
|
+
# This program is free software: you can redistribute it and/or modify
|
|
17
|
+
# it under the terms of the GNU General Public License as published by
|
|
18
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
19
|
+
# (at your option) any later version.
|
|
20
|
+
# https://www.gnu.org/licenses/
|
|
21
|
+
# ****************************************************************************
|
|
22
|
+
|
|
23
|
+
from cpython.list cimport PyList_New
|
|
24
|
+
|
|
25
|
+
cdef extern from "Python.h":
|
|
26
|
+
ctypedef struct PyDictKeysObject
|
|
27
|
+
|
|
28
|
+
ctypedef struct PyDictObject:
|
|
29
|
+
Py_ssize_t ma_used
|
|
30
|
+
PyDictKeysObject * ma_keys
|
|
31
|
+
PyObject ** ma_values
|
|
32
|
+
|
|
33
|
+
int PyList_SetItem(object list, Py_ssize_t index, PyObject * item) except -1
|
|
34
|
+
|
|
35
|
+
cdef extern from "dict_internal.h":
|
|
36
|
+
Py_ssize_t DK_MASK(PyDictKeysObject *)
|
|
37
|
+
PyDictKeyEntry * DK_ENTRIES(PyDictKeysObject *keys)
|
|
38
|
+
|
|
39
|
+
Py_ssize_t dictkeys_get_index (PyDictKeysObject *keys, Py_ssize_t i)
|
|
40
|
+
void dictkeys_set_index (PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix)
|
|
41
|
+
|
|
42
|
+
Py_ssize_t DKIX_EMPTY, DKIX_DUMMY
|
|
43
|
+
int PERTURB_SHIFT
|
|
44
|
+
|
|
45
|
+
ctypedef struct PyDictKeyEntry:
|
|
46
|
+
Py_hash_t me_hash
|
|
47
|
+
PyObject * me_key
|
|
48
|
+
PyObject * me_value
|
|
49
|
+
|
|
50
|
+
cdef int del_dictitem_by_exact_value(PyDictObject *mp, PyObject *value, Py_hash_t hash) except -1:
|
|
51
|
+
"""
|
|
52
|
+
This is used in callbacks for the weak values of :class:`WeakValueDictionary`.
|
|
53
|
+
|
|
54
|
+
INPUT:
|
|
55
|
+
|
|
56
|
+
- ``PyDictObject *mp`` -- pointer to a dict
|
|
57
|
+
- ``PyObject *value`` -- pointer to a value of the dictionary
|
|
58
|
+
- ``Py_hash_t hash`` -- hash of the key by which the value is stored in the dict
|
|
59
|
+
|
|
60
|
+
The hash bucket determined by the given hash is searched for the item
|
|
61
|
+
containing the given value. If this item cannot be found, the function is
|
|
62
|
+
silently returning. Otherwise, the item is removed from the dict.
|
|
63
|
+
|
|
64
|
+
TESTS:
|
|
65
|
+
|
|
66
|
+
The following is an indirect doctest, as discussed on :issue:`13394`.
|
|
67
|
+
::
|
|
68
|
+
|
|
69
|
+
sage: from sage.misc.weak_dict import WeakValueDictionary
|
|
70
|
+
sage: V = [set(range(n)) for n in range(5)]
|
|
71
|
+
sage: D = WeakValueDictionary(enumerate(V))
|
|
72
|
+
|
|
73
|
+
The line ``V[k] = None`` triggers execution of the callback functions of
|
|
74
|
+
the dict values. However, the actual deletion is postponed till after the
|
|
75
|
+
iteration over the dictionary has finished. Hence, when the callbacks are
|
|
76
|
+
executed, the values which the callback belongs to has already been
|
|
77
|
+
overridden by a new value. Therefore, the callback does not delete the
|
|
78
|
+
item::
|
|
79
|
+
|
|
80
|
+
sage: for k in D: # indirect doctest
|
|
81
|
+
....: V[k] = None
|
|
82
|
+
....: D[k] = ZZ
|
|
83
|
+
sage: len(D)
|
|
84
|
+
5
|
|
85
|
+
sage: D[1]
|
|
86
|
+
Integer Ring
|
|
87
|
+
|
|
88
|
+
TESTS:
|
|
89
|
+
|
|
90
|
+
The following shows that the deletion of deeply nested structures does not
|
|
91
|
+
result in an error, by :issue:`15506`::
|
|
92
|
+
|
|
93
|
+
sage: class A: pass
|
|
94
|
+
sage: a = A(); prev = a
|
|
95
|
+
sage: M = WeakValueDictionary()
|
|
96
|
+
sage: for i in range(10^3+10): newA = A(); M[newA] = prev; prev = newA
|
|
97
|
+
sage: del a
|
|
98
|
+
"""
|
|
99
|
+
keys = mp.ma_keys
|
|
100
|
+
cdef size_t perturb
|
|
101
|
+
cdef size_t mask = DK_MASK(keys)
|
|
102
|
+
cdef PyDictKeyEntry *entries = DK_ENTRIES(keys)
|
|
103
|
+
cdef PyDictKeyEntry *ep
|
|
104
|
+
|
|
105
|
+
if mp.ma_values is not NULL:
|
|
106
|
+
raise TypeError("del_dictitem_by_exact_value cannot be applied to a shared key dict")
|
|
107
|
+
|
|
108
|
+
cdef size_t i = <size_t>hash & mask
|
|
109
|
+
ix = dictkeys_get_index(keys, i)
|
|
110
|
+
|
|
111
|
+
if ix == DKIX_EMPTY:
|
|
112
|
+
# key not found
|
|
113
|
+
return 0
|
|
114
|
+
|
|
115
|
+
ep = &(entries[ix])
|
|
116
|
+
perturb = hash
|
|
117
|
+
while (ep.me_value != value or ep.me_hash != hash):
|
|
118
|
+
perturb = perturb >> PERTURB_SHIFT
|
|
119
|
+
i = mask & (i * 5 + perturb + 1)
|
|
120
|
+
ix = dictkeys_get_index(keys, i)
|
|
121
|
+
if ix == DKIX_EMPTY:
|
|
122
|
+
# key not found
|
|
123
|
+
return 0
|
|
124
|
+
ep = &(entries[ix])
|
|
125
|
+
|
|
126
|
+
T = PyList_New(2)
|
|
127
|
+
PyList_SetItem(T, 0, ep.me_key)
|
|
128
|
+
PyList_SetItem(T, 1, ep.me_value)
|
|
129
|
+
ep.me_key = NULL
|
|
130
|
+
ep.me_value = NULL
|
|
131
|
+
mp.ma_used -= 1
|
|
132
|
+
dictkeys_set_index(keys, i, DKIX_DUMMY)
|
|
133
|
+
# We have transferred the to-be-deleted references to the list T
|
|
134
|
+
# we now delete the list so that the actual decref happens through a
|
|
135
|
+
# deallocation routine that uses the Python Trashcan macros to
|
|
136
|
+
# avoid stack overflow in deleting deep structures.
|
|
137
|
+
del T
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_del_dictitem_by_exact_value(D, value, h):
|
|
141
|
+
"""
|
|
142
|
+
This function helps testing some cdef function used to delete dictionary items.
|
|
143
|
+
|
|
144
|
+
INPUT:
|
|
145
|
+
|
|
146
|
+
- ``D`` -- a Python ``<dict>``
|
|
147
|
+
- ``value`` -- an object that is value ``D``
|
|
148
|
+
- ``h`` -- the hash of the key under which to find ``value`` in ``D``
|
|
149
|
+
|
|
150
|
+
The underlying cdef function deletes an item from ``D`` that is in the
|
|
151
|
+
hash bucket determined by ``h`` and whose value is identic with
|
|
152
|
+
``value``. Of course, this only makes sense if the pairs ``(h, value)``
|
|
153
|
+
corresponding to items in ``D`` are pair-wise distinct.
|
|
154
|
+
|
|
155
|
+
If a matching item cannot be found, the function does nothing and
|
|
156
|
+
silently returns.
|
|
157
|
+
|
|
158
|
+
TESTS:
|
|
159
|
+
|
|
160
|
+
See :issue:`13394` for a discussion.
|
|
161
|
+
::
|
|
162
|
+
|
|
163
|
+
sage: from sage.cpython.dict_del_by_value import test_del_dictitem_by_exact_value
|
|
164
|
+
sage: B=1000
|
|
165
|
+
sage: L=list(range(B))
|
|
166
|
+
sage: D1=dict()
|
|
167
|
+
sage: D2=dict()
|
|
168
|
+
sage: for i in range(100000): # long time
|
|
169
|
+
....: ki=L[floor(random()*B)]
|
|
170
|
+
....: vi=L[floor(random()*B)]
|
|
171
|
+
....: D1[ki]=vi
|
|
172
|
+
....: D2[ki]=vi
|
|
173
|
+
....: ko=L[floor(random()*B)]
|
|
174
|
+
....: if ko in D1:
|
|
175
|
+
....: vo=D1[ko]
|
|
176
|
+
....: del D1[ko]
|
|
177
|
+
....: test_del_dictitem_by_exact_value(D2,vo,hash(ko))
|
|
178
|
+
....: assert D1 == D2
|
|
179
|
+
|
|
180
|
+
No action is taken if the item prescribed by key hash and value does not
|
|
181
|
+
exist in the dictionary::
|
|
182
|
+
|
|
183
|
+
sage: D = {1: ZZ}
|
|
184
|
+
sage: test_del_dictitem_by_exact_value(D, ZZ, 2)
|
|
185
|
+
sage: D
|
|
186
|
+
{1: Integer Ring}
|
|
187
|
+
sage: test_del_dictitem_by_exact_value(D, QQ, 1)
|
|
188
|
+
sage: D
|
|
189
|
+
{1: Integer Ring}
|
|
190
|
+
"""
|
|
191
|
+
del_dictitem_by_exact_value(<PyDictObject *>D, <PyObject *>value, h)
|