Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add style guide / reference for # optional - sage.... doctest tags, extend sage -t and sage -fixdoctests for modularization tasks #35749

Merged
merged 157 commits into from
Jul 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
157 commits
Select commit Hold shift + click to select a range
664c56c
src/sage/features/sagemath.py: Expand documentation on # optional - s…
mkoeppe Jun 9, 2023
d7ecd4d
src/doc/en/developer/coding_basics.rst: Add style guide for formattin…
mkoeppe Jun 9, 2023
e7173cd
src/sage/features/sagemath.py: Fix markup, expand examples
mkoeppe Jun 9, 2023
3aacb73
src/sage/features/sagemath.py: Add module-level doc
mkoeppe Jun 10, 2023
bfb9a52
Fix markup
mkoeppe Jun 10, 2023
4b69756
src/sage/features/sagemath.py: Expand on sage.graphs
mkoeppe Jun 10, 2023
d46fb19
Expand on sage.graphs, sage.modules
mkoeppe Jun 10, 2023
5dc088f
src/doc/en/developer/coding_basics.rst: Fix doctest output
mkoeppe Jun 10, 2023
1ad2776
Fix markup
mkoeppe Jun 10, 2023
eef016f
src/doc/en/developer/coding_basics.rst: Fix doctest
mkoeppe Jun 11, 2023
74b98cf
Merge branch 'develop' into feature_definitions
mkoeppe Jun 11, 2023
2440c0b
Add persistent optional tag
kwankyu Jun 14, 2023
647380c
Fix a typo
kwankyu Jun 16, 2023
2bd55ab
Allow needs for optional
kwankyu Jun 17, 2023
9485097
Block ends with a blank line
kwankyu Jun 17, 2023
6dd4afd
Use needs in the doctest
kwankyu Jun 17, 2023
f7152bd
Remove redundant backslash
kwankyu Jun 17, 2023
87f5e15
Use formal needs:
kwankyu Jun 17, 2023
bdc4232
Revert to needs revising the doctest
kwankyu Jun 17, 2023
0596705
Merge tag '10.1.beta4' into feature_definitions
mkoeppe Jun 23, 2023
131e1f9
sage -fixdoctests: New options --venv, --environment, --full-tracebac…
mkoeppe Jun 23, 2023
d9d1900
sage -fixdoctests: Add option --keep-both
mkoeppe Jun 24, 2023
dda8c28
sage -fixdoctests: Handle why/explain annotation
mkoeppe Jun 24, 2023
e9f38c0
sage -fixdoctests: Shorter annotations for top-level NameError
mkoeppe Jun 24, 2023
9541219
sage -fixdoctests: Add option --only-tags
mkoeppe Jun 24, 2023
6e25da2
sage --fixdoctests: New option --distribution, defaults
mkoeppe Jun 24, 2023
a14580e
sage --fixdoctests: Use git --no-pager
mkoeppe Jun 24, 2023
48b1660
sage --fixdoctests: Rewrite # optional properly
mkoeppe Jun 24, 2023
58d857e
sage --fixdoctests: More detail on NameError
mkoeppe Jun 25, 2023
8ab0383
sage --fixdoctests: Remove debugging code
mkoeppe Jun 25, 2023
52fb3cc
sage --fixdoctests: Fix up 'why'
mkoeppe Jun 25, 2023
28019f4
sage --fixdoctests: Handle multiple files
mkoeppe Jun 25, 2023
65212a3
sage --fixdoctests: Exit early if the doctester does not work
mkoeppe Jun 25, 2023
2a2279f
Merge branch 'feature_standard_optional_static' into feature_definitions
mkoeppe Jun 25, 2023
66f1a7a
src/sage/doctest/parsing.py (unparse_optional_tags): Take spkg_type i…
mkoeppe Jun 25, 2023
f6d9acd
sage --fixdoctests: Remove line-level # optional tags that duplicate …
mkoeppe Jun 25, 2023
f407653
sage -t: Add option --probe
mkoeppe Jun 27, 2023
f7d7e5b
sage -fixdoctests: Use --probe
mkoeppe Jun 27, 2023
c890919
sage.misc.sagedoc: If terminal is too narrow, cut away # optional for…
mkoeppe Jun 27, 2023
7870c3d
sage.features.sagemath: Add more modules to the JoinFeatures
mkoeppe Jun 27, 2023
6f230ff
sage -fixdoctests: Map module names to feature names
mkoeppe Jun 27, 2023
40d44fe
sage -fixdoctests: Do not remove comments that precede annotations
mkoeppe Jun 27, 2023
7400851
sage.misc.sagedoc: Unconditionally remove "# optional" tags of presen…
mkoeppe Jun 28, 2023
c54d3d1
src/sage/doctest/parsing.py: Repair parse_optional_tags
mkoeppe Jun 28, 2023
231886d
sage.features.sagemath: Add even more modules to the JoinFeatures
mkoeppe Jun 28, 2023
793ec77
sage -fixdoctests: Do not add tags that are already file-level tags
mkoeppe Jun 28, 2023
747b3d4
sage -fixdoctests: Only check for a functional doctester when venv or…
mkoeppe Jun 28, 2023
f78ce64
sage.doctest: Restore 'variable referenced here was set only' warning…
mkoeppe Jun 28, 2023
2d72755
sage.doctest: Make 'variable referenced here was set only' warnings d…
mkoeppe Jun 28, 2023
87ce0db
sage -t: New option --only-lib; log when directly specified files are…
mkoeppe Jun 28, 2023
bb873c2
sage -fixdoctests: Use sage -t --only-lib, pass through 'Skipping ...…
mkoeppe Jun 28, 2023
499d68f
src/doc/en/developer/doctesting.rst: Add section 'Options for testing…
mkoeppe Jun 28, 2023
7d291cd
src/doc/en/developer/coding_basics.rst: Update description of file-le…
mkoeppe Jun 28, 2023
6410b89
src/doc/en/developer/doctesting.rst: Document sage -fixdoctests
mkoeppe Jun 28, 2023
dc2f81e
src/doc/en/developer/doctesting.rst: Document --probe
mkoeppe Jun 28, 2023
eb089fd
src/sage/doctest/control.py: Fix grammar in message
mkoeppe Jun 29, 2023
88451cd
sage -fixdoctest: Change default for --probe
mkoeppe Jun 29, 2023
b405d87
sage -t: Do not forget to discover available software when using skip…
mkoeppe Jun 29, 2023
b567951
sage -fixdoctest: Do do duplicate tags
mkoeppe Jun 29, 2023
7e7bd57
Merge branch 'persistent-optional-tags' into feature_definitions
mkoeppe Jun 29, 2023
80d15a3
sage -fixdoctest: Fix default of --keep-both
mkoeppe Jun 29, 2023
843b479
src/sage/doctest/parsing.py: Fix up merge
mkoeppe Jun 29, 2023
5a47c79
src/sage/doctest/parsing.py (unparse_optional_tags): Implement # opti…
mkoeppe Jun 29, 2023
7708ced
sage -fixdoctest: Rewrite # optional to # needs
mkoeppe Jun 29, 2023
c9e338a
src/sage/doctest/parsing.py: Add doctests, recognize is_persistent in…
mkoeppe Jun 29, 2023
6ac8b55
src/sage/doctest/parsing.py: No trailing newline in string_sans_tags
mkoeppe Jun 29, 2023
a19bdd3
sage -fixdoctest: Remove line-level # optional tags that are covered …
mkoeppe Jun 29, 2023
f2fd934
src/bin/sage-fixdoctests: Handle the new 'needs' keyword
mkoeppe Jun 30, 2023
1d544b0
sage.doctest: Do not try to detect available software outside of runners
mkoeppe Jun 30, 2023
feca1dc
sage -fixdoctests: Also rewrite a file-level annotation
mkoeppe Jun 30, 2023
9413da0
src/sage/doctest/parsing.py: Fix markup
mkoeppe Jun 30, 2023
038bb55
src/bin/sage-fixdoctests: Fix handling of multiple sage.doctest direc…
mkoeppe Jun 30, 2023
b86ffb3
src/sage/doctest/parsing.py: Add doctests
mkoeppe Jun 30, 2023
57c5c7d
sage.doctest.{parsing,sources}: Handle file_optional_tags properly
mkoeppe Jun 30, 2023
d75181e
sage.doctest: Refactor skipfile, defer 2nd read of file annotation to…
mkoeppe Jun 30, 2023
7765125
sage -fixdoctest: Fix default of --keep-both and --full-tracebacks again
mkoeppe Jun 30, 2023
84004a6
src/bin/sage-fixdoctests: Fix reading of block-level tags
mkoeppe Jun 30, 2023
bbd8270
sage.doctest: Remove use of skipfile with list of tags
mkoeppe Jun 30, 2023
4ffec03
src/doc/en/developer/doctesting.rst: Add warning
mkoeppe Jun 30, 2023
80e088d
src/sage/doctest: Fix markup
mkoeppe Jun 30, 2023
f0d851a
src/sage/doctest/forker.py: Fix wording of warning message
mkoeppe Jul 1, 2023
7b79b47
src/sage/doctest: Use dicts, not sets, for optional tags
mkoeppe Jul 1, 2023
ebfd164
src/sage/doctest/parsing.py (update_optional_tags): Alignment fixes, …
mkoeppe Jul 1, 2023
e0c1d84
Merge tag '10.1.beta5' into feature_definitions
mkoeppe Jul 1, 2023
93c11f1
src/sage/doctest/parsing.py: Hide tags from relint
mkoeppe Jul 1, 2023
1130c26
sage --fixdoctests: Add option --no-test
mkoeppe Jul 2, 2023
514d1f7
sage --fixdoctests: Do not add tags that duplicate file-scoped tags
mkoeppe Jul 2, 2023
65e6985
sage --fixdoctests: Add option --no-test (fixup)
mkoeppe Jul 2, 2023
5934fe7
sage --fixdoctests: Handle the case of multiple tags in 'may no longe…
mkoeppe Jul 2, 2023
51d406d
sage -t, sage --fixdoctests: Don't probe pure file-level tags
mkoeppe Jul 2, 2023
6f2ffd0
src/sage/repl/user_globals.py: Add # needs
mkoeppe Jul 2, 2023
914dd03
sage -t: While probing, do not issue "was set only in doctest marked"…
mkoeppe Jul 2, 2023
ce84e70
sage -t, sage --fixdoctests: Don't probe pure file-level/block-level …
mkoeppe Jul 2, 2023
c999202
sage --fixdoctests: Handle top-level NameErrors that resolve in sage.all
mkoeppe Jul 2, 2023
243654a
src/doc/en/developer, src/sage/features/sagemath.py: 'annotation' -> …
mkoeppe Jul 3, 2023
981ba19
sage.features.all (module_feature, name_feature): Move here from sage…
mkoeppe Jul 3, 2023
3d38f98
sage.features: Add more modules to join features, update # needs
mkoeppe Jul 3, 2023
9db9bf7
src/sage/features/sagemath.py: Fixup
mkoeppe Jul 3, 2023
6298290
src/doc/en/developer/doctesting.rst: Add examples
mkoeppe Jul 3, 2023
ff2b675
src/doc/en/developer: Update doctest writing / doctesting sections
mkoeppe Jul 3, 2023
627c5e8
src/doc/en/developer/coding_basics.rst: Explain why variables should …
mkoeppe Jul 4, 2023
2ef982c
src/sage/doctest/parsing.py: Merge file optional tags into block tags
mkoeppe Jul 4, 2023
ffd6177
src/doc/en/developer/coding_basics.rst: Fix doctest
mkoeppe Jul 4, 2023
8e41453
src/sage/coding/guruswami_sudan/gs_decoder.py: Fix expected doctest o…
mkoeppe Jul 4, 2023
ef0b5cf
src/sage/coding/linear_rank_metric.py: Fix broken doctest that was no…
mkoeppe Jul 4, 2023
16771d6
src/sage/combinat/diagram.py: Update # needs
mkoeppe Jul 4, 2023
87b4e1d
src/sage/geometry/polyhedron/base4.py: Remove deprecation warnings fr…
mkoeppe Jul 4, 2023
8938897
src/sage/doctest/parsing.py: Issue style warnings for repeated # opti…
mkoeppe Jul 4, 2023
edaeab2
src/sage/doctest/forker.py: Do not initialize warnings when already set
mkoeppe Jul 4, 2023
1ecb25c
src/bin/sage-fixdoctests: Take care of style warnings issued by the d…
mkoeppe Jul 4, 2023
d63808a
src/bin/sage-fixdoctests: Clean tags after processing blocks
mkoeppe Jul 4, 2023
6204e0c
src/sage/doctest/parsing.py: The end of a Sphinx codeblock also ends …
mkoeppe Jul 5, 2023
0ca9016
src/doc/en/developer/doctesting.rst (sage --fixdoctests): Update on w…
mkoeppe Jul 5, 2023
d09ac6f
src/sage/doctest/parsing.py: Parse the format # optional - foo (expla…
mkoeppe Jul 5, 2023
e7a0cc0
src/sage/doctest/forker.py: Follow the style warning
mkoeppe Jul 5, 2023
b0bbedc
src/sage/features/sagemath.py: Add to a join feature
mkoeppe Jul 5, 2023
557098e
sage.features.sagemath: Move features sage.libs.gap, sage.libs.singul…
mkoeppe Jul 5, 2023
b50ca94
src/sage/rings/big_oh.py: Follow the style warning
mkoeppe Jul 5, 2023
af3128c
src/sage/rings/homset.py: Follow the style advice
mkoeppe Jul 5, 2023
91bc915
src/sage/features/sagemath.py: Update from #35509
mkoeppe Jul 5, 2023
f9add88
sage.features: Fix doctests when sage.libs.ecl, sage.libs.gap are not…
mkoeppe Mar 12, 2023
95f5383
src/sage/features/__init__.py: Add # optional
mkoeppe Jun 28, 2023
fb689a2
./sage -fixdoctests src/sage/features/__init__.py
mkoeppe Jun 29, 2023
7a002a4
src/sage/features/interfaces.py: Revert unintended change
mkoeppe Jul 7, 2023
db3569b
src/sage/doctest: Update copyright
mkoeppe Jul 7, 2023
9109d0e
src/bin/sage-fixdoctests: Add copyright
mkoeppe Jul 7, 2023
ba8dd56
src/sage/rings/polynomial/multi_polynomial_ideal.py: Fix doctest that…
mkoeppe Jul 7, 2023
c5d2adf
./sage -fixdoctests src/sage/rings/function_field/ideal_polymod.py
mkoeppe Jul 7, 2023
31a30aa
src/sage/schemes/cyclic_covers/cycliccover_finite_field.py: Fix typo …
mkoeppe Jul 7, 2023
3106a06
src/sage/interfaces/gnuplot.py: Fix tag that is now parsed as TAG (CO…
mkoeppe Jul 7, 2023
48ea62c
'./sage -fixdoctests --long' for all files that sage.doctest.sources.…
mkoeppe Jul 7, 2023
8623513
src/sage/doctest/sources.py: Mark _test_enough_doctests test as # not…
mkoeppe Jul 7, 2023
31097fc
src/sage/doctest/test.py: Update doctests
mkoeppe Jul 7, 2023
4f55787
Merge branch 'develop' into feature_definitions
mkoeppe Jul 9, 2023
c6d1b89
src/doc/en/developer: s/codeblock-scoped/block-scoped/g
mkoeppe Jul 9, 2023
636a05d
src/doc/en/developer/doctesting.rst: Fix typo
mkoeppe Jul 9, 2023
2625d2a
src/sage/rings/polynomial/polynomial_ring.py: Use some more block-sco…
mkoeppe Jul 9, 2023
d5672a1
src/sage/combinat/finite_state_machine.py: Move import of QQbar into …
mkoeppe Jul 9, 2023
9132250
src/sage/misc/latex_standalone.py: Use more block-scoped tags, align …
mkoeppe Jul 9, 2023
eba5b80
src/sage/features/sagemath.py: Decapitalize some terms
mkoeppe Jul 9, 2023
4ad6345
src/doc/en/developer/coding_basics.rst: Add example for unbreakable d…
mkoeppe Jul 9, 2023
627c9c0
git grep -l annotation src/sage/doctest src/bin | xargs sed -i.bak 's…
mkoeppe Jul 10, 2023
44e5752
src/sage/doctest/parsing.py: Update docstring
mkoeppe Jul 10, 2023
a3e61ad
sage -fixdoctests: Actually handle --long
mkoeppe Jul 10, 2023
6019181
src/sage/doctest/parsing.py: Fix docstring markup
mkoeppe Jul 10, 2023
37d2303
src/sage/doctest/parsing.py (SageDocTestParser.__init__ docstring): R…
mkoeppe Jul 10, 2023
26d6766
src/doc/en/developer/doctesting.rst: Explain prompt engineering for t…
mkoeppe Jul 10, 2023
bf270c7
src/sage/misc/sagedoc.py (process_optional_doctest_tags): Rename from…
mkoeppe Jul 11, 2023
19eee80
src/bin/sage-fixdoctests: Append block tag line to previous line inst…
mkoeppe Jul 11, 2023
3c44670
./sage -fixdoctests: Issue a deprecation warning when 2 filenames are…
mkoeppe Jul 11, 2023
30e7dae
src/sage/doctest/parsing.py (update_optional_tags): Preserve two-colu…
mkoeppe Jul 11, 2023
b801474
src/sage/doctest/parsing.py: Highlight keywords from relint
mkoeppe Jul 11, 2023
fafaaf2
sage -t, sage -fixdoctests: Rename option --only-lib to --if-installed
mkoeppe Jul 12, 2023
8d25508
src/doc/en/developer/doctesting.rst: Standardize prompts
mkoeppe Jul 12, 2023
0c42086
./sage -fixdoctests: Update --help
mkoeppe Jul 12, 2023
6b5b82c
Fix random doctests in elliptic curves
kwankyu Jul 19, 2023
44549f6
Merge branch 'fix-doctests-elliptic-curves' into feature_definitions
mkoeppe Jul 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
407 changes: 333 additions & 74 deletions src/bin/sage-fixdoctests

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/bin/sage-runtests
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ if __name__ == "__main__":
help='run tests pretending that the software listed in FEATURES (separated by commas) is not installed; '
'if "all" is listed, will also hide features corresponding to all optional or experimental packages; '
'if "optional" is listed, will also hide features corresponding to optional packages.')
parser.add_argument("--probe", metavar="FEATURES", default="",
help='run tests that would not be run because one of the given FEATURES (separated by commas) is not installed; '
'report the tests that pass nevertheless')
parser.add_argument("--randorder", type=int, metavar="SEED", help="randomize order of tests")
parser.add_argument("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests",
default=os.environ.get("SAGE_DOCTEST_RANDOM_SEED"))
Expand All @@ -66,6 +69,7 @@ if __name__ == "__main__":
parser.add_argument("-i", "--initial", action="store_true", default=False, help="only show the first failure in each file")
parser.add_argument("--exitfirst", action="store_true", default=False, help="end the test run immediately after the first failure or unexpected exception")
parser.add_argument("--force_lib", "--force-lib", action="store_true", default=False, help="do not import anything from the tested file(s)")
parser.add_argument("--if-installed", action="store_true", default=False, help="skip Python/Cython files that are not installed as modules")
parser.add_argument("--abspath", action="store_true", default=False, help="print absolute paths rather than relative paths")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understood the meaning of --only-lib by the statement "Use the option --only-lib to skip the source files of all Python/Cython modules that are not installed in the virtual environment..." in the documentation. I still don't understand the meaning of the existing --force-lib. The common -lib refers to the same thing, "the library installed to a virtual environment"?

Copy link
Contributor Author

@mkoeppe mkoeppe Jul 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, in both cases, lib refers to the Sage library.

When sage -t is applied to a Python file outside of the Sage library (= the installed copy or "the" source tree; technically, a file that does not look like it belongs to a source tree with the top-level package "sage"), then it first calls load on that file, which adds stuff to the global namespace. This is a feature that simplifies testing user code, as one does not have to say from .... import in every doctest. --force-lib turns this mechanism off and treats that file like any file that is part of the Sage library.

The lib in --only-lib is a bit different. It also checks whether the given file looks like it belongs to a source tree with the top-level package "sage", but then it checks whether that is installed as a module in the installed Sage library.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Then how about --only-installed instead of --only-lib to avoid possible confusion with the lib in --force-lib? Perhaps together with --all-installed instead of --installed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like --only-installed as a replacement for --only-lib because --installed runs doctests as they appear in the installed files, whereas --only-lib runs the doctests in the given files and only filters by an additional condition

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then --if-installed as it filters out not-installed files? This is my last try :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, that's a good solution. Done in fafaaf2

parser.add_argument("--verbose", action="store_true", default=False, help="print debugging output during the test")
parser.add_argument("-d", "--debug", action="store_true", default=False, help="drop into a python debugger when an unexpected error is raised")
Expand Down
17 changes: 9 additions & 8 deletions src/doc/de/tutorial/latex.rst
Original file line number Diff line number Diff line change
Expand Up @@ -319,17 +319,18 @@ lΓ€sst. Diese Liste wird verwaltet durch die Befehle
``latex.add_to_mathjax_avoid_list`` und
``latex.mathjax_avoid_list``. ::

sage: latex.mathjax_avoid_list([]) # not tested
sage: latex.mathjax_avoid_list() # not tested
sage: # not tested
sage: latex.mathjax_avoid_list([])
sage: latex.mathjax_avoid_list()
[]
sage: latex.mathjax_avoid_list(['foo', 'bar']) # not tested
sage: latex.mathjax_avoid_list() # not tested
sage: latex.mathjax_avoid_list(['foo', 'bar'])
sage: latex.mathjax_avoid_list()
['foo', 'bar']
sage: latex.add_to_mathjax_avoid_list('tikzpicture') # not tested
sage: latex.mathjax_avoid_list() # not tested
sage: latex.add_to_mathjax_avoid_list('tikzpicture')
sage: latex.mathjax_avoid_list()
['foo', 'bar', 'tikzpicture']
sage: latex.mathjax_avoid_list([]) # not tested
sage: latex.mathjax_avoid_list() # not tested
sage: latex.mathjax_avoid_list([])
sage: latex.mathjax_avoid_list()
[]

Nehmen wir an ein LaTeX-Ausdruck wurde im Notebook durch ``view()``
Expand Down
152 changes: 124 additions & 28 deletions src/doc/en/developer/coding_basics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,15 @@ written.
Sage does not know about the function ``AA()`` by default, so it needs to be
imported before it is tested. Hence the first line in the example.

All blocks within the same docstring are linked: Variables set
in a doctest keep their values for the remaining doctests within the
same docstring. It is good practice to use different variable names for different
values, as it makes the data flow in the examples easier to understand
for human readers. (It also makes the data flow analysis in the
Sage doctester more precise.) In particular, when unrelated examples
appear in the same docstring, do not use the same variable name
for both examples.

- **Preparsing:** As in Sage's console, `4/3` returns `4/3` and not
`1.3333333333333333` as in Python 3.8. Testing occurs with full Sage
preparsing of input within the standard Sage shell environment, as
Expand All @@ -958,6 +967,78 @@ written.
5
7

- **Wrap long doctest lines:** Note that all doctests in EXAMPLES blocks
get formatted as part of our HTML and PDF reference manuals. Our HTML manuals
are formatted using the responsive design provided by the
:ref:`Furo theme <spkg_furo>`. Even when the browser window is expanded to
make use of the full width of a wide desktop screen, the style will not
allow code boxes to grow arbitrarily wide.

It is best to wrap long lines when possible so that readers do not have to
scroll horizontally (back and forth) to follow an example.

- Try to wrap long lines somewhere around columns 80 to 88
and try to never exceed column 95 in the source file.
(Columns numbers are from the left margin in the source file;
these rules work no matter how deep the docstring may be nested
because also the formatted output will be nested.)

- If you have to break an expression at a place that is not already
nested in parentheses, wrap it in parentheses::

sage: (len(list(Permutations(['a', 'b', 'c', 'd', 'e', 'f', 'g'])))
....: == len(list(Permutations(7))))
True

- If the output in your only example is very wide and cannot be reasonably
reformatted to fit (for example, large symbolic matrices or numbers with many digits),
consider showing a smaller example first.

- No need to wrap long ``import`` statements. Typically, the ``import`` statements
are not the interesting parts of the doctests. Users only need to be able to
copy-paste them into a Sage session or source file::

sage: from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict, MPolynomialRing_polydict_domain # this is fine

- Wrap and indent long output to maximize readability in the source code
and in the HTML output. But do not wrap strings::

sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_quasi
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
sage: S = P.subscheme([])
sage: T = P.subscheme([x - y])
sage: U = AlgebraicScheme_quasi(S, T); U
Quasi-projective subscheme X - Y of Projective Space of dimension 2
over Integer Ring,
where X is defined by: (no polynomials)
and Y is defined by: x - y
sage: U._repr_() # this is fine
'Quasi-projective subscheme X - Y of Projective Space of dimension 2 over Integer Ring, where X is defined by:\n (no polynomials)\nand Y is defined by:\n x - y'

Also, if there is no whitespace in the doctest output where you could wrap the line,
do not add such whitespace. Just don't wrap the line::

sage: B47 = RibbonGraph(4,7, bipartite=True); B47
Ribbon graph of genus 9 and 1 boundary components
sage: B47.sigma() # this is fine
(1,2,3,4,5,6,7)(8,9,10,11,12,13,14)(15,16,17,18,19,20,21)(22,23,24,25,26,27,28)(29,30,31,32)(33,34,35,36)(37,38,39,40)(41,42,43,44)(45,46,47,48)(49,50,51,52)(53,54,55,56)

- Doctest tags for modularization purposes such as ``# needs sage.modules``
(see :ref:`section-further_conventions`) should be aligned at column 88.
Clean lines from consistent alignment help reduce visual clutter.
Moreover, at the maximum window width, only the word ``# needs`` will be
visible in the HTML output without horizontal scrolling, striking a
thoughtfully chosen balance between presenting
the information and reducing visual clutter. (How much can be seen may be
browser-dependent, of course.) In visually dense doctests, you can try to sculpt out visual space to separate
the test commands from the annotation.

- Doctest tags such as ``# optional - pynormaliz`` that make the doctest
conditional on the presence of optional packages, on the other hand,
should be aligned so that they are visible without having to scroll horizontally.
The :ref:`doctest fixer <section-fixdoctests-optional-needs>` uses
tab stops at columns 48, 56, 64, ... for these tags.

- **Python3 print:** Python3 syntax for print must be used in Sage
code and doctests. If you use an old-style print in doctests, it
will raise a SyntaxError::
Expand Down Expand Up @@ -1131,44 +1212,25 @@ framework. Here is a comprehensive list:
Neither of this applies to files or directories which are explicitly given
as command line arguments: those are always tested.

- **optional:** A line flagged with ``optional - keyword`` is not tested unless
the ``--optional=keyword`` flag is passed to ``sage -t`` (see
- **optional/needs:** A line tagged with ``optional - FEATURE``
or ``needs FEATURE`` is not tested unless the ``--optional=KEYWORD`` flag
is passed to ``sage -t`` (see
:ref:`section-optional-doctest-flag`). The main applications are:

- **optional packages:** When a line requires an optional package to be
installed (e.g. the ``sloane_database`` package)::

sage: SloaneEncyclopedia[60843] # optional - sloane_database

.. NOTE::

If one of the first 10 lines of a file starts with any of
``r""" sage.doctest: optional - keyword``
(or ``""" sage.doctest: optional - keyword``
or ``# sage.doctest: optional - keyword``
or ``% sage.doctest: optional - keyword``
or ``.. sage.doctest: optional - keyword``,
or any of these with different spacing),
then that file will be skipped unless
the ``--optional=keyword`` flag is passed to ``sage -t``.

This does not apply to files which are explicitly given
as command line arguments: those are always tested.

If you add such a line to a file, you are strongly encouraged
to add a note to the module-level documentation, saying that
the doctests in this file will be skipped unless the
appropriate conditions are met.

- **internet:** For lines that require an internet connection::

sage: oeis(60843) # optional - internet
A060843: Busy Beaver problem: a(n) = maximal number of steps that an
n-state Turing machine can make on an initially blank tape before
eventually halting.

- **bug:** For lines that describe bugs. Alternatively, use ``# known bug``
instead: it is an alias for ``optional bug``.
- **known bugs:** For lines that describe known bugs, you can use ``# optional - bug``,
although ``# known bug`` is preferred.

.. CODE-BLOCK:: rest

Expand All @@ -1179,21 +1241,55 @@ framework. Here is a comprehensive list:
sage: 2+2 # known bug
5

- **modularization:** To enable
:ref:`separate testing of the distribution packages <section-doctesting-venv>`
of the modularized Sage library, doctests that depend on features provided
by other distribution packages can be tagged ``# needs FEATURE``.
For example:

.. CODE-BLOCK:: rest

Consider the following calculation::

sage: a = AA(2).sqrt() # needs sage.rings.number_field
sage: b = sqrt(3) # needs sage.symbolic
sage: a + AA(b) # needs sage.rings.number_field sage.symbolic
3.146264369941973?

.. NOTE::

- Any words after ``# optional`` are interpreted as a list of
- Any words after ``# optional`` and ``# needs`` are interpreted as a list of
package (spkg) names or other feature tags, separated by spaces.

- Any punctuation other than underscores (``_``) and periods (``.``),
that is, commas, hyphens, semicolons, ..., after the
first word ends the list of packages. Hyphens or colons between the
word ``optional`` and the first package name are allowed. Therefore,
you should not write ``optional: needs package CHomP`` but simply
``optional: CHomP``.
you should not write ``# optional - depends on package CHomP`` but simply
``# optional - CHomP``.

- Optional tags are case-insensitive, so you could also write ``optional:
- Optional tags are case-insensitive, so you could also write ``# optional -
chOMP``.

If ``# optional`` or ``# needs`` is placed right after the ``sage:`` prompt,
it is a block-scoped tag, which applies to all doctest lines until
a blank line is encountered.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for "codeblock-scoped tag", the initial word "code" seems redundant since the tags are already used within code block. The term "block-scoped tag" is already long, so why make it longer? I prefer "block-scoped tag".

On the other hand, the term "persistent tag" that I originally used is shorter but somewhat obscure...

I will not insist if you disagree though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"block-scoped" is fine with me, I'll change it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c6d1b89

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

These tags can also be applied to an entire file. If one of the first 10 lines
of a file starts with any of ``r""" sage.doctest: optional - FEATURE``,
``# sage.doctest: needs FEATURE``, or ``.. sage.doctest: optional - FEATURE``
(in ``.rst`` files), etc., then this applies to all doctests in this file.

When a file is skipped that was explicitly given as a command line argument,
a warning is displayed.

.. NOTE::

If you add such a line to a file, you are strongly encouraged
to add a note to the module-level documentation, saying that
the doctests in this file will be skipped unless the
appropriate conditions are met.

- **indirect doctest:** in the docstring of a function ``A(...)``, a line
calling ``A`` and in which the name ``A`` does not appear should have this
flag. This prevents ``sage --coverage <file>`` from reporting the docstring as
Expand Down
Loading