Description
I am working on #56, and having is some difficulty. I am using mypy, which was used in the original issue to identity files with untyped functions.
Mypy has exposed a code smell in this repo (type juggling- example below), which was originally intentionally, for the sake of saving memory in CircuitPython.
class Palette:
""" ... implemented in Adafruit_Blinka_Display.displayio """
palette = Palette.init # palette's type is a Callable (we may or not need this object later, so lets defer and pass down a reference to a Callable)
... its later, in a different file ...
def load(..., palette = None, ...):
....
palette = palette(*args) # palette's type is now Palette instance
palette.make_transparent() # mypy is now really angry, because a Callable shouldn't have any methods
There is a certain elegance to the way it was done: reuse the reference to the Callable, possibly allowing deallocation of the reference to the looked up function. But this is counter to what Mypy expects, because its a behavior commonly associated with having a bug in your code: Developer thinks they have a foo, but they accidentally overwrote it somewhere with variable name reuse.
So discuss the balance between "we want working type annotations, so the code is understandable and maintainable" and "we need to save memory through tricks, and are ok with here be dragons
". Scott wrote & I refactored a lot of the original code 3 years ago. Now looking back, It took me ~3 hours to determine what was going on, meaning there is a high barrier to entry for contributors. I'll be in the camp for "slay the dragons", and stop reusing variable names.
I know there are inline mypy decorators that can be dropped throughout the code to help get closer to mypy 'passing' by explicitly indicating when it happens, but its going to take a lot of them (every time the type changes) and be precarious to maintain. Inline decorators are intended to be used in exceptional cases, but there are many in the repo. So not a real option.
So:
- compromise on types: add best effort types, mypy never passes, so automated tooling can't be added to maintain types in the repo. Memory footprint is maintained, but the repo is still difficult to contribute to, and teaches anti-patterns.
- compromise on memory: a future release of imageload removes type juggling at the cost of slightly higher memory usage, and type checking can be added as a commit hook. Worst case is some memory constrained board that worked with a past version of the library now runs out of memory.