passagemath-objects 10.6.31rc3__cp314-cp314-musllinux_1_2_aarch64.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 (279) hide show
  1. passagemath_objects-10.6.31rc3.dist-info/METADATA +114 -0
  2. passagemath_objects-10.6.31rc3.dist-info/RECORD +279 -0
  3. passagemath_objects-10.6.31rc3.dist-info/WHEEL +5 -0
  4. passagemath_objects-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_objects.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  6. sage/all__sagemath_objects.py +37 -0
  7. sage/arith/all__sagemath_objects.py +5 -0
  8. sage/arith/long.pxd +411 -0
  9. sage/arith/numerical_approx.cpython-314-aarch64-linux-musl.so +0 -0
  10. sage/arith/numerical_approx.pxd +35 -0
  11. sage/arith/numerical_approx.pyx +75 -0
  12. sage/arith/power.cpython-314-aarch64-linux-musl.so +0 -0
  13. sage/arith/power.pxd +31 -0
  14. sage/arith/power.pyx +127 -0
  15. sage/categories/action.cpython-314-aarch64-linux-musl.so +0 -0
  16. sage/categories/action.pxd +29 -0
  17. sage/categories/action.pyx +641 -0
  18. sage/categories/algebra_functor.py +745 -0
  19. sage/categories/all__sagemath_objects.py +33 -0
  20. sage/categories/basic.py +62 -0
  21. sage/categories/cartesian_product.py +295 -0
  22. sage/categories/category.py +3401 -0
  23. sage/categories/category_cy_helper.cpython-314-aarch64-linux-musl.so +0 -0
  24. sage/categories/category_cy_helper.pxd +8 -0
  25. sage/categories/category_cy_helper.pyx +322 -0
  26. sage/categories/category_singleton.cpython-314-aarch64-linux-musl.so +0 -0
  27. sage/categories/category_singleton.pxd +3 -0
  28. sage/categories/category_singleton.pyx +342 -0
  29. sage/categories/category_types.py +637 -0
  30. sage/categories/category_with_axiom.py +2876 -0
  31. sage/categories/covariant_functorial_construction.py +703 -0
  32. sage/categories/facade_sets.py +228 -0
  33. sage/categories/functor.cpython-314-aarch64-linux-musl.so +0 -0
  34. sage/categories/functor.pxd +7 -0
  35. sage/categories/functor.pyx +691 -0
  36. sage/categories/homset.py +1338 -0
  37. sage/categories/homsets.py +364 -0
  38. sage/categories/isomorphic_objects.py +73 -0
  39. sage/categories/map.cpython-314-aarch64-linux-musl.so +0 -0
  40. sage/categories/map.pxd +34 -0
  41. sage/categories/map.pyx +2112 -0
  42. sage/categories/morphism.cpython-314-aarch64-linux-musl.so +0 -0
  43. sage/categories/morphism.pxd +14 -0
  44. sage/categories/morphism.pyx +895 -0
  45. sage/categories/objects.py +167 -0
  46. sage/categories/primer.py +1696 -0
  47. sage/categories/pushout.py +4834 -0
  48. sage/categories/quotients.py +64 -0
  49. sage/categories/realizations.py +200 -0
  50. sage/categories/sets_cat.py +3228 -0
  51. sage/categories/sets_with_partial_maps.py +52 -0
  52. sage/categories/subobjects.py +64 -0
  53. sage/categories/subquotients.py +21 -0
  54. sage/categories/with_realizations.py +311 -0
  55. sage/cpython/__init__.py +19 -0
  56. sage/cpython/_py2_random.py +619 -0
  57. sage/cpython/all.py +3 -0
  58. sage/cpython/atexit.cpython-314-aarch64-linux-musl.so +0 -0
  59. sage/cpython/atexit.pyx +262 -0
  60. sage/cpython/builtin_types.cpython-314-aarch64-linux-musl.so +0 -0
  61. sage/cpython/builtin_types.pyx +7 -0
  62. sage/cpython/cython_metaclass.cpython-314-aarch64-linux-musl.so +0 -0
  63. sage/cpython/cython_metaclass.h +117 -0
  64. sage/cpython/cython_metaclass.pxd +3 -0
  65. sage/cpython/cython_metaclass.pyx +130 -0
  66. sage/cpython/debug.cpython-314-aarch64-linux-musl.so +0 -0
  67. sage/cpython/debug.pyx +302 -0
  68. sage/cpython/dict_del_by_value.cpython-314-aarch64-linux-musl.so +0 -0
  69. sage/cpython/dict_del_by_value.pxd +9 -0
  70. sage/cpython/dict_del_by_value.pyx +191 -0
  71. sage/cpython/dict_internal.h +245 -0
  72. sage/cpython/getattr.cpython-314-aarch64-linux-musl.so +0 -0
  73. sage/cpython/getattr.pxd +9 -0
  74. sage/cpython/getattr.pyx +439 -0
  75. sage/cpython/pycore_long.h +97 -0
  76. sage/cpython/pycore_long.pxd +10 -0
  77. sage/cpython/python_debug.h +44 -0
  78. sage/cpython/python_debug.pxd +47 -0
  79. sage/cpython/pyx_visit.h +13 -0
  80. sage/cpython/string.cpython-314-aarch64-linux-musl.so +0 -0
  81. sage/cpython/string.pxd +76 -0
  82. sage/cpython/string.pyx +34 -0
  83. sage/cpython/string_impl.h +60 -0
  84. sage/cpython/type.cpython-314-aarch64-linux-musl.so +0 -0
  85. sage/cpython/type.pxd +2 -0
  86. sage/cpython/type.pyx +40 -0
  87. sage/cpython/wrapperdescr.pxd +67 -0
  88. sage/ext/all__sagemath_objects.py +3 -0
  89. sage/ext/ccobject.h +64 -0
  90. sage/ext/cplusplus.pxd +17 -0
  91. sage/ext/mod_int.h +30 -0
  92. sage/ext/mod_int.pxd +24 -0
  93. sage/ext/stdsage.pxd +39 -0
  94. sage/groups/all__sagemath_objects.py +1 -0
  95. sage/groups/group.cpython-314-aarch64-linux-musl.so +0 -0
  96. sage/groups/group.pxd +14 -0
  97. sage/groups/group.pyx +322 -0
  98. sage/groups/old.cpython-314-aarch64-linux-musl.so +0 -0
  99. sage/groups/old.pxd +14 -0
  100. sage/groups/old.pyx +219 -0
  101. sage/libs/all__sagemath_objects.py +3 -0
  102. sage/libs/gmp/__init__.py +1 -0
  103. sage/libs/gmp/all.pxd +6 -0
  104. sage/libs/gmp/binop.pxd +23 -0
  105. sage/libs/gmp/misc.pxd +8 -0
  106. sage/libs/gmp/mpf.pxd +88 -0
  107. sage/libs/gmp/mpn.pxd +57 -0
  108. sage/libs/gmp/mpq.pxd +57 -0
  109. sage/libs/gmp/mpz.pxd +202 -0
  110. sage/libs/gmp/pylong.cpython-314-aarch64-linux-musl.so +0 -0
  111. sage/libs/gmp/pylong.pxd +12 -0
  112. sage/libs/gmp/pylong.pyx +150 -0
  113. sage/libs/gmp/random.pxd +25 -0
  114. sage/libs/gmp/randomize.pxd +59 -0
  115. sage/libs/gmp/types.pxd +53 -0
  116. sage/libs/gmpxx.pxd +19 -0
  117. sage/misc/abstract_method.py +276 -0
  118. sage/misc/all__sagemath_objects.py +43 -0
  119. sage/misc/bindable_class.py +253 -0
  120. sage/misc/c3_controlled.cpython-314-aarch64-linux-musl.so +0 -0
  121. sage/misc/c3_controlled.pxd +2 -0
  122. sage/misc/c3_controlled.pyx +1402 -0
  123. sage/misc/cachefunc.cpython-314-aarch64-linux-musl.so +0 -0
  124. sage/misc/cachefunc.pxd +43 -0
  125. sage/misc/cachefunc.pyx +3781 -0
  126. sage/misc/call.py +188 -0
  127. sage/misc/classcall_metaclass.cpython-314-aarch64-linux-musl.so +0 -0
  128. sage/misc/classcall_metaclass.pxd +14 -0
  129. sage/misc/classcall_metaclass.pyx +599 -0
  130. sage/misc/constant_function.cpython-314-aarch64-linux-musl.so +0 -0
  131. sage/misc/constant_function.pyx +128 -0
  132. sage/misc/decorators.py +747 -0
  133. sage/misc/fast_methods.cpython-314-aarch64-linux-musl.so +0 -0
  134. sage/misc/fast_methods.pxd +20 -0
  135. sage/misc/fast_methods.pyx +351 -0
  136. sage/misc/flatten.py +90 -0
  137. sage/misc/fpickle.cpython-314-aarch64-linux-musl.so +0 -0
  138. sage/misc/fpickle.pyx +177 -0
  139. sage/misc/function_mangling.cpython-314-aarch64-linux-musl.so +0 -0
  140. sage/misc/function_mangling.pxd +11 -0
  141. sage/misc/function_mangling.pyx +308 -0
  142. sage/misc/inherit_comparison.cpython-314-aarch64-linux-musl.so +0 -0
  143. sage/misc/inherit_comparison.pxd +5 -0
  144. sage/misc/inherit_comparison.pyx +105 -0
  145. sage/misc/instancedoc.cpython-314-aarch64-linux-musl.so +0 -0
  146. sage/misc/instancedoc.pyx +331 -0
  147. sage/misc/lazy_attribute.cpython-314-aarch64-linux-musl.so +0 -0
  148. sage/misc/lazy_attribute.pyx +607 -0
  149. sage/misc/lazy_format.py +135 -0
  150. sage/misc/lazy_import.cpython-314-aarch64-linux-musl.so +0 -0
  151. sage/misc/lazy_import.pyx +1299 -0
  152. sage/misc/lazy_import_cache.py +36 -0
  153. sage/misc/lazy_list.cpython-314-aarch64-linux-musl.so +0 -0
  154. sage/misc/lazy_list.pxd +19 -0
  155. sage/misc/lazy_list.pyx +1187 -0
  156. sage/misc/lazy_string.cpython-314-aarch64-linux-musl.so +0 -0
  157. sage/misc/lazy_string.pxd +7 -0
  158. sage/misc/lazy_string.pyx +546 -0
  159. sage/misc/misc.py +1066 -0
  160. sage/misc/misc_c.cpython-314-aarch64-linux-musl.so +0 -0
  161. sage/misc/misc_c.pxd +3 -0
  162. sage/misc/misc_c.pyx +766 -0
  163. sage/misc/namespace_package.py +37 -0
  164. sage/misc/nested_class.cpython-314-aarch64-linux-musl.so +0 -0
  165. sage/misc/nested_class.pxd +3 -0
  166. sage/misc/nested_class.pyx +394 -0
  167. sage/misc/persist.cpython-314-aarch64-linux-musl.so +0 -0
  168. sage/misc/persist.pyx +1251 -0
  169. sage/misc/prandom.py +418 -0
  170. sage/misc/randstate.cpython-314-aarch64-linux-musl.so +0 -0
  171. sage/misc/randstate.pxd +30 -0
  172. sage/misc/randstate.pyx +1059 -0
  173. sage/misc/repr.py +203 -0
  174. sage/misc/reset.cpython-314-aarch64-linux-musl.so +0 -0
  175. sage/misc/reset.pyx +196 -0
  176. sage/misc/sage_ostools.cpython-314-aarch64-linux-musl.so +0 -0
  177. sage/misc/sage_ostools.pyx +323 -0
  178. sage/misc/sage_timeit.py +265 -0
  179. sage/misc/sage_timeit_class.cpython-314-aarch64-linux-musl.so +0 -0
  180. sage/misc/sage_timeit_class.pyx +120 -0
  181. sage/misc/sage_unittest.py +637 -0
  182. sage/misc/sageinspect.py +2768 -0
  183. sage/misc/session.cpython-314-aarch64-linux-musl.so +0 -0
  184. sage/misc/session.pyx +392 -0
  185. sage/misc/superseded.py +557 -0
  186. sage/misc/test_nested_class.py +228 -0
  187. sage/misc/timing.py +256 -0
  188. sage/misc/unknown.py +222 -0
  189. sage/misc/verbose.py +253 -0
  190. sage/misc/weak_dict.cpython-314-aarch64-linux-musl.so +0 -0
  191. sage/misc/weak_dict.pxd +15 -0
  192. sage/misc/weak_dict.pyx +1231 -0
  193. sage/modules/all__sagemath_objects.py +1 -0
  194. sage/modules/module.cpython-314-aarch64-linux-musl.so +0 -0
  195. sage/modules/module.pxd +5 -0
  196. sage/modules/module.pyx +329 -0
  197. sage/rings/all__sagemath_objects.py +3 -0
  198. sage/rings/integer_fake.h +22 -0
  199. sage/rings/integer_fake.pxd +55 -0
  200. sage/sets/all__sagemath_objects.py +3 -0
  201. sage/sets/pythonclass.cpython-314-aarch64-linux-musl.so +0 -0
  202. sage/sets/pythonclass.pxd +9 -0
  203. sage/sets/pythonclass.pyx +247 -0
  204. sage/structure/__init__.py +4 -0
  205. sage/structure/all.py +30 -0
  206. sage/structure/category_object.cpython-314-aarch64-linux-musl.so +0 -0
  207. sage/structure/category_object.pxd +28 -0
  208. sage/structure/category_object.pyx +1087 -0
  209. sage/structure/coerce.cpython-314-aarch64-linux-musl.so +0 -0
  210. sage/structure/coerce.pxd +44 -0
  211. sage/structure/coerce.pyx +2107 -0
  212. sage/structure/coerce_actions.cpython-314-aarch64-linux-musl.so +0 -0
  213. sage/structure/coerce_actions.pxd +27 -0
  214. sage/structure/coerce_actions.pyx +988 -0
  215. sage/structure/coerce_dict.cpython-314-aarch64-linux-musl.so +0 -0
  216. sage/structure/coerce_dict.pxd +51 -0
  217. sage/structure/coerce_dict.pyx +1557 -0
  218. sage/structure/coerce_exceptions.py +23 -0
  219. sage/structure/coerce_maps.cpython-314-aarch64-linux-musl.so +0 -0
  220. sage/structure/coerce_maps.pxd +28 -0
  221. sage/structure/coerce_maps.pyx +718 -0
  222. sage/structure/debug_options.cpython-314-aarch64-linux-musl.so +0 -0
  223. sage/structure/debug_options.pxd +6 -0
  224. sage/structure/debug_options.pyx +54 -0
  225. sage/structure/dynamic_class.py +541 -0
  226. sage/structure/element.cpython-314-aarch64-linux-musl.so +0 -0
  227. sage/structure/element.pxd +272 -0
  228. sage/structure/element.pyx +4772 -0
  229. sage/structure/element_wrapper.cpython-314-aarch64-linux-musl.so +0 -0
  230. sage/structure/element_wrapper.pxd +12 -0
  231. sage/structure/element_wrapper.pyx +582 -0
  232. sage/structure/factorization.py +1422 -0
  233. sage/structure/factorization_integer.py +105 -0
  234. sage/structure/factory.cpython-314-aarch64-linux-musl.so +0 -0
  235. sage/structure/factory.pyx +786 -0
  236. sage/structure/formal_sum.py +489 -0
  237. sage/structure/gens_py.py +73 -0
  238. sage/structure/global_options.py +1743 -0
  239. sage/structure/indexed_generators.py +863 -0
  240. sage/structure/list_clone.cpython-314-aarch64-linux-musl.so +0 -0
  241. sage/structure/list_clone.pxd +65 -0
  242. sage/structure/list_clone.pyx +1867 -0
  243. sage/structure/list_clone_demo.cpython-314-aarch64-linux-musl.so +0 -0
  244. sage/structure/list_clone_demo.pyx +248 -0
  245. sage/structure/list_clone_timings.py +179 -0
  246. sage/structure/list_clone_timings_cy.cpython-314-aarch64-linux-musl.so +0 -0
  247. sage/structure/list_clone_timings_cy.pyx +86 -0
  248. sage/structure/mutability.cpython-314-aarch64-linux-musl.so +0 -0
  249. sage/structure/mutability.pxd +21 -0
  250. sage/structure/mutability.pyx +348 -0
  251. sage/structure/nonexact.py +69 -0
  252. sage/structure/parent.cpython-314-aarch64-linux-musl.so +0 -0
  253. sage/structure/parent.pxd +112 -0
  254. sage/structure/parent.pyx +3093 -0
  255. sage/structure/parent_base.cpython-314-aarch64-linux-musl.so +0 -0
  256. sage/structure/parent_base.pxd +13 -0
  257. sage/structure/parent_base.pyx +44 -0
  258. sage/structure/parent_gens.cpython-314-aarch64-linux-musl.so +0 -0
  259. sage/structure/parent_gens.pxd +22 -0
  260. sage/structure/parent_gens.pyx +377 -0
  261. sage/structure/parent_old.cpython-314-aarch64-linux-musl.so +0 -0
  262. sage/structure/parent_old.pxd +25 -0
  263. sage/structure/parent_old.pyx +294 -0
  264. sage/structure/proof/__init__.py +1 -0
  265. sage/structure/proof/all.py +243 -0
  266. sage/structure/proof/proof.py +300 -0
  267. sage/structure/richcmp.cpython-314-aarch64-linux-musl.so +0 -0
  268. sage/structure/richcmp.pxd +213 -0
  269. sage/structure/richcmp.pyx +495 -0
  270. sage/structure/sage_object.cpython-314-aarch64-linux-musl.so +0 -0
  271. sage/structure/sage_object.pxd +3 -0
  272. sage/structure/sage_object.pyx +988 -0
  273. sage/structure/sage_object_test.py +19 -0
  274. sage/structure/sequence.py +937 -0
  275. sage/structure/set_factories.py +1178 -0
  276. sage/structure/set_factories_example.py +527 -0
  277. sage/structure/support_view.py +179 -0
  278. sage/structure/test_factory.py +56 -0
  279. 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,265 @@
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
+
21
+ class SageTimeitResult:
22
+ r"""
23
+ Represent the statistics of a timeit() command.
24
+
25
+ Prints as a string so that it can be easily returned to a user.
26
+
27
+ INPUT:
28
+
29
+ - ``stats`` -- tuple of length 5 containing the following information:
30
+
31
+ - integer, number of loops
32
+ - integer, repeat number
33
+ - Python integer, number of digits to print
34
+ - number, best timing result
35
+ - str, time unit
36
+
37
+ EXAMPLES::
38
+
39
+ sage: from sage.misc.sage_timeit import SageTimeitResult
40
+ sage: SageTimeitResult( (3, 5, int(8), pi, 'ms') ) # needs sage.symbolic
41
+ 3 loops, best of 5: 3.1415927 ms per loop
42
+
43
+ ::
44
+
45
+ sage: units = [u"s", u"ms", u"μs", u"ns"]
46
+ sage: scaling = [1, 1e3, 1e6, 1e9]
47
+ sage: number = 7
48
+ sage: repeat = 13
49
+ sage: precision = int(5)
50
+ sage: best = pi / 10 ^ 9 # needs sage.symbolic
51
+ sage: order = 3
52
+ sage: stats = (number, repeat, precision, best * scaling[order], units[order]) # needs sage.symbolic
53
+ sage: SageTimeitResult(stats) # needs sage.symbolic
54
+ 7 loops, best of 13: 3.1416 ns per loop
55
+
56
+ If the third argument is not a Python integer, a :exc:`TypeError` is raised::
57
+
58
+ sage: SageTimeitResult( (1, 2, 3, 4, 's') )
59
+ <repr(<sage.misc.sage_timeit.SageTimeitResult at 0x...>) failed: TypeError: * wants int>
60
+ """
61
+ def __init__(self, stats, series=None):
62
+ r"""
63
+ Construction of a timing result.
64
+
65
+ See documentation of ``SageTimeitResult`` for more details and
66
+ examples.
67
+
68
+ EXAMPLES::
69
+
70
+ sage: from sage.misc.sage_timeit import SageTimeitResult
71
+ sage: SageTimeitResult( (3, 5, int(8), pi, 'ms') ) # needs sage.symbolic
72
+ 3 loops, best of 5: 3.1415927 ms per loop
73
+ sage: s = SageTimeitResult( (3, 5, int(8), pi, 'ms'), [1.0,1.1,0.5]) # needs sage.symbolic
74
+ sage: s.series # needs sage.symbolic
75
+ [1.00000000000000, 1.10000000000000, 0.500000000000000]
76
+ """
77
+ self.stats = stats
78
+ self.series = series if not None else []
79
+
80
+ def __repr__(self):
81
+ r"""
82
+ String representation.
83
+
84
+ EXAMPLES::
85
+
86
+ sage: from sage.misc.sage_timeit import SageTimeitResult
87
+ sage: stats = (1, 2, int(3), pi, 'ns') # needs sage.symbolic
88
+ sage: SageTimeitResult(stats) #indirect doctest # needs sage.symbolic
89
+ 1 loop, best of 2: 3.14 ns per loop
90
+ """
91
+ if self.stats[0] > 1:
92
+ s = "%d loops, best of %d: %.*g %s per loop" % self.stats
93
+ else:
94
+ s = "%d loop, best of %d: %.*g %s per loop" % self.stats
95
+
96
+ if isinstance(s, str):
97
+ return s
98
+ return s.encode("utf-8")
99
+
100
+
101
+ def sage_timeit(stmt, globals_dict=None, preparse=None, number=0, repeat=3, precision=3, seconds=False):
102
+ """nodetex
103
+ Accurately measure the wall time required to execute ``stmt``.
104
+
105
+ INPUT:
106
+
107
+ - ``stmt`` -- a text string
108
+
109
+ - ``globals_dict`` -- dictionary or ``None`` (default). Evaluate
110
+ ``stmt`` in the context of the globals dictionary. If not set,
111
+ the current ``globals()`` dictionary is used.
112
+
113
+ - ``preparse`` -- (default: use globals preparser default) if
114
+ ``True`` preparse ``stmt`` using the Sage preparser
115
+
116
+ - ``number`` -- integer; (default: 0); number of loops
117
+
118
+ - ``repeat`` -- integer; (default: 3); number of repetition
119
+
120
+ - ``precision`` -- integer; (default: 3); precision of output time
121
+
122
+ - ``seconds`` -- boolean (default: ``False``); whether to just
123
+ return time in seconds
124
+
125
+ OUTPUT:
126
+
127
+ An instance of ``SageTimeitResult`` unless the optional parameter
128
+ ``seconds=True`` is passed. In that case, the elapsed time in
129
+ seconds is returned as a floating-point number.
130
+
131
+ EXAMPLES::
132
+
133
+ sage: from sage.misc.sage_timeit import sage_timeit
134
+ sage: sage_timeit('3^100000', globals(), preparse=True, number=50) # random output
135
+ '50 loops, best of 3: 1.97 ms per loop'
136
+ sage: sage_timeit('3^100000', globals(), preparse=False, number=50) # random output
137
+ '50 loops, best of 3: 67.1 ns per loop'
138
+ sage: a = 10
139
+ sage: sage_timeit('a^2', globals(), number=50) # random output
140
+ '50 loops, best of 3: 4.26 us per loop'
141
+
142
+ If you only want to see the timing and not have access to additional
143
+ information, just use the ``timeit`` object::
144
+
145
+ sage: timeit('10^2', number=50)
146
+ 50 loops, best of 3: ... per loop
147
+
148
+ Using sage_timeit gives you more information though::
149
+
150
+ sage: s = sage_timeit('10^2', globals(), repeat=1000)
151
+ sage: len(s.series)
152
+ 1000
153
+ sage: mean(s.series) # random output # needs sage.modules
154
+ 3.1298141479492283e-07
155
+ sage: min(s.series) # random output
156
+ 2.9258728027343752e-07
157
+ sage: t = stats.TimeSeries(s.series) # needs numpy sage.modules
158
+ sage: t.scale(10^6).plot_histogram(bins=20,figsize=[12,6], ymax=2) # needs numpy sage.modules sage.plot
159
+ Graphics object consisting of 20 graphics primitives
160
+
161
+
162
+ The input expression can contain newlines (but doctests cannot, so
163
+ we use ``os.linesep`` here)::
164
+
165
+ sage: from sage.misc.sage_timeit import sage_timeit
166
+ sage: from os import linesep as CR
167
+ sage: # sage_timeit(r'a = 2\\nb=131\\nfactor(a^b-1)')
168
+ sage: sage_timeit('a = 2' + CR + 'b=131' + CR + 'factor(a^b-1)', # needs sage.libs.pari
169
+ ....: globals(), number=10)
170
+ 10 loops, best of 3: ... per loop
171
+
172
+ Test to make sure that ``timeit`` behaves well with output::
173
+
174
+ sage: timeit("print('Hi')", number=50)
175
+ 50 loops, best of 3: ... per loop
176
+
177
+ If you want a machine-readable output, use the ``seconds=True`` option::
178
+
179
+ sage: timeit("print('Hi')", seconds=True) # random output
180
+ 1.42555236816e-06
181
+ sage: t = timeit("print('Hi')", seconds=True)
182
+ sage: t #r random output
183
+ 3.6010742187499999e-07
184
+
185
+ TESTS:
186
+
187
+ Make sure that garbage collection is re-enabled after an exception
188
+ occurs in timeit::
189
+
190
+ sage: def f(): raise ValueError
191
+ sage: import gc
192
+ sage: gc.isenabled()
193
+ True
194
+ sage: timeit("f()")
195
+ Traceback (most recent call last):
196
+ ...
197
+ ValueError
198
+ sage: gc.isenabled()
199
+ True
200
+ """
201
+ import math
202
+ import timeit as timeit_
203
+
204
+ import sage.repl.interpreter as interpreter
205
+ import sage.repl.preparse as preparser
206
+
207
+ number = int(number)
208
+ repeat = int(repeat)
209
+ precision = int(precision)
210
+ if preparse is None:
211
+ preparse = interpreter._do_preparse
212
+ if preparse:
213
+ stmt = preparser.preparse(stmt)
214
+ if stmt == "":
215
+ return ''
216
+
217
+ units = ["s", "ms", "μs", "ns"]
218
+ scaling = [1, 1e3, 1e6, 1e9]
219
+
220
+ timer = timeit_.Timer()
221
+
222
+ # this code has tight coupling to the inner workings of timeit.Timer,
223
+ # but is there a better way to achieve that the code stmt has access
224
+ # to the shell namespace?
225
+
226
+ src = timeit_.template.format(stmt=timeit_.reindent(stmt, 8),
227
+ setup='pass', init='')
228
+ code = compile(src, '<magic-timeit>', 'exec')
229
+ ns = {}
230
+ if not globals_dict:
231
+ globals_dict = globals()
232
+ exec(code, globals_dict, ns)
233
+ timer.inner = ns["inner"]
234
+
235
+ try:
236
+ import sys
237
+ f = sys.stdout
238
+ sys.stdout = open('/dev/null', 'w')
239
+
240
+ if number == 0:
241
+ # determine number so that 0.2 <= total time < 2.0
242
+ number = 1
243
+ for i in range(1, 5):
244
+ number *= 5
245
+ if timer.timeit(number) >= 0.2:
246
+ break
247
+
248
+ series = [s / number for s in timer.repeat(repeat, number)]
249
+ best = min(series)
250
+
251
+ finally:
252
+ sys.stdout.close()
253
+ sys.stdout = f
254
+ import gc
255
+ gc.enable()
256
+
257
+ if seconds:
258
+ return best
259
+
260
+ if best > 0.0:
261
+ order = min(-int(math.floor(math.log10(best)) // 3), 3)
262
+ else:
263
+ order = 3
264
+ stats = (number, repeat, precision, best * scaling[order], units[order])
265
+ return SageTimeitResult(stats, series=series)
@@ -0,0 +1,120 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ # This is here in Cython so we can access the interpreter globals
3
+ # cython: old_style_globals=True
4
+ """
5
+ The ``timeit`` command
6
+
7
+ This uses the function :func:`~sage.misc.sage_timeit.sage_timeit`.
8
+ """
9
+
10
+ from sage.misc import sage_timeit
11
+
12
+
13
+ class SageTimeit:
14
+ r"""nodetex
15
+ Time execution of a command or block of commands.
16
+
17
+ Displays the best WALL TIME for execution of the given code. This
18
+ is based on the Python ``timeit`` module, which avoids a number of
19
+ common traps for measuring execution times. It is also based on
20
+ IPython's ``%timeit`` command.
21
+
22
+ TYPICAL INPUT FORMAT::
23
+
24
+ timeit(statement, preparse=None, number=0, repeat=3, precision=3)
25
+
26
+ EXAMPLES::
27
+
28
+ sage: timeit('2^10000')
29
+ 625 loops, best of 3: ... per loop
30
+
31
+ We illustrate some options::
32
+
33
+ sage: timeit('2+2',precision=2,number=20,repeat=5)
34
+ 20 loops, best of 5: ... per loop
35
+
36
+ The preparser is on by default (if it is on), but the preparse option
37
+ allows us to override it::
38
+
39
+ sage: timeit('2^10000', preparse=False, number=50)
40
+ 50 loops, best of 3: ... per loop
41
+
42
+ The input can contain newlines::
43
+
44
+ sage: timeit("a = 2\nb=131\nfactor(a^b-1)", number=25) # needs sage.libs.pari
45
+ 25 loops, best of 3: ... per loop
46
+
47
+ .. SEEALSO:: :func:`runsnake`
48
+ """
49
+ def eval(self, code, globs=None, locals=None, **kwds):
50
+ r"""
51
+ This eval function is called when doing \%timeit in the notebook.
52
+
53
+ INPUT:
54
+
55
+ - ``code`` -- string of code to evaluate; may contain newlines
56
+
57
+ - ``globs`` -- global variables; if not given, uses module scope
58
+ globals
59
+
60
+ - ``locals`` -- ignored completely
61
+
62
+ - ``kwds`` -- passed onto sage_timeit. Common options are
63
+ ``preparse``, ``number``, ``repeat``, ``precision``. See
64
+ :func:`~sage.misc.sage_timeit.sage_timeit` for details.
65
+
66
+ OUTPUT: string; timing information
67
+
68
+ EXAMPLES::
69
+
70
+ sage: timeit.eval("2+2") # random output
71
+ '625 loops, best of 3: 1.47 us per loop'
72
+
73
+ We emphasize that timeit times WALL TIME. This is good in the
74
+ context of Sage where commands often call out to other
75
+ subprocesses that do not appear in CPU time. ::
76
+
77
+ sage: timeit('sleep(float(0.5))', number=3) # long time (5s on sage.math, 2012)
78
+ 3 loops, best of 3: ... ms per loop
79
+ """
80
+ if globs is None:
81
+ globs = globals()
82
+ return sage_timeit.sage_timeit(code, globs, **kwds)
83
+
84
+ def __call__(self, code, globals=None, **kwds):
85
+ """
86
+ INPUT:
87
+
88
+ - ``code`` -- string; a line or block of code, which may
89
+ contain newlines
90
+
91
+ - ``globals`` -- (optional) global variables; if not given the
92
+ globals of the calling module are used (e.g., if using this
93
+ from the command line, the globals of the command line are
94
+ used).
95
+
96
+ - ``preparse`` -- boolean or ``None`` (default). Whether or
97
+ not to preparse the input code using the Sage preparser. If
98
+ not specified, do the same thing as whatever was set by the
99
+ preparser command.
100
+
101
+ - ``**kwds`` -- passed onto self.eval(...). Common options are
102
+ ``preparse``, ``number``, ``repeat``, ``precision``. See
103
+ :func:`~sage.misc.sage_timeit.sage_timeit` for details.
104
+
105
+ OUTPUT:
106
+
107
+ Return the timing information, either as
108
+ :class:`~sage.misc.sage_timeit.SageTimeitResult`
109
+ or as a floating-point number containing the number of seconds
110
+ (if ``seconds=True`` was passed).
111
+
112
+ EXAMPLES::
113
+
114
+ sage: timeit('2^10000', preparse=False, number=100)
115
+ 100 loops, best of 3: ... per loop
116
+ """
117
+ return self.eval(code, globals, **kwds)
118
+
119
+
120
+ timeit = SageTimeit()