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,739 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Decorators
4
+
5
+ Python decorators for use in Sage.
6
+
7
+ AUTHORS:
8
+
9
+ - Tim Dumol (5 Dec 2009) -- initial version.
10
+ - Johan S. R. Nielsen (2010) -- collect decorators from various modules.
11
+ - Johan S. R. Nielsen (8 apr 2011) -- improve introspection on decorators.
12
+ - Simon King (2011-05-26) -- improve introspection of sage_wraps. Put this
13
+ file into the reference manual.
14
+ - Julian Rueth (2014-03-19): added ``decorator_keywords`` decorator
15
+ """
16
+ # *****************************************************************************
17
+ # Copyright (C) 2009 Tim Dumol
18
+ # 2010,2011 Johan S. R. Nielsen
19
+ # 2011 Simon King <simon.king@uni-jena.de>
20
+ # 2014 Julian Rueth <julian.rueth@fsfe.org>
21
+ #
22
+ # This program is free software: you can redistribute it and/or modify
23
+ # it under the terms of the GNU General Public License as published by
24
+ # the Free Software Foundation, either version 2 of the License, or
25
+ # (at your option) any later version.
26
+ # http://www.gnu.org/licenses/
27
+ # *****************************************************************************
28
+
29
+ from copy import copy
30
+ from functools import WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES, partial, update_wrapper
31
+ from inspect import FullArgSpec
32
+
33
+ from sage.misc.sageinspect import sage_getargspec, sage_getsource, sage_getsourcelines
34
+
35
+
36
+ def sage_wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES):
37
+ r"""
38
+ Decorator factory which should be used in decorators for making sure that
39
+ meta-information on the decorated callables are retained through the
40
+ decorator, such that the introspection functions of
41
+ ``sage.misc.sageinspect`` retrieves them correctly. This includes
42
+ documentation string, source, and argument specification. This is an
43
+ extension of the Python standard library decorator functools.wraps.
44
+
45
+ That the argument specification is retained from the decorated functions
46
+ implies, that if one uses ``sage_wraps`` in a decorator which intentionally
47
+ changes the argument specification, one should add this information to
48
+ the special attribute ``_sage_argspec_`` of the wrapping function (for an
49
+ example, see e.g. ``@options`` decorator in this module)::
50
+
51
+ sage: import cython
52
+ sage: def square(f):
53
+ ....: @sage_wraps(f)
54
+ ....: def new_f(x):
55
+ ....: return f(x)*f(x)
56
+ ....: return new_f
57
+
58
+ EXAMPLES:
59
+
60
+ Demonstrate that documentation string and source are retained from the
61
+ decorated function::
62
+
63
+ sage: def square(f):
64
+ ....: @sage_wraps(f)
65
+ ....: def new_f(x):
66
+ ....: return f(x)*f(x)
67
+ ....: return new_f
68
+ sage: @square
69
+ ....: def g(x):
70
+ ....: "My little function"
71
+ ....: return x
72
+ sage: g(2)
73
+ 4
74
+ sage: g(x) # needs sage.symbolic
75
+ x^2
76
+ sage: g.__doc__
77
+ 'My little function'
78
+ sage: from sage.misc.sageinspect import sage_getsource, sage_getsourcelines, sage_getfile
79
+ sage: sage_getsource(g)
80
+ '@square...def g(x)...'
81
+
82
+ Demonstrate that the argument description are retained from the
83
+ decorated function through the special method (when left
84
+ unchanged) (see :issue:`9976`)::
85
+
86
+ sage: def diff_arg_dec(f):
87
+ ....: @sage_wraps(f)
88
+ ....: def new_f(y, some_def_arg=2):
89
+ ....: return f(y+some_def_arg)
90
+ ....: return new_f
91
+ sage: @diff_arg_dec
92
+ ....: def g(x):
93
+ ....: return x
94
+ sage: g(1)
95
+ 3
96
+ sage: g(1, some_def_arg=4)
97
+ 5
98
+ sage: from sage.misc.sageinspect import sage_getargspec
99
+ sage: sage_getargspec(g)
100
+ FullArgSpec(args=['x'], varargs=None, varkw=None, defaults=None,
101
+ kwonlyargs=[], kwonlydefaults=None, annotations={})
102
+
103
+ Demonstrate that it correctly gets the source lines and the source
104
+ file, which is essential for interactive code edition; note that we
105
+ do not test the line numbers, as they may easily change::
106
+
107
+ sage: P.<x,y> = QQ[]
108
+ sage: I = P*[x,y]
109
+ sage: sage_getfile(I.interreduced_basis) # known bug
110
+ '.../sage/rings/polynomial/multi_polynomial_ideal.py'
111
+ sage: sage_getsourcelines(I.interreduced_basis) # needs sage.libs.singular
112
+ ([' @handle_AA_and_QQbar\n',
113
+ ' @singular_gb_standard_options\n',
114
+ ' @libsingular_gb_standard_options\n',
115
+ ' def interreduced_basis(self):\n',
116
+ ...
117
+ ' return self.basis.reduced()\n'], ...)
118
+
119
+ The ``f`` attribute of the decorated function refers to the
120
+ original function::
121
+
122
+ sage: foo = object()
123
+ sage: @sage_wraps(foo)
124
+ ....: def func():
125
+ ....: pass
126
+ sage: wrapped = sage_wraps(foo)(func)
127
+ sage: wrapped.f is foo
128
+ True
129
+
130
+ Demonstrate that sage_wraps works for non-function callables
131
+ (:issue:`9919`)::
132
+
133
+ sage: def square_for_met(f):
134
+ ....: @sage_wraps(f)
135
+ ....: def new_f(self, x):
136
+ ....: return f(self,x)*f(self,x)
137
+ ....: return new_f
138
+ sage: class T:
139
+ ....: @square_for_met
140
+ ....: def g(self, x):
141
+ ....: "My little method"
142
+ ....: return x
143
+ sage: t = T()
144
+ sage: t.g(2)
145
+ 4
146
+ sage: t.g.__doc__
147
+ 'My little method'
148
+
149
+ The bug described in :issue:`11734` is fixed::
150
+
151
+ sage: def square(f):
152
+ ....: @sage_wraps(f)
153
+ ....: def new_f(x):
154
+ ....: return f(x)*f(x)
155
+ ....: return new_f
156
+ sage: f = lambda x:x^2
157
+ sage: g = square(f)
158
+ sage: g(3) # this line used to fail for some people if these command were manually entered on the sage prompt
159
+ 81
160
+ """
161
+ # TRAC 9919: Workaround for bug in @update_wrapper when used with
162
+ # non-function callables.
163
+ assigned = set(assigned).intersection(set(dir(wrapped)))
164
+ # end workaround
165
+
166
+ def f(wrapper, assigned=assigned, updated=updated):
167
+ update_wrapper(wrapper, wrapped, assigned=assigned, updated=updated)
168
+ # For backwards-compatibility with old versions of sage_wraps
169
+ wrapper.f = wrapped
170
+ # For forwards-compatibility with functools.wraps on Python 3
171
+ wrapper.__wrapped__ = wrapped
172
+ wrapper._sage_src_ = lambda: sage_getsource(wrapped)
173
+ wrapper._sage_src_lines_ = lambda: sage_getsourcelines(wrapped)
174
+ # Getting the signature right in documentation by Sphinx (Issue 9976)
175
+ # The attribute _sage_argspec_() is read by Sphinx if present and used
176
+ # as the argspec of the function instead of using reflection.
177
+ wrapper._sage_argspec_ = lambda: sage_getargspec(wrapped)
178
+ return wrapper
179
+ return f
180
+
181
+
182
+ # Infix operator decorator
183
+ class infix_operator:
184
+ """
185
+ A decorator for functions which allows for a hack that makes
186
+ the function behave like an infix operator.
187
+
188
+ This decorator exists as a convenience for interactive use.
189
+
190
+ EXAMPLES:
191
+
192
+ An infix dot product operator::
193
+
194
+ sage: @infix_operator('multiply')
195
+ ....: def dot(a, b):
196
+ ....: '''Dot product.'''
197
+ ....: return a.dot_product(b)
198
+ sage: u = vector([1, 2, 3]) # needs sage.modules
199
+ sage: v = vector([5, 4, 3]) # needs sage.modules
200
+ sage: u *dot* v # needs sage.modules
201
+ 22
202
+
203
+ An infix element-wise addition operator::
204
+
205
+ sage: # needs sage.modules
206
+ sage: @infix_operator('add')
207
+ ....: def eadd(a, b):
208
+ ....: return a.parent([i + j for i, j in zip(a, b)])
209
+ sage: u = vector([1, 2, 3])
210
+ sage: v = vector([5, 4, 3])
211
+ sage: u +eadd+ v
212
+ (6, 6, 6)
213
+ sage: 2*u +eadd+ v
214
+ (7, 8, 9)
215
+
216
+ A hack to simulate a postfix operator::
217
+
218
+ sage: @infix_operator('or')
219
+ ....: def thendo(a, b):
220
+ ....: return b(a)
221
+ sage: x |thendo| cos |thendo| (lambda x: x^2) # needs sage.symbolic
222
+ cos(x)^2
223
+ """
224
+
225
+ operators = {
226
+ 'add': {'left': '__add__', 'right': '__radd__'},
227
+ 'multiply': {'left': '__mul__', 'right': '__rmul__'},
228
+ 'or': {'left': '__or__', 'right': '__ror__'},
229
+ }
230
+
231
+ def __init__(self, precedence):
232
+ """
233
+ INPUT:
234
+
235
+ - ``precedence`` -- one of ``'add'``, ``'multiply'``, or ``'or'``
236
+ indicating the new operator's precedence in the order of operations
237
+ """
238
+ self.precedence = precedence
239
+
240
+ def __call__(self, func):
241
+ """Returns a function which acts as an inline operator."""
242
+
243
+ left_meth = self.operators[self.precedence]['left']
244
+ right_meth = self.operators[self.precedence]['right']
245
+ wrapper_name = func.__name__
246
+ wrapper_members = {
247
+ 'function': staticmethod(func),
248
+ left_meth: _infix_wrapper._left,
249
+ right_meth: _infix_wrapper._right,
250
+ '_sage_src_': lambda: sage_getsource(func)
251
+ }
252
+ for attr in WRAPPER_ASSIGNMENTS:
253
+ try:
254
+ wrapper_members[attr] = getattr(func, attr)
255
+ except AttributeError:
256
+ pass
257
+
258
+ wrapper = type(wrapper_name, (_infix_wrapper,), wrapper_members)
259
+
260
+ wrapper_inst = wrapper()
261
+ wrapper_inst.__dict__.update(getattr(func, '__dict__', {}))
262
+ return wrapper_inst
263
+
264
+
265
+ class _infix_wrapper:
266
+ function = None
267
+
268
+ def __init__(self, left=None, right=None):
269
+ """
270
+ Initialize the actual infix object, with possibly a specified left
271
+ and/or right operand.
272
+ """
273
+ self.left = left
274
+ self.right = right
275
+
276
+ def __call__(self, *args, **kwds):
277
+ """Call the passed function."""
278
+ return self.function(*args, **kwds)
279
+
280
+ def _left(self, right):
281
+ """The function for the operation on the left (e.g., __add__)."""
282
+ if self.left is None:
283
+ if self.right is None:
284
+ new = copy(self)
285
+ new.right = right
286
+ return new
287
+ else:
288
+ raise SyntaxError("Infix operator already has its "
289
+ "right argument")
290
+ else:
291
+ return self.function(self.left, right)
292
+
293
+ def _right(self, left):
294
+ """The function for the operation on the right (e.g., __radd__)."""
295
+ if self.right is None:
296
+ if self.left is None:
297
+ new = copy(self)
298
+ new.left = left
299
+ return new
300
+ else:
301
+ raise SyntaxError("Infix operator already has its "
302
+ "left argument")
303
+ else:
304
+ return self.function(left, self.right)
305
+
306
+
307
+ def decorator_defaults(func):
308
+ """
309
+ This function allows a decorator to have default arguments.
310
+
311
+ Normally, a decorator can be called with or without arguments.
312
+ However, the two cases call for different types of return values.
313
+ If a decorator is called with no parentheses, it should be run
314
+ directly on the function. However, if a decorator is called with
315
+ parentheses (i.e., arguments), then it should return a function
316
+ that is then in turn called with the defined function as an
317
+ argument.
318
+
319
+ This decorator allows us to have these default arguments without
320
+ worrying about the return type.
321
+
322
+ EXAMPLES::
323
+
324
+ sage: from sage.misc.decorators import decorator_defaults
325
+ sage: @decorator_defaults
326
+ ....: def my_decorator(f, *args, **kwds):
327
+ ....: print(kwds)
328
+ ....: print(args)
329
+ ....: print(f.__name__)
330
+
331
+ sage: @my_decorator
332
+ ....: def my_fun(a, b):
333
+ ....: return a,b
334
+ {}
335
+ ()
336
+ my_fun
337
+ sage: @my_decorator(3,4,c=1,d=2)
338
+ ....: def my_fun(a, b):
339
+ ....: return a,b
340
+ {'c': 1, 'd': 2}
341
+ (3, 4)
342
+ my_fun
343
+ """
344
+ @sage_wraps(func)
345
+ def my_wrap(*args, **kwds):
346
+ if len(kwds) == 0 and len(args) == 1:
347
+ # call without parentheses
348
+ return func(*args)
349
+ else:
350
+ return lambda f: func(f, *args, **kwds)
351
+ return my_wrap
352
+
353
+
354
+ class suboptions:
355
+ def __init__(self, name, **options):
356
+ """
357
+ A decorator for functions which collects all keywords
358
+ starting with ``name+'_'`` and collects them into a dictionary
359
+ which will be passed on to the wrapped function as a
360
+ dictionary called ``name_options``.
361
+
362
+ The keyword arguments passed into the constructor are taken
363
+ to be default for the ``name_options`` dictionary.
364
+
365
+ EXAMPLES::
366
+
367
+ sage: from sage.misc.decorators import suboptions
368
+ sage: s = suboptions('arrow', size=2)
369
+ sage: s.name
370
+ 'arrow_'
371
+ sage: s.options
372
+ {'size': 2}
373
+ """
374
+ self.name = name + "_"
375
+ self.options = options
376
+
377
+ def __call__(self, func):
378
+ """
379
+ Return a wrapper around ``func``.
380
+
381
+ EXAMPLES::
382
+
383
+ sage: from sage.misc.decorators import suboptions
384
+ sage: def f(*args, **kwds): print(sorted(kwds.items()))
385
+ sage: f = suboptions('arrow', size=2)(f)
386
+ sage: f(size=2)
387
+ [('arrow_options', {'size': 2}), ('size', 2)]
388
+ sage: f(arrow_size=3)
389
+ [('arrow_options', {'size': 3})]
390
+ sage: f(arrow_options={'size':4})
391
+ [('arrow_options', {'size': 4})]
392
+ sage: f(arrow_options={'size':4}, arrow_size=5)
393
+ [('arrow_options', {'size': 5})]
394
+
395
+ Demonstrate that the introspected argument specification of the
396
+ wrapped function is updated (see :issue:`9976`)::
397
+
398
+ sage: from sage.misc.sageinspect import sage_getargspec
399
+ sage: sage_getargspec(f)
400
+ FullArgSpec(args=['arrow_size'], varargs='args', varkw='kwds', defaults=(2,),
401
+ kwonlyargs=[], kwonlydefaults=None, annotations={})
402
+ """
403
+ @sage_wraps(func)
404
+ def wrapper(*args, **kwds):
405
+ suboptions = copy(self.options)
406
+ suboptions.update(kwds.pop(self.name+"options", {}))
407
+
408
+ # Collect all the relevant keywords in kwds
409
+ # and put them in suboptions
410
+ for key, value in list(kwds.items()):
411
+ if key.startswith(self.name):
412
+ suboptions[key[len(self.name):]] = value
413
+ del kwds[key]
414
+
415
+ kwds[self.name + "options"] = suboptions
416
+
417
+ return func(*args, **kwds)
418
+
419
+ # Add the options specified by @options to the signature of the wrapped
420
+ # function in the Sphinx-generated documentation (Issue 9976), using the
421
+ # special attribute _sage_argspec_ (see e.g. sage.misc.sageinspect)
422
+ def argspec():
423
+ argspec = sage_getargspec(func)
424
+
425
+ def listForNone(l):
426
+ return l if l is not None else []
427
+ newArgs = [self.name + opt for opt in self.options.keys()]
428
+ args = (argspec.args if argspec.args is not None else []) + newArgs
429
+ defaults = (argspec.defaults if argspec.defaults is not None else ()) \
430
+ + tuple(self.options.values())
431
+ # Note: argspec.defaults is not always a tuple for some reason
432
+ return FullArgSpec(args, argspec.varargs, argspec.varkw, defaults,
433
+ kwonlyargs=[], kwonlydefaults=None, annotations={})
434
+ wrapper._sage_argspec_ = argspec
435
+
436
+ return wrapper
437
+
438
+
439
+ class options:
440
+ def __init__(self, **options):
441
+ """
442
+ A decorator for functions which allows for default options to be
443
+ set and reset by the end user. Additionally, if one needs to, one
444
+ can get at the original keyword arguments passed into the
445
+ decorator.
446
+
447
+ TESTS::
448
+
449
+ sage: from sage.misc.decorators import options
450
+ sage: o = options(rgbcolor=(0,0,1))
451
+ sage: o.options
452
+ {'rgbcolor': (0, 0, 1)}
453
+ sage: o = options(rgbcolor=(0,0,1), __original_opts=True)
454
+ sage: o.original_opts
455
+ True
456
+ sage: loads(dumps(o)).options
457
+ {'rgbcolor': (0, 0, 1)}
458
+
459
+ Demonstrate that the introspected argument specification of the wrapped
460
+ function is updated (see :issue:`9976`)::
461
+
462
+ sage: from sage.misc.decorators import options
463
+ sage: o = options(rgbcolor=(0,0,1))
464
+ sage: def f(*args, **kwds):
465
+ ....: print("{} {}".format(args, sorted(kwds.items())))
466
+ sage: f1 = o(f)
467
+ sage: from sage.misc.sageinspect import sage_getargspec
468
+ sage: sage_getargspec(f1)
469
+ FullArgSpec(args=['rgbcolor'], varargs='args', varkw='kwds', defaults=((0, 0, 1),),
470
+ kwonlyargs=[], kwonlydefaults=None, annotations={})
471
+ """
472
+ self.options = options
473
+ self.original_opts = options.pop('__original_opts', False)
474
+
475
+ def __call__(self, func):
476
+ """
477
+ EXAMPLES::
478
+
479
+ sage: from sage.misc.decorators import options
480
+ sage: o = options(rgbcolor=(0,0,1))
481
+ sage: def f(*args, **kwds):
482
+ ....: print("{} {}".format(args, sorted(kwds.items())))
483
+ sage: f1 = o(f)
484
+ sage: f1()
485
+ () [('rgbcolor', (0, 0, 1))]
486
+ sage: f1(rgbcolor=1)
487
+ () [('rgbcolor', 1)]
488
+ sage: o = options(rgbcolor=(0,0,1), __original_opts=True)
489
+ sage: f2 = o(f)
490
+ sage: f2(alpha=1)
491
+ () [('__original_opts', {'alpha': 1}), ('alpha', 1), ('rgbcolor', (0, 0, 1))]
492
+ """
493
+ @sage_wraps(func)
494
+ def wrapper(*args, **kwds):
495
+ options = copy(wrapper.options)
496
+ if self.original_opts:
497
+ options['__original_opts'] = kwds
498
+ options.update(kwds)
499
+ return func(*args, **options)
500
+
501
+ # Add the options specified by @options to the signature of the wrapped
502
+ # function in the Sphinx-generated documentation (Issue 9976), using the
503
+ # special attribute _sage_argspec_ (see e.g. sage.misc.sageinspect)
504
+ def argspec():
505
+ argspec = sage_getargspec(func)
506
+ args = ((argspec.args if argspec.args is not None else []) +
507
+ list(self.options))
508
+ defaults = (argspec.defaults or ()) + tuple(self.options.values())
509
+ # Note: argspec.defaults is not always a tuple for some reason
510
+ return FullArgSpec(args, argspec.varargs, argspec.varkw, defaults,
511
+ kwonlyargs=[], kwonlydefaults=None, annotations={})
512
+
513
+ wrapper._sage_argspec_ = argspec
514
+
515
+ def defaults():
516
+ """
517
+ Return the default options.
518
+
519
+ EXAMPLES::
520
+
521
+ sage: from sage.misc.decorators import options
522
+ sage: o = options(rgbcolor=(0,0,1))
523
+ sage: def f(*args, **kwds):
524
+ ....: print("{} {}".format(args, sorted(kwds.items())))
525
+ sage: f = o(f)
526
+ sage: f.options['rgbcolor']=(1,1,1)
527
+ sage: f.defaults()
528
+ {'rgbcolor': (0, 0, 1)}
529
+ """
530
+ return copy(self.options)
531
+
532
+ def reset():
533
+ """
534
+ Reset the options to the defaults.
535
+
536
+ EXAMPLES::
537
+
538
+ sage: from sage.misc.decorators import options
539
+ sage: o = options(rgbcolor=(0,0,1))
540
+ sage: def f(*args, **kwds):
541
+ ....: print("{} {}".format(args, sorted(kwds.items())))
542
+ sage: f = o(f)
543
+ sage: f.options
544
+ {'rgbcolor': (0, 0, 1)}
545
+ sage: f.options['rgbcolor']=(1,1,1)
546
+ sage: f.options
547
+ {'rgbcolor': (1, 1, 1)}
548
+ sage: f()
549
+ () [('rgbcolor', (1, 1, 1))]
550
+ sage: f.reset()
551
+ sage: f.options
552
+ {'rgbcolor': (0, 0, 1)}
553
+ sage: f()
554
+ () [('rgbcolor', (0, 0, 1))]
555
+ """
556
+ wrapper.options = copy(self.options)
557
+
558
+ wrapper.options = copy(self.options)
559
+ wrapper.reset = reset
560
+ wrapper.reset.__doc__ = """
561
+ Reset the options to the defaults.
562
+
563
+ Defaults:
564
+ %s
565
+ """ % self.options
566
+
567
+ wrapper.defaults = defaults
568
+ wrapper.defaults.__doc__ = """
569
+ Return the default options.
570
+
571
+ Defaults:
572
+ %s
573
+ """ % self.options
574
+
575
+ return wrapper
576
+
577
+
578
+ class rename_keyword:
579
+ def __init__(self, deprecated=None, deprecation=None, **renames):
580
+ """
581
+ A decorator which renames keyword arguments and optionally
582
+ deprecates the new keyword.
583
+
584
+ INPUT:
585
+
586
+ - ``deprecation`` -- integer; the github issue number where the
587
+ deprecation was introduced
588
+
589
+ - the rest of the arguments is a list of keyword arguments in the
590
+ form ``renamed_option='existing_option'``. This will have the
591
+ effect of renaming ``renamed_option`` so that the function only
592
+ sees ``existing_option``. If both ``renamed_option`` and
593
+ ``existing_option`` are passed to the function, ``existing_option``
594
+ will override the ``renamed_option`` value.
595
+
596
+ EXAMPLES::
597
+
598
+ sage: from sage.misc.decorators import rename_keyword
599
+ sage: r = rename_keyword(color='rgbcolor')
600
+ sage: r.renames
601
+ {'color': 'rgbcolor'}
602
+ sage: loads(dumps(r)).renames
603
+ {'color': 'rgbcolor'}
604
+
605
+ To deprecate an old keyword::
606
+
607
+ sage: r = rename_keyword(deprecation=13109, color='rgbcolor')
608
+ """
609
+ assert deprecated is None, 'Use @rename_keyword(deprecation=<issue_number>, ...)'
610
+ self.renames = renames
611
+ self.deprecation = deprecation
612
+
613
+ def __call__(self, func):
614
+ """
615
+ Rename keywords.
616
+
617
+ EXAMPLES::
618
+
619
+ sage: from sage.misc.decorators import rename_keyword
620
+ sage: r = rename_keyword(color='rgbcolor')
621
+ sage: def f(*args, **kwds):
622
+ ....: print("{} {}".format(args, kwds))
623
+ sage: f = r(f)
624
+ sage: f()
625
+ () {}
626
+ sage: f(alpha=1)
627
+ () {'alpha': 1}
628
+ sage: f(rgbcolor=1)
629
+ () {'rgbcolor': 1}
630
+ sage: f(color=1)
631
+ () {'rgbcolor': 1}
632
+
633
+ We can also deprecate the renamed keyword::
634
+
635
+ sage: r = rename_keyword(deprecation=13109, deprecated_option='new_option')
636
+ sage: def f(*args, **kwds):
637
+ ....: print("{} {}".format(args, kwds))
638
+ sage: f = r(f)
639
+ sage: f()
640
+ () {}
641
+ sage: f(alpha=1)
642
+ () {'alpha': 1}
643
+ sage: f(new_option=1)
644
+ () {'new_option': 1}
645
+ sage: f(deprecated_option=1)
646
+ doctest:...: DeprecationWarning: use the option 'new_option' instead of 'deprecated_option'
647
+ See https://github.com/sagemath/sage/issues/13109 for details.
648
+ () {'new_option': 1}
649
+ """
650
+ @sage_wraps(func)
651
+ def wrapper(*args, **kwds):
652
+ for old_name, new_name in self.renames.items():
653
+ if old_name in kwds and new_name not in kwds:
654
+ if self.deprecation is not None:
655
+ from sage.misc.superseded import deprecation
656
+ deprecation(self.deprecation, "use the option "
657
+ "%r instead of %r" % (new_name, old_name))
658
+ kwds[new_name] = kwds[old_name]
659
+ del kwds[old_name]
660
+ return func(*args, **kwds)
661
+
662
+ return wrapper
663
+
664
+
665
+ class specialize:
666
+ r"""
667
+ A decorator generator that returns a decorator that in turn
668
+ returns a specialized function for function ``f``. In other words,
669
+ it returns a function that acts like ``f`` with arguments
670
+ ``*args`` and ``**kwargs`` supplied.
671
+
672
+ INPUT:
673
+
674
+ - ``*args``, ``**kwargs`` -- arguments to specialize the function for
675
+
676
+ OUTPUT: a decorator that accepts a function ``f`` and specializes it
677
+ with ``*args`` and ``**kwargs``
678
+
679
+ EXAMPLES::
680
+
681
+ sage: f = specialize(5)(lambda x, y: x+y)
682
+ sage: f(10)
683
+ 15
684
+ sage: f(5)
685
+ 10
686
+ sage: @specialize("Bon Voyage")
687
+ ....: def greet(greeting, name):
688
+ ....: print("{0}, {1}!".format(greeting, name))
689
+ sage: greet("Monsieur Jean Valjean")
690
+ Bon Voyage, Monsieur Jean Valjean!
691
+ sage: greet(name = 'Javert')
692
+ Bon Voyage, Javert!
693
+ """
694
+ def __init__(self, *args, **kwargs):
695
+ self.args = args
696
+ self.kwargs = kwargs
697
+
698
+ def __call__(self, f):
699
+ return sage_wraps(f)(partial(f, *self.args, **self.kwargs))
700
+
701
+
702
+ def decorator_keywords(func):
703
+ r"""
704
+ A decorator for decorators with optional keyword arguments.
705
+
706
+ EXAMPLES::
707
+
708
+ sage: from sage.misc.decorators import decorator_keywords
709
+ sage: @decorator_keywords
710
+ ....: def preprocess(f=None, processor=None):
711
+ ....: def wrapper(*args, **kwargs):
712
+ ....: if processor is not None:
713
+ ....: args, kwargs = processor(*args, **kwargs)
714
+ ....: return f(*args, **kwargs)
715
+ ....: return wrapper
716
+
717
+ This decorator can be called with and without arguments::
718
+
719
+ sage: @preprocess
720
+ ....: def foo(x): return x
721
+ sage: foo(None)
722
+ sage: foo(1)
723
+ 1
724
+
725
+ sage: def normalize(x): return ((0,),{}) if x is None else ((x,),{})
726
+ sage: @preprocess(processor=normalize)
727
+ ....: def foo(x): return x
728
+ sage: foo(None)
729
+ 0
730
+ sage: foo(1)
731
+ 1
732
+ """
733
+ @sage_wraps(func)
734
+ def wrapped(f=None, **kwargs):
735
+ if f is None:
736
+ return sage_wraps(func)(lambda f: func(f, **kwargs))
737
+ else:
738
+ return func(f, **kwargs)
739
+ return wrapped