Neoteroi / BlackSheep

Fast ASGI web framework for Python
https://www.neoteroi.dev/blacksheep/
MIT License
1.8k stars 75 forks source link

PydanticModelTypeHandler rises AttributeError for EmailStr type with Pyrantic 2+ #428

Closed tyzhnenko closed 7 months ago

tyzhnenko commented 8 months ago

Describe the bug

PydanticModelTypeHandler in BlaskSheep v1.2.18 rises AttributeError for EmailStr type with Pyrantic 2+

Example app:

app = Application()

docs = OpenAPIHandler(info=Info(title="Example API", version="0.0.1"))
docs.bind_app(app)

class Email(BaseModel):
    email: EmailStr

@app.router.post("/")
def home(data: FromJSON[Email]):
    print(data)
    return f"{data}"
Traceback (most recent call last):
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/application.py", line 753, in _handle_lifespan
    await self.start()
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/application.py", line 742, in start
    await self.after_start.fire()
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/application.py", line 111, in fire
    await handler(self.context, *args, **kwargs)
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/common.py", line 394, in build_docs
    docs = self.generate_documentation(app)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 308, in generate_documentation
    info=self.info, paths=self.get_paths(app), components=self.components
                          ^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 312, in get_paths
    own_paths = self.get_routes_docs(app.router, path_prefix)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 957, in get_routes_docs
    request_body=self.get_request_body(handler),
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 671, in get_request_body
    content=self._get_body_binder_content_type(body_binder, body_examples),
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 645, in _get_body_binder_content_type
    return {
           ^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 647, in <dictcomp>
    schema=self.get_schema_by_type(body_binder.expected_type),
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 485, in get_schema_by_type
    schema = self._get_schema_by_type(child_type, type_args)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 501, in _get_schema_by_type
    return self._get_schema_for_class(object_type)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 416, in _get_schema_for_class
    for field in self.get_fields(object_type):
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 577, in get_fields
    return handler.get_type_fields(object_type)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 254, in get_type_fields
    return [
           ^
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 257, in <listcomp>
    self._open_api_v2_field_schema_to_type(
  File "/Users/user/workspace/neoteroi/BlackSheep/blacksheep/server/openapi/v3.py", line 195, in _open_api_v2_field_schema_to_type
    nullable = field_info.allow_none if field_info is not None else False
               ^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'FieldInfo' object has no attribute 'allow_none'
tyzhnenko commented 8 months ago

Just figured out that v1 doesn't support Pydantic 2+

RobertoPrevato commented 7 months ago

Hi @tyzhnenko I don´t plan to add more features to v1. A few months ago, shortly after pydantic v2 was released as stable, I made some changes to blacksheep v2 to support pydantic v2, but I don't have interest in adding the same to blacksheep v1. I'll close this ticket for now - blacksheep v2 is now stable and documented.