Features for testing the presence of Python modules in the Sage library#
All of these features are present in a monolithic installation of the Sage library, such as the one made by the SageMath distribution.
The features are defined for the purpose of separately testing modularized distributions such as sagemath-categories and sagemath-repl.
Often, doctests in a module of the Sage library illustrate the
interplay with a range of different objects; this is a form of integration testing.
These objects may come from modules shipped in
other distributions. For example, sage.structure.element
(shipped by sagemath-objects,
one of the most fundamental distributions) contains the
doctest:
sage: G = SymmetricGroup(4) # needs sage.groups
sage: g = G([2, 3, 4, 1]) # needs sage.groups
sage: g.powers(4) # needs sage.groups
[(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
>>> from sage.all import *
>>> G = SymmetricGroup(Integer(4)) # needs sage.groups
>>> g = G([Integer(2), Integer(3), Integer(4), Integer(1)]) # needs sage.groups
>>> g.powers(Integer(4)) # needs sage.groups
[(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
This test cannot pass when the distribution sagemath-objects
is tested separately (in a virtual environment): In this situation,
SymmetricGroup
is not defined anywhere (and thus not present
in the top-level namespace).
Hence, we conditionalize this doctest on the presence of the feature
sage.groups
.
- class sage.features.sagemath.SAGE_SRC(*args, **kwds)[source]#
Bases:
StaticFile
A
Feature
which describes the presence of the monolithic source tree of the Sage library.
- sage.features.sagemath.all_features()[source]#
Return features corresponding to parts of the Sage library.
These features are named after Python packages/modules (e.g.,
sage.symbolic
), not distribution packages (sagemath-symbolics).This design is motivated by a separation of concerns: The author of a module that depends on some functionality provided by a Python module usually already knows the name of the Python module, so we do not want to force the author to also know about the distribution package that provides the Python module.
Instead, we associate distribution packages to Python modules in
sage.features.sagemath
via thespkg
parameter ofFeature
.EXAMPLES:
sage: from sage.features.sagemath import all_features sage: list(all_features()) [...Feature('sage.combinat'), ...]
>>> from sage.all import * >>> from sage.features.sagemath import all_features >>> list(all_features()) [...Feature('sage.combinat'), ...]
- class sage.features.sagemath.sage__combinat(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.combinat
.EXAMPLES:
Python modules that provide elementary combinatorial objects such as
sage.combinat.subset
,sage.combinat.composition
,sage.combinat.permutation
are always available; there is no need for an# optional/needs
tag:sage: Permutation([1,2,3]).is_even() True sage: Permutation([6,1,4,5,2,3]).bruhat_inversions() [[0, 1], [0, 2], [0, 3], [2, 4], [2, 5], [3, 4], [3, 5]]
>>> from sage.all import * >>> Permutation([Integer(1),Integer(2),Integer(3)]).is_even() True >>> Permutation([Integer(6),Integer(1),Integer(4),Integer(5),Integer(2),Integer(3)]).bruhat_inversions() [[0, 1], [0, 2], [0, 3], [2, 4], [2, 5], [3, 4], [3, 5]]
Use
# needs sage.combinat
for doctests that use any other Python modules fromsage.combinat
, for examplesage.combinat.tableau_tuple
:sage: TableauTuple([[[7,8,9]],[],[[1,2,3],[4,5],[6]]]).shape() # needs sage.combinat ([3], [], [3, 2, 1])
>>> from sage.all import * >>> TableauTuple([[[Integer(7),Integer(8),Integer(9)]],[],[[Integer(1),Integer(2),Integer(3)],[Integer(4),Integer(5)],[Integer(6)]]]).shape() # needs sage.combinat ([3], [], [3, 2, 1])
Doctests that use Python modules from
sage.combinat
that involve trees, graphs, hypergraphs, posets, quivers, combinatorial designs, finite state machines etc. should be marked# needs sage.combinat sage.graphs
:sage: L = Poset({0: [1], 1: [2], 2:[3], 3:[4]}) # needs sage.combinat sage.graphs sage: L.is_chain() # needs sage.combinat sage.graphs True
>>> from sage.all import * >>> L = Poset({Integer(0): [Integer(1)], Integer(1): [Integer(2)], Integer(2):[Integer(3)], Integer(3):[Integer(4)]}) # needs sage.combinat sage.graphs >>> L.is_chain() # needs sage.combinat sage.graphs True
Doctests that use combinatorial modules/algebras, or root systems should use the tag
# needs sage.combinat sage.modules
:sage: # needs sage.combinat sage.modules sage: A = SchurAlgebra(QQ, 2, 3) sage: a = A.an_element(); a 2*S((1, 1, 1), (1, 1, 1)) + 2*S((1, 1, 1), (1, 1, 2)) + 3*S((1, 1, 1), (1, 2, 2)) sage: L = RootSystem(['A',3,1]).root_lattice() sage: PIR = L.positive_imaginary_roots(); PIR Positive imaginary roots of type ['A', 3, 1]
>>> from sage.all import * >>> # needs sage.combinat sage.modules >>> A = SchurAlgebra(QQ, Integer(2), Integer(3)) >>> a = A.an_element(); a 2*S((1, 1, 1), (1, 1, 1)) + 2*S((1, 1, 1), (1, 1, 2)) + 3*S((1, 1, 1), (1, 2, 2)) >>> L = RootSystem(['A',Integer(3),Integer(1)]).root_lattice() >>> PIR = L.positive_imaginary_roots(); PIR Positive imaginary roots of type ['A', 3, 1]
Doctests that use lattices, semilattices, or Dynkin diagrams should use the tag
# needs sage.combinat sage.graphs sage.modules
:sage: L = LatticePoset({0: [1,2], 1: [3], 2: [3,4], 3: [5], 4: [5]}) # needs sage.combinat sage.graphs sage.modules sage: L.meet_irreducibles() # needs sage.combinat sage.graphs sage.modules [1, 3, 4]
>>> from sage.all import * >>> L = LatticePoset({Integer(0): [Integer(1),Integer(2)], Integer(1): [Integer(3)], Integer(2): [Integer(3),Integer(4)], Integer(3): [Integer(5)], Integer(4): [Integer(5)]}) # needs sage.combinat sage.graphs sage.modules >>> L.meet_irreducibles() # needs sage.combinat sage.graphs sage.modules [1, 3, 4]
- class sage.features.sagemath.sage__geometry__polyhedron(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.geometry.polyhedron
.EXAMPLES:
Doctests that use polyhedra, cones, geometric complexes, triangulations, etc. should use the tag
# needs sage.geometry.polyhedron
:sage: co = polytopes.truncated_tetrahedron() # needs sage.geometry.polyhedron sage: co.volume() # needs sage.geometry.polyhedron 184/3
>>> from sage.all import * >>> co = polytopes.truncated_tetrahedron() # needs sage.geometry.polyhedron >>> co.volume() # needs sage.geometry.polyhedron 184/3
Some constructions of polyhedra require additional tags:
sage: # needs sage.combinat sage.geometry.polyhedron sage.rings.number_field sage: perm_a3_reg_nf = polytopes.generalized_permutahedron( ....: ['A',3], regular=True, backend='number_field'); perm_a3_reg_nf A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices
>>> from sage.all import * >>> # needs sage.combinat sage.geometry.polyhedron sage.rings.number_field >>> perm_a3_reg_nf = polytopes.generalized_permutahedron( ... ['A',Integer(3)], regular=True, backend='number_field'); perm_a3_reg_nf A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices
- class sage.features.sagemath.sage__graphs(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.graphs
.EXAMPLES:
Doctests that use anything from
sage.graphs
(Graph
,DiGraph
, …) should be marked# needs sage.graphs
. The same applies to any doctest that uses aPoset
, cluster algebra quiver, finite state machines, abelian sandpiles, or Dynkin diagrams:sage: g = graphs.PetersenGraph() # needs sage.graphs sage: r, s = g.is_weakly_chordal(certificate=True); r # needs sage.graphs False
>>> from sage.all import * >>> g = graphs.PetersenGraph() # needs sage.graphs >>> r, s = g.is_weakly_chordal(certificate=True); r # needs sage.graphs False
Also any use of tree classes defined in
sage.combinat
(BinaryTree
,RootedTree
, …) in doctests should be marked the same.By way of generalization, any use of
SimplicialComplex
or other abstract complexes fromsage.topology
, hypergraphs, and combinatorial designs, should be marked# needs sage.graphs
as well:sage: X = SimplicialComplex([[0,1,2], [1,2,3]]) # needs sage.graphs sage: X.link(Simplex([0])) # needs sage.graphs Simplicial complex with vertex set (1, 2) and facets {(1, 2)} sage: IncidenceStructure([[1,2,3],[1,4]]).degrees(2) # needs sage.graphs {(1, 2): 1, (1, 3): 1, (1, 4): 1, (2, 3): 1, (2, 4): 0, (3, 4): 0}
>>> from sage.all import * >>> X = SimplicialComplex([[Integer(0),Integer(1),Integer(2)], [Integer(1),Integer(2),Integer(3)]]) # needs sage.graphs >>> X.link(Simplex([Integer(0)])) # needs sage.graphs Simplicial complex with vertex set (1, 2) and facets {(1, 2)} >>> IncidenceStructure([[Integer(1),Integer(2),Integer(3)],[Integer(1),Integer(4)]]).degrees(Integer(2)) # needs sage.graphs {(1, 2): 1, (1, 3): 1, (1, 4): 1, (2, 3): 1, (2, 4): 0, (3, 4): 0}
On the other hand, matroids are not implemented as posets in Sage but are instead closely tied to linear algebra over fields; hence use
# needs sage.modules
instead:sage: # needs sage.modules sage: M = Matroid(Matrix(QQ, [[1, 0, 0, 0, 1, 1, 1], ....: [0, 1, 0, 1, 0, 1, 1], ....: [0, 0, 1, 1, 1, 0, 1]])) sage: N = (M / [2]).delete([3, 4]) sage: sorted(N.groundset()) [0, 1, 5, 6]
>>> from sage.all import * >>> # needs sage.modules >>> M = Matroid(Matrix(QQ, [[Integer(1), Integer(0), Integer(0), Integer(0), Integer(1), Integer(1), Integer(1)], ... [Integer(0), Integer(1), Integer(0), Integer(1), Integer(0), Integer(1), Integer(1)], ... [Integer(0), Integer(0), Integer(1), Integer(1), Integer(1), Integer(0), Integer(1)]])) >>> N = (M / [Integer(2)]).delete([Integer(3), Integer(4)]) >>> sorted(N.groundset()) [0, 1, 5, 6]
However, many constructions (and some methods) of matroids do involve graphs:
sage: # needs sage.modules sage: W = matroids.Wheel(3) # despite the name, not created via graphs sage: W.is_isomorphic(N) # goes through a graph isomorphism test # needs sage.graphs False sage: K4 = matroids.CompleteGraphic(4) # this one is created via graphs # needs sage.graphs sage: K4.is_isomorphic(W) # needs sage.graphs True
>>> from sage.all import * >>> # needs sage.modules >>> W = matroids.Wheel(Integer(3)) # despite the name, not created via graphs >>> W.is_isomorphic(N) # goes through a graph isomorphism test # needs sage.graphs False >>> K4 = matroids.CompleteGraphic(Integer(4)) # this one is created via graphs # needs sage.graphs >>> K4.is_isomorphic(W) # needs sage.graphs True
- class sage.features.sagemath.sage__groups(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.groups
.EXAMPLES:
Permutations and sets of permutations are always available, but permutation groups are implemented in Sage using the GAP system and require the tag
# needs sage.groups
:sage: p = Permutation([2,1,4,3]) sage: p.to_permutation_group_element() # needs sage.groups (1,2)(3,4)
>>> from sage.all import * >>> p = Permutation([Integer(2),Integer(1),Integer(4),Integer(3)]) >>> p.to_permutation_group_element() # needs sage.groups (1,2)(3,4)
- class sage.features.sagemath.sage__libs__braiding(*args, **kwds)[source]#
Bases:
PythonModule
A
Feature
describing the presence ofsage.libs.braiding
.EXAMPLES:
sage: from sage.features.sagemath import sage__libs__braiding sage: sage__libs__braiding().is_present() # needs sage.libs.braiding FeatureTestResult('sage.libs.braiding', True)
>>> from sage.all import * >>> from sage.features.sagemath import sage__libs__braiding >>> sage__libs__braiding().is_present() # needs sage.libs.braiding FeatureTestResult('sage.libs.braiding', True)
- class sage.features.sagemath.sage__libs__ecl(*args, **kwds)[source]#
Bases:
PythonModule
A
Feature
describing the presence ofsage.libs.ecl
.EXAMPLES:
sage: from sage.features.sagemath import sage__libs__ecl sage: sage__libs__ecl().is_present() # optional - sage.libs.ecl FeatureTestResult('sage.libs.ecl', True)
>>> from sage.all import * >>> from sage.features.sagemath import sage__libs__ecl >>> sage__libs__ecl().is_present() # optional - sage.libs.ecl FeatureTestResult('sage.libs.ecl', True)
- class sage.features.sagemath.sage__libs__flint(*args, **kwds)[source]#
Bases:
JoinFeature
A
sage.features.Feature
describing the presence ofsage.libs.flint
and other modules depending on FLINT.In addition to the modularization purposes that this tag serves, it also provides attribution to the upstream project.
- class sage.features.sagemath.sage__libs__gap(*args, **kwds)[source]#
Bases:
JoinFeature
A
sage.features.Feature
describing the presence ofsage.libs.gap
(the library interface to GAP) andsage.interfaces.gap
(the pexpect interface to GAP). By design, we do not distinguish between these two, in order to facilitate the conversion of code from the pexpect interface to the library interface.See also
Features for GAP packages
- class sage.features.sagemath.sage__libs__linbox(*args, **kwds)[source]#
Bases:
JoinFeature
A
sage.features.Feature
describing the presence ofsage.libs.linbox
and other modules depending on Givaro, FFLAS-FFPACK, LinBox.In addition to the modularization purposes that this tag serves, it also provides attribution to the upstream project.
- class sage.features.sagemath.sage__libs__m4ri(*args, **kwds)[source]#
Bases:
JoinFeature
A
sage.features.Feature
describing the presence of Cython modules depending on the M4RI and/or M4RIe libraries.In addition to the modularization purposes that this tag serves, it also provides attribution to the upstream project.
- class sage.features.sagemath.sage__libs__ntl(*args, **kwds)[source]#
Bases:
JoinFeature
A
sage.features.Feature
describing the presence ofsage.libs.ntl
and other modules depending on NTL.In addition to the modularization purposes that this tag serves, it also provides attribution to the upstream project.
- class sage.features.sagemath.sage__libs__pari(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.libs.pari
.SageMath uses the PARI library (via cypari2) for numerous purposes. Doctests that involves such features should be marked
# needs sage.libs.pari
.In addition to the modularization purposes that this tag serves, it also provides attribution to the upstream project.
EXAMPLES:
sage: R.<a> = QQ[] sage: S.<x> = R[] sage: f = x^2 + a; g = x^3 + a sage: r = f.resultant(g); r # needs sage.libs.pari a^3 + a^2
>>> from sage.all import * >>> R = QQ['a']; (a,) = R._first_ngens(1) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(2) + a; g = x**Integer(3) + a >>> r = f.resultant(g); r # needs sage.libs.pari a^3 + a^2
- class sage.features.sagemath.sage__libs__singular(*args, **kwds)[source]#
Bases:
JoinFeature
A
sage.features.Feature
describing the presence ofsage.libs.singular
(the library interface to Singular) andsage.interfaces.singular
(the pexpect interface to Singular). By design, we do not distinguish between these two, in order to facilitate the conversion of code from the pexpect interface to the library interface.See also
Feature singular
- class sage.features.sagemath.sage__modular(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.modular
.
- class sage.features.sagemath.sage__modules(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.modules
.EXAMPLES:
All uses of implementations of vector spaces / free modules in SageMath, whether
sage.modules.free_module.FreeModule
,sage.combinat.free_module.CombinatorialFreeModule
,sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule
, or additive abelian groups, should be marked# needs sage.modules
.The same holds for matrices, tensors, algebras, quadratic forms, point lattices, root systems, matrix/affine/Weyl/Coxeter groups, matroids, and ring derivations.
Likewise, all uses of
sage.coding
,sage.crypto
, andsage.homology
in doctests should be marked# needs sage.modules
.
- class sage.features.sagemath.sage__numerical__mip(*args, **kwds)[source]#
Bases:
PythonModule
A
Feature
describing the presence ofsage.numerical.mip
.
- class sage.features.sagemath.sage__plot(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.plot
.
- class sage.features.sagemath.sage__rings__complex_double(*args, **kwds)[source]#
Bases:
PythonModule
A
Feature
describing the presence ofsage.rings.complex_double
.
- class sage.features.sagemath.sage__rings__finite_rings(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.rings.finite_rings
; specifically, the element implementations using the PARI library.
- class sage.features.sagemath.sage__rings__function_field(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.rings.function_field
.EXAMPLES:
Rational function fields are always available:
sage: K.<x> = FunctionField(QQ) sage: K.maximal_order() Maximal order of Rational function field in x over Rational Field
>>> from sage.all import * >>> K = FunctionField(QQ, names=('x',)); (x,) = K._first_ngens(1) >>> K.maximal_order() Maximal order of Rational function field in x over Rational Field
Use the tag
# needs sage.rings.function_field
whenever extensions of function fields (by adjoining a root of a univariate polynomial) come into play:sage: R.<y> = K[] sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L # needs sage.rings.function_field Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
>>> from sage.all import * >>> R = K['y']; (y,) = R._first_ngens(1) >>> L = K.extension(y**Integer(5) - (x**Integer(3) + Integer(2)*x*y + Integer(1)/x), names=('y',)); (y,) = L._first_ngens(1); L # needs sage.rings.function_field Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
Such extensions of function fields are implemented using Gröbner bases of polynomial rings; Sage makes essential use of the Singular system for this. (It is not necessary to use the tag
# needs sage.libs.singular
; it is implied by# needs sage.rings.function_field
.)
- class sage.features.sagemath.sage__rings__number_field(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.rings.number_field
.Number fields are implemented in Sage using a complicated mixture of various libraries, including FLINT, GAP, MPFI, NTL, and PARI.
EXAMPLES:
Rational numbers are, of course, always available:
sage: QQ in NumberFields() True
>>> from sage.all import * >>> QQ in NumberFields() True
Doctests that construct algebraic number fields should be marked
# needs sage.rings.number_field
:sage: # needs sage.rings.number_field sage: K.<cuberoot2> = NumberField(x^3 - 2) sage: L.<cuberoot3> = K.extension(x^3 - 3) sage: S.<sqrt2> = L.extension(x^2 - 2); S Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field sage: # needs sage.rings.number_field sage: K.<zeta> = CyclotomicField(15) sage: CC(zeta) 0.913545457642601 + 0.406736643075800*I
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = NumberField(x**Integer(3) - Integer(2), names=('cuberoot2',)); (cuberoot2,) = K._first_ngens(1) >>> L = K.extension(x**Integer(3) - Integer(3), names=('cuberoot3',)); (cuberoot3,) = L._first_ngens(1) >>> S = L.extension(x**Integer(2) - Integer(2), names=('sqrt2',)); (sqrt2,) = S._first_ngens(1); S Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field >>> # needs sage.rings.number_field >>> K = CyclotomicField(Integer(15), names=('zeta',)); (zeta,) = K._first_ngens(1) >>> CC(zeta) 0.913545457642601 + 0.406736643075800*I
Doctests that make use of the algebraic field
QQbar
or the algebraic real fieldAA
should be marked likewise:sage: # needs sage.rings.number_field sage: AA(-1)^(1/3) -1 sage: QQbar(-1)^(1/3) 0.500000000000000? + 0.866025403784439?*I
>>> from sage.all import * >>> # needs sage.rings.number_field >>> AA(-Integer(1))**(Integer(1)/Integer(3)) -1 >>> QQbar(-Integer(1))**(Integer(1)/Integer(3)) 0.500000000000000? + 0.866025403784439?*I
Use of the universal cyclotomic field should be marked
# needs sage.libs.gap sage.rings.number_field
.sage: # needs sage.libs.gap sage.rings.number_field sage: UCF = UniversalCyclotomicField(); UCF Universal Cyclotomic Field sage: E = UCF.gen sage: f = E(2) + E(3); f 2*E(3) + E(3)^2 sage: f.galois_conjugates() [2*E(3) + E(3)^2, E(3) + 2*E(3)^2]
- class sage.features.sagemath.sage__rings__padics(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.rings.padics
.
- class sage.features.sagemath.sage__rings__polynomial__pbori(*args, **kwds)[source]#
Bases:
JoinFeature
A
sage.features.Feature
describing the presence ofsage.rings.polynomial.pbori
.
- class sage.features.sagemath.sage__rings__real_double(*args, **kwds)[source]#
Bases:
PythonModule
A
Feature
describing the presence ofsage.rings.real_double
.EXAMPLES:
The Real Double Field is basically always available, and no
# optional/needs
tag is needed:sage: RDF.characteristic() 0
>>> from sage.all import * >>> RDF.characteristic() 0
The feature exists for use in doctests of Python modules that are shipped by the most fundamental distributions.
- class sage.features.sagemath.sage__rings__real_mpfr(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.rings.real_mpfr
.
- class sage.features.sagemath.sage__sat(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.sat
.
- class sage.features.sagemath.sage__schemes(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.schemes
.
- class sage.features.sagemath.sage__symbolic(*args, **kwds)[source]#
Bases:
JoinFeature
A
Feature
describing the presence ofsage.symbolic
.EXAMPLES:
The symbolics subsystem of Sage will be provided by the distribution sagemath-symbolics, in preparation at Issue #35095. If it is not installed, Sage will be able to provide installation advice:
sage: from sage.features.sagemath import sage__symbolic sage: print(sage__symbolic().resolution()) # optional - sage_spkg, not tested ...To install sagemath_symbolics...you can try to run... pip install sagemath-symbolics ...
>>> from sage.all import * >>> from sage.features.sagemath import sage__symbolic >>> print(sage__symbolic().resolution()) # optional - sage_spkg, not tested ...To install sagemath_symbolics...you can try to run... pip install sagemath-symbolics ...
- class sage.features.sagemath.sagemath_doc_html(*args, **kwds)[source]#
Bases:
StaticFile
A
Feature
which describes the presence of the documentation of the Sage library in HTML format.Developers often use
make build
instead ofmake
to avoid the long time it takes to compile the documentation. Although commands such asmake ptest
build the documentation before testing, other test commands such asmake ptestlong-nodoc
or./sage -t --all
do not.All doctests that refer to the built documentation need to be marked
# needs sagemath_doc_html
.