Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DevLog #4

Open
tombulled opened this issue Jan 8, 2022 · 18 comments
Open

DevLog #4

tombulled opened this issue Jan 8, 2022 · 18 comments

Comments

@tombulled
Copy link
Owner

No description provided.

@tombulled

This comment was marked as outdated.

@tombulled
Copy link
Owner Author

tombulled commented Mar 16, 2022

Implement decorators:

import roster

@roster.record
def numbers(number: int) -> int:
    return number

@roster.roster(key=True)
def functions(func) -> str:
    return func.__name__

@roster.register(key=True)
def routes(path: str, method: str = 'GET') -> Route:
    return Route(path, method=method)

Draw inspiration from annotate

@tombulled
Copy link
Owner Author

tombulled commented Mar 17, 2022

Ability to change the underlying store? E.g., set instead of list, Namespace instead of dict

@tombulled
Copy link
Owner Author

tombulled commented Mar 18, 2022

record: Record[Set[int]] = Record(set())

@tombulled
Copy link
Owner Author

class Namespace(Record[T]):
    store: SimpleNamespace[T]

    def record(self, item: T, /) -> T:
        self.store[...] = ...

        return item

@tombulled
Copy link
Owner Author

tombulled commented Mar 18, 2022

def value_register(hook):
    @register
    def r(func: Callable, *args, **kwargs) -> Tuple[Callable, Any]:
        return (func, hook(*args, **kwargs))

    return r

def key_register(hook):
    @register
    def r(func: Callable, *args, **kwargs) -> Tuple[Callable, Any]:
        return (hook(*args, **kwargs), func)

    return r

@tombulled
Copy link
Owner Author

tombulled commented Mar 18, 2022

Make Register accept a single item, have to subclass to 'flatten', e.g:

class BasicRegister(Register):
    def __init__(self, factory):
        super(lambda k, v: (k, v))

        self._factory = factory

    def __call__(self, *args, **kwargs):
        return super().__call__(self._factory(*args, **kwargs))
        

@tombulled
Copy link
Owner Author

tombulled commented Mar 18, 2022

Consider:

@routes('/', method='GET')
def root(): pass
>>> routes
[Route(path='/', method='GET', target=<function root>)]

Hence, all containers should support an entrypoint

@tombulled
Copy link
Owner Author

Maybe the decorators get you to provide the entrypoint, and you can choose to specify a resolver?

E.g:

@register(resolve=lambda k, v: (v, k))
def routes(path: str, method: str='GET') -> Route:
    return Route(path=path, method=method)

@tombulled
Copy link
Owner Author

store = {}

def func(func):
    store[func] = 'FUNCTION'

    return func

def cls(cls):
    store[cls] = 'CLASS'

    return cls

@func
def foo(): pass

@cls
class Bar: pass

@tombulled
Copy link
Owner Author

routes = MapStore()

@routes.key
def route(path: str, method: str='GET') -> Route:
    return Route(path=path, method=method)

@tombulled
Copy link
Owner Author

tombulled commented Mar 19, 2022

class Record(Generic[V], ABC):
    @abstractmethod
    def record(self, value: V, /) -> None:
        ...

    def __call__(self, value: V, /) -> V:
        self.record(value)

        return value

    def item(self, func: Callable[[T], V], /) -> Callable[[T], T]:
        def proxy(item: T, /) -> T:
            self.record(func(item))

            return item

        return proxy

class ListRecord(Record[V], List[V]):
    def record(self, value: V, /) -> None:
        self.append(value)

class SetRecord(Record[V], Set[V]):
    def record(self, value: V, /) -> None:
        self.add(value)

@tombulled
Copy link
Owner Author

tombulled commented Mar 19, 2022

class Register(Generic[K, V], ABC):
    @abstractmethod
    def register(self, key: K, value: V, /) -> None:
        ...

    def __call__(self, key: K, /) -> Callable[[V], V]:
        def proxy(value: V, /) -> V:
            self.register(key, value)

            return value

        return proxy

    def key(self, func: Callable[..., K], /) -> Callable[..., Callable[[V], V]]:
        def proxy(*args: Any, **kwargs: Any) -> Callable[[V], V]:
            key: K = func(*args, **kwargs)

            def decorator(value: V, /) -> V:
                self.register(key, value)

                return value

            return decorator

        return proxy

    def value(self, func: Callable[..., V], /) -> Callable[..., Callable[[K], K]]:
        def proxy(*args: Any, **kwargs: Any) -> Callable[[K], K]:
            value: V = func(*args, **kwargs)

            def decorator(key: K, /) -> K:
                self.register(key, value)

                return key

            return decorator

        return proxy

    def entry(self, func: Callable[[T], Tuple[K, V]], /) -> Callable[[T], T]:
        def proxy(item: T, /) -> T:
            self.register(*func(item))

            return item

        return proxy

class DictRegister(Register[K, V], Dict[K, V]):
    def register(self, key: K, value: V, /) -> None:
        self[key] = value

@tombulled
Copy link
Owner Author

Implement decorators:

import roster

@roster.record
def numbers(number: int) -> int:
    return number

@roster.roster(key=True)
def functions(func) -> str:
    return func.__name__

@roster.register(key=True)
def routes(path: str, method: str = 'GET') -> Route:
    return Route(path, method=method)

Draw inspiration from annotate

Not a fan of this idea as it becomes unclear.

@tombulled
Copy link
Owner Author

record: Record[Set[int]] = Record(set())

This can't be done because a set is a Collection, whereas a list is a Sequence. Handy ref: https://docs.python.org/3/library/collections.abc.html#collections.abc.AsyncIterable

@tombulled
Copy link
Owner Author

Consider:

@routes('/', method='GET')
def root(): pass
>>> routes
[Route(path='/', method='GET', target=<function root>)]

Hence, all containers should support an entrypoint

^^^ TODO. Currently RecordABC.item expects a func that returns its first parameter - I assume the value would need to be returned instead?

@tombulled
Copy link
Owner Author

Add PyPI link to GitHub repo

@tombulled
Copy link
Owner Author

TODO: Improve typing - use param specs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant