Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-fastapi for openSUSE:Factory checked in at 2026-05-12 19:26:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-fastapi (Old) and /work/SRC/openSUSE:Factory/.python-fastapi.new.1966 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-fastapi" Tue May 12 19:26:09 2026 rev:51 rq:1352303 version:0.136.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-fastapi/python-fastapi.changes 2026-04-18 21:31:43.002191173 +0200 +++ /work/SRC/openSUSE:Factory/.python-fastapi.new.1966/python-fastapi.changes 2026-05-12 19:26:19.338226788 +0200 @@ -1,0 +2,6 @@ +Sun May 3 17:46:52 UTC 2026 - Dirk Müller <[email protected]> + +- update to 0.136.1: + * Update Pydantic v2 code to address deprecations. PR #15101 + +------------------------------------------------------------------- Old: ---- fastapi-0.136.0.tar.gz New: ---- fastapi-0.136.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-fastapi.spec ++++++ --- /var/tmp/diff_new_pack.1usV0m/_old 2026-05-12 19:26:19.926251158 +0200 +++ /var/tmp/diff_new_pack.1usV0m/_new 2026-05-12 19:26:19.930251324 +0200 @@ -31,7 +31,7 @@ %endif %{?sle15_python_module_pythons} Name: python-fastapi%{psuffix} -Version: 0.136.0 +Version: 0.136.1 Release: 0 Summary: FastAPI framework License: MIT ++++++ fastapi-0.136.0.tar.gz -> fastapi-0.136.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/PKG-INFO new/fastapi-0.136.1/PKG-INFO --- old/fastapi-0.136.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/fastapi-0.136.1/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: fastapi -Version: 0.136.0 +Version: 0.136.1 Summary: FastAPI framework, high performance, easy to learn, fast to code, ready for production Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= <[email protected]> License-Expression: MIT @@ -130,7 +130,6 @@ <a href="https://blockbee.io?ref=fastapi" target="_blank" title="BlockBee Cryptocurrency Payment Gateway"><img src="https://fastapi.tiangolo.com/img/sponsors/blockbee.png"></a> <a href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"><img src="https://fastapi.tiangolo.com/img/sponsors/scalar.svg"></a> <a href="https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=mainbadge" target="_blank" title="Auth, user management and more for your B2B product"><img src="https://fastapi.tiangolo.com/img/sponsors/propelauth.png"></a> -<a href="https://zuplo.link/fastapi-gh" target="_blank" title="Zuplo: Deploy, Secure, Document, and Monetize your FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/zuplo.png"></a> <a href="https://liblab.com?utm_source=fastapi" target="_blank" title="liblab - Generate SDKs from FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/liblab.png"></a> <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" target="_blank" title="Deploy & scale any full-stack web app on Render. Focus on building apps, not infra."><img src="https://fastapi.tiangolo.com/img/sponsors/render.svg"></a> <a href="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi" target="_blank" title="Cut Code Review Time & Bugs in Half with CodeRabbit"><img src="https://fastapi.tiangolo.com/img/sponsors/coderabbit.png"></a> @@ -139,7 +138,6 @@ <a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a> <a href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page" target="_blank" title="Greptile: The AI Code Reviewer"><img src="https://fastapi.tiangolo.com/img/sponsors/greptile.png"></a> <a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a> -<a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a> <a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a> <a href="https://www.stainlessapi.com/?utm_source=fastapi&utm_medium=referral" target="_blank" title="Stainless | Generate best-in-class SDKs"><img src="https://fastapi.tiangolo.com/img/sponsors/stainless.png"></a> <a href="https://www.permit.io/blog/implement-authorization-in-fastapi?utm_source=github&utm_medium=referral&utm_campaign=fastapi" target="_blank" title="Fine-Grained Authorization for FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/permit.png"></a> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/README.md new/fastapi-0.136.1/README.md --- old/fastapi-0.136.0/README.md 2026-04-16 13:47:04.724899500 +0200 +++ new/fastapi-0.136.1/README.md 2026-04-23 18:49:37.446899000 +0200 @@ -54,7 +54,6 @@ <a href="https://blockbee.io?ref=fastapi" target="_blank" title="BlockBee Cryptocurrency Payment Gateway"><img src="https://fastapi.tiangolo.com/img/sponsors/blockbee.png"></a> <a href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"><img src="https://fastapi.tiangolo.com/img/sponsors/scalar.svg"></a> <a href="https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=mainbadge" target="_blank" title="Auth, user management and more for your B2B product"><img src="https://fastapi.tiangolo.com/img/sponsors/propelauth.png"></a> -<a href="https://zuplo.link/fastapi-gh" target="_blank" title="Zuplo: Deploy, Secure, Document, and Monetize your FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/zuplo.png"></a> <a href="https://liblab.com?utm_source=fastapi" target="_blank" title="liblab - Generate SDKs from FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/liblab.png"></a> <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" target="_blank" title="Deploy & scale any full-stack web app on Render. Focus on building apps, not infra."><img src="https://fastapi.tiangolo.com/img/sponsors/render.svg"></a> <a href="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi" target="_blank" title="Cut Code Review Time & Bugs in Half with CodeRabbit"><img src="https://fastapi.tiangolo.com/img/sponsors/coderabbit.png"></a> @@ -63,7 +62,6 @@ <a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a> <a href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page" target="_blank" title="Greptile: The AI Code Reviewer"><img src="https://fastapi.tiangolo.com/img/sponsors/greptile.png"></a> <a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a> -<a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a> <a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a> <a href="https://www.stainlessapi.com/?utm_source=fastapi&utm_medium=referral" target="_blank" title="Stainless | Generate best-in-class SDKs"><img src="https://fastapi.tiangolo.com/img/sponsors/stainless.png"></a> <a href="https://www.permit.io/blog/implement-authorization-in-fastapi?utm_source=github&utm_medium=referral&utm_campaign=fastapi" target="_blank" title="Fine-Grained Authorization for FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/permit.png"></a> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/fastapi/__init__.py new/fastapi-0.136.1/fastapi/__init__.py --- old/fastapi-0.136.0/fastapi/__init__.py 2026-04-16 13:47:04.910413500 +0200 +++ new/fastapi-0.136.1/fastapi/__init__.py 2026-04-23 18:49:37.630811500 +0200 @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.136.0" +__version__ = "0.136.1" from starlette import status as status diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/fastapi/_compat/__init__.py new/fastapi-0.136.1/fastapi/_compat/__init__.py --- old/fastapi-0.136.0/fastapi/_compat/__init__.py 2026-04-16 13:47:04.910413500 +0200 +++ new/fastapi-0.136.1/fastapi/_compat/__init__.py 2026-04-23 18:49:37.630899200 +0200 @@ -26,7 +26,7 @@ from .v2 import Url as Url from .v2 import copy_field_info as copy_field_info from .v2 import create_body_model as create_body_model -from .v2 import evaluate_forwardref as evaluate_forwardref # ty: ignore[deprecated] +from .v2 import evaluate_forwardref as evaluate_forwardref from .v2 import get_cached_model_fields as get_cached_model_fields from .v2 import get_definitions as get_definitions from .v2 import get_flat_models_from_fields as get_flat_models_from_fields diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/fastapi/_compat/v2.py new/fastapi-0.136.1/fastapi/_compat/v2.py --- old/fastapi-0.136.0/fastapi/_compat/v2.py 2026-04-16 13:47:04.910618000 +0200 +++ new/fastapi-0.136.1/fastapi/_compat/v2.py 2026-04-23 18:49:37.631034600 +0200 @@ -22,10 +22,10 @@ from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation from pydantic import ValidationError as ValidationError +from pydantic._internal import _typing_extra as _pydantic_typing_extra from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined] # ty: ignore[unused-ignore-comment] GetJsonSchemaHandler as GetJsonSchemaHandler, ) -from pydantic._internal._typing_extra import eval_type_lenient # ty: ignore[deprecated] from pydantic.fields import FieldInfo as FieldInfo from pydantic.json_schema import GenerateJsonSchema as _GenerateJsonSchema from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue @@ -38,7 +38,20 @@ RequiredParam = PydanticUndefined Undefined = PydanticUndefined -evaluate_forwardref = eval_type_lenient # ty: ignore[deprecated] + + +def evaluate_forwardref( + value: Any, + globalns: dict[str, Any] | None = None, + localns: dict[str, Any] | None = None, +) -> Any: + # eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) + try_eval_type = getattr(_pydantic_typing_extra, "try_eval_type", None) + if try_eval_type is not None: + return try_eval_type(value, globalns, localns)[0] + return _pydantic_typing_extra.eval_type_lenient( # ty: ignore[deprecated] + value, globalns, localns + ) class GenerateJsonSchema(_GenerateJsonSchema): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/fastapi/dependencies/utils.py new/fastapi-0.136.1/fastapi/dependencies/utils.py --- old/fastapi-0.136.0/fastapi/dependencies/utils.py 2026-04-16 13:47:04.911332800 +0200 +++ new/fastapi-0.136.1/fastapi/dependencies/utils.py 2026-04-23 18:49:37.631709000 +0200 @@ -33,7 +33,7 @@ Undefined, copy_field_info, create_body_model, - evaluate_forwardref, # ty: ignore[deprecated] + evaluate_forwardref, field_annotation_is_scalar, field_annotation_is_scalar_sequence, field_annotation_is_sequence, @@ -245,7 +245,7 @@ def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any: if isinstance(annotation, str): annotation = ForwardRef(annotation) - annotation = evaluate_forwardref(annotation, globalns, globalns) # ty: ignore[deprecated] + annotation = evaluate_forwardref(annotation, globalns, globalns) if annotation is type(None): return None return annotation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/fastapi/encoders.py new/fastapi-0.136.1/fastapi/encoders.py --- old/fastapi-0.136.0/fastapi/encoders.py 2026-04-16 13:47:04.911332800 +0200 +++ new/fastapi-0.136.1/fastapi/encoders.py 2026-04-23 18:49:37.631709000 +0200 @@ -22,7 +22,6 @@ from fastapi.exceptions import PydanticV1NotSupportedError from fastapi.types import IncEx from pydantic import BaseModel -from pydantic.color import Color # ty: ignore[deprecated] from pydantic.networks import AnyUrl, NameEmail from pydantic.types import SecretBytes, SecretStr from pydantic_core import PydanticUndefinedType @@ -32,6 +31,23 @@ is_pydantic_v1_model_instance, ) +try: + # pydantic.color.Color is deprecated since v2.0b3, but supporting for bwd-compat + from pydantic.color import Color # ty: ignore[deprecated] +except ImportError: # pragma: no cover + + class Color: # type: ignore[no-redef] # ty: ignore[unused-ignore-comment] + pass + + +try: + # Supporting the new Color format for newer versions of Pydantic + from pydantic_extra_types.color import Color as PyExtraColor +except ImportError: # pragma: no cover + + class PyExtraColor: # type: ignore[no-redef] # ty: ignore[unused-ignore-comment] + pass + # Taken from Pydantic v1 as is def isoformat(o: datetime.date | datetime.time) -> str: @@ -67,7 +83,8 @@ ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = { bytes: lambda o: o.decode(), - Color: str, # ty: ignore[deprecated] + Color: str, + PyExtraColor: str, datetime.date: isoformat, datetime.datetime: isoformat, datetime.time: isoformat, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/pyproject.toml new/fastapi-0.136.1/pyproject.toml --- old/fastapi-0.136.0/pyproject.toml 2026-04-16 13:47:09.735903700 +0200 +++ new/fastapi-0.136.1/pyproject.toml 2026-04-23 18:49:40.875938200 +0200 @@ -52,7 +52,7 @@ "typing-inspection>=0.4.2", "annotated-doc>=0.0.2", ] -version = "0.136.0" +version = "0.136.1" [project.urls] Homepage = "https://github.com/fastapi/fastapi" @@ -106,6 +106,7 @@ { include-group = "translations" }, "playwright >=1.57.0", "prek >=0.2.22", + "zizmor >=1.23.1", ] docs = [ { include-group = "docs-tests" }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/scripts/general-llm-prompt.md new/fastapi-0.136.1/scripts/general-llm-prompt.md --- old/fastapi-0.136.0/scripts/general-llm-prompt.md 2026-04-16 13:47:04.913828100 +0200 +++ new/fastapi-0.136.1/scripts/general-llm-prompt.md 2026-04-23 18:49:37.634175500 +0200 @@ -6,6 +6,8 @@ The original content will be surrounded by triple percentage signs (%%%). Do not include the triple percentage signs in the translation. +[placeholder_for_additional_instructions] + ### Technical terms in English For technical terms in English that don't have a common translation term, use the original term in English. @@ -223,6 +225,8 @@ Use the following rules for links (apply both to Markdown-style links ([text](url)) and to HTML-style <a href="url">text</a> tags): +- The order of links should match the order of links in the English source. Do not change the order of links. Rephrase the sentence if necessary. + - For relative URLs, only translate the link text. Do not translate the URL or its parts. Example: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/scripts/translate.py new/fastapi-0.136.1/scripts/translate.py --- old/fastapi-0.136.0/scripts/translate.py 2026-04-16 13:47:04.917009600 +0200 +++ new/fastapi-0.136.1/scripts/translate.py 2026-04-23 18:49:37.637294300 +0200 @@ -57,39 +57,19 @@ return out_path [email protected]() -def translate_page( - *, - language: Annotated[str, typer.Option(envvar="LANGUAGE")], - en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], -) -> None: - assert language != "en", ( - "`en` is the source language, choose another language as translation target" +def get_prompt( + lang_prompt_content: str, + old_translation: str | None, + language: str, + language_name: str, + original_content: str, + additional_instructions: str, +) -> str: + general_prompt_with_additional_instructions = general_prompt.replace( + "[placeholder_for_additional_instructions]", additional_instructions ) - langs = get_langs() - language_name = langs[language] - lang_path = Path(f"docs/{language}") - lang_path.mkdir(exist_ok=True) - lang_prompt_path = lang_path / "llm-prompt.md" - assert lang_prompt_path.exists(), f"Prompt file not found: {lang_prompt_path}" - lang_prompt_content = lang_prompt_path.read_text(encoding="utf-8") - - en_docs_path = Path("docs/en/docs") - assert str(en_path).startswith(str(en_docs_path)), ( - f"Path must be inside {en_docs_path}" - ) - out_path = generate_lang_path(lang=language, path=en_path) - out_path.parent.mkdir(parents=True, exist_ok=True) - original_content = en_path.read_text(encoding="utf-8") - old_translation: str | None = None - if out_path.exists(): - print(f"Found existing translation: {out_path}") - old_translation = out_path.read_text(encoding="utf-8") - print(f"Translating {en_path} to {language} ({language_name})") - agent = Agent("openai:gpt-5") - prompt_segments = [ - general_prompt, + general_prompt_with_additional_instructions, lang_prompt_content, ] if old_translation: @@ -119,12 +99,57 @@ f"%%%\n{original_content}%%%", ] ) - prompt = "\n\n".join(prompt_segments) + return "\n\n".join(prompt_segments) + + [email protected]() +def translate_page( + *, + language: Annotated[str, typer.Option(envvar="LANGUAGE")], + en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], +) -> None: + assert language != "en", ( + "`en` is the source language, choose another language as translation target" + ) + langs = get_langs() + language_name = langs[language] + lang_path = Path(f"docs/{language}") + lang_path.mkdir(exist_ok=True) + lang_prompt_path = lang_path / "llm-prompt.md" + assert lang_prompt_path.exists(), f"Prompt file not found: {lang_prompt_path}" + lang_prompt_content = lang_prompt_path.read_text(encoding="utf-8") + + en_docs_path = Path("docs/en/docs") + assert str(en_path).startswith(str(en_docs_path)), ( + f"Path must be inside {en_docs_path}" + ) + out_path = generate_lang_path(lang=language, path=en_path) + out_path.parent.mkdir(parents=True, exist_ok=True) + original_content = en_path.read_text(encoding="utf-8") + old_translation: str | None = None + if out_path.exists(): + print(f"Found existing translation: {out_path}") + old_translation = out_path.read_text(encoding="utf-8") + print(f"Translating {en_path} to {language} ({language_name})") + agent = Agent("openai:gpt-5") MAX_ATTEMPTS = 3 + additional_instructions = "" for attempt_no in range(1, MAX_ATTEMPTS + 1): print(f"Running agent for {out_path} (attempt {attempt_no}/{MAX_ATTEMPTS})") - result = agent.run_sync(prompt) + prompt = get_prompt( + lang_prompt_content=lang_prompt_content, + old_translation=old_translation, + language=language, + language_name=language_name, + original_content=original_content, + additional_instructions=additional_instructions, + ) + result = agent.run_sync( + prompt.replace( + "[placeholder_for_additional_instructions]", additional_instructions + ) + ) out_content = f"{result.output.strip()}\n" try: check_translation( @@ -139,6 +164,11 @@ print( f"Translation check failed on attempt {attempt_no}/{MAX_ATTEMPTS}: {e}" ) + additional_instructions = ( + f"Current translation fails validation checks ({str(e)}). " + "Please, pay special attention to it." + ) + old_translation = out_content continue # Retry if not reached max attempts else: # Max retry attempts reached print(f"Translation failed for {out_path} after {MAX_ATTEMPTS} attempts") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fastapi-0.136.0/tests/test_jsonable_encoder.py new/fastapi-0.136.1/tests/test_jsonable_encoder.py --- old/fastapi-0.136.0/tests/test_jsonable_encoder.py 2026-04-16 13:47:04.920899200 +0200 +++ new/fastapi-0.136.1/tests/test_jsonable_encoder.py 2026-04-23 18:49:37.641899000 +0200 @@ -311,3 +311,21 @@ def test_encode_pydantic_undefined(): data = {"value": Undefined} assert jsonable_encoder(data) == {"value": None} + + [email protected]("ignore::DeprecationWarning") [email protected]( + "module_path", + [ + pytest.param("pydantic.color"), + pytest.param("pydantic_extra_types.color"), + ], +) +def test_encode_color(module_path): + try: + Color = __import__(module_path, fromlist=["Color"]).Color + except ImportError: # pragma: no cover + pytest.skip(f"{module_path} not available") + + data = {"color": Color("blue")} + assert jsonable_encoder(data) == {"color": "blue"}
