8000 The service methods should be passed the message objects, **not** their fields. · Issue #287 · danielgtaylor/python-betterproto · GitHub
[go: up one dir, main page]

Skip to content
The service methods should be passed the message objects, **not** their fields. #287
Closed
@FHTMitchell

Description

@FHTMitchell

I absolutely love betterproto but some of my protobuf files are very complicated with many fields and nested structures and I need to pass a lot of data around to a lot of different places. The objects I use to pass those around are, naturally, the dataclasses betterproto provides. However, betterproto splits these objects up so I end up with code that looks like

class VolService(VolServiceBase):
    async def run_vol_pipeline(
        self,
        oc_key: "OcKey",  # nested
        source: str,
        source_topic: str,
        cycle_id: str,
        cycle_time: datetime,
        chain_size: int,
        cycle_size: int,
        priced_count: int,
        unavailable_count: int,
        bad_count: int,
        snapshots: Optional[List["OptionSnapshot"]],  # repeated nested
    ) -> AsyncIterator["PyvolResult"]:
        
        req = PyvolRequest(
        oc_key,
        source,
        source_topic,
        cycle_id,
        cycle_time,
        chain_size,
        cycle_size,
        priced_count,
        unavailable_count,
        bad_count,
        snapshots,
        )

whereas if you pass the object the method signature is cleaner and users can easily extract fields anywhere down the call stack.

class VolService(VolServiceBase):
    async def run_vol_pipeline(self, request: PyvolRequest) -> AsyncIterator["PyvolResult"]:
        ...

This is actually how grpclib works! I also feel the same way about the clients. Why not allow us to pass a message object directly instead of having to do something like

async def query(req: fx.FxRequest) -> fx.FxResponse:
    service = fx.FxServiceStub(channel)  # the service stub
    asdict = {f.name: getattr(req, f.name) for f in dataclasses.fields(req)}
    return await service.run_fx_pipeline(**asdict)

It gives the user more control about how they want to handle data. It's fully typed so we don't lose anything.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0