- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 678
          Add style guide / reference for # optional - sage.... doctest tags, extend sage -t and sage -fixdoctests for modularization tasks
          #35749
        
          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
Changes from all commits
664c56c
              d7ecd4d
              e7173cd
              3aacb73
              bfb9a52
              4b69756
              d46fb19
              5dc088f
              1ad2776
              eef016f
              74b98cf
              2440c0b
              647380c
              2bd55ab
              9485097
              6dd4afd
              f7152bd
              87f5e15
              bdc4232
              0596705
              131e1f9
              d9d1900
              dda8c28
              e9f38c0
              9541219
              6e25da2
              a14580e
              48b1660
              58d857e
              8ab0383
              52fb3cc
              28019f4
              65212a3
              2a2279f
              66f1a7a
              f6d9acd
              f407653
              f7d7e5b
              c890919
              7870c3d
              6f230ff
              40d44fe
              7400851
              c54d3d1
              231886d
              793ec77
              747b3d4
              f78ce64
              2d72755
              87ce0db
              bb873c2
              499d68f
              7d291cd
              6410b89
              dc2f81e
              eb089fd
              88451cd
              b405d87
              b567951
              7e7bd57
              80d15a3
              843b479
              5a47c79
              7708ced
              c9e338a
              6ac8b55
              a19bdd3
              f2fd934
              1d544b0
              feca1dc
              9413da0
              038bb55
              b86ffb3
              57c5c7d
              d75181e
              7765125
              84004a6
              bbd8270
              4ffec03
              80e088d
              f0d851a
              7b79b47
              ebfd164
              e0c1d84
              93c11f1
              1130c26
              514d1f7
              65e6985
              5934fe7
              51d406d
              6f2ffd0
              914dd03
              ce84e70
              c999202
              243654a
              981ba19
              3d38f98
              9db9bf7
              6298290
              ff2b675
              627c5e8
              2ef982c
              ffd6177
              8e41453
              ef0b5cf
              16771d6
              87b4e1d
              8938897
              edaeab2
              1ecb25c
              d63808a
              6204e0c
              0ca9016
              d09ac6f
              e7a0cc0
              b0bbedc
              557098e
              b50ca94
              af3128c
              91bc915
              f9add88
              95f5383
              fb689a2
              7a002a4
              db3569b
              9109d0e
              ba8dd56
              c5d2adf
              31a30aa
              3106a06
              48ea62c
              8623513
              31097fc
              4f55787
              c6d1b89
              636a05d
              2625d2a
              d5672a1
              9132250
              eba5b80
              4ad6345
              627c9c0
              44e5752
              a3e61ad
              6019181
              37d2303
              26d6766
              bf270c7
              19eee80
              3c44670
              30e7dae
              b801474
              fafaaf2
              8d25508
              0c42086
              6b5b82c
              44549f6
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -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 | ||
|  | @@ -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:: | ||
|  | @@ -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 | ||
|  | ||
|  | @@ -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. | ||
|  | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "block-scoped" is fine with me, I'll change it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in c6d1b89 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|  | ||
There was a problem hiding this comment.
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-libby 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-librefers to the same thing, "the library installed to a virtual environment"?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, in both cases,
librefers to the Sage library.When
sage -tis 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 callsloadon that file, which adds stuff to the global namespace. This is a feature that simplifies testing user code, as one does not have to sayfrom .... importin every doctest.--force-libturns this mechanism off and treats that file like any file that is part of the Sage library.The
libin--only-libis 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.There was a problem hiding this comment.
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-installedinstead of--only-libto avoid possible confusion with thelibin--force-lib? Perhaps together with--all-installedinstead of--installed.There was a problem hiding this comment.
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-installedas a replacement for--only-libbecause--installedruns doctests as they appear in the installed files, whereas--only-libruns the doctests in the given files and only filters by an additional conditionThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then
--if-installedas it filters out not-installed files? This is my last try :-)There was a problem hiding this comment.
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