#further bikeshed
1 messages ยท Page 1 of 1 (latest)
more boilerplate for you to write
you could try and automate the checks with some decorator that inspects the function's type-hints, but those aren't implemented at all on CircuitPython as far as i know, so it wouldn't work on the MCU
but that might actually be useful, only spend time checking the arguments' types if you are on a computer and dont mind the extra time spent
further bikeshed
method decorators work fine in CircuitPython. But there's no support for the inspect module, and currently no way to get at most of the function info within CircuitPython.
as in... ```py
from future import annotations
import functools
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import ParamSpec, TypeVar # on older CPython, you'd want typing_extensions
P = ParamSpec("P")
R = TypeVar("R")
def safe(func: Callable[P, R]) -> Callable[P, R]:
@functools.wraps(func)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
# i dont know how this would exactly look, but you get the idea :P
for name, typ in func.annotations:
if not isinstance(name, typ): # how would we get value by name from args? :thinking:
raise TypeError("some message")
return func(*args, **kwargs)
def unsafe_variant(...): ...
safe_variant = safe(unsafe_variant)
@safe
def always_safe(...): ...
FWIW, my "personal preferences" tend to match yours for anything implementation specific - especially code that I don't expect to be used directly be anyone who isn't an experienced developer.
but yeah, as you already said, no inspect would likely break the deal (__annotations__ wouldn't be present either, AFAIK)
could make the decorator just be identity on the MCU and call it a day
if sys.implementation == "MicroPython": # or whatever the check looks like
def safe(func: Callable[P, R]) -> Callable[P, R]: return func
else:
# actual impl
but that would be as good as having nothing if you code is supposed to be run on MCUs, and not computers (which i dont know, because i lack info about your project)
anyway, leaving for a run now, will read later ๐
if you like "stupid decorator tricks', guess what this does:
@_MainAsyncLoop.reloadableMethod()
async def runAsyncSingleLoop(self:MainAsyncLoop,when:TimeInSeconds) -> None:
#...
too cursed, i'd rather not look at it ๐
deletes from sys.modules + reloads the function after X seconds?
don't knock it until you've tried it. Massive impact on productivity (for a few use cases)
deleting from sys.modules doesn't work if you want anything close to imporlib.reload(...) functionality
if you're curious, ping me when you get back from your run
but can see it being useful if your app's startup time is long
getting my "program" fully started up (including the web server) is around 45 seconds
I'd work on trying to speed that up before going the reloading way, though
and there's a while of "cold cache" style performance issues after that
Yeah, um, that is sped up.
Although it can be much quicker for a project which doesn't enable all the extra goodies (like browser/REST/WebSockets support)
(also varies based on how temperamental my WiFi router feels at the moment)
Forgot to do it ๐