Classes for sources of doctests¶
This module defines various classes for sources from which doctests originate, such as files, functions or database entries.
AUTHORS:
David Roe (2012-03-27) – initial version, based on Robert Bradshaw’s code.
-
class
sage.doctest.sources.
DictAsObject
(attrs)¶ Bases:
dict
A simple subclass of dict that inserts the items from the initializing dictionary into attributes.
EXAMPLES:
sage: from sage.doctest.sources import DictAsObject sage: D = DictAsObject({'a':2}) sage: D.a 2
-
class
sage.doctest.sources.
DocTestSource
(options)¶ Bases:
object
This class provides a common base class for different sources of doctests.
INPUT:
options
– asage.doctest.control.DocTestDefaults
instance or equivalent.
-
class
sage.doctest.sources.
FileDocTestSource
(path, options)¶ Bases:
sage.doctest.sources.DocTestSource
This class creates doctests from a file.
INPUT:
path
– string, the filenameoptions
– asage.doctest.control.DocTestDefaults
instance or equivalent.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.env import SAGE_SRC sage: import os sage: filename = os.path.join(SAGE_SRC,'sage','doctest','sources.py') sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS.basename 'sage.doctest.sources'
-
basename
()¶ The basename of this file source, e.g. sage.doctest.sources
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.env import SAGE_SRC sage: import os sage: filename = os.path.join(SAGE_SRC,'sage','rings','integer.pyx') sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS.basename 'sage.rings.integer'
-
create_doctests
(namespace)¶ Return a list of doctests for this file.
INPUT:
namespace
– a dictionary orsage.doctest.util.RecordingDict
.
OUTPUT:
doctests
– a list of doctests defined in this file.extras
– a dictionary
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.env import SAGE_SRC sage: import os sage: filename = os.path.join(SAGE_SRC,'sage','doctest','sources.py') sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: doctests, extras = FDS.create_doctests(globals()) sage: len(doctests) 41 sage: extras['tab'] False
We give a self referential example:
sage: doctests[18].name 'sage.doctest.sources.FileDocTestSource.create_doctests' sage: doctests[18].examples[10].source u'doctests[Integer(18)].examples[Integer(10)].source\n'
-
in_lib
()¶ Whether this file is part of a package (i.e. is in a directory containing an
__init__.py
file).Such files aren’t loaded before running tests.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.env import SAGE_SRC sage: import os sage: filename = os.path.join(SAGE_SRC, 'sage', 'rings', 'integer.pyx') sage: FDS = FileDocTestSource(filename, DocTestDefaults()) sage: FDS.in_lib True sage: filename = os.path.join(SAGE_SRC, 'sage', 'doctest', 'tests', 'abort.rst') sage: FDS = FileDocTestSource(filename, DocTestDefaults()) sage: FDS.in_lib False
You can override the default:
sage: FDS = FileDocTestSource("hello_world.py",DocTestDefaults()) sage: FDS.in_lib False sage: FDS = FileDocTestSource("hello_world.py",DocTestDefaults(force_lib=True)) sage: FDS.in_lib True
-
printpath
()¶ Whether the path is printed absolutely or relatively depends on an option.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.env import SAGE_SRC sage: import os sage: root = os.path.realpath(os.path.join(SAGE_SRC,'sage')) sage: filename = os.path.join(root,'doctest','sources.py') sage: cwd = os.getcwd() sage: os.chdir(root) sage: FDS = FileDocTestSource(filename,DocTestDefaults(randorder=0,abspath=False)) sage: FDS.printpath 'doctest/sources.py' sage: FDS = FileDocTestSource(filename,DocTestDefaults(randorder=0,abspath=True)) sage: FDS.printpath '.../sage/doctest/sources.py' sage: os.chdir(cwd)
-
class
sage.doctest.sources.
PythonSource
¶ Bases:
sage.doctest.sources.SourceLanguage
This class defines the functions needed for the extraction of doctests from python sources.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.env import SAGE_SRC sage: import os sage: filename = os.path.join(SAGE_SRC,'sage','doctest','sources.py') sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: type(FDS) <class 'sage.doctest.sources.PythonFileSource'>
-
ending_docstring
(line)¶ Determines whether the input line ends a docstring.
INPUT:
line
– a string, one line of an input file.
OUTPUT:
an object that, when evaluated in a boolean context, gives True or False depending on whether the input line marks the end of a docstring.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.doctest.util import NestedName sage: from sage.env import SAGE_SRC sage: import os sage: filename = os.path.join(SAGE_SRC,'sage','doctest','sources.py') sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS._init() sage: FDS.quotetype = "'''" sage: FDS.ending_docstring("'''") <...Match object...> sage: FDS.ending_docstring('\"\"\"')
-
starting_docstring
(line)¶ Determines whether the input line starts a docstring.
If the input line does start a docstring (a triple quote), then this function updates
self.qualified_name
.INPUT:
line
– a string, one line of an input file
OUTPUT:
either None or a Match object.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.doctest.util import NestedName sage: from sage.env import SAGE_SRC sage: import os sage: filename = os.path.join(SAGE_SRC,'sage','doctest','sources.py') sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS._init() sage: FDS.starting_docstring("r'''") <...Match object...> sage: FDS.ending_docstring("'''") <...Match object...> sage: FDS.qualified_name = NestedName(FDS.basename) sage: FDS.starting_docstring("class MyClass(object):") sage: FDS.starting_docstring(" def hello_world(self):") sage: FDS.starting_docstring(" '''") <...Match object...> sage: FDS.qualified_name sage.doctest.sources.MyClass.hello_world sage: FDS.ending_docstring(" '''") <...Match object...> sage: FDS.starting_docstring("class NewClass(object):") sage: FDS.starting_docstring(" '''") <...Match object...> sage: FDS.ending_docstring(" '''") <...Match object...> sage: FDS.qualified_name sage.doctest.sources.NewClass sage: FDS.starting_docstring("print(") sage: FDS.starting_docstring(" '''Not a docstring") sage: FDS.starting_docstring(" ''')") sage: FDS.starting_docstring("def foo():") sage: FDS.starting_docstring(" '''This is a docstring'''") <...Match object...>
-
-
class
sage.doctest.sources.
RestSource
¶ Bases:
sage.doctest.sources.SourceLanguage
This class defines the functions needed for the extraction of doctests from ReST sources.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: filename = "sage_doc.rst" sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: type(FDS) <class 'sage.doctest.sources.RestFileSource'>
-
ending_docstring
(line)¶ When the indentation level drops below the initial level the block ends.
INPUT:
line
– a string, one line of an input file
OUTPUT:
a boolean, whether the verbatim block is ending.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: filename = "sage_doc.rst" sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS._init() sage: FDS.starting_docstring("Hello world::") True sage: FDS.ending_docstring(" sage: 2 + 2") False sage: FDS.ending_docstring(" 4") False sage: FDS.ending_docstring("We are now done") True
-
parse_docstring
(docstring, namespace, start)¶ Return a list of doctest defined in this docstring.
Code blocks in a REST file can contain python functions with their own docstrings in addition to in-line doctests. We want to include the tests from these inner docstrings, but Python’s doctesting module has a problem if we just pass on the whole block, since it expects to get just a docstring, not the Python code as well.
Our solution is to create a new doctest source from this code block and append the doctests created from that source. We then replace the occurrences of “sage:” and “>>>” occurring inside a triple quote with “safe:” so that the doctest module doesn’t treat them as tests.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.doctest.parsing import SageDocTestParser sage: from sage.doctest.util import NestedName sage: filename = "sage_doc.rst" sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS.parser = SageDocTestParser(set(['sage'])) sage: FDS.qualified_name = NestedName('sage_doc') sage: s = "Some text::\n\n def example_python_function(a, \ ....: b):\n '''\n Brief description \ ....: of function.\n\n EXAMPLES::\n\n \ ....: sage: test1()\n sage: test2()\n \ ....: '''\n return a + b\n\n sage: test3()\n\nMore \ ....: ReST documentation." sage: tests = FDS.parse_docstring(s, {}, 100) sage: len(tests) 2 sage: for ex in tests[0].examples: ....: print(ex.sage_source) test3() sage: for ex in tests[1].examples: ....: print(ex.sage_source) test1() test2() sig_on_count() # check sig_on/off pairings (virtual doctest)
-
starting_docstring
(line)¶ A line ending with a double colon starts a verbatim block in a ReST file, as does a line containing
.. CODE-BLOCK:: language
.This function also determines whether the docstring block should be joined with the previous one, or should be skipped.
INPUT:
line
– a string, one line of an input file
OUTPUT:
either None or a Match object.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: filename = "sage_doc.rst" sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS._init() sage: FDS.starting_docstring("Hello world::") True sage: FDS.ending_docstring(" sage: 2 + 2") False sage: FDS.ending_docstring(" 4") False sage: FDS.ending_docstring("We are now done") True sage: FDS.starting_docstring(".. link") sage: FDS.starting_docstring("::") True sage: FDS.linking True
-
-
class
sage.doctest.sources.
SourceLanguage
¶ Bases:
object
An abstract class for functions that depend on the programming language of a doctest source.
Currently supported languages include Python, ReST and LaTeX.
-
parse_docstring
(docstring, namespace, start)¶ Return a list of doctest defined in this docstring.
This function is called by
DocTestSource._process_doc()
. The default implementation, defined here, is to use thesage.doctest.parsing.SageDocTestParser
attached to this source to get doctests from the docstring.INPUT:
docstring
– a string containing documentation and tests.namespace
– a dictionary orsage.doctest.util.RecordingDict
.start
– an integer, one less than the starting line number
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: from sage.doctest.parsing import SageDocTestParser sage: from sage.doctest.util import NestedName sage: from sage.env import SAGE_SRC sage: import os sage: filename = os.path.join(SAGE_SRC,'sage','doctest','util.py') sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: doctests, _ = FDS.create_doctests({}) sage: for dt in doctests: ....: FDS.qualified_name = dt.name ....: dt.examples = dt.examples[:-1] # strip off the sig_on() test ....: assert(FDS.parse_docstring(dt.docstring,{},dt.lineno-1)[0] == dt)
-
-
class
sage.doctest.sources.
StringDocTestSource
(basename, source, options, printpath, lineno_shift=0)¶ Bases:
sage.doctest.sources.DocTestSource
This class creates doctests from a string.
INPUT:
basename
– string such as ‘sage.doctests.sources’, going into the names of created doctests and examples.source
– a string, giving the source code to be parsed for doctests.options
– asage.doctest.control.DocTestDefaults
or equivalent.printpath
– a string, to be used in place of a filename when doctest failures are displayed.lineno_shift
– an integer (default: 0) by which to shift the line numbers of all doctests defined in this string.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import StringDocTestSource, PythonSource sage: from sage.structure.dynamic_class import dynamic_class sage: s = "'''\n sage: 2 + 2\n 4\n'''" sage: PythonStringSource = dynamic_class('PythonStringSource',(StringDocTestSource, PythonSource)) sage: PSS = PythonStringSource('<runtime>', s, DocTestDefaults(), 'runtime') sage: dt, extras = PSS.create_doctests({}) sage: len(dt) 1 sage: extras['tab'] [] sage: extras['line_number'] False sage: s = "'''\n\tsage: 2 + 2\n\t4\n'''" sage: PSS = PythonStringSource('<runtime>', s, DocTestDefaults(), 'runtime') sage: dt, extras = PSS.create_doctests({}) sage: extras['tab'] ['2', '3'] sage: s = "'''\n sage: import warnings; warnings.warn('foo')\n doctest:1: UserWarning: foo \n'''" sage: PSS = PythonStringSource('<runtime>', s, DocTestDefaults(), 'runtime') sage: dt, extras = PSS.create_doctests({}) sage: extras['line_number'] True
-
create_doctests
(namespace)¶ Creates doctests from this string.
INPUT:
namespace
– a dictionary orsage.doctest.util.RecordingDict
.
OUTPUT:
doctests
– a list of doctests defined by this stringtab_locations
– either False or a list of linenumbers on which tabs appear.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import StringDocTestSource, PythonSource sage: from sage.structure.dynamic_class import dynamic_class sage: s = "'''\n sage: 2 + 2\n 4\n'''" sage: PythonStringSource = dynamic_class('PythonStringSource',(StringDocTestSource, PythonSource)) sage: PSS = PythonStringSource('<runtime>', s, DocTestDefaults(), 'runtime') sage: dt, tabs = PSS.create_doctests({}) sage: for t in dt: ....: print("{} {}".format(t.name, t.examples[0].sage_source)) <runtime> 2 + 2
-
class
sage.doctest.sources.
TexSource
¶ Bases:
sage.doctest.sources.SourceLanguage
This class defines the functions needed for the extraction of doctests from a LaTeX source.
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: filename = "sage_paper.tex" sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: type(FDS) <class 'sage.doctest.sources.TexFileSource'>
-
ending_docstring
(line, check_skip=True)¶ Determines whether the input line ends a docstring.
Docstring blocks in tex files are defined by verbatim or lstlisting environments, and can be linked together by adding %link immediately after the end{verbatim} or end{lstlisting}.
Within a verbatim (or lstlisting) block, you can tell Sage not to process the rest of the block by including a %skip line.
INPUT:
line
– a string, one line of an input filecheck_skip
– boolean (default True), used internally in starting_docstring.
OUTPUT:
a boolean giving whether the input line marks the end of a docstring (verbatim block).
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: filename = "sage_paper.tex" sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS._init() sage: FDS.ending_docstring(r"\end{verbatim}") True sage: FDS.ending_docstring(r"\end{lstlisting}") True sage: FDS.linking False
Use %link to link with the next verbatim block:
sage: FDS.ending_docstring(r"\end{verbatim}%link") True sage: FDS.linking True
%skip also ends a docstring block:
sage: FDS.ending_docstring("%skip") True
-
starting_docstring
(line)¶ Determines whether the input line starts a docstring.
Docstring blocks in tex files are defined by verbatim or lstlisting environments, and can be linked together by adding %link immediately after the end{verbatim} or end{lstlisting}.
Within a verbatim (or lstlisting) block, you can tell Sage not to process the rest of the block by including a %skip line.
INPUT:
line
– a string, one line of an input file
OUTPUT:
a boolean giving whether the input line marks the start of a docstring (verbatim block).
EXAMPLES:
sage: from sage.doctest.control import DocTestDefaults sage: from sage.doctest.sources import FileDocTestSource sage: filename = "sage_paper.tex" sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: FDS._init()
We start docstrings with begin{verbatim} or begin{lstlisting}:
sage: FDS.starting_docstring(r"\begin{verbatim}") True sage: FDS.starting_docstring(r"\begin{lstlisting}") True sage: FDS.skipping False sage: FDS.ending_docstring("sage: 2+2") False sage: FDS.ending_docstring("4") False
To start ignoring the rest of the verbatim block, use %skip:
sage: FDS.ending_docstring("%skip") True sage: FDS.skipping True sage: FDS.starting_docstring("sage: raise RuntimeError") False
You can even pretend to start another verbatim block while skipping:
sage: FDS.starting_docstring(r"\begin{verbatim}") False sage: FDS.skipping True
To stop skipping end the verbatim block:
sage: FDS.starting_docstring(r"\end{verbatim} %link") False sage: FDS.skipping False
Linking works even when the block was ended while skipping:
sage: FDS.linking True sage: FDS.starting_docstring(r"\begin{verbatim}") True
-
-
sage.doctest.sources.
get_basename
(path)¶ This function returns the basename of the given path, e.g. sage.doctest.sources or doc.ru.tutorial.tour_advanced
EXAMPLES:
sage: from sage.doctest.sources import get_basename sage: from sage.env import SAGE_SRC sage: import os sage: get_basename(os.path.join(SAGE_SRC,'sage','doctest','sources.py')) 'sage.doctest.sources'