Skip to content

⬆️ Increase lower bound to pydantic >=2.9.0. and fix the test suite#15139

Merged
tiangolo merged 13 commits intofastapi:masterfrom
svlandeg:fix/ci_pydantic
Mar 23, 2026
Merged

⬆️ Increase lower bound to pydantic >=2.9.0. and fix the test suite#15139
tiangolo merged 13 commits intofastapi:masterfrom
svlandeg:fix/ci_pydantic

Conversation

@svlandeg
Copy link
Copy Markdown
Member

@svlandeg svlandeg commented Mar 17, 2026

Our CI is intended to test the lowest ranges of our dependency pins as well as the highest, but it turns out this wasn't actually working well for Pydantic, and our lowest "supported" version wasn't actually being tested. Cf more digging by Yurii here.

This PR ensures that the lowest Pydantic supported version is installed when we're testing the lower bounds. From the first commit on this PR, you can see that it fails for the current master, which means that we weren't actually supporting the lower versions included in our dependency range.

Some of the issues include:

  • AttributeError: Config has no attribute val_json_bytes (only introduced in Pydantic 2.9)
    • This is easily fixed by bumping to lower bound 2.9, solving most issues in one sweep
  • Comparison assert failures in test_schema_pydantic.v2.py.
    • One is caused by additionalProperties being set to True always since Pydantic 2.11
    • Bumping to lower bound 2.11 feels a bit much right now, so I've opted to fix these tests instead, allowing multiple versions of the schema.

@svlandeg svlandeg self-assigned this Mar 17, 2026
@svlandeg svlandeg removed the internal label Mar 17, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 17, 2026

Merging this PR will not alter performance

✅ 20 untouched benchmarks


Comparing svlandeg:fix/ci_pydantic (cf6054d) with master (64feaec)

Open in CodSpeed

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 17, 2026

@svlandeg svlandeg changed the title ⬆️ Update lower Pydantic pin ⬆️ Update lower Pydantic pin to pydantic >=2.10.0. Mar 17, 2026
@svlandeg svlandeg changed the title ⬆️ Update lower Pydantic pin to pydantic >=2.10.0. ⬆️ Update lower Pydantic pin to pydantic >=2.9.0. and fix the test suite Mar 17, 2026
@svlandeg svlandeg changed the title ⬆️ Update lower Pydantic pin to pydantic >=2.9.0. and fix the test suite ⬆️ Increase lower bound to pydantic >=2.9.0. and fix the test suite Mar 17, 2026
@svlandeg svlandeg marked this pull request as ready for review March 18, 2026 10:37
@svlandeg svlandeg removed their assignment Mar 18, 2026
@svlandeg svlandeg requested a review from YuriiMotov March 18, 2026 10:38
Copy link
Copy Markdown
Member

@YuriiMotov YuriiMotov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

I only suggest we specify exact version number in the comments. So that it would be easier to track when we can remove this.


With Pydantic 2.7 we have 70 tests failing with various reasons:

Details
FAILED tests/test_no_schema_split.py::test_openapi_schema - AssertionError: assert {'components'...e Message'}}}} == {'components'...e Message'}}}}
FAILED tests/test_openapi_examples.py::test_openapi_schema - AssertionError: assert {'components'...ples'}}, ...}} == {'components'...ples'}}, ...}}
FAILED tests/test_regex_deprecated_body.py::test_openapi_schema - AssertionError: assert {'components'...ead Items'}}}} == {'components'...ead Items'}}}}
FAILED tests/test_request_params/test_body/test_optional_str.py::test_optional_str_alias_schema[/optional-alias] - KeyError: ''
FAILED tests/test_request_params/test_body/test_optional_list.py::test_optional_list_str_alias_schema[/optional-list-alias] - KeyError: ''
FAILED tests/test_request_params/test_body/test_optional_list.py::test_optional_list_alias_and_validation_alias_schema[/optional-list-alias-and-validation-alias] - KeyError: ''
FAILED tests/test_request_params/test_body/test_optional_list.py::test_optional_list_validation_alias_schema[/optional-list-validation-alias] - KeyError: ''
FAILED tests/test_request_params/test_body/test_optional_list.py::test_optional_list_str_schema[/optional-list-str] - KeyError: ''
FAILED tests/test_request_params/test_body/test_optional_str.py::test_optional_str_schema[/optional-str] - KeyError: ''
FAILED tests/test_request_params/test_body/test_optional_str.py::test_optional_alias_and_validation_alias_schema[/optional-alias-and-validation-alias] - KeyError: ''
FAILED tests/test_request_params/test_body/test_optional_str.py::test_optional_validation_alias_schema[/optional-validation-alias] - KeyError: ''
FAILED tests/test_request_params/test_file/test_list.py::test_list_alias_schema[/list-uploadfile-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_list.py::test_list_schema[/list-uploadfile] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_list.py::test_list_alias_schema[/list-bytes-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_list.py::test_list_schema[/list-bytes] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_list.py::test_list_alias_and_validation_alias_schema[/list-uploadfile-alias-and-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional.py::test_optional_schema[/optional-bytes] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional.py::test_optional_alias_schema[/optional-bytes-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_list.py::test_list_validation_alias_schema[/list-uploadfile-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_list.py::test_list_alias_and_validation_alias_schema[/list-bytes-alias-and-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional.py::test_optional_schema[/optional-uploadfile] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional.py::test_optional_alias_schema[/optional-uploadfile-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_list.py::test_list_validation_alias_schema[/list-bytes-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional.py::test_optional_validation_alias_schema[/optional-bytes-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional.py::test_optional_alias_and_validation_alias_schema[/optional-bytes-alias-and-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional.py::test_optional_alias_and_validation_alias_schema[/optional-uploadfile-alias-and-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional_list.py::test_optional_list_schema[/optional-list-bytes] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_required.py::test_required_schema[/required-bytes] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional_list.py::test_optional_list_schema[/optional-list-uploadfile] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional_list.py::test_optional_list_alias_schema[/optional-list-uploadfile-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional_list.py::test_optional_list_alias_and_validation_alias_schema[/optional-list-bytes-alias-and-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional_list.py::test_optional_validation_alias_schema[/optional-list-uploadfile-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional_list.py::test_optional_list_alias_and_validation_alias_schema[/optional-list-uploadfile-alias-and-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional_list.py::test_optional_validation_alias_schema[/optional-list-bytes-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_required.py::test_required_alias_schema[/required-uploadfile-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_required.py::test_required_validation_alias_schema[/required-bytes-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_required.py::test_required_validation_alias_schema[/required-uploadfile-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_optional.py::test_optional_validation_alias_schema[/optional-uploadfile-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_form/test_optional_list.py::test_optional_list_str_schema[/optional-list-str] - KeyError: ''
FAILED tests/test_request_params/test_form/test_optional_list.py::test_optional_list_str_alias_schema[/optional-list-alias] - KeyError: ''
FAILED tests/test_request_params/test_file/test_required.py::test_required_alias_schema[/required-bytes-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_form/test_optional_list.py::test_optional_list_validation_alias_schema[/optional-list-validation-alias] - KeyError: ''
FAILED tests/test_request_params/test_form/test_optional_list.py::test_optional_list_alias_and_validation_alias_schema[/optional-list-alias-and-validation-alias] - KeyError: ''
FAILED tests/test_request_params/test_file/test_optional_list.py::test_optional_list_alias_schema[/optional-list-bytes-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_file/test_required.py::test_required_schema[/required-uploadfile] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_form/test_optional_str.py::test_optional_str_schema[/optional-str] - KeyError: ''
FAILED tests/test_request_params/test_file/test_required.py::test_required_alias_and_validation_alias_schema[/required-bytes-alias-and-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_form/test_optional_str.py::test_optional_str_alias_schema[/optional-alias] - KeyError: ''
FAILED tests/test_request_params/test_file/test_required.py::test_required_alias_and_validation_alias_schema[/required-uploadfile-alias-and-validation-alias] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_request_params/test_form/test_optional_str.py::test_optional_validation_alias_schema[/optional-validation-alias] - KeyError: ''
FAILED tests/test_request_params/test_form/test_optional_str.py::test_optional_alias_and_validation_alias_schema[/optional-alias-and-validation-alias] - KeyError: ''
FAILED tests/test_schema_extra_examples.py::test_openapi_schema - AssertionError: assert {'components'...mple'}}, ...}} == {'components'...mple'}}, ...}}
FAILED tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py::test_post_data_in_out[tutorial001_py310] - AssertionError: assert {'data': 'U0d...: 'A plumbus'} == {'data': 'SGV...: 'A plumbus'}
FAILED tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py::test_post_data[tutorial001_py310] - AssertionError: assert {'content': '...on': 'A file'} == {'content': '...on': 'A file'}
FAILED tests/test_tutorial/test_request_files/test_tutorial001.py::test_openapi_schema[tutorial001_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_files/test_tutorial001.py::test_openapi_schema[tutorial001_an_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_files/test_tutorial001_03.py::test_openapi_schema[tutorial001_03_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_files/test_tutorial001_03.py::test_openapi_schema[tutorial001_03_an_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_files/test_tutorial002.py::test_openapi_schema[tutorial002_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_files/test_tutorial002.py::test_openapi_schema[tutorial002_an_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_files/test_tutorial003.py::test_openapi_schema[tutorial003_an_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_schema_extra_example/test_tutorial003.py::test_openapi_schema[tutorial003_py310] - AssertionError: assert {'components'...or'}}, ...}}}} == {'components'...or'}}, ...}}}}
FAILED tests/test_tutorial/test_schema_extra_example/test_tutorial003.py::test_openapi_schema[tutorial003_an_py310] - AssertionError: assert {'components'...or'}}, ...}}}} == {'components'...or'}}, ...}}}}
FAILED tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py::test_openapi_schema[tutorial001_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_files/test_tutorial001_02.py::test_openapi_schema[tutorial001_02_an_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py::test_openapi_schema[tutorial001_an_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_schema_extra_example/test_tutorial004.py::test_openapi_schema[tutorial004_py310] - AssertionError: assert {'components'...or'}}, ...}}}} == {'components'...or'}}, ...}}}}
FAILED tests/test_tutorial/test_schema_extra_example/test_tutorial004.py::test_openapi_schema[tutorial004_an_py310] - AssertionError: assert {'components'...or'}}, ...}}}} == {'components'...or'}}, ...}}}}
FAILED tests/test_tutorial/test_request_files/test_tutorial001_02.py::test_openapi_schema[tutorial001_02_py310] - AttributeError: Config has no attribute 'val_json_bytes'
FAILED tests/test_tutorial/test_request_files/test_tutorial003.py::test_openapi_schema[tutorial003_py310] - AttributeError: Config has no attribute 'val_json_bytes'

Comment thread tests/test_schema_compat_pydantic_v2.py Outdated
Comment thread tests/test_schema_compat_pydantic_v2.py Outdated
Comment thread .github/workflows/test.yml
@svlandeg
Copy link
Copy Markdown
Member Author

Note: once we merge this, we can remove the # pragma: no cover from evaluate_forwardref introduced in #15101

@YuriiMotov
Copy link
Copy Markdown
Member

Note: once we merge this, we can remove the # pragma: no cover from evaluate_forwardref introduced in #15101

I think we can do it right in this PR)

@svlandeg
Copy link
Copy Markdown
Member Author

Note: once we merge this, we can remove the # pragma: no cover from evaluate_forwardref introduced in #15101

I think we can do it right in this PR)

We can't, because that PR isn't merged yet. Whichever merges first, we can update the other one.

Copy link
Copy Markdown
Member

@tiangolo tiangolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thank you! 🙌

@tiangolo tiangolo merged commit aeb9f4b into fastapi:master Mar 23, 2026
38 checks passed
@svlandeg svlandeg deleted the fix/ci_pydantic branch March 23, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants