想要從 Apache Foundation 的 Top Level Project 開始貢獻 看到 Apache Airflow 有 38.6k 的 star 在 Data Team 看也發現 Airflow 確實也是 Data Engineering 領域的重要工具 目前也對 Python 最為熟悉
classBaseParam(Generic[T],ABC):"""Base class for filters."""def__init__(self,value:T|None=None,skip_none:bool=True)->None:self.value=valueself.attribute:ColumnElement|None=Noneself.skip_none=skip_none@abstractmethoddefto_orm(self,select:Select)->Select:passdefset_value(self,value:T|None)->Self:self.value=valuereturnself@abstractmethoddefdepends(self,*args:Any,**kwargs:Any)->Self:pass
Problem 但隨著越來越多 API 被 Migrate 到 FastAPI 的架構 每個 API 都在 common/parameters.py 的 module 加上繼承 BaseParam 的 class 有 n 個 entity 的 API 就會多出 n 個 class
所以應該要有一個通用的 Factory Pattern 並對 FastAPI 所需的 typing 綁定來產生這些 class 經過這個重構的 PR 應該 50+ 個 API 都有利用到 filter_param_factory
deffilter_param_factory(attribute:ColumnElement,_type:type,filter_option:FilterOptionEnum=FilterOptionEnum.EQUAL,filter_name:str|None=None,default_value:T|None=None,default_factory:Callable[[],T|None]|None=None,skip_none:bool=True,transform_callable:Callable[[T|None],Any]|None=None,)->Callable[[T|None],FilterParam[T|None]]:# if filter_name is not provided, use the attribute name as the defaultfilter_name=filter_nameorattribute.name# can only set either default_value or default_factoryquery=(Query(alias=filter_name,default_factory=default_factory)ifdefault_factoryisnotNoneelseQuery(alias=filter_name,default=default_value))defdepends_filter(value:T|None=query)->FilterParam[T|None]:iftransform_callable:value=transform_callable(value)returnFilterParam(attribute,value,filter_option,skip_none)# add type hint to value at runtimedepends_filter.__annotations__["value"]=_typereturndepends_filter