[Python-ideas] [Brainstorm] Testing with Documented ABCs

Abe Dillon abedillon at gmail.com
Wed Nov 28 16:31:54 EST 2018


[Steven D'Aprano]

> You should look at the state of the art in Design By Contract. In
> Eiffel, DBC is integrated in the language:
> https://www.eiffel.com/values/design-by-contract/introduction/
>
> https://www.eiffel.org/doc/eiffel/ET-_Design_by_Contract_%28tm%29%2C_Assertions_and_Exceptions
>
> Eiffel uses a rather Pythonic block structure to define invariants.
> The syntax is not identical to Python's (Eiffel eschews the colons) but
> it also comes close to executable pseudo-code.


Thank you! I forgot to mention this (or look into how other languages solve
this problem).
I saw your example syntax in the recent DBC main thread and liked it a lot.

One thought I keep coming back to is this comparison between doc string
formats <https://bwanamarko.alwaysdata.net/napoleon/format_exception.html>.
It seems obvious that the "Sphynxy" style is the noisiest, most verbose,
and ugliest format.
Instead of putting ":arg ...:" and ":type ...:" for each parameter and the
return value, it makes much more sense to open up an Args: section and use
a concise notation for type.

The decorator-based pre and post conditions seem like they suffer from the
same redundant, noisy, verbosity problem as the Sphynxy docstring format
but makes it worse by put all that noise before the function declaration
itself.

It makes sense to me that a docstring might have a markdown-style syntax
like

def format_exception(etype, value):
    """    Format the exception with a traceback.
    Args:       etype (str):  what etype represents           [some
constraint on etype](precondition)           [another constraint on
etype](in_line_precondition?)       value (int): what value represents
          [some constraint on value](precondition)       [some
constraints across multiple params](precondition)
    Returns:       What the return value represents  # usually very
similar to the description at the top           [some constraint on
return](postcondition)
    """
    ...


That ties most bits of the documentation to some code that enforces the
correctness of the documentation. And if it's a little noisy, we could take
another page from markdown's book and offer alternate ways to reference
precondition and postcondition logic. I'm worried that such a style would
carry a lot of the same drawbacks as doctest
<https://bemusement.org/doctests-arent-code>

Also, my sense of coding style has been heavily influenced by [this talk](
https://vimeo.com/74316116), particularly the part where he shoves a
mangled Hamlet Soliloquy into the margins, so now many of my functions
adopt the following style:

def someDescriptiveName(
        arg1: SomeType,
        arg2: AnotherType[Thing],
        ...
        argN: SomeOtherType = default_value) -> ReturnType:
    """
    what the function does

    Args:
        arg1: what arg1 represents
        arg2: what arg2 represents
        ...
    """
    ...

This highlights a rather obvious duplication of code. We declare an
arguments section in code and list all the arguments, then we do so again
in the doc string.
If you want your doc string to stay in sync with the code, this duplication
is a problem. It makes more sense to tie the documentation for an argument
to said argument:

def someDescriptiveName( # what the function does
        arg1: SomeType,
            # what arg1 represents
        arg2: AnotherType[Thing],
            # what arg2 represents
        ...
        argN: SomeOtherType = default_value
            # what argN represents
        ) -> ReturnType:  # what the return value represents
    ...

I think it especially makes sense if you consider the preconditions,
postconditions, and invariants as a sort-of extension of typing in the
sense that it Typing narrows the set of acceptable values to a set of types
and contracts restrict that set further.

I hope that clarifies my thought process. I don't like the d-strings that I
proposed. I'd prefer syntax closer to Eiffel, but the above is the line of
thought I was following to arrive at d-strings.

>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181128/ef8cdd2f/attachment.html>


More information about the Python-ideas mailing list