passagemath-objects 10.6.46__cp314-cp314t-macosx_13_0_x86_64.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.

Files changed (280) hide show
  1. passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_objects/__init__.py +3 -0
  3. passagemath_objects-10.6.46.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.46.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.46.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.46.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_objects.py +37 -0
  8. sage/arith/all__sagemath_objects.py +5 -0
  9. sage/arith/long.pxd +411 -0
  10. sage/arith/numerical_approx.cpython-314t-darwin.so +0 -0
  11. sage/arith/numerical_approx.pxd +35 -0
  12. sage/arith/numerical_approx.pyx +75 -0
  13. sage/arith/power.cpython-314t-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-314t-darwin.so +0 -0
  17. sage/categories/action.pxd +29 -0
  18. sage/categories/action.pyx +641 -0
  19. sage/categories/algebra_functor.py +745 -0
  20. sage/categories/all__sagemath_objects.py +33 -0
  21. sage/categories/basic.py +62 -0
  22. sage/categories/cartesian_product.py +295 -0
  23. sage/categories/category.py +3401 -0
  24. sage/categories/category_cy_helper.cpython-314t-darwin.so +0 -0
  25. sage/categories/category_cy_helper.pxd +8 -0
  26. sage/categories/category_cy_helper.pyx +322 -0
  27. sage/categories/category_singleton.cpython-314t-darwin.so +0 -0
  28. sage/categories/category_singleton.pxd +3 -0
  29. sage/categories/category_singleton.pyx +342 -0
  30. sage/categories/category_types.py +637 -0
  31. sage/categories/category_with_axiom.py +2876 -0
  32. sage/categories/covariant_functorial_construction.py +703 -0
  33. sage/categories/facade_sets.py +228 -0
  34. sage/categories/functor.cpython-314t-darwin.so +0 -0
  35. sage/categories/functor.pxd +7 -0
  36. sage/categories/functor.pyx +691 -0
  37. sage/categories/homset.py +1338 -0
  38. sage/categories/homsets.py +364 -0
  39. sage/categories/isomorphic_objects.py +73 -0
  40. sage/categories/map.cpython-314t-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-314t-darwin.so +0 -0
  44. sage/categories/morphism.pxd +14 -0
  45. sage/categories/morphism.pyx +895 -0
  46. sage/categories/objects.py +167 -0
  47. sage/categories/primer.py +1696 -0
  48. sage/categories/pushout.py +4834 -0
  49. sage/categories/quotients.py +64 -0
  50. sage/categories/realizations.py +200 -0
  51. sage/categories/sets_cat.py +3290 -0
  52. sage/categories/sets_with_partial_maps.py +52 -0
  53. sage/categories/subobjects.py +64 -0
  54. sage/categories/subquotients.py +21 -0
  55. sage/categories/with_realizations.py +311 -0
  56. sage/cpython/__init__.py +19 -0
  57. sage/cpython/_py2_random.py +619 -0
  58. sage/cpython/all.py +3 -0
  59. sage/cpython/atexit.cpython-314t-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-314t-darwin.so +0 -0
  64. sage/cpython/cython_metaclass.h +117 -0
  65. sage/cpython/cython_metaclass.pxd +3 -0
  66. sage/cpython/cython_metaclass.pyx +130 -0
  67. sage/cpython/debug.cpython-314t-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-314t-darwin.so +0 -0
  70. sage/cpython/dict_del_by_value.pxd +9 -0
  71. sage/cpython/dict_del_by_value.pyx +191 -0
  72. sage/cpython/dict_internal.h +245 -0
  73. sage/cpython/getattr.cpython-314t-darwin.so +0 -0
  74. sage/cpython/getattr.pxd +9 -0
  75. sage/cpython/getattr.pyx +439 -0
  76. sage/cpython/pycore_long.h +97 -0
  77. sage/cpython/pycore_long.pxd +10 -0
  78. sage/cpython/python_debug.h +44 -0
  79. sage/cpython/python_debug.pxd +47 -0
  80. sage/cpython/pyx_visit.h +13 -0
  81. sage/cpython/string.cpython-314t-darwin.so +0 -0
  82. sage/cpython/string.pxd +76 -0
  83. sage/cpython/string.pyx +34 -0
  84. sage/cpython/string_impl.h +60 -0
  85. sage/cpython/type.cpython-314t-darwin.so +0 -0
  86. sage/cpython/type.pxd +2 -0
  87. sage/cpython/type.pyx +40 -0
  88. sage/cpython/wrapperdescr.pxd +67 -0
  89. sage/ext/all__sagemath_objects.py +3 -0
  90. sage/ext/ccobject.h +64 -0
  91. sage/ext/cplusplus.pxd +17 -0
  92. sage/ext/mod_int.h +30 -0
  93. sage/ext/mod_int.pxd +24 -0
  94. sage/ext/stdsage.pxd +39 -0
  95. sage/groups/all__sagemath_objects.py +1 -0
  96. sage/groups/group.cpython-314t-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-314t-darwin.so +0 -0
  100. sage/groups/old.pxd +14 -0
  101. sage/groups/old.pyx +219 -0
  102. sage/libs/all__sagemath_objects.py +3 -0
  103. sage/libs/gmp/__init__.py +1 -0
  104. sage/libs/gmp/all.pxd +6 -0
  105. sage/libs/gmp/binop.pxd +23 -0
  106. sage/libs/gmp/misc.pxd +8 -0
  107. sage/libs/gmp/mpf.pxd +88 -0
  108. sage/libs/gmp/mpn.pxd +57 -0
  109. sage/libs/gmp/mpq.pxd +57 -0
  110. sage/libs/gmp/mpz.pxd +202 -0
  111. sage/libs/gmp/pylong.cpython-314t-darwin.so +0 -0
  112. sage/libs/gmp/pylong.pxd +12 -0
  113. sage/libs/gmp/pylong.pyx +150 -0
  114. sage/libs/gmp/random.pxd +25 -0
  115. sage/libs/gmp/randomize.pxd +59 -0
  116. sage/libs/gmp/types.pxd +53 -0
  117. sage/libs/gmpxx.pxd +19 -0
  118. sage/misc/abstract_method.py +276 -0
  119. sage/misc/all__sagemath_objects.py +43 -0
  120. sage/misc/bindable_class.py +253 -0
  121. sage/misc/c3_controlled.cpython-314t-darwin.so +0 -0
  122. sage/misc/c3_controlled.pxd +2 -0
  123. sage/misc/c3_controlled.pyx +1402 -0
  124. sage/misc/cachefunc.cpython-314t-darwin.so +0 -0
  125. sage/misc/cachefunc.pxd +43 -0
  126. sage/misc/cachefunc.pyx +3781 -0
  127. sage/misc/call.py +188 -0
  128. sage/misc/classcall_metaclass.cpython-314t-darwin.so +0 -0
  129. sage/misc/classcall_metaclass.pxd +14 -0
  130. sage/misc/classcall_metaclass.pyx +599 -0
  131. sage/misc/constant_function.cpython-314t-darwin.so +0 -0
  132. sage/misc/constant_function.pyx +130 -0
  133. sage/misc/decorators.py +747 -0
  134. sage/misc/fast_methods.cpython-314t-darwin.so +0 -0
  135. sage/misc/fast_methods.pxd +20 -0
  136. sage/misc/fast_methods.pyx +351 -0
  137. sage/misc/flatten.py +90 -0
  138. sage/misc/fpickle.cpython-314t-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-314t-darwin.so +0 -0
  141. sage/misc/function_mangling.pxd +11 -0
  142. sage/misc/function_mangling.pyx +308 -0
  143. sage/misc/inherit_comparison.cpython-314t-darwin.so +0 -0
  144. sage/misc/inherit_comparison.pxd +5 -0
  145. sage/misc/inherit_comparison.pyx +105 -0
  146. sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-314t-darwin.so +0 -0
  149. sage/misc/lazy_attribute.pyx +607 -0
  150. sage/misc/lazy_format.py +135 -0
  151. sage/misc/lazy_import.cpython-314t-darwin.so +0 -0
  152. sage/misc/lazy_import.pyx +1299 -0
  153. sage/misc/lazy_import_cache.py +36 -0
  154. sage/misc/lazy_list.cpython-314t-darwin.so +0 -0
  155. sage/misc/lazy_list.pxd +19 -0
  156. sage/misc/lazy_list.pyx +1187 -0
  157. sage/misc/lazy_string.cpython-314t-darwin.so +0 -0
  158. sage/misc/lazy_string.pxd +7 -0
  159. sage/misc/lazy_string.pyx +546 -0
  160. sage/misc/misc.py +1066 -0
  161. sage/misc/misc_c.cpython-314t-darwin.so +0 -0
  162. sage/misc/misc_c.pxd +3 -0
  163. sage/misc/misc_c.pyx +766 -0
  164. sage/misc/namespace_package.py +37 -0
  165. sage/misc/nested_class.cpython-314t-darwin.so +0 -0
  166. sage/misc/nested_class.pxd +3 -0
  167. sage/misc/nested_class.pyx +394 -0
  168. sage/misc/persist.cpython-314t-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-314t-darwin.so +0 -0
  172. sage/misc/randstate.pxd +30 -0
  173. sage/misc/randstate.pyx +1059 -0
  174. sage/misc/repr.py +203 -0
  175. sage/misc/reset.cpython-314t-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
  178. sage/misc/sage_ostools.pyx +323 -0
  179. sage/misc/sage_timeit.py +275 -0
  180. sage/misc/sage_timeit_class.cpython-314t-darwin.so +0 -0
  181. sage/misc/sage_timeit_class.pyx +120 -0
  182. sage/misc/sage_unittest.py +637 -0
  183. sage/misc/sageinspect.py +2768 -0
  184. sage/misc/session.cpython-314t-darwin.so +0 -0
  185. sage/misc/session.pyx +392 -0
  186. sage/misc/superseded.py +557 -0
  187. sage/misc/test_nested_class.py +228 -0
  188. sage/misc/timing.py +264 -0
  189. sage/misc/unknown.py +222 -0
  190. sage/misc/verbose.py +253 -0
  191. sage/misc/weak_dict.cpython-314t-darwin.so +0 -0
  192. sage/misc/weak_dict.pxd +15 -0
  193. sage/misc/weak_dict.pyx +1231 -0
  194. sage/modules/all__sagemath_objects.py +1 -0
  195. sage/modules/module.cpython-314t-darwin.so +0 -0
  196. sage/modules/module.pxd +5 -0
  197. sage/modules/module.pyx +329 -0
  198. sage/rings/all__sagemath_objects.py +3 -0
  199. sage/rings/integer_fake.h +22 -0
  200. sage/rings/integer_fake.pxd +55 -0
  201. sage/sets/all__sagemath_objects.py +3 -0
  202. sage/sets/pythonclass.cpython-314t-darwin.so +0 -0
  203. sage/sets/pythonclass.pxd +9 -0
  204. sage/sets/pythonclass.pyx +247 -0
  205. sage/structure/__init__.py +4 -0
  206. sage/structure/all.py +30 -0
  207. sage/structure/category_object.cpython-314t-darwin.so +0 -0
  208. sage/structure/category_object.pxd +28 -0
  209. sage/structure/category_object.pyx +1087 -0
  210. sage/structure/coerce.cpython-314t-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-314t-darwin.so +0 -0
  214. sage/structure/coerce_actions.pxd +27 -0
  215. sage/structure/coerce_actions.pyx +988 -0
  216. sage/structure/coerce_dict.cpython-314t-darwin.so +0 -0
  217. sage/structure/coerce_dict.pxd +51 -0
  218. sage/structure/coerce_dict.pyx +1557 -0
  219. sage/structure/coerce_exceptions.py +23 -0
  220. sage/structure/coerce_maps.cpython-314t-darwin.so +0 -0
  221. sage/structure/coerce_maps.pxd +28 -0
  222. sage/structure/coerce_maps.pyx +718 -0
  223. sage/structure/debug_options.cpython-314t-darwin.so +0 -0
  224. sage/structure/debug_options.pxd +6 -0
  225. sage/structure/debug_options.pyx +54 -0
  226. sage/structure/dynamic_class.py +541 -0
  227. sage/structure/element.cpython-314t-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-314t-darwin.so +0 -0
  231. sage/structure/element_wrapper.pxd +12 -0
  232. sage/structure/element_wrapper.pyx +582 -0
  233. sage/structure/factorization.py +1422 -0
  234. sage/structure/factorization_integer.py +105 -0
  235. sage/structure/factory.cpython-314t-darwin.so +0 -0
  236. sage/structure/factory.pyx +786 -0
  237. sage/structure/formal_sum.py +489 -0
  238. sage/structure/gens_py.py +73 -0
  239. sage/structure/global_options.py +1743 -0
  240. sage/structure/indexed_generators.py +863 -0
  241. sage/structure/list_clone.cpython-314t-darwin.so +0 -0
  242. sage/structure/list_clone.pxd +65 -0
  243. sage/structure/list_clone.pyx +1867 -0
  244. sage/structure/list_clone_demo.cpython-314t-darwin.so +0 -0
  245. sage/structure/list_clone_demo.pyx +248 -0
  246. sage/structure/list_clone_timings.py +179 -0
  247. sage/structure/list_clone_timings_cy.cpython-314t-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-314t-darwin.so +0 -0
  250. sage/structure/mutability.pxd +21 -0
  251. sage/structure/mutability.pyx +348 -0
  252. sage/structure/nonexact.py +69 -0
  253. sage/structure/parent.cpython-314t-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-314t-darwin.so +0 -0
  257. sage/structure/parent_base.pxd +13 -0
  258. sage/structure/parent_base.pyx +44 -0
  259. sage/structure/parent_gens.cpython-314t-darwin.so +0 -0
  260. sage/structure/parent_gens.pxd +22 -0
  261. sage/structure/parent_gens.pyx +377 -0
  262. sage/structure/parent_old.cpython-314t-darwin.so +0 -0
  263. sage/structure/parent_old.pxd +25 -0
  264. sage/structure/parent_old.pyx +294 -0
  265. sage/structure/proof/__init__.py +1 -0
  266. sage/structure/proof/all.py +243 -0
  267. sage/structure/proof/proof.py +300 -0
  268. sage/structure/richcmp.cpython-314t-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-314t-darwin.so +0 -0
  272. sage/structure/sage_object.pxd +3 -0
  273. sage/structure/sage_object.pyx +988 -0
  274. sage/structure/sage_object_test.py +19 -0
  275. sage/structure/sequence.py +937 -0
  276. sage/structure/set_factories.py +1178 -0
  277. sage/structure/set_factories_example.py +527 -0
  278. sage/structure/support_view.py +179 -0
  279. sage/structure/test_factory.py +56 -0
  280. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,323 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Miscellaneous operating system functions
4
+ """
5
+
6
+ IF UNAME_SYSNAME == "Linux" or UNAME_SYSNAME == "Darwin":
7
+
8
+ from posix.unistd cimport dup, dup2, close
9
+
10
+ from cpython.exc cimport PyErr_SetFromErrno
11
+
12
+ ELSE:
13
+
14
+ def dup(x):
15
+ return -1
16
+
17
+ def dup2(x, y):
18
+ return -1
19
+
20
+ def close():
21
+ return
22
+
23
+ def PyErr_SetFromErrno(x):
24
+ return
25
+
26
+ import os
27
+ import contextlib
28
+
29
+
30
+ def have_program(program, path=None) -> bool:
31
+ """
32
+ Return ``True`` if a ``program`` executable is found in the path
33
+ given by ``path``.
34
+
35
+ INPUT:
36
+
37
+ - ``program`` -- string, the name of the program to check
38
+
39
+ - ``path`` -- string or ``None``. Paths to search for ``program``,
40
+ separated by ``os.pathsep``. If ``None``, use the :envvar:`PATH`
41
+ environment variable.
42
+
43
+ OUTPUT: boolean
44
+
45
+ EXAMPLES::
46
+
47
+ sage: from sage.misc.sage_ostools import have_program
48
+ sage: have_program('ls')
49
+ True
50
+ sage: have_program('there_is_not_a_program_with_this_name')
51
+ False
52
+ sage: have_program('sh', '/bin')
53
+ True
54
+ sage: have_program('sage', '/there_is_not_a_path_with_this_name')
55
+ False
56
+ sage: have_program('there_is_not_a_program_with_this_name', "/bin")
57
+ False
58
+ """
59
+ if path is None:
60
+ path = os.environ.get('PATH', "")
61
+ for p in path.split(os.pathsep):
62
+ try:
63
+ if os.access(os.path.join(p, program), os.X_OK):
64
+ return True
65
+ except OSError:
66
+ pass
67
+ return False
68
+
69
+
70
+ @contextlib.contextmanager
71
+ def restore_cwd(chdir=None):
72
+ """
73
+ Context manager that restores the original working directory upon exiting.
74
+
75
+ INPUT:
76
+
77
+ - ``chdir`` -- optionally change directories to the given directory
78
+ upon entering the context manager
79
+
80
+ EXAMPLES::
81
+
82
+ sage: from sage.misc.sage_ostools import restore_cwd
83
+ sage: import tempfile
84
+ sage: orig_cwd = os.getcwd()
85
+ sage: with tempfile.TemporaryDirectory() as d:
86
+ ....: with restore_cwd(d):
87
+ ....: print(os.getcwd() == orig_cwd)
88
+ False
89
+ sage: os.getcwd() == orig_cwd
90
+ True
91
+ """
92
+ orig_cwd = os.getcwd()
93
+ if chdir is not None:
94
+ os.chdir(chdir)
95
+ try:
96
+ yield
97
+ finally:
98
+ os.chdir(orig_cwd)
99
+
100
+
101
+ cdef file_and_fd(x, int* fd):
102
+ """
103
+ If ``x`` is a file, return ``x`` and set ``*fd`` to its file
104
+ descriptor. If ``x`` is an integer, return ``None`` and set
105
+ ``*fd`` to ``x``. Otherwise, set ``*fd = -1`` and raise a
106
+ :exc:`TypeError`.
107
+ """
108
+ fd[0] = -1
109
+ try:
110
+ m = x.fileno
111
+ except AttributeError:
112
+ try:
113
+ fd[0] = x
114
+ except Exception: # Some objects raise bizarre exceptions when calling int()
115
+ raise TypeError(f"{x} must be a Python file or an integer")
116
+ return None
117
+ fd[0] = m()
118
+ return x
119
+
120
+
121
+ cdef class redirection:
122
+ r"""
123
+ Context to implement redirection of files, analogous to the
124
+ ``>file`` or ``1>&2`` syntax in POSIX shells.
125
+
126
+ Unlike the ``redirect_stdout`` and ``redirect_stderr`` contexts in
127
+ the Python 3.4 standard library, this acts on the OS level, not on
128
+ the Python level. This implies that it only works for true files,
129
+ not duck-type file objects such as ``StringIO``.
130
+
131
+ INPUT:
132
+
133
+ - ``source`` -- the file to be redirected
134
+
135
+ - ``dest`` -- where the source file should be redirected to
136
+
137
+ - ``close`` -- boolean (default: ``True``); whether to close the
138
+ destination file upon exiting the context. This is only supported
139
+ if ``dest`` is a Python file.
140
+
141
+ The ``source`` and ``dest`` arguments can be either Python files
142
+ or file descriptors.
143
+
144
+ EXAMPLES::
145
+
146
+ sage: from sage.misc.sage_ostools import redirection
147
+ sage: fn = tmp_filename()
148
+
149
+ ::
150
+
151
+ sage: with redirection(sys.stdout, open(fn, 'w')):
152
+ ....: print("hello world!")
153
+ sage: with open(fn) as f:
154
+ ....: _ = sys.stdout.write(f.read())
155
+ hello world!
156
+
157
+ We can do the same using a file descriptor as source::
158
+
159
+ sage: fd = sys.stdout.fileno()
160
+ sage: with redirection(fd, open(fn, 'wb')):
161
+ ....: _ = os.write(fd, b"hello world!\n")
162
+ sage: with open(fn) as f:
163
+ ....: _ = sys.stdout.write(f.read())
164
+ hello world!
165
+
166
+ The converse also works::
167
+
168
+ sage: with open(fn, 'w') as f:
169
+ ....: _ = f.write("This goes to the file\n")
170
+ ....: with redirection(f, sys.stdout, close=False):
171
+ ....: _ = f.write("This goes to stdout\n")
172
+ ....: _ = f.write("This goes to the file again\n")
173
+ This goes to stdout
174
+ sage: with open(fn) as f:
175
+ ....: _ = sys.stdout.write(f.read())
176
+ This goes to the file
177
+ This goes to the file again
178
+
179
+ The same :class:`redirection` instance can be reused multiple times,
180
+ provided that ``close=False``::
181
+
182
+ sage: f = open(fn, 'w+')
183
+ sage: r = redirection(sys.stdout, f, close=False)
184
+ sage: with r:
185
+ ....: print("Line 1")
186
+ sage: with r:
187
+ ....: print("Line 2")
188
+ sage: with f:
189
+ ....: _ = f.seek(0)
190
+ ....: _ = sys.stdout.write(f.read())
191
+ Line 1
192
+ Line 2
193
+
194
+ The redirection also works for subprocesses::
195
+
196
+ sage: import subprocess
197
+ sage: with redirection(sys.stdout, open(fn, 'w')):
198
+ ....: _ = subprocess.call(["echo", "hello world"])
199
+ sage: with open(fn) as f:
200
+ ....: _ = sys.stdout.write(f.read())
201
+ hello world
202
+
203
+ TESTS::
204
+
205
+ sage: import io
206
+ sage: redirection(sys.stdout, io.StringIO())
207
+ Traceback (most recent call last):
208
+ ...
209
+ io.UnsupportedOperation: fileno
210
+
211
+ The redirection is removed and the destination file is closed even
212
+ in the case of errors::
213
+
214
+ sage: f = open(os.devnull, 'w')
215
+ sage: with redirection(sys.stdout, f):
216
+ ....: raise KeyboardInterrupt
217
+ Traceback (most recent call last):
218
+ ...
219
+ KeyboardInterrupt
220
+ sage: f.closed
221
+ True
222
+
223
+ Reusing a :class:`redirection` instance with ``close=True``::
224
+
225
+ sage: f = open(fn, 'w+')
226
+ sage: r = redirection(sys.stdout, f, close=True)
227
+ sage: with r:
228
+ ....: print("Line 1")
229
+ sage: with r:
230
+ ....: print("Line 2")
231
+ Traceback (most recent call last):
232
+ ...
233
+ ValueError: invalid destination file
234
+
235
+ Using ``close=True`` on a non-file::
236
+
237
+ sage: redirection(sys.stdout, 0, close=True)
238
+ Traceback (most recent call last):
239
+ ...
240
+ ValueError: close=True requires a Python destination file
241
+
242
+ Passing invalid file descriptors::
243
+
244
+ sage: with redirection(-123, open(os.devnull, 'w')):
245
+ ....: pass
246
+ Traceback (most recent call last):
247
+ ...
248
+ OSError: [Errno 9] Bad file descriptor
249
+ sage: with redirection(sys.stdout, -123):
250
+ ....: pass
251
+ Traceback (most recent call last):
252
+ ...
253
+ OSError: [Errno 9] Bad file descriptor
254
+
255
+ Nesting the same :class:`redirection` object is not allowed::
256
+
257
+ sage: with redirection(sys.stdout, open(os.devnull, 'w')) as r:
258
+ ....: with r:
259
+ ....: pass
260
+ Traceback (most recent call last):
261
+ ...
262
+ ValueError: source already redirected
263
+ """
264
+ cdef readonly source_file, dest_file
265
+ cdef readonly int source_fd, dest_fd, dup_source_fd
266
+ cdef bint close_dest
267
+
268
+ def __cinit__(self):
269
+ self.source_fd = -1
270
+ self.dest_fd = -1
271
+ self.dup_source_fd = -1
272
+
273
+ def __init__(self, source, dest, close=None):
274
+ self.source_file = file_and_fd(source, &self.source_fd)
275
+ self.dest_file = file_and_fd(dest, &self.dest_fd)
276
+
277
+ if self.dest_file is None:
278
+ if close:
279
+ raise ValueError("close=True requires a Python destination file")
280
+ elif close is None:
281
+ close = True
282
+ self.close_dest = close
283
+
284
+ cdef int flush(self) except -1:
285
+ for f in (self.source_file, self.dest_file):
286
+ if f is not None:
287
+ f.flush()
288
+
289
+ def __enter__(self):
290
+ # Basic sanity checks
291
+ if self.source_fd == -1:
292
+ raise ValueError("invalid source file")
293
+ if self.dest_fd == -1:
294
+ raise ValueError("invalid destination file")
295
+ if self.dup_source_fd != -1:
296
+ raise ValueError("source already redirected")
297
+
298
+ self.flush()
299
+
300
+ dupsrc = dup(self.source_fd)
301
+ if dupsrc == -1:
302
+ PyErr_SetFromErrno(OSError)
303
+ fd = dup2(self.dest_fd, self.source_fd)
304
+ if fd == -1:
305
+ try:
306
+ PyErr_SetFromErrno(OSError)
307
+ finally:
308
+ close(dupsrc)
309
+ self.dup_source_fd = dupsrc
310
+ return self
311
+
312
+ def __exit__(self, *args):
313
+ try:
314
+ self.flush()
315
+ finally:
316
+ fd = dup2(self.dup_source_fd, self.source_fd)
317
+ if fd == -1:
318
+ PyErr_SetFromErrno(OSError)
319
+ close(self.dup_source_fd)
320
+ self.dup_source_fd = -1
321
+ if self.close_dest:
322
+ self.dest_file.close()
323
+ self.dest_fd = -1
@@ -0,0 +1,275 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ """
3
+ Accurate timing information for Sage commands
4
+
5
+ This is an implementation of nice timeit functionality, like the
6
+ ``%timeit`` magic command in IPython. To use it, use the ``timeit``
7
+ command. This command then calls :func:`sage_timeit`, which you can
8
+ find below.
9
+
10
+ EXAMPLES::
11
+
12
+ sage: timeit('1+1') # random output
13
+ 625 loops, best of 3: 314 ns per loop
14
+
15
+ AUTHOR:
16
+
17
+ -- William Stein, based on code by Fernando Perez included in IPython
18
+ """
19
+
20
+ import os
21
+
22
+
23
+ class SageTimeitResult:
24
+ r"""
25
+ Represent the statistics of a timeit() command.
26
+
27
+ Prints as a string so that it can be easily returned to a user.
28
+
29
+ INPUT:
30
+
31
+ - ``stats`` -- tuple of length 5 containing the following information:
32
+
33
+ - integer, number of loops
34
+ - integer, repeat number
35
+ - Python integer, number of digits to print
36
+ - number, best timing result
37
+ - str, time unit
38
+
39
+ EXAMPLES::
40
+
41
+ sage: from sage.misc.sage_timeit import SageTimeitResult
42
+ sage: SageTimeitResult( (3, 5, int(8), pi, 'ms') ) # needs sage.symbolic
43
+ 3 loops, best of 5: 3.1415927 ms per loop
44
+
45
+ ::
46
+
47
+ sage: units = [u"s", u"ms", u"μs", u"ns"]
48
+ sage: scaling = [1, 1e3, 1e6, 1e9]
49
+ sage: number = 7
50
+ sage: repeat = 13
51
+ sage: precision = int(5)
52
+ sage: best = pi / 10 ^ 9 # needs sage.symbolic
53
+ sage: order = 3
54
+ sage: stats = (number, repeat, precision, best * scaling[order], units[order]) # needs sage.symbolic
55
+ sage: SageTimeitResult(stats) # needs sage.symbolic
56
+ 7 loops, best of 13: 3.1416 ns per loop
57
+
58
+ If the third argument is not a Python integer, a :exc:`TypeError` is raised::
59
+
60
+ sage: SageTimeitResult( (1, 2, 3, 4, 's') )
61
+ <repr(<sage.misc.sage_timeit.SageTimeitResult at 0x...>) failed: TypeError: * wants int>
62
+ """
63
+ def __init__(self, stats, series=None):
64
+ r"""
65
+ Construction of a timing result.
66
+
67
+ See documentation of ``SageTimeitResult`` for more details and
68
+ examples.
69
+
70
+ EXAMPLES::
71
+
72
+ sage: from sage.misc.sage_timeit import SageTimeitResult
73
+ sage: SageTimeitResult( (3, 5, int(8), pi, 'ms') ) # needs sage.symbolic
74
+ 3 loops, best of 5: 3.1415927 ms per loop
75
+ sage: s = SageTimeitResult( (3, 5, int(8), pi, 'ms'), [1.0,1.1,0.5]) # needs sage.symbolic
76
+ sage: s.series # needs sage.symbolic
77
+ [1.00000000000000, 1.10000000000000, 0.500000000000000]
78
+ """
79
+ self.stats = stats
80
+ self.series = series if not None else []
81
+
82
+ def __repr__(self):
83
+ r"""
84
+ String representation.
85
+
86
+ EXAMPLES::
87
+
88
+ sage: from sage.misc.sage_timeit import SageTimeitResult
89
+ sage: stats = (1, 2, int(3), pi, 'ns') # needs sage.symbolic
90
+ sage: SageTimeitResult(stats) #indirect doctest # needs sage.symbolic
91
+ 1 loop, best of 2: 3.14 ns per loop
92
+ """
93
+ if self.stats[0] > 1:
94
+ s = "%d loops, best of %d: %.*g %s per loop" % self.stats
95
+ else:
96
+ s = "%d loop, best of %d: %.*g %s per loop" % self.stats
97
+
98
+ if isinstance(s, str):
99
+ return s
100
+ return s.encode("utf-8")
101
+
102
+
103
+ def sage_timeit(stmt, globals_dict=None, preparse=None, number=0, repeat=3, precision=3, seconds=False):
104
+ """nodetex
105
+ Accurately measure the wall time required to execute ``stmt``.
106
+
107
+ INPUT:
108
+
109
+ - ``stmt`` -- a text string
110
+
111
+ - ``globals_dict`` -- dictionary or ``None`` (default). Evaluate
112
+ ``stmt`` in the context of the globals dictionary. If not set,
113
+ the current ``globals()`` dictionary is used.
114
+
115
+ - ``preparse`` -- (default: use globals preparser default) if
116
+ ``True`` preparse ``stmt`` using the Sage preparser
117
+
118
+ - ``number`` -- integer; (default: 0); number of loops
119
+
120
+ - ``repeat`` -- integer; (default: 3); number of repetition
121
+
122
+ - ``precision`` -- integer; (default: 3); precision of output time
123
+
124
+ - ``seconds`` -- boolean (default: ``False``); whether to just
125
+ return time in seconds
126
+
127
+ OUTPUT:
128
+
129
+ An instance of ``SageTimeitResult`` unless the optional parameter
130
+ ``seconds=True`` is passed. In that case, the elapsed time in
131
+ seconds is returned as a floating-point number.
132
+
133
+ EXAMPLES::
134
+
135
+ sage: from sage.misc.sage_timeit import sage_timeit
136
+ sage: sage_timeit('3^100000', globals(), preparse=True, number=50) # random output
137
+ '50 loops, best of 3: 1.97 ms per loop'
138
+ sage: sage_timeit('3^100000', globals(), preparse=False, number=50) # random output
139
+ '50 loops, best of 3: 67.1 ns per loop'
140
+ sage: a = 10
141
+ sage: sage_timeit('a^2', globals(), number=50) # random output
142
+ '50 loops, best of 3: 4.26 us per loop'
143
+
144
+ If you only want to see the timing and not have access to additional
145
+ information, just use the ``timeit`` object::
146
+
147
+ sage: timeit('10^2', number=50)
148
+ 50 loops, best of 3: ... per loop
149
+
150
+ Using sage_timeit gives you more information though::
151
+
152
+ sage: s = sage_timeit('10^2', globals(), repeat=1000)
153
+ sage: len(s.series)
154
+ 1000
155
+ sage: mean(s.series) # random output # needs sage.modules
156
+ 3.1298141479492283e-07
157
+ sage: min(s.series) # random output
158
+ 2.9258728027343752e-07
159
+ sage: t = stats.TimeSeries(s.series) # needs numpy sage.modules
160
+ sage: t.scale(10^6).plot_histogram(bins=20,figsize=[12,6], ymax=2) # needs numpy sage.modules sage.plot
161
+ Graphics object consisting of 20 graphics primitives
162
+
163
+
164
+ The input expression can contain newlines (but doctests cannot, so
165
+ we use ``os.linesep`` here)::
166
+
167
+ sage: from sage.misc.sage_timeit import sage_timeit
168
+ sage: from os import linesep as CR
169
+ sage: # sage_timeit(r'a = 2\\nb=131\\nfactor(a^b-1)')
170
+ sage: sage_timeit('a = 2' + CR + 'b=131' + CR + 'factor(a^b-1)', # needs sage.libs.pari
171
+ ....: globals(), number=10)
172
+ 10 loops, best of 3: ... per loop
173
+
174
+ Test to make sure that ``timeit`` behaves well with output::
175
+
176
+ sage: timeit("print('Hi')", number=50)
177
+ 50 loops, best of 3: ... per loop
178
+
179
+ If you want a machine-readable output, use the ``seconds=True`` option::
180
+
181
+ sage: timeit("print('Hi')", seconds=True) # random output
182
+ 1.42555236816e-06
183
+ sage: t = timeit("print('Hi')", seconds=True)
184
+ sage: t #r random output
185
+ 3.6010742187499999e-07
186
+
187
+ TESTS:
188
+
189
+ Make sure that garbage collection is re-enabled after an exception
190
+ occurs in timeit::
191
+
192
+ sage: def f(): raise ValueError
193
+ sage: import gc
194
+ sage: gc.isenabled()
195
+ True
196
+ sage: timeit("f()")
197
+ Traceback (most recent call last):
198
+ ...
199
+ ValueError
200
+ sage: gc.isenabled()
201
+ True
202
+ """
203
+ import math
204
+ import timeit as timeit_
205
+
206
+ import sage.repl.interpreter as interpreter
207
+ import sage.repl.preparse as preparser
208
+
209
+ number = int(number)
210
+ repeat = int(repeat)
211
+ precision = int(precision)
212
+ if preparse is None:
213
+ preparse = interpreter._do_preparse
214
+ if preparse:
215
+ stmt = preparser.preparse(stmt)
216
+ if stmt == "":
217
+ return ''
218
+
219
+ units = ["s", "ms", "μs", "ns"]
220
+ scaling = [1, 1e3, 1e6, 1e9]
221
+
222
+ timer = timeit_.Timer()
223
+
224
+ # this code has tight coupling to the inner workings of timeit.Timer,
225
+ # but is there a better way to achieve that the code stmt has access
226
+ # to the shell namespace?
227
+
228
+ src = timeit_.template.format(stmt=timeit_.reindent(stmt, 8),
229
+ setup='pass', init='')
230
+ code = compile(src, '<magic-timeit>', 'exec')
231
+ ns = {}
232
+ if not globals_dict:
233
+ globals_dict = globals()
234
+ exec(code, globals_dict, ns)
235
+ timer.inner = ns["inner"]
236
+
237
+ import sys
238
+ f = sys.stdout
239
+
240
+ try:
241
+ null = open(os.devnull, 'w')
242
+ except Exception:
243
+ null = None
244
+
245
+ try:
246
+ if null is not None:
247
+ sys.stdout = null
248
+
249
+ if number == 0:
250
+ # determine number so that 0.2 <= total time < 2.0
251
+ number = 1
252
+ for i in range(1, 5):
253
+ number *= 5
254
+ if timer.timeit(number) >= 0.2:
255
+ break
256
+
257
+ series = [s / number for s in timer.repeat(repeat, number)]
258
+ best = min(series)
259
+
260
+ finally:
261
+ if null is not None:
262
+ sys.stdout.close()
263
+ sys.stdout = f
264
+ import gc
265
+ gc.enable()
266
+
267
+ if seconds:
268
+ return best
269
+
270
+ if best > 0.0:
271
+ order = min(-int(math.floor(math.log10(best)) // 3), 3)
272
+ else:
273
+ order = 3
274
+ stats = (number, repeat, precision, best * scaling[order], units[order])
275
+ return SageTimeitResult(stats, series=series)