#further bikeshed

1 messages ยท Page 1 of 1 (latest)

silver warren
#

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

celest cedar
#

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.

silver warren
#

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(...): ...

celest cedar
#

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.

silver warren
#

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 ๐Ÿ™‚

celest cedar
#

if you like "stupid decorator tricks', guess what this does:

@_MainAsyncLoop.reloadableMethod()
async def runAsyncSingleLoop(self:MainAsyncLoop,when:TimeInSeconds) -> None:
  #...
silver warren
#

too cursed, i'd rather not look at it ๐Ÿ˜›

#

deletes from sys.modules + reloads the function after X seconds?

celest cedar
#

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

silver warren
#

gladly i dont ๐Ÿ˜›

#

i just re-run my programs when needed

celest cedar
#

if you're curious, ping me when you get back from your run

silver warren
#

but can see it being useful if your app's startup time is long

celest cedar
silver warren
#

I'd work on trying to speed that up before going the reloading way, though

celest cedar
#

and there's a while of "cold cache" style performance issues after that

celest cedar
#

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)

silver warren