Search code examples
pythonpython-dataclassesdoctest

Define a dataclass in a doctest body


I need to define a temporary dataclass in order to test a given function via Doctest. However, I am not able to use to @dataclass decorator syntax in a doctest body.

Sample file test.py:

from typing import Any

def myprint(x: Any):
    """
    >>> from dataclasses import dataclass
    >>> @dataclass
    >>> class SomeDataClass:
    ...    field1: int
    ...    field2: str
    >>> myprint(SomeDataClass(1, "txt"))
    SomeDataClass(field1=1, field2='txt')

    """
    print(x)

The doctest invocation is done, as usual, with:

python -m doctest test.py

This results in a "unexpected EOF while parsing" error.

What am I doing wrong?

**********************************************************************
File "test.py", line 6, in test.myprint
Failed example:
    @dataclass
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.9/doctest.py", line 1336, in __run
        exec(compile(example.source, filename, "single",
      File "<doctest test.myprint[1]>", line 1
        @dataclass
                  ^
    SyntaxError: unexpected EOF while parsing
**********************************************************************
[ this error is triggered by the first one and is not relevant ]
File "test.py", line 10, in test.myprint
Failed example:
    myprint(SomeDataClass(1, "txt"))
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.9/doctest.py", line 1336, in __run
        exec(compile(example.source, filename, "single",
      File "<doctest test.myprint[3]>", line 1, in <module>
        myprint(SomeDataClass(1, "txt"))
    TypeError: SomeDataClass() takes no arguments
**********************************************************************
1 items had failures:
   2 of   4 in test.myprint
***Test Failed*** 2 failures.

This test was done on Python 3.9.


Solution

  • A decorator isn't a statement on its own; it connects with the definition below (class or def). So replace the >>> class with ... class.