Skip to content

Commit f74f7e9

Browse files
committed
2 parents 7f2bfd1 + 5e04a85 commit f74f7e9

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

src/sage/doctest/control.py

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
except ImportError:
5454
pass
5555

56+
from sage.features.sagemath import sage_optional_tags
57+
auto_optional_tags.update(sage_optional_tags())
58+
5659
class DocTestDefaults(SageObject):
5760
"""
5861
This class is used for doctesting the Sage doctest module.

src/sage/doctest/parsing.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from .external import available_software
3535

3636
float_regex = re.compile(r'\s*([+-]?\s*((\d*\.?\d+)|(\d+\.?))([eE][+-]?\d+)?)')
37-
optional_regex = re.compile(r'(arb216|arb218|py2|py3|long time|not implemented|not tested|known bug)|([^ a-z]\s*optional\s*[:-]*((\s|\w)*))')
37+
optional_regex = re.compile(r'(arb216|arb218|py2|py3|long time|not implemented|not tested|known bug)|([^ a-z]\s*optional\s*[:-]*((\s|\w|[.])*))')
3838
# Version 4.65 of glpk prints the warning "Long-step dual simplex will
3939
# be used" frequently. When Sage uses a system installation of glpk
4040
# which has not been patched, we need to ignore that message.
@@ -316,6 +316,8 @@ def parse_optional_tags(string):
316316
{''}
317317
sage: sorted(list(parse_optional_tags("sage: #optional -- foo bar, baz")))
318318
['bar', 'foo']
319+
sage: parse_optional_tags("sage: #optional -- foo.bar, baz")
320+
{'foo.bar'}
319321
sage: sorted(list(parse_optional_tags(" sage: factor(10^(10^10) + 1) # LoNg TiME, NoT TeSTED; OptioNAL -- P4cka9e")))
320322
['long time', 'not tested', 'p4cka9e']
321323
sage: parse_optional_tags(" sage: raise RuntimeError # known bug")

src/sage/features/sagemath.py

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
r"""
2+
Check for SageMath Python modules
3+
"""
4+
from . import PythonModule
5+
6+
7+
class sage__combinat(PythonModule):
8+
9+
def __init__(self):
10+
# sage.combinat will be a namespace package.
11+
# Testing whether sage.combinat itself can be imported is meaningless.
12+
# Hence, we test a Python module within the package.
13+
PythonModule.__init__(self, 'sage.combinat.combinations')
14+
15+
16+
class sage__graphs(PythonModule):
17+
18+
def __init__(self):
19+
PythonModule.__init__(self, 'sage.graphs.graph')
20+
21+
22+
class sage__rings__real_double(PythonModule):
23+
24+
def __init__(self):
25+
PythonModule.__init__(self, 'sage.rings.real_double')
26+
27+
28+
class sage__symbolic(PythonModule):
29+
30+
def __init__(self):
31+
PythonModule.__init__(self, 'sage.symbolic.expression', spkg="sagemath_symbolics")
32+
33+
34+
def sage_optional_tags():
35+
"""
36+
Return tags for conditionalizing doctests.
37+
38+
These tags are named after Python packages/modules (e.g., :mod:`~sage.symbolic`),
39+
not distribution packages (``sagemath-symbolics``).
40+
41+
This is motivated by a separation of concerns: The author of a module that depends
42+
on some functionality provided by a Python module usually already knows the
43+
name of the Python module, so we do not want to force the author to also
44+
know about the distribution package that provides the Python module.
45+
46+
Instead, we associate distribution packages to Python modules in
47+
:mod:`sage.features.sagemath` via the ``spkg`` parameter of :class:`PythonModule``.
48+
"""
49+
if sage__combinat().is_present():
50+
yield 'sage.combinat'
51+
if sage__graphs().is_present():
52+
yield 'sage.graphs'
53+
if sage__rings__real_double().is_present():
54+
yield 'sage.rings.real_double'
55+
if sage__symbolic().is_present():
56+
yield 'sage.symbolic'

0 commit comments

Comments
 (0)