Dissert is a granular assertion disabler. Lets you write all the inline assertions you want for development and testing, but puts the fast version into the hands of your users. All the code lives in a happy little file with an MIT license and everything, so feel free to grab it and put it wherever.
There was a long-lost feature of Python, where you could disable asserts in a file. It was cool, if before my time. I use like using asserts as in-line unit tests in C++, and ship with them disabled. A coworker asked how to do the same in Python. I'd recently seen some fun projects abusing source code encodings to fill weird niches, and this project was born that very night.
We want to litter our code with assertions, and write "always-on" unit tests.
But then your code is sluggish! Many say to use
python -O, but your user
might want asserts for something they're using your module for! Well good
news, we can eat cake and also have cake. As long as we're all good at
cleaning up our rooms (or
__pycache__ or whatever).
Absolute file-level dissertion
To disable all asserts in a file, simply set its source encoding to
> source = b"""# encoding: dissert assert False print("okay")""" > exec(source) okay
Selectable file-level dissertion
We also provide a toggle mechanism for somewhat granular control.
# encoding: dissert-select def foo(x): print("oh no, I got called") assert x is not x if foo is not None: assert foo() is not None print("okay")
Include it without asserts (delete your
> from dissert import dissert_selector > with dissert_selector(True): > import fail.py okay
Include it with asserts (delete your
> from dissert import dissert_selector > with dissert_selector(False): > import fail.py oh no, I got called AssertionError: ...
Selectable module-level dissertion
Dissert your module for release builds by renaming your
_init_.py and replacing it with a shim. Of course, it will only remove
dissert-select-encoded files, but that's more
of a feature than a drawback.
from dissert import dissert from mymodule.__package_info__ import __release__ with dissert_selector(__release__): from mymodule._init_ import *
Note that this uses a global variable under the hood, so you might want to
__pycache__ of dependent projects which also use
can be a bit of a rabbit-hole if you want very granular selectivity, as
you'll have to be extremely careful about import order.
The module also defines an
Assert function that works even in affected
files (but also goes away with
-O). Additionally, we provide an
function that emulates assertions with
if...raise and doesn't go away under
-O. In a future version, these may be accomplished through mangling the AST
rather than imports. Make a PR or open a discussion ticket if you think this
is a good/bad idea.
> source = b''' > # encoding: dissert > from dissert import Assert > assert(False, "wrong failure!") > Assert(False, "successfully failed!") > raise RuntimeError("bad success") > ''' > exec(source) ... AssertionError: successfully failed!