passagemath-repl 10.5.1__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 (162) hide show
  1. passagemath_repl-10.5.1.data/scripts/sage-cachegrind +25 -0
  2. passagemath_repl-10.5.1.data/scripts/sage-callgrind +16 -0
  3. passagemath_repl-10.5.1.data/scripts/sage-cleaner +230 -0
  4. passagemath_repl-10.5.1.data/scripts/sage-coverage +327 -0
  5. passagemath_repl-10.5.1.data/scripts/sage-eval +14 -0
  6. passagemath_repl-10.5.1.data/scripts/sage-fixdoctests +710 -0
  7. passagemath_repl-10.5.1.data/scripts/sage-inline-fortran +12 -0
  8. passagemath_repl-10.5.1.data/scripts/sage-ipynb2rst +50 -0
  9. passagemath_repl-10.5.1.data/scripts/sage-ipython +16 -0
  10. passagemath_repl-10.5.1.data/scripts/sage-massif +25 -0
  11. passagemath_repl-10.5.1.data/scripts/sage-notebook +267 -0
  12. passagemath_repl-10.5.1.data/scripts/sage-omega +25 -0
  13. passagemath_repl-10.5.1.data/scripts/sage-preparse +302 -0
  14. passagemath_repl-10.5.1.data/scripts/sage-run +27 -0
  15. passagemath_repl-10.5.1.data/scripts/sage-run-cython +10 -0
  16. passagemath_repl-10.5.1.data/scripts/sage-runtests +9 -0
  17. passagemath_repl-10.5.1.data/scripts/sage-startuptime.py +163 -0
  18. passagemath_repl-10.5.1.data/scripts/sage-valgrind +34 -0
  19. passagemath_repl-10.5.1.dist-info/METADATA +77 -0
  20. passagemath_repl-10.5.1.dist-info/RECORD +162 -0
  21. passagemath_repl-10.5.1.dist-info/WHEEL +5 -0
  22. passagemath_repl-10.5.1.dist-info/top_level.txt +1 -0
  23. sage/all__sagemath_repl.py +119 -0
  24. sage/doctest/__init__.py +4 -0
  25. sage/doctest/__main__.py +236 -0
  26. sage/doctest/all.py +4 -0
  27. sage/doctest/check_tolerance.py +261 -0
  28. sage/doctest/control.py +1727 -0
  29. sage/doctest/external.py +534 -0
  30. sage/doctest/fixtures.py +383 -0
  31. sage/doctest/forker.py +2665 -0
  32. sage/doctest/marked_output.py +102 -0
  33. sage/doctest/parsing.py +1708 -0
  34. sage/doctest/parsing_test.py +79 -0
  35. sage/doctest/reporting.py +733 -0
  36. sage/doctest/rif_tol.py +124 -0
  37. sage/doctest/sources.py +1657 -0
  38. sage/doctest/test.py +584 -0
  39. sage/doctest/tests/1second.rst +4 -0
  40. sage/doctest/tests/99seconds.rst +4 -0
  41. sage/doctest/tests/abort.rst +5 -0
  42. sage/doctest/tests/atexit.rst +7 -0
  43. sage/doctest/tests/fail_and_die.rst +6 -0
  44. sage/doctest/tests/initial.rst +15 -0
  45. sage/doctest/tests/interrupt.rst +7 -0
  46. sage/doctest/tests/interrupt_diehard.rst +14 -0
  47. sage/doctest/tests/keyboardinterrupt.rst +11 -0
  48. sage/doctest/tests/longtime.rst +5 -0
  49. sage/doctest/tests/nodoctest +5 -0
  50. sage/doctest/tests/random_seed.rst +4 -0
  51. sage/doctest/tests/show_skipped.rst +18 -0
  52. sage/doctest/tests/sig_on.rst +9 -0
  53. sage/doctest/tests/simple_failure.rst +8 -0
  54. sage/doctest/tests/sleep_and_raise.rst +106 -0
  55. sage/doctest/tests/tolerance.rst +31 -0
  56. sage/doctest/util.py +750 -0
  57. sage/interfaces/cleaner.py +48 -0
  58. sage/interfaces/quit.py +163 -0
  59. sage/misc/all__sagemath_repl.py +51 -0
  60. sage/misc/banner.py +235 -0
  61. sage/misc/benchmark.py +221 -0
  62. sage/misc/classgraph.py +134 -0
  63. sage/misc/copying.py +22 -0
  64. sage/misc/cython.py +694 -0
  65. sage/misc/dev_tools.py +745 -0
  66. sage/misc/edit_module.py +304 -0
  67. sage/misc/explain_pickle.py +3079 -0
  68. sage/misc/gperftools.py +361 -0
  69. sage/misc/inline_fortran.py +212 -0
  70. sage/misc/messaging.py +86 -0
  71. sage/misc/pager.py +21 -0
  72. sage/misc/profiler.py +179 -0
  73. sage/misc/python.py +70 -0
  74. sage/misc/remote_file.py +53 -0
  75. sage/misc/sage_eval.py +249 -0
  76. sage/misc/sage_input.py +3621 -0
  77. sage/misc/sagedoc.py +1742 -0
  78. sage/misc/sh.py +38 -0
  79. sage/misc/trace.py +90 -0
  80. sage/repl/__init__.py +16 -0
  81. sage/repl/all.py +15 -0
  82. sage/repl/attach.py +625 -0
  83. sage/repl/configuration.py +186 -0
  84. sage/repl/display/__init__.py +1 -0
  85. sage/repl/display/fancy_repr.py +354 -0
  86. sage/repl/display/formatter.py +318 -0
  87. sage/repl/display/jsmol_iframe.py +290 -0
  88. sage/repl/display/pretty_print.py +153 -0
  89. sage/repl/display/util.py +163 -0
  90. sage/repl/image.py +302 -0
  91. sage/repl/inputhook.py +91 -0
  92. sage/repl/interface_magic.py +298 -0
  93. sage/repl/interpreter.py +854 -0
  94. sage/repl/ipython_extension.py +593 -0
  95. sage/repl/ipython_kernel/__init__.py +1 -0
  96. sage/repl/ipython_kernel/__main__.py +4 -0
  97. sage/repl/ipython_kernel/all_jupyter.py +10 -0
  98. sage/repl/ipython_kernel/install.py +301 -0
  99. sage/repl/ipython_kernel/interact.py +278 -0
  100. sage/repl/ipython_kernel/kernel.py +217 -0
  101. sage/repl/ipython_kernel/widgets.py +466 -0
  102. sage/repl/ipython_kernel/widgets_sagenb.py +587 -0
  103. sage/repl/ipython_tests.py +163 -0
  104. sage/repl/load.py +326 -0
  105. sage/repl/preparse.py +2218 -0
  106. sage/repl/prompts.py +90 -0
  107. sage/repl/rich_output/__init__.py +4 -0
  108. sage/repl/rich_output/backend_base.py +648 -0
  109. sage/repl/rich_output/backend_doctest.py +316 -0
  110. sage/repl/rich_output/backend_emacs.py +151 -0
  111. sage/repl/rich_output/backend_ipython.py +596 -0
  112. sage/repl/rich_output/buffer.py +311 -0
  113. sage/repl/rich_output/display_manager.py +829 -0
  114. sage/repl/rich_output/example.avi +0 -0
  115. sage/repl/rich_output/example.canvas3d +1 -0
  116. sage/repl/rich_output/example.dvi +0 -0
  117. sage/repl/rich_output/example.flv +0 -0
  118. sage/repl/rich_output/example.gif +0 -0
  119. sage/repl/rich_output/example.jpg +0 -0
  120. sage/repl/rich_output/example.mkv +0 -0
  121. sage/repl/rich_output/example.mov +0 -0
  122. sage/repl/rich_output/example.mp4 +0 -0
  123. sage/repl/rich_output/example.ogv +0 -0
  124. sage/repl/rich_output/example.pdf +0 -0
  125. sage/repl/rich_output/example.png +0 -0
  126. sage/repl/rich_output/example.svg +54 -0
  127. sage/repl/rich_output/example.webm +0 -0
  128. sage/repl/rich_output/example.wmv +0 -0
  129. sage/repl/rich_output/example_jmol.spt.zip +0 -0
  130. sage/repl/rich_output/example_wavefront_scene.mtl +7 -0
  131. sage/repl/rich_output/example_wavefront_scene.obj +17 -0
  132. sage/repl/rich_output/output_basic.py +391 -0
  133. sage/repl/rich_output/output_browser.py +103 -0
  134. sage/repl/rich_output/output_catalog.py +54 -0
  135. sage/repl/rich_output/output_graphics.py +320 -0
  136. sage/repl/rich_output/output_graphics3d.py +345 -0
  137. sage/repl/rich_output/output_video.py +231 -0
  138. sage/repl/rich_output/preferences.py +432 -0
  139. sage/repl/rich_output/pretty_print.py +339 -0
  140. sage/repl/rich_output/test_backend.py +201 -0
  141. sage/repl/user_globals.py +214 -0
  142. sage/tests/all.py +0 -0
  143. sage/tests/all__sagemath_repl.py +3 -0
  144. sage/tests/article_heuberger_krenn_kropf_fsm-in-sage.py +630 -0
  145. sage/tests/arxiv_0812_2725.py +351 -0
  146. sage/tests/benchmark.py +1925 -0
  147. sage/tests/book_schilling_zabrocki_kschur_primer.py +795 -0
  148. sage/tests/book_stein_ent.py +651 -0
  149. sage/tests/book_stein_modform.py +558 -0
  150. sage/tests/cmdline.py +796 -0
  151. sage/tests/combinatorial_hopf_algebras.py +52 -0
  152. sage/tests/finite_poset.py +623 -0
  153. sage/tests/functools_partial_src.py +27 -0
  154. sage/tests/gosper-sum.py +218 -0
  155. sage/tests/lazy_imports.py +28 -0
  156. sage/tests/modular_group_cohomology.py +80 -0
  157. sage/tests/numpy.py +21 -0
  158. sage/tests/parigp.py +76 -0
  159. sage/tests/startup.py +27 -0
  160. sage/tests/symbolic-series.py +76 -0
  161. sage/tests/sympy.py +16 -0
  162. sage/tests/test_deprecation.py +31 -0
@@ -0,0 +1,48 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ """
3
+ Interface to the Sage cleaner
4
+
5
+ Triva Note: For the name "sage-cleaner", think of the
6
+ "The Cleaner" from Pulp Fiction:
7
+ http://www.frankjankowski.de/quiz/illus/keitel.jpg
8
+ """
9
+ # ****************************************************************************
10
+ # Copyright (C) 2007 William Stein <wstein@gmail.com>
11
+ #
12
+ # Distributed under the terms of the GNU General Public License (GPL)
13
+ # as published by the Free Software Foundation; either version 2 of
14
+ # the License, or (at your option) any later version.
15
+ # https://www.gnu.org/licenses/
16
+ # ****************************************************************************
17
+ import os
18
+ import atexit
19
+ import tempfile
20
+
21
+ _spd = tempfile.TemporaryDirectory()
22
+ SAGE_SPAWNED_PROCESS_FILE = os.path.join(_spd.name, "spawned_processes")
23
+ atexit.register(lambda: _spd.cleanup())
24
+
25
+
26
+ def start_cleaner():
27
+ """
28
+ Start ``sage-cleaner`` in a new process group.
29
+ """
30
+ if not os.fork():
31
+ os.setpgid(os.getpid(), os.getpid())
32
+
33
+ # Redirect stdin, stdout, stderr to /dev/null
34
+ with open(os.devnull, "r+") as f:
35
+ os.dup2(f.fileno(), 0)
36
+ os.dup2(f.fileno(), 1)
37
+ os.dup2(f.fileno(), 2)
38
+
39
+ # Close all other file descriptors
40
+ try:
41
+ maxopenfiles = os.sysconf("SC_OPEN_MAX")
42
+ if maxopenfiles <= 0:
43
+ raise ValueError
44
+ except ValueError:
45
+ maxopenfiles = 1024
46
+ os.closerange(3, maxopenfiles)
47
+
48
+ os.execlp("sage-cleaner", "sage-cleaner")
@@ -0,0 +1,163 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ """
3
+ Quitting interfaces
4
+ """
5
+
6
+ ################################################################################
7
+ # Copyright (C) 2010 William Stein <wstein@gmail.com>
8
+ #
9
+ # Distributed under the terms of (any version of) the GNU
10
+ # General Public License (GPL). The full text of the GPL is available at:
11
+ #
12
+ # https://www.gnu.org/licenses/
13
+ ################################################################################
14
+
15
+ import os
16
+
17
+ from sage.misc.cachefunc import cached_function
18
+
19
+
20
+ @cached_function
21
+ def sage_spawned_process_file():
22
+ """
23
+ EXAMPLES::
24
+
25
+ sage: from sage.interfaces.quit import sage_spawned_process_file
26
+ sage: len(sage_spawned_process_file()) > 1
27
+ True
28
+ """
29
+ # This is the old value of SAGE_TMP. Until sage-cleaner is
30
+ # completely removed, we need to leave these spawned_processes
31
+ # files where sage-cleaner will look for them.
32
+ from sage.env import DOT_SAGE, HOSTNAME
33
+ d = os.path.join(DOT_SAGE, "temp", HOSTNAME, str(os.getpid()))
34
+ os.makedirs(d, exist_ok=True)
35
+ return os.path.join(d, "spawned_processes")
36
+
37
+
38
+ def register_spawned_process(pid, cmd=''):
39
+ """
40
+ Write a line to the ``spawned_processes`` file with the given
41
+ ``pid`` and ``cmd``.
42
+ """
43
+ if cmd != '':
44
+ cmd = cmd.strip().split()[0]
45
+ # This is safe, since only this process writes to this file.
46
+ try:
47
+ with open(sage_spawned_process_file(), 'a') as o:
48
+ o.write('%s %s\n' % (pid, cmd))
49
+ except OSError:
50
+ pass
51
+ else:
52
+ # If sage is being used as a python library, we need to launch
53
+ # the cleaner ourselves upon being told that there will be
54
+ # something to clean.
55
+ from sage.interfaces.cleaner import start_cleaner
56
+ start_cleaner()
57
+
58
+
59
+ expect_objects = []
60
+
61
+
62
+ def expect_quitall(verbose=False):
63
+ """
64
+ EXAMPLES::
65
+
66
+ sage: sage.interfaces.quit.expect_quitall()
67
+ sage: gp.eval('a=10') # needs sage.libs.pari
68
+ '10'
69
+ sage: gp('a') # needs sage.libs.pari
70
+ 10
71
+ sage: sage.interfaces.quit.expect_quitall()
72
+ sage: gp('a') # needs sage.libs.pari
73
+ a
74
+ sage: sage.interfaces.quit.expect_quitall(verbose=True) # needs sage.libs.pari
75
+ Exiting PARI/GP interpreter with PID ... running .../gp --fast --emacs --quiet --stacksize 10000000
76
+ """
77
+ for P in expect_objects:
78
+ R = P()
79
+ if R is not None:
80
+ try:
81
+ R.quit(verbose=verbose)
82
+ except RuntimeError:
83
+ pass
84
+ kill_spawned_jobs()
85
+
86
+
87
+ def kill_spawned_jobs(verbose=False):
88
+ """
89
+ INPUT:
90
+
91
+ - ``verbose`` -- boolean (default: ``False``); if ``True``, display a
92
+ message each time a process is sent a kill signal
93
+
94
+ EXAMPLES::
95
+
96
+ sage: gp.eval('a=10') # needs sage.libs.pari
97
+ '10'
98
+ sage: sage.interfaces.quit.kill_spawned_jobs(verbose=False)
99
+ sage: sage.interfaces.quit.expect_quitall()
100
+ sage: gp.eval('a=10') # needs sage.libs.pari
101
+ '10'
102
+ sage: sage.interfaces.quit.kill_spawned_jobs(verbose=True) # needs sage.libs.pari
103
+ Killing spawned job ...
104
+
105
+ After doing the above, we do the following to avoid confusion in other doctests::
106
+
107
+ sage: sage.interfaces.quit.expect_quitall()
108
+ """
109
+ fname = sage_spawned_process_file()
110
+ if not os.path.exists(fname):
111
+ return
112
+
113
+ with open(fname) as f:
114
+ for L in f:
115
+ i = L.find(' ')
116
+ pid = L[:i].strip()
117
+ try:
118
+ if verbose:
119
+ print("Killing spawned job %s" % pid)
120
+ os.killpg(int(pid), 9)
121
+ except OSError:
122
+ pass
123
+
124
+
125
+ def is_running(pid):
126
+ """
127
+ Return ``True`` if and only if there is a process with id pid running.
128
+ """
129
+ try:
130
+ os.kill(int(pid), 0)
131
+ return True
132
+ except (OSError, ValueError):
133
+ return False
134
+
135
+
136
+ def invalidate_all():
137
+ """
138
+ Invalidate all of the expect interfaces.
139
+
140
+ This is used, e.g., by the fork-based @parallel decorator.
141
+
142
+ EXAMPLES::
143
+
144
+ sage: # needs sage.libs.pari sage.symbolic
145
+ sage: a = maxima(2); b = gp(3)
146
+ sage: a, b
147
+ (2, 3)
148
+ sage: sage.interfaces.quit.invalidate_all()
149
+ sage: a
150
+ (invalid Maxima object -- The maxima session in which this object was defined is no longer running.)
151
+ sage: b
152
+ (invalid PARI/GP interpreter object -- The pari session in which this object was defined is no longer running.)
153
+
154
+ However the maxima and gp sessions should still work out, though with their state reset::
155
+
156
+ sage: a = maxima(2); b = gp(3) # needs sage.libs.pari sage.symbolic
157
+ sage: a, b # needs sage.libs.pari sage.symbolic
158
+ (2, 3)
159
+ """
160
+ for I in expect_objects:
161
+ I1 = I()
162
+ if I1:
163
+ I1.detach()
@@ -0,0 +1,51 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+
3
+ from sage.misc.all__sagemath_objects import *
4
+
5
+ from sage.misc.sage_eval import sage_eval, sageobj
6
+
7
+ from sage.misc.sage_input import sage_input
8
+
9
+ from sage.misc.banner import version
10
+
11
+ lazy_import('sage.misc.banner', 'banner', deprecation=34259)
12
+
13
+ lazy_import('sage.misc.sagedoc', ['browse_sage_doc',
14
+ 'search_src', 'search_def', 'search_doc',
15
+ 'tutorial', 'reference', 'manual', 'developer',
16
+ 'constructions', 'help'])
17
+
18
+ lazy_import('pydoc', 'help', 'python_help')
19
+
20
+ from sage.misc.explain_pickle import (explain_pickle, unpickle_newobj, unpickle_build,
21
+ unpickle_instantiate, unpickle_persistent,
22
+ unpickle_extension, unpickle_appends)
23
+
24
+ lazy_import('sage.misc.trace', 'trace', deprecation=34259)
25
+
26
+ lazy_import('sage.misc.profiler', 'Profiler', deprecation=34259)
27
+
28
+ lazy_import('sage.misc.classgraph', 'class_graph')
29
+
30
+ from sage.misc.dev_tools import import_statements
31
+
32
+ lazy_import('sage.misc.dev_tools', 'runsnake', deprecation=34259)
33
+
34
+ from sage.misc.edit_module import edit
35
+
36
+ lazy_import('sage.misc.edit_module', 'set_edit_template', deprecation=34259)
37
+
38
+ lazy_import('sage.misc.pager', 'pager')
39
+
40
+ lazy_import('sage.misc.remote_file', 'get_remote_file')
41
+
42
+ lazy_import('sage.misc.sh', 'sh')
43
+
44
+ lazy_import("sage.misc.cython", "cython_lambda")
45
+ lazy_import("sage.misc.cython", "cython_compile", "cython")
46
+ lazy_import('sage.misc.inline_fortran', 'fortran')
47
+
48
+ lazy_import('sage.misc.package', ('installed_packages', 'is_package_installed',
49
+ 'package_versions'),
50
+ deprecation=34259)
51
+ lazy_import('sage.misc.benchmark', 'benchmark', deprecation=34259)
sage/misc/banner.py ADDED
@@ -0,0 +1,235 @@
1
+ # sage_setup: distribution = sagemath-repl
2
+ r"""
3
+ SageMath version and banner info
4
+ """
5
+
6
+ # ****************************************************************************
7
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
8
+ #
9
+ # Distributed under the terms of the GNU General Public License (GPL)
10
+ # as published by the Free Software Foundation; either version 2 of
11
+ # the License, or (at your option) any later version.
12
+ # https://www.gnu.org/licenses/
13
+ # ****************************************************************************
14
+ import sys
15
+
16
+ from sage.env import (SAGE_VERSION, SAGE_VERSION_BANNER, SAGE_BANNER)
17
+
18
+
19
+ def version():
20
+ """
21
+ Return the version of Sage.
22
+
23
+ OUTPUT: string
24
+
25
+ EXAMPLES::
26
+
27
+ sage: version()
28
+ '... version ..., Release Date: ...'
29
+ """
30
+ return SAGE_VERSION_BANNER
31
+
32
+
33
+ def banner_text(full=True):
34
+ """
35
+ Text for the Sage banner.
36
+
37
+ INPUT:
38
+
39
+ - ``full`` -- boolean (default: ``True``)
40
+
41
+ OUTPUT:
42
+
43
+ A string containing the banner message.
44
+
45
+ If option full is ``False``, a simplified plain ASCII banner is
46
+ displayed; if ``True`` the full banner with box art is displayed.
47
+
48
+ EXAMPLES::
49
+
50
+ sage: print(sage.misc.banner.banner_text(full=True))
51
+ ┌────────────────────────────────────────────────────────────────────┐
52
+ │ ... version ...
53
+ sage: print(sage.misc.banner.banner_text(full=False))
54
+ ... version ..., Release Date: ...
55
+ """
56
+ if not full:
57
+ return version()
58
+
59
+ bars = "─" * 68
60
+ s = []
61
+ a = s.append
62
+ a('┌' + bars + '┐')
63
+ a("\n│ %-66s │\n" % version())
64
+ python_version = sys.version_info[:3]
65
+ a("│ %-66s │\n" % 'Using Python {}.{}.{}. Type "help()" for help.'.format(*python_version))
66
+ a('└' + bars + '┘')
67
+ pre = version_dict()['prerelease']
68
+ try:
69
+ import sage.all
70
+ have_sage_all = True
71
+ except ImportError:
72
+ have_sage_all = False
73
+ if pre or not have_sage_all:
74
+ red_in = '\033[31m'
75
+ red_out = '\033[0m'
76
+ bars2 = bars.replace('─', '━')
77
+ a('\n')
78
+ a(red_in + '┏' + bars2 + '┓' + '\n')
79
+ if pre:
80
+ a("┃ %-66s ┃\n" % 'Warning: this is a prerelease version, and it may be unstable.')
81
+ if not have_sage_all:
82
+ a("┃ %-66s ┃\n" % 'Warning: sage.all is not available; this is a limited REPL.')
83
+ a('┗' + bars2 + '┛' + red_out)
84
+ return ''.join(s)
85
+
86
+
87
+ def banner():
88
+ """
89
+ Print the Sage banner.
90
+
91
+ OUTPUT: none
92
+
93
+ If the environment variable ``SAGE_BANNER`` is set to ``no``, no
94
+ banner is displayed. If ``SAGE_BANNER`` is set to ``bare``, a
95
+ simplified plain ASCII banner is displayed. Otherwise, the full
96
+ banner with box art is displayed.
97
+
98
+ EXAMPLES::
99
+
100
+ sage: import sage.misc.banner; sage.misc.banner.SAGE_BANNER = ''
101
+ sage: sage.misc.banner.banner()
102
+ ┌────────────────────────────────────────────────────────────────────┐
103
+ │ ... version ..., Release Date: ... │
104
+ │ Using Python .... Type "help()" for help. │
105
+ ...
106
+ """
107
+ typ = SAGE_BANNER.lower()
108
+
109
+ if typ == "no":
110
+ return
111
+
112
+ if typ != "bare":
113
+ try:
114
+ print(banner_text(full=True))
115
+ return
116
+ except UnicodeEncodeError:
117
+ pass
118
+
119
+ print(banner_text(full=False))
120
+
121
+
122
+ def version_dict():
123
+ """
124
+ A dictionary describing the version of Sage.
125
+
126
+ OUTPUT: dictionary with keys 'major', 'minor', 'tiny', 'prerelease'
127
+
128
+ This process the Sage version string and produces a dictionary.
129
+ It expects the Sage version to be in one of these forms::
130
+
131
+ N.N
132
+ N.N.N
133
+ N.N.N.N
134
+ N.N.str
135
+ N.N.N.str
136
+ N.N.N.N.str
137
+
138
+ where 'N' stands for an integer and 'str' stands for a string.
139
+ The first integer is stored under the 'major' key and the second
140
+ integer under 'minor'. If there is one more integer, it is stored
141
+ under 'tiny'; if there are two more integers, then they are stored
142
+ together as a float N.N under 'tiny'. If there is a string, then
143
+ the key 'prerelease' returns True.
144
+
145
+ For example, if the Sage version is '3.2.1', then the dictionary
146
+ is {'major': 3, 'minor': 2, 'tiny': 1, 'prerelease': False}.
147
+ If the Sage version is '3.2.1.2', then the dictionary is
148
+ {'major': 3, 'minor': 2, 'tiny': 1.200..., 'prerelease': False}.
149
+ If the Sage version is '3.2.alpha0', then the dictionary is
150
+ {'major': 3, 'minor': 2, 'tiny': 0, 'prerelease': True}.
151
+
152
+ EXAMPLES::
153
+
154
+ sage: from sage.misc.banner import version_dict
155
+ sage: print("SageMath major version is %s" % version_dict()['major'])
156
+ SageMath major version is ...
157
+ sage: version_dict()['major'] == int(sage.version.version.split('.')[0])
158
+ True
159
+ """
160
+ v = SAGE_VERSION.split('.')
161
+ dict = {}
162
+ dict['major'] = int(v[0])
163
+ dict['minor'] = int(v[1])
164
+ dict['tiny'] = 0
165
+ dict['prerelease'] = False
166
+ try:
167
+ int(v[-1])
168
+ except ValueError: # when last entry is not an integer
169
+ dict['prerelease'] = True
170
+ if (len(v) == 3 and not dict['prerelease']) or len(v) > 3:
171
+ dict['tiny'] = int(v[2])
172
+ try:
173
+ teeny = int(v[3])
174
+ dict['tiny'] += 0.1 * teeny
175
+ except (ValueError, IndexError):
176
+ pass
177
+ return dict
178
+
179
+
180
+ def require_version(major, minor=0, tiny=0, prerelease=False,
181
+ print_message=False):
182
+ """
183
+ Return ``True`` if Sage version is at least ``major.minor.tiny``.
184
+
185
+ INPUT:
186
+
187
+ - ``major`` -- integer
188
+ - ``minor`` -- integer (default: 0)
189
+ - ``tiny`` -- float (default: 0)
190
+ - ``prerelease`` -- boolean (default: ``False``)
191
+ - ``print_message`` -- boolean (default: ``False``)
192
+
193
+ OUTPUT: ``True`` if ``major.minor.tiny`` is <= version of Sage, ``False``
194
+ otherwise
195
+
196
+ For example, if the Sage version number is 3.1.2, then
197
+ require_version(3, 1, 3) will return False, while
198
+ require_version(3, 1, 2) will return True.
199
+ If the Sage version is 3.1.2.alpha0, then
200
+ require_version(3, 1, 1) will return True, while, by default,
201
+ require_version(3, 1, 2) will return False. Note, though, that
202
+ require_version(3, 1, 2, prerelease=True) will return True:
203
+ if the optional argument prerelease is True, then a prerelease
204
+ version of Sage counts as if it were the released version.
205
+
206
+ If optional argument print_message is ``True`` and this function
207
+ is returning False, print a warning message.
208
+
209
+ EXAMPLES::
210
+
211
+ sage: from sage.misc.banner import require_version
212
+ sage: require_version(2, 1, 3)
213
+ True
214
+ sage: require_version(821, 4)
215
+ False
216
+ sage: require_version(821, 4, print_message=True)
217
+ This code requires at least version 821.4 of SageMath to run correctly.
218
+ You are running version ...
219
+ False
220
+ """
221
+ vers = version_dict()
222
+ prerelease_checked = (prerelease if vers['prerelease'] else True)
223
+ if (vers['major'] > major
224
+ or (vers['major'] == major and vers['minor'] > minor)
225
+ or (vers['major'] == major and vers['minor'] == minor
226
+ and vers['tiny'] > tiny)
227
+ or (vers['major'] == major and vers['minor'] == minor
228
+ and vers['tiny'] == tiny and prerelease_checked)):
229
+ return True
230
+ else:
231
+ if print_message:
232
+ txt = "This code requires at least version {} of SageMath to run correctly."
233
+ print(txt.format(major + 0.1 * minor + 0.01 * tiny))
234
+ print("You are running version {}.".format(SAGE_VERSION))
235
+ return False