Format Sage documentation for viewing with IPython and the notebook¶
AUTHORS:
William Stein (2005): initial version.
Nick Alexander (2007): nodetex functions
Nick Alexander (2008): search_src, search_def improvements
Martin Albrecht (2008-03-21): parse LaTeX description environments in sagedoc
John Palmieri (2009-04-11): fix for #5754 plus doctests
Dan Drake (2009-05-21): refactor search_* functions, use system ‘find’ instead of sage -grep
John Palmieri (2009-06-28): don’t use ‘find’ – use Python (os.walk, re.search) instead.
Simon King (2011-09): Use os.linesep, avoid destruction of embedding information, enable nodetex in a docstring. Consequently use sage_getdoc.
- sage.misc.sagedoc.detex(s, embedded=False)[source]¶
This strips LaTeX commands from a string; it is used by the
format
function to process docstrings for display from the command line interface.INPUT:
s
– stringembedded
– boolean (default:False
)
If
embedded
isFalse
, then do the replacements in bothmath_substitutes
andnonmath_substitutes
. IfTrue
, then only dononmath_substitutes
.OUTPUT: string
EXAMPLES:
sage: from sage.misc.sagedoc import detex sage: detex(r'Some math: `n \geq k`. A website: \url{sagemath.org}.') 'Some math: n >= k. A website: sagemath.org.\n' sage: detex(r'More math: `x \mapsto y`. {\bf Bold face}.') 'More math: x |--> y. { Bold face}.\n' sage: detex(r'`a, b, c, \ldots, z`') 'a, b, c, ..., z\n' sage: detex(r'`a, b, c, \ldots, z`', embedded=True) '`a, b, c, \\ldots, z`' sage: detex(r'`\left(\lvert x\ast y \rvert\right]`') '(| x * y |]\n' sage: detex(r'`\left(\leq\le\leftarrow \rightarrow\unknownmacro\to`') '(<=<=<-- -->\\unknownmacro-->\n'
>>> from sage.all import * >>> from sage.misc.sagedoc import detex >>> detex(r'Some math: `n \geq k`. A website: \url{sagemath.org}.') 'Some math: n >= k. A website: sagemath.org.\n' >>> detex(r'More math: `x \mapsto y`. {\bf Bold face}.') 'More math: x |--> y. { Bold face}.\n' >>> detex(r'`a, b, c, \ldots, z`') 'a, b, c, ..., z\n' >>> detex(r'`a, b, c, \ldots, z`', embedded=True) '`a, b, c, \\ldots, z`' >>> detex(r'`\left(\lvert x\ast y \rvert\right]`') '(| x * y |]\n' >>> detex(r'`\left(\leq\le\leftarrow \rightarrow\unknownmacro\to`') '(<=<=<-- -->\\unknownmacro-->\n'
from sage.misc.sagedoc import detex detex(r'Some math: `n \geq k`. A website: \url{sagemath.org}.') detex(r'More math: `x \mapsto y`. {\bf Bold face}.') detex(r'`a, b, c, \ldots, z`') detex(r'`a, b, c, \ldots, z`', embedded=True) detex(r'`\left(\lvert x\ast y \rvert\right]`') detex(r'`\left(\leq\le\leftarrow \rightarrow\unknownmacro\to`')
- sage.misc.sagedoc.format(s, embedded=False)[source]¶
noreplace Format Sage documentation
s
for viewing with IPython.This calls
detex()
ons
to convert LaTeX commands to plain text, unless the directivenodetex
is given in the first line of the string.Also, if
s
contains a string of the form<<<obj>>>
, then it replaces it with the docstring forobj
, unless the directivenoreplace
is given in the first line. If an error occurs under the attempt to find the docstring forobj
, then the substring<<<obj>>>
is preserved.Directives must be separated by a comma.
INPUT:
s
– stringembedded
– boolean (default:False
)
OUTPUT: string
Set
embedded
equal toTrue
if formatting for use in the notebook; this just gets passed as an argument todetex()
.See also
sage.misc.sageinspect.sage_getdoc()
to get the formatted documentation of a given object.EXAMPLES:
sage: from sage.misc.sagedoc import format sage: format('Let `A` be an `m` by `n` (0,1)-matrix. We identify `A` with a chessboard') 'Let A be an m by n (0,1)-matrix. We identify A with a chessboard\n'
>>> from sage.all import * >>> from sage.misc.sagedoc import format >>> format('Let `A` be an `m` by `n` (0,1)-matrix. We identify `A` with a chessboard') 'Let A be an m by n (0,1)-matrix. We identify A with a chessboard\n'
from sage.misc.sagedoc import format format('Let `A` be an `m` by `n` (0,1)-matrix. We identify `A` with a chessboard')
If the first line of the string is ‘nodetex’, remove ‘nodetex’ but don’t modify any TeX commands:
sage: format("nodetex\n`x \\geq y`") '`x \\geq y`'
>>> from sage.all import * >>> format("nodetex\n`x \\geq y`") '`x \\geq y`'
format("nodetex\n`x \\geq y`")
Testing a string enclosed in triple angle brackets:
sage: format('<<<identity_matrix') '<<<identity_matrix\n' sage: format('identity_matrix>>>') 'identity_matrix>>>\n' sage: format('<<<identity_matrix>>>') # needs sage.modules '...Definition: identity_matrix(...' sage: format('<<<identity_matrix>>>')[:28] # needs sphinx 'Definition: identity_matrix('
>>> from sage.all import * >>> format('<<<identity_matrix') '<<<identity_matrix\n' >>> format('identity_matrix>>>') 'identity_matrix>>>\n' >>> format('<<<identity_matrix>>>') # needs sage.modules '...Definition: identity_matrix(...' >>> format('<<<identity_matrix>>>')[:Integer(28)] # needs sphinx 'Definition: identity_matrix('
format('<<<identity_matrix') format('identity_matrix>>>') format('<<<identity_matrix>>>') # needs sage.modules format('<<<identity_matrix>>>')[:28] # needs sphinx
- sage.misc.sagedoc.format_search_as_html(what, results, search)[source]¶
Format the output from
search_src
,search_def
, orsearch_doc
as html, for use in the notebook.INPUT:
what
– string; what was searched (source code or documentation)results
– string or list; the results of the search as a string or list of search resultssearch
– string or list; what was being searched for, either as a string which is taken verbatim, or a list of multiple search terms if there were more than one
This function parses
results
: each line should have either the formFILENAME
orFILENAME: string
where FILENAME is the file in which the string that matched the search was found. If FILENAME ends in ‘.html’, then this is part of the documentation; otherwise, it is in the source code. In either case, an appropriate link is created.EXAMPLES:
sage: from sage.misc.sagedoc import format_search_as_html sage: format_search_as_html('Source', 'algebras/steenrod_algebra_element.py: an antihomomorphism: if we call the antipode `c`, then', 'antipode antihomomorphism') '<html><font color="black"><h2>Search Source: "antipode antihomomorphism"</h2></font><font color="darkpurple"><ol><li><a href="/src/algebras/steenrod_algebra_element.py" target="_blank"><tt>algebras/steenrod_algebra_element.py</tt></a>\n</ol></font></html>' sage: format_search_as_html('Other', 'html/en/reference/sage/algebras/steenrod_algebra_element.html:an antihomomorphism: if we call the antipode <span class="math">c</span>, then', 'antipode antihomomorphism') '<html><font color="black"><h2>Search Other: "antipode antihomomorphism"</h2></font><font color="darkpurple"><ol><li><a href="/doc/live/reference/sage/algebras/steenrod_algebra_element.html" target="_blank"><tt>reference/sage/algebras/steenrod_algebra_element.html</tt></a>\n</ol></font></html>'
>>> from sage.all import * >>> from sage.misc.sagedoc import format_search_as_html >>> format_search_as_html('Source', 'algebras/steenrod_algebra_element.py: an antihomomorphism: if we call the antipode `c`, then', 'antipode antihomomorphism') '<html><font color="black"><h2>Search Source: "antipode antihomomorphism"</h2></font><font color="darkpurple"><ol><li><a href="/src/algebras/steenrod_algebra_element.py" target="_blank"><tt>algebras/steenrod_algebra_element.py</tt></a>\n</ol></font></html>' >>> format_search_as_html('Other', 'html/en/reference/sage/algebras/steenrod_algebra_element.html:an antihomomorphism: if we call the antipode <span class="math">c</span>, then', 'antipode antihomomorphism') '<html><font color="black"><h2>Search Other: "antipode antihomomorphism"</h2></font><font color="darkpurple"><ol><li><a href="/doc/live/reference/sage/algebras/steenrod_algebra_element.html" target="_blank"><tt>reference/sage/algebras/steenrod_algebra_element.html</tt></a>\n</ol></font></html>'
from sage.misc.sagedoc import format_search_as_html format_search_as_html('Source', 'algebras/steenrod_algebra_element.py: an antihomomorphism: if we call the antipode `c`, then', 'antipode antihomomorphism') format_search_as_html('Other', 'html/en/reference/sage/algebras/steenrod_algebra_element.html:an antihomomorphism: if we call the antipode <span class="math">c</span>, then', 'antipode antihomomorphism')
- sage.misc.sagedoc.format_src(s)[source]¶
Format Sage source code
s
for viewing with IPython.If
s
contains a string of the form “<<<obj>>>”, then it replaces it with the source code for “obj”.INPUT:
s
– string
OUTPUT: string
EXAMPLES:
sage: from sage.misc.sagedoc import format_src sage: format_src('unladen swallow') 'unladen swallow' sage: format_src('<<<Sq>>>')[5:15] # needs sage.combinat sage.modules 'Sq(*nums):'
>>> from sage.all import * >>> from sage.misc.sagedoc import format_src >>> format_src('unladen swallow') 'unladen swallow' >>> format_src('<<<Sq>>>')[Integer(5):Integer(15)] # needs sage.combinat sage.modules 'Sq(*nums):'
from sage.misc.sagedoc import format_src format_src('unladen swallow') format_src('<<<Sq>>>')[5:15] # needs sage.combinat sage.modules
- sage.misc.sagedoc.help(module=None)[source]¶
If there is an argument
module
, print the Python help message formodule
. With no argument, print a help message about getting help in Sage.EXAMPLES:
sage: help() Welcome to Sage ...
>>> from sage.all import * >>> help() Welcome to Sage ...
help()
- sage.misc.sagedoc.my_getsource(obj, oname='')[source]¶
Retrieve the source code for
obj
.INPUT:
obj
– a Sage object, function, etc.oname
– string (optional); a name under which the object is known. Currently ignored by Sage
OUTPUT:
Its documentation (string)
EXAMPLES:
sage: from sage.misc.sagedoc import my_getsource sage: s = my_getsource(identity_matrix) # needs sage.modules sage: s[15:34] # needs sage.modules 'def identity_matrix'
>>> from sage.all import * >>> from sage.misc.sagedoc import my_getsource >>> s = my_getsource(identity_matrix) # needs sage.modules >>> s[Integer(15):Integer(34)] # needs sage.modules 'def identity_matrix'
from sage.misc.sagedoc import my_getsource s = my_getsource(identity_matrix) # needs sage.modules s[15:34] # needs sage.modules
- sage.misc.sagedoc.process_dollars(s)[source]¶
Replace dollar signs with backticks.
More precisely, do a regular expression search. Replace a plain dollar sign ($) by a backtick (`). Replace an escaped dollar sign (\$) by a dollar sign ($). Don’t change a dollar sign preceded or followed by a backtick (`$ or $`), because of strings like “
$HOME
”. Don’t make any changes on lines starting with more spaces than the first nonempty line ins
, because those are indented and hence part of a block of code or examples.This also doesn’t replaces dollar signs enclosed in curly braces, to avoid nested math environments.
EXAMPLES:
sage: from sage.misc.sagedoc import process_dollars sage: process_dollars('hello') 'hello' sage: process_dollars('some math: $x=y$') doctest:warning... DeprecationWarning: using dollar signs to mark up math in Sage docstrings is deprecated; use backticks instead See https://github.com/sagemath/sage/issues/33973 for details. 'some math: `x=y`'
>>> from sage.all import * >>> from sage.misc.sagedoc import process_dollars >>> process_dollars('hello') 'hello' >>> process_dollars('some math: $x=y$') doctest:warning... DeprecationWarning: using dollar signs to mark up math in Sage docstrings is deprecated; use backticks instead See https://github.com/sagemath/sage/issues/33973 for details. 'some math: `x=y`'
from sage.misc.sagedoc import process_dollars process_dollars('hello') process_dollars('some math: $x=y$')
Replace \$ with $, and don’t do anything when backticks are involved:
sage: process_dollars(r'a ``$REAL`` dollar sign: \$') 'a ``$REAL`` dollar sign: $'
>>> from sage.all import * >>> process_dollars(r'a ``$REAL`` dollar sign: \$') 'a ``$REAL`` dollar sign: $'
process_dollars(r'a ``$REAL`` dollar sign: \$')
Don’t make any changes on lines indented more than the first nonempty line:
sage: s = '\n first line\n indented $x=y$' sage: s == process_dollars(s) True
>>> from sage.all import * >>> s = '\n first line\n indented $x=y$' >>> s == process_dollars(s) True
s = '\n first line\n indented $x=y$' s == process_dollars(s)
Don’t replace dollar signs enclosed in curly braces:
sage: process_dollars(r'f(n) = 0 \text{ if $n$ is prime}') 'f(n) = 0 \\text{ if $n$ is prime}'
>>> from sage.all import * >>> process_dollars(r'f(n) = 0 \text{ if $n$ is prime}') 'f(n) = 0 \\text{ if $n$ is prime}'
process_dollars(r'f(n) = 0 \text{ if $n$ is prime}')
This is not perfect:
sage: process_dollars(r'$f(n) = 0 \text{ if $n$ is prime}$') '`f(n) = 0 \\text{ if $n$ is prime}$'
>>> from sage.all import * >>> process_dollars(r'$f(n) = 0 \text{ if $n$ is prime}$') '`f(n) = 0 \\text{ if $n$ is prime}$'
process_dollars(r'$f(n) = 0 \text{ if $n$ is prime}$')
The regular expression search doesn’t find the last $. Fortunately, there don’t seem to be any instances of this kind of expression in the Sage library, as of this writing.
- sage.misc.sagedoc.process_extlinks(s, embedded=False)[source]¶
In docstrings at the command line, process markup related to the Sphinx extlinks extension. For example, replace
:issue:`NUM`
withhttps://github.com/sagemath/sage/issues/NUM
, and similarly with:python:TEXT
and:wikipedia:TEXT
, looking up the url from the dictionaryextlinks
insage_docbuild.conf
. IfTEXT
is of the formblah <LINK>
, then it usesLINK
rather thanTEXT
to construct the url.In the notebook, don’t do anything: let sphinxify take care of it.
INPUT:
s
– string, in practice a docstringembedded
– boolean (default:False
)
This function is called by
format()
, and if in the notebook, it setsembedded
to beTrue
, otherwiseFalse
.EXAMPLES:
sage: from sage.misc.sagedoc import process_extlinks sage: process_extlinks('See :issue:`1234`, :wikipedia:`Wikipedia <Sage_(mathematics_software)>`, and :issue:`4321` ...') 'See https://github.com/sagemath/sage/issues/1234, https://en.wikipedia.org/wiki/Sage_(mathematics_software), and https://github.com/sagemath/sage/issues/4321 ...' sage: process_extlinks('See :issue:`1234` for more information.', embedded=True) 'See :issue:`1234` for more information.' sage: process_extlinks('see :python:`Implementing Descriptors <reference/datamodel.html#implementing-descriptors>` ...') 'see https://docs.python.org/release/.../reference/datamodel.html#implementing-descriptors ...'
>>> from sage.all import * >>> from sage.misc.sagedoc import process_extlinks >>> process_extlinks('See :issue:`1234`, :wikipedia:`Wikipedia <Sage_(mathematics_software)>`, and :issue:`4321` ...') 'See https://github.com/sagemath/sage/issues/1234, https://en.wikipedia.org/wiki/Sage_(mathematics_software), and https://github.com/sagemath/sage/issues/4321 ...' >>> process_extlinks('See :issue:`1234` for more information.', embedded=True) 'See :issue:`1234` for more information.' >>> process_extlinks('see :python:`Implementing Descriptors <reference/datamodel.html#implementing-descriptors>` ...') 'see https://docs.python.org/release/.../reference/datamodel.html#implementing-descriptors ...'
from sage.misc.sagedoc import process_extlinks process_extlinks('See :issue:`1234`, :wikipedia:`Wikipedia <Sage_(mathematics_software)>`, and :issue:`4321` ...') process_extlinks('See :issue:`1234` for more information.', embedded=True) process_extlinks('see :python:`Implementing Descriptors <reference/datamodel.html#implementing-descriptors>` ...')
- sage.misc.sagedoc.process_mathtt(s)[source]¶
Replace \mathtt{BLAH} with BLAH in the command line.
INPUT:
s
– string, in practice a docstring
This function is called by
format()
.EXAMPLES:
sage: from sage.misc.sagedoc import process_mathtt sage: process_mathtt(r'e^\mathtt{self}') 'e^self'
>>> from sage.all import * >>> from sage.misc.sagedoc import process_mathtt >>> process_mathtt(r'e^\mathtt{self}') 'e^self'
from sage.misc.sagedoc import process_mathtt process_mathtt(r'e^\mathtt{self}')
- sage.misc.sagedoc.process_optional_doctest_tags(s)[source]¶
Remove
# optional/needs
doctest tags for present features from docstrings
.EXAMPLES:
sage: from sage.misc.sagedoc import process_optional_doctest_tags sage: process_optional_doctest_tags(“sage: # needs sage.rings.finite_ringsnsage: K.<x> = FunctionField(GF(5^2,’a’)); KnRational function field in x over Finite Field in a of size 5^2”) # needs sage.rings.finite_rings “sage: K.<x> = FunctionField(GF(5^2,’a’)); KnRational function field in x over Finite Field in a of size 5^2”
- sage.misc.sagedoc.search_def(name, extra1='', extra2='', extra3='', extra4='', extra5='', **kwds)[source]¶
Search Sage library source code for function definitions containing
name
. The search is case-insensitive by default.INPUT: same as for
search_src()
.OUTPUT: same as for
search_src()
Note
The regular expression used by this function only finds function definitions that are preceded by spaces, so if you use tabs on a “def” line, this function will not find it. As tabs are not allowed in Sage library code, this should not be a problem.
EXAMPLES:
See the documentation for
search_src()
for more examples.sage: print(search_def("fetch", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key): matrix/matrix0.pxd: cdef fetch(self, key) sage: print(search_def("fetch", path_re="pyx", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key):
>>> from sage.all import * >>> print(search_def("fetch", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key): matrix/matrix0.pxd: cdef fetch(self, key) >>> print(search_def("fetch", path_re="pyx", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key):
print(search_def("fetch", interact=False)) # random # long time print(search_def("fetch", path_re="pyx", interact=False)) # random # long time
- sage.misc.sagedoc.search_doc(string, extra1='', extra2='', extra3='', extra4='', extra5='', **kwds)[source]¶
Search Sage HTML documentation for lines containing
string
. The search is case-insensitive by default.The file paths in the output are relative to
$SAGE_DOC
.INPUT: same as for
search_src()
.OUTPUT: same as for
search_src()
EXAMPLES:
See the documentation for
search_src()
for more examples.sage: search_doc('creates a polynomial', path_re='tutorial', interact=False) # random html/en/tutorial/tour_polynomial.html:<p>This creates a polynomial ring and tells Sage to use (the string)
>>> from sage.all import * >>> search_doc('creates a polynomial', path_re='tutorial', interact=False) # random html/en/tutorial/tour_polynomial.html:<p>This creates a polynomial ring and tells Sage to use (the string)
search_doc('creates a polynomial', path_re='tutorial', interact=False) # random
If you search the documentation for ‘tree’, then you will get too many results, because many lines in the documentation contain the word ‘toctree’. If you use the
whole_word
option, though, you can search for ‘tree’ without returning all of the instances of ‘toctree’. In the following, sincesearch_doc('tree', interact=False)
returns a string with one line for each match, counting the length ofsearch_doc('tree', interact=False).splitlines()
gives the number of matches.sage: # long time, needs sagemath_doc_html sage: N = len(search_doc('tree', interact=False).splitlines()) sage: L = search_doc('tree', whole_word=True, interact=False).splitlines() sage: len(L) < N True sage: import re sage: tree_re = re.compile(r'(^|\W)tree(\W|$)', re.I) sage: all(tree_re.search(l) for l in L) True
>>> from sage.all import * >>> # long time, needs sagemath_doc_html >>> N = len(search_doc('tree', interact=False).splitlines()) >>> L = search_doc('tree', whole_word=True, interact=False).splitlines() >>> len(L) < N True >>> import re >>> tree_re = re.compile(r'(^|\W)tree(\W|$)', re.I) >>> all(tree_re.search(l) for l in L) True
# long time, needs sagemath_doc_html N = len(search_doc('tree', interact=False).splitlines()) L = search_doc('tree', whole_word=True, interact=False).splitlines() len(L) < N import re tree_re = re.compile(r'(^|\W)tree(\W|$)', re.I) all(tree_re.search(l) for l in L)
- sage.misc.sagedoc.search_src(string, extra1='', extra2='', extra3='', extra4='', extra5='', **kwds)[source]¶
Search Sage library source code for lines containing
string
. The search is case-insensitive by default.INPUT:
string
– string to find in the Sage source codeextra1
, …,extra5
– additional strings to require when searching. Lines must match all of these, as well asstring
whole_word
– (default:False
) ifTrue
, search forstring
andextra1
(etc.) as whole words only. This assumes that each of these arguments is a single word, not a regular expression, and it might have unexpected results if used with regular expressions.ignore_case
– boolean (default:True
); ifFalse
, perform a case-sensitive searchmultiline
– (default:False
) ifTrue
, search more than one line at a time. In this case, print any matching file names, but don’t print line numbers.interact
– boolean (default:True
); ifFalse
, return a string with all the matches. Otherwise, this function returnsNone
, and the results are displayed appropriately, according to whether you are using the notebook or the command-line interface. You should not ordinarily need to use this.path_re
– (default:''
) regular expression which the filename (including the path) must matchmodule
– (default:'sage'
) the module in which to search. The default is ‘sage’, the entire Sage library. Ifmodule
doesn’t start with “sage”, then the links in the notebook output may not function.
OUTPUT:
If
interact
isFalse
, then return a string with all of the matches, separated by newlines. On the other hand, ifinteract
isTrue
(the default), there is no output. Instead: at the command line, the search results are printed on the screen in the formfilename:line_number:line of text
, showing the filename in which each match occurs, the line number where it occurs, and the actual matching line. (Ifmultiline
isTrue
, then only the filename is printed for each match.) The file paths in the output are relative to$SAGE_SRC
. In the notebook, each match produces a link to the actual file in which it occurs.The
string
andextraN
arguments are treated as regular expressions, as ispath_re
, and errors will be raised if they are invalid. The matches will be case-insensitive unlessignore_case
isFalse
.Note
The
extraN
parameters are present only becausesearch_src(string, *extras, interact=False)
is not parsed correctly by Python 2.6; see http://bugs.python.org/issue1909.EXAMPLES:
First note that without using
interact=False
, this function produces no output, while withinteract=False
, the output is a string. These examples almost all use this option, so that they have something to which to compare their output.You can search for “matrix” by typing
search_src("matrix")
. This particular search will produce many results:sage: len(search_src("matrix", interact=False).splitlines()) # random # long time 9522
>>> from sage.all import * >>> len(search_src("matrix", interact=False).splitlines()) # random # long time 9522
len(search_src("matrix", interact=False).splitlines()) # random # long time
You can restrict to the Sage calculus code with
search_src("matrix", module="sage.calculus")
, and this produces many fewer results:sage: len(search_src("matrix", module="sage.calculus", interact=False).splitlines()) # random 26
>>> from sage.all import * >>> len(search_src("matrix", module="sage.calculus", interact=False).splitlines()) # random 26
len(search_src("matrix", module="sage.calculus", interact=False).splitlines()) # random
Note that you can do tab completion on the
module
string. Another way to accomplish a similar search:sage: len(search_src("matrix", path_re="calc", # needs sage.modules ....: interact=False).splitlines()) > 15 True
>>> from sage.all import * >>> len(search_src("matrix", path_re="calc", # needs sage.modules ... interact=False).splitlines()) > Integer(15) True
len(search_src("matrix", path_re="calc", # needs sage.modules interact=False).splitlines()) > 15
The following produces an error because the string ‘fetch(’ is a malformed regular expression:
sage: print(search_src(" fetch(", "def", interact=False)) Traceback (most recent call last): ... error: missing ), unterminated subpattern at position 6
>>> from sage.all import * >>> print(search_src(" fetch(", "def", interact=False)) Traceback (most recent call last): ... error: missing ), unterminated subpattern at position 6
print(search_src(" fetch(", "def", interact=False))
To fix this, escape the parenthesis with a backslash:
sage: print(search_src(r" fetch\(", "def", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key): matrix/matrix0.pxd: cdef fetch(self, key) sage: print(search_src(r" fetch\(", "def", "pyx", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key):
>>> from sage.all import * >>> print(search_src(r" fetch\(", "def", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key): matrix/matrix0.pxd: cdef fetch(self, key) >>> print(search_src(r" fetch\(", "def", "pyx", interact=False)) # random # long time matrix/matrix0.pyx: cdef fetch(self, key):
print(search_src(r" fetch\(", "def", interact=False)) # random # long time print(search_src(r" fetch\(", "def", "pyx", interact=False)) # random # long time
As noted above, the search is case-insensitive, but you can make it case-sensitive with the ‘ignore_case’ key word:
sage: s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > 0 True sage: s = search_src('MatRiX', path_re='matrix', interact=False); s.find('x') > 0 True sage: s = search_src('MatRiX', path_re='matrix', ....: interact=False, ignore_case=False); s.find('x') > 0 False
>>> from sage.all import * >>> s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > Integer(0) True >>> s = search_src('MatRiX', path_re='matrix', interact=False); s.find('x') > Integer(0) True >>> s = search_src('MatRiX', path_re='matrix', ... interact=False, ignore_case=False); s.find('x') > Integer(0) False
s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > 0 s = search_src('MatRiX', path_re='matrix', interact=False); s.find('x') > 0 s = search_src('MatRiX', path_re='matrix', interact=False, ignore_case=False); s.find('x') > 0
Searches are by default restricted to single lines, but this can be changed by setting
multiline
to be True. In the following, sincesearch_src(string, interact=False)
returns a string with one line for each match, counting the length ofsearch_src(string, interact=False).splitlines()
gives the number of matches.sage: len(search_src('log', 'derivative', interact=False).splitlines()) < 40 True sage: len(search_src('log', 'derivative', ....: interact=False, multiline=True).splitlines()) > 70 True
>>> from sage.all import * >>> len(search_src('log', 'derivative', interact=False).splitlines()) < Integer(40) True >>> len(search_src('log', 'derivative', ... interact=False, multiline=True).splitlines()) > Integer(70) True
len(search_src('log', 'derivative', interact=False).splitlines()) < 40 len(search_src('log', 'derivative', interact=False, multiline=True).splitlines()) > 70
A little recursive narcissism: let’s do a doctest that searches for this function’s doctests. Note that you can’t put “sage:” in the doctest string because it will get replaced by the Python “>>>” prompt.
sage: print(search_src(r'^ *sage[:] .*search_src\(', interact=False)) # long time misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines())... misc/sagedoc.py:... len(search_src("matrix", module="sage.calculus", interact=False).splitlines())... misc/sagedoc.py:... len(search_src("matrix", path_re="calc"... misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False))... misc/sagedoc.py:... print(search_src(r" fetch\(", "def", interact=False))... misc/sagedoc.py:... print(search_src(r" fetch\(", "def", "pyx", interact=False))... misc/sagedoc.py:... s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > 0... misc/sagedoc.py:... s = search_src('MatRiX', path_re='matrix', interact=False); s.find('x') > 0... misc/sagedoc.py:... s = search_src('MatRiX', path_re='matrix',... misc/sagedoc.py:... len(search_src('log', 'derivative', interact=False).splitlines()) < 40... misc/sagedoc.py:... len(search_src('log', 'derivative'... misc/sagedoc.py:... print(search_src(r'^ *sage[:] .*search_src\(', interact=False))... misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines()) > 9000... misc/sagedoc.py:... print(search_src('matrix', 'column', 'row', 'sub',... misc/sagedoc.py:... sage: results = search_src('format_search_as_html',...
>>> from sage.all import * >>> print(search_src(r'^ *sage[:] .*search_src\(', interact=False)) # long time misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines())... misc/sagedoc.py:... len(search_src("matrix", module="sage.calculus", interact=False).splitlines())... misc/sagedoc.py:... len(search_src("matrix", path_re="calc"... misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False))... misc/sagedoc.py:... print(search_src(r" fetch\(", "def", interact=False))... misc/sagedoc.py:... print(search_src(r" fetch\(", "def", "pyx", interact=False))... misc/sagedoc.py:... s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > 0... misc/sagedoc.py:... s = search_src('MatRiX', path_re='matrix', interact=False); s.find('x') > 0... misc/sagedoc.py:... s = search_src('MatRiX', path_re='matrix',... misc/sagedoc.py:... len(search_src('log', 'derivative', interact=False).splitlines()) < 40... misc/sagedoc.py:... len(search_src('log', 'derivative'... misc/sagedoc.py:... print(search_src(r'^ *sage[:] .*search_src\(', interact=False))... misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines()) > 9000... misc/sagedoc.py:... print(search_src('matrix', 'column', 'row', 'sub',... misc/sagedoc.py:... sage: results = search_src('format_search_as_html',...
print(search_src(r'^ *sage[:] .*search_src\(', interact=False)) # long time
- sage.misc.sagedoc.skip_TESTS_block(docstring)[source]¶
Remove blocks labeled “TESTS:” from
docstring
.INPUT:
docstring
– string
A “TESTS” block is a block starting “TESTS:” (or the same with two colons), on a line on its own, and ending either with a line indented less than “TESTS”, or with a line with the same level of indentation – not more – matching one of the following:
a Sphinx directive of the form “.. foo:”, optionally followed by other text.
text of the form “UPPERCASE:”, optionally followed by other text.
lines which look like a reST header: one line containing anything, followed by a line consisting only of a string of hyphens, equal signs, or other characters which are valid markers for reST headers:
- = ` : ' " ~ _ ^ * + # < >
. However, lines only containing double colons \(::\) do not end “TESTS” blocks.
Return the string obtained from
docstring
by removing these blocks.EXAMPLES:
sage: from sage.misc.sagedoc import skip_TESTS_block sage: start = ' Docstring\n\n' sage: test = ' TESTS: \n\n Here is a test::\n sage: 2+2 \n 5 \n\n' sage: test2 = ' TESTS:: \n\n sage: 2+2 \n 6 \n\n'
>>> from sage.all import * >>> from sage.misc.sagedoc import skip_TESTS_block >>> start = ' Docstring\n\n' >>> test = ' TESTS: \n\n Here is a test::\n sage: 2+2 \n 5 \n\n' >>> test2 = ' TESTS:: \n\n sage: 2+2 \n 6 \n\n'
from sage.misc.sagedoc import skip_TESTS_block start = ' Docstring\n\n' test = ' TESTS: \n\n Here is a test::\n sage: 2+2 \n 5 \n\n' test2 = ' TESTS:: \n\n sage: 2+2 \n 6 \n\n'
Test lines starting with “REFERENCES:”:
sage: refs = ' REFERENCES: \n text text \n' sage: skip_TESTS_block(start + test + refs).rstrip() == (start + refs).rstrip() True sage: skip_TESTS_block(start + test + test2 + refs).rstrip() == (start + refs).rstrip() True sage: skip_TESTS_block(start + test + refs + test2).rstrip() == (start + refs).rstrip() True
>>> from sage.all import * >>> refs = ' REFERENCES: \n text text \n' >>> skip_TESTS_block(start + test + refs).rstrip() == (start + refs).rstrip() True >>> skip_TESTS_block(start + test + test2 + refs).rstrip() == (start + refs).rstrip() True >>> skip_TESTS_block(start + test + refs + test2).rstrip() == (start + refs).rstrip() True
refs = ' REFERENCES: \n text text \n' skip_TESTS_block(start + test + refs).rstrip() == (start + refs).rstrip() skip_TESTS_block(start + test + test2 + refs).rstrip() == (start + refs).rstrip() skip_TESTS_block(start + test + refs + test2).rstrip() == (start + refs).rstrip()
Test Sphinx directives:
sage: directive = ' .. todo:: \n do some stuff \n' sage: skip_TESTS_block(start + test + refs + test2 + directive).rstrip() == (start + refs + directive).rstrip() True
>>> from sage.all import * >>> directive = ' .. todo:: \n do some stuff \n' >>> skip_TESTS_block(start + test + refs + test2 + directive).rstrip() == (start + refs + directive).rstrip() True
directive = ' .. todo:: \n do some stuff \n' skip_TESTS_block(start + test + refs + test2 + directive).rstrip() == (start + refs + directive).rstrip()
Test unindented lines:
sage: unindented = 'NOT INDENTED\n' sage: skip_TESTS_block(start + test + unindented).rstrip() == (start + unindented).rstrip() True sage: skip_TESTS_block(start + test + unindented + test2 + unindented).rstrip() == (start + unindented + unindented).rstrip() True
>>> from sage.all import * >>> unindented = 'NOT INDENTED\n' >>> skip_TESTS_block(start + test + unindented).rstrip() == (start + unindented).rstrip() True >>> skip_TESTS_block(start + test + unindented + test2 + unindented).rstrip() == (start + unindented + unindented).rstrip() True
unindented = 'NOT INDENTED\n' skip_TESTS_block(start + test + unindented).rstrip() == (start + unindented).rstrip() skip_TESTS_block(start + test + unindented + test2 + unindented).rstrip() == (start + unindented + unindented).rstrip()
Test headers:
sage: header = ' Header:\n ~~~~~~~~' sage: skip_TESTS_block(start + test + header) == start + header True
>>> from sage.all import * >>> header = ' Header:\n ~~~~~~~~' >>> skip_TESTS_block(start + test + header) == start + header True
header = ' Header:\n ~~~~~~~~' skip_TESTS_block(start + test + header) == start + header
Not a header because the characters on the second line must all be the same:
sage: fake_header = ' Header:\n -=-=-=-=-=' sage: skip_TESTS_block(start + test + fake_header).rstrip() == start.rstrip() True
>>> from sage.all import * >>> fake_header = ' Header:\n -=-=-=-=-=' >>> skip_TESTS_block(start + test + fake_header).rstrip() == start.rstrip() True
fake_header = ' Header:\n -=-=-=-=-=' skip_TESTS_block(start + test + fake_header).rstrip() == start.rstrip()
Not a header because it’s indented compared to ‘TEST’ in the string
test
:sage: another_fake = '\n blah\n ----' sage: skip_TESTS_block(start + test + another_fake).rstrip() == start.rstrip() True
>>> from sage.all import * >>> another_fake = '\n blah\n ----' >>> skip_TESTS_block(start + test + another_fake).rstrip() == start.rstrip() True
another_fake = '\n blah\n ----' skip_TESTS_block(start + test + another_fake).rstrip() == start.rstrip()
Double colons
::
are also not considered as headers (Issue #27896):sage: colons = ' ::\n\n sage: 2+2\n 4\n\n' sage: skip_TESTS_block(start + test2 + colons).rstrip() == start.rstrip() True
>>> from sage.all import * >>> colons = ' ::\n\n sage: 2+2\n 4\n\n' >>> skip_TESTS_block(start + test2 + colons).rstrip() == start.rstrip() True
colons = ' ::\n\n sage: 2+2\n 4\n\n' skip_TESTS_block(start + test2 + colons).rstrip() == start.rstrip()