Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork2.2k
CoreMetadata
refactor with an emphasis on documentation and reducing complexity#10675
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
…lue is overridden by introduced complexity and overhead
cloudflare-workers-and-pagesbot commentedOct 21, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Deploying pydantic-docs with |
Latest commit: | 2a08ddf |
Status: | ✅ Deploy successful! |
Preview URL: | https://1b3fed65.pydantic-docs.pages.dev |
Branch Preview URL: | https://metadata-stuck-on-a-flight.pydantic-docs.pages.dev |
codspeed-hqbot commentedOct 21, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
CodSpeed Performance ReportMerging#10675 willnot alter performanceComparing Summary
|
CoreMetadata
refactor as a consequence of a very long flightCoreMetadata
refactor with an emphasis on documentation and reducing complexity…py and migrating to json_schema.py
…fers some typing support - to be improved with migration to pydantic-core
Uh oh!
There was an error while loading.Please reload this page.
pydantic/_internal/_core_metadata.py Outdated
pydantic_js_prefer_positional_arguments: bool | None = None, | ||
pydantic_js_input_core_schema: CoreSchema | None = None, |
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.
This is probably overkill (these params specifically). Happy to remove. The others make more sense given that they need special update logic.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
def get_json_schema_update_func( | ||
json_schema_update: JsonSchemaValue, json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None | ||
) -> GetJsonSchemaFunction: | ||
def json_schema_update_func( | ||
core_schema_or_field: CoreSchemaOrField, handler: GetJsonSchemaHandler | ||
) -> JsonSchemaValue: | ||
json_schema = {**handler(core_schema_or_field), **json_schema_update} | ||
add_json_schema_extra(json_schema, json_schema_extra) | ||
return json_schema | ||
return json_schema_update_func | ||
def add_json_schema_extra( | ||
json_schema: JsonSchemaValue, json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None | ||
): | ||
if isinstance(json_schema_extra, dict): | ||
json_schema.update(to_jsonable_python(json_schema_extra)) | ||
elif callable(json_schema_extra): | ||
json_schema_extra(json_schema) | ||
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.
Also, shouldn't be injson_schema.py
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
def _update_class_schema(self, json_schema: JsonSchemaValue, cls: type[Any], config: ConfigDict) -> None: | ||
"""Update json_schema with the following, extracted from `config` and `cls`: | ||
* title | ||
* description | ||
* additional properties | ||
* json_schema_extra | ||
* deprecated | ||
Done in place, hence there's no return value as the original json_schema is mutated. | ||
No ref resolving is involved here, as that's not appropriate for simple updates. |
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.
This now has lots of the logic that was mistakenly in_generate_schema.py
schema_to_update =self.get_schema_from_definitions(JsonRef(ref)) | ||
if schema_to_update is None: | ||
raise RuntimeError(f'Cannot update undefined schema for $ref={ref}') | ||
returnself.resolve_ref_schema(schema_to_update) |
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.
Renamed and simplified. There's a function called this inGenerateJsonSchemaHandler
, and ideally, we'd get rid of that eventually, so I think this helps draw some parallels to make that simplification easier in the future.
def test_typeddict_with_extra_behavior_allow(): | ||
class Model: | ||
@classmethod | ||
def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: | ||
return core_schema.typed_dict_schema( | ||
{'a': core_schema.typed_dict_field(core_schema.str_schema())}, | ||
extra_behavior='allow', | ||
) | ||
assert TypeAdapter(Model).json_schema() == { | ||
'type': 'object', | ||
'properties': {'a': {'title': 'A', 'type': 'string'}}, | ||
'required': ['a'], | ||
'additionalProperties': True, | ||
} |
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.
So, I think we should only be pulling theextra_behavior
from the config here. If folks disagree, I can pull from the schema as well, though not sure why we have this setting there - seems redundant.
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.
extra items are going to be supported soon for typed dicts in Python. Is Pydantic support for it going to be easy to implement with these changes?
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.
1 files reviewed, 1 total issue(s) found.
Uh oh!
There was an error while loading.Please reload this page.
github-actionsbot commentedOct 23, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Coverage reportClick to see where and how coverage changed
This report was generated bypython-coverage-comment-action |
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
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.
Generally looking good to me other than the couple comments I made above about the warning message; not sure if you plan to address any of the TODO comments you added before merging, but I'm okay even if they aren't addressed.
Wasn't planning on addressing the TODOs before merging - I feel like this is big enough already, and the callable stuff would represent a pretty significant structural change. I will work on getting the fastapi CI step to green, though. |
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.
Changes look reasonable and indeed having less stuff in theGenerateSchema
class is much better.
Move the
CoreMetadata
structure to rust so that we can pull out some of thecast
calls and just get natural type checking benefits there.
Will we get any benefits to move things to Rust here? Will this introduce an extra level of indirection, making things harder to understand?
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
def test_typeddict_with_extra_behavior_allow(): | ||
class Model: | ||
@classmethod | ||
def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: | ||
return core_schema.typed_dict_schema( | ||
{'a': core_schema.typed_dict_field(core_schema.str_schema())}, | ||
extra_behavior='allow', | ||
) | ||
assert TypeAdapter(Model).json_schema() == { | ||
'type': 'object', | ||
'properties': {'a': {'title': 'A', 'type': 'string'}}, | ||
'required': ['a'], | ||
'additionalProperties': True, | ||
} |
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.
extra items are going to be supported soon for typed dicts in Python. Is Pydantic support for it going to be easy to implement with these changes?
Uh oh!
There was an error while loading.Please reload this page.
My only thought here was then we could then type |
This is where moving this to rust would be super helpful, then we can type |
Yes, I haven't removed the |
I would rather support thePEP 728 added feature and slowly deprecate pulling the info from the config (or support both, but disallow having both specified at the same time?) |
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.
I'm also fine with removingextra_behavior
for now, and re-add it in some way with PEP 728 coming soon
if TYPE_CHECKING: | ||
from ..annotated_handlers import GetJsonSchemaHandler | ||
pass |
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.
Can be removed
80353c2
intomainUh oh!
There was an error while loading.Please reload this page.
# Remove the first one once that test is fixed, see https://github.com/pydantic/pydantic/pull/10029 | ||
# the remaining tests all failing bc we now correctly add a `'deprecated': True` attribute to the JSON schema, | ||
# So it's the FastAPI tests that need to be updated here | ||
./scripts/test.sh -vv \ |
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.
FYI I think the first one is already passing and the others should be fixed byhttps://github.com/fastapi/fastapi/pull/12971/files.
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.
Awesome, thanks!
If you wouldn't mind, could you open a PR againstpydantic
to remove these once yourFastAPI
PR is merged? Thanks!!
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.
I'd be happy to! Judging by my past experience with FastAPI I wouldn't expect that to happen any time soon 🙃
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.
Thanks so much!!
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.
Uh oh!
There was an error while loading.Please reload this page.
I would recommend reviewing this commit by commit, though looking over the whole thing afterwards gives some helpful perspective as well.
Changes in this PR:
CoreMetadataHandler
structure - it offered minimal type checking benefits, some overhead, and a good amount of unnecessary complexity.CoreMetadata
dict so that it's clear what we're adding to it and why._generate_schema.py
and_known_annotated_metadata.py
and consolidate it injson_schema.py
json_schema_extra
updates, no longer build a callable ahead of time.TODOs, in the future:
CoreMetadata
structure to rust so that we can pull out some of thecast
calls and just get natural type checking benefits there. One hiccup here is that replacingmetadata: dict[str, Any]
withmetadata: CoreMetadata
, doesn't allow for arbitrary injection (say, in a custom schema), so I'm not sure what we want to do about that. It also then raises errors when we do our temporary injects for say, discriminator application, but we shouldn't be doing that anyway.pydantic_js_functions
andpydantic_js_annotation_functions