passagemath-categories 10.6.32__cp314-cp314t-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.
Files changed (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
@@ -0,0 +1,1643 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ # sage.doctest: needs sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic
3
+ """
4
+ Common Interface Functionality through Pexpect
5
+
6
+ See the examples in the other sections for how to use specific
7
+ interfaces. The interface classes all derive from the generic
8
+ interface that is described in this section.
9
+
10
+ AUTHORS:
11
+
12
+ - William Stein (2005): initial version
13
+
14
+ - William Stein (2006-03-01): got rid of infinite loop on startup if
15
+ client system missing
16
+
17
+ - Felix Lawrence (2009-08-21): edited ._sage_() to support lists and float exponents in foreign notation.
18
+
19
+ - Simon King (2010-09-25): Expect._local_tmpfile() depends on
20
+ Expect.pid() and is cached; Expect.quit() clears that cache,
21
+ which is important for forking.
22
+
23
+ - Jean-Pierre Flori (2010,2011): Split non Pexpect stuff into a parent class.
24
+
25
+ - Simon King (2010-11-23): Ensure that the interface is started again
26
+ after a crash, when a command is executed in _eval_line. Allow
27
+ synchronisation of the GAP interface.
28
+
29
+ - François Bissey, Bill Page, Jeroen Demeyer (2015-12-09): Upgrade to
30
+ pexpect 4.0.1 + patches, see :issue:`10295`.
31
+ """
32
+ # ****************************************************************************
33
+ # Copyright (C) 2005 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
+ import io
42
+ import os
43
+ import re
44
+ import shlex
45
+ import signal
46
+ import sys
47
+ import weakref
48
+ import time
49
+ import gc
50
+ from . import quit
51
+ from random import randrange
52
+
53
+ import pexpect
54
+ from pexpect import ExceptionPexpect
55
+ import sage.interfaces.abc
56
+ from sage.interfaces.interface import (Interface, InterfaceElement,
57
+ InterfaceFunction, InterfaceFunctionElement)
58
+
59
+ from sage.structure.element import RingElement
60
+
61
+ from sage.env import SAGE_EXTCODE, LOCAL_IDENTIFIER
62
+ from sage.misc.object_multiplexer import Multiplex
63
+ from sage.misc.instancedoc import instancedoc
64
+
65
+ from sage.cpython.string import str_to_bytes, bytes_to_str
66
+
67
+ BAD_SESSION = -2
68
+
69
+ # The subprocess is a shared resource. In a multi-threaded
70
+ # environment, there would have to be a lock to control access to the
71
+ # subprocess. Fortunately, Sage does not use Python threads.
72
+ # Unfortunately, the combination of the garbage collector and __del__
73
+ # methods gives rise to the same issues. So, in places where we need
74
+ # to do a sequence of operations on the subprocess and make sure
75
+ # nothing else intervenes (for example, when we write a command and
76
+ # then read back the result) we need to disable the garbage collector.
77
+ # See TRAC #955 for a more detailed description of this problem.
78
+
79
+ # To turn off the garbage collector for a particular region of code,
80
+ # do:
81
+ # with gc_disabled():
82
+ # ... your code goes here ...
83
+ # The garbage collector will be returned to its original state
84
+ # whenever the code exits by any means (falling off the end, executing
85
+ # "return", "break", or "continue", raising an exception, ...)
86
+
87
+
88
+ class gc_disabled:
89
+ """
90
+ This is a "with" statement context manager. Garbage collection is
91
+ disabled within its scope. Nested usage is properly handled.
92
+
93
+ EXAMPLES::
94
+
95
+ sage: import gc
96
+ sage: from sage.interfaces.expect import gc_disabled
97
+ sage: gc.isenabled()
98
+ True
99
+ sage: with gc_disabled():
100
+ ....: print(gc.isenabled())
101
+ ....: with gc_disabled():
102
+ ....: print(gc.isenabled())
103
+ ....: print(gc.isenabled())
104
+ False
105
+ False
106
+ False
107
+ sage: gc.isenabled()
108
+ True
109
+ """
110
+ def __enter__(self):
111
+ self._enabled = gc.isenabled()
112
+ gc.disable()
113
+
114
+ def __exit__(self, ty, val, tb):
115
+ if self._enabled:
116
+ gc.enable()
117
+ return False
118
+
119
+
120
+ class Expect(Interface):
121
+ """
122
+ Expect interface object.
123
+ """
124
+ def __init__(self, name, prompt, command=None, env={}, server=None,
125
+ server_tmpdir=None,
126
+ ulimit=None, maxread=None,
127
+ script_subdirectory=None, restart_on_ctrlc=False,
128
+ verbose_start=False, init_code=[], max_startup_time=None,
129
+ logfile=None, eval_using_file_cutoff=0,
130
+ do_cleaner=True, remote_cleaner=False, path=None,
131
+ terminal_echo=True):
132
+
133
+ Interface.__init__(self, name)
134
+
135
+ # Read environment variables
136
+ env_name = 'SAGE_%s_{}' % self.name().upper()
137
+ if server is None:
138
+ server = os.getenv(env_name.format('SERVER'))
139
+ if server_tmpdir is None:
140
+ server_tmpdir = os.getenv(env_name.format('TMPDIR'))
141
+ if script_subdirectory is None:
142
+ script_subdirectory = os.getenv(env_name.format('SCRIPT_SUBDIRECTORY'))
143
+ self.__is_remote = False
144
+ self.__remote_ulimit = None
145
+ self.__remote_cleaner = remote_cleaner
146
+ self._expect = None
147
+ self._eval_using_file_cutoff = eval_using_file_cutoff
148
+ self.__verbose_start = verbose_start
149
+ self.set_server_and_command(server, command, server_tmpdir, ulimit)
150
+ self._env = env
151
+ self.__do_cleaner = do_cleaner
152
+ self._change_prompt(prompt)
153
+ self._restart_on_ctrlc = restart_on_ctrlc
154
+ if path is not None:
155
+ self.__path = os.path.abspath(path)
156
+ elif script_subdirectory is None:
157
+ self.__path = os.getcwd()
158
+ else:
159
+ self.__path = os.path.join(SAGE_EXTCODE, name, script_subdirectory)
160
+ if not os.path.isdir(self.__path):
161
+ raise OSError("path %r does not exist" % self.__path)
162
+ self.__initialized = False
163
+ self.__seq = -1
164
+ self._session_number = 0
165
+ self.__init_code = init_code
166
+
167
+ # Handle the log file
168
+ if isinstance(logfile, str):
169
+ self.__logfile = None
170
+ self.__logfilename = logfile
171
+ else:
172
+ self.__logfile = logfile
173
+ self.__logfilename = None
174
+
175
+ quit.expect_objects.append(weakref.ref(self))
176
+ self._available_vars = []
177
+ self._terminal_echo = terminal_echo
178
+
179
+ def set_server_and_command(self, server=None, command=None, server_tmpdir=None, ulimit=None):
180
+ """
181
+ Changes the server and the command to use for this interface.
182
+
183
+ This raises a :exc:`RuntimeError` if the interface is already started.
184
+
185
+ INPUT:
186
+
187
+ - ``server`` -- string or ``None`` (default); name of a remote host to connect to using ``ssh``
188
+
189
+ - ``command`` -- one of:
190
+
191
+ - a string; command line passed to the shell
192
+
193
+ - a sequence of an :class:`~sage.features.Executable` and strings, arguments to
194
+ pass to the executable.
195
+
196
+ EXAMPLES::
197
+
198
+ sage: magma.set_server_and_command(server='remote', command='mymagma') # indirect doctest
199
+ No remote temporary directory (option server_tmpdir) specified, using /tmp/ on remote
200
+ sage: magma.server()
201
+ 'remote'
202
+ sage: magma.command()
203
+ 'ssh -t remote mymagma'
204
+ """
205
+ if self._expect:
206
+ raise RuntimeError("interface has already started")
207
+ self._server = server
208
+ self.__remote_ulimit = ulimit
209
+ if server is not None:
210
+ self.__is_remote = True
211
+ self._eval_using_file_cutoff = 0 # don't allow this!
212
+ if self.__verbose_start:
213
+ print("Using remote server")
214
+ if server_tmpdir is None:
215
+ # TO DO: Why default to /tmp/? Might be better to use the expect process itself to get a tmp folder
216
+ print("No remote temporary directory (option server_tmpdir) specified, using /tmp/ on " + server)
217
+ self.__remote_tmpdir = "/tmp/"
218
+ else:
219
+ self.__remote_tmpdir = server_tmpdir
220
+ else:
221
+ self.__is_remote = False
222
+ self.__command = command
223
+
224
+ def server(self):
225
+ """
226
+ Return the server used in this interface.
227
+
228
+ EXAMPLES::
229
+
230
+ sage: magma.set_server_and_command(server='remote')
231
+ No remote temporary directory (option server_tmpdir) specified, using /tmp/ on remote
232
+ sage: magma.server() # indirect doctest
233
+ 'remote'
234
+ """
235
+ return self._server
236
+
237
+ def command(self):
238
+ """
239
+ Return the command used in this interface as a string.
240
+
241
+ EXAMPLES::
242
+
243
+ sage: magma.set_server_and_command(command='magma-2.19')
244
+ sage: magma.command() # indirect doctest
245
+ 'magma-2.19'
246
+ """
247
+ command = self.__command
248
+ server = self.server()
249
+ if command is None:
250
+ env_name = 'SAGE_%s_{}' % self.name().upper() # same as in __init__
251
+ command = os.getenv(env_name.format('COMMAND'), self.name())
252
+ elif not isinstance(command, str):
253
+ executable = command[0]
254
+ if server:
255
+ executable = executable.name
256
+ else:
257
+ executable = executable.absolute_filename()
258
+ command = ' '.join([shlex.quote(executable)]
259
+ + [shlex.quote(arg) for arg in command[1:]])
260
+ if server:
261
+ if self.__remote_ulimit:
262
+ command = f"ulimit {self.__remote_ulimit}; {command}"
263
+ command = f"ssh -t {shlex.quote(server)} {shlex.quote(command)}"
264
+
265
+ return command
266
+
267
+ def _get(self, wait=0.1, alternate_prompt=None):
268
+ if self._expect is None:
269
+ self._start()
270
+ E = self._expect
271
+ wait = float(wait)
272
+ try:
273
+ if alternate_prompt is None:
274
+ E.expect(self._prompt, timeout=wait)
275
+ else:
276
+ E.expect(str_to_bytes(alternate_prompt), timeout=wait)
277
+ except pexpect.TIMEOUT:
278
+ # TODO: In case an unexpected error occurred it's possible that the
279
+ # contents of E.before, if consisting of multi-byte encoded text,
280
+ # may be incomplete and contain errors, so merely calling
281
+ # bytes_to_str here is probably not sufficient.
282
+ return False, self._before()
283
+ except pexpect.EOF:
284
+ return True, self._before()
285
+ except Exception: # weird major problem!
286
+ return True, self._before()
287
+ return True, self._before()
288
+
289
+ def _send(self, cmd):
290
+ if self._expect is None:
291
+ self._start()
292
+ E = self._expect
293
+ self.__so_far = ''
294
+ E.sendline(cmd)
295
+
296
+ def is_running(self):
297
+ """
298
+ Return ``True`` if ``self`` is currently running.
299
+ """
300
+ if self._expect is None:
301
+ return False
302
+ try:
303
+ os.kill(self._expect.pid, 0)
304
+ except OSError:
305
+ # This means the process is not running
306
+ return False
307
+ return True
308
+
309
+ def _so_far(self, wait=0.1, alternate_prompt=None):
310
+ """
311
+ Return whether done and output so far and new output since last
312
+ time called.
313
+ """
314
+ done, new = self._get(wait=wait, alternate_prompt=alternate_prompt)
315
+ try:
316
+ if done:
317
+ # if new is not None:
318
+ X = self.__so_far + new
319
+ del self.__so_far
320
+ return True, X, new
321
+ # new = self._expect.before
322
+ try:
323
+ self.__so_far += new
324
+ except (AttributeError, TypeError):
325
+ self.__so_far = new
326
+ return False, self.__so_far, new
327
+ except AttributeError as msg: # no __so_far
328
+ raise RuntimeError(msg)
329
+
330
+ def is_remote(self):
331
+ return self.__is_remote
332
+
333
+ def is_local(self):
334
+ return not self.__is_remote
335
+
336
+ def user_dir(self):
337
+ return self.__path
338
+
339
+ def _change_prompt(self, prompt):
340
+ if isinstance(prompt, str):
341
+ prompt = str_to_bytes(prompt)
342
+ elif (isinstance(prompt, type(re.compile(''))) and
343
+ isinstance(prompt.pattern, str)):
344
+ prompt = re.compile(str_to_bytes(prompt.pattern),
345
+ prompt.flags & ~re.U)
346
+ self._prompt = prompt
347
+
348
+ def path(self):
349
+ return self.__path
350
+
351
+ def expect(self):
352
+ if self._expect is None:
353
+ self._start()
354
+ return self._expect
355
+
356
+ def pid(self):
357
+ """
358
+ Return the PID of the underlying sub-process.
359
+
360
+ REMARK:
361
+
362
+ If the interface terminates unexpectedly, the original
363
+ PID will still be used. But if it was terminated using
364
+ :meth:`quit`, a new sub-process with a new PID is
365
+ automatically started.
366
+
367
+ EXAMPLES::
368
+
369
+ sage: pid = gap.pid()
370
+ sage: gap.eval('quit;')
371
+ ''
372
+ sage: pid == gap.pid()
373
+ True
374
+ sage: gap.quit()
375
+ sage: pid == gap.pid()
376
+ False
377
+ """
378
+ if self._expect is None:
379
+ self._start()
380
+ return self._expect.pid
381
+
382
+ def _install_hints(self):
383
+ r"""
384
+ Hints for installing needed slave program on your computer.
385
+
386
+ There are no hints by default.
387
+ """
388
+ return ''
389
+
390
+ def _install_hints_ssh(self):
391
+ r"""
392
+ Hints for installing passwordless authentication on your
393
+ computer...
394
+ """
395
+ # Written by Paul-Olivier Dehaye 2007/08/23
396
+ return """
397
+ In order for Sage (on "local") to launch a "slave" process on "remote", the following command needs to work from local's console, without the need to enter any password:
398
+
399
+ "ssh -t remote slave",
400
+
401
+ where "slave" could be "math" (for text-mode Mathematica), "gap", "magma", "sage", "maple", etc.
402
+
403
+ This thus requires passwordless authentication to be setup, which can be done with commands like these:
404
+ cd; ssh-keygen -t rsa; scp .ssh/id_rsa.pub remote:.ssh/authorized_keys2\n
405
+ (WARNING: this would overwrite your current list of authorized keys on "remote")
406
+
407
+ In many cases, the server that can actually run "slave" is not accessible from the internet directly, but you have to hop through an intermediate trusted server, say "gate".
408
+ If that is your case, get help with _install_hints_ssh_through_gate().
409
+ """
410
+
411
+ def _install_hints_ssh_through_gate(self):
412
+ r"""
413
+ Hints for installing passwordless authentication through a gate
414
+ """
415
+ # Written by Paul-Olivier Dehaye 2007/08/23
416
+ return """
417
+
418
+ We assume you would like to run a "slave" process on a machine called "remote" from a machine running Sage called "local". We also assume "remote" can only be accessed from "local" by ssh'ing first to "gate" (this is a fairly common setup). Sometimes, "gate" and "remote" have a shared filesystem, and this helps a bit.
419
+
420
+ Note: You cannot just create shell scripts on "local" and "gate" that would use two successive SSH connections to "remote" in order to simulate running "slave" locally. This is because Sage will sometimes use files (and scp) to communicate with "remote", which shell scripts would not take care of.
421
+
422
+ You need to setup:
423
+ * passwordless authentication to "gate" from "local"
424
+ * add passwordless authentication to "remote" from "local",
425
+ for instance by appending the file local:~/.ssh/id_rsa.pub to remote:~/.ssh/authorized_keys2 and logging in once
426
+ (this is only needed if "remote" and "gate" don\'t share filesystem)
427
+ * add a few lines to your local:~/.ssh/ssh_config. Mine look like
428
+
429
+ Host remote_for_sage
430
+ ProxyCommand ssh gate nc -w 1 remote 22
431
+
432
+ That's it, normally.
433
+
434
+ The last step tells ssh that whenever an ssh connection is required to
435
+ the host "remote_for_sage", it should tunnel it through "gate". Any
436
+ attempt to scp-connect to "remote_for_sage" will use ssh and thus
437
+ this configuration file, and properly channel those file transfers
438
+ through the tunnel.
439
+
440
+ A good test is to attempt an scp connection from the command-line
441
+ of "local" to "remote_for_sage" as if no tunnel through "gate" was
442
+ required. No password should be asked for the second time around.
443
+
444
+ Finally, we created the new name "remote_for_sage" for "remote",
445
+ but this name only exists locally. this is to avoid interfering
446
+ with any other program that might already ssh to "remote" in
447
+ their own way.
448
+
449
+ If this all works, you can then make calls like:
450
+ math = Mathematica(server='remote_for_sage')
451
+ """
452
+
453
+ def _do_cleaner(self):
454
+ try:
455
+ return self.__do_cleaner
456
+ except AttributeError:
457
+ return False
458
+
459
+ def _start(self, alt_message=None, block_during_init=True):
460
+ if self.is_running():
461
+ # In case one is already running. We check first because
462
+ # quit() can reset the local temporary filename at an
463
+ # unexpected time as the process is started "on demand."
464
+ self.quit()
465
+
466
+ self._session_number += 1
467
+
468
+ if self.__logfile is None:
469
+ # If the 'SAGE_PEXPECT_LOG' environment variable is set and
470
+ # there is no logfile already defined, then create a
471
+ # logfile in .sage/pexpect_logs/
472
+ if self.__logfilename is None and 'SAGE_PEXPECT_LOG' in os.environ:
473
+ from sage.env import DOT_SAGE
474
+ logs = os.path.join(DOT_SAGE, 'pexpect_logs')
475
+ os.makedirs(logs, exist_ok=True)
476
+
477
+ filename = '{name}-{pid}-{id}-{session}'.format(
478
+ name=self.name(), pid=os.getpid(), id=id(self),
479
+ session=self._session_number)
480
+ self.__logfilename = os.path.join(logs, filename)
481
+ if self.__logfilename is not None:
482
+ self.__logfile = open(self.__logfilename, 'wb')
483
+
484
+ cmd = self.command()
485
+
486
+ if self.__verbose_start:
487
+ print(cmd)
488
+ print("Starting %s" % cmd.split()[0])
489
+
490
+ if self.__remote_cleaner and self._server:
491
+ c = 'ssh %s "nohup sage -cleaner" &' % self._server
492
+ os.system(c)
493
+
494
+ # Unset some environment variables for the children to
495
+ # reduce the chances they do something complicated breaking
496
+ # the terminal interface.
497
+ # See Issue #12221 and #13859.
498
+ pexpect_env = dict(os.environ)
499
+ pexpect_env.update(self._env)
500
+ pexpect_del_vars = ['TERM', 'COLUMNS']
501
+ for i in pexpect_del_vars:
502
+ try:
503
+ del pexpect_env[i]
504
+ except KeyError:
505
+ pass
506
+
507
+ # Run child from self.__path
508
+ currentdir = os.getcwd()
509
+ os.chdir(self.__path)
510
+ try:
511
+ try:
512
+ from sage.interfaces.sagespawn import SageSpawn
513
+
514
+ self._expect = SageSpawn(cmd,
515
+ logfile=self.__logfile,
516
+ timeout=None, # no timeout
517
+ env=pexpect_env,
518
+ name=self._repr_(),
519
+ echo=self._terminal_echo,
520
+ # Work around https://bugs.python.org/issue1652
521
+ preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL),
522
+ quit_string=self._quit_string())
523
+
524
+ # Attempt to shutdown the running process gracefully
525
+ # when sage terminates.
526
+ import atexit
527
+ atexit.register(self.quit)
528
+
529
+ except (ExceptionPexpect, pexpect.EOF) as e:
530
+ # Change pexpect errors to RuntimeError
531
+ raise RuntimeError("unable to start %s because the command %r failed: %s\n%s" %
532
+ (self.name(), cmd, e, self._install_hints()))
533
+ except BaseException:
534
+ self._expect = None
535
+ self._session_number = BAD_SESSION
536
+ raise
537
+ finally:
538
+ os.chdir(currentdir)
539
+
540
+ if self._do_cleaner():
541
+ quit.register_spawned_process(self._expect.pid, cmd)
542
+
543
+ try:
544
+ self._expect.expect(self._prompt)
545
+ except (pexpect.TIMEOUT, pexpect.EOF) as msg:
546
+ self._expect = None
547
+ self._session_number = BAD_SESSION
548
+ raise RuntimeError("unable to start %s: %s" % (self.name(), msg))
549
+ self._expect.timeout = None
550
+
551
+ with gc_disabled():
552
+ if block_during_init:
553
+ for X in self.__init_code:
554
+ self.eval(X)
555
+ else:
556
+ for X in self.__init_code:
557
+ self._send(X)
558
+
559
+ def _isalive(self):
560
+ """
561
+ Wrapper for pexpect's ``spawn.isalive()``.
562
+
563
+ Handles an issue where if the underlying process disappear (died / was
564
+ killed and wait()-ed by another process) before pexpect itself could
565
+ wait() on it, then pexpect (really ptyprocess) raises an exception but
566
+ does *not* mark the process as terminated. The same exception results,
567
+ then, from any attempt to close the pexpect process.
568
+
569
+ See https://github.com/sagemath/sage/issues/28354
570
+ """
571
+ try:
572
+ return self._expect is not None and self._expect.isalive()
573
+ except ExceptionPexpect:
574
+ self._expect.ptyproc.terminated = True
575
+ return False
576
+
577
+ def _close(self, force=True):
578
+ """
579
+ Wrapper for pexpect's ``spawn.close()``.
580
+
581
+ Since the underlying method calls ``isalive()`` it is affected by the
582
+ same issue described in ``_isalive()`` above.
583
+ """
584
+ try:
585
+ if self._expect is not None:
586
+ self._expect.close(force=force)
587
+ except (ExceptionPexpect, OSError):
588
+ self._expect.ptyproc.fd = -1
589
+ self._expect.ptyproc.closed = True
590
+ self._expect.child_fd = -1
591
+ self._expect.closed = True
592
+
593
+ def clear_prompts(self):
594
+ while True:
595
+ try:
596
+ self._expect.expect(self._prompt, timeout=0.1)
597
+ except pexpect.TIMEOUT:
598
+ return
599
+
600
+ def _reset_expect(self):
601
+ """
602
+ Delete ``self._expect`` and reset any state.
603
+
604
+ This is called by :meth:`quit` and :meth:`detach`.
605
+
606
+ EXAMPLES::
607
+
608
+ sage: gp("eulerphi(49)")
609
+ 42
610
+ sage: print(gp._expect)
611
+ PARI/GP interpreter with PID ...
612
+ sage: gp._reset_expect()
613
+ sage: print(gp._expect)
614
+ None
615
+ sage: gp("eulerphi(49)")
616
+ 42
617
+ """
618
+ self._session_number += 1
619
+ try:
620
+ # Spaghetti alert: when running several computations in
621
+ # parallel, the pexpect interface is reset in each one,
622
+ # and this next line is needed to trigger the generation
623
+ # of a new temporary file when otherwise the existing
624
+ # member variable would be shared. That also means that
625
+ # you can't use this method to clean up an existing
626
+ # tmpfile, because you can delete the one that the parent
627
+ # is using.
628
+ del self.__local_tmpfile
629
+ except AttributeError:
630
+ pass
631
+ self._expect = None
632
+
633
+ def quit(self, verbose=False):
634
+ """
635
+ Quit the running subprocess.
636
+
637
+ INPUT:
638
+
639
+ - ``verbose`` -- boolean (default: ``False``); whether to print a
640
+ message when quitting the process
641
+
642
+ EXAMPLES::
643
+
644
+ sage: a = maxima('y')
645
+ sage: maxima.quit(verbose=True)
646
+ Exiting Maxima with PID ... running ...maxima...
647
+ sage: a._check_valid()
648
+ Traceback (most recent call last):
649
+ ...
650
+ ValueError: The maxima session in which this object was defined is no longer running.
651
+
652
+ Calling ``quit()`` a second time does nothing::
653
+
654
+ sage: maxima.quit(verbose=True)
655
+ """
656
+ if self._expect is not None:
657
+ if verbose:
658
+ if self.is_remote():
659
+ print("Exiting %r (running on %s)" % (self._expect, self._server))
660
+ else:
661
+ print("Exiting %r" % (self._expect,))
662
+ self._close()
663
+ self._reset_expect()
664
+
665
+ def detach(self):
666
+ """
667
+ Forget the running subprocess: keep it running but pretend that
668
+ it's no longer running.
669
+
670
+ EXAMPLES::
671
+
672
+ sage: a = maxima('y')
673
+ sage: saved_expect = maxima._expect # Save this to close later
674
+ sage: maxima.detach()
675
+ sage: a._check_valid()
676
+ Traceback (most recent call last):
677
+ ...
678
+ ValueError: The maxima session in which this object was defined is no longer running.
679
+ sage: saved_expect.close() # Close child process
680
+
681
+ Calling ``detach()`` a second time does nothing::
682
+
683
+ sage: maxima.detach()
684
+ """
685
+ try:
686
+ self._expect._keep_alive()
687
+ except AttributeError:
688
+ pass
689
+ self._reset_expect()
690
+
691
+ def _quit_string(self):
692
+ """
693
+ Return the string which will be used to quit the application.
694
+
695
+ EXAMPLES::
696
+
697
+ sage: gp._quit_string()
698
+ '\\q'
699
+ sage: maxima._quit_string()
700
+ 'quit();'
701
+ """
702
+ return 'quit'
703
+
704
+ def _send_interrupt(self):
705
+ """
706
+ Send an interrupt to the application. This is used internally
707
+ by :meth:`interrupt`.
708
+
709
+ First CTRL-C to stop the current command, then quit.
710
+ """
711
+ self._expect.sendline(chr(3))
712
+ self._expect.sendline(self._quit_string())
713
+
714
+ def _local_tmpfile(self):
715
+ """
716
+ Return a filename that is used to buffer long command lines for this interface.
717
+
718
+ INPUT:
719
+
720
+ - ``e`` -- an expect interface instance
721
+
722
+ OUTPUT:
723
+
724
+ A string that provides a temporary filename and is unique for the
725
+ given interface.
726
+
727
+ TESTS:
728
+
729
+ The filename is cached::
730
+
731
+ sage: gap._local_tmpfile() is gap._local_tmpfile()
732
+ True
733
+
734
+ The following two problems were fixed in :issue:`10004`.
735
+
736
+ 1. Different interfaces have different temp-files::
737
+
738
+ sage: gap._local_tmpfile() != singular._local_tmpfile()
739
+ True
740
+
741
+ 2. Interface instances in different branches of a parallelised
742
+ function have different temp-files::
743
+
744
+ sage: @parallel
745
+ ....: def f(n):
746
+ ....: return gap._local_tmpfile()
747
+ sage: L = [t[1] for t in f(list(range(5)))]
748
+ sage: len(set(L))
749
+ 5
750
+
751
+ The following used to fail::
752
+
753
+ sage: s = gap._local_tmpfile()
754
+ sage: L = [t[1] for t in f(list(range(5)))]
755
+ sage: len(set(L))
756
+ 5
757
+
758
+ AUTHOR:
759
+
760
+ - Simon King (2010-09): Making the tmp-file unique for the interface instance
761
+ """
762
+ try:
763
+ return self.__local_tmpfile
764
+ except AttributeError:
765
+ pass
766
+
767
+ import atexit
768
+ from tempfile import NamedTemporaryFile
769
+ # FriCAS uses the ".input" suffix, and the other
770
+ # interfaces are suffix-agnostic, so using ".input" here
771
+ # lets us avoid a subclass override for FriCAS.
772
+ with NamedTemporaryFile(suffix='.input', delete=False) as f:
773
+ self.__local_tmpfile = f.name
774
+ atexit.register(lambda: os.remove(f.name))
775
+ return self.__local_tmpfile
776
+
777
+ def _remote_tmpdir(self):
778
+ return self.__remote_tmpdir
779
+
780
+ def _remote_tmpfile(self):
781
+ try:
782
+ return self.__remote_tmpfile
783
+ except AttributeError:
784
+ self.__remote_tmpfile = self._remote_tmpdir() + "/interface_%s:%s" % (LOCAL_IDENTIFIER, self.pid())
785
+ return self.__remote_tmpfile
786
+
787
+ def _send_tmpfile_to_server(self, local_file=None, remote_file=None):
788
+ if local_file is None:
789
+ local_file = self._local_tmpfile()
790
+ if remote_file is None:
791
+ remote_file = self._remote_tmpfile()
792
+ cmd = 'scp "%s" %s:"%s" 1>&2 2>/dev/null' % (local_file, self._server, remote_file)
793
+ os.system(cmd)
794
+
795
+ def _get_tmpfile_from_server(self, local_file=None, remote_file=None):
796
+ if local_file is None:
797
+ local_file = self._local_tmpfile()
798
+ if remote_file is None:
799
+ remote_file = self._remote_tmpfile()
800
+ cmd = 'scp %s:"%s" "%s" 1>&2 2>/dev/null' % (self._server, remote_file, local_file)
801
+ os.system(cmd)
802
+
803
+ def _remove_tmpfile_from_server(self):
804
+ if self.__remote_tmpfile is not None:
805
+ raise NotImplementedError
806
+
807
+ def _eval_line_using_file(self, line, restart_if_needed=True):
808
+ """
809
+ Evaluate a line of commands, using a temporary file.
810
+
811
+ REMARK:
812
+
813
+ By default, this is called when a long command is
814
+ evaluated in :meth:`eval`.
815
+
816
+ If the command can not be evaluated since the interface
817
+ has crashed, it is automatically restarted and tried
818
+ again *once*.
819
+
820
+ INPUT:
821
+
822
+ - ``line`` -- string; a command
823
+ - ``restart_if_needed`` -- boolean (default: ``True``);
824
+ if it is ``True``, the command evaluation is evaluated
825
+ a second time after restarting the interface, if an
826
+ :exc:`EOFError` occurred.
827
+
828
+ TESTS::
829
+
830
+ sage: singular._eval_line_using_file('def a=3;')
831
+ ''
832
+ sage: singular('a')
833
+ 3
834
+ sage: singular.eval('quit;')
835
+ ''
836
+ sage: singular._eval_line_using_file('def a=3;')
837
+ Singular crashed -- automatically restarting.
838
+ ''
839
+ sage: singular('a')
840
+ 3
841
+ sage: singular.eval('quit;')
842
+ ''
843
+ sage: singular._eval_line_using_file('def a=3;', restart_if_needed=False)
844
+ Traceback (most recent call last):
845
+ ...
846
+ RuntimeError: Singular terminated unexpectedly while reading in a large line...
847
+
848
+ We end by triggering a re-start of Singular, since otherwise
849
+ the doc test of another method would fail by a side effect.
850
+ ::
851
+
852
+ sage: singular(3)
853
+ Singular crashed -- automatically restarting.
854
+ 3
855
+ """
856
+ with open(self._local_tmpfile(), 'w') as F:
857
+ F.write(line + '\n')
858
+
859
+ tmp_to_use = self._local_tmpfile()
860
+ if self.is_remote():
861
+ self._send_tmpfile_to_server()
862
+ tmp_to_use = self._remote_tmpfile()
863
+ try:
864
+ s = self._eval_line(self._read_in_file_command(tmp_to_use), allow_use_file=False, restart_if_needed=False)
865
+ except pexpect.EOF:
866
+ if self._quit_string() in line:
867
+ # we expect to get an EOF if we're quitting.
868
+ return ''
869
+ elif restart_if_needed: # the subprocess might have crashed
870
+ try:
871
+ self._synchronize()
872
+ return self._post_process_from_file(self._eval_line_using_file(line, restart_if_needed=False))
873
+ except RuntimeError as msg:
874
+ raise RuntimeError('%s terminated unexpectedly while reading in a large line:\n%s' % (self, msg.args[0]))
875
+ except TypeError:
876
+ pass
877
+ raise RuntimeError('%s terminated unexpectedly while reading in a large line' % self)
878
+ except RuntimeError as msg:
879
+ if self._quit_string() in line:
880
+ if not self._isalive():
881
+ return ''
882
+ raise
883
+ if restart_if_needed and not self._isalive():
884
+ try:
885
+ self._synchronize()
886
+ return self._post_process_from_file(self._eval_line_using_file(line, restart_if_needed=False))
887
+ except TypeError:
888
+ pass
889
+ except RuntimeError:
890
+ raise RuntimeError('%s terminated unexpectedly while reading in a large line' % self)
891
+ if "Input/output error" in msg.args[0]:
892
+ # This occurs on non-linux machines
893
+ raise RuntimeError('%s terminated unexpectedly while reading in a large line' % self)
894
+ raise RuntimeError('%s terminated unexpectedly while reading in a large line:\n%s' % (self, msg.args[0]))
895
+ return self._post_process_from_file(s)
896
+
897
+ def _post_process_from_file(self, s):
898
+ return s
899
+
900
+ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if_needed=True):
901
+ """
902
+ Evaluate a line of commands.
903
+
904
+ REMARK:
905
+
906
+ By default, a long command (length exceeding ``self._eval_using_file_cutoff``)
907
+ is evaluated using :meth:`_eval_line_using_file`.
908
+
909
+ If the command can not be evaluated since the interface
910
+ has crashed, it is automatically restarted and tried
911
+ again *once*.
912
+
913
+ If the optional ``wait_for_prompt`` is ``False`` then even a very
914
+ long line will not be evaluated by :meth:`_eval_line_using_file`,
915
+ since this does not support the ``wait_for_prompt`` option.
916
+
917
+ INPUT:
918
+
919
+ - ``line`` -- string; a command
920
+ - ``allow_use_file`` -- boolean (default: ``True``);
921
+ allow to evaluate long commands using :meth:`_eval_line_using_file`.
922
+ - ``wait_for_prompt`` -- boolean (default: ``True``);
923
+ wait until the prompt appears in the sub-process' output.
924
+ - ``restart_if_needed`` -- boolean (default: ``True``);
925
+ if it is ``True``, the command evaluation is evaluated
926
+ a second time after restarting the interface, if an
927
+ :exc:`EOFError` occurred.
928
+
929
+ TESTS::
930
+
931
+ sage: from sage.interfaces.singular import singular
932
+ sage: singular._eval_line('def a=3;')
933
+ ''
934
+ sage: singular('a')
935
+ 3
936
+ sage: singular.eval('quit;')
937
+ ''
938
+ sage: singular._eval_line('def a=3;')
939
+ Singular crashed -- automatically restarting.
940
+ ''
941
+ sage: singular('a')
942
+ 3
943
+ sage: singular.eval('kill a')
944
+ ''
945
+
946
+ We are now sending a command that would run forever. But since
947
+ we declare that we are not waiting for a prompt, we can interrupt
948
+ it without a KeyboardInterrupt. At the same time, we test that
949
+ the line is not forwarded to :meth:`_eval_line_using_file`, since
950
+ that method would not support the ``wait_for_prompt`` option.
951
+ For reasons which are currently not understood, the ``interrupt``
952
+ test usually returns immediately, but sometimes it takes a very
953
+ long time on the same system. ::
954
+
955
+ sage: cutoff = singular._eval_using_file_cutoff
956
+ sage: singular._eval_using_file_cutoff = 4
957
+ sage: singular._eval_line('for(int i=1;i<=3;i++){i=1;};', wait_for_prompt=False)
958
+ ''
959
+ sage: singular.interrupt()
960
+ True
961
+ sage: singular._eval_using_file_cutoff = cutoff
962
+
963
+ The interface still works after this interrupt::
964
+
965
+ sage: singular('2+3')
966
+ 5
967
+
968
+ Last, we demonstrate that by default the execution of a command
969
+ is tried twice if it fails the first time due to a crashed
970
+ interface::
971
+
972
+ sage: singular.eval('quit;')
973
+ ''
974
+ sage: singular._eval_line_using_file('def a=3;', restart_if_needed=False)
975
+ Traceback (most recent call last):
976
+ ...
977
+ RuntimeError: Singular terminated unexpectedly while reading in a large line...
978
+
979
+ Since the test of the next method would fail, we re-start
980
+ Singular now. ::
981
+
982
+ sage: singular('2+3')
983
+ Singular crashed -- automatically restarting.
984
+ 5
985
+ """
986
+ if allow_use_file and wait_for_prompt and self._eval_using_file_cutoff and len(line) > self._eval_using_file_cutoff:
987
+ return self._eval_line_using_file(line)
988
+ try:
989
+ if self._expect is None:
990
+ self._start()
991
+ E = self._expect
992
+ try:
993
+ if len(line) >= 4096:
994
+ raise RuntimeError("Sending more than 4096 characters with %s on a line may cause a hang and you're sending %s characters" % (self, len(line)))
995
+ E.sendline(line)
996
+ if not wait_for_prompt:
997
+ return ''
998
+
999
+ except OSError as msg:
1000
+ if restart_if_needed:
1001
+ # The subprocess most likely crashed.
1002
+ # If it's really still alive, we fall through
1003
+ # and raise RuntimeError.
1004
+ if sys.platform.startswith('sunos'):
1005
+ # On (Open)Solaris, we might need to wait a
1006
+ # while because the process might not die
1007
+ # immediately. See Issue #14371.
1008
+ for t in [0.5, 1.0, 2.0]:
1009
+ if self._isalive():
1010
+ time.sleep(t)
1011
+ else:
1012
+ break
1013
+ if not self._isalive():
1014
+ try:
1015
+ self._synchronize()
1016
+ except (TypeError, RuntimeError):
1017
+ pass
1018
+ return self._eval_line(line, allow_use_file=allow_use_file, wait_for_prompt=wait_for_prompt, restart_if_needed=False)
1019
+ raise RuntimeError("%s\nError evaluating %s in %s" % (msg, line, self))
1020
+
1021
+ if line:
1022
+ try:
1023
+ if isinstance(wait_for_prompt, str):
1024
+ E.expect(str_to_bytes(wait_for_prompt))
1025
+ else:
1026
+ E.expect(self._prompt)
1027
+ except pexpect.EOF as msg:
1028
+ try:
1029
+ if self.is_local():
1030
+ tmp_to_use = self._local_tmpfile()
1031
+ else:
1032
+ tmp_to_use = self._remote_tmpfile()
1033
+ if self._read_in_file_command(tmp_to_use) in line:
1034
+ raise pexpect.EOF(msg)
1035
+ except NotImplementedError:
1036
+ pass
1037
+ if self._quit_string() in line:
1038
+ # we expect to get an EOF if we're quitting.
1039
+ return ''
1040
+ elif restart_if_needed: # the subprocess might have crashed
1041
+ try:
1042
+ self._synchronize()
1043
+ return self._eval_line(line, allow_use_file=allow_use_file, wait_for_prompt=wait_for_prompt, restart_if_needed=False)
1044
+ except (TypeError, RuntimeError):
1045
+ pass
1046
+ raise RuntimeError("%s\n%s crashed executing %s" % (msg, self, line))
1047
+ if self._terminal_echo:
1048
+ out = self._before()
1049
+ else:
1050
+ out = self._before().rstrip('\n\r')
1051
+ else:
1052
+ if self._terminal_echo:
1053
+ out = '\n\r'
1054
+ else:
1055
+ out = ''
1056
+ except KeyboardInterrupt:
1057
+ self._keyboard_interrupt()
1058
+ raise KeyboardInterrupt("Ctrl-c pressed while running %s" % self)
1059
+ if self._terminal_echo:
1060
+ i = out.find("\n")
1061
+ j = out.rfind("\r")
1062
+ return out[i + 1:j].replace('\r\n', '\n')
1063
+ else:
1064
+ return out.replace('\r\n', '\n')
1065
+
1066
+ def _keyboard_interrupt(self):
1067
+ print("Interrupting %s..." % self)
1068
+ if self._restart_on_ctrlc:
1069
+ try:
1070
+ self._close()
1071
+ except pexpect.ExceptionPexpect as msg:
1072
+ raise pexpect.ExceptionPexpect("THIS IS A BUG -- PLEASE REPORT. This should never happen.\n" + msg)
1073
+ self._start()
1074
+ raise KeyboardInterrupt("Restarting %s (WARNING: all variables defined in previous session are now invalid)" % self)
1075
+ else:
1076
+ self._expect.sendline(chr(3)) # send ctrl-c
1077
+ self._expect.expect(self._prompt)
1078
+ self._expect.expect(self._prompt)
1079
+ raise KeyboardInterrupt("Ctrl-c pressed while running %s" % self)
1080
+
1081
+ def interrupt(self, tries=5, timeout=2.0, quit_on_fail=True):
1082
+ E = self._expect
1083
+ if E is None:
1084
+ return True
1085
+ try:
1086
+ for i in range(tries):
1087
+ self._send_interrupt()
1088
+ try:
1089
+ E.expect(self._prompt, timeout=timeout)
1090
+ except (pexpect.TIMEOUT, pexpect.EOF):
1091
+ pass
1092
+ else:
1093
+ return True # Success
1094
+ except Exception:
1095
+ pass
1096
+ # Failed to interrupt...
1097
+ if quit_on_fail:
1098
+ self.quit()
1099
+ return False
1100
+
1101
+ ###########################################################################
1102
+ # BEGIN Synchronization code.
1103
+ ###########################################################################
1104
+
1105
+ def _before(self, encoding=None, errors=None) -> str:
1106
+ r"""
1107
+ Return the previous string that was sent through the interface.
1108
+
1109
+ This returns a ``str`` object.
1110
+
1111
+ The ``encoding`` and ``errors`` arguments are passed to
1112
+ :func:`sage.misc.cpython.bytes_to_str`.
1113
+
1114
+ EXAMPLES::
1115
+
1116
+ sage: singular('2+3')
1117
+ 5
1118
+ sage: singular._before()
1119
+ '5\r\n'
1120
+ """
1121
+ return bytes_to_str(self._expect.before, encoding, errors)
1122
+
1123
+ def _after(self, encoding=None, errors=None):
1124
+ r"""
1125
+ Return trailing data in the buffer after the text matched by the expect
1126
+ interface.
1127
+
1128
+ When the ``spawn.after`` attribute contains bytes, this returns ``str``
1129
+ objects on both Python 2 and Python 3. There are also cases (such as
1130
+ exceptions) where the ``.after`` attribute contains either an exception
1131
+ type or ``None``, in which case those values are returned.
1132
+
1133
+ The ``encoding`` and ``errors`` arguments are passed to
1134
+ :func:`sage.misc.cpython.bytes_to_str`.
1135
+
1136
+ EXAMPLES::
1137
+
1138
+ sage: singular('2+3')
1139
+ 5
1140
+ sage: singular._after()
1141
+ '> '
1142
+ """
1143
+ after = self._expect.after
1144
+ if isinstance(after, bytes):
1145
+ return bytes_to_str(after, encoding, errors)
1146
+
1147
+ return after
1148
+
1149
+ def _readline(self, size=-1, encoding=None, errors=None) -> str:
1150
+ r"""
1151
+ Wraps ``spawn.readline`` to pass the return values through
1152
+ ``bytes_to_str``, like `Expect._before` and `Expect._after`.
1153
+
1154
+ EXAMPLES::
1155
+
1156
+ sage: a = singular(1)
1157
+ sage: singular._expect.sendline('1+1;')
1158
+ 5
1159
+ sage: singular._readline()
1160
+ '2\r\n'
1161
+ """
1162
+ return bytes_to_str(self._expect.readline(size=size), encoding, errors)
1163
+
1164
+ def _interrupt(self):
1165
+ for i in range(15):
1166
+ try:
1167
+ self._sendstr('quit;\n' + chr(3))
1168
+ self._expect_expr(timeout=2)
1169
+ except pexpect.TIMEOUT:
1170
+ pass
1171
+ except pexpect.EOF:
1172
+ self._crash_msg()
1173
+ self.quit()
1174
+ else:
1175
+ return
1176
+
1177
+ def _expect_expr(self, expr=None, timeout=None):
1178
+ r"""
1179
+ Wait for a given expression expr (which could be a regular
1180
+ expression or list of regular expressions) to appear in the output
1181
+ for at most timeout seconds.
1182
+
1183
+ Use ``r._expect.before`` to see what was put in the
1184
+ output stream before the expression.
1185
+
1186
+ INPUT:
1187
+
1188
+ - ``expr`` -- ``None`` or a string or list of strings
1189
+ (default: ``None``)
1190
+
1191
+ - ``timeout`` -- ``None`` or a number (default: ``None``)
1192
+
1193
+ EXAMPLES:
1194
+
1195
+ We test all of this using the Singular interface. First we put
1196
+ 10 + 15 in the input stream::
1197
+
1198
+ sage: singular._sendstr('def abc = 10 + 15;\n')
1199
+
1200
+ Then we tell singular to print 10, which is an arbitrary number
1201
+ different from the expected result 35::
1202
+
1203
+ sage: singular._sendstr('10;\n')
1204
+
1205
+ Here an exception is raised because 25 hasn't appeared yet in the
1206
+ output stream. The key thing is that this doesn't lock, but instead
1207
+ quickly raises an exception::
1208
+
1209
+ sage: t = walltime()
1210
+ sage: try:
1211
+ ....: singular._expect_expr('25', timeout=float(0.4))
1212
+ ....: except Exception:
1213
+ ....: print('Did not get expression')
1214
+ Did not get expression
1215
+
1216
+ A quick consistency check on the time that the above took::
1217
+
1218
+ sage: w = walltime(t); 0.3 < w < 10
1219
+ True
1220
+
1221
+ We tell Singular to print abc, which equals 25::
1222
+
1223
+ sage: singular._sendstr('abc;\n')
1224
+
1225
+ Now 25 is in the output stream, so we can wait for it::
1226
+
1227
+ sage: singular._expect_expr('25')
1228
+
1229
+ This gives us everything before the 25, including the 10 we printed earlier::
1230
+
1231
+ sage: singular._expect.before.decode('ascii')
1232
+ '...10\r\n> '
1233
+
1234
+ We test interrupting ``_expect_expr`` using the GP interface,
1235
+ see :issue:`6661`. Unfortunately, this test doesn't work reliably using
1236
+ Singular, see :issue:`9163` and the follow-up :issue:`10476`.
1237
+ The ``gp.eval('0')`` in this test makes sure that ``gp`` is
1238
+ running, so a timeout of 1 second should be sufficient. ::
1239
+
1240
+ sage: print(sage0.eval("dummy=gp.eval('0'); alarm(1); gp._expect_expr('1')")) # long time
1241
+ ...Interrupting PARI/GP interpreter. Please wait a few seconds...
1242
+ ...
1243
+ ...AlarmInterrupt...
1244
+ """
1245
+ if expr is None:
1246
+ # the following works around gap._prompt_wait not being defined
1247
+ expr = getattr(self, '_prompt_wait', None) or self._prompt
1248
+ if self._expect is None:
1249
+ self._start()
1250
+ try:
1251
+ if timeout:
1252
+ i = self._expect.expect(expr, timeout=timeout)
1253
+ else:
1254
+ i = self._expect.expect(expr)
1255
+ if i > 0:
1256
+ v = self._before()
1257
+ self.quit()
1258
+ raise ValueError("%s\nComputation failed due to a bug in %s -- NOTE: Had to restart." % (v, self))
1259
+ except KeyboardInterrupt:
1260
+ print("Control-C pressed. Interrupting %s. Please wait a few seconds..." % self)
1261
+ self.interrupt()
1262
+ raise
1263
+
1264
+ def _sendstr(self, string):
1265
+ r"""
1266
+ Send a string to the pexpect interface, autorestarting the expect
1267
+ interface if anything goes wrong.
1268
+
1269
+ INPUT:
1270
+
1271
+ - ``string`` -- string
1272
+
1273
+ EXAMPLES: We illustrate this function using the Singular interface::
1274
+
1275
+ sage: singular._synchronize()
1276
+ sage: singular._sendstr('int i = 5;')
1277
+ sage: singular('i')
1278
+ 5
1279
+ """
1280
+ if self._expect is None:
1281
+ self._start()
1282
+ try:
1283
+ os.write(self._expect.child_fd, str_to_bytes(string))
1284
+ except OSError:
1285
+ self._crash_msg()
1286
+ self.quit()
1287
+ self._sendstr(string)
1288
+
1289
+ def _crash_msg(self):
1290
+ r"""
1291
+ Show a message if the interface crashed.
1292
+
1293
+ EXAMPLES::
1294
+
1295
+ sage: singular._crash_msg()
1296
+ Singular crashed -- automatically restarting.
1297
+
1298
+ ::
1299
+
1300
+ sage: singular('2+3')
1301
+ 5
1302
+ sage: singular._sendstr('quit;\n') # make it so that singular appears to die.
1303
+ sage: singular('2+3')
1304
+ Singular crashed -- automatically restarting.
1305
+ 5
1306
+ """
1307
+ print("%s crashed -- automatically restarting." % self)
1308
+
1309
+ def _synchronize(self, cmd='1+%s;\n'):
1310
+ """
1311
+ Synchronize pexpect interface.
1312
+
1313
+ This put a random integer (plus one!) into the output stream, then
1314
+ waits for it, thus resynchronizing the stream. If the random
1315
+ integer doesn't appear within 1 second, the interface is sent
1316
+ interrupt signals.
1317
+
1318
+ This way, even if you somehow left the interface in a busy state
1319
+ computing, calling _synchronize gets everything fixed.
1320
+
1321
+ EXAMPLES: We observe nothing, just as it should be::
1322
+
1323
+ sage: singular._synchronize()
1324
+
1325
+ TESTS:
1326
+
1327
+ This illustrates a synchronization bug being fixed (thanks
1328
+ to Simon King and David Joyner for tracking this down)::
1329
+
1330
+ sage: R.<x> = QQ[]; f = x^3 + x + 1; g = x^3 - x - 1; r = f.resultant(g); gap(ZZ); singular(R)
1331
+ Integers
1332
+ polynomial ring, over a field, global ordering
1333
+ // coefficients: QQ...
1334
+ // number of vars : 1
1335
+ // block 1 : ordering lp
1336
+ // : names x
1337
+ // block 2 : ordering C
1338
+ """
1339
+ if self._expect is None:
1340
+ return
1341
+ rnd = randrange(2147483647)
1342
+ s = str(rnd + 1)
1343
+ cmd = cmd % rnd
1344
+ self._sendstr(cmd)
1345
+ try:
1346
+ self._expect_expr(timeout=0.5)
1347
+ if s not in self._before():
1348
+ self._expect_expr(s, timeout=0.5)
1349
+ self._expect_expr(timeout=0.5)
1350
+ except pexpect.TIMEOUT:
1351
+ self._interrupt()
1352
+ except pexpect.EOF:
1353
+ self._crash_msg()
1354
+ self.quit()
1355
+
1356
+ ###########################################################################
1357
+ # END Synchronization code.
1358
+ ###########################################################################
1359
+
1360
+ def eval(self, code, strip=True, synchronize=False, locals=None, allow_use_file=True,
1361
+ split_lines='nofile', **kwds):
1362
+ """
1363
+ INPUT:
1364
+
1365
+ - ``code`` -- text to evaluate
1366
+
1367
+ - ``strip`` -- boolean; whether to strip output prompts,
1368
+ etc. (ignored in the base class)
1369
+
1370
+ - ``locals`` -- None (ignored); this is used for compatibility
1371
+ with the Sage notebook's generic system interface
1372
+
1373
+ - ``allow_use_file`` -- boolean (default: ``True``); if ``True`` and
1374
+ ``code`` exceeds an interface-specific threshold then ``code`` will
1375
+ be communicated via a temporary file rather that the character-based
1376
+ interface. If ``False`` then the code will be communicated via the
1377
+ character interface.
1378
+
1379
+ - ``split_lines`` -- Tri-state (default: ``'nofile'``); if "nofile"
1380
+ then ``code`` is sent line by line unless it gets communicated via a
1381
+ temporary file. If ``True`` then ``code`` is sent line by line, but
1382
+ some lines individually might be sent via temporary file. Depending
1383
+ on the interface, this may transform grammatical ``code`` into
1384
+ ungrammatical input. If ``False``, then the whole block of code is
1385
+ evaluated all at once.
1386
+
1387
+ - ``**kwds`` -- all other arguments are passed onto the ``_eval_line``
1388
+ method. An often useful example is ``reformat=False``.
1389
+ """
1390
+ if synchronize:
1391
+ try:
1392
+ self._synchronize()
1393
+ except AttributeError:
1394
+ pass
1395
+
1396
+ if strip:
1397
+ try:
1398
+ code = self._strip_prompt(code)
1399
+ except AttributeError:
1400
+ pass
1401
+
1402
+ if not isinstance(code, str):
1403
+ raise TypeError('input code must be a string.')
1404
+
1405
+ # Remove extra whitespace
1406
+ code = code.strip()
1407
+
1408
+ try:
1409
+ with gc_disabled():
1410
+ if (split_lines == "nofile" and allow_use_file and
1411
+ self._eval_using_file_cutoff and len(code) > self._eval_using_file_cutoff):
1412
+ return self._eval_line_using_file(code)
1413
+ elif split_lines:
1414
+ return '\n'.join(self._eval_line(L, allow_use_file=allow_use_file, **kwds)
1415
+ for L in code.split('\n') if L)
1416
+ else:
1417
+ return self._eval_line(code, allow_use_file=allow_use_file, **kwds)
1418
+ # DO NOT CATCH KeyboardInterrupt, as it is being caught
1419
+ # by _eval_line
1420
+ # In particular, do NOT call self._keyboard_interrupt()
1421
+ except TypeError as s:
1422
+ raise TypeError('error evaluating "%s":\n%s' % (code, s))
1423
+
1424
+ ############################################################
1425
+ # Functions for working with variables.
1426
+ # The first three must be overloaded by derived classes,
1427
+ # and the definition depends a lot on the class. But
1428
+ # the functionality one gets from this is very nice.
1429
+ ############################################################
1430
+
1431
+ def _object_class(self):
1432
+ """
1433
+ EXAMPLES::
1434
+
1435
+ sage: from sage.interfaces.expect import Expect
1436
+ sage: Expect._object_class(maxima)
1437
+ <class 'sage.interfaces.expect.ExpectElement'>
1438
+ """
1439
+ return ExpectElement
1440
+
1441
+ def _function_class(self):
1442
+ """
1443
+ EXAMPLES::
1444
+
1445
+ sage: from sage.interfaces.expect import Expect
1446
+ sage: Expect._function_class(maxima)
1447
+ <class 'sage.interfaces.expect.ExpectFunction'>
1448
+ """
1449
+ return ExpectFunction
1450
+
1451
+ def _function_element_class(self):
1452
+ """
1453
+ EXAMPLES::
1454
+
1455
+ sage: from sage.interfaces.expect import Expect
1456
+ sage: Expect._function_element_class(maxima)
1457
+ <class 'sage.interfaces.expect.FunctionElement'>
1458
+ """
1459
+ return FunctionElement
1460
+
1461
+
1462
+ @instancedoc
1463
+ class ExpectFunction(InterfaceFunction):
1464
+ """
1465
+ Expect function.
1466
+ """
1467
+ pass
1468
+
1469
+
1470
+ @instancedoc
1471
+ class FunctionElement(InterfaceFunctionElement):
1472
+ """
1473
+ Expect function element.
1474
+ """
1475
+ pass
1476
+
1477
+
1478
+ def is_ExpectElement(x):
1479
+ """
1480
+ Return ``True`` if ``x`` is of type :class:`ExpectElement`.
1481
+
1482
+ This function is deprecated; use :func:`isinstance`
1483
+ (of :class:`sage.interfaces.abc.ExpectElement`) instead.
1484
+
1485
+ EXAMPLES::
1486
+
1487
+ sage: from sage.interfaces.expect import is_ExpectElement
1488
+ sage: is_ExpectElement(2)
1489
+ doctest:...: DeprecationWarning: the function is_ExpectElement is deprecated; use isinstance(x, sage.interfaces.abc.ExpectElement) instead
1490
+ See https://github.com/sagemath/sage/issues/34804 for details.
1491
+ False
1492
+ """
1493
+ from sage.misc.superseded import deprecation
1494
+ deprecation(34804, "the function is_ExpectElement is deprecated; use isinstance(x, sage.interfaces.abc.ExpectElement) instead")
1495
+
1496
+ return isinstance(x, ExpectElement)
1497
+
1498
+
1499
+ @instancedoc
1500
+ class ExpectElement(InterfaceElement, sage.interfaces.abc.ExpectElement):
1501
+ """
1502
+ Expect element.
1503
+ """
1504
+ def __init__(self, parent, value, is_name=False, name=None):
1505
+ RingElement.__init__(self, parent)
1506
+ self._create = value
1507
+ if parent is None:
1508
+ return # means "invalid element"
1509
+ # idea: Joe Wetherell -- try to find out if the output
1510
+ # is too long and if so get it using file, otherwise
1511
+ # don't.
1512
+ if isinstance(value, str) and parent._eval_using_file_cutoff and \
1513
+ parent._eval_using_file_cutoff < len(value):
1514
+ self._get_using_file = True
1515
+
1516
+ if is_name:
1517
+ self._name = value
1518
+ else:
1519
+ try:
1520
+ self._name = parent._create(value, name=name)
1521
+ # Convert ValueError and RuntimeError to TypeError for
1522
+ # coercion to work properly.
1523
+ except (RuntimeError, ValueError) as x:
1524
+ self._session_number = -1
1525
+ raise TypeError(*x.args)
1526
+ except BaseException:
1527
+ self._session_number = -1
1528
+ raise
1529
+ self._session_number = parent._session_number
1530
+
1531
+ def __hash__(self):
1532
+ """
1533
+ Return the hash of ``self``.
1534
+
1535
+ This is a default implementation of hash
1536
+ which just takes the hash of the string of ``self``.
1537
+ """
1538
+ return hash('%s%s' % (self, self._session_number))
1539
+
1540
+ def _check_valid(self):
1541
+ """
1542
+ Check that this object is valid, i.e., the session in which this
1543
+ object is defined is still running. This is relevant for
1544
+ interpreters that can't be interrupted via ctrl-C, hence get
1545
+ restarted.
1546
+ """
1547
+ try:
1548
+ P = self.parent()
1549
+ if P is None or P._session_number == BAD_SESSION or self._session_number == -1 or \
1550
+ P._session_number != self._session_number:
1551
+ raise ValueError("The %s session in which this object was defined is no longer running." % P.name())
1552
+ except AttributeError:
1553
+ raise ValueError("The session in which this object was defined is no longer running.")
1554
+ return P
1555
+
1556
+ def __del__(self):
1557
+ try:
1558
+ self._check_valid()
1559
+ except ValueError:
1560
+ return
1561
+ try:
1562
+ if hasattr(self, '_name'):
1563
+ P = self.parent()
1564
+ if P is not None:
1565
+ P.clear(self._name)
1566
+
1567
+ except (RuntimeError, ExceptionPexpect): # needed to avoid infinite loops in some rare cases
1568
+ pass
1569
+
1570
+ # def _sage_repr(self):
1571
+ # TO DO: this could use file transfers when self.is_remote()
1572
+
1573
+
1574
+ class StdOutContext:
1575
+ """
1576
+ A context in which all communication between Sage and a subprocess
1577
+ interfaced via pexpect is printed to stdout.
1578
+ """
1579
+ def __init__(self, interface, silent=False, stdout=None):
1580
+ """
1581
+ Construct a new context in which all communication between Sage
1582
+ and a subprocess interfaced via pexpect is printed to stdout.
1583
+
1584
+ INPUT:
1585
+
1586
+ - ``interface`` -- the interface whose communication shall be dumped
1587
+
1588
+ - ``silent`` -- if ``True`` this context does nothing
1589
+
1590
+ - ``stdout`` -- (optional) parameter for alternative stdout device (default: ``None``)
1591
+
1592
+ EXAMPLES::
1593
+
1594
+ sage: from sage.interfaces.expect import StdOutContext
1595
+ sage: with StdOutContext(Gp()) as g:
1596
+ ....: g('1+1')
1597
+ sage=...
1598
+ """
1599
+ self.interface = interface
1600
+ self.silent = silent
1601
+ self.stdout = stdout if stdout else sys.stdout
1602
+
1603
+ def __enter__(self):
1604
+ """
1605
+ EXAMPLES::
1606
+
1607
+ sage: from sage.interfaces.expect import StdOutContext
1608
+ sage: with StdOutContext(singular):
1609
+ ....: singular.eval('1+1')
1610
+ 1+1;
1611
+ ...
1612
+ """
1613
+ if self.silent:
1614
+ return self.interface
1615
+ if self.interface._expect is None:
1616
+ self.interface._start()
1617
+ self._logfile_backup = self.interface._expect.logfile
1618
+
1619
+ if isinstance(self.stdout, io.TextIOWrapper):
1620
+ stdout = self.stdout.buffer
1621
+ else:
1622
+ stdout = self.stdout
1623
+
1624
+ if self.interface._expect.logfile:
1625
+ self.interface._expect.logfile = Multiplex(self.interface._expect.logfile, stdout)
1626
+ else:
1627
+ self.interface._expect.logfile = Multiplex(stdout)
1628
+ return self.interface
1629
+
1630
+ def __exit__(self, typ, value, tb):
1631
+ r"""
1632
+ EXAMPLES::
1633
+
1634
+ sage: from sage.interfaces.expect import StdOutContext
1635
+ sage: with StdOutContext(gap):
1636
+ ....: gap('1+1')
1637
+ \$sage...
1638
+ """
1639
+ if self.silent:
1640
+ return
1641
+ self.interface._expect.logfile.flush()
1642
+ self.stdout.write("\n")
1643
+ self.interface._expect.logfile = self._logfile_backup