-
Notifications
You must be signed in to change notification settings - Fork 228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix AnyUrl not being encodable #1071
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,7 +52,6 @@ | |
from pydantic.json_schema import JsonSchemaValue | ||
from pydantic_core import CoreSchema, core_schema | ||
from pydantic_core.core_schema import ( | ||
ValidationInfo, | ||
simple_ser_schema, | ||
) | ||
else: | ||
|
@@ -64,8 +63,8 @@ | |
|
||
if IS_PYDANTIC_V2: | ||
plain_validator = ( | ||
core_schema.with_info_plain_validator_function | ||
if hasattr(core_schema, "with_info_plain_validator_function") | ||
core_schema.no_info_plain_validator_function | ||
if hasattr(core_schema, "no_info_plain_validator_function") | ||
else core_schema.general_plain_validator_function | ||
) | ||
else: | ||
Comment on lines
64
to
70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In my unpublished commit (working on the Link/BackLink serialization bugfix) I simply removed all of this boilerplate code and used the Pydantic v2 |
||
|
@@ -135,12 +134,14 @@ class PydanticObjectId(ObjectId): | |
|
||
@classmethod | ||
def __get_validators__(cls): | ||
yield cls.validate | ||
yield cls._validate | ||
|
||
if IS_PYDANTIC_V2: | ||
|
||
@classmethod | ||
def validate(cls, v, _: ValidationInfo): | ||
def _validate(cls, v: str | PydanticObjectId, *_) -> PydanticObjectId: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why write the signature of the Also, the |
||
if isinstance(v, ObjectId): | ||
return PydanticObjectId(v) | ||
if isinstance(v, bytes): | ||
v = v.decode("utf-8") | ||
try: | ||
|
@@ -152,20 +153,14 @@ def validate(cls, v, _: ValidationInfo): | |
def __get_pydantic_core_schema__( | ||
cls, source_type: Any, handler: GetCoreSchemaHandler | ||
) -> CoreSchema: # type: ignore | ||
return core_schema.json_or_python_schema( | ||
python_schema=plain_validator(cls.validate), | ||
json_schema=plain_validator( | ||
cls.validate, | ||
metadata={ | ||
"pydantic_js_input_core_schema": core_schema.str_schema( | ||
pattern="^[0-9a-f]{24}$", | ||
min_length=24, | ||
max_length=24, | ||
) | ||
}, | ||
), | ||
serialization=core_schema.plain_serializer_function_ser_schema( | ||
lambda instance: str(instance), when_used="json" | ||
return core_schema.no_info_after_validator_function( | ||
cls, | ||
schema=core_schema.json_or_python_schema( | ||
json_schema=core_schema.str_schema(), | ||
python_schema=plain_validator(cls._validate), | ||
serialization=core_schema.plain_serializer_function_ser_schema( | ||
lambda instance: str(instance), when_used="json" | ||
), | ||
), | ||
) | ||
|
||
|
@@ -185,7 +180,7 @@ def __get_pydantic_json_schema__( | |
else: | ||
|
||
@classmethod | ||
def validate(cls, v): | ||
def _validate(cls, v): | ||
if isinstance(v, bytes): | ||
v = v.decode("utf-8") | ||
try: | ||
|
@@ -378,7 +373,7 @@ def serialize(value: Union[Link, BaseModel]): | |
|
||
@classmethod | ||
def build_validation(cls, handler, source_type): | ||
def validate(v: Union[DBRef, T], validation_info: ValidationInfo): | ||
def validate(v: Union[DBRef, T], *_): | ||
document_class = DocsRegistry.evaluate_fr( | ||
get_args(source_type)[0] | ||
) # type: ignore # noqa: F821 | ||
|
@@ -477,7 +472,7 @@ def __init__(self, document_class: Type[T]): | |
|
||
@classmethod | ||
def build_validation(cls, handler, source_type): | ||
def validate(v: Union[DBRef, T], field): | ||
def validate(v: Union[DBRef, T], *_): | ||
document_class = DocsRegistry.evaluate_fr( | ||
get_args(source_type)[0] | ||
) # type: ignore # noqa: F821 | ||
|
@@ -590,7 +585,7 @@ def merge_indexes( | |
def __get_pydantic_core_schema__( | ||
cls, source_type: Any, handler: GetCoreSchemaHandler | ||
) -> CoreSchema: # type: ignore | ||
def validate(v, _): | ||
def validate(v, *_): | ||
if isinstance(v, IndexModel): | ||
return IndexModelField(v) | ||
else: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,10 +33,14 @@ def get_model_fields(model): | |
|
||
|
||
def parse_model(model_type: Type[BaseModel], data: Any): | ||
if IS_PYDANTIC_V2: | ||
return model_type.model_validate(data) | ||
else: | ||
return model_type.parse_obj(data) | ||
try: | ||
if IS_PYDANTIC_V2: | ||
return model_type.model_validate(data) | ||
else: | ||
return model_type.parse_obj(data) | ||
except Exception: | ||
print(f"Error parsing model {model_type} with data {data}") | ||
model_type.model_validate(data) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the validation failed for whatever reason, why try and re-call the |
||
|
||
|
||
def get_extra_field_info(field, parameter: str): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from fastapi.openapi.utils import get_openapi | ||
|
||
from tests.fastapi.app import app | ||
|
||
|
||
def test_openapi_schema_generation(): | ||
get_openapi( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A test should ideally have some |
||
title=app.title, | ||
version=app.version, | ||
summary=app.summary, | ||
description=app.description, | ||
routes=app.routes, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,18 +18,29 @@ class SampleModel3(SampleModel2): ... | |
|
||
class TestConcurrency: | ||
async def test_without_init(self, settings): | ||
for i in range(10): | ||
cli = motor.motor_asyncio.AsyncIOMotorClient(settings.mongodb_dsn) | ||
cli.get_io_loop = asyncio.get_running_loop | ||
db = cli[settings.mongodb_db_name] | ||
await init_beanie( | ||
db, document_models=[SampleModel3, SampleModel, SampleModel2] | ||
) | ||
|
||
async def insert_find(): | ||
await SampleModel2().insert() | ||
docs = await SampleModel2.find(SampleModel2.i == 10).to_list() | ||
return docs | ||
|
||
await asyncio.gather(*[insert_find() for _ in range(10)]) | ||
await SampleModel2.delete_all() | ||
clients = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like there's too many unrelated changes now in this PR. |
||
try: | ||
for i in range(10): | ||
cli = motor.motor_asyncio.AsyncIOMotorClient( | ||
settings.mongodb_dsn | ||
) | ||
clients.append(cli) | ||
cli.get_io_loop = asyncio.get_running_loop | ||
db = cli[settings.mongodb_db_name] | ||
await init_beanie( | ||
db, | ||
document_models=[SampleModel3, SampleModel, SampleModel2], | ||
) | ||
|
||
async def insert_find(): | ||
await SampleModel2().insert() | ||
docs = await SampleModel2.find( | ||
SampleModel2.i == 10 | ||
).to_list() | ||
return docs | ||
|
||
await asyncio.gather(*[insert_find() for _ in range(10)]) | ||
await SampleModel2.delete_all() | ||
finally: | ||
for cli in clients: | ||
cli.close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way we can ensure that it is now not also broken on Pydantic v2.9.2, or some version inbetween?
Or should we always support the newer versions, or rather, test against these newer versions?
Because in the pyproject.toml we support any Pydantic v2 version.