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
sage/misc/misc.py ADDED
@@ -0,0 +1,980 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Miscellaneous functions
4
+
5
+ AUTHORS:
6
+
7
+ - William Stein
8
+
9
+ - William Stein (2006-04-26): added workaround for Windows where most
10
+ users' home directory has a space in it.
11
+
12
+ - Robert Bradshaw (2007-09-20): Ellipsis range/iterator.
13
+
14
+ TESTS:
15
+
16
+ The following test, verifying that :issue:`16181` has been resolved, needs
17
+ to stay at the beginning of this file so that its context is not
18
+ poisoned by other tests::
19
+
20
+ sage: sage.misc.misc.inject_variable('a', 0)
21
+ sage: a
22
+ 0
23
+
24
+ Check the fix from :issue:`8323`::
25
+
26
+ sage: 'name' in globals()
27
+ False
28
+ sage: 'func' in globals()
29
+ False
30
+ """
31
+
32
+ # ****************************************************************************
33
+ # Copyright (C) 2006 William Stein <wstein@gmail.com>
34
+ #
35
+ # This program is free software: you can redistribute it and/or modify
36
+ # it under the terms of the GNU General Public License as published by
37
+ # the Free Software Foundation, either version 2 of the License, or
38
+ # (at your option) any later version.
39
+ # https://www.gnu.org/licenses/
40
+ # ****************************************************************************
41
+
42
+ import contextlib
43
+ import functools
44
+ import os
45
+ import pdb
46
+ import sys
47
+ import warnings
48
+
49
+ from sage.env import DOT_SAGE, HOSTNAME
50
+ from sage.misc.lazy_import import lazy_import
51
+
52
+ lazy_import("sage.combinat.subset", ["powerset", "subsets", "uniq"],
53
+ deprecation=35564)
54
+
55
+ lazy_import(
56
+ "sage.misc.timing", ["cputime", "GlobalCputime", "walltime"],
57
+ deprecation=35816
58
+ )
59
+
60
+ LOCAL_IDENTIFIER = '%s.%s' % (HOSTNAME, os.getpid())
61
+
62
+ #################################################################
63
+ # File and directory utilities
64
+ #################################################################
65
+
66
+ # We create the DOT_SAGE directory (if it does not exist yet; note in particular
67
+ # that it may already have been created by the bin/sage script) with
68
+ # restrictive permissions, since otherwise possibly just anybody can easily see
69
+ # every command you type.
70
+
71
+ os.makedirs(DOT_SAGE, mode=0o700, exist_ok=True)
72
+
73
+
74
+ def try_read(obj, splitlines=False):
75
+ r"""
76
+ Determine if a given object is a readable file-like object and if so
77
+ read and return its contents.
78
+
79
+ That is, the object has a callable method named ``read()`` which takes
80
+ no arguments (except ``self``) then the method is executed and the
81
+ contents are returned.
82
+
83
+ Alternatively, if the ``splitlines=True`` is given, first ``splitlines()``
84
+ is tried, then if that fails ``read().splitlines()``.
85
+
86
+ If either method fails, ``None`` is returned.
87
+
88
+ INPUT:
89
+
90
+ - ``obj`` -- typically a `file` or `io.BaseIO` object, but any other
91
+ object with a ``read()`` method is accepted
92
+
93
+ - ``splitlines`` -- boolean (default: ``False``); if ``True``, return a
94
+ list of lines instead of a string
95
+
96
+ EXAMPLES::
97
+
98
+ sage: import io
99
+ sage: filename = tmp_filename()
100
+ sage: from sage.misc.misc import try_read
101
+ sage: with open(filename, 'w') as fobj:
102
+ ....: _ = fobj.write('a\nb\nc')
103
+ sage: with open(filename) as fobj:
104
+ ....: print(try_read(fobj))
105
+ a
106
+ b
107
+ c
108
+ sage: with open(filename) as fobj:
109
+ ....: try_read(fobj, splitlines=True)
110
+ ['a\n', 'b\n', 'c']
111
+
112
+ The following example is identical to the above example on Python 3,
113
+ but different on Python 2 where ``open != io.open``::
114
+
115
+ sage: with io.open(filename) as fobj:
116
+ ....: print(try_read(fobj))
117
+ a
118
+ b
119
+ c
120
+
121
+ I/O buffers::
122
+
123
+ sage: buf = io.StringIO('a\nb\nc')
124
+ sage: print(try_read(buf))
125
+ a
126
+ b
127
+ c
128
+ sage: _ = buf.seek(0); try_read(buf, splitlines=True)
129
+ ['a\n', 'b\n', 'c']
130
+ sage: buf = io.BytesIO(b'a\nb\nc')
131
+ sage: try_read(buf) == b'a\nb\nc'
132
+ True
133
+ sage: _ = buf.seek(0)
134
+ sage: try_read(buf, splitlines=True) == [b'a\n', b'b\n', b'c']
135
+ True
136
+
137
+ Custom readable::
138
+
139
+ sage: class MyFile():
140
+ ....: def read(self): return 'Hello world!'
141
+ sage: try_read(MyFile())
142
+ 'Hello world!'
143
+ sage: try_read(MyFile(), splitlines=True)
144
+ ['Hello world!']
145
+
146
+ Not readable::
147
+
148
+ sage: try_read(1) is None
149
+ True
150
+ """
151
+
152
+ if splitlines:
153
+ try:
154
+ return obj.readlines()
155
+ except (AttributeError, TypeError):
156
+ pass
157
+
158
+ try:
159
+ data = obj.read()
160
+ except (AttributeError, TypeError):
161
+ return
162
+
163
+ if splitlines:
164
+ try:
165
+ data = data.splitlines()
166
+ except (AttributeError, TypeError):
167
+ # Not a string??
168
+ data = [data]
169
+
170
+ return data
171
+
172
+
173
+ try:
174
+ # Create the matplotlib config directory.
175
+ os.makedirs(os.environ["MPLCONFIGDIR"], exist_ok=True)
176
+ except KeyError:
177
+ pass
178
+
179
+
180
+ def exactly_one_is_true(iterable):
181
+ r"""
182
+ Return whether exactly one element of ``iterable`` evaluates ``True``.
183
+
184
+ INPUT:
185
+
186
+ - ``iterable`` -- an iterable object
187
+
188
+ OUTPUT: boolean
189
+
190
+ .. NOTE::
191
+
192
+ The implementation is suggested by
193
+ `stackoverflow entry <https://stackoverflow.com/a/16801605/1052778>`_.
194
+
195
+ EXAMPLES::
196
+
197
+ sage: from sage.misc.misc import exactly_one_is_true
198
+ sage: exactly_one_is_true([])
199
+ False
200
+ sage: exactly_one_is_true([True])
201
+ True
202
+ sage: exactly_one_is_true([False])
203
+ False
204
+ sage: exactly_one_is_true([True, True])
205
+ False
206
+ sage: exactly_one_is_true([False, True])
207
+ True
208
+ sage: exactly_one_is_true([True, False, True])
209
+ False
210
+ sage: exactly_one_is_true([False, True, False])
211
+ True
212
+ """
213
+ it = iter(iterable)
214
+ return any(it) and not any(it)
215
+
216
+
217
+ def strunc(s, n=60):
218
+ """
219
+ Truncate at first space after position n, adding '...' if
220
+ nontrivial truncation.
221
+ """
222
+ n = int(n)
223
+ s = str(s)
224
+ if len(s) > n:
225
+ i = n
226
+ while i < len(s) and s[i] != ' ':
227
+ i += 1
228
+ return s[:i] + " ..."
229
+ return s
230
+
231
+
232
+ def newton_method_sizes(N):
233
+ r"""
234
+ Return a sequence of integers
235
+ `1 = a_1 \leq a_2 \leq \cdots \leq a_n = N` such that
236
+ `a_j = \lceil a_{j+1} / 2 \rceil` for all `j`.
237
+
238
+ This is useful for Newton-style algorithms that double the
239
+ precision at each stage. For example if you start at precision 1
240
+ and want an answer to precision 17, then it's better to use the
241
+ intermediate stages 1, 2, 3, 5, 9, 17 than to use 1, 2, 4, 8, 16,
242
+ 17.
243
+
244
+ INPUT:
245
+
246
+ - ``N`` -- positive integer
247
+
248
+ EXAMPLES::
249
+
250
+ sage: newton_method_sizes(17)
251
+ [1, 2, 3, 5, 9, 17]
252
+ sage: newton_method_sizes(16)
253
+ [1, 2, 4, 8, 16]
254
+ sage: newton_method_sizes(1)
255
+ [1]
256
+
257
+ AUTHORS:
258
+
259
+ - David Harvey (2006-09-09)
260
+ """
261
+
262
+ N = int(N)
263
+ if N < 1:
264
+ raise ValueError("N (={}) must be a positive integer".format(N))
265
+
266
+ output = []
267
+ while N > 1:
268
+ output.append(N)
269
+ N = (N + 1) >> 1
270
+
271
+ output.append(1)
272
+ output.reverse()
273
+ return output
274
+
275
+
276
+ #################################################################
277
+ # Generally useful
278
+ #################################################################
279
+
280
+
281
+ def compose(f, g):
282
+ r"""
283
+ Return the composition of one-variable functions: `f \circ g`.
284
+
285
+ See also :func:`nest()`
286
+
287
+ INPUT:
288
+
289
+ - ``f`` -- a function of one variable
290
+ - ``g`` -- another function of one variable
291
+
292
+ OUTPUT: a function, such that compose(f,g)(x) = f(g(x))
293
+
294
+ EXAMPLES::
295
+
296
+ sage: def g(x): return 3*x
297
+ sage: def f(x): return x + 1
298
+ sage: h1 = compose(f, g)
299
+ sage: h2 = compose(g, f)
300
+ sage: _ = var('x') # needs sage.symbolic
301
+ sage: h1(x) # needs sage.symbolic
302
+ 3*x + 1
303
+ sage: h2(x) # needs sage.symbolic
304
+ 3*x + 3
305
+
306
+ ::
307
+
308
+ sage: _ = function('f g') # needs sage.symbolic
309
+ sage: _ = var('x') # needs sage.symbolic
310
+ sage: compose(f, g)(x) # needs sage.symbolic
311
+ f(g(x))
312
+ """
313
+ return lambda x: f(g(x))
314
+
315
+
316
+ def nest(f, n, x):
317
+ """
318
+ Return `f(f(...f(x)...))`, where the composition occurs n times.
319
+
320
+ See also :func:`compose()` and :func:`self_compose()`
321
+
322
+ INPUT:
323
+
324
+ - ``f`` -- a function of one variable
325
+ - ``n`` -- nonnegative integer
326
+ - ``x`` -- any input for `f`
327
+
328
+ OUTPUT: `f(f(...f(x)...))`, where the composition occurs n times
329
+
330
+ EXAMPLES::
331
+
332
+ sage: def f(x): return x^2 + 1
333
+ sage: x = var('x') # needs sage.symbolic
334
+ sage: nest(f, 3, x) # needs sage.symbolic
335
+ ((x^2 + 1)^2 + 1)^2 + 1
336
+
337
+ ::
338
+
339
+ sage: _ = function('f') # needs sage.symbolic
340
+ sage: _ = var('x') # needs sage.symbolic
341
+ sage: nest(f, 10, x) # needs sage.symbolic
342
+ f(f(f(f(f(f(f(f(f(f(x))))))))))
343
+
344
+ ::
345
+
346
+ sage: _ = function('f') # needs sage.symbolic
347
+ sage: _ = var('x') # needs sage.symbolic
348
+ sage: nest(f, 0, x) # needs sage.symbolic
349
+ x
350
+ """
351
+ from sage.rings.integer import Integer
352
+
353
+ n = Integer(n)
354
+
355
+ if n < 0:
356
+ raise ValueError("n must be a nonnegative integer, not {}.".format(n))
357
+
358
+ for i in range(n):
359
+ x = f(x)
360
+ return x
361
+
362
+
363
+ #################################################################
364
+ # The A \ b operator has been removed after issue #36394
365
+ #################################################################
366
+
367
+ #################################################################
368
+ # is_iterator function
369
+ #################################################################
370
+ def is_iterator(it) -> bool:
371
+ """
372
+ Test if it is an iterator.
373
+
374
+ The mantra ``if hasattr(it, 'next')`` was used to tests if ``it`` is an
375
+ iterator. This is not quite correct since ``it`` could have a ``next``
376
+ methods with a different semantic.
377
+
378
+ EXAMPLES::
379
+
380
+ sage: it = iter([1,2,3])
381
+ sage: is_iterator(it)
382
+ True
383
+
384
+ sage: class wrong():
385
+ ....: def __init__(self): self.n = 5
386
+ ....: def __next__(self):
387
+ ....: self.n -= 1
388
+ ....: if self.n == 0: raise StopIteration
389
+ ....: return self.n
390
+ sage: x = wrong()
391
+ sage: is_iterator(x)
392
+ False
393
+ sage: list(x)
394
+ Traceback (most recent call last):
395
+ ...
396
+ TypeError: 'wrong' object is not iterable
397
+
398
+ sage: class good(wrong):
399
+ ....: def __iter__(self): return self
400
+ sage: x = good()
401
+ sage: is_iterator(x)
402
+ True
403
+ sage: list(x)
404
+ [4, 3, 2, 1]
405
+
406
+ sage: P = Partitions(3)
407
+ sage: is_iterator(P)
408
+ False
409
+ sage: is_iterator(iter(P))
410
+ True
411
+ """
412
+ # see issue #7398 for a discussion
413
+ try:
414
+ return it is iter(it)
415
+ except Exception:
416
+ return False
417
+
418
+
419
+ #################################################################
420
+ # Useful but hard to classify
421
+ #################################################################
422
+
423
+
424
+ def random_sublist(X, s):
425
+ """
426
+ Return a pseudo-random sublist of the list X where the probability
427
+ of including a particular element is s.
428
+
429
+ INPUT:
430
+
431
+ - ``X`` -- list
432
+
433
+ - ``s`` -- floating point number between 0 and 1
434
+
435
+ OUTPUT: list
436
+
437
+ EXAMPLES::
438
+
439
+ sage: from sage.misc.misc import is_sublist
440
+ sage: S = [1,7,3,4,18]
441
+ sage: sublist = random_sublist(S, 0.5); sublist # random
442
+ [1, 3, 4]
443
+ sage: is_sublist(sublist, S)
444
+ True
445
+ sage: sublist = random_sublist(S, 0.5); sublist # random
446
+ [1, 3]
447
+ sage: is_sublist(sublist, S)
448
+ True
449
+ """
450
+ import sage.misc.prandom as random
451
+
452
+ return [a for a in X if random.random() <= s]
453
+
454
+
455
+ def is_sublist(X, Y) -> bool:
456
+ """
457
+ Test whether ``X`` is a sublist of ``Y``.
458
+
459
+ EXAMPLES::
460
+
461
+ sage: from sage.misc.misc import is_sublist
462
+ sage: S = [1, 7, 3, 4, 18]
463
+ sage: is_sublist([1, 7], S)
464
+ True
465
+ sage: is_sublist([1, 3, 4], S)
466
+ True
467
+ sage: is_sublist([1, 4, 3], S)
468
+ False
469
+ sage: is_sublist(S, S)
470
+ True
471
+ """
472
+ X_i = 0
473
+ for Y_i, y in enumerate(Y):
474
+ if X_i == len(X):
475
+ return True
476
+ if y == X[X_i]:
477
+ X_i += 1
478
+ return X_i == len(X)
479
+
480
+
481
+ def some_tuples(elements, repeat, bound, max_samples=None):
482
+ r"""
483
+ Return an iterator over at most ``bound`` number of ``repeat``-tuples of
484
+ ``elements``.
485
+
486
+ INPUT:
487
+
488
+ - ``elements`` -- an iterable
489
+ - ``repeat`` -- integer (default: ``None``); the length of the tuples to be returned.
490
+ If ``None``, just returns entries from ``elements``.
491
+ - ``bound`` -- the maximum number of tuples returned (ignored if ``max_samples`` given)
492
+ - ``max_samples`` -- nonnegative integer (default: ``None``); if given,
493
+ then a sample of the possible tuples will be returned,
494
+ instead of the first few in the standard order
495
+
496
+ OUTPUT:
497
+
498
+ If ``max_samples`` is not provided, an iterator over the first
499
+ ``bound`` tuples of length ``repeat``, in the standard nested-for-loop order.
500
+
501
+ If ``max_samples`` is provided, a list of at most ``max_samples`` tuples,
502
+ sampled uniformly from the possibilities. In this case, ``elements``
503
+ must be finite.
504
+
505
+ TESTS::
506
+
507
+ sage: from sage.misc.misc import some_tuples
508
+ sage: l = some_tuples([0,1,2,3], 2, 3)
509
+ sage: l
510
+ <itertools.islice object at ...>
511
+ sage: len(list(l))
512
+ 3
513
+
514
+ sage: l = some_tuples(range(50), 3, 10)
515
+ sage: len(list(l))
516
+ 10
517
+
518
+ sage: l = some_tuples(range(3), 2, None, max_samples=10)
519
+ sage: len(list(l))
520
+ 9
521
+ """
522
+ if max_samples is None:
523
+ from itertools import islice, product
524
+
525
+ P = elements if repeat is None else product(elements, repeat=repeat)
526
+ return islice(P, int(bound))
527
+ else:
528
+ if not (hasattr(elements, '__len__') and hasattr(elements, '__getitem__')):
529
+ elements = list(elements)
530
+ n = len(elements)
531
+ N = n if repeat is None else n**repeat
532
+ if N <= max_samples:
533
+ from itertools import product
534
+
535
+ return elements if repeat is None else product(elements, repeat=repeat)
536
+ return _some_tuples_sampling(elements, repeat, max_samples, n)
537
+
538
+
539
+ def _some_tuples_sampling(elements, repeat, max_samples, n):
540
+ """
541
+ Internal function for :func:`some_tuples`.
542
+
543
+ TESTS::
544
+
545
+ sage: from sage.misc.misc import _some_tuples_sampling
546
+ sage: l = list(_some_tuples_sampling(range(3), 3, 2, 3))
547
+ sage: len(l)
548
+ 2
549
+ sage: all(len(tup) == 3 for tup in l)
550
+ True
551
+ sage: all(el in range(3) for tup in l for el in tup)
552
+ True
553
+ sage: l = list(_some_tuples_sampling(range(20), None, 4, 20))
554
+ sage: len(l)
555
+ 4
556
+ sage: all(el in range(20) for el in l)
557
+ True
558
+ """
559
+ from sage.rings.integer import Integer
560
+ import sage.misc.prandom as random
561
+
562
+ N = n if repeat is None else n**repeat
563
+ # We sample on range(N) and create tuples manually since we don't want to create the list of all possible tuples in memory
564
+ for a in random.sample(range(N), max_samples):
565
+ if repeat is None:
566
+ yield elements[a]
567
+ else:
568
+ yield tuple(elements[j] for j in Integer(a).digits(n, padto=repeat))
569
+
570
+
571
+ #################################################################
572
+ # Misc.
573
+ #################################################################
574
+
575
+
576
+ def exists(S, P):
577
+ """
578
+ If S contains an element x such that P(x) is ``True``, this function
579
+ returns ``True`` and the element x. Otherwise it returns ``False`` and
580
+ None.
581
+
582
+ Note that this function is NOT suitable to be used in an
583
+ if-statement or in any place where a boolean expression is
584
+ expected. For those situations, use the Python built-in
585
+
586
+ any(P(x) for x in S)
587
+
588
+ INPUT:
589
+
590
+ - ``S`` -- object (that supports enumeration)
591
+
592
+ - ``P`` -- function that returns ``True`` or ``False``
593
+
594
+ OUTPUT:
595
+
596
+ - ``bool`` -- whether or not P is ``True`` for some element
597
+ x of S
598
+
599
+ - ``object`` -- x
600
+
601
+ EXAMPLES: lambda functions are very useful when using the exists
602
+ function::
603
+
604
+ sage: exists([1,2,5], lambda x : x > 7)
605
+ (False, None)
606
+ sage: exists([1,2,5], lambda x : x > 3)
607
+ (True, 5)
608
+
609
+ The following example is similar to one in the MAGMA handbook. We
610
+ check whether certain integers are a sum of two (small) cubes::
611
+
612
+ sage: cubes = [t**3 for t in range(-10,11)]
613
+ sage: exists([(x,y) for x in cubes for y in cubes], lambda v : v[0]+v[1] == 218)
614
+ (True, (-125, 343))
615
+ sage: exists([(x,y) for x in cubes for y in cubes], lambda v : v[0]+v[1] == 219)
616
+ (False, None)
617
+ """
618
+ for x in S:
619
+ if P(x):
620
+ return True, x
621
+ return False, None
622
+
623
+
624
+ def forall(S, P):
625
+ """
626
+ If `P(x)` is true every x in S, return ``True`` and ``None``. If there is
627
+ some element x in S such that P is not ``True``, return ``False`` and `x`.
628
+
629
+ Note that this function is NOT suitable to be used in an
630
+ if-statement or in any place where a boolean expression is
631
+ expected. For those situations, use the Python built-in
632
+
633
+ all(P(x) for x in S)
634
+
635
+ INPUT:
636
+
637
+ - ``S`` -- object (that supports enumeration)
638
+
639
+ - ``P`` -- function that returns ``True`` or ``False``
640
+
641
+ OUTPUT:
642
+
643
+ - ``bool`` -- whether or not P is ``True`` for all elements
644
+ of S
645
+
646
+ - ``object`` -- x
647
+
648
+ EXAMPLES: lambda functions are very useful when using the forall
649
+ function. As a toy example we test whether certain integers are
650
+ greater than 3.
651
+
652
+ ::
653
+
654
+ sage: forall([1,2,5], lambda x : x > 3)
655
+ (False, 1)
656
+ sage: forall([1,2,5], lambda x : x > 0)
657
+ (True, None)
658
+
659
+ Next we ask whether every positive integer less than 100 is a
660
+ product of at most 2 prime factors::
661
+
662
+ sage: forall(range(1,100), lambda n : len(factor(n)) <= 2)
663
+ (False, 30)
664
+
665
+ The answer is no, and 30 is a counterexample. However, every
666
+ positive integer 100 is a product of at most 3 primes.
667
+
668
+ ::
669
+
670
+ sage: forall(range(1,100), lambda n : len(factor(n)) <= 3)
671
+ (True, None)
672
+ """
673
+ for x in S:
674
+ if not P(x):
675
+ return False, x
676
+ return True, None
677
+
678
+
679
+ #################################################################
680
+ # debug tracing
681
+ #################################################################
682
+ set_trace = pdb.set_trace
683
+
684
+
685
+ #################################################################
686
+ # Word wrap lines
687
+ #################################################################
688
+ def word_wrap(s, ncols=85):
689
+ t = []
690
+ if ncols == 0:
691
+ return s
692
+ for x in s.split('\n'):
693
+ if not x or x.lstrip()[:5] == 'sage:':
694
+ t.append(x)
695
+ continue
696
+ while len(x) > ncols:
697
+ k = ncols
698
+ while k > 0 and x[k] != ' ':
699
+ k -= 1
700
+ if k == 0:
701
+ k = ncols
702
+ end = '\\'
703
+ else:
704
+ end = ''
705
+ t.append(x[:k] + end)
706
+ x = x[k:]
707
+ k = 0
708
+ while k < len(x) and x[k] == ' ':
709
+ k += 1
710
+ x = x[k:]
711
+ t.append(x)
712
+ return '\n'.join(t)
713
+
714
+
715
+ def pad_zeros(s, size=3):
716
+ """
717
+ EXAMPLES::
718
+
719
+ sage: pad_zeros(100)
720
+ '100'
721
+ sage: pad_zeros(10)
722
+ '010'
723
+ sage: pad_zeros(10, 5)
724
+ '00010'
725
+ sage: pad_zeros(389, 5)
726
+ '00389'
727
+ sage: pad_zeros(389, 10)
728
+ '0000000389'
729
+ """
730
+ return "0" * (size - len(str(s))) + str(s)
731
+
732
+
733
+ def is_in_string(line, pos):
734
+ r"""
735
+ Return ``True`` if the character at position ``pos`` in ``line`` occurs
736
+ within a string.
737
+
738
+ EXAMPLES::
739
+
740
+ sage: from sage.misc.misc import is_in_string
741
+ sage: line = 'test(\'#\')'
742
+ sage: is_in_string(line, line.rfind('#'))
743
+ True
744
+ sage: is_in_string(line, line.rfind(')'))
745
+ False
746
+ """
747
+ i = 0
748
+ in_single_quote = False
749
+ in_double_quote = False
750
+ in_triple_quote = False
751
+
752
+ def in_quote():
753
+ return in_single_quote or in_double_quote or in_triple_quote
754
+
755
+ while i < pos:
756
+ # Update quote parsing
757
+ # We only do this if this quote isn't backquoted itself,
758
+ # which is the case if the previous character isn't
759
+ # a backslash, or it is but both previous characters
760
+ # are backslashes.
761
+ if line[i - 1 : i] != '\\' or line[i - 2 : i] == '\\\\':
762
+ if line[i : i + 3] in ['"""', "'''"]:
763
+ if not in_quote():
764
+ in_triple_quote = True
765
+ elif in_triple_quote:
766
+ in_triple_quote = False
767
+ elif line[i] == "'":
768
+ if not in_quote():
769
+ in_single_quote = True
770
+ elif in_single_quote:
771
+ in_single_quote = False
772
+ elif line[i] == '"':
773
+ if not in_quote():
774
+ in_double_quote = True
775
+ elif in_double_quote:
776
+ in_double_quote = False
777
+ i += 1
778
+ return in_quote()
779
+
780
+
781
+ def get_main_globals():
782
+ """
783
+ Return the main global namespace.
784
+
785
+ EXAMPLES::
786
+
787
+ sage: from sage.misc.misc import get_main_globals
788
+ sage: G = get_main_globals()
789
+ sage: bla = 1
790
+ sage: G['bla']
791
+ 1
792
+ sage: bla = 2
793
+ sage: G['bla']
794
+ 2
795
+ sage: G['ble'] = 5
796
+ sage: ble
797
+ 5
798
+
799
+ This is analogous to :func:`globals`, except that it can be called
800
+ from any function, even if it is in a Python module::
801
+
802
+ sage: def f():
803
+ ....: G = get_main_globals()
804
+ ....: assert G['bli'] == 14
805
+ ....: G['blo'] = 42
806
+ sage: bli = 14
807
+ sage: f()
808
+ sage: blo
809
+ 42
810
+
811
+ ALGORITHM:
812
+
813
+ The main global namespace is discovered by going up the frame
814
+ stack until the frame for the :mod:`__main__` module is found.
815
+ Should this frame not be found (this should not occur in normal
816
+ operation), an exception "ValueError: call stack is not deep
817
+ enough" will be raised by ``_getframe``.
818
+
819
+ See :meth:`inject_variable_test` for a real test that this works
820
+ within deeply nested calls in a function defined in a Python
821
+ module.
822
+ """
823
+ import sys
824
+
825
+ depth = 0
826
+ while True:
827
+ G = sys._getframe(depth).f_globals
828
+ if G.get("__name__", None) == "__main__":
829
+ break
830
+ depth += 1
831
+ return G
832
+
833
+
834
+ def inject_variable(name, value, warn=True):
835
+ """
836
+ Inject a variable into the main global namespace.
837
+
838
+ INPUT:
839
+
840
+ - ``name`` -- string
841
+ - ``value`` -- anything
842
+ - ``warn`` -- boolean (default: ``False``)
843
+
844
+ EXAMPLES::
845
+
846
+ sage: from sage.misc.misc import inject_variable
847
+ sage: inject_variable("a", 314)
848
+ sage: a
849
+ 314
850
+
851
+ A warning is issued the first time an existing value is overwritten::
852
+
853
+ sage: inject_variable("a", 271)
854
+ doctest:...: RuntimeWarning: redefining global value `a`
855
+ sage: a
856
+ 271
857
+ sage: inject_variable("a", 272)
858
+ sage: a
859
+ 272
860
+
861
+ That's because warn seem to not reissue twice the same warning::
862
+
863
+ sage: from warnings import warn
864
+ sage: warn("blah")
865
+ doctest:...: UserWarning: blah
866
+ sage: warn("blah")
867
+
868
+ Warnings can be disabled::
869
+
870
+ sage: b = 3
871
+ sage: inject_variable("b", 42, warn=False)
872
+ sage: b
873
+ 42
874
+
875
+ Use with care!
876
+ """
877
+ assert isinstance(name, str)
878
+ # Using globals() does not work, even in Cython, because
879
+ # inject_variable is called not only from the interpreter, but
880
+ # also from functions in various modules.
881
+ G = get_main_globals()
882
+ if name in G and warn:
883
+ warnings.warn(
884
+ "redefining global value `%s`" % name, RuntimeWarning, stacklevel=2
885
+ )
886
+ G[name] = value
887
+
888
+
889
+ def inject_variable_test(name, value, depth):
890
+ """
891
+ A function for testing deep calls to ``inject_variable``.
892
+
893
+ EXAMPLES::
894
+
895
+ sage: from sage.misc.misc import inject_variable_test
896
+ sage: inject_variable_test("a0", 314, 0)
897
+ sage: a0
898
+ 314
899
+ sage: inject_variable_test("a1", 314, 1)
900
+ sage: a1
901
+ 314
902
+ sage: inject_variable_test("a2", 314, 2)
903
+ sage: a2
904
+ 314
905
+ sage: inject_variable_test("a2", 271, 2)
906
+ doctest:...: RuntimeWarning: redefining global value `a2`
907
+ sage: a2
908
+ 271
909
+ """
910
+ if depth == 0:
911
+ inject_variable(name, value)
912
+ else:
913
+ inject_variable_test(name, value, depth - 1)
914
+
915
+
916
+ # from https://stackoverflow.com/questions/4103773/efficient-way-of-having-a-function-only-execute-once-in-a-loop
917
+ def run_once(func):
918
+ """
919
+ Run a function (successfully) only once.
920
+
921
+ The running can be reset by setting the ``has_run`` attribute to False
922
+
923
+ TESTS::
924
+
925
+ sage: from sage.repl.ipython_extension import run_once
926
+ sage: @run_once
927
+ ....: def foo(work):
928
+ ....: if work:
929
+ ....: return 'foo worked'
930
+ ....: raise RuntimeError("foo didn't work")
931
+ sage: foo(False)
932
+ Traceback (most recent call last):
933
+ ...
934
+ RuntimeError: foo didn't work
935
+ sage: foo(True)
936
+ 'foo worked'
937
+ sage: foo(False)
938
+ sage: foo(True)
939
+ """
940
+
941
+ @functools.wraps(func)
942
+ def wrapper(*args, **kwargs):
943
+ if not wrapper.has_run:
944
+ result = func(*args, **kwargs)
945
+ wrapper.has_run = True
946
+ return result
947
+
948
+ wrapper.has_run = False
949
+ return wrapper
950
+
951
+
952
+ @contextlib.contextmanager
953
+ def increase_recursion_limit(increment):
954
+ r"""
955
+ Context manager to temporarily change the Python maximum recursion depth.
956
+
957
+ INPUT:
958
+
959
+ - ``increment`` -- increment to add to the current limit
960
+
961
+ EXAMPLES::
962
+
963
+ sage: from sage.misc.misc import increase_recursion_limit
964
+ sage: def rec(n): None if n == 0 else rec(n-1)
965
+ sage: rec(10000)
966
+ Traceback (most recent call last):
967
+ ...
968
+ RecursionError: maximum recursion depth exceeded...
969
+ sage: with increase_recursion_limit(10000): rec(10000)
970
+ sage: rec(10000)
971
+ Traceback (most recent call last):
972
+ ...
973
+ RecursionError: maximum recursion depth exceeded...
974
+ """
975
+ old_limit = sys.getrecursionlimit()
976
+ sys.setrecursionlimit(old_limit + increment)
977
+ try:
978
+ yield
979
+ finally:
980
+ sys.setrecursionlimit(old_limit)