On Tue, Oct 5, 2021 at 9:02 AM Caleb Donovick <donovick@cs.stanford.edu> wrote:
>
> > I wonder, could this be simplified a bit, on the assumption that a
> > well-written assertion shouldn't have a problem with being executed
> > twice?
>
> While I agree as an engineering principle an assert should not have side effects
> and hence re-evaluation should be fine in most cases, it is not universal. It is possible
> for assertions to not have side effects but yet change value between evaluations if they
> interact with a shared resource such as the file system..
>
> For example consider the following assertion:
>
> assert os.path.isdir("config") and os.path.isfile("config/setup.yml")
>
> It is completely possible for the value of this expression to change between evaluations. Granted this would
> like mean their is some more significant issue with my code, however, I would like the interpreter to give me
> accurate information about why my assertion failed. Bad information is worse than no information. Like imagine
> that on the first evaluation the directory config does not exist but on the second it has been created by another process.
> A naive revaluation strategy would likely result in it pointing at the second clause and saying the assertion failed their
> when it really failed on the first clause. This would send me down a rabbit hole of debugging why setup.yml was not
> constructed properly instead of debugging why the config directory didn’t exist.
That seems like an abuse of assertions. If you have assertions that
depend on external state that can change that quickly, then the
assertion is *already useless*. What do you gain by asserting
something that might have changed by the next line of code?
> Further while it is bad engineering practices to have side effects in an assert it is completely possible.
> For example consider the following pathological example:
>
> class PathologicalFoo:
> def __init__(self):
> self._val = 0
>
> def get(self):
> old_val = self._val
> self._val = 1
> return old_val
>
> foo = PathologicalFoo()
> assert foo.get() == 1
>
Yes, side effects in assertions are always possible. If someone has
assertions with side effects, do we say that python -O is buggy, or
the assertion is buggy? In a world in which assertions might and might
not be evaluated, is it such a stretch to demand that they can be
safely reevaluated (in the same context)? Yes, it's a change to the
expectations, but one which well-designed assertions shouldn't be
bothered by.
My imagining of this is that it'd be handled when an AssertionError
reaches top level, and it'd be broadly thus:
try:
all_your_code()
except AssertionError as e:
... reevaluate etc
Meaning there are four possibilities:
1) The assertion is consistent, and the extra info is absolutely correct
2) Some OTHER exception occurs on the reevaluation. It's a chained
exception like any other.
3) No assertion failure happens (eg PathologicalFoo). Might require a
minor special case "if nothing goes wrong, print out the original" but
that's the most obvious thing to do.
4) The assertion fails in an inconsistent way, but it still fails.
You'll get the second form instead of the first.
It's only really the fourth case that would be confusing, and only if
the first evaluation actually causes the problem (otherwise it's just
an inconsistent assertion and you'd need to debug both parts anyway).
This is a pretty narrow problem, and even then, you've been shown a
weird assertion that needs to be debugged. Is it that bad to say that
an assertion that gives inconsistent results is buggy?
ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@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/GYNRJA4U5N3RMUVTWU6WJUKC46G5TOTF/
Code of Conduct: http://python.org/psf/codeofconduct/