diff --git a/docs/modules/typing.md b/docs/modules/typing.md new file mode 100644 index 00000000..1cb7a058 --- /dev/null +++ b/docs/modules/typing.md @@ -0,0 +1,6 @@ +--- +icon: package +label: typing +--- + +Placeholder module for type hints. diff --git a/python/typing.py b/python/typing.py new file mode 100644 index 00000000..59f7dcb0 --- /dev/null +++ b/python/typing.py @@ -0,0 +1,23 @@ +class Placeholder: + def __init__(self, *args, **kwargs): + pass + def __getitem__(self, *args, **kwargs): + return self + def __call__(self, *args, **kwargs): + return self + + +_PLACEHOLDER = Placeholder() + +List = _PLACEHOLDER +Dict = _PLACEHOLDER +Tuple = _PLACEHOLDER +Set = _PLACEHOLDER +Any = _PLACEHOLDER +Union = _PLACEHOLDER +Optional = _PLACEHOLDER +Callable = _PLACEHOLDER +Type = _PLACEHOLDER + +TypeVar = _PLACEHOLDER +Self = _PLACEHOLDER \ No newline at end of file diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 7b8d3d33..363dda2b 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -1548,7 +1548,7 @@ void VM::post_init(){ add_module_base64(this); add_module_timeit(this); - for(const char* name: {"this", "functools", "collections", "heapq", "bisect", "pickle", "_long", "colorsys"}){ + for(const char* name: {"this", "functools", "collections", "heapq", "bisect", "pickle", "_long", "colorsys", "typing"}){ _lazy_modules[name] = kPythonLibs[name]; } diff --git a/tests/80_typing.py b/tests/80_typing.py new file mode 100644 index 00000000..25470996 --- /dev/null +++ b/tests/80_typing.py @@ -0,0 +1,74 @@ +from typing import Dict, Tuple, List + +bill: Dict[str, float] = { + "apple": 3.14, + "watermelon": 15.92, + "pineapple": 6.53, +} +completed: Tuple[str] = ("DONE",) +succeeded: Tuple[int, str] = (1, "SUCCESS") +statuses: Tuple[str, ...] = ( + "DONE", "SUCCESS", "FAILED", "ERROR", +) +codes: List[int] = (0, 1, -1, -2) + + +from typing import Union + +def resp200(meaningful) -> Union[int, str]: + return "OK" if meaningful else 200 + + +from typing import Self + +class Employee: + name: str = "John Doe" + age: int = 0 + + def set_name(self: Self, name) -> Self: + self.name = name + return self + +from typing import TypeVar, Type + +T = TypeVar("T") + +# "mapper" is a type, like int, str, MyClass and so on. +# "default" is an instance of type T, such as 314, "string", MyClass() and so on. +# returned is an instance of type T too. +def converter(raw, mapper: Type[T] = None, default: T = None) -> T: + try: + return mapper(raw) + except: + return default + +raw: str = '4' +result: int = converter(raw, mapper=int, default=0) + +from typing import TypeVar, Callable, Any + +T = TypeVar("T") + +def converter(raw, mapper: Callable[[Any], T] = None, default: T = None) -> T: + try: + return mapper(raw) + except: + return default + +# Callable[[Any], ReturnType] means a function declare like: +# def func(arg: Any) -> ReturnType: +# pass + +# Callable[[str, int], ReturnType] means a function declare like: +# def func(string: str, times: int) -> ReturnType: +# pass + +# Callable[..., ReturnType] means a function declare like: +# def func(*args, **kwargs) -> ReturnType: +# pass + +def is_success(value) -> bool: + return value in (0, "OK", True, "success") + +resp = {'code': 0, 'message': 'OK', 'data': []} +successed: bool = converter(resp['message'], mapper=is_success, default=False)