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/