From 7dad5a820bfe99e49a6cfaefde537e09644c2c2b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 30 Jun 2023 20:25:16 +0200 Subject: [PATCH] =?utf8?q?=E2=9C=A8=20Add=20support=20for=20OpenAPI=203.1.?= =?utf8?q?0=20(#9770)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * ✨ Update OpenAPI models for JSON Schema 2020-12 and OpenAPI 3.1.0 * ✨ Add support for summary and webhooks * ✨ Update JSON Schema for UploadFiles * ⏪️ Revert making paths optional, to ensure always correctness * ⏪️ Keep UploadFile as format: binary for compatibility with the rest of Pydantic bytes fields in v1 * ✨ Update version of OpenAPI generated to 3.1.0 * ✨ Update the version of Swagger UI * 📝 Update docs about extending OpenAPI * 📝 Update docs and links to refer to OpenAPI 3.1.0 * ✨ Update logic for handling webhooks * ♻️ Update parameter functions and classes, deprecate example and make examples the main field * ✅ Update tests for OpenAPI 3.1.0 * 📝 Update examples for OpenAPI metadata * ✅ Add and update tests for OpenAPI metadata * 📝 Add source example for webhooks * 📝 Update docs for metadata * 📝 Update docs for Schema extra * 📝 Add docs for webhooks * 🔧 Add webhooks docs to MkDocs * ✅ Update tests for extending OpenAPI * ✅ Add tests for webhooks * ♻️ Refactor generation of OpenAPI and JSON Schema with params * 📝 Update source examples for field examples * ✅ Update tests for examples * ➕ Make sure the minimum version of typing-extensions installed has deprecated() (already a dependency of Pydantic) * ✏️ Fix typo in Webhooks example code * 🔥 Remove commented out code of removed nullable field * 🗑️ Add deprecation warnings for example argument * ✅ Update tests to check for deprecation warnings * ✅ Add test for webhooks with security schemes, for coverage * 🍱 Update image for metadata, with new summary * 🍱 Add docs image for Webhooks * 📝 Update docs for webhooks, add docs UI image --- docs/en/docs/advanced/additional-responses.md | 4 +- docs/en/docs/advanced/behind-a-proxy.md | 4 +- docs/en/docs/advanced/extending-openapi.md | 16 +- docs/en/docs/advanced/openapi-callbacks.md | 4 +- docs/en/docs/advanced/openapi-webhooks.md | 51 ++ .../path-operation-advanced-configuration.md | 2 +- .../en/docs/img/tutorial/metadata/image01.png | Bin 90062 -> 86437 bytes .../img/tutorial/openapi-webhooks/image01.png | Bin 0 -> 86925 bytes docs/en/docs/tutorial/first-steps.md | 2 +- docs/en/docs/tutorial/metadata.md | 15 +- docs/en/docs/tutorial/path-params.md | 2 +- docs/en/docs/tutorial/schema-extra-example.md | 118 ++-- docs/en/mkdocs.yml | 1 + docs_src/extending_openapi/tutorial001.py | 3 +- docs_src/metadata/tutorial001.py | 1 + docs_src/metadata/tutorial001_1.py | 38 ++ docs_src/openapi_webhooks/tutorial001.py | 25 + docs_src/schema_extra_example/tutorial001.py | 14 +- .../schema_extra_example/tutorial001_py310.py | 14 +- docs_src/schema_extra_example/tutorial002.py | 8 +- .../schema_extra_example/tutorial002_py310.py | 8 +- docs_src/schema_extra_example/tutorial003.py | 14 +- .../schema_extra_example/tutorial003_an.py | 14 +- .../tutorial003_an_py310.py | 14 +- .../tutorial003_an_py39.py | 14 +- .../schema_extra_example/tutorial003_py310.py | 14 +- docs_src/schema_extra_example/tutorial004.py | 10 +- .../schema_extra_example/tutorial004_an.py | 10 +- .../tutorial004_an_py310.py | 10 +- .../tutorial004_an_py39.py | 10 +- .../schema_extra_example/tutorial004_py310.py | 10 +- fastapi/applications.py | 8 +- fastapi/openapi/docs.py | 4 +- fastapi/openapi/models.py | 93 ++- fastapi/openapi/utils.py | 38 +- fastapi/param_functions.py | 73 ++- fastapi/params.py | 108 +++- pyproject.toml | 1 + tests/test_additional_properties.py | 2 +- tests/test_additional_response_extra.py | 2 +- tests/test_additional_responses_bad.py | 2 +- ...onal_responses_custom_model_in_callback.py | 2 +- ...tional_responses_custom_validationerror.py | 2 +- ...ional_responses_default_validationerror.py | 2 +- ...est_additional_responses_response_class.py | 2 +- tests/test_additional_responses_router.py | 2 +- tests/test_annotated.py | 2 +- tests/test_application.py | 2 +- tests/test_custom_route_class.py | 2 +- tests/test_dependency_duplicates.py | 2 +- tests/test_deprecated_openapi_prefix.py | 2 +- tests/test_duplicate_models_openapi.py | 2 +- tests/test_enforce_once_required_parameter.py | 2 +- tests/test_extra_routes.py | 2 +- tests/test_filter_pydantic_sub_model.py | 2 +- tests/test_generate_unique_id_function.py | 14 +- tests/test_get_request_body.py | 2 +- .../test_include_router_defaults_overrides.py | 2 +- .../test_modules_same_name_body/test_main.py | 2 +- tests/test_multi_body_errors.py | 2 +- tests/test_multi_query_errors.py | 2 +- .../test_openapi_query_parameter_extension.py | 2 +- tests/test_openapi_route_extensions.py | 2 +- tests/test_openapi_servers.py | 2 +- tests/test_param_in_path_and_dependency.py | 2 +- tests/test_param_include_in_schema.py | 2 +- tests/test_put_no_body.py | 2 +- tests/test_repeated_dependency_schema.py | 2 +- tests/test_repeated_parameter_alias.py | 2 +- tests/test_reponse_set_reponse_code_empty.py | 2 +- ...test_request_body_parameters_media_type.py | 2 +- tests/test_response_by_alias.py | 2 +- tests/test_response_class_no_mediatype.py | 2 +- tests/test_response_code_no_body.py | 2 +- ...est_response_model_as_return_annotation.py | 2 +- tests/test_response_model_sub_types.py | 2 +- tests/test_schema_extra_examples.py | 572 ++++++++---------- tests/test_security_api_key_cookie.py | 2 +- ...est_security_api_key_cookie_description.py | 2 +- .../test_security_api_key_cookie_optional.py | 2 +- tests/test_security_api_key_header.py | 2 +- ...est_security_api_key_header_description.py | 2 +- .../test_security_api_key_header_optional.py | 2 +- tests/test_security_api_key_query.py | 2 +- ...test_security_api_key_query_description.py | 2 +- tests/test_security_api_key_query_optional.py | 2 +- tests/test_security_http_base.py | 2 +- tests/test_security_http_base_description.py | 2 +- tests/test_security_http_base_optional.py | 2 +- tests/test_security_http_basic_optional.py | 2 +- tests/test_security_http_basic_realm.py | 2 +- ...t_security_http_basic_realm_description.py | 2 +- tests/test_security_http_bearer.py | 2 +- .../test_security_http_bearer_description.py | 2 +- tests/test_security_http_bearer_optional.py | 2 +- tests/test_security_http_digest.py | 2 +- .../test_security_http_digest_description.py | 2 +- tests/test_security_http_digest_optional.py | 2 +- tests/test_security_oauth2.py | 2 +- ...curity_oauth2_authorization_code_bearer.py | 2 +- ...2_authorization_code_bearer_description.py | 2 +- tests/test_security_oauth2_optional.py | 2 +- ...st_security_oauth2_optional_description.py | 2 +- ...ecurity_oauth2_password_bearer_optional.py | 2 +- ...h2_password_bearer_optional_description.py | 2 +- tests/test_security_openid_connect.py | 2 +- ...est_security_openid_connect_description.py | 2 +- .../test_security_openid_connect_optional.py | 2 +- tests/test_starlette_exception.py | 2 +- tests/test_sub_callbacks.py | 2 +- tests/test_tuples.py | 2 +- .../test_tutorial001.py | 2 +- .../test_tutorial002.py | 2 +- .../test_tutorial003.py | 2 +- .../test_tutorial004.py | 2 +- .../test_tutorial001.py | 2 +- .../test_behind_a_proxy/test_tutorial001.py | 2 +- .../test_behind_a_proxy/test_tutorial002.py | 2 +- .../test_behind_a_proxy/test_tutorial003.py | 2 +- .../test_behind_a_proxy/test_tutorial004.py | 2 +- .../test_bigger_applications/test_main.py | 2 +- .../test_bigger_applications/test_main_an.py | 2 +- .../test_main_an_py39.py | 2 +- .../test_body/test_tutorial001.py | 2 +- .../test_body/test_tutorial001_py310.py | 2 +- .../test_body_fields/test_tutorial001.py | 2 +- .../test_body_fields/test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py310.py | 2 +- .../test_tutorial001_an_py39.py | 2 +- .../test_tutorial001_py310.py | 2 +- .../test_tutorial001.py | 2 +- .../test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py310.py | 2 +- .../test_tutorial001_an_py39.py | 2 +- .../test_tutorial001_py310.py | 2 +- .../test_tutorial003.py | 2 +- .../test_tutorial003_an.py | 2 +- .../test_tutorial003_an_py310.py | 2 +- .../test_tutorial003_an_py39.py | 2 +- .../test_tutorial003_py310.py | 2 +- .../test_tutorial009.py | 2 +- .../test_tutorial009_py39.py | 2 +- .../test_body_updates/test_tutorial001.py | 2 +- .../test_tutorial001_py310.py | 2 +- .../test_tutorial001_py39.py | 2 +- .../test_tutorial001.py | 2 +- .../test_cookie_params/test_tutorial001.py | 2 +- .../test_cookie_params/test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py310.py | 2 +- .../test_tutorial001_an_py39.py | 2 +- .../test_tutorial001_py310.py | 2 +- .../test_custom_response/test_tutorial001.py | 2 +- .../test_custom_response/test_tutorial001b.py | 2 +- .../test_custom_response/test_tutorial004.py | 2 +- .../test_custom_response/test_tutorial005.py | 2 +- .../test_custom_response/test_tutorial006.py | 2 +- .../test_custom_response/test_tutorial006b.py | 2 +- .../test_custom_response/test_tutorial006c.py | 2 +- .../test_dataclasses/test_tutorial001.py | 2 +- .../test_dataclasses/test_tutorial002.py | 2 +- .../test_dataclasses/test_tutorial003.py | 2 +- .../test_dependencies/test_tutorial001.py | 2 +- .../test_dependencies/test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py310.py | 2 +- .../test_tutorial001_an_py39.py | 2 +- .../test_tutorial001_py310.py | 2 +- .../test_dependencies/test_tutorial004.py | 2 +- .../test_dependencies/test_tutorial004_an.py | 2 +- .../test_tutorial004_an_py310.py | 2 +- .../test_tutorial004_an_py39.py | 2 +- .../test_tutorial004_py310.py | 2 +- .../test_dependencies/test_tutorial006.py | 2 +- .../test_dependencies/test_tutorial006_an.py | 2 +- .../test_tutorial006_an_py39.py | 2 +- .../test_dependencies/test_tutorial012.py | 2 +- .../test_dependencies/test_tutorial012_an.py | 2 +- .../test_tutorial012_an_py39.py | 2 +- .../test_events/test_tutorial001.py | 2 +- .../test_events/test_tutorial002.py | 2 +- .../test_events/test_tutorial003.py | 2 +- .../test_tutorial001.py | 5 +- .../test_extra_data_types/test_tutorial001.py | 2 +- .../test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py310.py | 2 +- .../test_tutorial001_an_py39.py | 2 +- .../test_tutorial001_py310.py | 2 +- .../test_extra_models/test_tutorial003.py | 2 +- .../test_tutorial003_py310.py | 2 +- .../test_extra_models/test_tutorial004.py | 2 +- .../test_tutorial004_py39.py | 2 +- .../test_extra_models/test_tutorial005.py | 2 +- .../test_tutorial005_py39.py | 2 +- .../test_first_steps/test_tutorial001.py | 2 +- .../test_generate_clients/test_tutorial003.py | 2 +- .../test_handling_errors/test_tutorial001.py | 2 +- .../test_handling_errors/test_tutorial002.py | 2 +- .../test_handling_errors/test_tutorial003.py | 2 +- .../test_handling_errors/test_tutorial004.py | 2 +- .../test_handling_errors/test_tutorial005.py | 2 +- .../test_handling_errors/test_tutorial006.py | 2 +- .../test_header_params/test_tutorial001.py | 2 +- .../test_header_params/test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py310.py | 2 +- .../test_tutorial001_py310.py | 2 +- .../test_header_params/test_tutorial002.py | 2 +- .../test_header_params/test_tutorial002_an.py | 2 +- .../test_tutorial002_an_py310.py | 2 +- .../test_tutorial002_an_py39.py | 2 +- .../test_tutorial002_py310.py | 2 +- .../test_header_params/test_tutorial003.py | 2 +- .../test_header_params/test_tutorial003_an.py | 2 +- .../test_tutorial003_an_py310.py | 2 +- .../test_tutorial003_an_py39.py | 2 +- .../test_tutorial003_py310.py | 2 +- .../test_metadata/test_tutorial001.py | 3 +- .../test_metadata/test_tutorial001_1.py | 49 ++ .../test_metadata/test_tutorial004.py | 2 +- .../test_tutorial001.py | 2 +- .../test_openapi_webhooks/__init__.py | 0 .../test_openapi_webhooks/test_tutorial001.py | 117 ++++ .../test_tutorial001.py | 2 +- .../test_tutorial002.py | 2 +- .../test_tutorial003.py | 2 +- .../test_tutorial004.py | 2 +- .../test_tutorial005.py | 2 +- .../test_tutorial006.py | 2 +- .../test_tutorial007.py | 2 +- .../test_tutorial002b.py | 2 +- .../test_tutorial005.py | 2 +- .../test_tutorial005_py310.py | 2 +- .../test_tutorial005_py39.py | 2 +- .../test_tutorial006.py | 2 +- .../test_path_params/test_tutorial004.py | 2 +- .../test_path_params/test_tutorial005.py | 2 +- .../test_query_params/test_tutorial005.py | 2 +- .../test_query_params/test_tutorial006.py | 2 +- .../test_tutorial006_py310.py | 2 +- .../test_tutorial010.py | 2 +- .../test_tutorial010_an.py | 2 +- .../test_tutorial010_an_py310.py | 2 +- .../test_tutorial010_an_py39.py | 2 +- .../test_tutorial010_py310.py | 2 +- .../test_tutorial011.py | 2 +- .../test_tutorial011_an.py | 2 +- .../test_tutorial011_an_py310.py | 2 +- .../test_tutorial011_an_py39.py | 2 +- .../test_tutorial011_py310.py | 2 +- .../test_tutorial011_py39.py | 2 +- .../test_tutorial012.py | 2 +- .../test_tutorial012_an.py | 2 +- .../test_tutorial012_an_py39.py | 2 +- .../test_tutorial012_py39.py | 2 +- .../test_tutorial013.py | 2 +- .../test_tutorial013_an.py | 2 +- .../test_tutorial013_an_py39.py | 2 +- .../test_tutorial014.py | 2 +- .../test_tutorial014_an.py | 2 +- .../test_tutorial014_an_py310.py | 2 +- .../test_tutorial014_an_py39.py | 2 +- .../test_tutorial014_py310.py | 2 +- .../test_request_files/test_tutorial001.py | 2 +- .../test_request_files/test_tutorial001_02.py | 2 +- .../test_tutorial001_02_an.py | 2 +- .../test_tutorial001_02_an_py310.py | 2 +- .../test_tutorial001_02_an_py39.py | 2 +- .../test_tutorial001_02_py310.py | 2 +- .../test_request_files/test_tutorial001_03.py | 2 +- .../test_tutorial001_03_an.py | 2 +- .../test_tutorial001_03_an_py39.py | 2 +- .../test_request_files/test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py39.py | 2 +- .../test_request_files/test_tutorial002.py | 2 +- .../test_request_files/test_tutorial002_an.py | 2 +- .../test_tutorial002_an_py39.py | 2 +- .../test_tutorial002_py39.py | 2 +- .../test_request_files/test_tutorial003.py | 2 +- .../test_request_files/test_tutorial003_an.py | 2 +- .../test_tutorial003_an_py39.py | 2 +- .../test_tutorial003_py39.py | 2 +- .../test_request_forms/test_tutorial001.py | 2 +- .../test_request_forms/test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py39.py | 2 +- .../test_tutorial001.py | 2 +- .../test_tutorial001_an.py | 2 +- .../test_tutorial001_an_py39.py | 2 +- .../test_response_model/test_tutorial003.py | 2 +- .../test_tutorial003_01.py | 2 +- .../test_tutorial003_01_py310.py | 2 +- .../test_tutorial003_02.py | 2 +- .../test_tutorial003_03.py | 2 +- .../test_tutorial003_05.py | 2 +- .../test_tutorial003_05_py310.py | 2 +- .../test_tutorial003_py310.py | 2 +- .../test_response_model/test_tutorial004.py | 2 +- .../test_tutorial004_py310.py | 2 +- .../test_tutorial004_py39.py | 2 +- .../test_response_model/test_tutorial005.py | 2 +- .../test_tutorial005_py310.py | 2 +- .../test_response_model/test_tutorial006.py | 2 +- .../test_tutorial006_py310.py | 2 +- .../test_tutorial004.py | 51 +- .../test_tutorial004_an.py | 51 +- .../test_tutorial004_an_py310.py | 51 +- .../test_tutorial004_an_py39.py | 51 +- .../test_tutorial004_py310.py | 51 +- .../test_security/test_tutorial001.py | 2 +- .../test_security/test_tutorial001_an.py | 2 +- .../test_security/test_tutorial001_an_py39.py | 2 +- .../test_security/test_tutorial003.py | 2 +- .../test_security/test_tutorial003_an.py | 2 +- .../test_tutorial003_an_py310.py | 2 +- .../test_security/test_tutorial003_an_py39.py | 2 +- .../test_security/test_tutorial003_py310.py | 2 +- .../test_security/test_tutorial005.py | 2 +- .../test_security/test_tutorial005_an.py | 2 +- .../test_tutorial005_an_py310.py | 2 +- .../test_security/test_tutorial005_an_py39.py | 2 +- .../test_security/test_tutorial005_py310.py | 2 +- .../test_security/test_tutorial005_py39.py | 2 +- .../test_security/test_tutorial006.py | 2 +- .../test_security/test_tutorial006_an.py | 2 +- .../test_security/test_tutorial006_an_py39.py | 2 +- .../test_sql_databases/test_sql_databases.py | 2 +- .../test_sql_databases_middleware.py | 2 +- .../test_sql_databases_middleware_py310.py | 2 +- .../test_sql_databases_middleware_py39.py | 2 +- .../test_sql_databases_py310.py | 2 +- .../test_sql_databases_py39.py | 2 +- .../test_sql_databases_peewee.py | 2 +- .../test_sub_applications/test_tutorial001.py | 4 +- tests/test_tutorial/test_testing/test_main.py | 2 +- .../test_testing/test_tutorial001.py | 2 +- tests/test_union_body.py | 2 +- tests/test_union_inherited_body.py | 2 +- tests/test_webhooks_security.py | 126 ++++ 335 files changed, 1564 insertions(+), 922 deletions(-) create mode 100644 docs/en/docs/advanced/openapi-webhooks.md create mode 100644 docs/en/docs/img/tutorial/openapi-webhooks/image01.png create mode 100644 docs_src/metadata/tutorial001_1.py create mode 100644 docs_src/openapi_webhooks/tutorial001.py create mode 100644 tests/test_tutorial/test_metadata/test_tutorial001_1.py create mode 100644 tests/test_tutorial/test_openapi_webhooks/__init__.py create mode 100644 tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py create mode 100644 tests/test_webhooks_security.py diff --git a/docs/en/docs/advanced/additional-responses.md b/docs/en/docs/advanced/additional-responses.md index dca5f6a985..624036ce97 100644 --- a/docs/en/docs/advanced/additional-responses.md +++ b/docs/en/docs/advanced/additional-responses.md @@ -236,5 +236,5 @@ For example: To see what exactly you can include in the responses, you can check these sections in the OpenAPI specification: -* OpenAPI Responses Object, it includes the `Response Object`. -* OpenAPI Response Object, you can include anything from this directly in each response inside your `responses` parameter. Including `description`, `headers`, `content` (inside of this is that you declare different media types and JSON Schemas), and `links`. +* OpenAPI Responses Object, it includes the `Response Object`. +* OpenAPI Response Object, you can include anything from this directly in each response inside your `responses` parameter. Including `description`, `headers`, `content` (inside of this is that you declare different media types and JSON Schemas), and `links`. diff --git a/docs/en/docs/advanced/behind-a-proxy.md b/docs/en/docs/advanced/behind-a-proxy.md index 03198851a3..e7af77f3da 100644 --- a/docs/en/docs/advanced/behind-a-proxy.md +++ b/docs/en/docs/advanced/behind-a-proxy.md @@ -46,7 +46,7 @@ The docs UI would also need the OpenAPI schema to declare that this API `server` ```JSON hl_lines="4-8" { - "openapi": "3.0.2", + "openapi": "3.1.0", // More stuff here "servers": [ { @@ -298,7 +298,7 @@ Will generate an OpenAPI schema like: ```JSON hl_lines="5-7" { - "openapi": "3.0.2", + "openapi": "3.1.0", // More stuff here "servers": [ { diff --git a/docs/en/docs/advanced/extending-openapi.md b/docs/en/docs/advanced/extending-openapi.md index 36619696b5..c47f939af6 100644 --- a/docs/en/docs/advanced/extending-openapi.md +++ b/docs/en/docs/advanced/extending-openapi.md @@ -29,10 +29,14 @@ And that function `get_openapi()` receives as parameters: * `title`: The OpenAPI title, shown in the docs. * `version`: The version of your API, e.g. `2.5.0`. -* `openapi_version`: The version of the OpenAPI specification used. By default, the latest: `3.0.2`. -* `description`: The description of your API. +* `openapi_version`: The version of the OpenAPI specification used. By default, the latest: `3.1.0`. +* `summary`: A short summary of the API. +* `description`: The description of your API, this can include markdown and will be shown in the docs. * `routes`: A list of routes, these are each of the registered *path operations*. They are taken from `app.routes`. +!!! info + The parameter `summary` is available in OpenAPI 3.1.0 and above, supported by FastAPI 0.99.0 and above. + ## Overriding the defaults Using the information above, you can use the same utility function to generate the OpenAPI schema and override each part that you need. @@ -51,7 +55,7 @@ First, write all your **FastAPI** application as normally: Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function: -```Python hl_lines="2 15-20" +```Python hl_lines="2 15-21" {!../../../docs_src/extending_openapi/tutorial001.py!} ``` @@ -59,7 +63,7 @@ Then, use the same utility function to generate the OpenAPI schema, inside a `cu Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema: -```Python hl_lines="21-23" +```Python hl_lines="22-24" {!../../../docs_src/extending_openapi/tutorial001.py!} ``` @@ -71,7 +75,7 @@ That way, your application won't have to generate the schema every time a user o It will be generated only once, and then the same cached schema will be used for the next requests. -```Python hl_lines="13-14 24-25" +```Python hl_lines="13-14 25-26" {!../../../docs_src/extending_openapi/tutorial001.py!} ``` @@ -79,7 +83,7 @@ It will be generated only once, and then the same cached schema will be used for Now you can replace the `.openapi()` method with your new function. -```Python hl_lines="28" +```Python hl_lines="29" {!../../../docs_src/extending_openapi/tutorial001.py!} ``` diff --git a/docs/en/docs/advanced/openapi-callbacks.md b/docs/en/docs/advanced/openapi-callbacks.md index 71924ce8b2..37339eae57 100644 --- a/docs/en/docs/advanced/openapi-callbacks.md +++ b/docs/en/docs/advanced/openapi-callbacks.md @@ -103,11 +103,11 @@ It should look just like a normal FastAPI *path operation*: There are 2 main differences from a normal *path operation*: * It doesn't need to have any actual code, because your app will never call this code. It's only used to document the *external API*. So, the function could just have `pass`. -* The *path* can contain an OpenAPI 3 expression (see more below) where it can use variables with parameters and parts of the original request sent to *your API*. +* The *path* can contain an OpenAPI 3 expression (see more below) where it can use variables with parameters and parts of the original request sent to *your API*. ### The callback path expression -The callback *path* can have an OpenAPI 3 expression that can contain parts of the original request sent to *your API*. +The callback *path* can have an OpenAPI 3 expression that can contain parts of the original request sent to *your API*. In this case, it's the `str`: diff --git a/docs/en/docs/advanced/openapi-webhooks.md b/docs/en/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000..63cbdc6103 --- /dev/null +++ b/docs/en/docs/advanced/openapi-webhooks.md @@ -0,0 +1,51 @@ +# OpenAPI Webhooks + +There are cases where you want to tell your API **users** that your app could call *their* app (sending a request) with some data, normally to **notify** of some type of **event**. + +This means that instead of the normal process of your users sending requests to your API, it's **your API** (or your app) that could **send requests to their system** (to their API, their app). + +This is normally called a **webhook**. + +## Webhooks steps + +The process normally is that **you define** in your code what is the message that you will send, the **body of the request**. + +You also define in some way at which **moments** your app will send those requests or events. + +And **your users** define in some way (for example in a web dashboard somewhere) the **URL** where your app should send those requests. + +All the **logic** about how to register the URLs for webhooks and the code to actually send those requests is up to you. You write it however you want to in **your own code**. + +## Documenting webhooks with **FastAPI** and OpenAPI + +With **FastAPI**, using OpenAPI, you can define the names of these webhooks, the types of HTTP operations that your app can send (e.g. `POST`, `PUT`, etc.) and the request **bodies** that your app would send. + +This can make it a lot easier for your users to **implement their APIs** to receive your **webhook** requests, they might even be able to autogenerate some of their own API code. + +!!! info + Webhooks are available in OpenAPI 3.1.0 and above, supported by FastAPI `0.99.0` and above. + +## An app with webhooks + +When you create a **FastAPI** application, there is a `webhooks` attribute that you can use to define *webhooks*, the same way you would define *path operations*, for example with `@app.webhooks.post()`. + +```Python hl_lines="9-13 36-53" +{!../../../docs_src/openapi_webhooks/tutorial001.py!} +``` + +The webhooks that you define will end up in the **OpenAPI** schema and the automatic **docs UI**. + +!!! info + The `app.webhooks` object is actually just an `APIRouter`, the same type you would use when structuring your app with multiple files. + +Notice that with webhooks you are actually not declaring a *path* (like `/items/`), the text you pass there is just an **identifier** of the webhook (the name of the event), for example in `@app.webhooks.post("new-subscription")`, the webhook name is `new-subscription`. + +This is because it is expected that **your users** would define the actual **URL path** where they want to receive the webhook request in some other way (e.g. a web dashboard). + +### Check the docs + +Now you can start your app with Uvicorn and go to http://127.0.0.1:8000/docs. + +You will see your docs have the normal *path operations* and now also some **webhooks**: + + diff --git a/docs/en/docs/advanced/path-operation-advanced-configuration.md b/docs/en/docs/advanced/path-operation-advanced-configuration.md index a1c902ef2c..6d9a5fe708 100644 --- a/docs/en/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/en/docs/advanced/path-operation-advanced-configuration.md @@ -97,7 +97,7 @@ And if you see the resulting OpenAPI (at `/openapi.json` in your API), you will ```JSON hl_lines="22" { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "FastAPI", "version": "0.1.0" diff --git a/docs/en/docs/img/tutorial/metadata/image01.png b/docs/en/docs/img/tutorial/metadata/image01.png index b7708a3fd98ad2170d880781896623ec8ed80204..4146a8607b5b4278b9d826c5d9e45ee9ff183ce3 100644 GIT binary patch literal 86437 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

brjF2aNDYJxK4|~sL@2iVvN@(A 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 v$rV{nl0h+WbK* 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

4DR;kh-kH#XMSOW? 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⪙6ziEE``II;Ag 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%0D%?G&;zjG?$)Oy7+?(B7EazRq-tDMR z0Ud0<$u3W@5RyaR(N({lcOg#=Q9k(bzDfDEPJnF-SEu?A3e&F()Y}`Sb5phH_gB+Y zI_DPlYyM~`5q_jVu=?eaNvq>91Ne5S7UwL0yJN8a<>;kPB>j)iH-L7Gc%v!(KG2Hb z#*W-=c$_DG)cd{5qk=tiDhf}I5FfdFG1U=h(eUZj9rU9)j)AIo$2C`Ay=n`Y*a}Gp z`2Uz|zU{(;2KqvUYMnhv`&xG0uTimF@Y>;CcBI(!z41nge@c$kiu#4E-R4vEIq{G0 zhAZz5UNOIY@sjGq(#_%q>E%YQvu)14G3*a?e7*%dVwK+W?Ck8>FRvR}R)3RWxVT*D z-7h!a%SZCIPo6f-ZMW>YHJN!=C+=WRO;4XZYm(E8IZ+HT(q&)zu2gSM-*oSSrf1q= z@4uDrr-;u@^MB%Mf4ttcdiR@o&Z{TRw)`i5%avupfgM~7E?@6?JM#0($jV*?jk6R* zqpl8YE4;pa=A=oV;@3wn&FcL#-@BFVY1?(oVjvQ1ah}fwcpAM3Oo%_TjdS( zV|FYNgI+mQ?R9Zc+?%_bZx=9p_@dzfSvuEbM=enEk2R;s5AUIO_KkcX>T`Er7MVm$|DIn$~9zcXumS%P)WM z(9oWvDapP0=)HKj;^qHQyX*dJoF!gWU=I%uD_r4`(zCo!>W^QrpP}~>l@#hd87{Zb zUqMRE+FVurYH21nqG4a-lla|K;z_>~76xSy=9962{TiyDb$s>%I(7)YqAt4AsjOG-&CR0X83!yrN?yA!!# zEqT-5mX35rzlT2@@6xUKDEZO@=Gz@h)32wU?Pw{uvkU!izpHHdIOra z(p9%DEq!yR2AYPYfXU&%caqyWygW_dFp{!+b`QL!!$2VIL%@L`IFW7)b#J%U?^m|z z1rGi-OGoAVQamqT{;I4*OE05cHakCK6cxp)(T}nF*DkiB`}^yT4#a1JzHa*;Ei7A} z($MsSzyV>ntYG4fhr;~4sOO0qWVA@jP!Ua-l0cM}NB~+8pPU@AbW~i0_|u6Q5?aT+ zpRucR(U^qKdl)=w%`D{65bYW(K9Y4M=G2hxvI)?(`s*7US`Kxt_W|)fJ8fPiZ}~ou z0Z%{x*Z6NT*^_8S8X9j53?9!~sAxZjo}NDE=FV7Nb}-_hXlh!RcYwG@NP(0{p{kj; zoD_sgl4m{s(7@E&J{k4q5#BZ!$iL0ZJQIC>X(|2YqCKy5xi3m2s(a6UR_|^rKE~~8 zpoA|~_2b8n|0E|Xo_~w-zuhC4oC>VqY+0B~hO^4d=T&EVt@@~D`SVKgwmzv@NbU|J zuCbjWH@OArIyV{FTn67ygiQ^MjjazB+?i}%t?L?%-QS(KMN&&89UdOWmmAuq1!LkC zlKeGIZHU=gUiS$HUWa0sG{XRl&b}(&j%M&X(s(#&j(|;#3neMa$(_RQkgd1-A0;Iv zcc+V(H=UYN)ur!<8{Vh9Q&8wr3Mh|>A-)H~-S3-M%ZENhT=|R^Qz!}=j8HeDa^iq^`|n)gR9o4T{Y#V3C4Vkz%~2Y`P$YN&&Q`p z=&=nS&Pk@^}E z+1zkvD_LWGpIlftw(NTVBgNngs+%9$W`-;_x{#LWRzQ{j?c4jYy63BKhK!Gyo_ntJ zM~iiv`S*T_kYU}7N(4Y1nTWE2^Jv|iZkw?EHoR;vCa5uTkF-V zgu`MjRnT|R6EoQ9FlzsI?CuRJG6Zz7Wsiy4gXV{mUhX6rI$;z(?o_`Y2U7{zvDDby z>w<0`{6Q^v&Ln`UVQF+zT~dF?HKNz`En8@YuOeHkxcDJep^Lh62_=Rj2WQuj=gcmW zkO;4LZZ2}vx_iz6M{2EbhzqR9ujivLxYqCj^f`bs}2NoC@80;@!mQ_WGxow}#WHg~|ZEtJ0Nq>6B zWN!Y;|7yl)QBm&nW+!{HMR(jl*4x9%%BsRA2Z0h`xXL++7*5DwG8v8|B z-9aOCksmdqe=;-QfB5jkxH&`DvJKx4`m?n)Dd+JW+&^nO7cZGmzE!_62O4f)LNQ$G~epxZ5zE>A!4SH^Jm@zI|FtvHF$)6>f-cw#)~;|oVc zuGj$42qgR(9jC*1Qz~krKpmh{W~8%O*ZDoU(q`NQdboh!u{~-?`N|nB0Die$Qn5`! zP5q;wfDPr6=1cWQbxtCnpFj7JGb`SkR|weVxE?n-H#t6yh||XJbSF_pGzP-$_V#u; zd5`Te3D&js_0DPoU#AkmR8?<3KV76lok5B3AU;0+%@X)N3?y~Mg5RFiO)P`xS@yXo z8ESG`@y$?UL*BkPJ!$|?@c!Z@SK;5uW{6pE_+49@fR2R6XS67ENyDt@lSmP=yUnN=4 zW4{D}xTx^InaL3U>gVw@@&JLDc!5d!Jh| zVW;JfCpMDMd1fO)YxkLP-6&dFlhrEvU8`Z8O5ZCF0xE%&iQMw-i*ad4#657327thi z=F7{e1UGdrP3+a~5=7iF@VOKK@4X{CJNO%N9oqaKxA_M+DTT%U@H8{&$YDo#$q z5GyMowUhvV|MW|${QUgG<))H8dkqZ@)c_?dUxG|iqiCV!?Hpc=P1xo0)@0M zyI(~4U#`Eh9=-b_vI?7vWjFDgq?CYC6X0NG18>*yhRfT1Sp=>9O$1XwmyfL=R?nV2 z)BN~xx)7NvjTCIxzjT}#uWK83YN+u((&;5aEQ$%woxNtHnvYLO}}ZU9lmY%(%#+5t29{0H-niEW(~ZFe}RfK*yF zVo~*~xvcEP3oLBxEN}A{udssR;!}`iLK42?CnDgF^u&sOU)1}x`wjb$dm(etP(;>T zemamV;(>6|eNp#{C>R( z52~&fP%fP%{gQ;*_qs8(gErZtTW|(oX_Z5lV}t8x%7hSxv#l+Mgx8Us>w=&F(Lb>+ zKPL_PI4o2rb_Ahi`JdyV;v@MQ$ zJ0um#cDI*%qx&;;#9p6A#Bqt~a!~kMZrsf0b&QC2nrrie3T&rMgoI#eefXev<-4)= z=99IxhU>D_gyTYj;+-ZLu!Pu;9uAc*6*T1rDdKCrIK9ItY`}(`#(H zD54l8Z!X2njZZ>y@*FDi;M<2S9M0wSKc8WJ=}4?r5Z`jr9FL7pVcxKWM@ZP~v!(Hd zj+vS2mG|?aqLwohN8^!>j*E*chU<78&i6u+jr+cBMa?@1qworaIe-2<*&e;W4GC)A zO$Sg(BV19FT3LItvmG82W4ZiNq{e#G!1dz%(dqThqJ96Gv#4HnD|*mj25p>(!`5-j z@m9-8V8@<&wcQo9Dl4G8&6A*__0~7{peQddsy%A?a41$UJbMdRdVxHwvruf?%;FK5v>Q0l~w*T1|Rau zPO}cD2J@`LBOQ1*cX^WBaSguLBYPcqW5u6r z3gnPMUaI6C;H|BAfxElS%$6I|@g6-gn=5~Ya<_6j*({oxu`q^!x8@p8A4p_6pgneD z!vaM@ML5uGY;4@X0mQE0fa}v_kYvcGSjR;%~AH_(Sv|p`lMb#(XHF6zb$2B-agO=j5TM8)(ak zx-Z?0C1mSU15DUvyqNafbP3t{S0R-xaJwD`d=6bO!N z53N^^(%o{u1k6|d@}`s&^%teNM+(*KpNEDwOB+hH3t#p>#+<8jvy3}+gfm-QcXj(+}qIw7{6 zF<}rn1?d5ggWjJg%7>z0N)RF}p|7uxhKh-NcGEK~mj@~i4z!u#9$0H@ow9kqe^-7Q z)J)>hS8#EuA_}pd3&cj%#=^x#4N9e{j5gP1=|{r1J4_Ofn$I-aIy&EGig~O5K97h7 z1-?!{!t)fR#lpdkOOO9LYR&fid63Jdlld~t@DTw)>2(`= zl9soB#zwz6qibS6Ym=CmDC|>j!w^r5#35u7md=9GF`>yOO+`KD6a z$@%a%5!-;UT#TB9n9|bH;wy!^-;rpi!{*4%t!*!6V}SAoJDW{_#WTbWcryIY{qoC zOquf~y(LpHWAWrwp(R*OtxISw(t0FCV{}o$*48$CuSzf-IWRhkZH9mu?jPO+AnS^_ zjVi+x3na&KwdifuzsR@VElwNEMa4u|qNoU-AI6Eur$7y=K4ROqSA4ILt`MDKWBP=eW`0Z)YA)Yj~13HRD zD{habDlTS8C89Ul>-L$*)c1*xT2)kv6kRviRIC~W9O+fpRKvWXrKHC+L`09bZw>og zuIel~czM}`taRh=e=0`#d>_A`NbmJB=@mSP$(qKUyjE8~-=$Mx$)F*^wk^#-3IqmN z;)$UJWNj7j9y4vjnEzD$u(^G2c6-L$isUitn&LfM8z{#TuTjdn7Er(2#1*hhziQ_= zm~A2M2Z;PY@8-#wYg&hCD0|-Gkl(ikkK~rn$bMIEj_h<#d&t}c?tU8kbTB5_RviSlF2tiqME;iQ$)*}Xr8YNuzTrI#~; zX6HG#zV7Pv$uK=J6i&Iusw#%&O@9oX1JWO(F;B&LyWbI88 zJ~Bp(Sl_uH9627REVOv>;u6u9-rktr`+nuUhm)a#v|ZKs1FV}B`nzkYEaOX>cR6a` zXW#8bl9$Dh@1d8!L}ZQaOzM36Sn0p;_y@OqK`q-n7@Q4fRmWIE;lKkHlspEZ+4@0G z_qi&nd@i=h;i@g8tGgZns?tWD5baMkR%h$*6P-|SL6%Q6>O&ONmGf5G|K1p7=f>N` zDp-m?HA8>|@pe}7{cz5l0;!d_llj&o`iyDZVcwI|xv+xMTM~)y#BF02meB;dO2`b5 zT1H1UEA0(n@}OuG$J@OINv;dVGk@#X*|{M4oUpjGVVi$S-;=A5G$ zgWYda-$=^Apdi(x@$B9adHbqbP`E~NpP9JpOAY}S7G2L!DG+d21Z4GO-j5~s_M48e zz1`}$Q6o}^-<-w3Ew6%=r&sHjkq7)C5nA!$s2Bde`AyE~D)pK;_f(IxNUlv{2U z930F-NaNebAgDzj@WpoO&TU^Xr4564Jc-IoGT=6n`W~=QQzgiaplA4^Zl!+eF&Fa! z6@nOmuvi9QA##5fB}Nr0Oxg^bLDcsV#rHouVKCU~*`YpRxr7arn^gw!2#HH*eKXk` z^&P~reD&(O$6@QJK*V`UupfCofQTE^oVLM^FUkDczpZ?Ks!G#~<{qN`DpFhO2OvY33+Z%U5mV#4K(rJKRh9Sb19X zw7sKJEu>AhJ{QRhN0%ZBB&0|0$G(BN{Jyny?+G2c;`Gq&C600QkLMZ?f9DT}^$b%w z199KB9d4a~$Ig38=5_rYd`8xOv6%cx{lLr4F+VhJ%43tgBKPTjxGCqlDdhIcXj<=L zsM`XqtI&1Sp}|!Iv+G87Q{#TO)7G1N25*4I<7jFtsn=WD@swnZ(J`R;4^(m8xPt53 zpFIPFBkDpwEadt#^ZS85-2%iC+t!m=_>Ps1sEAKKE%i896r-Q zwtg|bi7tk$2LQIRI)h#H(W zREGSri;6P=xo`1arSmo0aoHGOnXzmax1{M5T=^&4zjS*;kjqNg4?B3ZeNtMgt2KVm zXk+%&G!TYQMOgo}=(xG?q7k1-dQafi6OU~gj8(5XJ7yRRF07JsxJ}>{PC$Ee*@)_Y zTuKu_mj9^$V0}~V@rjm3?agI4+{YVhZRpbtn`xXw)Tep6nTDwk5+c*mcA)wd;FYZ$ z)dBLbc`+|KU@9YNGRQ3_r}%g#Dk6fJpFcK6`WEZqDel@en5&!bqcoFSpn?MFI2Y33 z>dw#C*P=l;>z?)Uz;MSGmzbXE7XU1tJoAFXmK~ph+s?Hq%l91b8=(q{^*uvzSLl(- z&Q%fM{GdW;Jh!67i97zJB{`aod2oDuC;#3r6aYff2hlh+Mh{-EsDu&G%{TC7CY$<1 zL56jwz3=PhqSx;RuP2(^*nUKm(Tcl=H>?5+_T8wpqJ7*zpAPCBC6SkI+7(ile=sFc zAGB7)c?n{tJBG&iw>WR%$B%1AM=M)RKkNuQvd2E3Wr4}@I?99)cN&bMF7GTLZ-i`2 zGS?fLt`YR(5IclciN)sTLYw^@UU!yhu_tkd28!q%uGU33ow-C2bO`I*ZF1s>2H`WT z|6ZJ})K*CkUYAR8_>{Nf+J$DR#chNQ$k&$r6fAJU-+?QqFW95#=5e-IoyejZlV3B4lG^;cYwqqwg%spBRyARjc1K zFjMD!y?*90d`e4iLVP~`ai|=rPDC^L15IWl%(TC9fL55>@b$ORm{X?!$`409u-3dP zqlLN2uBx(roC$hpRfgM-Nx^DutrmJKtQNRDW2sB?Xb8=jOc z;7IuuS*hQlaVp3V*!bm-bZ*n{ZlXK5@#7c2Max@nFkH#GS;QJbiVrBXtwz~$nQ;5% zV?$_u4WI*KV?(HA!#@K;-r~X(o=|;ayLhc;)f8sj56KkJuk)r4Gm2$lG43hM^OwG3 zY_o$a=t|S*II)1bR8_mo%3H~mr42QOrrTKT@k{C2K{p3w09lnE0M^f_*#;Jbl2FO_ZH%*hnE4*nS)7_Z3K zI)^R+HU~k{V_^)yk+iylM?^%dFRZ+xtWMfQqTZ*AxGm%-pRWh5?v%H%X=9J!H6Xu( z?vWhQh+R@3-0_9Asi}$IkyW!tMA75MC=NwO>#>Z{9YHRML04B-YUAJEs*@`!01;Sg zT1EQku)3lOlBqh^$%2$} z;%CL5*1}sFn=Xi?y-#uNqyYGMY~dE%H#0eIYDDrzuf0R?hPHC{{+kN`omX>O`3C*v zEpY(`n_O9*Z+OT>QICbVxX`lWGm1YCJ=yvF5yw|X5IE0XG+VRA&XJ$tj2L-YiFk(= zy-)s?!v@oq{P|C=wj9QzWPo0MjVlOBhD8!+;tm-C@?S=Y#J69nBsrEH*3T!~vs}*J zvAFB^=6qF5;=POOU5aU8n3;==DG3?5bQi!6?(XNIPIxBqo!~T=MI!!igM<&hzQbwe zX8rWV%zllpz9SXYmY)Y(u~Z)2D-tTQ=mqbi2zx)u*^| zfnI2-h^?hmKb{}VLn&j@x>ntgf>PF-cTLw;RCt+u;U+s}&n>+m=aaG=hswO@0t44E z+heOcBzv(6-vG=9`Q;E>MbAH6ap;yj%+1c&Zou~yl0^HZ4X6#0Tb)s#;SNOt^D?&g zAr3$3(=-dNib_WM`j8}rHFTW&^W~;e{VTDKN%X63d1`1e1B-Km3*GIPB+oNzyZM0r z>LfXHXU4t|*8-ui!wfsztuy9o1ohO|RV}d{NO%QU{_WuRn1HqL=|c4FVqQ`JX_2gx z34KNDIkmdv8Ks7XhClM^EjhQ5o@J)4Ntxt$tM$m|zDTO~C=&HhDc{N}>NfIshHh4U z<%S10n%AM;h1XD?A8VDgk8FHHYOA^N3`l)jLs{_%49W)Ulw+73%$6bQEjW~vWK$)) z=vP-)5s-0Wfq+{Zlmw;`;$2Twl|&?mrAQ+M?`|p@(Dj<##pomy&U-dvs{L;sM=CG} z-VDo*q+MZGd>kgNH~3aIryJe81%bq-HMb~P*{PyI&jsq=*=&X^0ZLl$y?lqSvF^_< zK4u>eZZ8fvczL+AEE#<7ZaTlQZI$#U=2i3ln)rf^2LxSY(YvBGeZ?0htF=8MMRsv; zixp;3ZxvfDNGcxo`opW0+^_QuNaAL;(Og%U!(Eb8qAaUyH{NCCKS}!itMv!33l-7R z1&g(tUwlB0%vra!ap zr@{A3YCgbxW+obERRziva+X3nj!7w!pXocN_@7>Ue%m%(Cs}r`YvT=CmlFr>!1ojt z&|iH7^v~fDCe{S|epb$$Em*C0%Gp1vERQ~_FWG67(7)NEt%O!MWMB4qmc9C&d0@+s zym+E&4^l|3$_XAfnfv0%WYacTEszy(jD4KujXP%~nC5xZ1>4ydb;s`?2s zl;{teV6)Liw%&Kb69dS5d-Hz(&N^+(E$&FqP<3!PhN*9^rCk;qNq5xadW9YqFKF}hb61^GwoRf_lXjDJ9Plcyhyd3kwx+PxpWdDHn!|A$_?gM35)5T$Q>+>Z>J z?maFs7$7GnSwUR6}9@KtvScXpksm-_PA08 zY4ZgWT!+Pu`a2PUySRw(1tg*Ei~NKq(b>GTM}5M#sb`%EN*u4|3uN&VkCeR5)?NgKJ!PJV z46Gy`lakRP;+1SKEvJPZ@#dd2OE@SD9b5pe>D7BcYJ4Ud z9C%87^mFqfn+uLhPV#28ebg%)0NcxjXvW{lGmW9G1lKd*O`<3Vw|FY7T8VWJDOLAME0#IH6 zyG^4KV2NF*0Tu4A3&C&WQc?!`qSDnk5x(Bu^|t{Ph0YrgNa)nw)}LP^q`tv6V;Q}r zsWp`1?(9>m>3xkdQOq11ctN4~-0X$@N~+uw#I}21>(1Qw#E$R@?_f8PM=-f`Fuh@ z*H<%DT@yd#OmUwbp&dTxr5N7q5SWueS{iy=g_3DEcksr~15Xwk0N_>}`!3$%Y2%h% zat3wh58cFc1VoR28~Xc~$^KRszgs;e;02r6+;$V6cg`-VZ>mxdGIcfvYpWcz+m6-; zU@oaJzuTR=*=>2Z>xCYyzqH`IhVqrT4(GS6$^#|P-5-cjT8Av_FaAMaR9!hSz8|_f zyaRggyi-l$CQ7XBaD85F_zLJ_n@1~^IyTA(CVM+A=Amlh^2w)PZAJ}-ksE&55Swj` zb|a=|#3<)cyouzYS>QN;In6pG+2BqhyFSl@zVNoMylLM=8wSBLs04Sapp{<{@9|S^ z7IsFAbbMlt@vN`~uJg1==-*cyPoxn2j@OS_$H ziF6mI(>CW3y6Rc~GPQai6dFN(I=>lneusM^c!VT=r>4d#CYCCXPw{Z(0(GU@c>?42 z`*hDPxS$|$W}NE@IQxyhzJ8gY$H_uXa$Fn<2`TQ3cfje|o5R&i1s@+VI5dCLS#%c+ zGL1+sYn)ehe&-yIaT@1)1A zcAVj3M3h70Kia#*z_cZ+8c*rGfx`v62g=ik7OofI?~f%We1S zA>YY^xVxJEVK$JDcZdeP)c~suAF~sAL3!epO7TEPt zLa)9bJ^ESPHG$dm3rouFy68&`+^jnV?v|+mXbj`8_^*e{B(%TZF^woV+~kWMzR-&V z!t~ul6SU->TKoHFZZU|z2Ci5AYG+FzTQhsSXC*S(5EfN?LcG@TW^t7khYcFi&Bb{V zfz2+hSJCYf=T9QoYk-XUor$G)PWc|UIzq!v{e);DY0_NySeUV70UEco3#DJoB& z7ABvCVArhS|mKAT53xdi(~~P6PquQQZtTTPFw9p*W+=b z9@8b20K?f3t;~#!W2MI(m2UX}uiHb3l1M0ybjz6VU_}7<^4%-jyuw0u=*hU*My40v z)_`0o2w5M8gbVI2H(e+>PECDwxPl+KHkDwU#=TG}@%4)N5pkrmxijCWm&9$NTveAc zzj=Ieq&FO*tCGYm^#W4Abkqtzh9hpqi8tIu^=mxoOiWDl%5-K+^@j}s$aF=90IZ1o zl+pAC=e>L-7Q(g=rTF8DAw5BB|FIqk0Go_VHl2j$WQ!Ls0+}9&?m9eM_K;kLY93bB zN*gvc_=5~2r1$%qx1XPO^hZZXLq`3826*x9DZ^7>%<*;0No)V6x@6zOqp|TU3IV_| zqImsJoA1>p*eMsK3*^yHSIyGW((ch))%d}%a|Jbr4^CV=J13ycefxd^m&t&UOsVv) zoG$8kQ*2ypx0RO-PbPk0x>=9sEYH5RgpaO#|1SKL{+b{=rWAS`JPw;8>!(+IHY0{% z2t}XVmolxYI)~u;Oq{%+N5Ges4@aKglqmX~uh5MeHE@7>CvR*!Nxr?fg8VqZwd_*3 z`}M5--j;4bk=1I*=;o!2pJ`uja`dl?;kVmKfE!={P+QM#_8iLZPRMNrKSof)n@{F^ zxH)N*ExMeW;nXf46D$UmnL!%^=e=$>?M&Z0lOyvg3gQt+Lzwj-rvP2z@Dwm@_?qGc zzuB6zZ)%72O=cqQ)Btffi}f0|(IMc=56yGI*|Uq{A=|*W-EU91RV!LgW<(O4W$>wH z0BGfPsI3`))N-*mlN)5bmv}&tf5gbfPuoA1U{?T{8A^24hX4~Hl{SzQhi;s5O;;jo zl7O)f<v8V*Nu6FY#07(EZl@hNyZgjO~H8JGF21X%>Zhy(ixZl{5)SB1x ziQILB0?GbC9y=FG(p5a~Ci>6?B`f((J&~QqFZJtHJRx|ROK z;q89;Y=9P8QeTG7%`FKTnf%9(&#bJhxb;4WQO%O+8kt;$v(!`oa@jz|K$C?x#Mrk?_>EgE>I@cYY>3lE0OqLZ`Es7dsbg+V)z)_No*l5z`u%~G$$aLk zIy>v>%O?J)7FTC6NHSYyGUF-*a(%4U*Y*8``W;YN`G8p6v8c3|^yyPuX8(Xu1RQ)) zX}#h>T+z*)Y0jyCeN5|$gj1h zP*Aev$fAEKn7jTUU3ziv49j$mTfEL~9fSHthypmFezygJYJ*XW{etPE3CYPqdyG?% zde-gq#t+l8_IXhghgb~8r;W?j3uQc*?GB`MMcBAx|mp3{21^l0sJTC7uu z<~J3~hrJ$V=r=JhD6ITI#>hmN0ZDoE7++FY%)moU;-*P{7cbvVW~ONW;}}opn@(>Z zzlI_KiA*(rRn{NekVamsj67mI2JVvXQ!8+Nv(9y zoVt~Vl{v&lYaAc4yWTCWpD=t7a?vqFaWK?&d@dqV!HE^a5Qx9o7h_*3(%9ITqAzH} z@3!p_3MMB29d#|4b5xr-U<&@=Ld#|>?d?rSOfF*jn}uQ`-QJD`!>!#5a2BP5rT7;X zR%+?#iJ1alzeZE){uY<;Dq&zCTDz@_gQMt^HNC}PTz;b9J1$s#%G%$20d`(q0BOvW zCYp42LSmwM-9G-yhxCs+{8QqNf+#40etggU3p&DobZZ-eWQ<=`&L3LH;$myx=Qb^cAMA6ehq`wj|3TXj6l0)K$UJXw-ip40T@A&o^7BP$ z)4F6Ix^=L6Ma>USh~1)KM9d&ALp-rl1Ah8Sbhk!uZddTsUKeCCk?-%zEKy-$Yzpe? zl5LXw)NOn|e%Z$8f6UNC8lBgRoo(M;aujU}+UPzD8lMMa(xaBTV=H&)$=|da^jE^K z|9wN|S&;nyudw*U^7@#fko@0YTah--Eh|piU;icwh1X(}M?mtxC5(UmCQ>oE>U=;W z|3BpR{BN>-$Q#T$G5-5YOri@Az^I3=_n&ul!cPt7#vgb5r{lg*@U4kR0-V7uR~=efnN7t;t0JuB_6rHQPpwLUuZ9(mrIXFKvyK6-pw zVEGB_Y-KDLFpi(rHaeOL{wEDilRBHJH{|BLX-9fw*75aqwlfoQoUMN4iLbm#*;lQ< zZ-`xsmBM3GiJ3+T+Ce;qvcK{hXA(F>`GQnT8|seVX?Mo;$&~7r2(U|mM#Kl)U|(QXyAB*b9FFSxULjsau1&_DwTlE zP%Y>nC005TtF+wzJiI{mt^~iM8CUNa(69s5Lho`ju0|SxfvQOcE>N2Z=K7l+7>(-G zj;8+b^VNET@1xa9E5)`0hcU!e#iPtJc%bQ*K z+QhLpHaTAidc1T4f#3dai@xgKY_$7Cf+>+|1}3@lnk64PSZwrS!K`QvH?N9?`OUM7 zrgV*id2QUXYF5u@y<|=&FYhx>(*g%XkENt@7#jGo?|r~<`z+?^(?Yt@>1)rrPbfGU`?c=Y0aFF;hcXZel) zhgWy>o~17a9h3tzd&R=`3kT>g51^FY;yoK$XUwMM{z=B=q}STln13f{pF?kETPN(W zpm86fOTW%y>?ejfewE8DnAs+uB?ouJqw8SD_mi`h_*=KZpmN%TwOu52L zVtIzHNxb+-w1LgCg6{PvDRA0b6_?Dmj&wngn0Z&p8g$&%W;|?{lsaM}b_`vGGqg6> ztw*#E>XUB%X0@M;D;B@ItHY|_Je;*XASMmIKk?O^qJ2RAX%*$LPW9QJxAkOO8>DI%qzvzCwO1<1L@<-shP28yS4>Tmvoq@7kkl^j&)95RcH(Z=D zr6zwdz*bw$kl6WrTEb^Hy~`TV56@AAoi(YPO4Aqurd~ODUrMMQ=Gu=p2DbOhN~xLq zdHX#jU(6bCYj!s8GE*?(51;?}+fn9le@9;w(j^YAvA=G=C00^%tKTk-qt6I6&mfm|uM?u=aXJB=)oEPk+V>;dbDb2OwwM zFDU|fBpQkS+GNxf*0-V69(CCj%B`yZ?pF)**IQsO*&7$RTR&O-QIpTP;80ld$kwn_ z>gC?`GybcOmUhR0eeA!mkG)ot>Cr##UkBwA?wB^`+pIX8?0EuU^V#FHWBBQtlCPra zU8uNRw1n=5?W2!7Ff86tUpJg`W$uR)6Bq=F0{z1`o^%r~o4Rnt(0U|`hxXW2fWsLb zvOvrEW&ZSo__vN|>dZ1V=)HJy46Rz^ins`3o$;w03{6aomJ^eG{m(kd?z4B^ex#og zgqxO8xFa;o5GPkF@&Sq&F%=&}*y~AWv6Q9W#E0OpK#+)m0o3|BXn`Buq-TsVnPP%U z*R=2bd(3>X{Nl3$S@LwYG>$P^ai>62W~Hem10M5A;A@e|14&97e!x^|F+%`?H2fSr zgX5EdI<3m_fKO};@sf*o^lx>{8E=Gi#J|9q?V+qEX-PdbtMlQDM{!8L5^0|_iAnl3WC3r1CBDCtMpfM^1YMdnGAMUh-^a9M zSfPpTlyBW0ie(3#6sH~Q3*;YR^_N6zDHHgx(PLiG>Nh)gi1{$}r1K1F892{lXPkC^Jt{Q}R3p)8v37=3S1V97Z2PJJG|;bYKG< z-^ec>3`?2&eqz^ekTw*YlXxh3Nw&0Kq7}2gEV`w?5w*r{*t>DWTislmbY%oJIAL}g z`FF}0YR$MX_W{%1xc6kE!|8)1`l+VlkHt##st51FP7GFm*diSJR;Nt+%j?}=r%=}= zskc0pqv=co{cxv9*m=pgf_`VNB&TcaT(p&CD05bw{ z>51=;N==)Kw=**`NhnnXN{HwKe*NPqceqwoXo-x^=Y3)vQFRPI^{A`&jfKR`AM6%)om+aX;rnX%jR{S~`F9YsSYa zhp#E6x=2sacTbtrJqp_)ay$fAtS@)w-$2;atqm0fmN*UL#*BZvE;UItR$e$KeHzc1 z1)9wX>zsHe%)m%VWg=W+Hz{Xb7;X3V*orPps?{*7LbJL>pv8rYh(;DW6~_rV+K5;?5u z>)|oVXHp-^p!{C2;y6Qi2WrvB}mZoeVu*vyQ8Zs|%Vm&J>=hZ#L1mfS9MK^lXE-*CzMl z6;Ef~UN8kJUGZl5-_^!l66pEG-IMR_1}WB=Tfd$Zp(ULO>|TNFmDWmG36Bkmc=RPTqOq-&(6841Qa zS%E?`mnABq{XF9f_;0Ii6@jNrdnegv8~GmBO9pd1R#qBUx?iXyVQ+oCp)U?gPNG96 z5ZZ{wJ$e${>}KinXx-ILn0$#(NuQA-S>EA1z9mUo-4V=br;6E1eTD1Ov6-7SFVD%V zAiPZ`4nD=n-X*26Z*+$qLHs~8(mwaz#vO_*q=m$~6mO0xE;E+gADC3$e{%tJpn2c= zoO@3{u#bPb`tj;5j>%}qsx_4NCeoHm@ZD;bdRNfra_T_36&1`q61?b0Iu;vYqvOS% zdYZ2CzaCDLOZ{zt@E8hSuXboB#5U8_QV#p-b}GV#nr%B z6sHH(LLS!`E$8~xYkvOattmi_2`o|WLvZC6pJ4&6Foik2h4}FDHcD?`-9pnBaluMc z8+Is*mDS=I?o)WO|FGoA@Vg%|EW$l+#j$j&7H>?vkRh=-C2o(#)p*~g4e zo^)AR41_2F16dg3pFC?Nfwh`ev<_sXx{bMIiIF15+)8-zKaD>=uOGD>ZZUtJ2s9S> z&fK%)XX3bs;m49JGF%WhYs*LBu4XZHYy;~yl{HH6#12@rn&jnwB*ggkWcwm{2n~7R=NBk}q|jjIpEPA+_>!m%?!Q>s4&LnpDsAvzHAY$pvf{)xE8k z2GtC--=7sXsV-=DE{C!Hxz1I~!o3(A1uP<)rb4?12{1khY;+NE2UJx>@m}`X&3^m# zPyFTCjJKvHK84R^ZfelM#=7ZNOrU|!21UYs6h-z84R8JF^u+t&l&Ye$GgAtgE>j9n z|DXws(5v-HKoD{Zbc%a!Dq45mp8V7nyngfYTDT2+n4+rH|LL%Lqb|q6T}F2^dG=EO zZIoDP%veuYQnml)q*n0`a~Szqfei14`u}3qt%Krhx^Ge3Ex1d9gajYl0|^q`-GT*o zXMmu=Ey&;mcXt__-~@Mv!QJ%&@B7uQbL;$09jRM&=C7G~y8G$gz4zK{?QTW^BCo(a zdy)jn-$oyV=-r+SBP8x3ybWk1V~n64xdTqOSc}}Q(Q~6XOxP37=9YuBI;(LK5t}}gn>pDudpmZ zV08Sm-O=67c>P2azSuR(HzgEDsFrsb{B$ju=?kGw+gRv1IzWZJQ)=|U+?%rDKR9Zk z@{YuZld{Kso@om;*x2>H2$R&pV3NMp0(3tJB(gHha%z9dw|;Jl~L%Lqf~C(y@K4(Ir*JVYQ2L*%H!#Dfd&;Id^!YNE~pqY-4zs z98TrBS4l9#ZiWI2GfHp4j#K4hHQ8KUuQ9z}3JbE`+>YI5(jG1<;^aiXB0~gxlQ#tU z`3166ulLg~W=xk2(>b2l3dW1ANFeW>4MfZ@G^mY4?t4BtN@BE`k@*Ipk-HYB96`of zgxtNI2grR1nuo>3Km383 zrAtC@I(?Yil;+{pW4B7+!*| z5|XCQ`Y}5C4eNEz`E@pAKZxtD;xeZV_*xCsxlrD9EK%%$9(Q6$6`RtomJEG`;K}Av z2f91K*R70T#())ThzThdZ9Rv@GH1ZES5|DQ#ZXHkti&qdeaLc!xaF}MC^a$Blalxn z4}P1Am18@gzT8{j2%w~q(NwxRU`9*|+~oX3SvYXg+DyYR7vGN863J|AI|^rlc6+^R zy1dJe(jnuwHTq^~TE;q)#Bozhx4&p5MoO-P#8JhVC#OjZ$#fOv@`z#WA|au=9D`-l zgW3=gcs_0oG|=~MWhoc(UaAK%+E`^dPLpGhV<>28-32dZv9hvO3vmTcSVR6E-7n>l zdS(Gj=LrR;t6a|Hq1-P)WD!fP0Lw^D$J z9tfjApUlU4b@+@owyfPo4oAX2HM?KjwJ*&sN~a6Ez*q4=)2X2jI!3FmO8#!03| zT9E5F&WmrQ+4~l1ZD*p1LW9608eqvSdPnDdK7etc-796&Dt84jM83YZ9$oe2C|(qb zsUQ;?c9)~J=x3B}VfiZ;|1TU`+Xy-wKJtt-Yn()rGSS~P4W=pfR6m)U$*dww?$4{X zg;+husx!GHFv#Iyf?oUYQx>XkPFab8Qq|d!haD{sbJ_-Uhn9LpV@gE=oj3o*5^HQQ z*V41-qxUL&c?Xe?kaJwXAjr!*)Z!8$mUpzl5W79Fv>}r%9O%DS zRR9eeOP;c|rjCkFf2ET-lFSgL{)~*6J_Isa&NT=49v~vs;r{G2W&nOCp9Kj~Lpq0B zo2|$iyzh=LNW2_4J~~I5e4CcrdWibhioa8upXe>|zpwW--d-Q0+H&J=!J?yDFZ&gT zdPF&$)Hn9VZQ|N6QMz29GPpNH0skTjB=(MR)!G~(KM{X?88=wJcV%f#l^u9_XjZwPu(Rtn==z=9fuPjr zi!OAsDx?0P#U>p?M{6@bN)jnoTD9&_BMBmpU_E}Bkl@DDe6=}Q_mD48^O8V zC)wxC(Zj}#o^Ss0YQIyeui8mOCQua_?&e|dz*r*>_r9IP9|JKj8O;}%dZn39h7oad8N-Dy^N zE&d=6`y(r~qbWH+E;8pEAR}@+7-&+Za>Q)Zy(R*sNEcR&xlyFi(lq<1Q&pcoLa+Qa zz1_$~N5ak#_3YBAx%%Kk>Crl(@bjF;X5U?gH6|_LB%WlgX17kS%=nXQpR6~5(o&`8 za@Lnzf`3o2*0Dfpqt68ba>9IdsuI~O@W;ig*`d|g44;fify*vXHi`EtZVEW&lL>Tu z$*p-~_9TB+exoKkbw>OucUOsa0l(tk*9DOCr-Cf6Kh1)(4BFQ)4J0A&m$W`{W69-} z?ilHE`%2=70Wzc>LisQtml}8}d@jgk)=ckkgXs#S1eG`S6Uv4t0yT1o|a7BnXmyywSW_%rx`K zET7mn*l{;TMDxfoP}h~*A5}ftC1W;??9cEp_a-k9%RXv0lkO6=Gy%9aQ06IS7^>-$ z)U%m*rMf1jrlvH}U$!xOYGpK26v}d@d^P)ui2Xa3ZLZUgSJ>TwLu-q9MUEH9e~v*b(P3V(`t1ri_BO|1!(! zx=u!YzX~M~Wn(pm4Kh1e&^0__T6WN2EG2qKuI-5H$ zX!ueBrpE6GlgDOAfj6JK_L1~pm=;X&h8?7j`r)MXYFDQi8rR@9>8OgkZ{&MCgusfEQ_Sv#+- zhUTVAOZ!25sR|=W=6ac=Tq+j<{f#Jvctd{sJt9d+oIM6XIxLpxl<8bY>$_$rY*Eko z>hK(yn379bi{ryGPW#;rbP8gu%{b%`fTwvcc6 zhHQ=d+PbSr;l(2b#nL?qwp~8DwKSsFRU^iq0o;HXiq3162-$0CuMzs@i1s<^uU;vt$u&3Pe1C=2aFa?mY2;Um0;+y%N1V8xTr38HlS%NniTmA?}zVV=Oanhyas9 zkZ&xf(wPIlE8@P`?MCf&`ZC$4MbLX;-81KOwnRr(B>54N_zw8zWH70L(Uwn)1ow$vSI5)80& z?&B|BJ(jnMa|oj|u*cVdwhfXeVCPHg>^>2{HdJuZK>|Wpm`N=Mx)*mtRaE*==XcZQ zm6Y3W9p+ARx(Hi;O~oH*VOA9oX9U)9#@U_aUXfRLWE3J`ukYaLxh%NZ1Y|Y_8osj` z_;9_xs+kcu9U9T*X2k=RJW!6+bNzYml1zS80{&&c+4vO$x*FNuOOfI8N^=@A+Kg5^ z1?Ch?jU{t&1|`oAW*WEuOf}XDx|FA5uW9{yEZ~B%xdM5Ctx`ZpUFWN_E@M~sSb3_bN{?UCoja- z)(bMR`ztC%-s(*c4YGRIFFe!5Rs;8N-={hLL~!smeAnYZ#2#MFOQ8K5m~Yp>G0C7? zM-ekjQ&a(AhnQ9yw)G2yxmK1IGt6w&D{XpA<+RS}CX&~* zP*B4SY!ZIW3=?5G8LutfDgI3$|H%XYt6AlLlxqHGM*E*nT>t&i{&&;hza9VAC;Wfq z@=cTKRdsHs59uJKPX5roqSrg=)--g-2AIUTj*~FtUd|kQbrh5@JZAvO+It_tK1OhL zPYWo-b2Xu-*I`SpeJUD=&}{Y!{`;tH6n?gk{Er8%o4>?}Yn5^4w0aDR#Qu4!Y0L$4 znHd_GtSZrdotq5@TT+Vqp`Tb2D5M8ACCg;W0-c@XR$7w%s}cJO^p_t)3?q5bNqRR7 zKzUXg)1@CMHzW=+>ES)PQ%9Hmkn~>1Z zk|@j!ylN=5@{4YvO1ZQqO3BFlFqHcXLpMq|+w7?gi;c^R?;e@=`lr zra2PrSc9ohCG!nJEb~BylB3!N7rDXydE7oMk_qcNri-oQxsfKK8rua)WE2JTb{k$* zy3t(5ReiREU{$MNY|dX9utx&mB4$&VKVjj)!vyWD=fxDmUB}7E$*65#2z0uN%38l_ zY9_@wY{9LdoI;lRs!cYgkm(oFFaQf#Mz%#Y2i_q5p#-Qh}!+}r#e z^V2L>nQj}0r6zk-m?!#AK_FI!=&+AZehmrxtCQk~5KxIz?>7546hLd5EXgiyJ4#8? zfE-DO4P}6omo0280u9bmvp=GDLrjUmOafPAkecb)cqoog8ZYwsdXmPKT_1@Y+eJY~ zqt!tW%fax8QP(H&S5dhWh7RW8;eoQ8uN}hjG=X1Xu}CP%tv3+cx)iN{XeIe$rgvrg z-I-V0n`Fe&#$a0F4Ql$3(A4R?%NQnzvrv4|k7@l`X0XvNR;DOoMBN2({K6oSF~4#| zaFjEdZwL=E8>dMvh9>GIw^_sl5tvL0YzxK|Bp8n&XH2_*e$^!rm8rnu6_0%M2@Ud; zzKD@9e?sFulC`#cz@Uwd2em_Kr9Q_0vSFa+|WLjiL`I@ zQegxUK4(d9moCmtDtIZ{BaAS?Y=OI!B=;yOo3r53Q8Jk3B)&L; z88{KJ+}IH{ms8Qr<;b$JKln;u9IqLfm;{;bIWgPixoBsCE0&hc7GSi8OIyMt6+LoD zxi(eI%g&G#9q$QOQfciQ5-lE z4(cQo+&S}~@jj-u=?ZXRbGzloZ&CQX({A3;j*;zr^hvXfJUhwx1wMejt95Qj2wJ|& zBRlgjq!QGG9NiAw+R)ToLk*eo0{~$F$lV0Ae~&ArEzT`lr-BS zuZZXx!=kQOBDsvFXXrAM84r}p!KXT?{ZOcA`w*9)Oqb(MJjekfE_?Q}Fs7JJJYLO` z4SY`1N6jT>LW+xwl+jN~=iwMOk%y&>FJ5RF9~?`!k}}^{;_uQAi>=Xe>!dO^izxbC?nEchj4Zno*bjWHrUASaM)=u`Oc%ZRxWdV zsj`tpD`g}^Mk8$7jl5tH(66KuYpwQ7MG=p<7D=g4MdmAPehrBU;?|4Z) z>X~iGmB4_wJ{JKQ>rLU@p?fAC9by#CwiJ>)`?ED{BqNrc-Qphmz!3HGfjbcIgV$DZ zp~?1D84X<{6y1DGa&+HHc8|q!qa{<_@|nZdW)oEGOJb^NghC5Od-%(+B~3K!a~KQ< zizU4)yu5EG{nRa>?Y-)j;!*5jmsr@p4U8qa_0wQT&n9Gae*!@86d5+O@+4t=JqU{;t;5*2ZUvM=H9O2YNqQL|NQ+v0YGnll&Qa zg7Ml<_4ny_#P zUYBofjJ@_PVzXiS;CpB4LC3_z1QvDB@Glnkdz;5cO{U$g-G3N)lFkHU{QZLy zPg#w$?R_xK-#}1$(c77W*E*zTgMU3?;agIz)jW=Jdev9_R=w_;hW28P#1s3os3N+l zknow82-%Kx!!dO87Ohw5Wz<{8>RcMDb=d@8epNz)8;t4Cym)cq7Lk)6s@FYTnl~GV z=XFsFKMHiBd*zW{P_^?_|9=1SU$}wnRQ%0??d)`ef!ALmUuDGLE!v=8lzD+-*b>3O1P)3wHlAeK$;>6L?-M9PTDcf zN!ep;ylt@k_`Iu)8Qs_J7J%D)gJAli8;o0iFENM^Bli%&t z+jPJdqtmgi4d*3Zepz9Tv>zh-NRMg6b^&T4ic_cPn_}JwhA%7k(jvm6j!8)o8S%bG znOp#Um-8gy-0$Vd@y&e6L2EjC$=n4*_AdG9|5*l`S0`eIDkZuJI5X_wP z5@>)+!fZ2OVarmxbqp0{S5p+;1~7P)`s}9R)bsP5_$~4hO&@QIu1lEB*yjH<1}F6u z>rtO2gR&$qkAk1QK^9O})@Qu?Yft@j?1Q@(?ZL0h#gnUVqNt>>Goo_o7}2rEPUAIpuMGZUo!H1Ng9Zr)Z$+k?-IY#`fa+CjR4mu`iQCM~taR%&4<+9x5^V^o6 z9$0y;9mLWk6*_aR3EgBvEF&7UTbbb9!wCM9m*N`ZksFImpY?tHYudH9){M~Er&5xc zVkvtg)RAE(pIU)y%OkW8m$(YLx^`b7VX7x{*t$&NbbFtnZ~VR|3@4VMZPbC848-AL zVDWGTp18qY*6%i}e{?N{-8`a)9qAF&51efQJRZ%Rm0=u>R`8zs!8-A>{PGoURG5$V z@F5a!b0AmUrmPiJt-j!odJ)57*b_z9o_Q zTq+M@I+h5y3I^l~4wpia;&etaRlpT&UJS)GV{ePxH(ZQNs>waNbBT25pq}^EwZc@iwlwnTQt*MruR3ta7-(bf-c%dg?lFk;x*Ca*Ear8rnG9w-oRqV}w))>t81Nlrillkiy-N`SjUZ&)dP5wpjy_&r7V7~D zO`}em#Tzysdv{Luk_ok|B6_`AlYW^wB;Is?F60`4mA;7DutYU~D_gyH8rq-qp6`$NBN3C;X_0}L)k-uuMkql|vxz%QL^d|f zY^0&U|Iq3|^dQ)^pf+j4yrM_PkdHYzsT|wU77A|HnMS93qn@6CsMj2zAh0JJ$*E%3dv@k=;GUuBG1TYRYS{g~XPUNFm(xWiCvZk$mua=D zH~NJg5c!U59D7{C>%Z-dv1KU?uCwTc%4+0nEv(*s?~rwAZiZ&NotmVo2mCT3BX%vqPUwqr;>P%XZ~%-5um^h&GtmZy1|$Xwl}O)NG~x&)S#d1 zF~wp^{6HC*Kv@~eU`d-deHpC#`6s3Pr`b1zDzM6=8NQ!me)p$NFa_&(OD^;?T1%O9 zRW~6sd!`X=Nt<3SacUpO1#5dB*!l*EC?_yN4);_!4+#)j)iJ1HKgG<^v>w^H^9I*G zbLJw9c84v&_JlwPyW7y7g+0;JWa!Aui%C}Ih`%nw4 zuWLv;w~@;yQM*%+Yzo^GYw1{gYVdy}L?VvzDQ2D~hHY1s94xqgz3X-G#)Q%DXy_5| z9WU&v)8OOfeIwmGEw&tdCJLpx8YJ@+YgK<>IxU4XySX^b-2HQnYeH34wQt13aFMqL zZ&qnTu)?&klZK$&!Woo^2Tq#g0 zwZQfr2|PwMo#$<MjUKc%v81yhZB$_mTePJm z>BbGkmU4?0f&d?{10M-0X6F7p{xQPRfyc^}y!g~L#C@Y-4GI(of|6_oJEVljos&1y z`cYnLx}7UJs5ch_P8SaCuQHxj3&uz<(f18l9+nd&_8`W~bqZ_PVZoPpmQK@Xu-` zkvMoWGQvwPgglk|+kETDB4AP;G;);A>@PUY;&qG+Ba=Y^%ls3v`BY*u;M-Jh2#g|o zDht5uj8IE-nEu*9FR%?t68WY=q=oX)=QGoF(Ctm4pN6NyH(Cn{M*ZGOj|LMJM8z1Y z^I_-@9Z}r7z1qMJn?fK57+gk316X<7VV_&9`i^k7ViBuVz>bG&D1Bs(d8uo(ecE;! zFY;`UuXMfc4HBXvp=Y;C1Ld1FF#nH}GJ*cZ>5_L1qHF}755%QpCxETNhJn! zC-y4x7Eo|#tc2tp8;_{cwT1COUij0!3y8-GTJG^sxAiQvk>+>f<-pebmFzd=55o9{ zJr5wBs@C2$7GV-a1lctYJ((Z=xTWAts7L`jz%)O~=d~RkM{K2Wt$IxCf6aYCRi8=Y z+PfS&5^{`+^-|`)vrEs;%?;e$HUIG8L%pTd+mUeoNAKF+vU~sB*g}D?8-EPME^T_b zJZfmxQ`CJY%9)jidUWvk!8svLj+9sg15w^T*V~uqc7wE}ti2NXoH;z>rR#lo z5E>a@^htV|O;Cg;qU)~Bk%_WY`$hJ!M*AFMYcJ3y8*nl00w}EV-hPoy-}xSO2Pf#K zD;|!zDY)+=^oX`@GV!QsX|X9N;04LT){0N+P5s@S1mC&cm#c%@}j z5|bp*ySlJ&NaUo;8GqD5u#}c(wC)bc3nM?v+D55=8<7dtJlsYS9~dYouoBg_?==KS zr#nM)EB?V*P9ApnfqcIfElIJMRG+t)=Z0K&KkwPk^vDVZC4J$4Ew7oEFhcdF#vLh2 z`^?mm{j|ChWafkL`$AIoKh0w&EF7GJFNL3R@lm{#Z+v+@ZQWJ>g!}33ixlFeo%#^< zKhV+(G0$pk8T~n-zEpnip;E?&dcObjOHeRxh)rVJbb?VLxv40yKdYt{Ku1Nz6qsUN z(YyQF#4!nO1{%naH|EhL#pVcn&{!f;t1El3$jW3i~l$^CrVWkhBY1_@OIVqW#BEl{? z?)M!Gyy~*h&z2+P@lFu_8+~0h643XZLP}d(yT}asvCHI#^)?I{8bSl*&3l(xRGi?? z`2_`g7&=-O7Oz!>)KX#?Ytf@6Vaka5`g%j13@yKUxyDN3q+Sbi^Zb$$j_a4Af#OHh z4)j=3u6t`JugH+Xk`fwD&Z*;9vy`yIi9gM2c4=t*Q*HQEtU~#JbUyRHd!Quwe|Vnu zzg~j*Z%3QZPEnEXXg-oQKCEpN2R<2NoY7uzH|Sh3o9@}Yl@5)1ixydRG7M?{H<<}Sgma9c|q)crGkwplg;aO*LkMUCzD9WoZ8YvlkqFUYR zoofv!>E(2${5by4p7H9yutc%u>lua~9lk}u;Phx87D2h>TEzXZ&@pB5$xY8d!O&H9 zTU^z9S^Bk@WQOY#%XasdOa6&c@$)Bx>-zF}EK5IhNw+I}luJ$lSpx$F_67~t=j6xb&ZF^KgiKqui4{N27gz(uEHTdI(@hx?&GK zt(Eu0is8MacIe{Hl_i(e?6~txE$2&jb09d*yC?glDw22jK{FlDj2`zF*XPy}ZOEu*3I0 zxgsHwHqT{^zL|BixE>-ts1D3H90+Q~alOtgB9!-TSv}ZOFSn(!;JOcAYe7W%vW8rH zB(W?A(q=ayRYTkRYspae8fyp8^+~I5@rzh1TU@jrz%u}^h2HbK zQaI4%aUln<)+GQQA{sV0EEX|>FyxyJ$ht|UDjaXPO%}O8#g{UjyK_ONY=(AkGPj4K z%`Xoa-rAVHabqr{h9J7I7!LNqjk6>_TF?rWV1gaVhQmBaI*(c>BW)jmAL*^e)b(Us zy@`^S-W!gS6lu8Mlng$6QXQbud+}LW*z|thw!iB>oi+rO6;$d0wd@G0gx^UKR)R%C)ML zUEk!n(Z_Uia6Lw)Kf0peRQ;wsm^){8h>xpjHp~vW&)cftjA^IAp=CK4lUDQ#H?Z65 zfN#bXSh`u^^&-ae^3$nGbX~`Ev)w9@2D>AfUEBrMG8x`mpF*xywgCrd0# zm3_NibU9wJif#BN40P)>-gva9jkH1mAKfY3u8n|NGxAF}TY$9VCXZ1m5$H~uZOu=X zNMN!*ji(6YDL{&|t%XiMu82|_nX+8hlTQA4ic6f=^tf?`;0E(}+)`0*{r+1R!xYLW(-%FVdsn*(I1BxDLLI0W&LvU;8Zbv+`!phGu4*m~K{a|hBw zQ#w7a*fHBIf+BE0S7<$>VJDIuBW^qO1Uc=PrP&186D88 zh!`8_jdov1L!5E9MFNnw#7Q+ySb^BT)8ZTrl%W>JY5iFyHL-MFx zMqTtM72Ns&c+O}>vbyl8joDFCxy1WOuV+Q<7X{T&Tw$<*jZv!Q4c7cNCtHE~&wKPJ zKslN`7R7aFb-WQ>(;pbR)a4nbY_HPCsohnLgo*dP6kVrFZ9gxuqGgb})oqV%; zpH#~&)YiMyH%5&2w;SjfI{4-XknHZel+A!+k@N9$0s+)0dmT%s2~DBpC@+yh(PX?~DjwrX^|Bk#yoYA(sPliBbm_sqRJ znU0?;GF5gPn5iY%9=}())3`m>?m#yXOcXH@vq#laMKiFx9Nz$|LMxX$&1zfgBEaED z-dPH#_~Jv0*W&A-KVNtfqFjuBII`?xrX6;&k=1okyt&+)FzQtSJ;R}Qq^&)~}$04+=v z#e~L)J5-On&?MAF%xL`U@D$YL#SA)m+hwMnWHuIR6+Su7loZ!{{GpGOKvz?R>Km#J z;E`T;oAaD8C`JA>2j_FUmtSZ}pBaeMLP9neiv-i2eVsq5*`666;mvLCL7C3um zk^%CqOQxN{rpBQ353eUUIdUcNFAK0mPS#yg6aqN#6Fp?bqkjEEc~*4+K4N^!oqHyaKlVL0g1giMJiqv=UXyqQb2HWZ}x-@Ut36n zT&$kk?<$$}+#?A%zJ5sNC5)X{pl`@l8nSAL2D6s=vs+!fV{zSm*^) zB#Z)kD_++|8+(I!LG@9)OR6l64Am9{lF=eT)J>e__PVlhD|Y3(on^U^TO2vK671N2 z@=W@Y{6UjJbvvBEmEK)v$@UF%iFu0S$3)hs!IdEJWoV@byMSqxQ>c`l7nONs5%~sM zkq40FW0RMO1*KwF2n01b5Yi8W-!h}Vl#MF>S*8oGL9o6P zn3whHa24}?X6pvC&-)W7?5W`*)Pn9%?+(n4 zWqlE6Okc#h=(=m3c+P4RIwRYINzsVpi9POvAQodq+6GJlEQDI7l!4z0SF9BT)jah9 z@Tk)haXH6ywzm8{z~S`;VUD0@j&c_i*W2@$Yl2~E;P(C>4$Vb|sLeb>=lA1BZW-$3 zk+_&X`i+b(fxu&(fg!^5GEaccI3%WtU?z2B;qElKg*HIS>s*xfG6bU~9E?%FpX{i6 z!S3K)dsu(!+@CgxDMsVXPO$8SRJSYu>U0@;XT$98vITg`G%==0n=qI@T?yBa5wTn@ zI@0fX1P!{j{$#${D|X`u5G8toIKcNe6fcZgz9!Gq-Nh&9PLQV z3Yr(kV_V;3>p(=+I3KvvnCN(H7hF#iwdaoG^US3*9D$BrBIrJ0MY_O#9N zth1SDPx-+=U66YBGykr}j%myVoR8VCZ1xvNRtEqQStDk_ebg=|_VKN%!tKKk{vA;h zt?$f;K-!Kw+@*w5Spo7O>EZAyb@qKce133J^AOE1@?uI->1?HG$4VyBVSnUzM58CT zC^!<3xueL9O)XVL6#pgHB%Y!w5bIk|%Df4H*@I`KxjD_ZPU?jeC%XDdl1c6@CKtca zGaO5l=7ql(e$7q5?*Gpv`bG{LPRkkFu{$(kcBE@|y7riV?p^*Xu>SA3cbGlJd^pZ+ zW@Tj+>;2CKPH|~z=~!>{HaetMbRiB7j$W^XSD~MFOoD?WYH7J&v8*M9_1FbtD>@VY z`7Nn{`!5M<5o+wr+}y31v)3`lxvpWldU~*t;E>>8y1KjHAi*W^+d!3K)<;YD+j2`k zHhH+Mtk9~GG38Wl<-5Eb7eDPU0=0jsEM1?-MF9GRJFwUee2}pdx#{21u6@IulG|xl zq|cHuo8+v}DVa2{P?T!Xsu@$Q@SJH=t@M0fGdiCwfvw;vOrk&;fSrp_Pn2&kN+j;> zJ(!=*Usz+de6_dv(HFG0n&Ob^&dnl-iM_&|KunrFwLZ)MTU@CI8b^FTZ+qewbmukqaX|rK8P@*X_N-{eK_v zOwK3TEvFN@EjwhBwLZ#Cd$9*O9hDg@-g*wk-2Kyzz3{;a=v>HRf3AR5pV@vi%$;AM z#uQQN^`E-{r(Y&@X& z=*fy1<83+XE*#9qt$Gu7P{?|BEebuf-G(SR!pSdoE$ZqzRzFebC0e9>s?PGI7?xR6-ix=neKlH5HTtfQ{H294?&jcfr))EiDeq8a1M z!qngWy;^b=6Cw}E4LH)Q8#dj43XC}w(+*8>Zy5badt#!8Zk;EEGobUEp;ImjH<>8|!yWtRthG&0J z)8eFUPZtT|xZ6%P%rN&c8~V4nbONE7#SG4bH@Qksj_0ij*v!nK!JN~<0p)0B^- zhI!f(u4ta+o0&i5NuQ7ntzp2}U{%JXcw z%X^p~WA1j3A_sroOG&5qcygmHV-q=^wVE#93@}yqf~xM!tGX^&LFF>duqOB3%WE_epL*#oraZ)ENwle&God=U5mm4`c!n+#l$wcfvV z{C?;jA1XYq-`s3-#{|M>z+Db`gz$i-5Fm}=8+Wxl-cuMR!(bd_1*noaI-idtTo9#i z&oj9GyI0CBCh#Tz+7y+NVCM(Fy^mq?v5n%;{;J_0tsfKEssr3@oy9T>$ZM~4^RkH zx}nc|EUcpWIQhBJb0FlvfnQ?h`Bd6TfvYf=|as@1V92wzCnYE7vK8 zmCs;xkd+sF5-LA-3h=fO;eMY47py*_Di}YTQKE@{eb7F{9_D{-qCjP8&H(5UI86k0n*zmm7AHNArwl*7B!=v zl~UYUVg^wOLaAOdddBf+eH6|SBf;{iEKK=b%rVIN3$S@WeGhw2*+e>irMm6**M9D3 z;Ju5_ZG5R~-KCFZceb2f8|}M%r}p!morsqHKNUbX+(%ahmbu+_OaLe}-k=1L)Ok?+ zDvI*~cQ;4r=Y@5rAemV0U}F0z?6AJlPG(?w7$KXGC?Nk6l&4^^$x%r6#_t}m7E7x4 zhrI0meo5hyV-W&U>7Sjl2QE2@yU9WUG3aK$Zs1nRiZb)7f9=zp$uIIpB0o&JZo?oo z3`IQT*?$dFm3LcP9wOlIsoMiT?|2?w=WjL8i5Yyx=Yx_iU6rqgNw^sCbBR})g8{Ha z5sJ0hTFA&JolS*=Xrf(>J(P158-@L2C znqR(Js3`P9h^@{bpj&JiM#n8_HReT4vqi_=V9-DRDzw#%bHp$nLENg#9yHi&Uno~U zzW0}!79CSqBTjBEd1s$V2tFeAy$#WyZ3uRXaaVoNChGXCiur2xSVC)7Pqd>q)Md#T zQSxM*e+1vGI*-o=SI5j_u?52Q7P>UBHc>FLkbX`{QpcF_>w^TXOh`wg39VG6dBwh4 za6wKMh->gqu>+t@HAI!!cy{Zk;saD1rc0RYH|bvq4!PGhU(RLDe^W#Fq=i)VG2IjC znK63wsK{VmQsWiwed&WI;1RkGi)i7@e~r@LG({!gQ7pEbsCc6G&5jg-S))p*UM1*x*YzD9M7J zvHFVT;s8!$w<__W%l>jcgr48hP@)h#L~>pmIzKptJ(OM)SaB#tbF*pn zYqP`vsEdnp%h4?M>zwEgWjxSbq57OBW?D^OP&+JG{(e45#@Zl^IAP@M$jd)d?d@%- z2}|gbUR&i6BAdf33(R6ME@NtYaUE}!t(eVuYU}S~!q1ofF|aw;h(+(&l!bpXJNx}G z{A3{A$Q|i>%Q|X`@$s=D<+L8D!y^bgUnTR>jOF`ijG@PSkBw(_u^wLq4as~XJvpp~T3u`^1zb3Oa zWru3$4thn`b^6f*KaEMcU;r?dd;IQAyoZNxOUg}eXue&2uJQchsD$|f6jyy(hSL`N zXv8ywem+p|2QGVdlWYc%);7G!`3n%*eq(?CaNHOe^MwdoBm?F6_{*NAxmke=(=sR7 z`;0+o`GF<8Gf*^t5D{RkkAp9(qw=@n_F9lC^yISIw~~H32M3HGw zy5P5q(sdzo%W=WTgO5EZSe_JeDLS;J@|oz7RBZVt0((c^+uFyd8GqgEcWi*4A@M?;G5U14W0e+?U&wa>OQAWByP>x% z_f!hc%b3V*QOXC9FAjqaE6zOQkN3|RdsPs&FyZ2K7QewvR)m|>Q=DBqDd*VzFrE*OOl&9Oa*1*24} zG0UKRVySvoo9PadW+~N?7eu~KL9)1?wzKP&rZ>(^idq+0I{t%PK$0f}*Mr4`GPn~e$F+0DXl5* z@$1Su6b=WtPC!3vy(d*3Pnpw^fjR8MJ%U}GwP`+T2-%-Xq7w7kjM#yCM^**FX->R= zKFwlVzIE61Ep>S@EX%eu=%Zh2SgO!;)jQZlq3?Gd!Um`WlSPIkm;^~9M4Brjy(RH@ z5k{RGG4V-!{;|$`+fcAaeYu6(yasxd!;P3JC!T^&%tZ5JG(UHGerW%I1KM;ewmbA3aV6X{mc=4*h|$EJ}ac<7K{1g z(Ph+U`p4)wx367WGyyqI`(nL9QNMUBqcfF!rCZ-YN*IL4QNlfcH?fr8Y2V#8CmNv` z#@OD7!fL%tzC2fU?F!{zf?r;_uw|hnJoRuBdhI;5r>q9(a8NKc`$e{D3!nO9?bhiH zSk^SN2nOMq4Y&w~sw9eG{Qc;i;pRn*W2&` zCa8qm9Z|p*vRbdcj6bh#%yJD#vM7fwih39F&NlG-crq3Po|z6lGVXhr&>0{d9=Nn7 zKStT^VE}Y5X&as#$-I`wqmFhKc&vfIJ)Bm7T{gLQ)e}%BH&;Lfq2?eA5#V58Nn zx(!Dv`W^T4<1kR(dYMK!gg-**5i%etOkKrJ`a{E=D6w?20!+Q+A;9o&XW$-(4ui z5?hCrJfb;{4rwb$`?$|FfU?^2p!cExWK|2n(2$VU6hdT{WzmG`89tH;Veg2{%Lmr~ zP!5VGNW)Wxbii7$#QER$YtHWN)1xNBC>AtCd1Zh1sYoMJ{EFPRoas6ChOw(ml|b-8 zyr$}r)7gum_AJqU8B`b*;m}mKIf9jbcdz5D$g)5Geas>!`dn*Vv>b!1AF_0|ZI3+t zWPocRP#H}yb&Kte@~NNFcBE8b?V@Q$x!w&+2YVjQ0KwsVKt(d8aD;~|PM+@>+;Ir7 zb`8n(VxUUmEy?|+clpX?7Rqa){#_Vx2ySnsN;x)RYPNE22;=#2aV9joyfyK#&VOfN zeOXr~5~~_CRzsaCgwN_NzM`0db^IkO&a=yt;YFgA@1#!W%+TUo?}_xxfiDxIUBPqd zkJ!WTZjhjGz{nO~G1NlUyo3j<6)D^9SEFpg5Gm%2RtaRJ#HayM#4}a~tTQWfnO$q; z2pBPjQ@ZYO?UY@(qUH;JA2p`g(E$}4u6SekDW4bxAcl|(tT5V$6-|a0=^bCw9okh` z+p5BWZ{J_VzpWb1tNp5(7r@Ub*J-|x9+bbA!Lj6SB1Zn&L~u54Snmh4z?#`nhZdYg zp*K2kv^vrjiZqg^!xuhVQazR-?63Ap-?k@dHZL^j@lzwXRr;xtORrV#nED**DmsWm zBAZ_Lve*W6czyzgZtV)7cC)*29b<~H)%SZQPT@PTRm()AD4sflmCkx-sI~LYs!9(q zmH((MXg+B!d~Z-H+jhoJ3cmd<;{;sBV`K6d$75R=&-)vzp;1Lg0=nQpb$VgXt$akG zWjHl%dS5JY*Kp%w1%8*NA{+!5ZM2OeDX_CrUsT9TV2gdG9*S`DUS-cieh z5RaxhWj(XLs8})85H6&1jLU$EzGQh>8t=co2u6P!ORu0D*?5CpReeoDt(iNz_X_9& z2J4oy8?ba-#VJKY6XQQBJ;9C8_#RQ>g^Ka2?{A>Tj3TE>uHG}DE>G2hUNCx!`A($g zC*}51A-FV;`n``Tyj6(xpx&KGi`-0cjd2A4U(|(jLZU)^G*{i_+h`r4yS1KMsFe=- z;61bp^0@VCC?DVt-;no{e(QAv54n<5MhT@aNRN}e67w)jBStBOJ|t*MZef25d-eHS zDp5#hZo^}H2$xi+aeoovHajS4qQv^R(rn_;=K}K##)_;M21g|y_TF2zzr}3TUrFA4 zI@WCD^=berGL6KueekHeGmHV|ARL}rA)Q-FVR?DbDe-(|Z54kzx&NVr;g;E4NQ_3* zjlpD3Gh-(|j-%t$D-3{_u2h5F;!B5UUKIB3}~^>DP-Q+B0s>VR)F! zVtu%nN1gWjZ3Z!BboY7HoQ$>`9%1(N(ZHQWt}-HySk_O^ZafCjLof8}JYQM}s-g9J z1-0(|74Brwns`|k%FJi{6oNdI>3vj`y3^;RWDj0{tvvGhwBpZ&iGRDBtFaogE`@;= zjtJUC^5WQ3gTEd5T?Z5EGen{LtWV;6!8^Du0wQMaUv&m|x2>Ps=!3;yyk2Nd#Mq=N z8A6=`zNR%N7FfR~-75=^mvuZ^NB4nWlo()H6?njPNPni__mhODRCD}(?%mU#Aa1*W zR2sFuut6p#!a-96HJ2XOo;5$+ORhnPlM2-)_k#c(jJ*W{-Ya|p@DiA4+)Z?Zknz3` zY&J721>|C!+bprG!(UUA`R{bW;(Y<~G98o!MNwikPIM7==hhiiI9$x#--ZV6;}g_3 zh#%kL#OK!?D4TT02hXF?);MU(nb(juG&1&P%FxUfMLw$Sdl=4Qwogti+?nB;nX|g{ z8%XBT>{E|7PSumhF$+0w^adZRONW)F!?!&u5&NwA&a3`@xkD?f8?Lc@BH^{B*kbol zSMCDSMOM(=Oo3$OEA6b>jP0hxX7(A|doZczy#30`*DGkbZ{JIc;?5ib1)I30LNo8F zhyi^=RA?XWKIC){xc*j5RkX#|x$p%M*-$&2hp&cySc;t=@tHwdP5V>topv9=9)=d4 z$9^}1cu`3m%y8AMycaFS{-Qr_$nb$=`OZ;3iK)K>x34+;^({{djxkx{l41Xocg>YW z9#2LqrUH$T2koAiNQxPjkNDnJv&$X{o_LDqMI^<~F++2Z$lZ@4@E`IsJumiuVodWc zRx?lPUk;dbv%;>|R(pFjI;ZZn?6^CUV(@fQU!;`PZ{MT}01PP5mocAx+>IT(qm+-E z^h73;Q*~ndUm>a=GMMgRAQQW0_x;bi`{gz;z2HA^x>(u-az?&lPz1HL3CkA5x}W&m zx7qqW3<{dWXJxG&o&^R8Qgcoz*2@2n!2SEoe;M(^U!r2x+Ke)s`u~d3NL`Y;zTa_Z zSMPCX>HbGzZnic>tN$Od`3;(%uL2c%!FKTfO4Pcq@aJz7_y@6Mg#YJ(yS^v$Q~1oh za3sTwdlI4$J?BC~5dv9h%hn9J|K9U|5qn(+UdM} z`=K+yD)v(Hzl!}UTyy&ziHzre{qEPZiA$?R(*EBC|MNADd`? zLI20*H@FXh|6eAkqSSC|n^8tz^?kuQ8KB;jCb}av;5ljayB!e^6)5vM4^Dbk0TfG0 zZcT^igW*hcuG!;^8MXG{&-a19GlM(+@gXk4K=a+sH{BhtOPWLqbMZS0s}K&CB~RuE zs+1nF0gh!NfiM~JE4r&X+c}Lz1FMIZ#D-t6$=he*Te~5njk_X}`*k^6A$G8JyF%=uPYtAHMZ}HHA73mX;O%N2k`Gzfdi? zICDb95&4)ppM6Cfeq)K9RsNDri7LmXb<8B{=6c5S3-v1wz3$R_F8Aqs@V&*cfLd6| zY}8~g@oOfoh=4uagq~XR?3n51DBl!BN)$3-P(5}wT zE$g*^>%FSu)9Rr9WEga z^&Klp<>|+R;a>oK(?HhwhMB}#?-|*|&UOk|fy`$wznf1&Qx>484kd~_eG;kcCiJor zzlBjkgt7TL6_s&y$SnRIz}T`fp;^#29YM`ZKz>&S!K)Ut7(Q zeV6;6NWJ&P?9g#so%jk$6(Mu3&WWZzzZsV9SdaYl)s*xn_?9$bC2rk;PlqKMy)V&X zx#uy%$LnN`HQaeT?~_R33=%}z$V6z8uia_90AdS=tjvSDy{m<6xc6PbyAv}?!1wUyg8t8v7y1TWKKOSw@Z}`837gbB zZ*BC&f}-ABqj!BD>PFN+I6Dd2Jx)>rjTJ6jEi@1R?4$LQ2$hjGATNuc_)DntpoitgLm!~Q zUVobD@E-WxbA&A#aIjPV*oBDGw$=YQ#3y@TVBjh#FnP2>RArmQh;6=dnOQNPG#nq-=B(jGR&xYNa#ggcmRC1XmirpihFI%@W1dH1~2 zU@K_Yzsl@4-zjgXTkkNuQ!2_|ad$n1Lq=(AhpjLWYu8qpEKd`%~i<^aUKwJ}{;Bs+cB)5T*y1gBoj z{;H+H=)KT(yrSnkl!#^cy?%x=A7RR&VCLq|HFG1|9&l#p5o@zs$rrv5YJhvE#u+?4 zW;E}(JZIZ2e9y*kt(wuP$k6#|_hd?Id<&mSXS=%|Hjo4Gd-lM#3Qza6hrP)@>oxfn z26W?08%_$2eB2d`c&;zH(uKz^;&B?|qW$=+UvmSdztfBc3UdE~1$?$fxX zYWnfj;sIO1&{mR!?2ES=Wr9a@Lq%)HaebXB*JG$1k{Gen4x?85ld?pEHxrs_T>5=j zLheU787*(PI4LQ^>i|qkDD7{#q~iP)B~>xAdTPpNanY zASE8tp&ET}pNv6VX9V$#5r65MsFi4ZcP&uN>!_wdNM5op8Zh_C;8k|(t^l7B{j^XGBvO_g;eCf^_G zwA8L-4`WK3Z!QrQJJXz)7>wLaFESbsl8w?wbj_FFB8Qot(K6rJX8IJ8SRX^i;@bOv zW(bNTdNWQX(hDsq=msGAW_}%Q{vsddo|rST9r~dp%4BuZ1A*|<1Q`Qk63^xdCwG?n zY#d@O$Koym0NH57SZ0Wt2>%$o%Lz{BO*#%Nx153nnW1eC{7`?4D5Di-T}xaNv+}2~S%Fo&v4#z@KC)_=>e@GaId^x&Q73*ao|R%jG6Zj27(Yqas9oBh1P& zEv)S^F6jViRET(-4S~K;7h+>glA-7&ZZ>8RspO~UVJ;H z&hwxr>`ViZB(oCLmOSo&`qBP=j&`M_I!>KY#4F-D_bp>{>>xIW!dM$CYl4+1qbvLN z{^tPXSN)M5#`gK8RFkQoTo`ko@^NZ`fcEE5=@9SlTxQVUIpfMvzMA{U-43k%4}W}s zq>l|~A9Nq7XMF_1zb_)FthyD32-+~a%+CJ=o554tf|7!^TuF%74HaTs(!b1L%ko@Z zWQc?ls&Z7o$!8VTJXvzaB|-)kBg0d~%0-2VD$NYQM^R88NAk9MlVsRNTYmdniO~nM z@>MgN`{t%X&Lh>IU^^~qkU+rq)PVev)pdDRWX;<>WxN-DmBa{!r`WPS#f{h9uHLF@ z;|d<7CJtR0bGN_nJF|C0)EDpDzfpy5ru(2$xN;WcX@l+}-pIY5& zJh7MR^9DlVj;0Qzk{rr#b1IX4@iwTTlG`hrq(D(BwA&3cN(DW-bOMG3x5Y>F;(~g5 zF{RaVA*%6m^?tci-e@Bj{nM8Y6$65kafl7kC-Z;~%CEZZ zqwa9#5GYf@*xFvrW$yyrvaTbdf$(H1z(D^D@;qT=;P)?Czbca)9;wCeas~YFC`>mf zOAE4#_b-n zo3l3#Jw1wri48YFUPOe1f$z^A>#hs7;5;f<9ET&YHQ(WfY**DO3FPK`JV7gVRtxEz z!eFot&icn|T;qUgKXirHuOzuura)ll!7*Tl=UuOPvDuR?{G3k zHeVxX+Z!?zv))K!VtlGl$vGhYYKz1AcnPt)Z|1?-0MAKbqN(IvkK;a1BQf-$=DGT* zz`MhggE6r_Z7q20P0@llFE;d{mpo5m4?@^AufHn#E?w^Tbb2dCq?Sp@#}MB`>u04S zO}|CUx|{MlI~aFmU><5H+9zJZWOfODlzf)pu2Y;8HzIjo2@d&< zW6~A6VoI(nLE(;ILPeunBweAx^RAVV@yb2xC_mW+s9Jn9;1`bQ(2EVJJRA%_GqMy_ zv-HBDJqQ{Ioo&2rb)N{H)KgXb9%G|ExS`#OL+NLcW5api!4-6yxi6I->1x!~5fSFJ zdQ^Cf*LR-dLtwuafTnzeKsG|r$UxE_TkkSU{g5N2$D?TNb#oiwOv`{8e>_wqBoK`I z+@8L}$QPygT6i=&FF}T><*l0`O70EZcG>D;x-R8Q>?0Bm&WX@!PfiKVu~f^xMl(@v zPOZ%=sPHY0srUgtAU$@&pnu})QVT^hXyvWBmM4AtGm%A}p^NRu#URdxuOU|)H8^b0 zH)||*8q*nPPIp2ofxYCbHdBDb)t*1fJ^sns!;bstY~N@?8Id{6{)nR{GSlimbBaU%mUO+`1@#MZI%`_R)>m6&O#e)l_|`WMM>!*wwo=}1 z2VtyI`htsXn?GkuKJ9$*=*e&u7blS3cERwl=;uTbh3BV?0V4Nas0>j8+9(V%Y)VV6 z?MgCRODQyl_6z-9FRxE~TxwjxW_1?Hq~x@jC;7_JFFg zAD-)>Z|WQTr{t9W|v5}L(;2~D&J2j zD`xZxdRsbq;7-ctogHj>k`5FaTY9{kAzd@>Poj}xTiG<;*M~%c`}mCA`UoXxJB-u3bfdUUP>aCWMX{*}vuXmbUi+ z>(9}gOhB$Ue2C;)5pmO3?CsO!bq$VTmDO^oCBuV+s%ShpGc0$>H1SjFZq`DHy)ohB zKO}q6^nSH2y(juY-zHk*0?e#fsM~p!HLd!z*Fg87kmV~kHRA_dp|3#5I|mRrUhP#g zG-Ew{a$c}C17d_qk9L7Xv{SQ0)j$8{WAZSUASiVDqvf)ikdV!B{F7x+_H4v7uz#$m zr1J|W&HHe{t4y<}!^}V!MxL)c!3KOKcy3PRx+iPid1CImkZd15JLhV2udVFx<@>dE zYhuQix089nV8OmS9QpQjFO=%k(rVXBi6i%yp6fH>AaTQ$#U8g4r-SmjA*q7#w&2`6 zq3bxW+~r>qMr_U0Vu8#|Vfyxtzcu}zKe23uZtP9hL0u$+jTPo|Fn3T$r2 zu{C|l{h<&n1VU<|wdLz(SHoktC;sDgn<+!8eb--lsG`kVJIam(P0B<|Vt>pRU(w3u zPIAUUllNt<+WRxhH_F|G#F-*V*zReR1$+@P93nf~wRSeDJjJJ?5zMbtVfU8sC{kQO zsLq--K3J>|BG7BAfQ!x%Z(QZm!I;zz;SByaFKDGIruMZLFBHtR_(Tpl`XKIxvQs!3KeE@D`1*c6}wEG zw!Hd!f!#Q^$6fA;>q`{)=wcTa3u=JAujf9X%o1RQJ-j_y30UDrT?ji>MUXfg;>?jsH;rEj7{az9g5zjj@*DXqS#vgrR@PKoEE>7bEnS@L?j?F`E*O`VQW$13jtQ zPKHbrjZtE@^7jZjx?EH%VVFrQ7{3dRCsA=nNlyW~1Z z8&L@ElxmaWf&>M5&3`kt@bO3zVcj5INF?GkywUmG5_uJM_<#yO3~zkjI~OdT)uYXE zOAY@VIIh7Vq3kt~-d1#umtZF-#JUi^TT}QzrSHYMAUFg_>pN!TX7|;|X)$rZ=<_Y{ z@6o2l{OT6CT*$EPtu#vt>DASXV5a-Aq?Q!de=*|uN+o-HY-Dk2KiiquUFcoJy~j+? z6u-~d-WOpMxi)o7ac^7LeE*qqBLhh4V~Nw|a3O2G%Ze9N=ed`*?wZ$Zo9^(G)U zVE}8rT0%9N+N$KzVf&2b3+v_2!ZDb&_`WPYWssN~?NWHK(b#H0#jAil5OIXpnN4>z zNv7mYgp#?IE%T#0rJ=#822uHIGDOvahxr>CI%V&gy`%UIaz;tr{bF?-p7d*GN%@lc z5Q!agOUU!j^zqNXcA7_Q_F}cFK9%xx_JQhuNM;!Zd!u~%gceMz!5i%S^ca}QDmYY3 zx7QKUnNV*N+o5pqB!z6QigsJIHm1wZ-d?w>6nR^IuMDd0U||fF`UtP?NhTzWKI4R2 zj9g%vzuFO&x#T9}eiv}Wt21vlPjglw={RRe z+%ou{cE}urcU(kfw4KWN#)D#vgh%BW>@kfqEC=n7GQBeWeVs> z!b-GzuFw&6xs2{5>WFG>2@*U>P|+3mwW$T+mqY8mn1(5!-?d8Fw$Sh_ z8aroiwyZPw+j>cZNLG95_1+^i#=DgNQG|8F1X<0yeCp#ThbbtnFXlm#6E?bgA>SIlu1Xx{$y0yv%T9=+6_LX%!SEH zoe`>7P;>b7x>#C#FB4i=*SaHOeF{pm6A<1yLrv%prse#o_GCG*q%`Nzcj}2+1O9M4 zwhD!c?4OZQNN$B_s7s{ONWcmqv9fh|C!^MY6T>aj0P#7sh7*M9S?z9Nzw?}45`GsV z4y=<;r@NqXF^Hvl0!g$E$Nul+vhq=&3QCZ22GB28&ztG`?CYy^Vqsh@f^hXctvW0Wg6*rT-ox^Mj8$9x+9}b8X{yMps%RaYt!0@ zaz)rKeSKJ{7XTjvB`YqsbbQq&-09z~RNG_u5lbmNxa{+$D%l^Z1xp;tmHdK=Ja4y$ z->t7Fr>DB7qZT1E6`nI;G31*1n^s3m z5DuLC28MK1`SF9U*TG(VtKrj1w~DvhD%z3?X*-=Sg>)4E2=(8$WBpitAUphkbr?c) zxXCcA9-eUv=XIdue7sJD`Sp1mwd~!yz)!01k5^&L7}#y){xb%$aW^l0CzU<;4p`I4 zWUi(*k?|Q7`0{-OFWX;7==f!LV=bONG4Z?GU z6uj4L6vSVDDOcT`QIhiJD_Mxwk@Mtbc_+x+AV@5+RtfVtA>_~M1EDahW~@n8l`9&hKQy&*NzWG`>Dlgt=F)z3L92Ju)9N9_qe2bQ_lp z_zd-j3Skg+`h0eMNsNANNXeDONTd#5c<3J%;W5D<@M$!x$^7kfNOxn=`B)e95a&+8 zSh3dxyv=G5wT@N=wE=O=J`%CunAN(1;VGfh%3Av1gT1P|dC;3v^Y>?48PlkD8#i^x z;ST(uXp4&j3BvBCQu2kOptwwaCshS_&ye&1wfmVO)5Ofp=|Q0nGlKa~W;8r1SIlLN zh9%5f<2lZX9?RcCvX-VqANb0bG%m8LhO3`+6&9d4DbGnsS`Th+TYE0uo#>4ap%@E; zwUHd>@T*7EsPkTCei3yxin%eOa>f&ZAs5Z2oaEFjHnmgTu|kLVz-1rR@PUfx)`V2M zvTtj8(hUbB2G8E4!*#6R8*6DT28Rt*V+gBNE)O(r@nk)e2$zX^Kj|^2t&Td2DGwOa zc~6wdr`BQNYt$NKjZE{`F_pOSS?+GCuv~mzns2*SlZ~G?6teHrKl|cgtKr?NaYu%->)$UuXN-)u(wtf&W zn-@zHP-bE|WF%MFa+BaQK^8jzea|*FqpTT0!J~aX{*bG7L&K-tyQ)qdV^izjD?1oW zkeSsSe{BAMefX2fE9LUr>l)1yDwZY4&ClnZ?=`czsx`J*gT@FdUo~jLf*{k9*?{Z_ zJ{WKEK&R0(5kL0~-Oo2#r)JOI%oqHoLznjU1^8v6 zLk+vl>0DeS;_#>HSb&y>Rp&lP)H&KblfA z^_lXj#3p@N9Ilgj&0#co!3#nex6D4CQrl%4>QUDAZ)rqPwSrIiOT_hwKW)!=ef)}H zcK+k3M)1l481QsZeif95f_{`ixf6?}MUeSeM!W&L-8G#hn>{Xbnq@=f;{ZsBx9ZmcWMvh%eqf%Y4bIOUD?qvm?bu!arq zMo^+s`pEH29~8SXFE};e%V8k+?&VgL6uqsy>h(r6pzoN_{6&%CcF1kcqVBlO;KBMbDIDKwF+x=PR za`ofS@77FR$8a`Q*j8CS;cdB5+JL|*W1$jBQr>Dr@4vMC7+=aD8fC7mFe5Iq$6UuW zv3l$#BiM0hry+MRohtFOahlN1c34NuV2|5UXBCC-^sI|=qPwC@RR_9`F{$_Du1hSJ zO^J9X$Wo1 z38&`E04HwwMco<9N1iFPt0VUC7W2>!$9{(5zfp$_#_}8FO$}G!uH|8++4R*QuTcfw zyC51xySu#Pnh^gGe*Lui+Q+$@$k0gcK^%=G*fRupQLF@5fb3s=m#5Yu8=_RRkH7S| zz~Uax2=wpv8OxhD$O*cW_fB03Z>Y0Ot#4Q~*t}B2)0A@B4~R}lZg`_%_6l?*42K+B z%)UUZt1QL5{=(1CA@5G*WlgI&KJg3$xp-y^ZQ6T*(uOe3z|o`}lGHw7fvYUpL0b@S zk+`x|lbI*q>Ovxr6w2jwIBcuRkqzFuah-VrCvtOdI*G)N(_{{bbGzm9Tt^5zT{}1K zV{G&{A6G#Qk&83@-tCfr353N?2B#;3gAp0ssD;AM6&MWelODmmd@73t)B#?mF)ux) zm}or7JS?F}rAf8NJE8enT~bSN;*dLjX`}|u)|1QtBjxxbbrq-$EvQGW|AUOlhN_Z~ zLBKR^m=h2FcpH2m7wGuYZk0#q#ZkvT#dtJo$gTO~tcJ$s``+Yu&EZ=5F&?jA!etS( z2#=p7p-@uGXH`{_Cf)=X<4e#z-?;0^Xh2o->546j>?LNN@0i(#W&Ez>y|iXL!fv_| zifC}Rc5K$S?$g4&vtCtF>I!=H~ENm0HS=4cdM{eoM${FQ~;@kd++k<^|`&#}v7DTQyxTOx1We)8(@+#h

2 z*R9j$-RjlkH?IdB1~&4q+h1^YRF7_4c}{YkRx>NR897>Eju!W1KTl6)EcecS*s;H{ z)6v$`g&{XwdY5wcKW)8F?5OjTIcU)Qo`(eqaN@vj+fIRpd!daZxdNjPGrXh_M8nZg zN78CEMQ{%=pGO#~ZQB100{;Px;)}CaPMOzl`B&n*HK0vr-eGBc&m?LW)grEgE|Oiy zWTSIAT6FH&A@8oJ`tM&!d)y3-Y&YKIQ%w~&@sb0GJVkjvzHB-~P`Xh}Sp|#MuVT;< zMwBMUwy3bKuLC@$0~8t`u(ldYaG~&cUy)O)#J=t#Kcbl}KMrDEK$hEK^zKhm6zOfr z`5_4&s9(9PFW1J)^er}yI5q@r*rjxsmf+skAfB)Oayunzt(&uXV%@4?*BZ=^!Kf+Y zMY{D3EWy{^%WLj&$5X$$5&SN4ArFs{1U0p7y;2vC#=_{TzMo{X3Q>4BSf4(l`qBdm z|F=&OA{9qMUV+kAL7X_10%#evX3o%#!6u#+$I;gk^&&MhSP=ekj<03v9$^Cd)(gMB zdpMmqxwGlo+3qf{3+7K3blDx@=!lytQZi{;Dk&@5DvX_phmpCcH~Hp5GF6MV?OmJ_ zq=Ob&_xE?*!5M1mM0HuK(p6377k=##di5zWZoV1aG0iRVYNM}ireT$S(9XCdrRjs}l}c)fS{RIA0ST+- zEg|9ew`A`uNOoZZpK?9f*e1>%Zw?80Tz1p)}a5-5%0Q^X5tyi?X?E0sc^aiy|vgb$r4MOmy z;pu7qjn0I!((KD>(D7i>iM`QO`O!8)f;_F&Yo+Xv3gX;xsa6?z$cs)whiW9jQ%cgV zeWv`H506X>y4fF(SFMMr`(PV4;O|@xhH>CI4fpX}ZTeSD?rSuCJ)grdVTO=Ip3);t zjjVBtfPaoL!42P3&VN?f)48i{6JD5mY*+n`!{aUwIDAQ5qYA_Mb@%1rBS!mw{Bri> zMbh?Z6Ao{&Soydb+?J56KG!|k+kt=vdx$(!&>C1)_X%7hE|e+${BIEWRna3pW?im_ zJQqwK0%SL|5s`_`Pab)&9uwkMj+c>bYC}cqBDRl#@IcfV?fEz4u4HS=EVf=lNQhz0 zZ3cbzvc%3?qWA8e%(&EqxSQSwvGbGi#~DW3zo`JWD4fU(7av78u>ZRk;OL5H!cGpJ zI7}Jl{SFr^$c?9 zwEG(pz>#(Vhqn{Lo1Vv_I4Cgxz#Z>DLQd#Yc9b3u_xhi+$YVP*2G^a|epv+Jib4wZ zbhbj_vwxoLDr|1;lu$H!zg@jRlNJRRU7;Mz($XnrjShq!Y!i`RVA=EpI7Q=nFWoz| zX2MQrHj66gcaZL+n+lZF`T!NCAg(0R@W!|pJtTd9-czCEW-&9Pr$6TAidrMV9Rtig z0gDrC`&T1dypLu-2E*g=vkh@D`ahW8yk1tTW4ynuQsOC2a3NAy${8I=X-vjq_MFG0 znugTTB4!?FXnZB+n1fi2T^1II;t*DuKw&Wvsr)~a@r9EGFA(u2!#PnuPaH^${$TzW zuYlcMQUp67y>}kQYK5#*Q`;}$B6QTcbdH3=l)GDG`~_0%_NDlBVie@8w0Xfw^u%lx z5d~$}uAoU54K2_#GKf;GEj?4Bjr`G|tY>0{-NU^eZ?XZ2x(?%ByjAz2lEBxVh6i7y zy{mO8GM-pxo5(Io6-xfX{qVRiU-hG-IO99$PO_Oz%xvLy?R1X7KxsEisrhS;B& zePBs%r$?g(;gV%9PQFVj@&4}H;6a7X{K#dx#&27;7zxFP~&D{@2E}uWb3}&8U zR*ljZ+<_vEP+iuvzZkWBZ|`&!au7QhYy5Z+PtD?^35~b%Zgv~@*sV;Vp zc-g~j3OyS&1bh-N{E#`e8MJkPUmbD><9p@SeeBsms*btcG2g%7KI6z7ntwFxjc=jb zMwoRaYUd7!@A7GHxkD672AkBYff@8MMc~17#0XDtnJQ2 zbzpz;BaLg7*kr&yB3l0sk|En?z8^<9Cs+G@!lrv6vOlc^poB4Pz*hE|0_QVh zp!#YsPO@clx{W_h>z7{ikz&9LBZ1R=hk_-L?F{=!cD)om>U-c+VO*D8tsIcnRu$Ay}Efp%y`V`wB} z&;HeZ22wJd>KmME+nz80@K^j=;(U1GFnJ!lZDx#XD+dxaqTxb!B>_%q=XmDgDOBjp z%a>sIH7QTY3HR^#4)@Zaviz(EhiboTkcrUdpNnZxJxuDbJA6U7wk5goz0JkrLJ{ym z%kl7?CKig~jsTMgN}(`iJdXS*nFGU48v4e@i}B)%L1=`nkF~;UCbi%5d-U`7n~vtCv2XQR#v{}G(;`D!a~Dt*xCcSXLr&_6x=0e990o%pxfwWbnF7QEX`Y0 zY>{bB?hu!VH0^0_}J3gr_(=#F|?pj;`LgYgOr^ zn^*_i@i*_XpmpDu?2(_Wp1)b}wR8D1HU&=zFvLn%ERGBHzm7a|s6lH7e40=)wPw{2 z9jLzzGv^lHAthS-FKgFCS)*(Yh}9~=?S?0m*`E0LTlf$R4!>VIm8wf6gjRhLN5Dky z`j?!!a3KBQ@X>V}KWj?cyN685%aMlet7JrobAcf$!CcLjj_LZexp1F5XNbOiJWBzT zH7FTBf@0xR`jj1U;RT3lF-s$n{)&l+nHkSE{oOE{fR7y#6B3-U8;U55(94eA|5;C4WMI3yLjJulo4_wnw zp-aRaf1tH{J;zWXh3vjA|Ihqk$Jij7 zEVL1cs;AH6ti-GFqlXl!$KGpJOzvB4{-+cxThjJ53GZM$@GJIC$g<30&M&OC;hj9n zh8#KCHRLS^emMlu+GhCTT3yT2vY%C1*JWo(a8w$booH5qx`Zj4QId@LBqT~>@&;s! zRi^}zS_OuKSR@Jnu-tP@ennF)t~u9@&#`rTO|onQRftiP$G5B)rJctEREUE2Z}*Xl z+*^(70=y|LlpL(gY@ggwZY$$1YlvC6;(9W674=u`{kkpQh^|>jTIhSLKf9Fb zwlBb!4$o)fAhgU?|G^X?5z*8%D>Sn4iRS#0q5g}vq)vSipw1)nX^bBvPIo!-89;15 zu}vWeFTmK*yB%E zwzh(LkOnXZ7yggiBAh3bEK~$We5Nhh6kVtbT`adYf?;p+Q&|?4HrXyH|G?5o9B?c0MPwmpvkPRr#HB;g%GSF@;p35YD(Lj z5W0efax1peJ%NI)>!K&<7M{TOTI+l;G0(ouUM1;HH1DFD(S73=Q}2O@5`eg7UxZd% zZTs*IC+eY9RvSO?_e zO4ANNf^JtwpOqxp;v0JtW0*F-%9hArDRNP)UiYwK#-m(i*{vBj>3fcl@?{!O2fGt3 z-4x~T#>?3tF1yC(i^>?t*fW~!p=nc=tBA2Vx2 z-+kVJpFoC3Vz*kSbjv<|GgJI=dRVrMm)%~0DN=0xJW8V1mkDul!HrqesK<^^nUR>t|c5JLa z-rJ|&L9xPD{A z%qEqJBIv zx4Z8joYUOfx4UmuclEF8_M8Hm8rkQPO$~N^Hd2kj8`Ltk*P~n+_M`zwErgrvZ-jl@ zAkg@5QsgJZo{Qt38ywrQR5i-sXcIQW?h^tMvq-s_00N?YPLH5bIj?eyBk{%?v6?@0+fL~-u0brFagh4=q_@c%gy}Ta z{KG>Z;2=oJqMqba4H+EmVy?>Fh229dE5&(7@eeDJz}w}eNhqxX)MRlET4ppJPU(p_ z;BO7$qLKA|EEA$!9ZcvnY>{zHKduo#_cj|+F z1-@uu&Y2QzN6vV(y9Z+`wGpi@)5Pu)BR|_xzA87CQH7Sp z)&hRdi^Obn&^CCNn$1H_K$`)V$?Y&hMouR+ph;d>GR8ZDM0Byt>&|6O3s|hi{4&L< z8wgz|KBL#3*4hx&1@T^U1)}QPaQjb{!-OAT$TN!Zp6_z)5z83?g@T)c5IYSEpMw!m zKHFF9nJX|*X0^n`_LqlW!mNLtwbsp){E(JN!YQAE0#NJrjMASJ%qqY=HJt3W{_?mg z_0*}BGQ(g^Tpu`k&7tr*+C&$+qz{ALp2cU$T}+mAx}mju+6A%TjzlEP+>WMFFsez9 zz4=E8a*~9aPa>*sCLYH*NgnFt;3Y9(p{>bml2}@U0I;dNY-AWNhGNvRF08w zie@B~cTlBV@1MXSy`U_GUkCTa@qTL_{?7(Fnz9sB;hN2SxZV!k@LAg)O9T`X2(#H2 zvhQoDVY6dg%KMC)&m}4kL%(mqv1C1yhy%J@GP(?3O>Q?v|-3ww;Ua_5>r&c_(3YGh`dl%yIybF!&nHOxx3SkX&;Nfc0$HU&5+)?bH;<$Iae#}F>sT)qXv_M*i=3(=vMOp zIZM#LERYe~1Ke+8C3RP3bZSX&tsz=iNo#CU>tcg6#+SJ-Z|Y~63MGpqi%T2tv4yO* z_h3koeq9cXTgo}WPNppLVfZM!AKUDVgjL%A+SL$-J-P7Xx0%RMpK*kQ7FrrIr)|T% z#~(%F6L@?L7p6UjHoYCy{t0fX-HEI#poc0M1biBR7h^@t4L`p#e> z9tkml>{oRr!o5+`Z{Ij4I#|P*T%w3p8^aSVIyQaVT$e0UvWEk`KA%@O zv~qI5v+G+-@48S*9dcB{7VTHX~rR8>bE5JX!{Akir5N__W1QT#&q{)`WINgB`w z5sH^0Okb!ohTmQbH`_}R%k%o8uLEheym_&7Dvl03L|?4h;-;sSt+@z=pRcie4@eDd zZn^57*-l|Js4TMp7}^zE<8BDx!Sm_ zBa2P`a{JBA|8jekrdFn_fCBTCrGNSQa^;E1PYk^((o*;3g+i5@E>}sHV2-!8pqcD9 zejEY-3JAzdqbVf zjyG?gKL5S?=@cWXG*kqr_FlCRi1;F(g3B43*q5TjzmW0&v+(90t^5}Yl^M?fWca%x zvkv$Az3i){H8_+Le8u=@8iD38*Q&>570cZhd9Nr5c1jAAt+Uy!ky!Ip0F0@;yUki0 zKViPy_Fs;E<4<^ZEOOhu$Z*J$<-1vU#bm<&Bb9dsrKhME1AHFT5K70-rb&o1>%qg2Jf@79sk9*r zGmF^^c`sGP8qlu2e7+Sm5K&J`?(k?Wq##Gzun=yifkhJK6}7M|7YjkH6mHL&BsVA+ z)kAJu*B7gO9?hspLG_CH?bg)gYftW{4p`t6V@ds$^}B4sBZ3V+UH2zn4Pppf*aY{^ zV%m71x@qj|g&1yJzfP$u$*E?0YAnbVs>gohPk1sfEJWHRHrKgNrlTaH`IM32z*sbq zwSD%~_+MQx357N8eV_W*5K1BJ>E$^4cE~j9Jh8D+knoFE;X{R}TS12VeF`*gqT#RK zt{%+$^$$-$vG7~nlVATg4Yg#X%2(G6M%ig8Sc-z6ZKtHmYTzKO!6Del<3-)$2q*7#Z z|FgWG%&y2<-GtNj%Z>MN2mGEd*W|4QF#BO*)@1w1! zAAaf=B8iAWjN&Ai=IamY5hf~TvF86ecNeA)8`U87+T8zqj`0->K<_5J7>v8<@{UzM5v8V7jVX#Uo2&b@rrGuARD)FCsrIvcDsKs4yC#3 z=C{0KERFAQj-^fA37jw&Mx=|h{#PhL{j2DH+3e^(&#mOl*($EZx*2`_2a(d!LwS>E z`aOnsG*8KEW|V6IU_3vMhQwptk$d+cwCPI){_J<7Vf^oGCkPeqE<5BubwxGIr*5wF zzw;-q+PCK!k(8V^_Z;VM8SMW~>+jT0w{H@sn=#S852}64(2W`wf@^@e-%zg=So55D zj2pLhH-c8QMa_4Rql(t5%XN|Kd&c|+8o(+ZKTf2wIhijmj*SV{2hNbKLu)Ik>lYo+ za0|nG-PVjh+9K$A9>JMaT7tP-!N0!O_7vxeVMD4iWFU*8ziKBi*SRn#tL&C)TOE%Z zlE$R3XY4L4xzDaz%?0CREHs^zg}7LIE@VanX!X{s<3-zQ z7n%bf<=pv{+g>&Z<%5-+JE&XQ+k;bg>T#2PT(1>`g=8p2PipGVJT~Ym@<#>sBKV2ZLQCuqM+<(^7_Qm8%;Lc@SnmJpQ!i^lDKc`bTK(zAH;vU8^h78da$)m-~keyQlunLg~qJS=fV$W<%X4lRp@v$8eF- z5Tx(j5f;@pdeMYHd}01AU@@B@+;$;*G81$U*SCCCsl3@|12am}zF9Y|rEGKO0~yIf zr{Zc=*%Z6mi`I4SBBv$nCaumIpanIdbEM!Pq9H`1L&mx ztY2lsrq#w4Q;HvV+r73aorjkSYT~cj^ho5Uel($+@xrAKg-sTsvmYMtGYb^Vuf#6I z8q=U=3~xeHLdlaFxSwGF3=!P+TOw2x*u?&)2z9fc>S7jeZ{;xZhGq{Im0~>S}pl%jFhTe*pmGU}Uw)X@zaUCotBH>bGD$v(76xQAPECj^-3h~z!y*&l-Vz1v_(Pt zO<9`aF9LEjqT2W%Q7iJVP@Cv~0emW$ZNEeR6`&ds+JGh`VvuyCuWz>u@=uKlsFv07 zI}4CTl|Cj!b}f3=QsrCtQ`c{(^Rrm+_kH&KC`>^V)RprBp^kMuXIX+?4+Fye@9sZ8 zMU<%#uG=bZ`3`C#c^LXN7t_B?Ot=nT37`!veA`0DKjItNI*MoQD( zN$sE~Wdl3Q7D;PNSLYcts#4T}&j=M272GHG=JJ7mPxhz_0<_E3T+bBXljyaAg~v#bG}k5LYXM;lWJ+IEDtl}rHv+tnAW{fm8*HGnS-IXef-_8?=#rB!3=XVv{zn$+hpKz`q z+}MY7HGSv$LLcESqZp;v&ae$|z;0rgYIy>b_lQ+Ogvps!`VCO<1DnO#C=cqBNYS?X zBe3&cbSGG-{OV%Ls_q^F)NRiOn*>pPsf|9(aEC5Etd}G_ars=7zjc7!E^D)uNaE9E z)`@Uj1H)f9Q!5MPd%jv0HuX}Ebiu6@K4xgR(K-tnMBVBC1vRdyzteNkffjta1}nvt zf42eUTw?Z}2xJI}OAP|*i;p0V5^FSE5=WkgE*!#%bT!1<1O*@9aRcgK7bgX!@4osJ z6Dke-a6E;FTcor2hzg$kE_8dS|8)3D!#8kV&xOl49o?8DEJ0+z{Db$3LnK7MoLMS;eJno5RBx)fWza%`o&FW` zQ7EQ76_jd*Q{Fn5Zli>x1dUq;?N+R{nd@iu0eBkT){47$$=L5S|0jaz*ah&$eMVSu znN>?}G2$;#E4~@In;|m<-L)U~)tiC`MOzTc#h%Dmetka;3Wv5g*|Hi z!&3R3dCtxh4WDhzS6}la^^TS}X(W25B)DVE6|hr=2}*p@980gEl6nm=5=d2KzG-59A{)aH}H#V>XC@bm-`&x(kRq-S?u zW7_WFnnF&>xKwtWTH8AVg(blfY!dMp(Vzq36V2O$jP6mH3kLadxDNR1UxdR4m#Vn5 ztksaCGKMb(*HX;W-^x~w`UQp>8EKlM(uaQSCI9-!jUWn$%?Q*s#$d`W3+}kir5Yq{ zKn0OA;x@Ftxo`6JU~dGYSfnTDrI#>a}Ra2@w?w(&A0p*DJJqh=Mu%m$n( z+ee-c?6wf)WR3rx6mcK&SbR`t3d@as`W=u^^?q7i0w_aW$)~XvF454V)+G|r6j>&J z#G!ZacFH_iEL~Mb`SPGB)@X1%@fMl{v)W6b9LNe8En^byO}Yv^uVD3NRR%c^ID58V zawa8B)I5@oV`$z#6BM>}#NU8ojMyKsX20|Iz}HbO5Lc1XI*ePJ`Xq{(Lb<~S&vXnnZY?iO>AT!ARJd9EU6&#F^K3fkFS85HSO`st`li7LAaN>^MvBx{)#_X5X$4+P+C#jj0;- zC<#BxgFDVhw7M5HlJbp{D3JMe3B4C8b4Ievs!RF*2t`{?>M5T;bJQvWe$%&}@60-Qbve6;)H2wtpQf%Z33?=~=xlHlHK#7FrS=2(dKW7?RdB2^Z{9UY!l4>^CbThu8OGHt>Kh zN9-ePevI>t%aAeT;S=+{*XQD(EY#(?pY7i<%M<^>oiI<*uTzPyyQH&2pl@a48TC2e z4Ff|}IvcZeXr(4`6w1Zm28nA&yqu)RW4q)PAPv9P-CB)6R{h&l3&dg0jv4k2Z%YqP z#EbdYN7@)6qt}_ju=*5*K310HI-=8sR1Cyg21{)Tx;Vvab)5SX9qkK}(Zc*Wb2cF- ziE8@{xZx*u6Z{Z{XA&dF2V>OJh2{a#yUX3vhh5@&2-iDMDQ!JO4P~)?;jvdV+bPI_ z+d8`C;27t(18r?B#6ipwJZQQ3!;T=B4)o@zJ#8Y(=YWX%vwjYe65hfW1DG=!yjSB2 zTXC8P)(i3DRg$83sN)#;Gj3$7>0Tm6+_%#-ZNh9AJ^U@Hqk_!0cGXs?#m zhcxxJC4wr_C(K%j|GG7knl^@n7PlC8?kgH`_c;g0w~y)DN|YE_MH&s(lu{=oy=cT^ zReLlWw%)a2tQPb0466?;ai}9|*R|-G*PXvE<_BtIeDXY1S@MVdwLO;hVLbgP(bS``w6$pb zFl&!P&YD1nk{)9cSXl)wS}3R0r4F42OdOKHh!OP8@AWy~ zHOJH@aKuwz{^k(N`Yn2=h%x=ryk=MH4kHzIL*C_u ze0peoW+qf?K|S_A;iyMS$V{`Gf8K4;Di`q+kfG%U@r1zgW^>$QsV(PQ8~9m1!hoE3 zJfR!S0rigOoerJSnU{#)P{^IZ%k0ifz;0`!i9nN4&oe;=S3)(jd5*b}w9UogF47tR z<;`I>{xE?K_ZvktdyXrXko)Hv^c!3HZy?F#zV%jSuw66#ombpLa zj|^^6&U;WatkvpftjKtHQozq37#82wT9p!oOumlbb>@yI<-`JjH_4vblU2kO!A8C; zaI?CEj%cjffGfLJW28&Yo99P2yQKFK0H}K!S~iZp4Gg^V`0SW#lfr*77p0_DvDP^U z`4-zu8y7MZQ6`H&wt}0cH+8Dkl=p2!sBHW(angP6sAxi~ok@3T)?}^h&D@z>zSle9YS}k!l>)+xZpJ{M>8X|&!nx$U(ktDyB4LJ*g&nMW;CJMy% zt!yW}CD_o?MVRD&Q#OPg4opW7x#6oTLDOJVVrL619(-jSW|EIwU)yTy(xGqL*Op{5OKfcAhr0HXfM!-hP**8rMjJo58oveNS zxSIhEv?M{lKSTrNq&c*-z zHgGT1Z`ACl8s*juChMbfJ8jg4cC?05CDl_}v6D82z7eE-lpXZ^422Z1v7scuydM@A z#qee8y?yxI!?v>?ju#rf#oQfYKiKJY*7=b{~18TkBe*wR zH~qz$fc#VcZwx>53<;Y?)~IYnxePKNr?#1eVrvt=db5Pg)ARyp+!WFx_YSi{`C=J}Wsqu1D)U}w?M?4}9UPzA0G`sO+c&LgemnLBxm+>zrKRkWf9y|c8WdPW z2*m9@{!Wp7S?xIgGrB!R;>~hxvFaLmYD3%*glk4~jB%mvM&Zfsd4>*^2Ipmk3 zHu-ACEjvyFrBG7d{G_L{Vn|TE4UO31dJ*CH@mNrgyN>F9a(;9@KBQ^4Eg0mXG=k-d zU07qiNW-S+J@j2gD1~PnY_ncP`<>F%4V^5zd}Oco*M5?-mA69YfxU3KTC4chcQ^OG zpK+3*97)V0&=YSxT@axZbRWY4NzsFHxo*V9A&*_yb{C_x110mh+^c8jp;#@_i~yB3 zvOv@|4)+{tQr|mH#50B7J83Li-fK?ej#`87cVw%CsZ3L-Onwrtm^%I(W+L>&F?YIZ z7g$_)#fvBhdW%|09w>?>d1a2po=R`Z;xMjOhT6<#y8_6Q8pAYP-dlpzN=+FTQN-8voYM!7mwGo7A!`Oyk@ce zmDomW;rUW9lqHe-EFK0(61{AX(NoSPh#TS{1M%Np+L+=Hki|`xWDNd}Y6(`u23zRL z+kB=XzzHI*JtOLd_4>E-WL2zIB<1m_;1>m&XE{lDb9hZU7M%6*erZOt{+G7GS4K0- zdw^hTyvFsABpN|bI5AIr5e2=s5&QkjL#`wd=uidc&9$4MQy z7k;<;CjVh{-GuV{2nJYi%hp>y+I^?QRYGlq(g7@>rm4l|`LylaK07$Ym|gR3^~0wk z1oKZl(zb^LNj4*!>d!r#r+a<#VUvQx(uXw?SUA|vaSO!e$DF~-i?0}PtzQ!)B0gQSTE|A+L*SM5c@ z5d8T}Pl6L#ZXVpQp3TNNLOMpqKGWKZ8AajEWH9-hsb8r8=Z`fHyEX0RFS|1aQ{1{R zGTH1IqE|H$o|Z@#f-uhgf5KkWiC@3QW@js|w<|)Q_nBquWMXIUXSJE}_tktu-MUNeRsJaNN;POIM}+6JMK84{RgUywMfPYFO**M9BMFxkDv=s?5ge>cn-y zpRSBJr{_-;b3Tqgtjc{iHj-gO{*GHX4I>_pwX`%%HBYqbedZ8_iL@hJTjqe}SMP^oz*)<`#{y|HtMKMh8!{Z&o`i~#3PuADv8F8-gUHa#Z zXq{l{c&gv^N&E@9tfl4TP!7zBW(vnFKB=j_MhoM0KhJ@S2S;c3iI9mH8&gFa8HPth z@Sb}4qyEWj{n$_ZsOUz9LH6$5=V#EJ(?%y0GUanRr}?CRC@SG=6nKk;D)Io4jmC(APxLC)QXw4I3O1~QnS((m3l8GoMg!8JNVq@84;fL7SxzbUTu^8=v4 zzJjL=4>vden}xgJ%p4%}^$ev`Y9{9~9lEFT?^6xpET}}#x$?ep!e=ps6;F|v* zlYjs3@_hf_rxO3qt^L80*EDS~|GS!xcJozwM18_VP9WwzWjydP;nelx7%Bej ziEyLcri&a2nB_`)ty2XZC_U56pwb?-z7{)lsSIdnyHv;WXeVAeCAkvnxa zM{f{tfjNQp#e2yyq3~4oY?RhB#M=QB}b|)yy)0wm+`)|eWbn@P53JZuw-B1&E|9$ zgaGXd?8xkf+pXOFZ~xO%HB_x z${J%?xUq49-r^R7X{N(kFO_aDztqtk-m_X8I}W;4X0x4QWEoz=cJt{8MM}OSU9~n9 zQAlJS`4jmfy<2Aq3~z@#oQK~tdupv(ygHJ+;!)SEk!|6+S&y%LjKk4Kznv_osq;?oxL4IST^wvh<)&t;RPubfql2VCX(Rw>C=;xm)vJJF%x}y<6JbUtB zo6(!de}^HnqM6L<_=!{tR^0gcaezSvU!qptY9RwCv5j1@Un4n^lB_GzHE#a6c7yD@ z!1OA+%;3?ksP;PlIoMqKh;*fUqCzOsT=?#fRdFcs)rHZ~lQ7u)(j)vH`x6vhklo(& zT#E+FuF0C$zDXftan9szAIwpwmCagdbTse}(a*<9 zy`I1R5U7H1d44S$9v(qMp(L`8!|q`RQb6ia+6OPoTWNd*Fjh3C_?rC)Ext;r)n~G+ ztjJOCU|yD5%J995roK3HN)>ivW2Ze0EMPxyJ5dU~{gC&R$!Tph6Ly6Kl{R^nweH|c z_KFnxqs8@+ilB9yMYiXPa(bFsYFl59}jsu+Vs z7?z>1q^}FE9*85xJ+s}`mb)sB(Q|Len(N?&GzUgHGRL3pT$M2^0$E}|sfHnipeZIL z)zG4}fFB7fQc;yueV&$OH%d`nqjBw*(c5m6(fcbQdW`7pl|*#x9$=B?`gy>`u}*RJ z7dK65N>rJah*a&}r9D8S z3JZ>ZMy&rFQZ4a^mrA=L zlU&qpJimUc+cN{P!%y5t*-bVIv!7ctk$W)W!rsJ4R2AWo7#bjr<@BL@5G{VUBBpnc zybi7~VP^NaAgBQgB&&Ln?`Hg%5V(DtR_mD|<7^Hyg6k)7FdjV$>9I?_pO5yoh1h%| zXls_Jwdt}dL#o?bxhjP*HMcWyDPB*U@bdFZ-3`I4GDAp57Q#A5}b73@p#KMRbw@=z7sz7O z;TIR#a1LE_g2BepGraT}A)|>HS6>tB-~#5J+rVE%X7{j92zATH979ut%UMfJr2BSF zvICfmcTnMs!IuMa>$swZMI-ngCRT4X9zsf^PMu&He0WkL8rBq4@hIZG>~Dx=h*+aQ z=Fk?`9W}fiKIg7#+%^gyvb%Jyf}-WpI0E1prDm9?&^!Ka54@WjT|o#PC(%Sa_Ws|$ zzq|cyWxUs}c8bs|fvRO5tr+41tl*_bkFakUZfXg>3bewkf5=iOG2@D(k4}B2(ZT4q z|7AY8u}o^*>UDQo*=h}wF89LZEH6;{1sRpGi#z8=q#t6G8c@?C@{TO(!yB5+5Dn7@7VIVxZ(v5SFi5czZAAn;pm3^337d%CC!CFP(m0 z7wp8AO?3vn?Qc^Su@37(ImNb${5xc*Mxl3e~jH`HLpzfu!w2)AHn7%p?PO4Q6c3Mw3a&f9sB3u)gK_ zD!w-<)H=x*vZL{K=}pZp^>PN?(DEpcc?#Jsw+W_KnV z%We*R%n6XI8^rp&qxI9R!?0x{UdBH<>4;bCpS{Ru2!mU7DhvACqM9xobNb*G@J9c6 zJDGKhnZ@vuNU~mYuewgQ%#ZW)=rKmGDa&Q<6pEZIxe(6q=PM1q8z_>L#DPV(QA6cQ3bpudi#}P8T8bbj z;&&cb4GnCj3SCooMQB^gCiYq?3vCY6P3yhH{f1Z;kdep(dp(Mes6EGwEB%iS6Vv;kww9l7Z@F;P>k3Tm(?b7lFLz&Bggu%fTW;+SVv#~pRh*cKYnvmMqC&L^WHe!<2sOvAR$GWwl zTYH%nvs7Vl$>Y@PF@Z0W7#C^Hc(`{p*zq0W36Fr!vGYn$y01`h)NqLL7vKjEYovps z{@2JD(woh|XcLJdHns7z;iX~{ly++rBl^q6%eX}ENBcrFm_ZGWAhWE6u?QPNV&6>n zCE6YKT{t{fC-e$JK7X?sGZh>;@|&L@)W$PMA5WqO8$Ds4{rJ){sPhM5q{F}6f4lk7 z@m&}{()8SP2*Xn^Mf6zM5zqa{Gp{LXpm9{n-~zJ20gMkGXOV48GLlK9e%~2kjnRJG z4B%tX<8%{{D7*EZV3Ck)FDi*63SR7+brxIl<zA}+0&~uQYEfL;>oT-X6W-DE zRH^AiGnFLHh;IR+*ER%-$0Y*`*_Ap$`N)1%5jUhipOn?C2*@U50hqAcK}wAQD@~=Z zLcWV1(_T5=7mx+~v|7R#95H!z%AQAPiD67It=X~zeQ~ezc0fBaB7ca4w*MtQ2Qk1V zT<)D}2SR@wOBW#v#mU^xu_i7(%^1N^MjUO<_^OC*jLr|#doS-QY^e2OtiZ@^Ltkn4 z6CAC8p-&l!ry2Zx85B1snQSJ^39506IGSGu&rc z%R@a04_1sb3#PwHjKKw!hCxZeQv{Gj=f$9ecrdSy)G@bcx(m6fgSHSlqW3TE38;#3GBtI z_Wf20U$|YeC@7fhJz;Wu%Qj)Ljf0StA6rD7{1#7%qI&bQqS#XqG#4pH1}iTwz#hvGrQ@$;?;C6K!zsvipSn=U1Hk3H85%+OQQkXzhFoP-4P?C$ zQ2rmpK;l&{n8U((gZ62+~g)F4)M%L`Wj!&C!#b1;E_%;Bn z{>4~2fh;#3T1_FlH;NPBA=kFANASGG1+OO%7&VAt65_Gb`t^?5(;H%9r@`a$`bv9E zVx1o>HnBydhV!PUWZ)Ev=E>%GVjhc$si+IzEMcvZwM!(WEq%V)((!cDzvafqQBUF9 zvi~Q(XC7=J_n;Hx?`P1@Aqq0zwtt=W5)+WD@kLkU&usLVcwZiV&p$z3hVUfU73s-o z-HjJKu_vEsZ%c#OV#Lrs0kQOODz1Yle^03AuuS{&-|)76D~U$LBciH`?R9%hE_CK` zITPlWf7Ef@x>jG%P7H+x6egA{JVNdku^f(oTKw?Zr|0O5Gec zezNllB8nkjJ`^w+rNSUOAH<3*#>?rkJpBPGhy%R-fw^lU)@RxM>s$-iZqQrZ>ZoJk z9g^p?ZSih6xwdM4mGZn7SOOolH3Y(`S5%?>K{3I}&ez@u5_e`R@zyo9rGBPhj%UI( z5dj}Rp+t4d`s!b~?Xcy4p$O*Ofx?E0eSO??IY>n&Tqt`2>m+8!I| z!a*)2Q6)Ky(8ps8f#rVKc`Fh({$YWK=E>-J-djg87QCGtCuoL(-?cOYbd!Q{mXbcUGoQ(BcRZn0^Ff ziYMY@guKiOP;zc9=!f~z=Z}cd0>UrE+JPPLMp90@pMIv0?dssD0^?#48%hOF>F@J3V=`*QkX#rRmhiD@08>!&j%H`6T*;Onq*dW8HGY+e zq{RP8ne>f)KhDv>Z#ta@W7!8FxJ~YMiPtZXDpkcl>gi1;*x|>8RdZ#9N{@1vXIXXj(Nt(z0R5c#AQJitYG)B6bzmzIux!4x+gbkq4{+ z`%f{dvMI%G)a#9)BIlxL@{Q0RZ{AT*k~jjjL~QSm$~XeBi~?wU@cE0*Fwc5vdt)(3 zk$c&8F4Xaqy-I>%bM6;P*JFq3R@pjw!9+P*WRqkfzEi?Y41mq^P`XV<{fwcJWzo*`HT8(?a#oM6wHT9l zY*u=akvoD}LcM_QxO}LFz2%g6js|@Ht-QC2iYw~6M3LYQ3BlbVcqrV1OMu|+5Zs-@ zCAb84PjGj44-nk7aEC&Rj(zvxj&XbZ_wOG4()Dy|oKySkwQbp~x#F~)hB3qz^CX*% zpR6y_t__CXQQ|w8Dk?L~*LJX8mw#>etO$*R;-<7vh15=v-PNG0ouW~97UmJqJ#b%A`KPMHv2YGLZq6rwCmGJ$Rmqsi_JM|!MWOaYgyi5uMS2-Cj>D(LEbM>Iw@O&X zApFd3^`u9s5jl?Sgz*T7SzUUnD0cU6rc2G|qr}=$2BltjyCZhQ>4?FB*jv`mreHW_AK5*<#}dG&c9Tm6xV&0%gIZ$0cLd* zPQLkd+xeM9{i%b4EqisLwesRAMh&ZJj{yFq0IRg}5r?pqI7_c}QKVc!7u9*jd>`@!@WzbO6!PcqCy#pRR))}o?#Dy+47p%LbpOey)dl5=y zzW3VcHr#&z{ZRVcWvP2`FKnmP_vT_MVsvPHX~KUf?F=JE*$r8U;><1-%mGxnfqTf! zbIktvOIKf$8ep8OV=KmJ1N-+GIi$jaYvR2fA&xBhMZ4Hu_u{y#Gx=s6s1lv=;}#;{751b^w9y?trX?}$$qQ)t%E}vljXo@{wsUp56i~UE-VW|heY$BD>$c*^ zaG)gC%8=868o^Pqbdm5o{{qmkH%C_zYKij)WJ-)yKsU6t1it~u?fpQ1)zI&7)Bdfm zKHML!FcET3t;hE|c4A*9KiVf8cs`iJ*eer3kKCJFJX)_!1>ii^Z6li2qc5wcE_(bu;?&dH;=| z7TOlG0w{4vbPi$ye+HaJ{Bn!Q>pVeJeyZ)LDZtg}IiNDL58xq|;fi~Har^^Rf!}zc zfU{#a-Le(^WvjXpWxz5z$zd|*+9uJKe(0LIw#yvs zp*2rX!J@F!MMR8GT*?}1gX4cxhJMt-Fjz39Y;wAjsUYgSv`0K<^^5$#;l3BXnz7J; zmHSaJB8xy$DVfE$83`@fR{1!0S@lWNj{QB4~eBi1?}463LzUV(rBEM8W}4NL%55{sh-$ zq3Wy`4bz4J?~VPM!za1ZSntfV#&=3dGBrn!}e8HlhX!%GU;bqqa`^97u+{~ zH_m76w{aYxMXhuV(avg0o_^Il?fgtYI7d+28Y3ih}-n`32_$yxXuN_+@mibf*ZtiNi|kFJMeKtP^7FwEv}aZ_i|vbNuju zcf>3^q9#i0wWlK+0eTl>DSC2idH6fC)`d-T*Yj2hq7D4&8dtI>2UOdMJ; zb@Jks9do)Sp7QI^02A;Q%vuA_Xlm@Vdu|m8+k#@=mIbP$C#*ETFV7rVgNsI&-OkUrZ91HbxvqGPcy}3bq z53tNUbx|O|n}S~cMFU)#Muz;cx{>!)FxSOEzwAcdXcGZqC^|xUiSPP$9-HMWwK3DR z-e$>$?L8Nh^+xo7VdqrA$T}-tr|D6YMf?C^Z>O|+>5|lHEIy;7s`2MX9!!{9TQc(= zhRel?aDmXN4i_gQm~=Wcgs{)4Qng&6bE={yV(8#cp~#DOolXlaII+jmk|i#3TK4G)MNEWTBoflND}P3^l%Whcjs) zAy3A3uX^g{S?$ER-15#ghFkRze_iX0wxF9c_=V*P;`T=>?DbcIf@-S?)BB#<4BcBg zH6+@DdX*NpwEw{ZyadSnjgI%gF%by`1mkQ=pRoI-pW?}{ABFz7V&P$W;^YbTlZtNA zR&FiD^DxFxMox~uzq58^oNhkwKavWi1fleT%#&Dvh1OH2GGy_0cN#fOG&yq)z#jd& zahWeNBV;-QPm(lMRXgWLrXKoR1RK%xeQK{`YiVL?Dwk=xxt9c46Pe8uYfb@^ak`Hc zoy#)x7-F?^7q5nC7kIPC9_d!K1W*C)dioEm%c&dR=iP5kiAJnQ9jnxkdLBzqp)aBY z+o3-lkkW9RU}V<{NiLf;kyG~zd-onHZa_jfBVWm2=&HAd-UxXH-DG=Z)TdL)l^6-V zf)O7Oy-zagp~9TuMK38Mxg}hZxDVAYu8Ojpu3;0Gz_dUNqCgb)-SaMdAlNWNs&Z2i zEaW>>15+NqwAmnp9jpYTYzWGzzwzB8*y!E7p0VAxCvHrAJvm%%g!mS>#>q)Hz#(Ni zz%i!?UO3R;RS>vV$hoWqK(h;aJN12-yxl99 zXg>hkTft=FCcag|P4DhXmvmYe03?W@*Jh_Uil3dOa}-xy zi&+2{r6krJ2w`Uesy5-+i^~f(5|2_ieHikWMW&Juey;Ln&K*>YB%u#mExBV_V*U#))JifNF~aXutUYH!Ij z096#Y#N;`5Tbany^WP?ur8iUq_DmEG5)_tCFMNdQg+vJ&#Ei?HzbB90`hlPuhgiv5ysg#FQ%5ypX4}t*IY0Yz+ zP*>k^V&-+Rj{NpORCrj}?;JsAj0^a5Ro_F?>n}QE5Uvs$5{;tAnxsAeroFvdE7SO! zPVeFUi%q`cV@}K*E(c89Jq_XpM+|ZN$r?;MVEP66;Pbf=J?D?o4P}n!3#E5W$9uX) zn!@c=+$=Ku=>^lxBf-WG8FtBNgRwFgY+h7D18~k?_yhdLLrG)+8c$oZvw-QV@Tlmz z{(oqLY*l3>%qj$pe{mI!l9I3*){MDAT4^(be<%j+bTbZ91(NEwD}xzjJdp=R$bUfL z+v67(cm)N}s2x;rbAqGoiW8LPxL>S@w z8AJ!a2BiL_0`vT=X z8+P=}CHDJvhcGL9e5r(v9aIGd!c>C~Lk$1DSIf3g;CXUl&yrB@)m9nx& z`AYXVY`2+>ilaB5xC#FQYZCc{5V9(ib_MgkGqjQI}&buctyUoHgX5HxWL*2F$4Q_Zl+<>?j z>d}UuejdqrTD~KliF68y-0BcJ8Um(|(H31jEZMvcr3h2x2^FEV-F&E!FLk>-A`1M2 z2rG_Gu<|3s!G{Y1aNKu#L8KNHFpMH^p!$Hd$U{04Rc{bXv$aA)qd z#UBI5k7`1CxP5Q$_!3pxqscx#4b1Q-B==AY@h7W@1~UP96F>kM>+RrB-$4|szznZd zseu*26b^7lZz2Ni`Sh*b2Hqb$9JgwxrytmMBNbtg4g3RhKgQ7mM2XmNGPq0Zr+Sr| zj=`mEGB$j2u-ZskZuH<_JMZg_Z81UrzI`N4 z*uzmsVtqP7P59`fwCUlSP7>2<*M6MK6=CB#Adv%>Tno3YSGUq;``M+H%oITzxs>dXYT{rq0wp2P`>ajDn%-uNe!L^q zIQDP4%T2c_7QD{Hzg4KVPB`rIt9#dEuR(UDr_?^iFv)F7UKKXh_lW!6%%I}2%~VxI zr)P{}ob33KX5C3pJZX{gBd%6=k_~sE*+b&aUSF*2#jWVb70SHR_j+i-bXp9I?RB@Jt-S2C^X`@;qQK6#FL7}yUv9qkUU?)NI1ai@!jnU9i;q!BLw9hQ7DNeq;S(YHC4N}?p z%e5t)q!(k}QGM+R`Is0`e5DtvQr7h!ouqhkOR%BBOgN!RkEz9xIX3SKjk#U}cOhIt zq@Wbini?5Hs;f&glBzofsojc%$Ea^)+Z73WcILoU zV*xg*joE!#kKOU#Rp&lawML@3!C65v710bftu{GyYI9kWnmAgBiO^==NPW+N|45~? z;LO1y(CUYw&=NUD8;a9<%j4?`hGCdIoE(2%#vxo9xoi`_biplGghvlvQcOB;l{CK7 zI}(MkSrNX%=IONK3kzUmw(O37yGD66uc)*Jh>J;{Fq7t~YwspD(Ws`NJZVeE*(TRu-8cc!!ef z1iV}=oBJYH(c}ef+CF%`;Vo z7PT?3se>ykm^1n6OkPLx^HsD8X9}EBj?|I?6}DsB;AAEb$SE5n7^8#oA11n;v>#%s=R7OCq2FzsK4JW2w9^+o zg#KGw0P8>8fB%aYN>I4}jf-Xim~)r!E`NFWN_&zS*Kh7x)y7@syInSHc_#El$rUnr z3y=OuGK%X}*&0m}0zL1t%MZ7qh}1=cV^-^Lc>VETd-w718#BLIkZX0;J&J`l)&KpD zIG|ZiEQjS=UWc69KN{qnQN{ld`u$&1w&H*KPW?9oUr5ak7eeX2tLpwO8gitwi;~KF z%g5wfzdP-^Uy{F{b;f$bx62u%3e+zkQJ)#UI|5X@>Z0954W7IC^)H1&dS`~c?fHk> ze=Z~+3(#VKYnsa;-hN zW8z5m1$e=tkW>Vf71MinRouS*y)0zswR*S8*a;}6hky>~--@pEu{r26hwF@G8%jD} z`*q@V9Gdb&#%!MqVM}|vf9Tndo$O_fE37Sos9zR!l=EjdvO`TbEZ8Nr?$@`O*S>wr zrFenL%H|(F#sY@2vo-#&-k(T9{rckYer5d0tE_T!3|>89u@KL zTG2NxVM_(Vu@Y*BNI?55p=4R(rSy8Wu!`xyLDzDp{B9|tKV(n7JL*;N1Qqvo&DkO1 zfOgoq7QIzC)%c{ z#QiGghDShF-1{hgv)w~uI(u@5W%@4_GBP82#odHGRTw7I$2vs?0~?iEJ!7imG<)3c zgC2f~**iTzrpE$=l<(AIIW=7rK9)896*H*)+e5~L;&7(x4BqZ#I-*I_s;Pv zi%GW@3%yfvt-B~{6eB4)P>e7imnr9ELRoLkC6dbu8wWH&ZgmGI@zIqiZwmp=`g(xv z-du>>YD3?mjG@@OS5IdU7W0klOP$wH)>j45pu173 z5F}{&ZT5CGQng?5y9i{uWlu!-C|W*H`ZWfrk*ouBzjo`u8R?qv)Fpuqu@9cd`szxL zt6l|)GoOav!`Bb5?d*-EfqouWr!?LAl8amHhszaPjD>c*_<^Y0o?#(48OR ztQ%vd+GU;Pcz2h&|5N+h;d#<!|IO6>;&g)U38=?ZqacSK+BU z0$kzl23vk)7%%pOd;r@)fEl*`QsYGsxo?l$oM&U@tlWFH_{h?I#H|0LSHk;8QK1xOF3l;XyG=Yz_}4 z2;+Rd{X@aTvgLO~T4N%&Bc_liNoxsvsLtT+IV% zKUm-iy4tC4gaEN+L5ARIA`^Q^I#Ont;Wp&iyS`@ONf@ z>EZ3_;-W}slN=1}Bo3pXY2nZyXrNMV^+kQsC0{msEF(lzqiDS?EPfM#q_qT-{ameB zH%$_PXSI_`X7`?KMaJtf)t+>w_K4$yW=qKA(V)n0`319^b}9xL!@ZwMXt zydjYg1*a})t^Ne0-D@2dkHLHM?x#%LKQg_=b2m^lU&A=-nX|!co;qU4a=5cVn|&0u zpAmkLOn3NzZ$Kh-%TmN~op4r|sz<}h?npN@L~ehL>D8d7tfd)V%ays373Y_pgd@@= zx4*CV{YX2kQy{ZRwl!E}w0gpa$2BsERa`>1V6a`CGmZxFZdnNF(iez0Hq|G7h#>rD zlJjkO`dD@8yzrW_<|3Bt(rx^WbUV`^H0}r93H5gKty2Tb&PaQlc$Y|Q z`v_lc5%;Bb;m#u-)%c~5|5MzA4=kz{f^4(j1jew}*visOMe3#~4P_R%12x0jMpa&2W5(d0k&piRc5 ziw!N&&dPL#BGnW2*9UX@eGuovF+&704^)UT--lGgHmXzu1^R`z)(w ze_rr4(X!bDjSChQkBuQo;C-cvGKpCCv2AP0v79DnOw5-|YmcI^s3MK{8K)FLqb}1w0!E7`GW7>9x;v%>3c;6 zv86^56TuGNI-XPENxN>zef~0f(4tbTkl8YgaDTTQgA^=U*VuR!Q&G=}HqycFf6`9C zFmJnE{w#mT+tQ=HgvU-wB!7AE-cK8&+VpEel#8u5vB3#nEMJjn+*jKd6MQOlRiu8F z)84mrv9T9W+ha#`6_*^&-IeZ4y(`VA(@wi>I?MHm@y4vi<~yv^?q6dI^8@mYgEKRJzc%oL09wnXW{~V=SzqGng3e9ydpAv z_&KEevh*C!Ka|gLomrm$n>ot=Cj{XgOrAPuwAJmNp<2p+yF_t1(xeNm5k>dcM^ooR z^Z!5Pqs7VYtaSx=Aul+>Ad==B^I<4`B5b?!l>}66WKmo5R4_bg-!y3{P&wD3gGO#X z0o;*N@}%*2Lynshqz+~^NftW8r}aAqCNN-ra74$YHjkz5bU~4YnO}XDnd=BXat|x% z2*l^}!c~FSb`JjQTsXB^Kdp%}KoTV&-+2loGH{H5_F-OgJ8TSxS7x|xJF;9KKETo- z7y}byrY60^A6LcORNq}Sw(xrT1%}!)GwhaEMjCE@*-gY15C^V%X6flkLgmy)$J5Sj zce>C7?@lV;wL{;{y;g2u{NW)oTe)XG*?f@PniBtB$Xw6U?;RZVr|chafBD_Vkvw@W z*Kx}>8y9tE99{8TTF-Af!tcT+UmCJ{^+W-@VE|~2Fw&Hu6YRA?w*}e#0ry|KjR4NT zFQGj4PM#zKke1lNrhyY0_ui5$cR(UKs9RsVH!EwMiq8u1qTMKrH131K0NT@LqZbmU z$>d%mVv!=XS0b@hrG|3RE^7nW_q$b^%in=v^7#4)1%+Mp8w;Rg72RT=8p3M&85;p$ zGw7ri_KZn{lu6FDBKMqT$~5E|_ITzImdX)f-?4g0Z%5Fz%`3qoNrc;_ULW+>*$7Sg z+unbEQIkGNqrmkB8y2lUvPO(zIJ@p)_3iRXRCWLi3$IdUWl0V9FaSRmaQo_;Bm37g z`=7!5ea|YSh8LH--iGftXNmp1Feo3ZnIt5#7oE2>P_Cm3W02AaR`J4h-&!UInegTI z+VYFANUo3*4G-(~=0YD+Q4zQkw6}=<<-%u!1|wvIxv)Bq;laPREB1Uz#q`>#BGt|# z4unEu%+9lye68}ux8F|h{!Ii;*BMaHbu+GDlO~!7u9XtqkH!sWAPQgzn-}1mwHy?+Exa%~m2aRJ8JLrNSg2Ut;KO;Zs6cUlXC{+nMd8uS?t3+I zRR-z*RCdGiv7WI+qU}5EIge;4K2%Fl^z9mN8OwXewrq5}Yc)6+3HLqG)v+5`1cw|1ZtW90Li zv&7Q4U+SI1LBS8H-dvP6OKqI2Z67In4L`Fq9r7)l6Jd@l4A_O~+98FQeki6}ZX-l2 zWEkRKPEI*h-}~C#V%cw7B)IQL6h&YCIHmRL7IHSl@68%$)2}peP1B5WFMqWm>_Z*l z+ZI)V@3Dja5-D9KsJ8vbk00^~56HI_atKH7k{bzX4O?uluLaDV^*gag2fac(UXCaQ zk=Z_KHC9=|^pH3Gz%+>=tQ=NY?+`v0i+*Yh?ugbv^m6cEDu~3hFY29G4r0l}aA^0> zw{6=b;e@or)?kEkoJ~1zDUv#FxRc1)XTxWxE zE(aD`8`7$8YtB2%%guFB{pX-^v)IJ3#GI+>>a$kokA$W|ra0ioVgFRcbwopIb?~vE zUc;KXZ`@`cplSWKc1*qFIP>#8VeRBHjKjtCfgs!0MkK{1jEmc=^|`Z4#~$4IMW-X1 z9-K(ZZfJL*4Jk<`B&1cxs8QMd7oIQQA@Mbb z|HT^)@7D!hL^mfZ5yfCk<;Sd-2Kmr*)(0Acd?!sx#d$}m+^Bdl#cp=d8zQl z3GYsN@%b1e)c@ACsNbndH&#P1f^RH=3L<$wAfO(2Fbs#+t=WN zGTxWg{nane{LCz*H^c$uUSXWnacne6QM>ZjipK=&8T?<{nxSRB0K1-P$w#r>i9er5Bp@hkkqEG6^WZqEoN`ZI7?R=x2>%%`I<(Yg8 z32|P0_-D*GmDO&!XR?v~7e$|PoN<|mqU6W#zE$wK9RB>q=o1?w1WEZwC+_9N_p+}g zJCkGmuio8Ivd&8Dn-^ro;ow^wioYNeXxz8 z&i?ZFzTkBkncF$sNUxV>s;aol5zn$bJZ^fR_J9eyfD@FOyb8;|8hH8!L@TNT+lt3s z@ma%>kMUI>2!p)Ot_DU~lx`^jCzFE1iG8K}L43EDGP}@H*FMygNQ#QN! z?XeJ{#*J^l%;fpkRXaNr$mZ0B`|&t`1xaENjTPuz^{-rS)Mzl^zbFRK@=B5XB!rBI zmv*BR&kMIQz}WjWREhMQ8&YwPCEt{f`@~D(XE@I_Bx3c3VL<%))Afxf1F!J$b4wNe z8D1SwKyo}7!46@ipO}v7s61C-F9ni`B1@XrSh6olD#MvyCA`(=+AKV_xfs-JwlL1# zS=4YtRJ8i-7QED5>`X|}3T{#CqM80$sA#@^h3lrD#R=|NimDk)!}7rbVj^b8w8h#l zV@$|8ZnaxNG|y2ek?9A?LN!lMFK?Z-P>r8)-+L+>B(bB{cBH;zM$bM zhfo`q=_pPqr*PeK**5dsR+1JStq#oGf31rgG20|Uh#LfN>ge^v=LBy_h8Q##Tso$~ zo3XvT?F~cm@^Jd)U&J7UYsHDlylToA)zEw^>$;|F8+9bI(YxBFqcbom=TMfCdA+z> zTcq+N%cm%)BVE}%$!?wq7jXd9T4DdrE1Cr1Dyr}L7&)=tl!<;tR%ee1d0;hcsxH00 z-;~KRBJXa>P{YD(dxo)uE6Ut=O1JOBbFi^pW$|&dX(B|0{A$|M4@vY4LOY>{5!?7# zupuWsN{A)rIDED*c`qIt8dBbAFy;6*(9ulUy%=`;PVYM;KcFxo$9|D&i>>SR)(|{x zD|;=y{hs07A)Tg1&&Vt+orejcgcWfq^4zv;_V6}JrwnH~XNQ)Er3eyR;l0T<`tj2QMmO(&?~b@p3O>F^l~D!;hSz?(Th(oryBrX!T=dz~GRFxrP5@-h+_{G=qXgYN9gCz;ejDb= z>0=t6X>73K{RZJMJ;~MVz2u^X6Dz`q4I4}KS<~a=8j|v$Bt$>6HSgx=hD4&hUDRIB z2M)oXL!E+G1hXB6a>pnASL@`~;5CKMM&^EX@KaW3AZtLapJ+0lQiM=&3BXsWnBgd+MIR ziy&Wl^qasFv|tG4nbY<`75nv(B^CI@8fUqTf9uSeoCe#X+_-nn47*5B-d4gK&~CHh z?1<6XyM?yw5H(6Ak^uZ&tbEAyqmq(CH>S7kohnq)B&OI%phsEClH4}m*`@vs+S7bT zV~LiY*jFd0W}$Io>#ah5#^s*w-tpLt9R0@RWp>A*(S4?M$Lh-gGpV*v5vA3&xd+ww z6LQ~|EJAkpSblb-QAgT{B+ua{CvLG&8pES>amV>l7Bye$d%brX5cSDLi)b2hf#eUh zt)dp^V(29PcaQMSA?wUZiLW1m^*0QRW5XLvLeQg%9{MSgvWUhrdqeC;4fq;%YO`5r z1pR|fU1sN_God778ic%YKfg1F}9n5`_N=oSVEofiE zKcE|y*x+bqF_UpJNB!Isy94#%VZ*zk0d1YP(FfR#q`;uQ@oPoto(1o)!1CB1vg_=B zGIZ?ZccPo>&>GCl6iGXEQ&h!KX2_Teo&M(8B?Vi}0KAKzkda)9g z@(eLkxz5((<2+WpTPX4_F6Nk?{qaxjErH1>043Z8Orb4XN06)Fyl3?#<1jBnGF)o( z#1#rDC~E7?CvZ!0o84&s+A{VGmHMBL!3+t7Eq^uARnY(&0SaH%II* zVW#^*OpZ<=nW@c7*wQ8rGwak~S>2xPuvPZ5-o5*EL-{SENWW##Dwly2=Ijh=j%RH&ee)ZQ+-$4%AP()NT;FPy|jA4XZG^w~Io);11CH5RovK47uc35f&a7cu+=&Zvz`YJw9c5gBk;0J~R zmN+Y`=>$!I@oPGbHsMv68U@k@#Ru<&_}Y&jqW^48nZ3va!2DX z+f3Az@4`p%$U48ZrSs>uc)Zr5Dnvd5A!>lm9xz8@FM&3lCNOi0_5 zt1|7Rkr8qey4NI8*LGfY`7-pX?TR?gIsl%6=(-b$|Lpzrvz%xsfh9#!P+y8{tH_o> z*MzQl1xADq6n<@Izf>*h{3aB4{DIxAQ{MP=`S@`k_}G7n12-b;JJOtsb}`PMvl}{E!i$0^lpJS=I;0Cp!lIuT(PmpOLjAb_v!xB& zCv#32{I;CK-HnE|^tDJK-IXm|R(a$qb52-AAS**7F^e4;o9%h75lG^89t3Nx> zQE(wgINV?ae_R4RhTUP>%%7*=Exxr#b0C`b=QP&%gm8dv*%OS5K~2I2>-lk6e(oDY z1dB57@XYc7(-H#|N+%9{f|c>_s$Q)D7EEq(_!DR@3SSt(TNm{kPG_dFo7-bAB0PM{ zeg>4C+ImBiU#u+b0oz~?huMna7OaQjm4$b$q()blHk_W?=dIu^Z(ly&W&2Y(=qjhd z#t_3}-{AP~uy+b|8_W7)nv2WciR@|B0R1g`&e`hE2P||IOA({Xk&{P79p6Jj>`CM8 z8icP|2coN|tBPKkXA-Vo;PO9O(T%UikddI8-L>P!VCS**BODYK7&_x zMsz;Dgrk=kL1Wd|ij$^OkrhZe%xboz<2^7X8uj6{q|CIKTvfdAS2vQR)K)q8RU8)= z9hto6nX$9pnl&5jRq8=ui5ck@<8L8Is5vH8doJ+Pm>^RQW`_}AA8 c)4_oV(QqRJo%(W%p?-a&KPZS-h#Ca^4>>0brT_o{ literal 0 Hc-jL100001 diff --git a/docs/en/docs/tutorial/first-steps.md b/docs/en/docs/tutorial/first-steps.md index 6ca5f39eb1..cfa1593294 100644 --- a/docs/en/docs/tutorial/first-steps.md +++ b/docs/en/docs/tutorial/first-steps.md @@ -99,7 +99,7 @@ It will show a JSON starting with something like: ```JSON { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "FastAPI", "version": "0.1.0" diff --git a/docs/en/docs/tutorial/metadata.md b/docs/en/docs/tutorial/metadata.md index cf13e7470f..e75b4a0b95 100644 --- a/docs/en/docs/tutorial/metadata.md +++ b/docs/en/docs/tutorial/metadata.md @@ -9,15 +9,16 @@ You can set the following fields that are used in the OpenAPI specification and | Parameter | Type | Description | |------------|------|-------------| | `title` | `str` | The title of the API. | +| `summary` | `str` | A short summary of the API. Available since OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | A short description of the API. It can use Markdown. | | `version` | `string` | The version of the API. This is the version of your own application, not of OpenAPI. For example `2.5.0`. | | `terms_of_service` | `str` | A URL to the Terms of Service for the API. If provided, this has to be a URL. | | `contact` | `dict` | The contact information for the exposed API. It can contain several fields.

contact fields
ParameterTypeDescription
namestrThe identifying name of the contact person/organization.
urlstrThe URL pointing to the contact information. MUST be in the format of a URL.
emailstrThe email address of the contact person/organization. MUST be in the format of an email address.
| -| `license_info` | `dict` | The license information for the exposed API. It can contain several fields.
license_info fields
ParameterTypeDescription
namestrREQUIRED (if a license_info is set). The license name used for the API.
urlstrA URL to the license used for the API. MUST be in the format of a URL.
| +| `license_info` | `dict` | The license information for the exposed API. It can contain several fields.
license_info fields
ParameterTypeDescription
namestrREQUIRED (if a license_info is set). The license name used for the API.
identifierstrAn SPDX license expression for the API. The identifier field is mutually exclusive of the url field. Available since OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrA URL to the license used for the API. MUST be in the format of a URL.
| You can set them as follows: -```Python hl_lines="3-16 19-31" +```Python hl_lines="3-16 19-32" {!../../../docs_src/metadata/tutorial001.py!} ``` @@ -28,6 +29,16 @@ With this configuration, the automatic API docs would look like: +## License identifier + +Since OpenAPI 3.1.0 and FastAPI 0.99.0, you can also set the `license_info` with an `identifier` instead of a `url`. + +For example: + +```Python hl_lines="31" +{!../../../docs_src/metadata/tutorial001_1.py!} +``` + ## Metadata for tags You can also add additional metadata for the different tags used to group your path operations with the parameter `openapi_tags`. diff --git a/docs/en/docs/tutorial/path-params.md b/docs/en/docs/tutorial/path-params.md index a0d70692e5..6594a7a8b5 100644 --- a/docs/en/docs/tutorial/path-params.md +++ b/docs/en/docs/tutorial/path-params.md @@ -83,7 +83,7 @@ And when you open your browser at
OpenAPI standard, there are many compatible tools. +And because the generated schema is from the OpenAPI standard, there are many compatible tools. Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc), which you can access at http://127.0.0.1:8000/redoc: diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md index e0f7ed2569..6cf8bf1813 100644 --- a/docs/en/docs/tutorial/schema-extra-example.md +++ b/docs/en/docs/tutorial/schema-extra-example.md @@ -6,17 +6,17 @@ Here are several ways to do it. ## Pydantic `schema_extra` -You can declare an `example` for a Pydantic model using `Config` and `schema_extra`, as described in Pydantic's docs: Schema customization: +You can declare `examples` for a Pydantic model using `Config` and `schema_extra`, as described in Pydantic's docs: Schema customization: === "Python 3.10+" - ```Python hl_lines="13-21" + ```Python hl_lines="13-23" {!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!} ``` === "Python 3.6+" - ```Python hl_lines="15-23" + ```Python hl_lines="15-25" {!> ../../../docs_src/schema_extra_example/tutorial001.py!} ``` @@ -27,11 +27,16 @@ That extra info will be added as-is to the output **JSON Schema** for that model For example you could use it to add metadata for a frontend user interface, etc. -## `Field` additional arguments +!!! info + OpenAPI 3.1.0 (used since FastAPI 0.99.0) added support for `examples`, which is part of the **JSON Schema** standard. + + Before that, it only supported the keyword `example` with a single example. That is still supported by OpenAPI 3.1.0, but is deprecated and is not part of the JSON Schema standard. So you are encouraged to migrate `example` to `examples`. 🤓 + + You can read more at the end of this page. -When using `Field()` with Pydantic models, you can also declare extra info for the **JSON Schema** by passing any other arbitrary arguments to the function. +## `Field` additional arguments -You can use this to add `example` for each field: +When using `Field()` with Pydantic models, you can also declare additional `examples`: === "Python 3.10+" @@ -45,10 +50,7 @@ You can use this to add `example` for each field: {!> ../../../docs_src/schema_extra_example/tutorial002.py!} ``` -!!! warning - Keep in mind that those extra arguments passed won't add any validation, only extra information, for documentation purposes. - -## `example` and `examples` in OpenAPI +## `examples` in OpenAPI When using any of: @@ -60,27 +62,27 @@ When using any of: * `Form()` * `File()` -you can also declare a data `example` or a group of `examples` with additional information that will be added to **OpenAPI**. +you can also declare a group of `examples` with additional information that will be added to **OpenAPI**. -### `Body` with `example` +### `Body` with `examples` -Here we pass an `example` of the data expected in `Body()`: +Here we pass `examples` containing one example of the data expected in `Body()`: === "Python 3.10+" - ```Python hl_lines="22-27" + ```Python hl_lines="22-29" {!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!} ``` === "Python 3.9+" - ```Python hl_lines="22-27" + ```Python hl_lines="22-29" {!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!} ``` === "Python 3.6+" - ```Python hl_lines="23-28" + ```Python hl_lines="23-30" {!> ../../../docs_src/schema_extra_example/tutorial003_an.py!} ``` @@ -89,7 +91,7 @@ Here we pass an `example` of the data expected in `Body()`: !!! tip Prefer to use the `Annotated` version if possible. - ```Python hl_lines="18-23" + ```Python hl_lines="18-25" {!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!} ``` @@ -98,7 +100,7 @@ Here we pass an `example` of the data expected in `Body()`: !!! tip Prefer to use the `Annotated` version if possible. - ```Python hl_lines="20-25" + ```Python hl_lines="20-27" {!> ../../../docs_src/schema_extra_example/tutorial003.py!} ``` @@ -110,16 +112,7 @@ With any of the methods above it would look like this in the `/docs`: ### `Body` with multiple `examples` -Alternatively to the single `example`, you can pass `examples` using a `dict` with **multiple examples**, each with extra information that will be added to **OpenAPI** too. - -The keys of the `dict` identify each example, and each value is another `dict`. - -Each specific example `dict` in the `examples` can contain: - -* `summary`: Short description for the example. -* `description`: A long description that can contain Markdown text. -* `value`: This is the actual example shown, e.g. a `dict`. -* `externalValue`: alternative to `value`, a URL pointing to the example. Although this might not be supported by as many tools as `value`. +You can of course also pass multiple `examples`: === "Python 3.10+" @@ -165,25 +158,76 @@ With `examples` added to `Body()` the `/docs` would look like: ## Technical Details +!!! tip + If you are already using **FastAPI** version **0.99.0 or above**, you can probably **skip** these details. + + They are more relevant for older versions, before OpenAPI 3.1.0 was available. + + You can consider this a brief OpenAPI and JSON Schema **history lesson**. 🤓 + !!! warning These are very technical details about the standards **JSON Schema** and **OpenAPI**. If the ideas above already work for you, that might be enough, and you probably don't need these details, feel free to skip them. -When you add an example inside of a Pydantic model, using `schema_extra` or `Field(example="something")` that example is added to the **JSON Schema** for that Pydantic model. +Before OpenAPI 3.1.0, OpenAPI used an older and modified version of **JSON Schema**. -And that **JSON Schema** of the Pydantic model is included in the **OpenAPI** of your API, and then it's used in the docs UI. +JSON Schema didn't have `examples`, so OpenAPI added it's own `example` field to its own modified version. + +OpenAPI also added `example` and `examples` fields to other parts of the specification: + +* `Parameter Object` (in the specification) that was used by FastAPI's: + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* `Request Body Object`, in the field `content`, on the `Media Type Object` (in the specification) that was used by FastAPI's: + * `Body()` + * `File()` + * `Form()` -**JSON Schema** doesn't really have a field `example` in the standards. Recent versions of JSON Schema define a field `examples`, but OpenAPI 3.0.3 is based on an older version of JSON Schema that didn't have `examples`. +### OpenAPI's `examples` field -So, OpenAPI 3.0.3 defined its own `example` for the modified version of **JSON Schema** it uses, for the same purpose (but it's a single `example`, not `examples`), and that's what is used by the API docs UI (using Swagger UI). +The shape of this field `examples` from OpenAPI is a `dict` with **multiple examples**, each with extra information that will be added to **OpenAPI** too. + +The keys of the `dict` identify each example, and each value is another `dict`. + +Each specific example `dict` in the `examples` can contain: + +* `summary`: Short description for the example. +* `description`: A long description that can contain Markdown text. +* `value`: This is the actual example shown, e.g. a `dict`. +* `externalValue`: alternative to `value`, a URL pointing to the example. Although this might not be supported by as many tools as `value`. + +This applies to those other parts of the OpenAPI specification apart from JSON Schema. + +### JSON Schema's `examples` field + +But then JSON Schema added an `examples` field to a new version of the specification. + +And then the new OpenAPI 3.1.0 was based on the latest version (JSON Schema 2020-12) that included this new field `examples`. + +And now this new `examples` field takes precedence over the old single (and custom) `example` field, that is now deprecated. + +This new `examples` field in JSON Schema is **just a `list`** of examples, not a dict with extra metadata as in the other places in OpenAPI (described above). + +!!! info + Even after OpenAPI 3.1.0 was released with this new simpler integration with JSON Schema, for a while, Swagger UI, the tool that provides the automatic docs, didn't support OpenAPI 3.1.0 (it does since version 5.0.0 🎉). + + Because of that, versions of FastAPI previous to 0.99.0 still used versions of OpenAPI lower than 3.1.0. + +### Pydantic and FastAPI `examples` + +When you add `examples` inside of a Pydantic model, using `schema_extra` or `Field(examples=["something"])` that example is added to the **JSON Schema** for that Pydantic model. + +And that **JSON Schema** of the Pydantic model is included in the **OpenAPI** of your API, and then it's used in the docs UI. -So, although `example` is not part of JSON Schema, it is part of OpenAPI's custom version of JSON Schema, and that's what will be used by the docs UI. +In versions of FastAPI before 0.99.0 (0.99.0 and above use the newer OpenAPI 3.1.0) when you used `example` or `examples` with any of the other utilities (`Query()`, `Body()`, etc.) those examples were not added to the JSON Schema that describes that data (not even to OpenAPI's own version of JSON Schema), they were added directly to the *path operation* declaration in OpenAPI (outside the parts of OpenAPI that use JSON Schema). -But when you use `example` or `examples` with any of the other utilities (`Query()`, `Body()`, etc.) those examples are not added to the JSON Schema that describes that data (not even to OpenAPI's own version of JSON Schema), they are added directly to the *path operation* declaration in OpenAPI (outside the parts of OpenAPI that use JSON Schema). +But now that FastAPI 0.99.0 and above uses OpenAPI 3.1.0, that uses JSON Schema 2020-12, and Swagger UI 5.0.0 and above, everything is more consistent and the examples are included in JSON Schema. -For `Path()`, `Query()`, `Header()`, and `Cookie()`, the `example` or `examples` are added to the OpenAPI definition, to the `Parameter Object` (in the specification). +### Summary -And for `Body()`, `File()`, and `Form()`, the `example` or `examples` are equivalently added to the OpenAPI definition, to the `Request Body Object`, in the field `content`, on the `Media Type Object` (in the specification). +I used to say I didn't like history that much... and look at me now giving "tech history" lessons. 😅 -On the other hand, there's a newer version of OpenAPI: **3.1.0**, recently released. It is based on the latest JSON Schema and most of the modifications from OpenAPI's custom version of JSON Schema are removed, in exchange of the features from the recent versions of JSON Schema, so all these small differences are reduced. Nevertheless, Swagger UI currently doesn't support OpenAPI 3.1.0, so, for now, it's better to continue using the ideas above. +In short, **upgrade to FastAPI 0.99.0 or above**, and things are much **simpler, consistent, and intuitive**, and you don't have to know all these historic details. 😎 diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 64dc403727..030bbe5d3e 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -147,6 +147,7 @@ nav: - advanced/conditional-openapi.md - advanced/extending-openapi.md - advanced/openapi-callbacks.md + - advanced/openapi-webhooks.md - advanced/wsgi.md - advanced/generate-clients.md - async.md diff --git a/docs_src/extending_openapi/tutorial001.py b/docs_src/extending_openapi/tutorial001.py index 561e95898f..35e31c0e0c 100644 --- a/docs_src/extending_openapi/tutorial001.py +++ b/docs_src/extending_openapi/tutorial001.py @@ -15,7 +15,8 @@ def custom_openapi(): openapi_schema = get_openapi( title="Custom title", version="2.5.0", - description="This is a very custom OpenAPI schema", + summary="This is a very custom OpenAPI schema", + description="Here's a longer description of the custom **OpenAPI** schema", routes=app.routes, ) openapi_schema["info"]["x-logo"] = { diff --git a/docs_src/metadata/tutorial001.py b/docs_src/metadata/tutorial001.py index 3fba9e7d1b..76656e81b4 100644 --- a/docs_src/metadata/tutorial001.py +++ b/docs_src/metadata/tutorial001.py @@ -18,6 +18,7 @@ You will be able to: app = FastAPI( title="ChimichangApp", description=description, + summary="Deadpool's favorite app. Nuff said.", version="0.0.1", terms_of_service="http://example.com/terms/", contact={ diff --git a/docs_src/metadata/tutorial001_1.py b/docs_src/metadata/tutorial001_1.py new file mode 100644 index 0000000000..a8f5b94588 --- /dev/null +++ b/docs_src/metadata/tutorial001_1.py @@ -0,0 +1,38 @@ +from fastapi import FastAPI + +description = """ +ChimichangApp API helps you do awesome stuff. 🚀 + +## Items + +You can **read items**. + +## Users + +You will be able to: + +* **Create users** (_not implemented_). +* **Read users** (_not implemented_). +""" + +app = FastAPI( + title="ChimichangApp", + description=description, + summary="Deadpool's favorite app. Nuff said.", + version="0.0.1", + terms_of_service="http://example.com/terms/", + contact={ + "name": "Deadpoolio the Amazing", + "url": "http://x-force.example.com/contact/", + "email": "dp@x-force.example.com", + }, + license_info={ + "name": "Apache 2.0", + "identifier": "MIT", + }, +) + + +@app.get("/items/") +async def read_items(): + return [{"name": "Katana"}] diff --git a/docs_src/openapi_webhooks/tutorial001.py b/docs_src/openapi_webhooks/tutorial001.py new file mode 100644 index 0000000000..5016f5b00f --- /dev/null +++ b/docs_src/openapi_webhooks/tutorial001.py @@ -0,0 +1,25 @@ +from datetime import datetime + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Subscription(BaseModel): + username: str + montly_fee: float + start_date: datetime + + +@app.webhooks.post("new-subscription") +def new_subscription(body: Subscription): + """ + When a new user subscribes to your service we'll send you a POST request with this + data to the URL that you register for the event `new-subscription` in the dashboard. + """ + + +@app.get("/users/") +def read_users(): + return ["Rick", "Morty"] diff --git a/docs_src/schema_extra_example/tutorial001.py b/docs_src/schema_extra_example/tutorial001.py index a5ae281274..6ab96ff859 100644 --- a/docs_src/schema_extra_example/tutorial001.py +++ b/docs_src/schema_extra_example/tutorial001.py @@ -14,12 +14,14 @@ class Item(BaseModel): class Config: schema_extra = { - "example": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - } + "examples": [ + { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + } + ] } diff --git a/docs_src/schema_extra_example/tutorial001_py310.py b/docs_src/schema_extra_example/tutorial001_py310.py index 77ceedd60d..ec83f1112f 100644 --- a/docs_src/schema_extra_example/tutorial001_py310.py +++ b/docs_src/schema_extra_example/tutorial001_py310.py @@ -12,12 +12,14 @@ class Item(BaseModel): class Config: schema_extra = { - "example": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - } + "examples": [ + { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + } + ] } diff --git a/docs_src/schema_extra_example/tutorial002.py b/docs_src/schema_extra_example/tutorial002.py index 6de434f81d..70f06567c3 100644 --- a/docs_src/schema_extra_example/tutorial002.py +++ b/docs_src/schema_extra_example/tutorial002.py @@ -7,10 +7,10 @@ app = FastAPI() class Item(BaseModel): - name: str = Field(example="Foo") - description: Union[str, None] = Field(default=None, example="A very nice Item") - price: float = Field(example=35.4) - tax: Union[float, None] = Field(default=None, example=3.2) + name: str = Field(examples=["Foo"]) + description: Union[str, None] = Field(default=None, examples=["A very nice Item"]) + price: float = Field(examples=[35.4]) + tax: Union[float, None] = Field(default=None, examples=[3.2]) @app.put("/items/{item_id}") diff --git a/docs_src/schema_extra_example/tutorial002_py310.py b/docs_src/schema_extra_example/tutorial002_py310.py index e84928bb11..27d7868676 100644 --- a/docs_src/schema_extra_example/tutorial002_py310.py +++ b/docs_src/schema_extra_example/tutorial002_py310.py @@ -5,10 +5,10 @@ app = FastAPI() class Item(BaseModel): - name: str = Field(example="Foo") - description: str | None = Field(default=None, example="A very nice Item") - price: float = Field(example=35.4) - tax: float | None = Field(default=None, example=3.2) + name: str = Field(examples=["Foo"]) + description: str | None = Field(default=None, examples=["A very nice Item"]) + price: float = Field(examples=[35.4]) + tax: float | None = Field(default=None, examples=[3.2]) @app.put("/items/{item_id}") diff --git a/docs_src/schema_extra_example/tutorial003.py b/docs_src/schema_extra_example/tutorial003.py index ce1736bbaf..385f3de8a1 100644 --- a/docs_src/schema_extra_example/tutorial003.py +++ b/docs_src/schema_extra_example/tutorial003.py @@ -17,12 +17,14 @@ class Item(BaseModel): async def update_item( item_id: int, item: Item = Body( - example={ - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, + examples=[ + { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + } + ], ), ): results = {"item_id": item_id, "item": item} diff --git a/docs_src/schema_extra_example/tutorial003_an.py b/docs_src/schema_extra_example/tutorial003_an.py index 1dec555a94..23675aba14 100644 --- a/docs_src/schema_extra_example/tutorial003_an.py +++ b/docs_src/schema_extra_example/tutorial003_an.py @@ -20,12 +20,14 @@ async def update_item( item: Annotated[ Item, Body( - example={ - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, + examples=[ + { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + } + ], ), ], ): diff --git a/docs_src/schema_extra_example/tutorial003_an_py310.py b/docs_src/schema_extra_example/tutorial003_an_py310.py index 9edaddfb8e..bbd2e171ec 100644 --- a/docs_src/schema_extra_example/tutorial003_an_py310.py +++ b/docs_src/schema_extra_example/tutorial003_an_py310.py @@ -19,12 +19,14 @@ async def update_item( item: Annotated[ Item, Body( - example={ - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, + examples=[ + { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + } + ], ), ], ): diff --git a/docs_src/schema_extra_example/tutorial003_an_py39.py b/docs_src/schema_extra_example/tutorial003_an_py39.py index fe08847d98..4728085617 100644 --- a/docs_src/schema_extra_example/tutorial003_an_py39.py +++ b/docs_src/schema_extra_example/tutorial003_an_py39.py @@ -19,12 +19,14 @@ async def update_item( item: Annotated[ Item, Body( - example={ - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, + examples=[ + { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + } + ], ), ], ): diff --git a/docs_src/schema_extra_example/tutorial003_py310.py b/docs_src/schema_extra_example/tutorial003_py310.py index 1e137101d9..2d31619be2 100644 --- a/docs_src/schema_extra_example/tutorial003_py310.py +++ b/docs_src/schema_extra_example/tutorial003_py310.py @@ -15,12 +15,14 @@ class Item(BaseModel): async def update_item( item_id: int, item: Item = Body( - example={ - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, + examples=[ + { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + } + ], ), ): results = {"item_id": item_id, "item": item} diff --git a/docs_src/schema_extra_example/tutorial004.py b/docs_src/schema_extra_example/tutorial004.py index b67edf30cd..eb49293fd8 100644 --- a/docs_src/schema_extra_example/tutorial004.py +++ b/docs_src/schema_extra_example/tutorial004.py @@ -18,8 +18,8 @@ async def update_item( *, item_id: int, item: Item = Body( - examples={ - "normal": { + examples=[ + { "summary": "A normal example", "description": "A **normal** item works correctly.", "value": { @@ -29,7 +29,7 @@ async def update_item( "tax": 3.2, }, }, - "converted": { + { "summary": "An example with converted data", "description": "FastAPI can convert price `strings` to actual `numbers` automatically", "value": { @@ -37,14 +37,14 @@ async def update_item( "price": "35.4", }, }, - "invalid": { + { "summary": "Invalid data is rejected with an error", "value": { "name": "Baz", "price": "thirty five point four", }, }, - }, + ], ), ): results = {"item_id": item_id, "item": item} diff --git a/docs_src/schema_extra_example/tutorial004_an.py b/docs_src/schema_extra_example/tutorial004_an.py index 82c9a92ac1..567ec47024 100644 --- a/docs_src/schema_extra_example/tutorial004_an.py +++ b/docs_src/schema_extra_example/tutorial004_an.py @@ -21,8 +21,8 @@ async def update_item( item: Annotated[ Item, Body( - examples={ - "normal": { + examples=[ + { "summary": "A normal example", "description": "A **normal** item works correctly.", "value": { @@ -32,7 +32,7 @@ async def update_item( "tax": 3.2, }, }, - "converted": { + { "summary": "An example with converted data", "description": "FastAPI can convert price `strings` to actual `numbers` automatically", "value": { @@ -40,14 +40,14 @@ async def update_item( "price": "35.4", }, }, - "invalid": { + { "summary": "Invalid data is rejected with an error", "value": { "name": "Baz", "price": "thirty five point four", }, }, - }, + ], ), ], ): diff --git a/docs_src/schema_extra_example/tutorial004_an_py310.py b/docs_src/schema_extra_example/tutorial004_an_py310.py index 01f1a486cb..0266548356 100644 --- a/docs_src/schema_extra_example/tutorial004_an_py310.py +++ b/docs_src/schema_extra_example/tutorial004_an_py310.py @@ -20,8 +20,8 @@ async def update_item( item: Annotated[ Item, Body( - examples={ - "normal": { + examples=[ + { "summary": "A normal example", "description": "A **normal** item works correctly.", "value": { @@ -31,7 +31,7 @@ async def update_item( "tax": 3.2, }, }, - "converted": { + { "summary": "An example with converted data", "description": "FastAPI can convert price `strings` to actual `numbers` automatically", "value": { @@ -39,14 +39,14 @@ async def update_item( "price": "35.4", }, }, - "invalid": { + { "summary": "Invalid data is rejected with an error", "value": { "name": "Baz", "price": "thirty five point four", }, }, - }, + ], ), ], ): diff --git a/docs_src/schema_extra_example/tutorial004_an_py39.py b/docs_src/schema_extra_example/tutorial004_an_py39.py index d50e8aa5f8..06219ede8d 100644 --- a/docs_src/schema_extra_example/tutorial004_an_py39.py +++ b/docs_src/schema_extra_example/tutorial004_an_py39.py @@ -20,8 +20,8 @@ async def update_item( item: Annotated[ Item, Body( - examples={ - "normal": { + examples=[ + { "summary": "A normal example", "description": "A **normal** item works correctly.", "value": { @@ -31,7 +31,7 @@ async def update_item( "tax": 3.2, }, }, - "converted": { + { "summary": "An example with converted data", "description": "FastAPI can convert price `strings` to actual `numbers` automatically", "value": { @@ -39,14 +39,14 @@ async def update_item( "price": "35.4", }, }, - "invalid": { + { "summary": "Invalid data is rejected with an error", "value": { "name": "Baz", "price": "thirty five point four", }, }, - }, + ], ), ], ): diff --git a/docs_src/schema_extra_example/tutorial004_py310.py b/docs_src/schema_extra_example/tutorial004_py310.py index 100a30860b..ef2b9d8cb9 100644 --- a/docs_src/schema_extra_example/tutorial004_py310.py +++ b/docs_src/schema_extra_example/tutorial004_py310.py @@ -16,8 +16,8 @@ async def update_item( *, item_id: int, item: Item = Body( - examples={ - "normal": { + examples=[ + { "summary": "A normal example", "description": "A **normal** item works correctly.", "value": { @@ -27,7 +27,7 @@ async def update_item( "tax": 3.2, }, }, - "converted": { + { "summary": "An example with converted data", "description": "FastAPI can convert price `strings` to actual `numbers` automatically", "value": { @@ -35,14 +35,14 @@ async def update_item( "price": "35.4", }, }, - "invalid": { + { "summary": "Invalid data is rejected with an error", "value": { "name": "Baz", "price": "thirty five point four", }, }, - }, + ], ), ): results = {"item_id": item_id, "item": item} diff --git a/fastapi/applications.py b/fastapi/applications.py index 9b161c5ec8..88f861c1ef 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -55,6 +55,7 @@ class FastAPI(Starlette): debug: bool = False, routes: Optional[List[BaseRoute]] = None, title: str = "FastAPI", + summary: Optional[str] = None, description: str = "", version: str = "0.1.0", openapi_url: Optional[str] = "/openapi.json", @@ -85,6 +86,7 @@ class FastAPI(Starlette): root_path_in_servers: bool = True, responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, callbacks: Optional[List[BaseRoute]] = None, + webhooks: Optional[routing.APIRouter] = None, deprecated: Optional[bool] = None, include_in_schema: bool = True, swagger_ui_parameters: Optional[Dict[str, Any]] = None, @@ -95,6 +97,7 @@ class FastAPI(Starlette): ) -> None: self.debug = debug self.title = title + self.summary = summary self.description = description self.version = version self.terms_of_service = terms_of_service @@ -110,7 +113,7 @@ class FastAPI(Starlette): self.swagger_ui_parameters = swagger_ui_parameters self.servers = servers or [] self.extra = extra - self.openapi_version = "3.0.2" + self.openapi_version = "3.1.0" self.openapi_schema: Optional[Dict[str, Any]] = None if self.openapi_url: assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'" @@ -123,6 +126,7 @@ class FastAPI(Starlette): "automatic. Check the docs at " "https://fastapi.tiangolo.com/advanced/sub-applications/" ) + self.webhooks = webhooks or routing.APIRouter() self.root_path = root_path or openapi_prefix self.state: State = State() self.dependency_overrides: Dict[Callable[..., Any], Callable[..., Any]] = {} @@ -215,11 +219,13 @@ class FastAPI(Starlette): title=self.title, version=self.version, openapi_version=self.openapi_version, + summary=self.summary, description=self.description, terms_of_service=self.terms_of_service, contact=self.contact, license_info=self.license_info, routes=self.routes, + webhooks=self.webhooks.routes, tags=self.openapi_tags, servers=self.servers, ) diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index bf335118fc..81f67dcc5b 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -17,8 +17,8 @@ def get_swagger_ui_html( *, openapi_url: str, title: str, - swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js", - swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css", + swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js", + swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css", swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png", oauth2_redirect_url: Optional[str] = None, init_oauth: Optional[Dict[str, Any]] = None, diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py index 81a24f389b..7420d3b55a 100644 --- a/fastapi/openapi/models.py +++ b/fastapi/openapi/models.py @@ -1,9 +1,10 @@ from enum import Enum -from typing import Any, Callable, Dict, Iterable, List, Optional, Union +from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Union from fastapi.logger import logger from pydantic import AnyUrl, BaseModel, Field -from typing_extensions import Literal +from typing_extensions import Annotated, Literal +from typing_extensions import deprecated as typing_deprecated try: import email_validator # type: ignore @@ -37,6 +38,7 @@ class Contact(BaseModel): class License(BaseModel): name: str + identifier: Optional[str] = None url: Optional[AnyUrl] = None class Config: @@ -45,6 +47,7 @@ class License(BaseModel): class Info(BaseModel): title: str + summary: Optional[str] = None description: Optional[str] = None termsOfService: Optional[str] = None contact: Optional[Contact] = None @@ -56,7 +59,7 @@ class Info(BaseModel): class ServerVariable(BaseModel): - enum: Optional[List[str]] = None + enum: Annotated[Optional[List[str]], Field(min_items=1)] = None default: str description: Optional[str] = None @@ -102,9 +105,42 @@ class ExternalDocumentation(BaseModel): class Schema(BaseModel): + # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu + # Core Vocabulary + schema_: Optional[str] = Field(default=None, alias="$schema") + vocabulary: Optional[str] = Field(default=None, alias="$vocabulary") + id: Optional[str] = Field(default=None, alias="$id") + anchor: Optional[str] = Field(default=None, alias="$anchor") + dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor") ref: Optional[str] = Field(default=None, alias="$ref") - title: Optional[str] = None - multipleOf: Optional[float] = None + dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef") + defs: Optional[Dict[str, "Schema"]] = Field(default=None, alias="$defs") + comment: Optional[str] = Field(default=None, alias="$comment") + # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s + # A Vocabulary for Applying Subschemas + allOf: Optional[List["Schema"]] = None + anyOf: Optional[List["Schema"]] = None + oneOf: Optional[List["Schema"]] = None + not_: Optional["Schema"] = Field(default=None, alias="not") + if_: Optional["Schema"] = Field(default=None, alias="if") + then: Optional["Schema"] = None + else_: Optional["Schema"] = Field(default=None, alias="else") + dependentSchemas: Optional[Dict[str, "Schema"]] = None + prefixItems: Optional[List["Schema"]] = None + items: Optional[Union["Schema", List["Schema"]]] = None + contains: Optional["Schema"] = None + properties: Optional[Dict[str, "Schema"]] = None + patternProperties: Optional[Dict[str, "Schema"]] = None + additionalProperties: Optional["Schema"] = None + propertyNames: Optional["Schema"] = None + unevaluatedItems: Optional["Schema"] = None + unevaluatedProperties: Optional["Schema"] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural + # A Vocabulary for Structural Validation + type: Optional[str] = None + enum: Optional[List[Any]] = None + const: Optional[Any] = None + multipleOf: Optional[float] = Field(default=None, gt=0) maximum: Optional[float] = None exclusiveMaximum: Optional[float] = None minimum: Optional[float] = None @@ -115,29 +151,41 @@ class Schema(BaseModel): maxItems: Optional[int] = Field(default=None, ge=0) minItems: Optional[int] = Field(default=None, ge=0) uniqueItems: Optional[bool] = None + maxContains: Optional[int] = Field(default=None, ge=0) + minContains: Optional[int] = Field(default=None, ge=0) maxProperties: Optional[int] = Field(default=None, ge=0) minProperties: Optional[int] = Field(default=None, ge=0) required: Optional[List[str]] = None - enum: Optional[List[Any]] = None - type: Optional[str] = None - allOf: Optional[List["Schema"]] = None - oneOf: Optional[List["Schema"]] = None - anyOf: Optional[List["Schema"]] = None - not_: Optional["Schema"] = Field(default=None, alias="not") - items: Optional[Union["Schema", List["Schema"]]] = None - properties: Optional[Dict[str, "Schema"]] = None - additionalProperties: Optional[Union["Schema", Reference, bool]] = None - description: Optional[str] = None + dependentRequired: Optional[Dict[str, Set[str]]] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c + # Vocabularies for Semantic Content With "format" format: Optional[str] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten + # A Vocabulary for the Contents of String-Encoded Data + contentEncoding: Optional[str] = None + contentMediaType: Optional[str] = None + contentSchema: Optional["Schema"] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta + # A Vocabulary for Basic Meta-Data Annotations + title: Optional[str] = None + description: Optional[str] = None default: Optional[Any] = None - nullable: Optional[bool] = None - discriminator: Optional[Discriminator] = None + deprecated: Optional[bool] = None readOnly: Optional[bool] = None writeOnly: Optional[bool] = None + examples: Optional[List[Any]] = None + # Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object + # Schema Object + discriminator: Optional[Discriminator] = None xml: Optional[XML] = None externalDocs: Optional[ExternalDocumentation] = None - example: Optional[Any] = None - deprecated: Optional[bool] = None + example: Annotated[ + Optional[Any], + typing_deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = None class Config: extra: str = "allow" @@ -248,7 +296,7 @@ class Operation(BaseModel): parameters: Optional[List[Union[Parameter, Reference]]] = None requestBody: Optional[Union[RequestBody, Reference]] = None # Using Any for Specification Extensions - responses: Dict[str, Union[Response, Any]] + responses: Optional[Dict[str, Union[Response, Any]]] = None callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None deprecated: Optional[bool] = None security: Optional[List[Dict[str, List[str]]]] = None @@ -375,6 +423,7 @@ class Components(BaseModel): links: Optional[Dict[str, Union[Link, Reference]]] = None # Using Any for Specification Extensions callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None + pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None class Config: extra = "allow" @@ -392,9 +441,11 @@ class Tag(BaseModel): class OpenAPI(BaseModel): openapi: str info: Info + jsonSchemaDialect: Optional[str] = None servers: Optional[List[Server]] = None # Using Any for Specification Extensions - paths: Dict[str, Union[PathItem, Any]] + paths: Optional[Dict[str, Union[PathItem, Any]]] = None + webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None components: Optional[Components] = None security: Optional[List[Dict[str, List[str]]]] = None tags: Optional[List[Tag]] = None diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 6d736647b5..609fe4389f 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -106,9 +106,7 @@ def get_openapi_operation_parameters( } if field_info.description: parameter["description"] = field_info.description - if field_info.examples: - parameter["examples"] = jsonable_encoder(field_info.examples) - elif field_info.example != Undefined: + if field_info.example != Undefined: parameter["example"] = jsonable_encoder(field_info.example) if field_info.deprecated: parameter["deprecated"] = field_info.deprecated @@ -134,9 +132,7 @@ def get_openapi_operation_request_body( if required: request_body_oai["required"] = required request_media_content: Dict[str, Any] = {"schema": body_schema} - if field_info.examples: - request_media_content["examples"] = jsonable_encoder(field_info.examples) - elif field_info.example != Undefined: + if field_info.example != Undefined: request_media_content["example"] = jsonable_encoder(field_info.example) request_body_oai["content"] = {request_media_type: request_media_content} return request_body_oai @@ -392,9 +388,11 @@ def get_openapi( *, title: str, version: str, - openapi_version: str = "3.0.2", + openapi_version: str = "3.1.0", + summary: Optional[str] = None, description: Optional[str] = None, routes: Sequence[BaseRoute], + webhooks: Optional[Sequence[BaseRoute]] = None, tags: Optional[List[Dict[str, Any]]] = None, servers: Optional[List[Dict[str, Union[str, Any]]]] = None, terms_of_service: Optional[str] = None, @@ -402,6 +400,8 @@ def get_openapi( license_info: Optional[Dict[str, Union[str, Any]]] = None, ) -> Dict[str, Any]: info: Dict[str, Any] = {"title": title, "version": version} + if summary: + info["summary"] = summary if description: info["description"] = description if terms_of_service: @@ -415,13 +415,14 @@ def get_openapi( output["servers"] = servers components: Dict[str, Dict[str, Any]] = {} paths: Dict[str, Dict[str, Any]] = {} + webhook_paths: Dict[str, Dict[str, Any]] = {} operation_ids: Set[str] = set() - flat_models = get_flat_models_from_routes(routes) + flat_models = get_flat_models_from_routes(list(routes or []) + list(webhooks or [])) model_name_map = get_model_name_map(flat_models) definitions = get_model_definitions( flat_models=flat_models, model_name_map=model_name_map ) - for route in routes: + for route in routes or []: if isinstance(route, routing.APIRoute): result = get_openapi_path( route=route, model_name_map=model_name_map, operation_ids=operation_ids @@ -436,11 +437,30 @@ def get_openapi( ) if path_definitions: definitions.update(path_definitions) + for webhook in webhooks or []: + if isinstance(webhook, routing.APIRoute): + result = get_openapi_path( + route=webhook, + model_name_map=model_name_map, + operation_ids=operation_ids, + ) + if result: + path, security_schemes, path_definitions = result + if path: + webhook_paths.setdefault(webhook.path_format, {}).update(path) + if security_schemes: + components.setdefault("securitySchemes", {}).update( + security_schemes + ) + if path_definitions: + definitions.update(path_definitions) if definitions: components["schemas"] = {k: definitions[k] for k in sorted(definitions)} if components: output["components"] = components output["paths"] = paths + if webhook_paths: + output["webhooks"] = webhook_paths if tags: output["tags"] = tags return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py index 75f054e9dc..2f5818c85c 100644 --- a/fastapi/param_functions.py +++ b/fastapi/param_functions.py @@ -1,7 +1,8 @@ -from typing import Any, Callable, Dict, Optional, Sequence +from typing import Any, Callable, List, Optional, Sequence from fastapi import params from pydantic.fields import Undefined +from typing_extensions import Annotated, deprecated def Path( # noqa: N802 @@ -17,8 +18,14 @@ def Path( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, @@ -56,8 +63,14 @@ def Query( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, @@ -96,8 +109,14 @@ def Header( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, @@ -136,8 +155,14 @@ def Cookie( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, @@ -177,8 +202,14 @@ def Body( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, **extra: Any, ) -> Any: return params.Body( @@ -215,8 +246,14 @@ def Form( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, **extra: Any, ) -> Any: return params.Form( @@ -252,8 +289,14 @@ def File( # noqa: N802 min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, **extra: Any, ) -> Any: return params.File( diff --git a/fastapi/params.py b/fastapi/params.py index 16c5c309a7..4069f2cda6 100644 --- a/fastapi/params.py +++ b/fastapi/params.py @@ -1,7 +1,9 @@ +import warnings from enum import Enum -from typing import Any, Callable, Dict, Optional, Sequence +from typing import Any, Callable, List, Optional, Sequence from pydantic.fields import FieldInfo, Undefined +from typing_extensions import Annotated, deprecated class ParamTypes(Enum): @@ -28,16 +30,30 @@ class Param(FieldInfo): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, ): self.deprecated = deprecated + if example is not Undefined: + warnings.warn( + "`example` has been depreacated, please use `examples` instead", + category=DeprecationWarning, + stacklevel=1, + ) self.example = example - self.examples = examples self.include_in_schema = include_in_schema + extra_kwargs = {**extra} + if examples: + extra_kwargs["examples"] = examples super().__init__( default=default, alias=alias, @@ -50,7 +66,7 @@ class Param(FieldInfo): min_length=min_length, max_length=max_length, regex=regex, - **extra, + **extra_kwargs, ) def __repr__(self) -> str: @@ -74,8 +90,14 @@ class Path(Param): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, @@ -119,8 +141,14 @@ class Query(Param): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, @@ -163,8 +191,14 @@ class Header(Param): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, @@ -207,8 +241,14 @@ class Cookie(Param): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, deprecated: Optional[bool] = None, include_in_schema: bool = True, **extra: Any, @@ -250,14 +290,28 @@ class Body(FieldInfo): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, **extra: Any, ): self.embed = embed self.media_type = media_type + if example is not Undefined: + warnings.warn( + "`example` has been depreacated, please use `examples` instead", + category=DeprecationWarning, + stacklevel=1, + ) self.example = example - self.examples = examples + extra_kwargs = {**extra} + if examples is not None: + extra_kwargs["examples"] = examples super().__init__( default=default, alias=alias, @@ -270,7 +324,7 @@ class Body(FieldInfo): min_length=min_length, max_length=max_length, regex=regex, - **extra, + **extra_kwargs, ) def __repr__(self) -> str: @@ -293,8 +347,14 @@ class Form(Body): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, **extra: Any, ): super().__init__( @@ -333,8 +393,14 @@ class File(Form): min_length: Optional[int] = None, max_length: Optional[int] = None, regex: Optional[str] = None, - example: Any = Undefined, - examples: Optional[Dict[str, Any]] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, **extra: Any, ): super().__init__( diff --git a/pyproject.toml b/pyproject.toml index 5c0d3c48ec..61dbf76298 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,7 @@ classifiers = [ dependencies = [ "starlette>=0.27.0,<0.28.0", "pydantic>=1.7.4,!=1.8,!=1.8.1,<2.0.0", + "typing-extensions>=4.5.0" ] dynamic = ["version"] diff --git a/tests/test_additional_properties.py b/tests/test_additional_properties.py index 516a569e42..be14d10edc 100644 --- a/tests/test_additional_properties.py +++ b/tests/test_additional_properties.py @@ -29,7 +29,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/foo": { diff --git a/tests/test_additional_response_extra.py b/tests/test_additional_response_extra.py index d62638c8fa..55be19bad2 100644 --- a/tests/test_additional_response_extra.py +++ b/tests/test_additional_response_extra.py @@ -30,7 +30,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_additional_responses_bad.py b/tests/test_additional_responses_bad.py index d2eb4d7a19..36df07f468 100644 --- a/tests/test_additional_responses_bad.py +++ b/tests/test_additional_responses_bad.py @@ -11,7 +11,7 @@ async def a(): openapi_schema = { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a": { diff --git a/tests/test_additional_responses_custom_model_in_callback.py b/tests/test_additional_responses_custom_model_in_callback.py index 5c08eaa6d2..3971591427 100644 --- a/tests/test_additional_responses_custom_model_in_callback.py +++ b/tests/test_additional_responses_custom_model_in_callback.py @@ -32,7 +32,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_additional_responses_custom_validationerror.py b/tests/test_additional_responses_custom_validationerror.py index 0526027685..9fec5c96d4 100644 --- a/tests/test_additional_responses_custom_validationerror.py +++ b/tests/test_additional_responses_custom_validationerror.py @@ -37,7 +37,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a/{id}": { diff --git a/tests/test_additional_responses_default_validationerror.py b/tests/test_additional_responses_default_validationerror.py index 58de46ff60..153f04f579 100644 --- a/tests/test_additional_responses_default_validationerror.py +++ b/tests/test_additional_responses_default_validationerror.py @@ -16,7 +16,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a/{id}": { diff --git a/tests/test_additional_responses_response_class.py b/tests/test_additional_responses_response_class.py index 6746760f0e..68753561c9 100644 --- a/tests/test_additional_responses_response_class.py +++ b/tests/test_additional_responses_response_class.py @@ -42,7 +42,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a": { diff --git a/tests/test_additional_responses_router.py b/tests/test_additional_responses_router.py index 58d54b733e..71cabc7c3d 100644 --- a/tests/test_additional_responses_router.py +++ b/tests/test_additional_responses_router.py @@ -85,7 +85,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a": { diff --git a/tests/test_annotated.py b/tests/test_annotated.py index a4f42b038f..5a70c45418 100644 --- a/tests/test_annotated.py +++ b/tests/test_annotated.py @@ -118,7 +118,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/default": { diff --git a/tests/test_application.py b/tests/test_application.py index e5f2f43878..b036e67afe 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -55,7 +55,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/api_route": { diff --git a/tests/test_custom_route_class.py b/tests/test_custom_route_class.py index d1b18ef1d2..55374584b0 100644 --- a/tests/test_custom_route_class.py +++ b/tests/test_custom_route_class.py @@ -75,7 +75,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a/": { diff --git a/tests/test_dependency_duplicates.py b/tests/test_dependency_duplicates.py index 285fdf1ab7..4f4f3166ca 100644 --- a/tests/test_dependency_duplicates.py +++ b/tests/test_dependency_duplicates.py @@ -86,7 +86,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/with-duplicates": { diff --git a/tests/test_deprecated_openapi_prefix.py b/tests/test_deprecated_openapi_prefix.py index 688b9837f2..ec7366d2af 100644 --- a/tests/test_deprecated_openapi_prefix.py +++ b/tests/test_deprecated_openapi_prefix.py @@ -22,7 +22,7 @@ def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/app": { diff --git a/tests/test_duplicate_models_openapi.py b/tests/test_duplicate_models_openapi.py index 116b2006a0..83e86d231a 100644 --- a/tests/test_duplicate_models_openapi.py +++ b/tests/test_duplicate_models_openapi.py @@ -36,7 +36,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index bf05aa5852..b64f8341b8 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -57,7 +57,7 @@ expected_schema = { } }, "info": {"title": "FastAPI", "version": "0.1.0"}, - "openapi": "3.0.2", + "openapi": "3.1.0", "paths": { "/foo": { "get": { diff --git a/tests/test_extra_routes.py b/tests/test_extra_routes.py index c0db62c19d..fa95d061c4 100644 --- a/tests/test_extra_routes.py +++ b/tests/test_extra_routes.py @@ -99,7 +99,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_filter_pydantic_sub_model.py b/tests/test_filter_pydantic_sub_model.py index 15b15f8624..6ee928d07f 100644 --- a/tests/test_filter_pydantic_sub_model.py +++ b/tests/test_filter_pydantic_sub_model.py @@ -66,7 +66,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/model/{name}": { diff --git a/tests/test_generate_unique_id_function.py b/tests/test_generate_unique_id_function.py index 0b519f8596..c5ef5182b7 100644 --- a/tests/test_generate_unique_id_function.py +++ b/tests/test_generate_unique_id_function.py @@ -48,7 +48,7 @@ def test_top_level_generate_unique_id(): response = client.get("/openapi.json") data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { @@ -249,7 +249,7 @@ def test_router_overrides_generate_unique_id(): response = client.get("/openapi.json") data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { @@ -450,7 +450,7 @@ def test_router_include_overrides_generate_unique_id(): response = client.get("/openapi.json") data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { @@ -661,7 +661,7 @@ def test_subrouter_top_level_include_overrides_generate_unique_id(): response = client.get("/openapi.json") data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { @@ -928,7 +928,7 @@ def test_router_path_operation_overrides_generate_unique_id(): response = client.get("/openapi.json") data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { @@ -1136,7 +1136,7 @@ def test_app_path_operation_overrides_generate_unique_id(): response = client.get("/openapi.json") data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { @@ -1353,7 +1353,7 @@ def test_callback_override_generate_unique_id(): response = client.get("/openapi.json") data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_get_request_body.py b/tests/test_get_request_body.py index 541147fa8f..cc567b88f6 100644 --- a/tests/test_get_request_body.py +++ b/tests/test_get_request_body.py @@ -29,7 +29,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/product": { diff --git a/tests/test_include_router_defaults_overrides.py b/tests/test_include_router_defaults_overrides.py index ced56c84d3..33baa25e6a 100644 --- a/tests/test_include_router_defaults_overrides.py +++ b/tests/test_include_router_defaults_overrides.py @@ -443,7 +443,7 @@ def test_openapi(): assert issubclass(w[-1].category, UserWarning) assert "Duplicate Operation ID" in str(w[-1].message) assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/override1": { diff --git a/tests/test_modules_same_name_body/test_main.py b/tests/test_modules_same_name_body/test_main.py index 1ebcaee8cf..cc165bdcaa 100644 --- a/tests/test_modules_same_name_body/test_main.py +++ b/tests/test_modules_same_name_body/test_main.py @@ -35,7 +35,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a/compute": { diff --git a/tests/test_multi_body_errors.py b/tests/test_multi_body_errors.py index 358684bc5c..96043aa35f 100644 --- a/tests/test_multi_body_errors.py +++ b/tests/test_multi_body_errors.py @@ -80,7 +80,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_multi_query_errors.py b/tests/test_multi_query_errors.py index e7a833f2ba..c1f0678d01 100644 --- a/tests/test_multi_query_errors.py +++ b/tests/test_multi_query_errors.py @@ -46,7 +46,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_openapi_query_parameter_extension.py b/tests/test_openapi_query_parameter_extension.py index 8a9086ebe1..6f62e67265 100644 --- a/tests/test_openapi_query_parameter_extension.py +++ b/tests/test_openapi_query_parameter_extension.py @@ -42,7 +42,7 @@ def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_openapi_route_extensions.py b/tests/test_openapi_route_extensions.py index 943dc43f2d..3a30994367 100644 --- a/tests/test_openapi_route_extensions.py +++ b/tests/test_openapi_route_extensions.py @@ -22,7 +22,7 @@ def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_openapi_servers.py b/tests/test_openapi_servers.py index 26abeaa12d..11cd795ac5 100644 --- a/tests/test_openapi_servers.py +++ b/tests/test_openapi_servers.py @@ -30,7 +30,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "servers": [ {"url": "/", "description": "Default, relative server"}, diff --git a/tests/test_param_in_path_and_dependency.py b/tests/test_param_in_path_and_dependency.py index 0aef7ac7bc..08eb0f40f3 100644 --- a/tests/test_param_in_path_and_dependency.py +++ b/tests/test_param_in_path_and_dependency.py @@ -25,7 +25,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/{user_id}": { diff --git a/tests/test_param_include_in_schema.py b/tests/test_param_include_in_schema.py index d0c29f7b2d..26201e9e2d 100644 --- a/tests/test_param_include_in_schema.py +++ b/tests/test_param_include_in_schema.py @@ -34,7 +34,7 @@ async def hidden_query( openapi_schema = { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/hidden_cookie": { diff --git a/tests/test_put_no_body.py b/tests/test_put_no_body.py index a02d1152c8..8f4c82532c 100644 --- a/tests/test_put_no_body.py +++ b/tests/test_put_no_body.py @@ -28,7 +28,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_repeated_dependency_schema.py b/tests/test_repeated_dependency_schema.py index ca0305184a..d7d0dfa052 100644 --- a/tests/test_repeated_dependency_schema.py +++ b/tests/test_repeated_dependency_schema.py @@ -50,7 +50,7 @@ schema = { } }, "info": {"title": "FastAPI", "version": "0.1.0"}, - "openapi": "3.0.2", + "openapi": "3.1.0", "paths": { "/": { "get": { diff --git a/tests/test_repeated_parameter_alias.py b/tests/test_repeated_parameter_alias.py index c656a161df..fd72eaab29 100644 --- a/tests/test_repeated_parameter_alias.py +++ b/tests/test_repeated_parameter_alias.py @@ -58,7 +58,7 @@ def test_openapi_schema(): } }, "info": {"title": "FastAPI", "version": "0.1.0"}, - "openapi": "3.0.2", + "openapi": "3.1.0", "paths": { "/{repeated_alias}": { "get": { diff --git a/tests/test_reponse_set_reponse_code_empty.py b/tests/test_reponse_set_reponse_code_empty.py index 14770fed0a..bf3aa758c3 100644 --- a/tests/test_reponse_set_reponse_code_empty.py +++ b/tests/test_reponse_set_reponse_code_empty.py @@ -32,7 +32,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/{id}": { diff --git a/tests/test_request_body_parameters_media_type.py b/tests/test_request_body_parameters_media_type.py index 32f6c6a725..8424bf551e 100644 --- a/tests/test_request_body_parameters_media_type.py +++ b/tests/test_request_body_parameters_media_type.py @@ -41,7 +41,7 @@ def test_openapi_schema(): assert response.status_code == 200, response.text # insert_assert(response.json()) assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/products": { diff --git a/tests/test_response_by_alias.py b/tests/test_response_by_alias.py index 1861a40fab..c3ff5b1d25 100644 --- a/tests/test_response_by_alias.py +++ b/tests/test_response_by_alias.py @@ -138,7 +138,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/dict": { diff --git a/tests/test_response_class_no_mediatype.py b/tests/test_response_class_no_mediatype.py index 2d75c75358..706929ac36 100644 --- a/tests/test_response_class_no_mediatype.py +++ b/tests/test_response_class_no_mediatype.py @@ -42,7 +42,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a": { diff --git a/tests/test_response_code_no_body.py b/tests/test_response_code_no_body.py index 3851a325de..3ca8708f12 100644 --- a/tests/test_response_code_no_body.py +++ b/tests/test_response_code_no_body.py @@ -50,7 +50,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/a": { diff --git a/tests/test_response_model_as_return_annotation.py b/tests/test_response_model_as_return_annotation.py index 7decdff7d0..7a0cf47ec4 100644 --- a/tests/test_response_model_as_return_annotation.py +++ b/tests/test_response_model_as_return_annotation.py @@ -507,7 +507,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/no_response_model-no_annotation-return_model": { diff --git a/tests/test_response_model_sub_types.py b/tests/test_response_model_sub_types.py index e462006ff1..660bcee1bb 100644 --- a/tests/test_response_model_sub_types.py +++ b/tests/test_response_model_sub_types.py @@ -50,7 +50,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/valid1": { diff --git a/tests/test_schema_extra_examples.py b/tests/test_schema_extra_examples.py index 41021a9839..45caa16150 100644 --- a/tests/test_schema_extra_examples.py +++ b/tests/test_schema_extra_examples.py @@ -1,240 +1,220 @@ from typing import Union +import pytest from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi.testclient import TestClient from pydantic import BaseModel -app = FastAPI() - -class Item(BaseModel): - data: str - - class Config: - schema_extra = {"example": {"data": "Data in schema_extra"}} - - -@app.post("/schema_extra/") -def schema_extra(item: Item): - return item - - -@app.post("/example/") -def example(item: Item = Body(example={"data": "Data in Body example"})): - return item - - -@app.post("/examples/") -def examples( - item: Item = Body( - examples={ - "example1": { - "summary": "example1 summary", - "value": {"data": "Data in Body examples, example1"}, - }, - "example2": {"value": {"data": "Data in Body examples, example2"}}, - }, - ) -): - return item - - -@app.post("/example_examples/") -def example_examples( - item: Item = Body( - example={"data": "Overridden example"}, - examples={ - "example1": {"value": {"data": "examples example_examples 1"}}, - "example2": {"value": {"data": "examples example_examples 2"}}, - }, - ) -): - return item - - -# TODO: enable these tests once/if Form(embed=False) is supported -# TODO: In that case, define if File() should support example/examples too -# @app.post("/form_example") -# def form_example(firstname: str = Form(example="John")): -# return firstname - - -# @app.post("/form_examples") -# def form_examples( -# lastname: str = Form( -# ..., -# examples={ -# "example1": {"summary": "last name summary", "value": "Doe"}, -# "example2": {"value": "Doesn't"}, -# }, -# ), -# ): -# return lastname - - -# @app.post("/form_example_examples") -# def form_example_examples( -# lastname: str = Form( -# ..., -# example="Doe overridden", -# examples={ -# "example1": {"summary": "last name summary", "value": "Doe"}, -# "example2": {"value": "Doesn't"}, -# }, -# ), -# ): -# return lastname - - -@app.get("/path_example/{item_id}") -def path_example( - item_id: str = Path( - example="item_1", - ), -): - return item_id - - -@app.get("/path_examples/{item_id}") -def path_examples( - item_id: str = Path( - examples={ - "example1": {"summary": "item ID summary", "value": "item_1"}, - "example2": {"value": "item_2"}, - }, - ), -): - return item_id - - -@app.get("/path_example_examples/{item_id}") -def path_example_examples( - item_id: str = Path( - example="item_overridden", - examples={ - "example1": {"summary": "item ID summary", "value": "item_1"}, - "example2": {"value": "item_2"}, - }, - ), -): - return item_id - - -@app.get("/query_example/") -def query_example( - data: Union[str, None] = Query( - default=None, - example="query1", - ), -): - return data - - -@app.get("/query_examples/") -def query_examples( - data: Union[str, None] = Query( - default=None, - examples={ - "example1": {"summary": "Query example 1", "value": "query1"}, - "example2": {"value": "query2"}, - }, - ), -): - return data - - -@app.get("/query_example_examples/") -def query_example_examples( - data: Union[str, None] = Query( - default=None, - example="query_overridden", - examples={ - "example1": {"summary": "Query example 1", "value": "query1"}, - "example2": {"value": "query2"}, - }, - ), -): - return data - - -@app.get("/header_example/") -def header_example( - data: Union[str, None] = Header( - default=None, - example="header1", - ), -): - return data - - -@app.get("/header_examples/") -def header_examples( - data: Union[str, None] = Header( - default=None, - examples={ - "example1": {"summary": "header example 1", "value": "header1"}, - "example2": {"value": "header2"}, - }, - ), -): - return data - - -@app.get("/header_example_examples/") -def header_example_examples( - data: Union[str, None] = Header( - default=None, - example="header_overridden", - examples={ - "example1": {"summary": "Query example 1", "value": "header1"}, - "example2": {"value": "header2"}, - }, - ), -): - return data - - -@app.get("/cookie_example/") -def cookie_example( - data: Union[str, None] = Cookie( - default=None, - example="cookie1", - ), -): - return data - - -@app.get("/cookie_examples/") -def cookie_examples( - data: Union[str, None] = Cookie( - default=None, - examples={ - "example1": {"summary": "cookie example 1", "value": "cookie1"}, - "example2": {"value": "cookie2"}, - }, - ), -): - return data - - -@app.get("/cookie_example_examples/") -def cookie_example_examples( - data: Union[str, None] = Cookie( - default=None, - example="cookie_overridden", - examples={ - "example1": {"summary": "Query example 1", "value": "cookie1"}, - "example2": {"value": "cookie2"}, - }, - ), -): - return data - - -client = TestClient(app) +def create_app(): + app = FastAPI() + + class Item(BaseModel): + data: str + + class Config: + schema_extra = {"example": {"data": "Data in schema_extra"}} + + @app.post("/schema_extra/") + def schema_extra(item: Item): + return item + + with pytest.warns(DeprecationWarning): + + @app.post("/example/") + def example(item: Item = Body(example={"data": "Data in Body example"})): + return item + + @app.post("/examples/") + def examples( + item: Item = Body( + examples=[ + {"data": "Data in Body examples, example1"}, + {"data": "Data in Body examples, example2"}, + ], + ) + ): + return item + + with pytest.warns(DeprecationWarning): + + @app.post("/example_examples/") + def example_examples( + item: Item = Body( + example={"data": "Overridden example"}, + examples=[ + {"data": "examples example_examples 1"}, + {"data": "examples example_examples 2"}, + ], + ) + ): + return item + + # TODO: enable these tests once/if Form(embed=False) is supported + # TODO: In that case, define if File() should support example/examples too + # @app.post("/form_example") + # def form_example(firstname: str = Form(example="John")): + # return firstname + + # @app.post("/form_examples") + # def form_examples( + # lastname: str = Form( + # ..., + # examples={ + # "example1": {"summary": "last name summary", "value": "Doe"}, + # "example2": {"value": "Doesn't"}, + # }, + # ), + # ): + # return lastname + + # @app.post("/form_example_examples") + # def form_example_examples( + # lastname: str = Form( + # ..., + # example="Doe overridden", + # examples={ + # "example1": {"summary": "last name summary", "value": "Doe"}, + # "example2": {"value": "Doesn't"}, + # }, + # ), + # ): + # return lastname + + with pytest.warns(DeprecationWarning): + + @app.get("/path_example/{item_id}") + def path_example( + item_id: str = Path( + example="item_1", + ), + ): + return item_id + + @app.get("/path_examples/{item_id}") + def path_examples( + item_id: str = Path( + examples=["item_1", "item_2"], + ), + ): + return item_id + + with pytest.warns(DeprecationWarning): + + @app.get("/path_example_examples/{item_id}") + def path_example_examples( + item_id: str = Path( + example="item_overridden", + examples=["item_1", "item_2"], + ), + ): + return item_id + + with pytest.warns(DeprecationWarning): + + @app.get("/query_example/") + def query_example( + data: Union[str, None] = Query( + default=None, + example="query1", + ), + ): + return data + + @app.get("/query_examples/") + def query_examples( + data: Union[str, None] = Query( + default=None, + examples=["query1", "query2"], + ), + ): + return data + + with pytest.warns(DeprecationWarning): + + @app.get("/query_example_examples/") + def query_example_examples( + data: Union[str, None] = Query( + default=None, + example="query_overridden", + examples=["query1", "query2"], + ), + ): + return data + + with pytest.warns(DeprecationWarning): + + @app.get("/header_example/") + def header_example( + data: Union[str, None] = Header( + default=None, + example="header1", + ), + ): + return data + + @app.get("/header_examples/") + def header_examples( + data: Union[str, None] = Header( + default=None, + examples=[ + "header1", + "header2", + ], + ), + ): + return data + + with pytest.warns(DeprecationWarning): + + @app.get("/header_example_examples/") + def header_example_examples( + data: Union[str, None] = Header( + default=None, + example="header_overridden", + examples=["header1", "header2"], + ), + ): + return data + + with pytest.warns(DeprecationWarning): + + @app.get("/cookie_example/") + def cookie_example( + data: Union[str, None] = Cookie( + default=None, + example="cookie1", + ), + ): + return data + + @app.get("/cookie_examples/") + def cookie_examples( + data: Union[str, None] = Cookie( + default=None, + examples=["cookie1", "cookie2"], + ), + ): + return data + + with pytest.warns(DeprecationWarning): + + @app.get("/cookie_example_examples/") + def cookie_example_examples( + data: Union[str, None] = Cookie( + default=None, + example="cookie_overridden", + examples=["cookie1", "cookie2"], + ), + ): + return data + + return app def test_call_api(): + app = create_app() + client = TestClient(app) response = client.post("/schema_extra/", json={"data": "Foo"}) assert response.status_code == 200, response.text response = client.post("/example/", json={"data": "Foo"}) @@ -277,10 +257,12 @@ def test_openapi_schema(): * Body(example={}) overrides schema_extra in pydantic model * Body(examples{}) overrides Body(example={}) and schema_extra in pydantic model """ + app = create_app() + client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/schema_extra/": { @@ -351,20 +333,14 @@ def test_openapi_schema(): "requestBody": { "content": { "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "example1": { - "summary": "example1 summary", - "value": { - "data": "Data in Body examples, example1" - }, - }, - "example2": { - "value": { - "data": "Data in Body examples, example2" - } - }, - }, + "schema": { + "allOf": [{"$ref": "#/components/schemas/Item"}], + "title": "Item", + "examples": [ + {"data": "Data in Body examples, example1"}, + {"data": "Data in Body examples, example2"}, + ], + } } }, "required": True, @@ -394,15 +370,15 @@ def test_openapi_schema(): "requestBody": { "content": { "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "example1": { - "value": {"data": "examples example_examples 1"} - }, - "example2": { - "value": {"data": "examples example_examples 2"} - }, + "schema": { + "allOf": [{"$ref": "#/components/schemas/Item"}], + "title": "Item", + "examples": [ + {"data": "examples example_examples 1"}, + {"data": "examples example_examples 2"}, + ], }, + "example": {"data": "Overridden example"}, } }, "required": True, @@ -463,13 +439,10 @@ def test_openapi_schema(): "parameters": [ { "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "examples": { - "example1": { - "summary": "item ID summary", - "value": "item_1", - }, - "example2": {"value": "item_2"}, + "schema": { + "title": "Item Id", + "type": "string", + "examples": ["item_1", "item_2"], }, "name": "item_id", "in": "path", @@ -500,14 +473,12 @@ def test_openapi_schema(): "parameters": [ { "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "examples": { - "example1": { - "summary": "item ID summary", - "value": "item_1", - }, - "example2": {"value": "item_2"}, + "schema": { + "title": "Item Id", + "type": "string", + "examples": ["item_1", "item_2"], }, + "example": "item_overridden", "name": "item_id", "in": "path", } @@ -568,13 +539,10 @@ def test_openapi_schema(): "parameters": [ { "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "Query example 1", - "value": "query1", - }, - "example2": {"value": "query2"}, + "schema": { + "type": "string", + "title": "Data", + "examples": ["query1", "query2"], }, "name": "data", "in": "query", @@ -605,14 +573,12 @@ def test_openapi_schema(): "parameters": [ { "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "Query example 1", - "value": "query1", - }, - "example2": {"value": "query2"}, + "schema": { + "type": "string", + "title": "Data", + "examples": ["query1", "query2"], }, + "example": "query_overridden", "name": "data", "in": "query", } @@ -642,7 +608,7 @@ def test_openapi_schema(): "parameters": [ { "required": False, - "schema": {"title": "Data", "type": "string"}, + "schema": {"type": "string", "title": "Data"}, "example": "header1", "name": "data", "in": "header", @@ -673,13 +639,10 @@ def test_openapi_schema(): "parameters": [ { "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "header example 1", - "value": "header1", - }, - "example2": {"value": "header2"}, + "schema": { + "type": "string", + "title": "Data", + "examples": ["header1", "header2"], }, "name": "data", "in": "header", @@ -710,14 +673,12 @@ def test_openapi_schema(): "parameters": [ { "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "Query example 1", - "value": "header1", - }, - "example2": {"value": "header2"}, + "schema": { + "type": "string", + "title": "Data", + "examples": ["header1", "header2"], }, + "example": "header_overridden", "name": "data", "in": "header", } @@ -747,7 +708,7 @@ def test_openapi_schema(): "parameters": [ { "required": False, - "schema": {"title": "Data", "type": "string"}, + "schema": {"type": "string", "title": "Data"}, "example": "cookie1", "name": "data", "in": "cookie", @@ -778,13 +739,10 @@ def test_openapi_schema(): "parameters": [ { "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "cookie example 1", - "value": "cookie1", - }, - "example2": {"value": "cookie2"}, + "schema": { + "type": "string", + "title": "Data", + "examples": ["cookie1", "cookie2"], }, "name": "data", "in": "cookie", @@ -815,14 +773,12 @@ def test_openapi_schema(): "parameters": [ { "required": False, - "schema": {"title": "Data", "type": "string"}, - "examples": { - "example1": { - "summary": "Query example 1", - "value": "cookie1", - }, - "example2": {"value": "cookie2"}, + "schema": { + "type": "string", + "title": "Data", + "examples": ["cookie1", "cookie2"], }, + "example": "cookie_overridden", "name": "data", "in": "cookie", } diff --git a/tests/test_security_api_key_cookie.py b/tests/test_security_api_key_cookie.py index b1c648c55e..4ddb8e2eeb 100644 --- a/tests/test_security_api_key_cookie.py +++ b/tests/test_security_api_key_cookie.py @@ -41,7 +41,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_api_key_cookie_description.py b/tests/test_security_api_key_cookie_description.py index ac8b4abf87..d99d616e06 100644 --- a/tests/test_security_api_key_cookie_description.py +++ b/tests/test_security_api_key_cookie_description.py @@ -41,7 +41,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_api_key_cookie_optional.py b/tests/test_security_api_key_cookie_optional.py index b8c440c9d7..cb5590168d 100644 --- a/tests/test_security_api_key_cookie_optional.py +++ b/tests/test_security_api_key_cookie_optional.py @@ -48,7 +48,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_api_key_header.py b/tests/test_security_api_key_header.py index 96ad80b54a..1ff883703d 100644 --- a/tests/test_security_api_key_header.py +++ b/tests/test_security_api_key_header.py @@ -41,7 +41,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_api_key_header_description.py b/tests/test_security_api_key_header_description.py index 382f53dd78..27f9d0f29e 100644 --- a/tests/test_security_api_key_header_description.py +++ b/tests/test_security_api_key_header_description.py @@ -41,7 +41,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_api_key_header_optional.py b/tests/test_security_api_key_header_optional.py index adfb20ba08..6f9682a64f 100644 --- a/tests/test_security_api_key_header_optional.py +++ b/tests/test_security_api_key_header_optional.py @@ -47,7 +47,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_api_key_query.py b/tests/test_security_api_key_query.py index da98eafd6c..dc7a0a621a 100644 --- a/tests/test_security_api_key_query.py +++ b/tests/test_security_api_key_query.py @@ -41,7 +41,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_api_key_query_description.py b/tests/test_security_api_key_query_description.py index 3c08afc5f4..35dc7743a2 100644 --- a/tests/test_security_api_key_query_description.py +++ b/tests/test_security_api_key_query_description.py @@ -41,7 +41,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_api_key_query_optional.py b/tests/test_security_api_key_query_optional.py index 99a26cfd0b..4cc134bd49 100644 --- a/tests/test_security_api_key_query_optional.py +++ b/tests/test_security_api_key_query_optional.py @@ -47,7 +47,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_base.py b/tests/test_security_http_base.py index d3a7542034..51928bafd5 100644 --- a/tests/test_security_http_base.py +++ b/tests/test_security_http_base.py @@ -31,7 +31,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_base_description.py b/tests/test_security_http_base_description.py index 3d7d150166..bc79f32424 100644 --- a/tests/test_security_http_base_description.py +++ b/tests/test_security_http_base_description.py @@ -31,7 +31,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_base_optional.py b/tests/test_security_http_base_optional.py index 180c9110e9..dd4d76843a 100644 --- a/tests/test_security_http_base_optional.py +++ b/tests/test_security_http_base_optional.py @@ -37,7 +37,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_basic_optional.py b/tests/test_security_http_basic_optional.py index 7e7fcac32a..9b6cb6c455 100644 --- a/tests/test_security_http_basic_optional.py +++ b/tests/test_security_http_basic_optional.py @@ -54,7 +54,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_basic_realm.py b/tests/test_security_http_basic_realm.py index 470afd662a..9fc33971ae 100644 --- a/tests/test_security_http_basic_realm.py +++ b/tests/test_security_http_basic_realm.py @@ -52,7 +52,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_basic_realm_description.py b/tests/test_security_http_basic_realm_description.py index 44289007b5..02122442eb 100644 --- a/tests/test_security_http_basic_realm_description.py +++ b/tests/test_security_http_basic_realm_description.py @@ -52,7 +52,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_bearer.py b/tests/test_security_http_bearer.py index f24869fc32..5b9e2d6919 100644 --- a/tests/test_security_http_bearer.py +++ b/tests/test_security_http_bearer.py @@ -37,7 +37,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_bearer_description.py b/tests/test_security_http_bearer_description.py index 6d5ad0b8e7..2f11c3a148 100644 --- a/tests/test_security_http_bearer_description.py +++ b/tests/test_security_http_bearer_description.py @@ -37,7 +37,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_bearer_optional.py b/tests/test_security_http_bearer_optional.py index b596ac7300..943da2ee2e 100644 --- a/tests/test_security_http_bearer_optional.py +++ b/tests/test_security_http_bearer_optional.py @@ -43,7 +43,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_digest.py b/tests/test_security_http_digest.py index 2a25efe023..133d35763c 100644 --- a/tests/test_security_http_digest.py +++ b/tests/test_security_http_digest.py @@ -39,7 +39,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_digest_description.py b/tests/test_security_http_digest_description.py index 721f7cfde5..4e31a0c008 100644 --- a/tests/test_security_http_digest_description.py +++ b/tests/test_security_http_digest_description.py @@ -39,7 +39,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_http_digest_optional.py b/tests/test_security_http_digest_optional.py index d4c3597bcb..1e6eb8bd7f 100644 --- a/tests/test_security_http_digest_optional.py +++ b/tests/test_security_http_digest_optional.py @@ -45,7 +45,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_oauth2.py b/tests/test_security_oauth2.py index 23dce7cfa9..73d1b7d94c 100644 --- a/tests/test_security_oauth2.py +++ b/tests/test_security_oauth2.py @@ -135,7 +135,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/login": { diff --git a/tests/test_security_oauth2_authorization_code_bearer.py b/tests/test_security_oauth2_authorization_code_bearer.py index 6df81528db..f2097b1490 100644 --- a/tests/test_security_oauth2_authorization_code_bearer.py +++ b/tests/test_security_oauth2_authorization_code_bearer.py @@ -41,7 +41,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_security_oauth2_authorization_code_bearer_description.py b/tests/test_security_oauth2_authorization_code_bearer_description.py index c119abde4d..5386fbbd9d 100644 --- a/tests/test_security_oauth2_authorization_code_bearer_description.py +++ b/tests/test_security_oauth2_authorization_code_bearer_description.py @@ -44,7 +44,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_security_oauth2_optional.py b/tests/test_security_oauth2_optional.py index 3ef9f4a8d2..b24c1b58ff 100644 --- a/tests/test_security_oauth2_optional.py +++ b/tests/test_security_oauth2_optional.py @@ -139,7 +139,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/login": { diff --git a/tests/test_security_oauth2_optional_description.py b/tests/test_security_oauth2_optional_description.py index b6425fde4d..cda635151e 100644 --- a/tests/test_security_oauth2_optional_description.py +++ b/tests/test_security_oauth2_optional_description.py @@ -140,7 +140,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/login": { diff --git a/tests/test_security_oauth2_password_bearer_optional.py b/tests/test_security_oauth2_password_bearer_optional.py index e5dcbb553d..4c9362c3eb 100644 --- a/tests/test_security_oauth2_password_bearer_optional.py +++ b/tests/test_security_oauth2_password_bearer_optional.py @@ -41,7 +41,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_security_oauth2_password_bearer_optional_description.py b/tests/test_security_oauth2_password_bearer_optional_description.py index 9ff48e7156..6e6ea846cd 100644 --- a/tests/test_security_oauth2_password_bearer_optional_description.py +++ b/tests/test_security_oauth2_password_bearer_optional_description.py @@ -45,7 +45,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_security_openid_connect.py b/tests/test_security_openid_connect.py index 206de6574f..1e322e640e 100644 --- a/tests/test_security_openid_connect.py +++ b/tests/test_security_openid_connect.py @@ -47,7 +47,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_openid_connect_description.py b/tests/test_security_openid_connect_description.py index 5884de7930..44cf57f862 100644 --- a/tests/test_security_openid_connect_description.py +++ b/tests/test_security_openid_connect_description.py @@ -49,7 +49,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_security_openid_connect_optional.py b/tests/test_security_openid_connect_optional.py index 8ac7191183..e817434b0d 100644 --- a/tests/test_security_openid_connect_optional.py +++ b/tests/test_security_openid_connect_optional.py @@ -53,7 +53,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_starlette_exception.py b/tests/test_starlette_exception.py index 96f835b935..229fe80163 100644 --- a/tests/test_starlette_exception.py +++ b/tests/test_starlette_exception.py @@ -80,7 +80,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/http-no-body-statuscode-exception": { diff --git a/tests/test_sub_callbacks.py b/tests/test_sub_callbacks.py index c5a0237e80..dce3ea5e29 100644 --- a/tests/test_sub_callbacks.py +++ b/tests/test_sub_callbacks.py @@ -87,7 +87,7 @@ def test_openapi_schema(): with client: response = client.get("/openapi.json") assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/invoices/": { diff --git a/tests/test_tuples.py b/tests/test_tuples.py index 4fa1f7a133..c37a25ca69 100644 --- a/tests/test_tuples.py +++ b/tests/test_tuples.py @@ -86,7 +86,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/model-with-tuple/": { diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial001.py b/tests/test_tutorial/test_additional_responses/test_tutorial001.py index 3d6267023e..3afeaff840 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial001.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial001.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial002.py b/tests/test_tutorial/test_additional_responses/test_tutorial002.py index 6182ed5079..8e084e152d 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial002.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial002.py @@ -27,7 +27,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial003.py b/tests/test_tutorial/test_additional_responses/test_tutorial003.py index 77568d9d4f..bd34d2938c 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial003.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial003.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial004.py b/tests/test_tutorial/test_additional_responses/test_tutorial004.py index 3fbd91e5c2..5fc8b81ca0 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial004.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial004.py @@ -27,7 +27,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py b/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py index 3da362a505..8126cdcc6c 100644 --- a/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py +++ b/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py @@ -22,7 +22,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/notes/": { diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py index 7533a1b689..a070f850f7 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py @@ -15,7 +15,7 @@ def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/app": { diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py index 930ab3bf5c..ce791e2157 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py @@ -15,7 +15,7 @@ def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/app": { diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py index ae8f1a495d..0ae9f4f933 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py @@ -15,7 +15,7 @@ def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "servers": [ {"url": "/api/v1"}, diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py index e67ad1cb1f..576a411a4a 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py @@ -15,7 +15,7 @@ def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "servers": [ {"url": "https://stag.example.com", "description": "Staging environment"}, diff --git a/tests/test_tutorial/test_bigger_applications/test_main.py b/tests/test_tutorial/test_bigger_applications/test_main.py index a13decd75b..7da663435a 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main.py +++ b/tests/test_tutorial/test_bigger_applications/test_main.py @@ -166,7 +166,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_bigger_applications/test_main_an.py b/tests/test_tutorial/test_bigger_applications/test_main_an.py index 64e19c3f39..8f42d9dd1d 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main_an.py +++ b/tests/test_tutorial/test_bigger_applications/test_main_an.py @@ -166,7 +166,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_bigger_applications/test_main_an_py39.py b/tests/test_tutorial/test_bigger_applications/test_main_an_py39.py index 70c86b4d7f..44694e371e 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main_an_py39.py +++ b/tests/test_tutorial/test_bigger_applications/test_main_an_py39.py @@ -181,7 +181,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index cd1209adea..469198e0ff 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -200,7 +200,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_body/test_tutorial001_py310.py b/tests/test_tutorial/test_body/test_tutorial001_py310.py index 5ebcbbf574..a68b4e0446 100644 --- a/tests/test_tutorial/test_body/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body/test_tutorial001_py310.py @@ -215,7 +215,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001.py b/tests/test_tutorial/test_body_fields/test_tutorial001.py index a7ea0e9496..4999cbf6b5 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001.py @@ -64,7 +64,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_an.py b/tests/test_tutorial/test_body_fields/test_tutorial001_an.py index 32f996ecbd..011946d075 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_an.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_an.py @@ -64,7 +64,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_an_py310.py b/tests/test_tutorial/test_body_fields/test_tutorial001_an_py310.py index 20e032fcd8..e7dcb54e9c 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_an_py310.py @@ -72,7 +72,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_an_py39.py b/tests/test_tutorial/test_body_fields/test_tutorial001_an_py39.py index e3baf5f2ba..f1015a03b4 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_an_py39.py @@ -72,7 +72,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py b/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py index 4c2f48674a..29c8ef4e9c 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001_py310.py @@ -72,7 +72,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py index 496ab38fb9..ce41a42834 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py @@ -50,7 +50,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an.py index 74a8a9b2e4..acc4cfadc7 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an.py @@ -50,7 +50,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py310.py index 9c764b6d17..a8dc02a6c2 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py310.py @@ -58,7 +58,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py39.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py39.py index 0cca294333..f31fee78e4 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_an_py39.py @@ -58,7 +58,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py index 3b61e717ec..0e46df253f 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001_py310.py @@ -58,7 +58,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py index b34377a28c..8555cf88c5 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py @@ -90,7 +90,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py index 9b8d5e15ba..f4d300cc56 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py @@ -90,7 +90,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py index f8af555fcd..afe2b2c20b 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py @@ -98,7 +98,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py index 06e2c3146f..033d5892e5 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py @@ -98,7 +98,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py index 82c5fb1013..8fcc000138 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py @@ -98,7 +98,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py index 378c241975..ac39cd93f4 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py @@ -31,7 +31,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/index-weights/": { diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py index 5ca63a92bd..0800abe29b 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009_py39.py @@ -41,7 +41,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/index-weights/": { diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py index 939bf44e0a..151b4b9176 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py @@ -34,7 +34,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py b/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py index 5f50f2071a..c4b4b9df33 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py @@ -44,7 +44,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py b/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py index d4fdabce66..940b4b3b86 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py @@ -44,7 +44,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py index c1d8fd8051..a43394ab16 100644 --- a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py +++ b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py @@ -33,7 +33,7 @@ def test_default_openapi(): assert response.status_code == 200, response.text response = client.get("/openapi.json") assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001.py b/tests/test_tutorial/test_cookie_params/test_tutorial001.py index c3511d129e..902bed843b 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001.py @@ -30,7 +30,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_an.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_an.py index f4f94c09dc..aa5807844f 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_an.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_an.py @@ -30,7 +30,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py310.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py310.py index a80f10f810..ffb55d4e15 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py310.py @@ -36,7 +36,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py39.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py39.py index 1be898c092..9bc38effde 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_an_py39.py @@ -36,7 +36,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py index 7ba542c902..bb2953ef61 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py @@ -36,7 +36,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001.py b/tests/test_tutorial/test_custom_response/test_tutorial001.py index da2ca8d620..fc83624673 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001b.py b/tests/test_tutorial/test_custom_response/test_tutorial001b.py index f681f5a9d0..91e5c501e3 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001b.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_custom_response/test_tutorial004.py b/tests/test_tutorial/test_custom_response/test_tutorial004.py index ef0ba34469..de60574f5e 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial004.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial004.py @@ -27,7 +27,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_custom_response/test_tutorial005.py b/tests/test_tutorial/test_custom_response/test_tutorial005.py index e4b5c15466..889bf3e929 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial005.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial005.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006.py b/tests/test_tutorial/test_custom_response/test_tutorial006.py index 9f1b07bee9..2d0a2cd3f6 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/typer": { diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006b.py b/tests/test_tutorial/test_custom_response/test_tutorial006b.py index cf204cbc05..1739fd4570 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006b.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/fastapi": { diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006c.py b/tests/test_tutorial/test_custom_response/test_tutorial006c.py index f196899aca..51aa1833de 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006c.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006c.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/pydantic": { diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial001.py b/tests/test_tutorial/test_dataclasses/test_tutorial001.py index 26ae04c515..e20c0efe95 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial001.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial001.py @@ -34,7 +34,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial002.py b/tests/test_tutorial/test_dataclasses/test_tutorial002.py index 675e826b11..e122239d85 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial002.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial002.py @@ -22,7 +22,7 @@ def test_openapi_schema(): assert response.status_code == 200 data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/next": { diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py index f3378fe629..204426e8bc 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py @@ -55,7 +55,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/authors/{author_id}/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001.py b/tests/test_tutorial/test_dependencies/test_tutorial001.py index 974b9304fd..a8e564ebe6 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001.py @@ -26,7 +26,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_an.py b/tests/test_tutorial/test_dependencies/test_tutorial001_an.py index b1ca27ff8b..4e6a329f44 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_an.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_an.py @@ -26,7 +26,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_an_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial001_an_py310.py index 70bed03f62..205aee908a 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_an_py310.py @@ -34,7 +34,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial001_an_py39.py index 9c5723be88..73593ea55e 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_an_py39.py @@ -34,7 +34,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py index 1bcde4e9f4..10bf84fb53 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_py310.py @@ -34,7 +34,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004.py b/tests/test_tutorial/test_dependencies/test_tutorial004.py index 298bc290d2..d16fd9ef70 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004.py @@ -64,7 +64,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_an.py b/tests/test_tutorial/test_dependencies/test_tutorial004_an.py index f985be8df0..46fe97fb2c 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_an.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_an.py @@ -64,7 +64,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_an_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial004_an_py310.py index fc02867028..c6a0fc6656 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_an_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_an_py310.py @@ -72,7 +72,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial004_an_py39.py index 1e37673ed8..30431cd293 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_an_py39.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_an_py39.py @@ -72,7 +72,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py b/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py index ab936ccdc0..9793c8c331 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial004_py310.py @@ -72,7 +72,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006.py b/tests/test_tutorial/test_dependencies/test_tutorial006.py index 2e9c82d711..6fac9f8eb3 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006.py @@ -54,7 +54,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006_an.py b/tests/test_tutorial/test_dependencies/test_tutorial006_an.py index 919066dcad..810537e486 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006_an.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006_an.py @@ -54,7 +54,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial006_an_py39.py index c237184796..f17cbcfc72 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006_an_py39.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006_an_py39.py @@ -66,7 +66,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012.py b/tests/test_tutorial/test_dependencies/test_tutorial012.py index b92b96c019..af1fcde55e 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012.py @@ -99,7 +99,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012_an.py b/tests/test_tutorial/test_dependencies/test_tutorial012_an.py index 2ddb7bb532..c33d51d873 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012_an.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012_an.py @@ -99,7 +99,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial012_an_py39.py index 595c83a531..d7bd756b5f 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012_an_py39.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012_an_py39.py @@ -115,7 +115,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_events/test_tutorial001.py b/tests/test_tutorial/test_events/test_tutorial001.py index 52f9beed5d..a5bb299ac0 100644 --- a/tests/test_tutorial/test_events/test_tutorial001.py +++ b/tests/test_tutorial/test_events/test_tutorial001.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_events/test_tutorial002.py b/tests/test_tutorial/test_events/test_tutorial002.py index 882d41aa51..81cbf4ab6d 100644 --- a/tests/test_tutorial/test_events/test_tutorial002.py +++ b/tests/test_tutorial/test_events/test_tutorial002.py @@ -17,7 +17,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_events/test_tutorial003.py b/tests/test_tutorial/test_events/test_tutorial003.py index b2820b63c6..0ad1a1f8b2 100644 --- a/tests/test_tutorial/test_events/test_tutorial003.py +++ b/tests/test_tutorial/test_events/test_tutorial003.py @@ -22,7 +22,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/predict": { diff --git a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py index 6e71bb2deb..a85a313501 100644 --- a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py +++ b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py @@ -15,11 +15,12 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "Custom title", + "summary": "This is a very custom OpenAPI schema", + "description": "Here's a longer description of the custom **OpenAPI** schema", "version": "2.5.0", - "description": "This is a very custom OpenAPI schema", "x-logo": { "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" }, diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py index 07a8349903..39d2005ab7 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py @@ -30,7 +30,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an.py index 76836d447d..3e497a291b 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an.py @@ -30,7 +30,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py310.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py310.py index 158ee01b38..b539cf3d65 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py310.py @@ -39,7 +39,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py39.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py39.py index 5be6452ee5..efd31e63d7 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_an_py39.py @@ -39,7 +39,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py index 5413fe428b..733d9f4060 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001_py310.py @@ -39,7 +39,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003.py b/tests/test_tutorial/test_extra_models/test_tutorial003.py index f08bf4c509..21192b7db7 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003.py @@ -28,7 +28,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py b/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py index 407c717873..c17ddbbe1d 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py @@ -38,7 +38,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial004.py b/tests/test_tutorial/test_extra_models/test_tutorial004.py index 47790ba8f9..71f6a8c700 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial004.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial004.py @@ -18,7 +18,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial004_py39.py b/tests/test_tutorial/test_extra_models/test_tutorial004_py39.py index a98700172a..5475b92e10 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial004_py39.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial004_py39.py @@ -27,7 +27,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial005.py b/tests/test_tutorial/test_extra_models/test_tutorial005.py index 7c094b2538..b0861c37f7 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial005.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial005.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/keyword-weights/": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial005_py39.py b/tests/test_tutorial/test_extra_models/test_tutorial005_py39.py index b403864501..7278e93c36 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial005_py39.py @@ -24,7 +24,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/keyword-weights/": { diff --git a/tests/test_tutorial/test_first_steps/test_tutorial001.py b/tests/test_tutorial/test_first_steps/test_tutorial001.py index ea37aec53a..6cc9fc2282 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial001.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial001.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial003.py b/tests/test_tutorial/test_generate_clients/test_tutorial003.py index 8b22eab9ee..1cd9678a1c 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial003.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial003.py @@ -32,7 +32,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial001.py b/tests/test_tutorial/test_handling_errors/test_tutorial001.py index 99a1053cab..8809c135bd 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial001.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial001.py @@ -22,7 +22,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial002.py b/tests/test_tutorial/test_handling_errors/test_tutorial002.py index 091c74f4de..efd86ebdec 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial002.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial002.py @@ -22,7 +22,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items-header/{item_id}": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial003.py b/tests/test_tutorial/test_handling_errors/test_tutorial003.py index 1639cb1d8b..4763f68f3f 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial003.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial003.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/unicorns/{name}": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial004.py b/tests/test_tutorial/test_handling_errors/test_tutorial004.py index 246f3b94c1..0c0988c643 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial004.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial004.py @@ -32,7 +32,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial005.py b/tests/test_tutorial/test_handling_errors/test_tutorial005.py index af47fd1a4f..f356178ac7 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial005.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial005.py @@ -31,7 +31,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial006.py b/tests/test_tutorial/test_handling_errors/test_tutorial006.py index 4a39bd1022..4dd1adf43e 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial006.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial006.py @@ -35,7 +35,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial001.py b/tests/test_tutorial/test_header_params/test_tutorial001.py index 80f502d6a8..030159dcf0 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001.py @@ -24,7 +24,7 @@ def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial001_an.py b/tests/test_tutorial/test_header_params/test_tutorial001_an.py index f0ad7b8160..3755ab758c 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001_an.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001_an.py @@ -24,7 +24,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial001_an_py310.py b/tests/test_tutorial/test_header_params/test_tutorial001_an_py310.py index d095c71233..207b3b02b0 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001_an_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001_an_py310.py @@ -32,7 +32,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial001_py310.py b/tests/test_tutorial/test_header_params/test_tutorial001_py310.py index bf176bba27..bf51982b7e 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001_py310.py @@ -32,7 +32,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial002.py b/tests/test_tutorial/test_header_params/test_tutorial002.py index 516abda8bf..545fc836bc 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002.py @@ -35,7 +35,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial002_an.py b/tests/test_tutorial/test_header_params/test_tutorial002_an.py index 97493e6040..cfd581e33f 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002_an.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002_an.py @@ -35,7 +35,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial002_an_py310.py b/tests/test_tutorial/test_header_params/test_tutorial002_an_py310.py index e0c60342a7..c8d61e42ec 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002_an_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002_an_py310.py @@ -43,7 +43,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial002_an_py39.py b/tests/test_tutorial/test_header_params/test_tutorial002_an_py39.py index c1bc5faf8a..85150d4a9e 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002_an_py39.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002_an_py39.py @@ -46,7 +46,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial002_py310.py b/tests/test_tutorial/test_header_params/test_tutorial002_py310.py index 81871b8c6d..f189d85b56 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002_py310.py @@ -46,7 +46,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial003.py b/tests/test_tutorial/test_header_params/test_tutorial003.py index 99dd9e25fe..b2fc17b8fa 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003.py @@ -26,7 +26,7 @@ def test_openapi_schema(): assert response.status_code == 200 # insert_assert(response.json()) assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial003_an.py b/tests/test_tutorial/test_header_params/test_tutorial003_an.py index 4477da7a89..87fa839e2d 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003_an.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003_an.py @@ -26,7 +26,7 @@ def test_openapi_schema(): assert response.status_code == 200 # insert_assert(response.json()) assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial003_an_py310.py b/tests/test_tutorial/test_header_params/test_tutorial003_an_py310.py index b52304a2b9..ef6c268c5a 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003_an_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003_an_py310.py @@ -34,7 +34,7 @@ def test_openapi_schema(client: TestClient): assert response.status_code == 200 # insert_assert(response.json()) assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial003_an_py39.py b/tests/test_tutorial/test_header_params/test_tutorial003_an_py39.py index dffdd16228..6525fd50c3 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003_an_py39.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003_an_py39.py @@ -34,7 +34,7 @@ def test_openapi_schema(client: TestClient): assert response.status_code == 200 # insert_assert(response.json()) assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial003_py310.py b/tests/test_tutorial/test_header_params/test_tutorial003_py310.py index 64ef7b22a2..b404ce5d8f 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003_py310.py @@ -34,7 +34,7 @@ def test_openapi_schema(client: TestClient): assert response.status_code == 200 # insert_assert(response.json()) assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_metadata/test_tutorial001.py b/tests/test_tutorial/test_metadata/test_tutorial001.py index f1ddc32595..04e8ff82b0 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial001.py +++ b/tests/test_tutorial/test_metadata/test_tutorial001.py @@ -15,9 +15,10 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "ChimichangApp", + "summary": "Deadpool's favorite app. Nuff said.", "description": "\nChimichangApp API helps you do awesome stuff. 🚀\n\n## Items\n\nYou can **read items**.\n\n## Users\n\nYou will be able to:\n\n* **Create users** (_not implemented_).\n* **Read users** (_not implemented_).\n", "termsOfService": "http://example.com/terms/", "contact": { diff --git a/tests/test_tutorial/test_metadata/test_tutorial001_1.py b/tests/test_tutorial/test_metadata/test_tutorial001_1.py new file mode 100644 index 0000000000..3efb1c4329 --- /dev/null +++ b/tests/test_tutorial/test_metadata/test_tutorial001_1.py @@ -0,0 +1,49 @@ +from fastapi.testclient import TestClient + +from docs_src.metadata.tutorial001_1 import app + +client = TestClient(app) + + +def test_items(): + response = client.get("/items/") + assert response.status_code == 200, response.text + assert response.json() == [{"name": "Katana"}] + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": { + "title": "ChimichangApp", + "summary": "Deadpool's favorite app. Nuff said.", + "description": "\nChimichangApp API helps you do awesome stuff. 🚀\n\n## Items\n\nYou can **read items**.\n\n## Users\n\nYou will be able to:\n\n* **Create users** (_not implemented_).\n* **Read users** (_not implemented_).\n", + "termsOfService": "http://example.com/terms/", + "contact": { + "name": "Deadpoolio the Amazing", + "url": "http://x-force.example.com/contact/", + "email": "dp@x-force.example.com", + }, + "license": { + "name": "Apache 2.0", + "identifier": "MIT", + }, + "version": "0.0.1", + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + } diff --git a/tests/test_tutorial/test_metadata/test_tutorial004.py b/tests/test_tutorial/test_metadata/test_tutorial004.py index f7f47a558e..5072203712 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial004.py +++ b/tests/test_tutorial/test_metadata/test_tutorial004.py @@ -16,7 +16,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py index c6cdc60648..a6e898c498 100644 --- a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py @@ -22,7 +22,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/invoices/": { diff --git a/tests/test_tutorial/test_openapi_webhooks/__init__.py b/tests/test_tutorial/test_openapi_webhooks/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py new file mode 100644 index 0000000000..9111fdb2fe --- /dev/null +++ b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py @@ -0,0 +1,117 @@ +from fastapi.testclient import TestClient + +from docs_src.openapi_webhooks.tutorial001 import app + +client = TestClient(app) + + +def test_get(): + response = client.get("/users/") + assert response.status_code == 200, response.text + assert response.json() == ["Rick", "Morty"] + + +def test_dummy_webhook(): + # Just for coverage + app.webhooks.routes[0].endpoint({}) + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "summary": "Read Users", + "operationId": "read_users_users__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + "webhooks": { + "new-subscription": { + "post": { + "summary": "New Subscription", + "description": "When a new user subscribes to your service we'll send you a POST request with this\ndata to the URL that you register for the event `new-subscription` in the dashboard.", + "operationId": "new_subscriptionnew_subscription_post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Subscription"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": {"$ref": "#/components/schemas/ValidationError"}, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "Subscription": { + "properties": { + "username": {"type": "string", "title": "Username"}, + "montly_fee": {"type": "number", "title": "Montly Fee"}, + "start_date": { + "type": "string", + "format": "date-time", + "title": "Start Date", + }, + }, + "type": "object", + "required": ["username", "montly_fee", "start_date"], + "title": "Subscription", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py index c1cdbee241..95542398e4 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py index fdaddd0187..d1388c3670 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py index 782c64a845..313bb2a04a 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": {}, } diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py index f5fd868eb7..cd9fc520e4 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py index 52379c01e1..07e2d7d202 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py @@ -14,7 +14,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py index deb6b09101..f92c59015e 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py @@ -22,7 +22,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py index 470956a77d..3b88a38c28 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py @@ -56,7 +56,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py index 76e44b5e59..58dec5769d 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py index cf8e203a0e..30278caf86 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py index 497fc90242..cf59d354cd 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py @@ -30,7 +30,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py index 09fac44c4d..a93ea8807e 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py @@ -30,7 +30,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py index e90771f24b..91180d1097 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py @@ -24,7 +24,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_path_params/test_tutorial004.py b/tests/test_tutorial/test_path_params/test_tutorial004.py index ab0455bf5d..acbeaca769 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params/test_tutorial004.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/{file_path}": { diff --git a/tests/test_tutorial/test_path_params/test_tutorial005.py b/tests/test_tutorial/test_path_params/test_tutorial005.py index 3401f22534..b9b58c9615 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params/test_tutorial005.py @@ -51,7 +51,7 @@ def test_openapi(): assert response.status_code == 200, response.text data = response.json() assert data == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/models/{model_name}": { diff --git a/tests/test_tutorial/test_query_params/test_tutorial005.py b/tests/test_tutorial/test_query_params/test_tutorial005.py index 3c408449b8..6c2cba7e12 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params/test_tutorial005.py @@ -35,7 +35,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_query_params/test_tutorial006.py b/tests/test_tutorial/test_query_params/test_tutorial006.py index 7fe58a9900..626637903f 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006.py @@ -60,7 +60,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_query_params/test_tutorial006_py310.py b/tests/test_tutorial/test_query_params/test_tutorial006_py310.py index b90c0a6c8e..b6fb2f39e1 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006_py310.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006_py310.py @@ -67,7 +67,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py index c41f554ba3..370ae0ff05 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py @@ -45,7 +45,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py index dc8028f811..1f76ef3146 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py @@ -45,7 +45,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py index 496b95b797..3a06b4bc7a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py @@ -55,7 +55,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py index 2005e50433..1e6f930937 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py @@ -55,7 +55,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py index 8147d768e0..63524d291d 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py @@ -55,7 +55,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py index d6d69c1691..164ec11930 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py index 3a53d422e0..2afaafd92e 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py index f00df28791..fafd38337c 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py @@ -33,7 +33,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py index 895fb8e9f4..f3fb475283 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py @@ -33,7 +33,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py index 4f4b1fd558..21f348f2b9 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py @@ -33,7 +33,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py index d85bb62312..f2c2a5a33e 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py @@ -33,7 +33,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py index 7bc020540a..1436db384c 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py index be5557f6ad..270763f1d1 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py index d9512e193f..5483916839 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py @@ -33,7 +33,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py index b2a2c8d1d1..e7d7451548 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py @@ -33,7 +33,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py index 4a0b9e8b5f..1ba1fdf618 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py index 71e4638ae4..3432617481 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py index 4e90db358b..537d6325b3 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py @@ -33,7 +33,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py index 7686c07b39..7bce7590c2 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py index e739044a83..2182e87b75 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py index 73f0ba78b8..344004d01b 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py @@ -31,7 +31,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py index e2c1499921..5d4f6df3d0 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py @@ -31,7 +31,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py index 07f30b7395..dad49fb12d 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py @@ -31,7 +31,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index 3269801efc..84c736180f 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -66,7 +66,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py index 4b6edfa066..8ebe4eafdd 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py @@ -43,7 +43,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py index 0c34620e38..5da8b320be 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py @@ -43,7 +43,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py index 04442c76f4..166f59b1a1 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py @@ -55,7 +55,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py index f5249ef5bf..02ea604b2b 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py @@ -55,7 +55,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py index f690d107ba..c753e14d16 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py @@ -55,7 +55,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index 4af659a111..f02170814c 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -31,7 +31,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py index 91dbc60b90..acfb749ce2 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py @@ -31,7 +31,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py index 7c4ad326c4..36e5faac18 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py @@ -39,7 +39,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_an.py index 80c288ed6e..6eb2d55dc8 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_an.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_an.py @@ -66,7 +66,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py index 4dc1f752ce..4e3ef68694 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py @@ -76,7 +76,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index 6868be3284..65a8a9e61a 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -77,7 +77,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial002_an.py b/tests/test_tutorial/test_request_files/test_tutorial002_an.py index ca1f62ea39..52a8e19648 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002_an.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002_an.py @@ -77,7 +77,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial002_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial002_an_py39.py index e593ae75de..6594e0116c 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002_an_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002_an_py39.py @@ -96,7 +96,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial002_py39.py b/tests/test_tutorial/test_request_files/test_tutorial002_py39.py index bacd25b97e..bfe964604e 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002_py39.py @@ -96,7 +96,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial003.py b/tests/test_tutorial/test_request_files/test_tutorial003.py index e2d69184b9..85cd03a590 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003.py @@ -54,7 +54,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial003_an.py b/tests/test_tutorial/test_request_files/test_tutorial003_an.py index f199d4d2fd..0327a2db6c 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003_an.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003_an.py @@ -54,7 +54,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial003_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial003_an_py39.py index 51fa834705..3aa68c6215 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003_an_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003_an_py39.py @@ -82,7 +82,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial003_py39.py b/tests/test_tutorial/test_request_files/test_tutorial003_py39.py index 32b0289096..238bb39cd0 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003_py39.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003_py39.py @@ -82,7 +82,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_forms/test_tutorial001.py b/tests/test_tutorial/test_request_forms/test_tutorial001.py index 721c97fb18..4a2a7abe95 100644 --- a/tests/test_tutorial/test_request_forms/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms/test_tutorial001.py @@ -70,7 +70,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/login/": { diff --git a/tests/test_tutorial/test_request_forms/test_tutorial001_an.py b/tests/test_tutorial/test_request_forms/test_tutorial001_an.py index 6b8abab193..347361344b 100644 --- a/tests/test_tutorial/test_request_forms/test_tutorial001_an.py +++ b/tests/test_tutorial/test_request_forms/test_tutorial001_an.py @@ -70,7 +70,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/login/": { diff --git a/tests/test_tutorial/test_request_forms/test_tutorial001_an_py39.py b/tests/test_tutorial/test_request_forms/test_tutorial001_an_py39.py index 5862524add..e65a8823e7 100644 --- a/tests/test_tutorial/test_request_forms/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_request_forms/test_tutorial001_an_py39.py @@ -81,7 +81,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/login/": { diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py index dcc44cf092..be12656d2c 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py @@ -112,7 +112,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an.py index f11e369844..a5fcb3a94d 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an.py @@ -112,7 +112,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an_py39.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an_py39.py index 9b5e8681c6..6eacb2fcf2 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an_py39.py @@ -131,7 +131,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/files/": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003.py b/tests/test_tutorial/test_response_model/test_tutorial003.py index 4a95cb2b56..9cb0419a33 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003.py @@ -27,7 +27,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/user/": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_01.py b/tests/test_tutorial/test_response_model/test_tutorial003_01.py index a055bc6885..8b8fe514ae 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_01.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_01.py @@ -27,7 +27,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/user/": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_01_py310.py b/tests/test_tutorial/test_response_model/test_tutorial003_01_py310.py index 8cb4ac208e..01dc8e71ca 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_01_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_01_py310.py @@ -36,7 +36,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/user/": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_02.py b/tests/test_tutorial/test_response_model/test_tutorial003_02.py index 6ccb054b83..eabd203456 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_02.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_02.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/portal": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_03.py b/tests/test_tutorial/test_response_model/test_tutorial003_03.py index ba4c0f2750..970ff58450 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_03.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_03.py @@ -15,7 +15,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/teleport": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_05.py b/tests/test_tutorial/test_response_model/test_tutorial003_05.py index d7c232e751..c7a39cc748 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_05.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_05.py @@ -21,7 +21,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/portal": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_05_py310.py b/tests/test_tutorial/test_response_model/test_tutorial003_05_py310.py index a89f1dad8b..f80d62572e 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_05_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_05_py310.py @@ -31,7 +31,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/portal": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_py310.py b/tests/test_tutorial/test_response_model/test_tutorial003_py310.py index 1f4ec9057f..602147b139 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_py310.py @@ -36,7 +36,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/user/": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial004.py b/tests/test_tutorial/test_response_model/test_tutorial004.py index 8cb7dc9cf4..07af292072 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004.py @@ -36,7 +36,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial004_py310.py b/tests/test_tutorial/test_response_model/test_tutorial004_py310.py index 2ba8143ba6..90147fbdd2 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004_py310.py @@ -44,7 +44,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial004_py39.py b/tests/test_tutorial/test_response_model/test_tutorial004_py39.py index 97df0a238f..740a49590e 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004_py39.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004_py39.py @@ -44,7 +44,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial005.py b/tests/test_tutorial/test_response_model/test_tutorial005.py index 76662f7937..e8c8946c54 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial005.py +++ b/tests/test_tutorial/test_response_model/test_tutorial005.py @@ -25,7 +25,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}/name": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial005_py310.py b/tests/test_tutorial/test_response_model/test_tutorial005_py310.py index 1b1cf41755..388e030bd5 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial005_py310.py @@ -35,7 +35,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}/name": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial006.py b/tests/test_tutorial/test_response_model/test_tutorial006.py index 3a759fde41..548a3dbd87 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial006.py +++ b/tests/test_tutorial/test_response_model/test_tutorial006.py @@ -25,7 +25,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}/name": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial006_py310.py b/tests/test_tutorial/test_response_model/test_tutorial006_py310.py index 07e84cc82a..075bb80790 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial006_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial006_py310.py @@ -35,7 +35,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}/name": { diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py index 784517d69e..dea136fb22 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { @@ -41,31 +41,34 @@ def test_openapi_schema(): "requestBody": { "content": { "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "normal": { - "summary": "A normal example", - "description": "A **normal** item works correctly.", - "value": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, + "schema": { + "allOf": [{"$ref": "#/components/schemas/Item"}], + "title": "Item", + "examples": [ + { + "summary": "A normal example", + "description": "A **normal** item works correctly.", + "value": { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, }, - }, - "converted": { - "summary": "An example with converted data", - "description": "FastAPI can convert price `strings` to actual `numbers` automatically", - "value": {"name": "Bar", "price": "35.4"}, - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": { - "name": "Baz", - "price": "thirty five point four", + { + "summary": "An example with converted data", + "description": "FastAPI can convert price `strings` to actual `numbers` automatically", + "value": {"name": "Bar", "price": "35.4"}, }, - }, - }, + { + "summary": "Invalid data is rejected with an error", + "value": { + "name": "Baz", + "price": "thirty five point four", + }, + }, + ], + } } }, "required": True, diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an.py index 222a4edfe8..571feb19f8 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an.py @@ -23,7 +23,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { @@ -41,31 +41,34 @@ def test_openapi_schema(): "requestBody": { "content": { "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "normal": { - "summary": "A normal example", - "description": "A **normal** item works correctly.", - "value": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, + "schema": { + "allOf": [{"$ref": "#/components/schemas/Item"}], + "title": "Item", + "examples": [ + { + "summary": "A normal example", + "description": "A **normal** item works correctly.", + "value": { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, }, - }, - "converted": { - "summary": "An example with converted data", - "description": "FastAPI can convert price `strings` to actual `numbers` automatically", - "value": {"name": "Bar", "price": "35.4"}, - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": { - "name": "Baz", - "price": "thirty five point four", + { + "summary": "An example with converted data", + "description": "FastAPI can convert price `strings` to actual `numbers` automatically", + "value": {"name": "Bar", "price": "35.4"}, }, - }, - }, + { + "summary": "Invalid data is rejected with an error", + "value": { + "name": "Baz", + "price": "thirty five point four", + }, + }, + ], + } } }, "required": True, diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an_py310.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an_py310.py index 1eacd640af..e255317949 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an_py310.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an_py310.py @@ -32,7 +32,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { @@ -50,31 +50,34 @@ def test_openapi_schema(client: TestClient): "requestBody": { "content": { "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "normal": { - "summary": "A normal example", - "description": "A **normal** item works correctly.", - "value": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, + "schema": { + "allOf": [{"$ref": "#/components/schemas/Item"}], + "title": "Item", + "examples": [ + { + "summary": "A normal example", + "description": "A **normal** item works correctly.", + "value": { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, }, - }, - "converted": { - "summary": "An example with converted data", - "description": "FastAPI can convert price `strings` to actual `numbers` automatically", - "value": {"name": "Bar", "price": "35.4"}, - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": { - "name": "Baz", - "price": "thirty five point four", + { + "summary": "An example with converted data", + "description": "FastAPI can convert price `strings` to actual `numbers` automatically", + "value": {"name": "Bar", "price": "35.4"}, }, - }, - }, + { + "summary": "Invalid data is rejected with an error", + "value": { + "name": "Baz", + "price": "thirty five point four", + }, + }, + ], + } } }, "required": True, diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an_py39.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an_py39.py index 632f2cbe0b..dafc5afade 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an_py39.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_an_py39.py @@ -32,7 +32,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { @@ -50,31 +50,34 @@ def test_openapi_schema(client: TestClient): "requestBody": { "content": { "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "normal": { - "summary": "A normal example", - "description": "A **normal** item works correctly.", - "value": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, + "schema": { + "allOf": [{"$ref": "#/components/schemas/Item"}], + "title": "Item", + "examples": [ + { + "summary": "A normal example", + "description": "A **normal** item works correctly.", + "value": { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, }, - }, - "converted": { - "summary": "An example with converted data", - "description": "FastAPI can convert price `strings` to actual `numbers` automatically", - "value": {"name": "Bar", "price": "35.4"}, - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": { - "name": "Baz", - "price": "thirty five point four", + { + "summary": "An example with converted data", + "description": "FastAPI can convert price `strings` to actual `numbers` automatically", + "value": {"name": "Bar", "price": "35.4"}, }, - }, - }, + { + "summary": "Invalid data is rejected with an error", + "value": { + "name": "Baz", + "price": "thirty five point four", + }, + }, + ], + } } }, "required": True, diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_py310.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_py310.py index c99cb75c89..29004218bb 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004_py310.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004_py310.py @@ -32,7 +32,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/{item_id}": { @@ -50,31 +50,34 @@ def test_openapi_schema(client: TestClient): "requestBody": { "content": { "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "normal": { - "summary": "A normal example", - "description": "A **normal** item works correctly.", - "value": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, + "schema": { + "allOf": [{"$ref": "#/components/schemas/Item"}], + "title": "Item", + "examples": [ + { + "summary": "A normal example", + "description": "A **normal** item works correctly.", + "value": { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, }, - }, - "converted": { - "summary": "An example with converted data", - "description": "FastAPI can convert price `strings` to actual `numbers` automatically", - "value": {"name": "Bar", "price": "35.4"}, - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": { - "name": "Baz", - "price": "thirty five point four", + { + "summary": "An example with converted data", + "description": "FastAPI can convert price `strings` to actual `numbers` automatically", + "value": {"name": "Bar", "price": "35.4"}, }, - }, - }, + { + "summary": "Invalid data is rejected with an error", + "value": { + "name": "Baz", + "price": "thirty five point four", + }, + }, + ], + } } }, "required": True, diff --git a/tests/test_tutorial/test_security/test_tutorial001.py b/tests/test_tutorial/test_security/test_tutorial001.py index a7f55b78b2..417bed8f7a 100644 --- a/tests/test_tutorial/test_security/test_tutorial001.py +++ b/tests/test_tutorial/test_security/test_tutorial001.py @@ -29,7 +29,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_security/test_tutorial001_an.py b/tests/test_tutorial/test_security/test_tutorial001_an.py index fc48703aa0..59460da7ff 100644 --- a/tests/test_tutorial/test_security/test_tutorial001_an.py +++ b/tests/test_tutorial/test_security/test_tutorial001_an.py @@ -29,7 +29,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_security/test_tutorial001_an_py39.py b/tests/test_tutorial/test_security/test_tutorial001_an_py39.py index 345e0be0f3..d8e7127736 100644 --- a/tests/test_tutorial/test_security/test_tutorial001_an_py39.py +++ b/tests/test_tutorial/test_security/test_tutorial001_an_py39.py @@ -40,7 +40,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_tutorial/test_security/test_tutorial003.py b/tests/test_tutorial/test_security/test_tutorial003.py index c10f928eb4..cb5cdaa04d 100644 --- a/tests/test_tutorial/test_security/test_tutorial003.py +++ b/tests/test_tutorial/test_security/test_tutorial003.py @@ -70,7 +70,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial003_an.py b/tests/test_tutorial/test_security/test_tutorial003_an.py index 41872fda03..26e68a0299 100644 --- a/tests/test_tutorial/test_security/test_tutorial003_an.py +++ b/tests/test_tutorial/test_security/test_tutorial003_an.py @@ -70,7 +70,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial003_an_py310.py b/tests/test_tutorial/test_security/test_tutorial003_an_py310.py index 02bd748c8c..1250d4afb3 100644 --- a/tests/test_tutorial/test_security/test_tutorial003_an_py310.py +++ b/tests/test_tutorial/test_security/test_tutorial003_an_py310.py @@ -86,7 +86,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial003_an_py39.py b/tests/test_tutorial/test_security/test_tutorial003_an_py39.py index 7e74afafb1..b74cfdc54c 100644 --- a/tests/test_tutorial/test_security/test_tutorial003_an_py39.py +++ b/tests/test_tutorial/test_security/test_tutorial003_an_py39.py @@ -86,7 +86,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial003_py310.py b/tests/test_tutorial/test_security/test_tutorial003_py310.py index a463751f5e..8a75d2321c 100644 --- a/tests/test_tutorial/test_security/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_security/test_tutorial003_py310.py @@ -86,7 +86,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py index ccb5b3c9f8..4e4b6afe80 100644 --- a/tests/test_tutorial/test_security/test_tutorial005.py +++ b/tests/test_tutorial/test_security/test_tutorial005.py @@ -179,7 +179,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial005_an.py b/tests/test_tutorial/test_security/test_tutorial005_an.py index e851f47fec..51cc8329a3 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_an.py +++ b/tests/test_tutorial/test_security/test_tutorial005_an.py @@ -179,7 +179,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial005_an_py310.py b/tests/test_tutorial/test_security/test_tutorial005_an_py310.py index cca5819802..b0d0fed128 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_an_py310.py +++ b/tests/test_tutorial/test_security/test_tutorial005_an_py310.py @@ -207,7 +207,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial005_an_py39.py b/tests/test_tutorial/test_security/test_tutorial005_an_py39.py index eae8514575..26deaaf3c2 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_an_py39.py +++ b/tests/test_tutorial/test_security/test_tutorial005_an_py39.py @@ -207,7 +207,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial005_py310.py b/tests/test_tutorial/test_security/test_tutorial005_py310.py index cdbd8f75ec..e93f34c3bc 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_security/test_tutorial005_py310.py @@ -207,7 +207,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial005_py39.py b/tests/test_tutorial/test_security/test_tutorial005_py39.py index 45b2a2341d..737a8548fd 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_security/test_tutorial005_py39.py @@ -207,7 +207,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/token": { diff --git a/tests/test_tutorial/test_security/test_tutorial006.py b/tests/test_tutorial/test_security/test_tutorial006.py index 73cbdc538d..dc459b6fd0 100644 --- a/tests/test_tutorial/test_security/test_tutorial006.py +++ b/tests/test_tutorial/test_security/test_tutorial006.py @@ -42,7 +42,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_tutorial/test_security/test_tutorial006_an.py b/tests/test_tutorial/test_security/test_tutorial006_an.py index 5f970ed013..52ddd938f9 100644 --- a/tests/test_tutorial/test_security/test_tutorial006_an.py +++ b/tests/test_tutorial/test_security/test_tutorial006_an.py @@ -42,7 +42,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_tutorial/test_security/test_tutorial006_an_py39.py b/tests/test_tutorial/test_security/test_tutorial006_an_py39.py index 7d7a851acf..52b22e5739 100644 --- a/tests/test_tutorial/test_security/test_tutorial006_an_py39.py +++ b/tests/test_tutorial/test_security/test_tutorial006_an_py39.py @@ -54,7 +54,7 @@ def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/me": { diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases.py b/tests/test_tutorial/test_sql_databases/test_sql_databases.py index a2628f3c3b..d927940dab 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases.py @@ -89,7 +89,7 @@ def test_openapi_schema(client): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py index 02501b1a24..08d7b35339 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py @@ -91,7 +91,7 @@ def test_openapi_schema(client): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py index 67b92ea4a4..493fb3b6b9 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py @@ -105,7 +105,7 @@ def test_openapi_schema(client): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py index a2af20ea23..7b56685bc1 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py @@ -105,7 +105,7 @@ def test_openapi_schema(client): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py index 2f918cfd8b..43c2b272fe 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py @@ -104,7 +104,7 @@ def test_openapi_schema(client): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py index f2eefe41d0..fd33517db8 100644 --- a/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py +++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py @@ -104,7 +104,7 @@ def test_openapi_schema(client): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py b/tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py index d2470a2db9..ac6c427ca5 100644 --- a/tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py +++ b/tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py @@ -97,7 +97,7 @@ def test_openapi_schema(client): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/users/": { diff --git a/tests/test_tutorial/test_sub_applications/test_tutorial001.py b/tests/test_tutorial/test_sub_applications/test_tutorial001.py index 00e9aec577..0790d207be 100644 --- a/tests/test_tutorial/test_sub_applications/test_tutorial001.py +++ b/tests/test_tutorial/test_sub_applications/test_tutorial001.py @@ -5,7 +5,7 @@ from docs_src.sub_applications.tutorial001 import app client = TestClient(app) openapi_schema_main = { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/app": { @@ -23,7 +23,7 @@ openapi_schema_main = { }, } openapi_schema_sub = { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/sub": { diff --git a/tests/test_tutorial/test_testing/test_main.py b/tests/test_tutorial/test_testing/test_main.py index 937ce75e42..fe34980813 100644 --- a/tests/test_tutorial/test_testing/test_main.py +++ b/tests/test_tutorial/test_testing/test_main.py @@ -9,7 +9,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_tutorial/test_testing/test_tutorial001.py b/tests/test_tutorial/test_testing/test_tutorial001.py index f3db70af2b..471e896c93 100644 --- a/tests/test_tutorial/test_testing/test_tutorial001.py +++ b/tests/test_tutorial/test_testing/test_tutorial001.py @@ -9,7 +9,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/": { diff --git a/tests/test_union_body.py b/tests/test_union_body.py index bc1e744328..57a14b5748 100644 --- a/tests/test_union_body.py +++ b/tests/test_union_body.py @@ -39,7 +39,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_union_inherited_body.py b/tests/test_union_inherited_body.py index 988b920aa7..c2a37d3ddd 100644 --- a/tests/test_union_inherited_body.py +++ b/tests/test_union_inherited_body.py @@ -39,7 +39,7 @@ def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { "/items/": { diff --git a/tests/test_webhooks_security.py b/tests/test_webhooks_security.py new file mode 100644 index 0000000000..a1c7b18fb8 --- /dev/null +++ b/tests/test_webhooks_security.py @@ -0,0 +1,126 @@ +from datetime import datetime + +from fastapi import FastAPI, Security +from fastapi.security import HTTPBearer +from fastapi.testclient import TestClient +from pydantic import BaseModel +from typing_extensions import Annotated + +app = FastAPI() + +bearer_scheme = HTTPBearer() + + +class Subscription(BaseModel): + username: str + montly_fee: float + start_date: datetime + + +@app.webhooks.post("new-subscription") +def new_subscription( + body: Subscription, token: Annotated[str, Security(bearer_scheme)] +): + """ + When a new user subscribes to your service we'll send you a POST request with this + data to the URL that you register for the event `new-subscription` in the dashboard. + """ + + +client = TestClient(app) + + +def test_dummy_webhook(): + # Just for coverage + new_subscription(body={}, token="Bearer 123") + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + # insert_assert(response.json()) + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": {}, + "webhooks": { + "new-subscription": { + "post": { + "summary": "New Subscription", + "description": "When a new user subscribes to your service we'll send you a POST request with this\ndata to the URL that you register for the event `new-subscription` in the dashboard.", + "operationId": "new_subscriptionnew_subscription_post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Subscription"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "security": [{"HTTPBearer": []}], + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": {"$ref": "#/components/schemas/ValidationError"}, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "Subscription": { + "properties": { + "username": {"type": "string", "title": "Username"}, + "montly_fee": {"type": "number", "title": "Montly Fee"}, + "start_date": { + "type": "string", + "format": "date-time", + "title": "Start Date", + }, + }, + "type": "object", + "required": ["username", "montly_fee", "start_date"], + "title": "Subscription", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + }, + "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}}, + }, + } -- 2.47.3