passagemath-repl 10.5.42__py3-none-any.whl → 10.6.1rc1__py3-none-any.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.
- passagemath_repl-10.6.1rc1.data/data/share/jupyter/kernels/sagemath/kernel.json +1 -0
- {passagemath_repl-10.5.42.dist-info → passagemath_repl-10.6.1rc1.dist-info}/METADATA +5 -6
- {passagemath_repl-10.5.42.dist-info → passagemath_repl-10.6.1rc1.dist-info}/RECORD +56 -57
- sage/all__sagemath_repl.py +0 -6
- sage/doctest/__main__.py +1 -1
- sage/doctest/control.py +30 -28
- sage/doctest/external.py +31 -27
- sage/doctest/fixtures.py +37 -11
- sage/doctest/forker.py +8 -5
- sage/doctest/parsing.py +42 -27
- sage/doctest/sources.py +10 -0
- sage/doctest/test.py +18 -5
- sage/doctest/tests/fail_and_die.rst +4 -1
- sage/doctest/util.py +15 -6
- sage/misc/banner.py +12 -4
- sage/misc/cython.py +8 -5
- sage/misc/dev_tools.py +10 -84
- sage/misc/gperftools.py +13 -14
- sage/repl/configuration.py +4 -4
- sage/repl/ipython_extension.py +12 -8
- sage/repl/ipython_kernel/install.py +1 -1
- sage/repl/ipython_kernel/widgets.py +1 -1
- sage/repl/ipython_tests.py +19 -2
- sage/repl/rich_output/backend_ipython.py +0 -1
- sage/repl/rich_output/display_manager.py +1 -1
- sage/tests/all.py +1 -0
- sage/tests/benchmark.py +6 -2
- sage/tests/books/computational-mathematics-with-sagemath/domaines_doctest.py +1 -1
- sage/tests/books/computational-mathematics-with-sagemath/linsolve_doctest.py +1 -1
- sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py +1 -1
- sage/tests/books/computational-mathematics-with-sagemath/premierspas_doctest.py +1 -1
- sage/tests/books/computational-mathematics-with-sagemath/sol/mpoly_doctest.py +1 -1
- sage/tests/cmdline.py +6 -4
- sage/tests/startup.py +1 -1
- passagemath_repl-10.5.42.data/data/share/jupyter/kernels/sagemath/kernel.json +0 -1
- sage/interfaces/cleaner.py +0 -48
- sage/interfaces/quit.py +0 -178
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/data/share/jupyter/kernels/sagemath/logo-64x64.png +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/data/share/jupyter/kernels/sagemath/logo.svg +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-cachegrind +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-callgrind +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-cleaner +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-coverage +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-eval +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-fixdoctests +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-inline-fortran +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-ipynb2rst +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-ipython +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-massif +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-notebook +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-omega +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-preparse +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-run +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-run-cython +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-runtests +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-startuptime.py +0 -0
- {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-valgrind +0 -0
- {passagemath_repl-10.5.42.dist-info → passagemath_repl-10.6.1rc1.dist-info}/WHEEL +0 -0
- {passagemath_repl-10.5.42.dist-info → passagemath_repl-10.6.1rc1.dist-info}/top_level.txt +0 -0
sage/doctest/fixtures.py
CHANGED
@@ -33,15 +33,15 @@ communicates with its surroundings::
|
|
33
33
|
exit f -> None
|
34
34
|
"""
|
35
35
|
|
36
|
-
|
36
|
+
# ****************************************************************************
|
37
37
|
# Copyright (C) 2014-2015 Martin von Gagern <Martin.vGagern@gmx.net>
|
38
38
|
#
|
39
39
|
# This program is free software: you can redistribute it and/or modify
|
40
40
|
# it under the terms of the GNU General Public License as published by
|
41
41
|
# the Free Software Foundation, either version 2 of the License, or
|
42
42
|
# (at your option) any later version.
|
43
|
-
#
|
44
|
-
|
43
|
+
# https://www.gnu.org/licenses/
|
44
|
+
# ****************************************************************************
|
45
45
|
|
46
46
|
from functools import wraps
|
47
47
|
|
@@ -50,6 +50,15 @@ def reproducible_repr(val):
|
|
50
50
|
r"""
|
51
51
|
String representation of an object in a reproducible way.
|
52
52
|
|
53
|
+
.. NOTE::
|
54
|
+
|
55
|
+
This function is deprecated, in most cases it suffices to use
|
56
|
+
the automatic sorting of dictionary keys and set items by a displayhook.
|
57
|
+
See :func:`sage.doctest.forker.init_sage`.
|
58
|
+
If used in a format string, use :func:`IPython.lib.pretty.pretty`.
|
59
|
+
In the rare cases where the ordering of the elements is not reliable
|
60
|
+
or transitive, ``sorted`` with a sane key can be used instead.
|
61
|
+
|
53
62
|
This tries to ensure that the returned string does not depend on
|
54
63
|
factors outside the control of the doctest.
|
55
64
|
One example is the order of elements in a hash-based structure.
|
@@ -74,6 +83,7 @@ def reproducible_repr(val):
|
|
74
83
|
|
75
84
|
EXAMPLES::
|
76
85
|
|
86
|
+
sage: # not tested (test fails because of deprecation warning)
|
77
87
|
sage: from sage.doctest.fixtures import reproducible_repr
|
78
88
|
sage: print(reproducible_repr(set(["a", "c", "b", "d"])))
|
79
89
|
set(['a', 'b', 'c', 'd'])
|
@@ -85,7 +95,20 @@ def reproducible_repr(val):
|
|
85
95
|
{'2': 'two', 1: 'one', 3.00000000000000: 'three'}
|
86
96
|
sage: print(reproducible_repr("foo\nbar")) # demonstrate default case
|
87
97
|
'foo\nbar'
|
98
|
+
|
99
|
+
TESTS:
|
100
|
+
|
101
|
+
Ensures deprecation warning is printed out::
|
102
|
+
|
103
|
+
sage: from sage.doctest.fixtures import reproducible_repr
|
104
|
+
sage: print(reproducible_repr(set(["a", "c", "b", "d"])))
|
105
|
+
doctest:warning...
|
106
|
+
DeprecationWarning: reproducible_repr is deprecated, see its documentation for details
|
107
|
+
See https://github.com/sagemath/sage/issues/39420 for details.
|
108
|
+
set(['a', 'b', 'c', 'd'])
|
88
109
|
"""
|
110
|
+
from sage.misc.superseded import deprecation
|
111
|
+
deprecation(39420, 'reproducible_repr is deprecated, see its documentation for details')
|
89
112
|
|
90
113
|
def sorted_pairs(iterable, pairs=False):
|
91
114
|
# We don't know whether container data structures will have
|
@@ -181,22 +204,23 @@ class AttributeAccessTracerHelper:
|
|
181
204
|
4
|
182
205
|
"""
|
183
206
|
val = getattr(self.delegate, name)
|
207
|
+
from IPython.lib.pretty import pretty
|
184
208
|
if callable(val) and name not in self.delegate.__dict__:
|
185
209
|
@wraps(val)
|
186
210
|
def wrapper(*args, **kwds):
|
187
|
-
arglst = [
|
188
|
-
arglst.extend("{}={}".format(k,
|
211
|
+
arglst = [pretty(arg) for arg in args]
|
212
|
+
arglst.extend("{}={}".format(k, pretty(v))
|
189
213
|
for k, v in sorted(kwds.items()))
|
190
214
|
res = val(*args, **kwds)
|
191
215
|
print("{}call {}({}) -> {}"
|
192
216
|
.format(self.prefix, name, ", ".join(arglst),
|
193
|
-
|
217
|
+
pretty(res)))
|
194
218
|
return res
|
195
219
|
return wrapper
|
196
220
|
else:
|
197
221
|
if self.reads:
|
198
222
|
print("{}read {} = {}".format(self.prefix, name,
|
199
|
-
|
223
|
+
pretty(val)))
|
200
224
|
return val
|
201
225
|
|
202
226
|
def set(self, name, val):
|
@@ -218,8 +242,9 @@ class AttributeAccessTracerHelper:
|
|
218
242
|
sage: foo.x
|
219
243
|
2
|
220
244
|
"""
|
245
|
+
from IPython.lib.pretty import pretty
|
221
246
|
print("{}write {} = {}".format(self.prefix, name,
|
222
|
-
|
247
|
+
pretty(val)))
|
223
248
|
setattr(self.delegate, name, val)
|
224
249
|
|
225
250
|
|
@@ -373,11 +398,12 @@ def trace_method(obj, meth, **kwds):
|
|
373
398
|
|
374
399
|
@wraps(f)
|
375
400
|
def g(*args, **kwds):
|
376
|
-
|
377
|
-
arglst
|
401
|
+
from IPython.lib.pretty import pretty
|
402
|
+
arglst = [pretty(arg) for arg in args]
|
403
|
+
arglst.extend("{}={}".format(k, pretty(v))
|
378
404
|
for k, v in sorted(kwds.items()))
|
379
405
|
print("enter {}({})".format(meth, ", ".join(arglst)))
|
380
406
|
res = f(t, *args, **kwds)
|
381
|
-
print("exit {} -> {}".format(meth,
|
407
|
+
print("exit {} -> {}".format(meth, pretty(res)))
|
382
408
|
return res
|
383
409
|
setattr(obj, meth, g)
|
sage/doctest/forker.py
CHANGED
@@ -250,7 +250,7 @@ def init_sage(controller: DocTestController | None = None) -> None:
|
|
250
250
|
|
251
251
|
try:
|
252
252
|
import sympy
|
253
|
-
except ImportError:
|
253
|
+
except (ImportError, AttributeError):
|
254
254
|
# Do not require sympy for running doctests (Issue #25106).
|
255
255
|
pass
|
256
256
|
else:
|
@@ -263,7 +263,8 @@ def showwarning_with_traceback(message, category, filename, lineno, file=None, l
|
|
263
263
|
r"""
|
264
264
|
Displays a warning message with a traceback.
|
265
265
|
|
266
|
-
INPUT: see :func:`warnings.showwarning
|
266
|
+
INPUT: see :func:`warnings.showwarning` with the difference that with ``file=None``
|
267
|
+
the message will be written to stdout.
|
267
268
|
|
268
269
|
OUTPUT: none
|
269
270
|
|
@@ -295,7 +296,7 @@ def showwarning_with_traceback(message, category, filename, lineno, file=None, l
|
|
295
296
|
lines.extend(traceback.format_exception_only(category, category(message)))
|
296
297
|
|
297
298
|
if file is None:
|
298
|
-
file = sys.
|
299
|
+
file = sys.stdout
|
299
300
|
try:
|
300
301
|
file.writelines(lines)
|
301
302
|
file.flush()
|
@@ -666,7 +667,8 @@ class SageDocTestRunner(doctest.DocTestRunner):
|
|
666
667
|
# We print the example we're running for easier debugging
|
667
668
|
# if this file times out or crashes.
|
668
669
|
with OriginalSource(example):
|
669
|
-
|
670
|
+
assert example.source.endswith("\n"), example
|
671
|
+
print("sage: " + example.source[:-1].replace("\n", "\n....: ") + " ## line %s ##" % (test.lineno + example.lineno + 1))
|
670
672
|
# Update the position so that result comparison works
|
671
673
|
self._fakeout.getvalue()
|
672
674
|
if not quiet:
|
@@ -1099,7 +1101,7 @@ class SageDocTestRunner(doctest.DocTestRunner):
|
|
1099
1101
|
False
|
1100
1102
|
sage: doctests, extras = FDS.create_doctests(globs)
|
1101
1103
|
sage: ex0 = doctests[0].examples[0]
|
1102
|
-
sage: flags =
|
1104
|
+
sage: flags = 524288
|
1103
1105
|
sage: def compiler(ex):
|
1104
1106
|
....: return compile(ex.source, '<doctest sage.doctest.forker[0]>',
|
1105
1107
|
....: 'single', flags, 1)
|
@@ -1492,6 +1494,7 @@ class SageDocTestRunner(doctest.DocTestRunner):
|
|
1492
1494
|
from sage.repl.configuration import sage_ipython_config
|
1493
1495
|
from IPython.terminal.embed import InteractiveShellEmbed
|
1494
1496
|
cfg = sage_ipython_config.default()
|
1497
|
+
cfg.InteractiveShell.enable_tip = False
|
1495
1498
|
# Currently this doesn't work: prompts only work in pty
|
1496
1499
|
# We keep simple_prompt=True, prompts will be "In [0]:"
|
1497
1500
|
# cfg.InteractiveShell.prompts_class = DebugPrompts
|
sage/doctest/parsing.py
CHANGED
@@ -39,36 +39,44 @@ import platform
|
|
39
39
|
import re
|
40
40
|
from collections import defaultdict
|
41
41
|
from functools import reduce
|
42
|
+
from re import Pattern
|
42
43
|
from typing import Literal, Union, overload
|
43
44
|
|
45
|
+
from sage.doctest.check_tolerance import (
|
46
|
+
ToleranceExceededError,
|
47
|
+
check_tolerance_complex_domain,
|
48
|
+
check_tolerance_real_domain,
|
49
|
+
float_regex,
|
50
|
+
)
|
51
|
+
from sage.doctest.external import available_software, external_software
|
52
|
+
from sage.doctest.marked_output import MarkedOutput
|
53
|
+
from sage.doctest.rif_tol import RIFtol, add_tolerance
|
44
54
|
from sage.misc.cachefunc import cached_function
|
45
55
|
from sage.repl.preparse import preparse, strip_string_literals
|
46
|
-
from sage.doctest.rif_tol import RIFtol, add_tolerance
|
47
|
-
from sage.doctest.marked_output import MarkedOutput
|
48
|
-
from sage.doctest.check_tolerance import (
|
49
|
-
ToleranceExceededError, check_tolerance_real_domain,
|
50
|
-
check_tolerance_complex_domain, float_regex)
|
51
|
-
|
52
|
-
from .external import available_software, external_software
|
53
|
-
|
54
56
|
|
55
57
|
# This is the correct pattern to match ISO/IEC 6429 ANSI escape sequences:
|
56
|
-
ansi_escape_sequence = re.compile(
|
58
|
+
ansi_escape_sequence: Pattern[str] = re.compile(
|
59
|
+
r"(\x1b[@-Z\\-~]|\x1b\[.*?[@-~]|\x9b.*?[@-~])"
|
60
|
+
)
|
57
61
|
|
58
|
-
|
62
|
+
special_optional_regex_raw = (
|
59
63
|
"py2|long time|not implemented|not tested|optional|needs|known bug"
|
60
64
|
)
|
61
|
-
|
62
|
-
optional_regex = re.compile(
|
63
|
-
rf"[^ a-z]\s*(?P<cmd>{
|
65
|
+
tag_with_explanation_regex_raw = r"((?:!?\w|[.])*)\s*(?:\((?P<cmd_explanation>.*?)\))?"
|
66
|
+
optional_regex: Pattern[str] = re.compile(
|
67
|
+
rf"[^ a-z]\s*(?P<cmd>{special_optional_regex_raw})(?:\s|[:-])*(?P<tags>(?:(?:{tag_with_explanation_regex_raw})\s*)*)",
|
64
68
|
re.IGNORECASE,
|
65
69
|
)
|
66
|
-
special_optional_regex = re.compile(
|
67
|
-
|
70
|
+
special_optional_regex: Pattern[str] = re.compile(
|
71
|
+
special_optional_regex_raw, re.IGNORECASE
|
72
|
+
)
|
73
|
+
tag_with_explanation_regex: Pattern[str] = re.compile(
|
74
|
+
tag_with_explanation_regex_raw, re.IGNORECASE
|
75
|
+
)
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
|
77
|
+
no_doctest_regex: Pattern[str] = re.compile(r'\s*(#+|%+|r"+|"+|\.\.)\s*nodoctest')
|
78
|
+
optional_tag_regex: Pattern[str] = re.compile(r"^(\w|[.])+$")
|
79
|
+
optional_file_directive_regex: Pattern[str] = re.compile(
|
72
80
|
r'\s*(#+|%+|r"+|"+|\.\.)\s*sage\.doctest: (.*)'
|
73
81
|
)
|
74
82
|
|
@@ -167,7 +175,7 @@ def parse_optional_tags(
|
|
167
175
|
....: return_string_sans_tags=True)
|
168
176
|
({'scipy': None}, 'sage: #this is not \n....: import scipy', False)
|
169
177
|
"""
|
170
|
-
safe, literals,
|
178
|
+
safe, literals, _ = strip_string_literals(string)
|
171
179
|
split = safe.split('\n', 1)
|
172
180
|
if len(split) > 1:
|
173
181
|
first_line, rest = split
|
@@ -231,7 +239,7 @@ def parse_optional_tags(
|
|
231
239
|
return tags
|
232
240
|
|
233
241
|
|
234
|
-
def parse_file_optional_tags(lines):
|
242
|
+
def parse_file_optional_tags(lines) -> dict[str, str | None]:
|
235
243
|
r"""
|
236
244
|
Scan the first few lines for file-level doctest directives.
|
237
245
|
|
@@ -261,11 +269,11 @@ def parse_file_optional_tags(lines):
|
|
261
269
|
....: parse_file_optional_tags(enumerate(f))
|
262
270
|
{'xyz': None}
|
263
271
|
"""
|
264
|
-
tags = {}
|
272
|
+
tags: dict[str, str | None] = {}
|
265
273
|
for line_count, line in lines:
|
266
|
-
if
|
274
|
+
if no_doctest_regex.match(line):
|
267
275
|
tags['not tested'] = None
|
268
|
-
if m :=
|
276
|
+
if m := optional_file_directive_regex.match(line):
|
269
277
|
file_tag_string = m.group(2)
|
270
278
|
tags.update(parse_optional_tags('#' + file_tag_string))
|
271
279
|
if line_count >= 10:
|
@@ -274,7 +282,7 @@ def parse_file_optional_tags(lines):
|
|
274
282
|
|
275
283
|
|
276
284
|
@cached_function
|
277
|
-
def _standard_tags():
|
285
|
+
def _standard_tags() -> frozenset[str]:
|
278
286
|
r"""
|
279
287
|
Return the set of the names of all standard features.
|
280
288
|
|
@@ -321,7 +329,7 @@ def _tag_group(tag):
|
|
321
329
|
return 'special'
|
322
330
|
|
323
331
|
|
324
|
-
def unparse_optional_tags(tags, prefix='# '):
|
332
|
+
def unparse_optional_tags(tags, prefix='# ') -> str:
|
325
333
|
r"""
|
326
334
|
Return a comment string that sets ``tags``.
|
327
335
|
|
@@ -596,7 +604,7 @@ def parse_tolerance(source, want):
|
|
596
604
|
return want
|
597
605
|
|
598
606
|
|
599
|
-
def pre_hash(s):
|
607
|
+
def pre_hash(s) -> str:
|
600
608
|
"""
|
601
609
|
Prepends a string with its length.
|
602
610
|
|
@@ -1482,7 +1490,7 @@ class SageOutputChecker(doctest.OutputChecker):
|
|
1482
1490
|
did_fixup = True
|
1483
1491
|
|
1484
1492
|
if "R[write to console]" in got:
|
1485
|
-
#
|
1493
|
+
# suppress R warnings
|
1486
1494
|
r_warning_regex = re.compile(r'R\[write to console\]:.*')
|
1487
1495
|
got = r_warning_regex.sub('', got)
|
1488
1496
|
did_fixup = True
|
@@ -1513,6 +1521,13 @@ class SageOutputChecker(doctest.OutputChecker):
|
|
1513
1521
|
got = dup_lib_regex.sub('', got)
|
1514
1522
|
did_fixup = True
|
1515
1523
|
|
1524
|
+
if "duplicate" in got:
|
1525
|
+
# Warnings about duplicate rpaths in the linker command line
|
1526
|
+
# occurs sometimes when compiling cython code via sage.misc.cython
|
1527
|
+
dup_rpath_regex = re.compile("ld: warning: duplicate -rpath .* ignored")
|
1528
|
+
got = dup_rpath_regex.sub('', got)
|
1529
|
+
did_fixup = True
|
1530
|
+
|
1516
1531
|
return did_fixup, want, got
|
1517
1532
|
|
1518
1533
|
def output_difference(self, example, got, optionflags):
|
sage/doctest/sources.py
CHANGED
@@ -87,8 +87,18 @@ def get_basename(path):
|
|
87
87
|
sage: import os
|
88
88
|
sage: get_basename(sage.doctest.sources.__file__)
|
89
89
|
'sage.doctest.sources'
|
90
|
+
|
91
|
+
::
|
92
|
+
|
93
|
+
sage: # optional - !meson_editable
|
90
94
|
sage: get_basename(os.path.join(sage.structure.__path__[0], 'element.pxd'))
|
91
95
|
'sage.structure.element.pxd'
|
96
|
+
|
97
|
+
TESTS::
|
98
|
+
|
99
|
+
sage: # optional - meson_editable
|
100
|
+
sage: get_basename(os.path.join(os.path.dirname(sage.structure.__file__), 'element.pxd'))
|
101
|
+
'sage.structure.element.pxd'
|
92
102
|
"""
|
93
103
|
if path is None:
|
94
104
|
return None
|
sage/doctest/test.py
CHANGED
@@ -295,15 +295,21 @@ Test a doctest failing with ``abort()``::
|
|
295
295
|
...
|
296
296
|
16
|
297
297
|
|
298
|
-
A different kind of crash
|
298
|
+
A different kind of crash (also test printing of line continuation ``...:``,
|
299
|
+
represented by ``<DOTSCOLON>`` below)::
|
299
300
|
|
300
|
-
sage:
|
301
|
-
|
301
|
+
sage: # long time
|
302
|
+
sage: proc = subprocess.run(["sage", "-t", "--warn-long", "0",
|
303
|
+
....: "--random-seed=0", "--optional=sage", "fail_and_die.rst"], **kwds,
|
304
|
+
....: stdout=subprocess.PIPE, text=True)
|
305
|
+
sage: # the replacements are needed to avoid the strings being interpreted
|
306
|
+
....: # specially by the doctesting framework
|
307
|
+
sage: print(proc.stdout.replace('sage:', 'sage<COLON>').replace('....:', '<DOTSCOLON>'))
|
302
308
|
Running doctests...
|
303
309
|
Doctesting 1 file.
|
304
310
|
sage -t --warn-long 0.0 --random-seed=0 fail_and_die.rst
|
305
311
|
**********************************************************************
|
306
|
-
File "fail_and_die.rst", line
|
312
|
+
File "fail_and_die.rst", line 8, in sage.doctest.tests.fail_and_die
|
307
313
|
Failed example:
|
308
314
|
this_gives_a_NameError
|
309
315
|
Exception raised:
|
@@ -313,11 +319,18 @@ A different kind of crash::
|
|
313
319
|
Killed due to kill signal
|
314
320
|
**********************************************************************
|
315
321
|
Tests run before process (pid=...) failed:
|
316
|
-
|
322
|
+
sage<COLON> import time, signal ## line 4 ##
|
323
|
+
sage<COLON> print(1,
|
324
|
+
<DOTSCOLON> 2) ## line 5 ##
|
325
|
+
1 2
|
326
|
+
sage<COLON> this_gives_a_NameError ## line 8 ##
|
327
|
+
sage<COLON> os.kill(os.getpid(), signal.SIGKILL) ## line 9 ##
|
328
|
+
**********************************************************************
|
317
329
|
----------------------------------------------------------------------
|
318
330
|
sage -t --warn-long 0.0 --random-seed=0 fail_and_die.rst # Killed due to kill signal
|
319
331
|
----------------------------------------------------------------------
|
320
332
|
...
|
333
|
+
sage: proc.returncode
|
321
334
|
16
|
322
335
|
|
323
336
|
Test that ``sig_on_count`` is checked correctly::
|
@@ -1,6 +1,9 @@
|
|
1
1
|
The :exc:`NameError` raised on the second line should be displayed, even
|
2
|
-
if we crash immediately afterwards::
|
2
|
+
if we crash immediately afterwards (also test printing of line continuation)::
|
3
3
|
|
4
4
|
sage: import time, signal
|
5
|
+
sage: print(1,
|
6
|
+
....: 2)
|
7
|
+
1 2
|
5
8
|
sage: this_gives_a_NameError
|
6
9
|
sage: os.kill(os.getpid(), signal.SIGKILL)
|
sage/doctest/util.py
CHANGED
@@ -23,10 +23,9 @@ AUTHORS:
|
|
23
23
|
# https://www.gnu.org/licenses/
|
24
24
|
# ****************************************************************************
|
25
25
|
|
26
|
+
from os import times
|
26
27
|
from time import time as walltime
|
27
|
-
from os import sysconf, times
|
28
28
|
from contextlib import contextmanager
|
29
|
-
from cysignals.alarm import alarm, cancel_alarm, AlarmInterrupt
|
30
29
|
|
31
30
|
|
32
31
|
def count_noun(number, noun, plural=None, pad_number=False, pad_noun=False):
|
@@ -206,6 +205,8 @@ class Timer:
|
|
206
205
|
raise OSError(f"unable to parse {path}") from e
|
207
206
|
|
208
207
|
try:
|
208
|
+
from os import sysconf
|
209
|
+
|
209
210
|
hertz = sysconf("SC_CLK_TCK")
|
210
211
|
except (ValueError) as e:
|
211
212
|
# ValueError: SC_CLK_TCK doesn't exist
|
@@ -332,7 +333,10 @@ class Timer:
|
|
332
333
|
sage: Timer().start()
|
333
334
|
{'cputime': ..., 'walltime': ...}
|
334
335
|
"""
|
335
|
-
|
336
|
+
try:
|
337
|
+
from sage.interfaces.quit import expect_objects
|
338
|
+
except ImportError:
|
339
|
+
expect_objects = []
|
336
340
|
self.cputime = self._quick_cputime(expect_objects)
|
337
341
|
self.walltime = walltime()
|
338
342
|
return self
|
@@ -351,7 +355,10 @@ class Timer:
|
|
351
355
|
sage: timer.stop()
|
352
356
|
{'cputime': ..., 'walltime': ...}
|
353
357
|
"""
|
354
|
-
|
358
|
+
try:
|
359
|
+
from sage.interfaces.quit import expect_objects
|
360
|
+
except ImportError:
|
361
|
+
expect_objects = []
|
355
362
|
self.cputime = self._quick_cputime(expect_objects) - self.cputime
|
356
363
|
self.walltime = walltime() - self.walltime
|
357
364
|
return self
|
@@ -607,7 +614,7 @@ def make_recording_dict(D, st, gt):
|
|
607
614
|
EXAMPLES::
|
608
615
|
|
609
616
|
sage: from sage.doctest.util import make_recording_dict
|
610
|
-
sage: D = make_recording_dict({'a':4,'d':42},set(
|
617
|
+
sage: D = make_recording_dict({'a':4,'d':42},set(),set(['not_here']))
|
611
618
|
sage: sorted(D.items())
|
612
619
|
[('a', 4), ('d', 42)]
|
613
620
|
sage: D.got
|
@@ -802,7 +809,7 @@ def ensure_interruptible_after(seconds: float, max_wait_after_interrupt: float =
|
|
802
809
|
....: check_interrupt_only_occasionally()
|
803
810
|
Traceback (most recent call last):
|
804
811
|
...
|
805
|
-
RuntimeError: Function is not interruptible within 1.0000 seconds, only after 1.
|
812
|
+
RuntimeError: Function is not interruptible within 1.0000 seconds, only after 1.6... seconds
|
806
813
|
sage: with ensure_interruptible_after(1, max_wait_after_interrupt=0.9):
|
807
814
|
....: check_interrupt_only_occasionally()
|
808
815
|
|
@@ -870,6 +877,8 @@ def ensure_interruptible_after(seconds: float, max_wait_after_interrupt: float =
|
|
870
877
|
sage: data
|
871
878
|
{'alarm_raised': False, 'elapsed': ...}
|
872
879
|
"""
|
880
|
+
from cysignals.alarm import alarm, cancel_alarm, AlarmInterrupt
|
881
|
+
|
873
882
|
seconds = float(seconds)
|
874
883
|
max_wait_after_interrupt = float(max_wait_after_interrupt)
|
875
884
|
inaccuracy_tolerance = float(inaccuracy_tolerance)
|
sage/misc/banner.py
CHANGED
@@ -13,7 +13,8 @@ SageMath version and banner info
|
|
13
13
|
# ****************************************************************************
|
14
14
|
import sys
|
15
15
|
|
16
|
-
from sage.env import
|
16
|
+
from sage.env import SAGE_BANNER, SAGE_VERSION
|
17
|
+
from sage.version import banner as sage_banner
|
17
18
|
|
18
19
|
|
19
20
|
def version():
|
@@ -25,9 +26,16 @@ def version():
|
|
25
26
|
EXAMPLES::
|
26
27
|
|
27
28
|
sage: version()
|
29
|
+
doctest:warning
|
30
|
+
...
|
31
|
+
DeprecationWarning: Use sage.version instead.
|
32
|
+
...
|
28
33
|
'... version ..., Release Date: ...'
|
29
34
|
"""
|
30
|
-
|
35
|
+
from sage.misc.superseded import deprecation
|
36
|
+
|
37
|
+
deprecation(39015, "Use sage.version instead.")
|
38
|
+
return sage_banner
|
31
39
|
|
32
40
|
|
33
41
|
def banner_text(full=True):
|
@@ -54,13 +62,13 @@ def banner_text(full=True):
|
|
54
62
|
... version ..., Release Date: ...
|
55
63
|
"""
|
56
64
|
if not full:
|
57
|
-
return
|
65
|
+
return sage_banner
|
58
66
|
|
59
67
|
bars = "─" * 68
|
60
68
|
s = []
|
61
69
|
a = s.append
|
62
70
|
a('┌' + bars + '┐')
|
63
|
-
a("\n│ %-66s │\n" %
|
71
|
+
a("\n│ %-66s │\n" % sage_banner)
|
64
72
|
python_version = sys.version_info[:3]
|
65
73
|
a("│ %-66s │\n" % 'Using Python {}.{}.{}. Type "help()" for help.'.format(*python_version))
|
66
74
|
a('└' + bars + '┘')
|
sage/misc/cython.py
CHANGED
@@ -30,11 +30,10 @@ from pathlib import Path
|
|
30
30
|
|
31
31
|
from sage.env import (SAGE_LOCAL, cython_aliases,
|
32
32
|
sage_include_directories)
|
33
|
+
from sage.misc.cachefunc import cached_function
|
34
|
+
from sage.misc.sage_ostools import restore_cwd, redirection
|
33
35
|
from sage.misc.temporary_file import spyx_tmp, tmp_filename
|
34
36
|
from sage.repl.user_globals import get_globals
|
35
|
-
from sage.misc.sage_ostools import restore_cwd, redirection
|
36
|
-
from sage.cpython.string import str_to_bytes
|
37
|
-
from sage.misc.cachefunc import cached_function
|
38
37
|
|
39
38
|
|
40
39
|
@cached_function
|
@@ -90,7 +89,7 @@ def _webbrowser_open_file(path):
|
|
90
89
|
|
91
90
|
def cython(filename, verbose=0, compile_message=False,
|
92
91
|
use_cache=False, create_local_c_file=False, annotate=True, view_annotate=False,
|
93
|
-
view_annotate_callback=
|
92
|
+
view_annotate_callback=None, sage_namespace=True, create_local_so_file=False):
|
94
93
|
r"""
|
95
94
|
Compile a Cython file. This converts a Cython file to a C (or C++ file),
|
96
95
|
and then compiles that. The .c file and the .so file are
|
@@ -126,7 +125,8 @@ def cython(filename, verbose=0, compile_message=False,
|
|
126
125
|
- ``view_annotate_callback`` -- function; a function that takes a string
|
127
126
|
being the path to the html file. This can be overridden to change
|
128
127
|
what to do with the annotated html file. Have no effect unless
|
129
|
-
``view_annotate`` is ``True``.
|
128
|
+
``view_annotate`` is ``True``. By default, the html file is opened in a
|
129
|
+
web browser.
|
130
130
|
|
131
131
|
- ``sage_namespace`` -- boolean (default: ``True``); if ``True``, import
|
132
132
|
``sage.all``
|
@@ -273,6 +273,9 @@ def cython(filename, verbose=0, compile_message=False,
|
|
273
273
|
sage: len(collected_paths)
|
274
274
|
1
|
275
275
|
"""
|
276
|
+
if view_annotate_callback is None:
|
277
|
+
# needed because of https://github.com/sagemath/sage/pull/38946#issuecomment-2656329774
|
278
|
+
view_annotate_callback = _webbrowser_open_file
|
276
279
|
if not filename.endswith('pyx'):
|
277
280
|
print("Warning: file (={}) should have extension .pyx".format(filename), file=sys.stderr)
|
278
281
|
|