GreaterThan, LLC

PipeLayer 0.3.1

The is only one notable change in 0.3.1: The pipelayer.Step base class was converted to an interface (a Protocol). This means for your implementation, all you need to do is create a class that implements a run method with this signature:

class MyFilter:
    def run(data: Any, context: Context) -> Any:
        ...

As I continued to work on the microservice example (using v0.3.0), I found I was not creating filters by sub-classing pipelayer.Filter. Doing so would have meant I had to create a separate class for each filter, and so any logical grouping was placed on the directory structure of the project and not the domain namespace. For example:

from service.config import AppContext

class UserRequest(Filter):

    @staticmethod
    def run(request: UserRequest, context: AppContext) -> dict:
        req = (f"{context.settings.resreq_api}/"
               f"{request.api_name}/{request.id}")
        resreq_resp = requests.get(req)
        user = json.loads(resreq_resp.content)
        context.log.info("User received from ResReq")
        return user

as opposed to this:

from service.config import AppContext
from service.model.resreq_model import ResReqModel

class MapResReq(Filter):

    @staticmethod
    def from_resreq_api_response(response: dict, 
                                 context: AppContext) -> ResReqModel:
        resreq = ResReqModel.parse_obj(response)
        return resreq

A subtle difference, but here’s how these filters would look in a pipeline:

get_user_pipeline = Pipeline(
    name="Get User Pipeline",
    steps=[
        MapRequest.from_get_user_request,
        UserRequest,                         # pipelayer.Filter
        MapResReq.from_resreq_api_response,  # static method
        MapUser.from_resreq_model
    ]
)

Since class names are generally nouns and functions are verbs, I think using a custom static method reads more clearly.

Now, one of the benefits of implementing a sub-class of Filter is that can enforce a separation of concerns. It would be very easy to create a single class with every filter in your app using the static method approach.

NOTE: If your list of filters can change at runtime, implementing the pipelayer.Step interface (or sub-classing pipelayer.Filter) is the easiest way to implement a pipeline.

in PipeLayer, PyPi, Python