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

bpo-29428: make doctest documentation clearer #45

Closed
wants to merge 3 commits into from

Conversation

JDLH
Copy link
Contributor

@JDLH JDLH commented Feb 12, 2017

A fix for bug bpo-29428, Doctest documentation unclear about multi-line fixtures.

This changes Doc/library/doctest.rst only. No code changes.

Clarify the introduction of section, "How are Docstring
Examples Recognized", by moving it to above the example
and rewriting for clarity.

Change the example in that section to use more plausible
code, which also demonstrates a multi-line test fixture.

Add three "fine print" points, about the example prefix
strings, blank expected output, and multi-line expected
output.

Clarify the introduction of section, "What's the Execution
Context", by rewriting for clarity, and breaking into three
paragraphs.

Copy-edit the first paragraph in section, "Which Docstrings
Are Examined?".

Clarify the introduction of section, "How are Docstring 
Examples Recognized", by moving it to above the example 
and rewriting for clarity. 

Change the example in that section to use more plausible
code, which also demonstrates a multi-line test fixture.

Add three "fine print" points, about the example prefix 
strings, blank expected output, and multi-line expected 
output.

Clarify the introduction of section, "What's the Execution 
Context", by rewriting for clarity, and breaking into three
paragraphs. 

Copy-edit the first paragraph in section, "Which Docstrings 
Are Examined?".
Copy link
Member

@bitdancer bitdancer left a comment

Choose a reason for hiding this comment

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

Thanks for the suggestions. I have a bunch of tweaks to suggest :)

Note that since you are mostly changing whole paragraphs, you should go ahead and reflow them.

@@ -300,33 +301,49 @@ their contained methods and nested classes.
How are Docstring Examples Recognized?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The :mod:`doctest` module treats any line beginning with ``>>>`` as an
example to be tested.
Following lines which begin with ``...`` continue the example.
Copy link
Member

Choose a reason for hiding this comment

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

In doctest, 'example' generally refers to a block of lines that have no intervening text, although really it refers to an expository unit that would be very difficult to automatically parse. You were probably thinking 'test' here, but that is also incorrect, since 'test' includes the model output lines. So I think what you want to say here is "... continues the code portion of the test", but I'm not at all sure it is worth being that precise here. I would suggest leaving all this to the fine print section.

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'm using 'example' because I think that's what this document chose as the term for this line-beginning-with->>> thing. I think 'test' would be a clearer term, but then the whole document should be changed to use 'test'. Let's choose one and make the document consistent.

searched. Objects imported into the module are not searched.
The docstring for the module, and the docstrings for all functions,
classes, and methods in that module, are searched.
Objects imported into the module are not searched.
Copy link
Member

Choose a reason for hiding this comment

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

I prefer the existing wording here. Your formulation uses more words without adding any clarity. This isn't a strong preference, however, so if other people prefer it I have no object. However, 'for the' should be 'of', since the docstring belongs to the object.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

First, thank you, David, for your careful review. You have found many ways to improve this PR.

The phrase "The module docstring" caused me to stumble as I read it. The first meaning that came to mind was "The module known as docstring", that is, a module. Of course the intended meaning is "The docstring of the module", that is, a docstring. I think the original wording affords two interpretations, and the replacement affords only one. But, I don't feel strongly about this change. I just improved it on my way to the next section.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for the @JDLH wording.

Copy link
Member

Choose a reason for hiding this comment

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

+1 for disambiguating, can probably be made short again using something like:

The docstring of the module, and all function, class and method docstrings are searched.

Subsequent non-blank lines, if any, form an expected output string.
A blank (all-whitespace) line, or a line with ``>>>`` (beginning the
next example), ends the expected output string.

Copy link
Member

Choose a reason for hiding this comment

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

As implied above, I prefer the original exposition. The key point right here is that a copy and paste of an interactive session works. The rest should go in the fine print.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The overarching theme in this revision is, I think the document tries to say "here's how you use doctest", and imply what doctest does. This breaks down when implication isn't clear enough, the reader has a problem, and comes looking for a solution. I think it's a good approach to say "this is what doctest does", then move on to "here's how you use doctest". I think the original wording, "In most cases a copy-and-paste... works fine", was worse: it didn't say how you use doctest, it just implied it. Hence my leading with the "this is what doctest does" statement.

12
>>> if x == 13:
... print("yes")
...
Copy link
Member

Choose a reason for hiding this comment

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

This looks to me like a bug in the interactive shell. Let's not include the bug in the docs, and instead file a separate issue about 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.

The bug being, the Python 3.7 in-dev interactive shell receives a comment-only line, and prints a sys.ps2 prompt ... in response. A sys.ps1 >>> prompt is expected. Yes, this behaviour seemed strange. Python2.7 behaves as expected. I'm happy to delete the ... line after the comment line. Should I also file the bug report, or do you want to?

Copy link
Member

Choose a reason for hiding this comment

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

Please submit it.

Copy link
Contributor Author

@JDLH JDLH Feb 14, 2017

Choose a reason for hiding this comment

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

I take it back. Every one of my Python versions, 2.7 from Macports, 2.7 from Apple, 3.7 from master, 3.6 from Macports, all print out a sys.ps2 prompt after a comment-only line. How does your copy of Python behave? If the sys.ps2 prompt is what every current Python shell does, then I think the example should reflect that.

Copy link
Contributor Author

@JDLH JDLH Feb 14, 2017

Choose a reason for hiding this comment

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

http://bugs.python.org/issue29561 Interactive mode gives sys.ps2 not sys.ps1 after comment-only line

... print("yes")
...
>>> import math
>>> x = factorial(10); math.ceil(math.log10(x))
Copy link
Member

Choose a reason for hiding this comment

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

Most doctests would not use ;. It will strengthen your 'multiline' example to make these two lines. Having an import does enhance the example, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using an import statement in the example is at the heart of why I'm offering this revision. I'm glad it works. I agree that having a statement list is unusual. However, 1) it's an unobtrusive way of demonstrating that the doctest module looks for statement lists, not statements, and 2) I actually use statement lists in some of my doctests. But this is a minor point, I'm willing to bow to wisdom of the more experienced contributors.


* The expected output can contain multiple lines. These lines become a
string, which is compared to the string of actual output from
testing the example.
Copy link
Member

Choose a reason for hiding this comment

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

These lines become a string containing newlines. The leading indentation of the example block is stripped when building the string. The resulting string is compared to the string of actual output from running the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good improvement. Thank you.


* The expected output can contain multiple lines. These lines become a
string, which is compared to the string of actual output from
testing the example.
Copy link
Member

Choose a reason for hiding this comment

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

Another point could be added: "The last code continuation line of an example copied from the interactive shell (the line starting with "..." that is otherwise blank in the example above) may be omitted without changing the meaning of the test."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good improvement. Thank you.

in the docstring being run. Examples cannot see names defined in other
Within a docstring, later examples can use names defined by earlier
examples. It's fine for an example to set up state, and
have no output.
Copy link
Member

Choose a reason for hiding this comment

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

IMO this paragraph is unneeded. It is already clearly demonstrated in your enhanced example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This new paragraph and the two following new paragraphs are my attempt to say more clearly what the old text says in one, jumbled paragraph. I like explicitly saying that state is shared within a docstring, because it's a contrast to what the next paragraph says about state between docstrings. Also, the old text buried the news about shared state within a docstring, and I'm working out my frustrations by now saying it clearly. I think this is an important point, and it's worth saying it explicitly and also showing it in the examples.

:mod:`M`.
When doctest tests examples, it doesn't change the module's real globals.

This shallow copy of globals is discarded at the end of each docstring,
Copy link
Member

Choose a reason for hiding this comment

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

s/at the end of each docstring/after the docstring has been processed/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good improvement. Thank you.

This shallow copy of globals is discarded at the end of each docstring,
and copied afresh for the next docstring. Thus, examples in one docstring
in :mod:`M` can't leave behind crumbs that accidentally allow an example
in another docstring to work. Examples cannot see names defined in other
docstrings.
Copy link
Member

Choose a reason for hiding this comment

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

This is definitely an improvement over the original text.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you. This is another instance of me working out my frustrations against the old text.

Copy link
Contributor Author

@JDLH JDLH left a comment

Choose a reason for hiding this comment

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

Responses to David (bitdancer's) review comments. A good share of them should be adopted. More review welcome.

searched. Objects imported into the module are not searched.
The docstring for the module, and the docstrings for all functions,
classes, and methods in that module, are searched.
Objects imported into the module are not searched.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

First, thank you, David, for your careful review. You have found many ways to improve this PR.

The phrase "The module docstring" caused me to stumble as I read it. The first meaning that came to mind was "The module known as docstring", that is, a module. Of course the intended meaning is "The docstring of the module", that is, a docstring. I think the original wording affords two interpretations, and the replacement affords only one. But, I don't feel strongly about this change. I just improved it on my way to the next section.

@@ -300,33 +301,49 @@ their contained methods and nested classes.
How are Docstring Examples Recognized?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The :mod:`doctest` module treats any line beginning with ``>>>`` as an
example to be tested.
Following lines which begin with ``...`` continue the example.
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'm using 'example' because I think that's what this document chose as the term for this line-beginning-with->>> thing. I think 'test' would be a clearer term, but then the whole document should be changed to use 'test'. Let's choose one and make the document consistent.

Subsequent non-blank lines, if any, form an expected output string.
A blank (all-whitespace) line, or a line with ``>>>`` (beginning the
next example), ends the expected output string.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The overarching theme in this revision is, I think the document tries to say "here's how you use doctest", and imply what doctest does. This breaks down when implication isn't clear enough, the reader has a problem, and comes looking for a solution. I think it's a good approach to say "this is what doctest does", then move on to "here's how you use doctest". I think the original wording, "In most cases a copy-and-paste... works fine", was worse: it didn't say how you use doctest, it just implied it. Hence my leading with the "this is what doctest does" statement.

Subsequent non-blank lines, if any, form an expected output string.
A blank (all-whitespace) line, or a line with ``>>>`` (beginning the
next example), ends the expected output string.

In most cases a copy-and-paste of an interactive console session works fine,
but doctest isn't trying to do an exact emulation of any specific Python shell.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This sentence is verbatim from the previous version of the document. I don't have strong feelings about this change. I'm happy to go with "the python shell".

12
>>> if x == 13:
... print("yes")
...
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The bug being, the Python 3.7 in-dev interactive shell receives a comment-only line, and prints a sys.ps2 prompt ... in response. A sys.ps1 >>> prompt is expected. Yes, this behaviour seemed strange. Python2.7 behaves as expected. I'm happy to delete the ... line after the comment line. Should I also file the bug report, or do you want to?

:ref:`compound statement <compound>`.
The ``...`` string tells the module that the line continues a compound
statement. (Actually, doctest gets these strings from the PS1 and PS2
values of the :mod:`sys` module.)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are correct. I had remembered incorrectly the _EXAMPLE_RE in cpython/Lib/doctest.py:582-593. We should delete the whole sentence in parentheses. I don't think that news that it resembles the default values of sys.PS[12].


* The expected output can contain multiple lines. These lines become a
string, which is compared to the string of actual output from
testing the example.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good improvement. Thank you.

This shallow copy of globals is discarded at the end of each docstring,
and copied afresh for the next docstring. Thus, examples in one docstring
in :mod:`M` can't leave behind crumbs that accidentally allow an example
in another docstring to work. Examples cannot see names defined in other
docstrings.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you. This is another instance of me working out my frustrations against the old text.

in the docstring being run. Examples cannot see names defined in other
Within a docstring, later examples can use names defined by earlier
examples. It's fine for an example to set up state, and
have no output.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This new paragraph and the two following new paragraphs are my attempt to say more clearly what the old text says in one, jumbled paragraph. I like explicitly saying that state is shared within a docstring, because it's a contrast to what the next paragraph says about state between docstrings. Also, the old text buried the news about shared state within a docstring, and I'm working out my frustrations by now saying it clearly. I think this is an important point, and it's worth saying it explicitly and also showing it in the examples.

:mod:`M`.
When doctest tests examples, it doesn't change the module's real globals.

This shallow copy of globals is discarded at the end of each docstring,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good improvement. Thank you.

@codecov
Copy link

codecov bot commented Feb 13, 2017

Codecov Report

Merging #45 into master will decrease coverage by -0.01%.
The diff coverage is n/a.

@@            Coverage Diff             @@
##           master      #45      +/-   ##
==========================================
- Coverage   82.37%   82.37%   -0.01%     
==========================================
  Files        1427     1427              
  Lines      350948   350948              
==========================================
- Hits       289089   289081       -8     
- Misses      61859    61867       +8

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2294f3a...62a9a46. Read the comment docs.

@JDLH
Copy link
Contributor Author

JDLH commented Feb 13, 2017

Commits a140a7f and 62a9a46 address those of @bitdancer 's comments with which I agree. There are still some paragraphs where we are not yet resolved. Please continue reviewing.

@bitdancer
Copy link
Member

bitdancer commented Feb 14, 2017 via email

@serhiy-storchaka serhiy-storchaka added the docs Documentation in the Doc dir label Feb 18, 2017
@rhettinger
Copy link
Contributor

Sorry to say that overall I don't think this reads any better than what we have now and is in some ways worse. Instead of a rewrite effort, please focus on any one part that have reason to believe to be misleading. These docs have been around a long time and have worked reasonably well for a lot of users. Much of this I believe was written originally by Tim Peters who has knack for saying just what needs to be said.

@JDLH
Copy link
Contributor Author

JDLH commented Apr 5, 2017

@rhettinger Thank you for looking at this. I'm sorry to hear that it doesn't read any better for you.

This is not a rewrite effort. This is a targeted change to those sections where inadequate explanation misled me when I was writing my doctests. Specifically the existing docs aren't clear about when to use >>> and when to use ..., doesn't demonstrate how to use an imported module in a doctest, and doesn't talk clearly about the execution context within a docstring. My changes try to improve those points.

Perhaps you could point out the places where this version is worse? I could improve those.

Comments from others?

Copy link
Member

@JulienPalard JulienPalard left a comment

Choose a reason for hiding this comment

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

Hi JDLH and thanks for your efforts. First sorry it takes us too long for providing feedback.

It would help if you keep your changes atomic, and your messages short on b.p.o: It's hard to review a PR that changes a lot of paragragraphs sometimes completly unlinked to the original issue, and when messages take a whole screen on b.p.o it's also long to read which can slow the review process.

I understand that's frustrating to have changes rejected, as I previously said atomic obvious changes are more likely to be merged quickly, you probably gone too far on this one.

searched. Objects imported into the module are not searched.
The docstring for the module, and the docstrings for all functions,
classes, and methods in that module, are searched.
Objects imported into the module are not searched.
Copy link
Member

Choose a reason for hiding this comment

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

+1 for disambiguating, can probably be made short again using something like:

The docstring of the module, and all function, class and method docstrings are searched.

@@ -300,36 +301,54 @@ their contained methods and nested classes.
How are Docstring Examples Recognized?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A doctest example is composed of one or more tests. An individual test
Copy link
Member

Choose a reason for hiding this comment

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

This looks wrong, an example (that you name test) starts with >>> and ends after its output.

Meaning this is a correct example not covered by your paragraph:

>>> say = "Ni"
>>> print(say)
Ni

This is already covered by:

Any expected output must immediately follow the final '>>> ' or '... ' line containing the code, and the expected output (if any) extends to the next '>>> ' or all-whitespace line.

Please remove this paragraph.

In most cases a copy-and-paste of an interactive console session works fine,
but doctest isn't trying to do an exact emulation of any specific Python shell.
but doctest isn't trying to do an exact emulation of the Python shell.
Copy link
Member

Choose a reason for hiding this comment

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

There exist more than one Python shell, please leave "any specific".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reviewers are not consistent. Back on the first commit, I kept the wording "any specific Python shell". @bitdancer 's comment on Feb 12, 2017 was:

Perhaps this should say "the python shell" instead of "any specific python shell", since I think most alternate shells can't be cut and pasted as doctests.
My reply was:
This sentence is verbatim from the previous version of the document. I don't have strong feelings about this change. I'm happy to go with "the python shell".

What wording will satisfy both @bitdancer and @JulienPalard ?

Copy link
Member

Choose a reason for hiding this comment

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

Sorry for the inconsistencies, both are true, I still prefer "any specific", but "the" is simplier. In any cases the message passes about "don't rely on copy/paste to work 100% of the times".

Again, this modification is not linked to your original issue, when we're saying "try to propose atomic changes" we're having this in mind: The more you're modifying, the more people will discuss it, this is also why I originally said "please leave" this as is.

... print("no")
... print("NO")
... print("NO!!!")
... print("differ:\n{0}\n{1}".format(x, factorial(9)*10))
Copy link
Member

Choose a reason for hiding this comment

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

Multi-line examples having a setup phrase is already covered in the original example as @bitdancer said, in:

>>> x = 12
>>> x
12

In your example, the line: >>> x = factorial(10); math.ceil(math.log10(x)) is not clear, I do not expect one to know the REPL is printing the last statement of a line containing multiple ones separated by semi columns, it just make the example hard to read, if not surprising. Yes I even had to test it in my REPL to convince me it actually works.

Please do not change the example, it was simple and covered the point you're trying to fix.

Any expected output must immediately follow the final ``'>>> '`` or ``'... '``
line containing the code, and the expected output (if any) extends to the next
``'>>> '`` or all-whitespace line.

Copy link
Member

Choose a reason for hiding this comment

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

As in a previous review I asked you to remove the new intro paragraph with wrong statement in it, please keep this one.

* The expected output can contain multiple lines. These lines become a
string containing newlines. The leading indentation of the example
block is stripped when building the string. The resulting string is
compared to the string of actual output from running the test.
Copy link
Member

Choose a reason for hiding this comment

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

*example

* Expected output cannot contain an all-whitespace line, since such a line is
taken to signal the end of expected output. If expected output does contain a
blank line, put ``<BLANKLINE>`` in your doctest example each place a blank line
blank line, put ``<BLANKLINE>`` in your doctest test each place a blank line
Copy link
Member

Choose a reason for hiding this comment

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

I disagree, the doctest module is not aimed to write tests in docstrings, but to test examples found in docstrings. So here example was the right word.

@@ -373,21 +392,28 @@ The fine print:
1

and as many leading whitespace characters are stripped from the expected output
as appeared in the initial ``'>>> '`` line that started the example.
as appeared in the initial ``'>>> '`` line that started the test.
Copy link
Member

Choose a reason for hiding this comment

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

same.

freely use any names defined at top-level in :mod:`M`, and names defined earlier
in the docstring being run. Examples cannot see names defined in other
docstrings.
Within a docstring, later tests can use names defined by earlier
Copy link
Member

Choose a reason for hiding this comment

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

I would not say so, exemples should be as autonomous as possible to make sense, one should not write an example containing only setup statements, then other examples using them, it's possible, but it's not a feature, just a bad practice, let's not encourage it. Still one can put setup statement in its example so the example is reproductible by itself (autonomous). Please remove this paragraph.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@JulienPalard, the core of this PR is that I wanted to test some code which required an import of another module to run. Is this "bad practice"? If I think I need to import a module to make an "example" run, should I stop using doctests and put that code in a unittest fixture instead?

Copy link
Member

Choose a reason for hiding this comment

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

It's not a bad practice to use import in a doctest, I'm saying you don't need two separate doctests in the same docstring to do so, a single doctest is enough, like:

"""
An example:
>>> import math
>>> math.sqrt(4)
2.0
"""

I do not even consider bad practice separating imports and examples, like:

"""
An example:
First do the import:
>>> import math

Then use sqrt:
>>> math.sqrt(4)
2.0
"""

Yet it's harder to read, it's visually two distincts sessions, with a lot of context switch (text, repl text, repl). It would make more sense when demoing 4 different features, avoiding to import 4 times.

The point of my comment: you're stating "Within a docstring, later tests can use names defined by earlier" which is generalizing to variables, not only imports, and I see very few examples where it can be readable with shared variables. After reading this line, I image one writing:

def foo():
    """
    First example with division:
    >>> a = 10 / 3
    >>> print(a)
    3.3333333333333335

    Second example, with floor division:
    >>> a // 2
    1.0
    """

Which is just bad (this is what I consider "bad practice"): the second example will work under doctest, but one every other user will probably just be interested by the second example, which will fail if they try it alone. This is why I'm speaking of "autonomous examples".

examples. It's fine for a test to set up state, and
have no output.

For each docstring, :mod:`doctest` makes (by default) a
Copy link
Member

Choose a reason for hiding this comment

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

You're reformulating this paragraph but it is not linked to the original issue you're trying to fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@JulienPalard , thank you for your review.

Maybe this is a philosophical issue about documentation. I believe documentation works as a related structure: a particular idea may be introduced early in the document, illustrated with examples in the middle of the document, and then defined with detailed text later in the document. So, improving how a document describes one concept may touch multiple places in a file. I worry that all the insistence on limiting changes just a few adjacent lines makes it hard to refactor the concepts in a document. It also makes it harder to review how a set of changes to the same document will affect the coherence of that document.

Reformulating this paragraph is related to the original issue I'm trying to fix. The original issue is how an import statement is handled in doctests. This is related to concepts of how the state accumulates across examples within a docstring, and how state is reset between docstrings. This paragraph does a poor job of describing how state is reset between docstrings. That is why I try to improve it.

But if it's not possible to refactor documents, only to propose changes to one paragraph or another, then I can break this P.R. up into multiple, each trying to fix one weakness. I think that will be harder to review, and more likely to result in partial changes that are incoherent. But I will try to improve what I can improve.

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@JDLH
Copy link
Contributor Author

JDLH commented Feb 11, 2018

Reviewers: Thank you very much for your attention to this PR and to bpo-29428. I have a feeling we are getting stuck. I have a feeling that part of the problem is that the Github review process doesn't work as well for diffuse issues in a document as it does for atomic issues in code. Part of the problem is that Github doesn't give us tools to have a conversation. Part of the problem is that reasonable people can disagree about writing style (I received contradictory feedback from reviewers).

If we were in a company, this would be the point where I would propose having a meeting. We could talk through the issues.

But this is the Python project. I don't know what the best way to make progress is. What should I do to make progress?

The fundamental problem I want to solve with this P.R. is: I wanted to write a doctest which required an import statement to get a module needed for an example. This documentation did not show me how to do that. I want to improve this documentation so that the next person who thinks they need to import a module for a doctest example will have better guidance.

A secondary goal is to improve the document overall. I see unclear writing and inconsistent terminology. I hear pushback against changes that are not "atomic". Overall document improvements won't be atomic. How does the Python project improve documents overall?

Also, In https://bugs.python.org/msg286973 Marco Bhutto proposed adding a Howto for doctests. A Howto might be a way to make progress on my goals, but I fear that a newbie like me will not be able to write a Howto that will survive the sort of review this PR has received.

@JulienPalard
Copy link
Member

Reviewers: Thank you very much for your attention to this PR

Thank you for contributing, I see this thread is way too long for your original goal.

The fundamental problem I want to solve with this P.R. is: I wanted to write a doctest which required an import statement to get a module needed for an example. This documentation did not show me how to do that.

The documentation (https://docs.python.org/3.6/library/doctest.html#simple-usage-checking-examples-in-a-text-file) give this exact example of separating the import and example:

This is an example text file in reStructuredText format.  First import
``factorial`` from the ``example`` module:

    >>> from example import factorial

Now use it:

    >>> factorial(6)
    120

A secondary goal is to improve the document overall.

This is probably why your PR is stuck, it make your PR too big for the original issue. Try to fix your issue first, as simply as possible, and then, in another PR, try to improve the document overall.

I see unclear writing and inconsistent terminology.

An issue and a PR about them would be appreciated, let's not pollute this already bloath thread with out-of-topic issues.

I hear pushback against changes that are not "atomic".

Yes, atomic chances are faster to review and faster to merge. As you said you're trying to fix an issue AND improving the overall document, this is a "comment magnet" as you see.

Overall document improvements won't be atomic.

Overall improvements can also be specifics: First fix the inconsistency on a single word. Then another word. Then a paragraph. Then add an example. Then ...

How does the Python project improve documents overall?

Run "git log -p Doc/" in your cpython clone, yes it goes slowly, (yes there's not much people really interested in participating full-time on the documentation).

Also, In https://bugs.python.org/msg286973 Marco Bhutto proposed adding a Howto for doctests. A Howto might be a way to make progress on my goals, but I fear that a newbie like me will not be able to write a Howto that will survive the sort of review this PR has received.

In one hand it looks like a big chunk to do. In the other, being a newcomer can help you to know what should be explained to newcomers, so it may end up interesting for other newcomers. Anyway please open a separate issue / PR to discuss this.

What should I do to make progress?

First, don't get bit by https://en.wikipedia.org/wiki/Sunk_cost this is not because we all (especially you) spent a lot of time on this PR that it have to still grow.

I'll in contrast simplify the PR a lot. Look the paragraph [https://docs.python.org/3.6/library/doctest.html#what-s-the-execution-context](26.3.3.3. What’s the Execution Context?), it's really short, and it is the one explainig the scope (This is the one containing the sentence "and names defined earlier in the docstring being run", directly in relation with your issue) maybe you can add your example in it (the one with import math). But refrain from also demoing the ";" in it, it's another example, showing something else, don't mix them, it just make them hard to read. There's probably other places where

@willingc
Copy link
Contributor

But this is the Python project. I don't know what the best way to make progress is. What should I do to make progress?

Thanks @JDLH for taking the time to create a PR, and thanks to @bitdancer, @JulienPalard, and @rhettinger for the effort to review.

I'm recommending that this PR be closed as it is languishing due to its scope being too broad. If you wish to break this PR up into a smaller PR with one atomic change, I will be happy to review the new PR. Thanks.

@willingc willingc closed this May 21, 2018
iritkatriel referenced this pull request in iritkatriel/cpython Jul 22, 2021
jaraco pushed a commit to jaraco/cpython that referenced this pull request Feb 17, 2023
Fix parameter markup

Closes python#45

See merge request python-devs/importlib_resources!46
koxudaxi pushed a commit to koxudaxi/cpython that referenced this pull request Jul 16, 2024
python#45)

Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting changes docs Documentation in the Doc dir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants