This module defines various classes for sources from which doctests originate, such as files, functions or database entries.
AUTHORS:
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
Bases: object
This class provides a common base class for different sources of doctests.
INPUT:
Bases: sage.doctest.sources.DocTestSource
This class creates doctests from a file.
INPUT:
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'
TESTS:
sage: TestSuite(FDS).run()
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'
Returns a list of doctests for this file.
INPUT:
OUTPUT:
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)
40
sage: extras['tab']
False
We give a self referential example:
sage: doctests[17].name
'sage.doctest.sources.FileDocTestSource.create_doctests'
sage: doctests[17].examples[10].source
'doctests[Integer(17)].examples[Integer(10)].source\n'
TESTS:
We check that we correctly process results that depend on 32 vs 64 bit architecture:
sage: import sys
sage: bitness = '64' if sys.maxsize > (1 << 32) else '32'
sage: n = -920390823904823094890238490238484; hash(n) > 0
False # 32-bit
True # 64-bit
sage: ex = doctests[17].examples[13]
sage: (bitness == '64' and ex.want == 'True \n') or (bitness == '32' and ex.want == 'False \n')
True
We check that lines starting with a # aren’t doctested:
#sage: raise RuntimeError
Whether this file should be considered part of the Sage library.
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
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
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)
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'>
Determines whether the input line ends a docstring.
INPUT:
OUTPUT:
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("'''")
<_sre.SRE_Match object at ...>
sage: FDS.ending_docstring('\"\"\"')
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:
OUTPUT:
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'''")
<_sre.SRE_Match object at ...>
sage: FDS.ending_docstring("'''")
<_sre.SRE_Match object at ...>
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(" '''")
<_sre.SRE_Match object at ...>
sage: FDS.qualified_name
sage.doctest.sources.MyClass.hello_world
sage: FDS.ending_docstring(" '''")
<_sre.SRE_Match object at ...>
sage: FDS.starting_docstring("class NewClass(object):")
sage: FDS.starting_docstring(" '''")
<_sre.SRE_Match object at ...>
sage: FDS.qualified_name
sage.doctest.sources.NewClass
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'>
When the indentation level drops below the initial level the block ends.
INPUT:
OUTPUT:
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
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(False, 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)
A line ending with a double quote starts a verbatim block in a ReST file.
This function also determines whether the docstring block should be joined with the previous one, or should be skipped.
INPUT:
OUTPUT:
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
An abstract class for functions that depend on the programming language of a doctest source.
Currently supported languages include Python, ReST and LaTeX.
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 the sage.doctest.parsing.SageDocTestParser attached to this source to get doctests from the docstring.
INPUT:
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)
Bases: sage.doctest.sources.DocTestSource
This class creates doctests from a string.
INPUT:
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
Creates doctests from this string.
INPUT:
OUTPUT:
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 t.name, t.examples[0].sage_source
<runtime> 2 + 2
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'>
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:
OUTPUT:
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
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:
OUTPUT:
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
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'