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

Support examples section #35

Merged
merged 2 commits into from
Jun 1, 2020

Conversation

igonro
Copy link
Contributor

@igonro igonro commented May 15, 2020

This PR is to support the examples section.

In progress...

Issue #8 and PR mkdocstrings/mkdocstrings#112

@pawamoy
Copy link
Member

pawamoy commented May 15, 2020

I canceled the CI, it hanged because of #36 and #37. I'll fix those tomorrow 🙂

@igonro
Copy link
Contributor Author

igonro commented May 26, 2020

Hey @pawamoy, can you check briefly this PR and mkdocstrings/mkdocstrings#112. I think I almost have it, but I think there is something failing... I tried to debug, but I didn't find the way to debug among 3 different projects using Pycharm. How do you debug while using code from 3 different projects (mkdocs, mkdocstrings, pytkdocs)?

@pawamoy
Copy link
Member

pawamoy commented May 26, 2020

Hey @igonro! Your PRs are looking great so far 🙂

About debugging. MkDocs and mkdocstrings run in the same process, so it's easy to debug them together: in PyCharm, just go to mkdocs code in the site-packages directory, and add your breakpoints there (you can also control-click on an mkdocs object/class to be sent directly where it's defined).

But pytkdocs runs in a subprocess. In PyCharm settings, it seems that subprocess that have python in their name are attached to the debugger, however I was not always able to make it work. There is an issue in their bug tracker about it, not sure if it is still relevant: https://youtrack.jetbrains.com/issue/PY-22623. There's also some information on StackOverflow https://stackoverflow.com/questions/26465221/debugging-popen-subprocesses-with-pycharm, but nothing really helping I'm afraid.

What you can do to ease debugging is to also install pytkdocs in mkdocstrings project in editable mode. Just go the clone of your mkdocstrings fork, activate the virtualenv (poetry shell), then go to your pytkdocs directory and run pip install -e . It should install pytkdocs in mkdocstrings virtualenv as a symlink, so any changes done in pytkdocs are immediately reflected in your mkdocstrings environement. I hope it's clear, sorry if it's not 😅

@pawamoy
Copy link
Member

pawamoy commented May 26, 2020

Now for the review:

The idea here is to support the classic syntax for examples block. What you did here is great, but it's only a start. The parser should especially parse blocks like this:

>>> print("some statement")
some statement

...to allow users to write their examples naturally, without fenced code blocks or extra indentation.

You would need to store the text and examples in order somehow, so we can render them accordingly in mkdocstrings.

A more complete example:

This is my docstring.

Examples:
    This is my *example* block. It contains Markdown text,
    but also special Python interactive-like code blocks:

    >>> 1 + 1
    2
    >>> str(2 + 2)
    "4"

    Maybe we could support multiple "markdown" vs "code examples"
    paragraphs.

    >>> print("last example")
    last example

The spec to detect and parse such code blocks:

  • separated from other text paragraphs by blank lines
  • should not contain blank lines
  • always in pairs: one line starting with >>>, all the following lines that are not empty and not starting with >>>

I'm going to ask your and @jaimergp's opinion on this spec. Is it correct?

Finally, when rendering examples section, we will have to force the syntax highlight to Python for the detected code blocks.

@jaimergp
Copy link

I think the doctest spec allows several consecutive test lines:

>>> returns_none()
>>> returns_arg("a")
"a"

Multiline doctest is also possible and detected with the indentation relative to the >>>

>>> for i in range(5):
>>>     do_something()
1 2 3 4 5

@jaimergp
Copy link

More details: https://docs.python.org/3/library/doctest.html#how-it-works

@igonro igonro changed the title [WIP] Support examples section Support examples section May 27, 2020
@igonro
Copy link
Contributor Author

igonro commented May 27, 2020

I've done everything I could have done, but I think that the result is pretty good.

I've added a test with the following docstring:

    """
        Examples:
            Some examples that will create an unified code block:
            >>> 2 + 2 == 5
            False
            >>> print("examples")
            "examples"
            This is just a random comment in the examples section.

            These examples will generate two different code blocks. Note the blank line.
            >>> print("I'm in the first code block!")
            "I'm in the first code block!"

            >>> print("I'm in other code block!")
            "I'm in other code block!"

            We also can write multiline examples:
            >>> x = 3 + 2
            >>> y = x + 10
            >>> y
            15
            But the output of the example must be just one line... but wait until the last example.

            And this is just a typical Python code block:
            ```python
            print("examples")
            return 2 + 2
            ```

            And yeah, distracted people are safe, this works too:
            ```python
            >>>print("examples")
            "examples"
            >>>2 + 2
            4
            ```

            But this allows us to write examples with multiline outputs:
            ```python
            >>> x = 3
            >>> y = "apple"
            >>> z = False
            >>> l = [x, y, z]
            >>> my_print_list_function(l)
            3
            "apple"
            False
            ```
    """

And the result is the following one:
examples_section

@igonro
Copy link
Contributor Author

igonro commented May 27, 2020

@jaimergp and @pawamoy, what do you think? If you think there is needed another major modifications, you can send your proposals, but I've already spent more time than I wanted.

@igonro
Copy link
Contributor Author

igonro commented May 27, 2020

I don' know why but I'm not being able to run make check. I've been waited a long time (like 10 minutes or so) but it looks like it gets stucked. So the maybe the CI is failing because of this.

@pawamoy
Copy link
Member

pawamoy commented May 27, 2020

Yes it's my fault the CI doesn't pass, don't worry about it, I'll fix it (just the current directory missing in python sys path).

So, this all look great 🙂 Thank you very much for having invested time to send these PRs, I really appreciate it. If you don't have more time to spend, which I totally understand, I'll take it from there.

I think it's important that we support the full doctest spec, and the link @jaimergp posted shows that we could maybe use DocTestParser.parse, which divide a text into text vs doctest parts: https://docs.python.org/3/library/doctest.html#doctest.DocTestParser.parse. I'll play with it a bit to see if it doesn't have quirks (like trying to parse rst, and failing on fenced code blocks?).

If you checked the "allow maintainers to edit this PR" or similar check box on this PR, I'll be able to push commits to your branch. If not, could you check it? Thanks!

@pawamoy pawamoy force-pushed the support-examples-section branch from 9365643 to f7fa027 Compare June 1, 2020 15:01
@pawamoy
Copy link
Member

pawamoy commented Jun 1, 2020

Thanks again @igonro, I'll merge this now and continue the work from a fresh master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants