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.
Files changed (59) hide show
  1. passagemath_repl-10.6.1rc1.data/data/share/jupyter/kernels/sagemath/kernel.json +1 -0
  2. {passagemath_repl-10.5.42.dist-info → passagemath_repl-10.6.1rc1.dist-info}/METADATA +5 -6
  3. {passagemath_repl-10.5.42.dist-info → passagemath_repl-10.6.1rc1.dist-info}/RECORD +56 -57
  4. sage/all__sagemath_repl.py +0 -6
  5. sage/doctest/__main__.py +1 -1
  6. sage/doctest/control.py +30 -28
  7. sage/doctest/external.py +31 -27
  8. sage/doctest/fixtures.py +37 -11
  9. sage/doctest/forker.py +8 -5
  10. sage/doctest/parsing.py +42 -27
  11. sage/doctest/sources.py +10 -0
  12. sage/doctest/test.py +18 -5
  13. sage/doctest/tests/fail_and_die.rst +4 -1
  14. sage/doctest/util.py +15 -6
  15. sage/misc/banner.py +12 -4
  16. sage/misc/cython.py +8 -5
  17. sage/misc/dev_tools.py +10 -84
  18. sage/misc/gperftools.py +13 -14
  19. sage/repl/configuration.py +4 -4
  20. sage/repl/ipython_extension.py +12 -8
  21. sage/repl/ipython_kernel/install.py +1 -1
  22. sage/repl/ipython_kernel/widgets.py +1 -1
  23. sage/repl/ipython_tests.py +19 -2
  24. sage/repl/rich_output/backend_ipython.py +0 -1
  25. sage/repl/rich_output/display_manager.py +1 -1
  26. sage/tests/all.py +1 -0
  27. sage/tests/benchmark.py +6 -2
  28. sage/tests/books/computational-mathematics-with-sagemath/domaines_doctest.py +1 -1
  29. sage/tests/books/computational-mathematics-with-sagemath/linsolve_doctest.py +1 -1
  30. sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py +1 -1
  31. sage/tests/books/computational-mathematics-with-sagemath/premierspas_doctest.py +1 -1
  32. sage/tests/books/computational-mathematics-with-sagemath/sol/mpoly_doctest.py +1 -1
  33. sage/tests/cmdline.py +6 -4
  34. sage/tests/startup.py +1 -1
  35. passagemath_repl-10.5.42.data/data/share/jupyter/kernels/sagemath/kernel.json +0 -1
  36. sage/interfaces/cleaner.py +0 -48
  37. sage/interfaces/quit.py +0 -178
  38. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/data/share/jupyter/kernels/sagemath/logo-64x64.png +0 -0
  39. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/data/share/jupyter/kernels/sagemath/logo.svg +0 -0
  40. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-cachegrind +0 -0
  41. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-callgrind +0 -0
  42. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-cleaner +0 -0
  43. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-coverage +0 -0
  44. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-eval +0 -0
  45. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-fixdoctests +0 -0
  46. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-inline-fortran +0 -0
  47. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-ipynb2rst +0 -0
  48. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-ipython +0 -0
  49. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-massif +0 -0
  50. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-notebook +0 -0
  51. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-omega +0 -0
  52. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-preparse +0 -0
  53. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-run +0 -0
  54. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-run-cython +0 -0
  55. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-runtests +0 -0
  56. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-startuptime.py +0 -0
  57. {passagemath_repl-10.5.42.data → passagemath_repl-10.6.1rc1.data}/scripts/sage-valgrind +0 -0
  58. {passagemath_repl-10.5.42.dist-info → passagemath_repl-10.6.1rc1.dist-info}/WHEEL +0 -0
  59. {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
- # http://www.gnu.org/licenses/
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 = [reproducible_repr(arg) for arg in args]
188
- arglst.extend("{}={}".format(k, reproducible_repr(v))
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
- reproducible_repr(res)))
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
- reproducible_repr(val)))
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
- reproducible_repr(val)))
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
- arglst = [reproducible_repr(arg) for arg in args]
377
- arglst.extend("{}={}".format(k, reproducible_repr(v))
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, reproducible_repr(res)))
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.stderr
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
- print("sage: " + example.source[:-1] + " ## line %s ##" % (test.lineno + example.lineno + 1))
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 = 32768 if sys.version_info.minor < 8 else 524288
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(r"(\x1b[@-Z\\-~]|\x1b\[.*?[@-~]|\x9b.*?[@-~])")
58
+ ansi_escape_sequence: Pattern[str] = re.compile(
59
+ r"(\x1b[@-Z\\-~]|\x1b\[.*?[@-~]|\x9b.*?[@-~])"
60
+ )
57
61
 
58
- special_optional_regex = (
62
+ special_optional_regex_raw = (
59
63
  "py2|long time|not implemented|not tested|optional|needs|known bug"
60
64
  )
61
- tag_with_explanation_regex = r"((?:!?\w|[.])*)\s*(?:\((?P<cmd_explanation>.*?)\))?"
62
- optional_regex = re.compile(
63
- rf"[^ a-z]\s*(?P<cmd>{special_optional_regex})(?:\s|[:-])*(?P<tags>(?:(?:{tag_with_explanation_regex})\s*)*)",
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(special_optional_regex, re.IGNORECASE)
67
- tag_with_explanation_regex = re.compile(tag_with_explanation_regex, re.IGNORECASE)
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
- nodoctest_regex = re.compile(r'\s*(#+|%+|r"+|"+|\.\.)\s*nodoctest')
70
- optionaltag_regex = re.compile(r"^(\w|[.])+$")
71
- optionalfiledirective_regex = re.compile(
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, state = strip_string_literals(string)
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 nodoctest_regex.match(line):
274
+ if no_doctest_regex.match(line):
267
275
  tags['not tested'] = None
268
- if m := optionalfiledirective_regex.match(line):
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
- # Supress R warnings
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: subprocess.call(["sage", "-t", "--warn-long", "0", # long time
301
- ....: "--random-seed=0", "--optional=sage", "fail_and_die.rst"], **kwds)
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 5, in sage.doctest.tests.fail_and_die
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
- from sage.interfaces.quit import expect_objects
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
- from sage.interfaces.quit import expect_objects
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([]),set(['not_here']))
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.60... seconds
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 (SAGE_VERSION, SAGE_VERSION_BANNER, SAGE_BANNER)
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
- return SAGE_VERSION_BANNER
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 version()
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" % version())
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=_webbrowser_open_file, sage_namespace=True, create_local_so_file=False):
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