Maillol / aiohttp-pydantic

Aiohttp View that validates request body and query sting regarding the annotations declared in the View method
MIT License
67 stars 21 forks source link

Creating link references #7

Open Bengreen opened 3 years ago

Bengreen commented 3 years ago

What are the plans for representing links? https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#linkObject

With some input for alignment.. I'm happy to contribute code and PR.

Maillol commented 3 years ago

This feature seems hard to provide. We should extend r200, object to write a code liking this:

class Link:
    operationId = "GetUserAddress"
    parameters = {
        "userId":  "$request.path.id"
    }

class GetUser(PydanticView):
    async def get(self, id: UUID, /) -> r200[UserSchema, Link]:
        ...

class GetUserAddress(PydanticView):
    async def get(self, id: UUID, /) -> r200[str]:
        ...

But currently we cannot write r200[type, other_data_such_as_link] and the code can become hard to read.

Perhaps is better to define the links outside the http handler annotations.

oas.define_link('/users/id', ...)

A Link needs an operationId and the operationId can be easily added in the generated OAS

1) operation_id property id is added here: https://github.com/Maillol/aiohttp-pydantic/blob/4ff9739293a28a1cbfe728521769cd4dcd682689/aiohttp_pydantic/oas/struct.py#L167

2) The oas_operation.operation_id is set with handler.__qualname__ here:

https://github.com/Maillol/aiohttp-pydantic/blob/4ff9739293a28a1cbfe728521769cd4dcd682689/aiohttp_pydantic/oas/view.py#L105

Could you create a PR to add the operation_id?

I need time to plan how to define links but proposals are welcome.

Thank you and happy new year 2021!

Maillol commented 3 years ago

I would like use typing.NewType to define which parameters can be used as input in other method.

https://docs.python.org/3.8/library/typing.html#typing.NewType

UserIdType = NewType('UserIdType', UUID)  # All parameters typed UserIdType will be linked. 

class UserToCreate(BaseModel)
    name: str
    address: str

class ReturnedUser(BaseModel):
    id: UserIdType
    name: str
    address: str

class PostUser(PydanticView):
    async def post(self, user: UserToCreate) -> r201[ReturnedUser]:
        ...

class GetUser(PydanticView):
    async def get(self, id: UserIdType, /) -> r200[ReturnedUser]:
        ...
Maillol commented 3 years ago

Hello @Bengreen

I started a MR to represente the links.

https://github.com/Maillol/aiohttp-pydantic/compare/add_oas_link_references

Do you want continue ?