Technical Details#
To have a summarised version of the behavior of this package, we could simply state:
We do nothing at runtime. We just fool the type checkers.
For more details, read ahead.
Instantiation#
The classes Unit and IntUnit (and their derived classes defined
by the user) are never actually instantiated. Their instantiations produce ints
and floats, as can be seen in the definitions of their __new__()
dunder method.
This should be kept in mind in order to understand that, at runtime, things
like IntUnit(2) are just ints. This means that the following
code would raise an error.
class Seconds(IntUnit):
...
x = Seconds(2)
assert isinstance(x, Seconds)
Note
The same observations apply, mutatis mutandis, to embed_unit() and
its return.
Inheriting from int (or float)#
A reasonable suggestion would be to have Unit (resp. IntUnit)
inherit from float (resp. int). For instance, this would make
the builtin sum() function not raise a warning.
However, this pushes back situations where problems may live. For example,
summing a IntUnit with an int would not raise a warning. Instead,
the sum will become an int, and this would probably result in a warning
only further down the code (for example, if the return type was an IntUnit).
Not only is this inconvenient, but we also want to deliberately consider the sum of something that has a unit with something that does not have to be an “error”.
However, if the user thinks that this behavior is desirable, it suffices to
make their units inherit from float/int like so:
from unitstools import IntUnit
class Seconds(IntUnit, int):
...
Note
It is important for IntUnit be the first class of the inheritance
due to how Python’s resolution order works.
Final Comments#
So, to reiterate: this package does nothing at runtime (with the exception of the conversion functionalities, which are just multiplications at runtime). This is by design, choice and scope of the project. For example, if an user wants to define centimeters and meters, adding them will raise an error with Pylance (which, again, is by design). If they want to make the code raise no typing errors, they should convert one of them to the other by means of a conversion function or something similar.
Note
There are tools which provide ways to work with units at runtime, e.g. Pint. This is not the scope of unitstools.