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

doctest command continuation and chained methods #173

Open
Swandog opened this issue Mar 15, 2023 · 1 comment
Open

doctest command continuation and chained methods #173

Swandog opened this issue Mar 15, 2023 · 1 comment

Comments

@Swandog
Copy link

Swandog commented Mar 15, 2023

I'm having a problem with a doctest in one of my repos. We have some doctests where methods are chained, and they are written across multiple lines using the "command continuation" format. But I seem to have trouble getting both doctest and blackdoc to work simultaneously.

This example is trivial, but I think shows the problem:

def do_things():
    """
    do things


    Examples
    --------
    do this

    >>> g=[8,2,3]
    >>> sorted(g) \
          .pop()
    8
    """
    pass


def do_things_differently():
    """
    do things


    Examples
    --------
    do this

    >>> g=[8,2,3]
    >>> sorted(g) \\
    ...   .pop()
    8
    """
    pass

def do_other_things():
    """
    do things


    Examples
    --------
    do this

    >>> g=[8,2,3]
    >>> sorted(g) \
    ...   .pop()
    8
    """
    pass

def do_that():
    """
    do things


    Examples
    --------
    do this

    >>> g = [8, 2, 3]
    >>> sorted(g)
          .pop()
    8
    """
    pass

if __name__ == "__main__":
    import doctest

    doctest.testmod()

do_things works as a doctest, but it fails to parse in blackdoc: error: cannot format /private/tmp/testing/test.py: Cannot parse: 12:0: EOF in multi-line statement
do_things_differently also works as a doctest, but fails to parse in blackdoc: error: cannot format /private/tmp/testing/test.py: Cannot parse: 28:9: sorted(g) \\
do_other_things parses in blackdoc (and it suggests collapsing lines 44-45 into 1 line), but does not parse as a doctest:

**********************************************************************
File "/private/tmp/testing/test.py", line 44, in __main__.do_other_things
Failed example:
    sorted(g)     ...   .pop()
Exception raised:
    Traceback (most recent call last):
      File "/usr/local/Cellar/[email protected]/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10/doctest.py", line 1350, in __run
        exec(compile(example.source, filename, "single",
      File "<doctest __main__.do_other_things[1]>", line 1
        sorted(g)     ...   .pop()
                      ^^^
    SyntaxError: invalid syntax
**********************************************************************

do_that parses correctly in blackdoc, but gives the wrong answer in doctest:

**********************************************************************
File "/private/tmp/testing/test.py", line 60, in __main__.do_that
Failed example:
    sorted(g)
Expected:
          .pop()
    8
Got:
    [2, 3, 8]
**********************************************************************
1 items had failures:
   1 of   2 in __main__.do_that
***Test Failed*** 1 failures.

Obviously in this case we could just put everything on one line, but in general in our repo we'd to have it chained, on multiple lines. Is there a way to format this that I'm not seeing?

OS: MacOS 13.2.1
Python: 3.10.10
Blackdoc: 0.3.8

Thanks for your help.

@keewis
Copy link
Owner

keewis commented Mar 20, 2023

The reason do_things and do_things_differently work with doctest but not with blackdoc is that doctest executes the file, and python will concatenate any lines with trailing \ with the following line. That's also why do_other_things fail with doctest: the concatenated lines contain the prompt.

blackdoc does not know about \ (because I didn't teach it to), so any example that makes use of that will inevitably fail. I'm open to adding support for that since that's one of the things black will reformat, but it seems a bit tricky to implement and I'm also unlikely to have time for that anytime soon.

For new code I'd use parens: they don't have the issues \ has, and it's also what black will suggest using:

-    >>> g=[8,2,3]
-    >>> (sorted(g)
-    ...   .long_method_name1()
-    ...   .long_method_name2()
-    ...   .long_method_name3()
-    ...   .long_method_name4()
-    ...   .long_method_name5())
+    >>> g = [8, 2, 3]
+    >>> (
+    ...     sorted(g)
+    ...     .long_method_name1()
+    ...     .long_method_name2()
+    ...     .long_method_name3()
+    ...     .long_method_name4()
+    ...     .long_method_name5()
+    ... )
     8
    """

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

No branches or pull requests

2 participants