I think that this is a great idea. However, pipes only point to one
character, which can be confusing. (Citation: many tracebacks before 3.10.)

I'm wondering: Could failed assertions step you into `pdb`, if they are
used for testing purposes? Could there be a way to specify different levels
of assertions? For example, maybe certain assertions are turned off with -O
or -OO, others turned off only with -O, and some that never are?
There are lots of ways `assert` could be improved, and the question is how?
What is/are the best way(s)?

--
Finn Mason

On Mon, Sep 13, 2021, 5:36 AM Juancarlo Añez <apal...@gmail.com> wrote:

> What about asserts that are not used for testing, but as classic “unless
>> there’s a bug, this should hold”?
>
>
> To me this relates to the thread about having a structured *assert* that
> doesn't go away with *-O*.
>
> My purpose when addressing *assert* was precisely the *“unless there’s a
> bug, this should hold”* kind of assertions.
>
> In that context, introducing additional yet known costs (as in this
> "power" idea), providing for different exception types (maybe all
> descending from AssertError?), and allowing for a block to prepare the
> exception, are all worth it.
>
> Introducing the new syntax for *assert* would imply zero cost for
> existing assertions.
>
> On Sun, Sep 12, 2021 at 10:28 AM Guido van Rossum <gu...@python.org>
> wrote:
>
>> This is cool.
>>
>> AFAIK pytest does something like this. How does your implementation
>> differ?
>>
>> What is your argument for making this part of the language? Why not a 3rd
>> party library?
>>
>> What about asserts that are not used for testing, but as classic “unless
>> there’s a bug, this should hold”? Those may not want to incur the extra
>> cost.
>>
>> —Guido
>>
>> On Sun, Sep 12, 2021 at 07:09 <n...@10ne.org> wrote:
>>
>>> Hi all,
>>>
>>> I’d like your comments and feedback on an enhancement that introduces
>>> power assertions to the Python language.
>>>
>>> Proposal
>>> --------
>>> This feature is inspired by a similar feature of the Groovy language[1],
>>> and is effectively a variant of the `assert` keyword.
>>> When an assertion expression evaluates to `False`, the output shows not
>>> only the failure, but also a breakdown of the evaluated expression from the
>>> inner part to the outer part.
>>>
>>> For example, a procedure like:
>>> ```python
>>> class SomeClass:
>>>     def __init__(self):
>>>         self.val = {'d': 'e'}
>>>
>>>     def __str__(self):
>>>         return str(self.val)
>>>
>>> sc = SomeClass()
>>>
>>> assert sc.val['d'] == 'f'
>>> ```
>>>
>>> Will result in the output:
>>>
>>> ```python
>>> Assertion failed:
>>>
>>> sc.val['d'] == f
>>> |  |        |
>>> |  e        False
>>> |
>>> {'d': 'e'}
>>> ```
>>> See link [2] if the formatting above is screwed up.
>>>
>>> In the output above we can see the value of every part of the expression
>>> from left to right, mapped to their expression fragment with the pipe (`|`).
>>> The number of rows that are printed depend on the value of each fragment
>>> of the expression.
>>> If the value of a fragment is longer than the actual fragment (`{'d':
>>> 'e'}` is longer than `sc`), then the next value (`e`) will be printed on a
>>> new line which will appear above.
>>> Values are appended to the same line until it overflows in length to
>>> horizontal position of the next fragment.
>>>
>>> The information that’s displayed is dictated by the type.
>>> If the type is a constant value, it will be displayed as is.
>>> If the type implements `__str__`, then the return value of that will be
>>> displayed.
>>>
>>> It is important to note that expressions with side effects are affected
>>> by this feature. This is because in order to display this information, we
>>> must store references to the instances and not just the values.
>>>
>>> Rational
>>> --------
>>> Every test boils down to the binary statement "Is this true or false?",
>>> whether you use the built-in assert keyword or a more advanced assertion
>>> method provided by a testing framework.
>>> When an assertion fails, the output is binary too — "Expected x, but got
>>> y".
>>>
>>> There are helpful libraries like Hamcrest which give you a more verbose
>>> breakdown of the difference and answer the question "What exactly is the
>>> difference between x and y?".
>>> This is extremely helpful, but it still focuses on the difference
>>> between the values.
>>>
>>> We need to keep in mind that a given state is normally an outcome of a
>>> series of states, that is, one outcome is a result of multiple conditions
>>> and causes.
>>> This is where power assertion comes in. It allows us to better
>>> understand what led to the failure.
>>>
>>> Implementation
>>> --------
>>> I’ve already built a fully functional implementation[2] of this feature
>>> as part of my Python testing framework - Nimoy[3].
>>> The current implementation uses AST manipulation to remap the expression
>>> to a data structure[4] at compile time, so that it can then be evaluated
>>> and printed[5] at runtime.
>>>
>>>
>>> [1]
>>> http://docs.groovy-lang.org/next/html/documentation/core-testing-guide.html#_power_assertions
>>> [2]
>>> https://browncoat-ninjas.github.io/nimoy/examples/#power-assertions-beta
>>> [3] https://github.com/browncoat-ninjas/nimoy/
>>> [4]
>>> https://github.com/browncoat-ninjas/nimoy/blob/develop/nimoy/ast_tools/expression_transformer.py#L77
>>> [5]
>>> https://github.com/browncoat-ninjas/nimoy/blob/develop/nimoy/assertions/power.py
>>> _______________________________________________
>>> Python-ideas mailing list -- python-ideas@python.org
>>> To unsubscribe send an email to python-ideas-le...@python.org
>>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>>> Message archived at
>>> https://mail.python.org/archives/list/python-ideas@python.org/message/T26DR4BMPG5EOB3A2ELVEWQPYRENRXHM/
>>> Code of Conduct: http://python.org/psf/codeofconduct/
>>>
>> --
>> --Guido (mobile)
>> _______________________________________________
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/EEVHXKWUMVSEPAR73WOBQM3BO7NESPBZ/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
>
> --
> Juancarlo *Añez*
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/RHXMGHUXNSHJTDBNAI3ZQGWZXN2TDFLN/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/H44YL7J35JNWOB2IWRDFJY5LA7TQJGDD/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to