Skip to content

Instantly share code, notes, and snippets.

@mila
Created January 16, 2023 20:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mila/e3d01d7136315a0ff5397470f895db3e to your computer and use it in GitHub Desktop.
Save mila/e3d01d7136315a0ff5397470f895db3e to your computer and use it in GitHub Desktop.
Python decorator with TypeVar and @overload
import datetime as dt
from dataclasses import dataclass
from typing import Callable, Generic, Optional, TypeVar, overload
INPUT_T = TypeVar("INPUT_T")
OUTPUT_T = TypeVar("OUTPUT_T")
class pass_thru_none(Generic[INPUT_T, OUTPUT_T]):
def __init__(self, func: Callable[[INPUT_T], OUTPUT_T]) -> None:
self.func = func
@overload
def __call__(self, value: INPUT_T) -> OUTPUT_T:
...
@overload
def __call__(self, value: None) -> Optional[OUTPUT_T]:
...
def __call__(self, value: Optional[INPUT_T]) -> Optional[OUTPUT_T]:
if value is None:
return None
return self.func(value)
@pass_thru_none
def format_datetime(value: dt.datetime) -> str:
return value.isoformat()
@dataclass
class UserModel:
name: str
create_date: dt.datetime
login_date: Optional[dt.datetime]
@dataclass
class UserSchema:
name: str
createDate: str
loginDate: Optional[str]
@staticmethod
def from_model(model: UserModel) -> "UserSchema":
return UserSchema(
name=model.name,
createDate=format_datetime(model.create_date),
loginDate=format_datetime(model.login_date),
)
def test() -> None:
model = UserModel(
name="jdoe",
create_date=dt.datetime(2023, 1, 1, 0, 0),
login_date=None,
)
assert UserSchema.from_model(model) == UserSchema(
name="jdoe",
createDate="2023-01-01T00:00:00",
loginDate=None,
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment