passagemath-objects 10.6.41__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.
Potentially problematic release.
This version of passagemath-objects might be problematic. Click here for more details.
- passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.41.dist-info/METADATA +115 -0
- passagemath_objects-10.6.41.dist-info/RECORD +280 -0
- passagemath_objects-10.6.41.dist-info/WHEEL +6 -0
- passagemath_objects-10.6.41.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 +2112 -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 +3228 -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 +276 -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
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
r"""
|
|
3
|
+
Special Methods for Classes
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- Nicolas M. Thiery (2009-2011) implementation of
|
|
8
|
+
``__classcall__``, ``__classget__``, ``__classcontains__``;
|
|
9
|
+
- Florent Hivert (2010-2012): implementation of ``__classcall_private__``,
|
|
10
|
+
documentation, Cythonization and optimization.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# ****************************************************************************
|
|
14
|
+
# Copyright (C) 2009 Nicolas M. Thiery <nthiery at users.sf.net>
|
|
15
|
+
# Copyright (C) 2010-2012 Florent Hivert <Florent.Hivert at lri.fr>
|
|
16
|
+
#
|
|
17
|
+
# This program is free software: you can redistribute it and/or modify
|
|
18
|
+
# it under the terms of the GNU General Public License as published by
|
|
19
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
20
|
+
# (at your option) any later version.
|
|
21
|
+
# https://www.gnu.org/licenses/
|
|
22
|
+
# ****************************************************************************
|
|
23
|
+
|
|
24
|
+
from cpython.object cimport *
|
|
25
|
+
from cpython.type cimport type as pytype
|
|
26
|
+
|
|
27
|
+
__all__ = ['ClasscallMetaclass', 'typecall', 'timeCall']
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
cdef class ClasscallMetaclass(NestedClassMetaclass):
|
|
31
|
+
r"""
|
|
32
|
+
A metaclass providing support for special methods for classes.
|
|
33
|
+
|
|
34
|
+
From the Section :python:`Special method names
|
|
35
|
+
<reference/datamodel.html#special-method-names>` of the Python Reference
|
|
36
|
+
Manual:
|
|
37
|
+
|
|
38
|
+
\`a class ``cls`` can implement certain operations on its instances
|
|
39
|
+
that are invoked by special syntax (such as arithmetic operations or
|
|
40
|
+
subscripting and slicing) by defining methods with special
|
|
41
|
+
names\'.
|
|
42
|
+
|
|
43
|
+
The purpose of this metaclass is to allow for the class ``cls`` to
|
|
44
|
+
implement analogues of those special methods for the operations on the
|
|
45
|
+
class itself.
|
|
46
|
+
|
|
47
|
+
Currently, the following special methods are supported:
|
|
48
|
+
|
|
49
|
+
- ``.__classcall__`` (and ``.__classcall_private__``) for
|
|
50
|
+
customizing ``cls(...)`` (analogue of ``.__call__``).
|
|
51
|
+
|
|
52
|
+
- ``.__classcontains__`` for customizing membership testing
|
|
53
|
+
``x in cls`` (analogue of ``.__contains__``).
|
|
54
|
+
|
|
55
|
+
- ``.__classget__`` for customizing the binding behavior in
|
|
56
|
+
``foo.cls`` (analogue of ``.__get__``).
|
|
57
|
+
|
|
58
|
+
See the documentation of :meth:`__call__` and of :meth:`__get__`
|
|
59
|
+
and :meth:`__contains__` for the description of the respective
|
|
60
|
+
protocols.
|
|
61
|
+
|
|
62
|
+
.. WARNING::
|
|
63
|
+
|
|
64
|
+
For technical reasons, ``__classcall__``,
|
|
65
|
+
``__classcall_private__``, ``__classcontains__``, and
|
|
66
|
+
``__classget__`` must be defined as :func:`staticmethod`'s,
|
|
67
|
+
even though they receive the class itself as their first
|
|
68
|
+
argument.
|
|
69
|
+
|
|
70
|
+
.. WARNING::
|
|
71
|
+
|
|
72
|
+
For efficiency reasons, the resolution for the special methods
|
|
73
|
+
is done once for all, upon creation of the class. Thus, later
|
|
74
|
+
dynamic changes to those methods are ignored. But see also
|
|
75
|
+
:meth:`_set_classcall`.
|
|
76
|
+
|
|
77
|
+
``ClasscallMetaclass`` is an extension of the base :class:`type`.
|
|
78
|
+
|
|
79
|
+
.. TODO:: find a good name for this metaclass.
|
|
80
|
+
|
|
81
|
+
TESTS::
|
|
82
|
+
|
|
83
|
+
sage: PerfectMatchings(2).list() # needs sage.combinat
|
|
84
|
+
[[(1, 2)]]
|
|
85
|
+
|
|
86
|
+
.. NOTE::
|
|
87
|
+
|
|
88
|
+
If a class is put in this metaclass it automatically becomes a
|
|
89
|
+
new-style class::
|
|
90
|
+
|
|
91
|
+
sage: from sage.misc.classcall_metaclass import ClasscallMetaclass
|
|
92
|
+
sage: class Foo(metaclass=ClasscallMetaclass): pass
|
|
93
|
+
sage: x = Foo(); x
|
|
94
|
+
<__main__.Foo object at 0x...>
|
|
95
|
+
sage: issubclass(Foo, object)
|
|
96
|
+
True
|
|
97
|
+
sage: isinstance(Foo, type)
|
|
98
|
+
True
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def __cinit__(self, *args, **opts):
|
|
102
|
+
r"""
|
|
103
|
+
TESTS::
|
|
104
|
+
|
|
105
|
+
sage: from sage.misc.classcall_metaclass import ClasscallMetaclass
|
|
106
|
+
sage: class FOO(metaclass=ClasscallMetaclass): pass
|
|
107
|
+
sage: isinstance(FOO, ClasscallMetaclass) # indirect doctest
|
|
108
|
+
True
|
|
109
|
+
"""
|
|
110
|
+
if '__classcall_private__' in self.__dict__:
|
|
111
|
+
self.classcall = self.__classcall_private__
|
|
112
|
+
elif hasattr(self, "__classcall__"):
|
|
113
|
+
self.classcall = self.__classcall__
|
|
114
|
+
else:
|
|
115
|
+
self.classcall = None
|
|
116
|
+
|
|
117
|
+
self.classcontains = getattr(self, "__classcontains__", None)
|
|
118
|
+
self.classget = getattr(self, "__classget__", None)
|
|
119
|
+
|
|
120
|
+
def _set_classcall(cls, function):
|
|
121
|
+
r"""
|
|
122
|
+
Change dynamically the classcall function for this class.
|
|
123
|
+
|
|
124
|
+
EXAMPLES::
|
|
125
|
+
|
|
126
|
+
sage: from sage.misc.classcall_metaclass import ClasscallMetaclass
|
|
127
|
+
sage: class FOO(metaclass=ClasscallMetaclass): pass
|
|
128
|
+
sage: FOO()
|
|
129
|
+
<__main__.FOO object at ...>
|
|
130
|
+
|
|
131
|
+
For efficiency reason, the resolution of the ``__classcall__``
|
|
132
|
+
method is done once for all, upon creation of the class. Thus,
|
|
133
|
+
later dynamic changes to this method are ignored by FOO::
|
|
134
|
+
|
|
135
|
+
sage: FOO.__classcall__ = ConstantFunction(1)
|
|
136
|
+
sage: FOO()
|
|
137
|
+
<__main__.FOO object at ...>
|
|
138
|
+
|
|
139
|
+
but not by subclasses created later on::
|
|
140
|
+
|
|
141
|
+
sage: class BAR(FOO): pass
|
|
142
|
+
sage: BAR()
|
|
143
|
+
1
|
|
144
|
+
|
|
145
|
+
To update the ``classcall`` special function for FOO, one
|
|
146
|
+
should use this setter::
|
|
147
|
+
|
|
148
|
+
sage: FOO._set_classcall(ConstantFunction(2))
|
|
149
|
+
sage: FOO()
|
|
150
|
+
2
|
|
151
|
+
|
|
152
|
+
Note that it has no influence on subclasses::
|
|
153
|
+
|
|
154
|
+
sage: class BAR(FOO): pass
|
|
155
|
+
sage: BAR()
|
|
156
|
+
1
|
|
157
|
+
"""
|
|
158
|
+
cls.classcall = function
|
|
159
|
+
|
|
160
|
+
def __call__(cls, *args, **kwds):
|
|
161
|
+
r"""
|
|
162
|
+
This method implements ``cls(<some arguments>)``.
|
|
163
|
+
|
|
164
|
+
Let ``cls`` be a class in :class:`ClasscallMetaclass`, and
|
|
165
|
+
consider a call of the form::
|
|
166
|
+
|
|
167
|
+
cls(<some arguments>)
|
|
168
|
+
|
|
169
|
+
- If ``cls`` defines a method ``__classcall_private__``, then
|
|
170
|
+
this results in a call to::
|
|
171
|
+
|
|
172
|
+
cls.__classcall_private__(cls, <some arguments>)
|
|
173
|
+
|
|
174
|
+
- Otherwise, if ``cls`` has a method ``__classcall__``, then instead
|
|
175
|
+
the following is called::
|
|
176
|
+
|
|
177
|
+
cls.__classcall__(cls, <some arguments>)
|
|
178
|
+
|
|
179
|
+
- If neither of these two methods are implemented, then the standard
|
|
180
|
+
``type.__call__(cls, <some arguments>)`` is called, which in turn
|
|
181
|
+
uses :meth:`~object.__new__` and :meth:`~object.__init__` as usual
|
|
182
|
+
(see Section :python:`Basic Customization
|
|
183
|
+
<reference/datamodel.html#basic-customization>` in the Python
|
|
184
|
+
Reference Manual).
|
|
185
|
+
|
|
186
|
+
.. warning:: for technical reasons, ``__classcall__`` must be
|
|
187
|
+
defined as a :func:`staticmethod`, even though it receives
|
|
188
|
+
the class itself as its first argument.
|
|
189
|
+
|
|
190
|
+
EXAMPLES::
|
|
191
|
+
|
|
192
|
+
sage: from sage.misc.classcall_metaclass import ClasscallMetaclass
|
|
193
|
+
sage: class Foo(metaclass=ClasscallMetaclass):
|
|
194
|
+
....: @staticmethod
|
|
195
|
+
....: def __classcall__(cls):
|
|
196
|
+
....: print("calling classcall")
|
|
197
|
+
....: return type.__call__(cls)
|
|
198
|
+
....: def __new__(cls):
|
|
199
|
+
....: print("calling new")
|
|
200
|
+
....: return super(Foo, cls).__new__(cls)
|
|
201
|
+
....: def __init__(self):
|
|
202
|
+
....: print("calling init")
|
|
203
|
+
sage: Foo()
|
|
204
|
+
calling classcall
|
|
205
|
+
calling new
|
|
206
|
+
calling init
|
|
207
|
+
<__main__.Foo object at ...>
|
|
208
|
+
|
|
209
|
+
This behavior is inherited::
|
|
210
|
+
|
|
211
|
+
sage: class Bar(Foo): pass
|
|
212
|
+
sage: Bar()
|
|
213
|
+
calling classcall
|
|
214
|
+
calling new
|
|
215
|
+
calling init
|
|
216
|
+
<__main__.Bar object at ...>
|
|
217
|
+
|
|
218
|
+
We now show the usage of ``__classcall_private__``::
|
|
219
|
+
|
|
220
|
+
sage: class FooNoInherits(object, metaclass=ClasscallMetaclass):
|
|
221
|
+
....: @staticmethod
|
|
222
|
+
....: def __classcall_private__(cls):
|
|
223
|
+
....: print("calling private classcall")
|
|
224
|
+
....: return type.__call__(cls)
|
|
225
|
+
sage: FooNoInherits()
|
|
226
|
+
calling private classcall
|
|
227
|
+
<__main__.FooNoInherits object at ...>
|
|
228
|
+
|
|
229
|
+
Here the behavior is not inherited::
|
|
230
|
+
|
|
231
|
+
sage: class BarNoInherits(FooNoInherits): pass
|
|
232
|
+
sage: BarNoInherits()
|
|
233
|
+
<__main__.BarNoInherits object at ...>
|
|
234
|
+
|
|
235
|
+
We now show the usage of both::
|
|
236
|
+
|
|
237
|
+
sage: class Foo2(object, metaclass=ClasscallMetaclass):
|
|
238
|
+
....: @staticmethod
|
|
239
|
+
....: def __classcall_private__(cls):
|
|
240
|
+
....: print("calling private classcall")
|
|
241
|
+
....: return type.__call__(cls)
|
|
242
|
+
....: @staticmethod
|
|
243
|
+
....: def __classcall__(cls):
|
|
244
|
+
....: print("calling classcall with %s" % cls)
|
|
245
|
+
....: return type.__call__(cls)
|
|
246
|
+
...
|
|
247
|
+
sage: Foo2()
|
|
248
|
+
calling private classcall
|
|
249
|
+
<__main__.Foo2 object at ...>
|
|
250
|
+
|
|
251
|
+
sage: class Bar2(Foo2): pass
|
|
252
|
+
sage: Bar2()
|
|
253
|
+
calling classcall with <class '__main__.Bar2'>
|
|
254
|
+
<__main__.Bar2 object at ...>
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
.. rubric:: Discussion
|
|
258
|
+
|
|
259
|
+
Typical applications include the implementation of factories or of
|
|
260
|
+
unique representation (see :class:`UniqueRepresentation`). Such
|
|
261
|
+
features are traditionally implemented by either using a wrapper
|
|
262
|
+
function, or fiddling with :meth:`~object.__new__`.
|
|
263
|
+
|
|
264
|
+
The benefit, compared with fiddling directly with
|
|
265
|
+
:meth:`~object.__new__` is a clear separation of the three distinct
|
|
266
|
+
roles:
|
|
267
|
+
|
|
268
|
+
- ``cls.__classcall__``: what ``cls(<...>)`` does
|
|
269
|
+
- ``cls.__new__``: memory allocation for a *new* instance
|
|
270
|
+
- ``cls.__init__``: initialization of a newly created instance
|
|
271
|
+
|
|
272
|
+
The benefit, compared with using a wrapper function, is that the
|
|
273
|
+
user interface has a single handle for the class::
|
|
274
|
+
|
|
275
|
+
sage: x = Partition([3,2,2])
|
|
276
|
+
sage: isinstance(x, Partition) # not implemented # needs sage.combinat
|
|
277
|
+
|
|
278
|
+
instead of::
|
|
279
|
+
|
|
280
|
+
sage: isinstance(x, sage.combinat.partition.Partition)
|
|
281
|
+
True
|
|
282
|
+
|
|
283
|
+
Another difference is that ``__classcall__`` is inherited by
|
|
284
|
+
subclasses, which may be desirable, or not. If not, one should
|
|
285
|
+
instead define the method ``__classcall_private__`` which will
|
|
286
|
+
not be called for subclasses. Specifically, if a class ``cls``
|
|
287
|
+
defines both methods ``__classcall__`` and
|
|
288
|
+
``__classcall_private__`` then, for any subclass ``sub`` of ``cls``:
|
|
289
|
+
|
|
290
|
+
- ``cls(<args>)`` will call ``cls.__classcall_private__(cls, <args>)``
|
|
291
|
+
- ``sub(<args>)`` will call ``cls.__classcall__(sub, <args>)``
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
TESTS:
|
|
295
|
+
|
|
296
|
+
We check that the idiom ``method_name in cls.__dict__`` works
|
|
297
|
+
for extension types::
|
|
298
|
+
|
|
299
|
+
sage: "_sage_" in SageObject.__dict__, "_sage_" in Parent.__dict__
|
|
300
|
+
(True, False)
|
|
301
|
+
|
|
302
|
+
We check for memory leaks::
|
|
303
|
+
|
|
304
|
+
sage: class NOCALL(object, metaclass=ClasscallMetaclass):
|
|
305
|
+
....: pass
|
|
306
|
+
sage: sys.getrefcount(NOCALL())
|
|
307
|
+
1
|
|
308
|
+
|
|
309
|
+
We check that exceptions are correctly handled::
|
|
310
|
+
|
|
311
|
+
sage: class Exc(object, metaclass=ClasscallMetaclass):
|
|
312
|
+
....: @staticmethod
|
|
313
|
+
....: def __classcall__(cls):
|
|
314
|
+
....: raise ValueError("Calling classcall")
|
|
315
|
+
sage: Exc()
|
|
316
|
+
Traceback (most recent call last):
|
|
317
|
+
...
|
|
318
|
+
ValueError: Calling classcall
|
|
319
|
+
"""
|
|
320
|
+
if cls.classcall is not None:
|
|
321
|
+
return cls.classcall(cls, *args, **kwds)
|
|
322
|
+
else:
|
|
323
|
+
# Fast version of type.__call__(cls, *args, **kwds)
|
|
324
|
+
return (<PyTypeObject*>type).tp_call(cls, args, kwds)
|
|
325
|
+
|
|
326
|
+
def __get__(cls, instance, owner):
|
|
327
|
+
r"""
|
|
328
|
+
This method implements instance binding behavior for nested classes.
|
|
329
|
+
|
|
330
|
+
Suppose that a class ``Outer`` contains a nested class ``cls`` which
|
|
331
|
+
is an instance of this metaclass. For any object ``obj`` of ``cls``,
|
|
332
|
+
this method implements a instance binding behavior for ``obj.cls`` by
|
|
333
|
+
delegating it to ``cls.__classget__(Outer, obj, owner)`` if available.
|
|
334
|
+
Otherwise, ``obj.cls`` results in ``cls``, as usual.
|
|
335
|
+
|
|
336
|
+
Similarly, a class binding as in ``Outer.cls`` is delegated
|
|
337
|
+
to ``cls.__classget__(Outer, None, owner)`` if available and
|
|
338
|
+
to ``cls`` if not.
|
|
339
|
+
|
|
340
|
+
.. warning:: for technical reasons, ``__classget__`` must be
|
|
341
|
+
defined as a :func:`staticmethod`, even though it receives
|
|
342
|
+
the class itself as its first argument.
|
|
343
|
+
|
|
344
|
+
For technical details, and in particular the description of the
|
|
345
|
+
``owner`` argument, see the Section :python:`Implementing Descriptor
|
|
346
|
+
<reference/datamodel.html#implementing-descriptors>` in the Python
|
|
347
|
+
reference manual.
|
|
348
|
+
|
|
349
|
+
EXAMPLES:
|
|
350
|
+
|
|
351
|
+
We show how to implement a nested class ``Outer.Inner`` with a
|
|
352
|
+
binding behavior, as if it was a method of ``Outer``: namely,
|
|
353
|
+
for ``obj`` an instance of ``Outer``, calling
|
|
354
|
+
``obj.Inner(...)`` is equivalent to ``Outer.Inner(obj, ...)``::
|
|
355
|
+
|
|
356
|
+
sage: import functools
|
|
357
|
+
sage: from sage.misc.nested_class import NestedClassMetaclass
|
|
358
|
+
sage: from sage.misc.classcall_metaclass import ClasscallMetaclass
|
|
359
|
+
sage: class Outer(metaclass=NestedClassMetaclass):
|
|
360
|
+
....: class Inner(metaclass=ClasscallMetaclass):
|
|
361
|
+
....: @staticmethod
|
|
362
|
+
....: def __classget__(cls, instance, owner):
|
|
363
|
+
....: print("calling __classget__(%s, %s, %s)" % (
|
|
364
|
+
....: cls, instance, owner))
|
|
365
|
+
....: if instance is None:
|
|
366
|
+
....: return cls
|
|
367
|
+
....: return functools.partial(cls, instance)
|
|
368
|
+
....: def __init__(self, instance):
|
|
369
|
+
....: self.instance = instance
|
|
370
|
+
sage: obj = Outer()
|
|
371
|
+
sage: bar = obj.Inner()
|
|
372
|
+
calling __classget__(<class '__main__.Outer.Inner'>, <__main__.Outer object at 0x...>, <class '__main__.Outer'>)
|
|
373
|
+
sage: bar.instance == obj
|
|
374
|
+
True
|
|
375
|
+
|
|
376
|
+
Calling ``Outer.Inner`` returns the (unbinded) class as usual::
|
|
377
|
+
|
|
378
|
+
sage: Inner = Outer.Inner
|
|
379
|
+
calling __classget__(<class '__main__.Outer.Inner'>, None, <class '__main__.Outer'>)
|
|
380
|
+
sage: Inner
|
|
381
|
+
<class '__main__.Outer.Inner'>
|
|
382
|
+
sage: type(bar) is Inner
|
|
383
|
+
True
|
|
384
|
+
|
|
385
|
+
.. warning:: Inner has to be a new style class (i.e. a subclass of object).
|
|
386
|
+
|
|
387
|
+
.. warning::
|
|
388
|
+
|
|
389
|
+
Calling ``obj.Inner`` no longer returns a class::
|
|
390
|
+
|
|
391
|
+
sage: bind = obj.Inner
|
|
392
|
+
calling __classget__(<class '__main__.Outer.Inner'>, <__main__.Outer object at 0x...>, <class '__main__.Outer'>)
|
|
393
|
+
sage: bind
|
|
394
|
+
functools.partial(<class '__main__.Outer.Inner'>, <__main__.Outer object at 0x...>)
|
|
395
|
+
"""
|
|
396
|
+
if cls.classget:
|
|
397
|
+
return cls.classget(cls, instance, owner)
|
|
398
|
+
else:
|
|
399
|
+
return cls
|
|
400
|
+
|
|
401
|
+
def __contains__(cls, x):
|
|
402
|
+
r"""
|
|
403
|
+
This method implements membership testing for a class.
|
|
404
|
+
|
|
405
|
+
Let ``cls`` be a class in :class:`ClasscallMetaclass`, and consider
|
|
406
|
+
a call of the form::
|
|
407
|
+
|
|
408
|
+
x in cls
|
|
409
|
+
|
|
410
|
+
If ``cls`` defines a method ``__classcontains__``, then this
|
|
411
|
+
results in a call to::
|
|
412
|
+
|
|
413
|
+
cls.__classcontains__(cls, x)
|
|
414
|
+
|
|
415
|
+
.. warning:: for technical reasons, ``__classcontains__`` must
|
|
416
|
+
be defined as a :func:`staticmethod`, even though it
|
|
417
|
+
receives the class itself as its first argument.
|
|
418
|
+
|
|
419
|
+
EXAMPLES:
|
|
420
|
+
|
|
421
|
+
We construct a class which implements membership testing, and
|
|
422
|
+
which contains ``1`` and no other x::
|
|
423
|
+
|
|
424
|
+
sage: from sage.misc.classcall_metaclass import ClasscallMetaclass
|
|
425
|
+
sage: class Foo(metaclass=ClasscallMetaclass):
|
|
426
|
+
....: @staticmethod
|
|
427
|
+
....: def __classcontains__(cls, x):
|
|
428
|
+
....: return x == 1
|
|
429
|
+
sage: 1 in Foo
|
|
430
|
+
True
|
|
431
|
+
sage: 2 in Foo
|
|
432
|
+
False
|
|
433
|
+
|
|
434
|
+
We now check that for a class without ``__classcontains__``
|
|
435
|
+
method, we emulate the usual error message::
|
|
436
|
+
|
|
437
|
+
sage: from sage.misc.classcall_metaclass import ClasscallMetaclass
|
|
438
|
+
sage: class Bar(metaclass=ClasscallMetaclass): pass
|
|
439
|
+
sage: 1 in Bar
|
|
440
|
+
Traceback (most recent call last):
|
|
441
|
+
...
|
|
442
|
+
TypeError: argument of type 'type' is not... iterable
|
|
443
|
+
"""
|
|
444
|
+
if cls.classcontains:
|
|
445
|
+
return cls.classcontains(cls, x)
|
|
446
|
+
else:
|
|
447
|
+
return x in object
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def typecall(pytype cls, *args, **kwds):
|
|
451
|
+
r"""
|
|
452
|
+
Object construction.
|
|
453
|
+
|
|
454
|
+
This is a faster equivalent to ``type.__call__(cls, <some arguments>)``.
|
|
455
|
+
|
|
456
|
+
INPUT:
|
|
457
|
+
|
|
458
|
+
- ``cls`` -- the class used for constructing the instance; it must be
|
|
459
|
+
a builtin type or a new style class (inheriting from :class:`object`)
|
|
460
|
+
|
|
461
|
+
EXAMPLES::
|
|
462
|
+
|
|
463
|
+
sage: from sage.misc.classcall_metaclass import typecall
|
|
464
|
+
sage: class Foo(): pass
|
|
465
|
+
sage: typecall(Foo)
|
|
466
|
+
<__main__.Foo object at 0x...>
|
|
467
|
+
sage: typecall(list)
|
|
468
|
+
[]
|
|
469
|
+
sage: typecall(Integer, 2)
|
|
470
|
+
2
|
|
471
|
+
"""
|
|
472
|
+
return (<PyTypeObject*>type).tp_call(cls, args, kwds)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
# Class for timing::
|
|
476
|
+
|
|
477
|
+
class CRef():
|
|
478
|
+
def __init__(self, i):
|
|
479
|
+
"""
|
|
480
|
+
TESTS::
|
|
481
|
+
|
|
482
|
+
sage: from sage.misc.classcall_metaclass import CRef
|
|
483
|
+
sage: P = CRef(2); P.i
|
|
484
|
+
3
|
|
485
|
+
"""
|
|
486
|
+
self.i = i+1
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
class C2(object, metaclass=ClasscallMetaclass):
|
|
490
|
+
def __init__(self, i):
|
|
491
|
+
"""
|
|
492
|
+
TESTS::
|
|
493
|
+
|
|
494
|
+
sage: from sage.misc.classcall_metaclass import C2
|
|
495
|
+
sage: P = C2(2); P.i
|
|
496
|
+
3
|
|
497
|
+
"""
|
|
498
|
+
self.i = i+1
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
class C3(object, metaclass = ClasscallMetaclass):
|
|
502
|
+
def __init__(self, i):
|
|
503
|
+
"""
|
|
504
|
+
TESTS::
|
|
505
|
+
|
|
506
|
+
sage: from sage.misc.classcall_metaclass import C3
|
|
507
|
+
sage: P = C3(2); P.i
|
|
508
|
+
3
|
|
509
|
+
"""
|
|
510
|
+
self.i = i+1
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
class C2C(object, metaclass=ClasscallMetaclass):
|
|
514
|
+
@staticmethod
|
|
515
|
+
def __classcall__(cls, i):
|
|
516
|
+
"""
|
|
517
|
+
TESTS::
|
|
518
|
+
|
|
519
|
+
sage: from sage.misc.classcall_metaclass import C2C
|
|
520
|
+
sage: C2C(2)
|
|
521
|
+
3
|
|
522
|
+
"""
|
|
523
|
+
return i+1
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
def timeCall(T, int n, *args):
|
|
527
|
+
r"""
|
|
528
|
+
We illustrate some timing when using the classcall mechanism.
|
|
529
|
+
|
|
530
|
+
EXAMPLES::
|
|
531
|
+
|
|
532
|
+
sage: from sage.misc.classcall_metaclass import (
|
|
533
|
+
....: ClasscallMetaclass, CRef, C2, C3, C2C, timeCall)
|
|
534
|
+
sage: timeCall(object, 1000)
|
|
535
|
+
|
|
536
|
+
For reference let construct basic objects and a basic Python class::
|
|
537
|
+
|
|
538
|
+
sage: %timeit timeCall(object, 1000) # not tested
|
|
539
|
+
625 loops, best of 3: 41.4 µs per loop
|
|
540
|
+
|
|
541
|
+
sage: i1 = int(1); i3 = int(3) # don't use Sage's Integer
|
|
542
|
+
sage: class PRef():
|
|
543
|
+
....: def __init__(self, i):
|
|
544
|
+
....: self.i = i+i1
|
|
545
|
+
|
|
546
|
+
For a Python class, compared to the reference class there is a 10%
|
|
547
|
+
overhead in using :class:`ClasscallMetaclass` if there is no classcall
|
|
548
|
+
defined::
|
|
549
|
+
|
|
550
|
+
sage: class P(metaclass=ClasscallMetaclass):
|
|
551
|
+
....: def __init__(self, i):
|
|
552
|
+
....: self.i = i+i1
|
|
553
|
+
|
|
554
|
+
sage: %timeit timeCall(PRef, 1000, i3) # not tested
|
|
555
|
+
625 loops, best of 3: 420 µs per loop
|
|
556
|
+
sage: %timeit timeCall(P, 1000, i3) # not tested
|
|
557
|
+
625 loops, best of 3: 458 µs per loop
|
|
558
|
+
|
|
559
|
+
For a Cython class (not cdef since they doesn't allows metaclasses), the
|
|
560
|
+
overhead is a little larger::
|
|
561
|
+
|
|
562
|
+
sage: %timeit timeCall(CRef, 1000, i3) # not tested
|
|
563
|
+
625 loops, best of 3: 266 µs per loop
|
|
564
|
+
sage: %timeit timeCall(C2, 1000, i3) # not tested
|
|
565
|
+
625 loops, best of 3: 298 µs per loop
|
|
566
|
+
|
|
567
|
+
Let's now compare when there is a classcall defined::
|
|
568
|
+
|
|
569
|
+
sage: class PC(object, metaclass=ClasscallMetaclass):
|
|
570
|
+
....: @staticmethod
|
|
571
|
+
....: def __classcall__(cls, i):
|
|
572
|
+
....: return i+i1
|
|
573
|
+
sage: %timeit timeCall(C2C, 1000, i3) # not tested
|
|
574
|
+
625 loops, best of 3: 148 µs per loop
|
|
575
|
+
sage: %timeit timeCall(PC, 1000, i3) # not tested
|
|
576
|
+
625 loops, best of 3: 289 µs per loop
|
|
577
|
+
|
|
578
|
+
The overhead of the indirection ( ``C(...) ->
|
|
579
|
+
ClasscallMetaclass.__call__(...) -> C.__classcall__(...)``) is
|
|
580
|
+
unfortunately quite large in this case (two method calls instead of
|
|
581
|
+
one). In reasonable usecases, the overhead should be mostly hidden by the
|
|
582
|
+
computations inside the classcall::
|
|
583
|
+
|
|
584
|
+
sage: %timeit timeCall(C2C.__classcall__, 1000, C2C, i3) # not tested
|
|
585
|
+
625 loops, best of 3: 33 µs per loop
|
|
586
|
+
sage: %timeit timeCall(PC.__classcall__, 1000, PC, i3) # not tested
|
|
587
|
+
625 loops, best of 3: 131 µs per loop
|
|
588
|
+
|
|
589
|
+
Finally, there is no significant difference between Cython's V2 and V3
|
|
590
|
+
syntax for metaclass::
|
|
591
|
+
|
|
592
|
+
sage: %timeit timeCall(C2, 1000, i3) # not tested
|
|
593
|
+
625 loops, best of 3: 330 µs per loop
|
|
594
|
+
sage: %timeit timeCall(C3, 1000, i3) # not tested
|
|
595
|
+
625 loops, best of 3: 328 µs per loop
|
|
596
|
+
"""
|
|
597
|
+
cdef int i
|
|
598
|
+
for 0<=i<n:
|
|
599
|
+
T(*args)
|
|
Binary file
|