Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Comments

🐛 Fix inconsistent processing of model docstring formfeed char with Pydantic V1#6039

Merged
tiangolo merged 7 commits intofastapi:masterfrom
MaxwellPayne:bugfix/model-description-formfeed-inconsistency
Sep 20, 2025
Merged

🐛 Fix inconsistent processing of model docstring formfeed char with Pydantic V1#6039
tiangolo merged 7 commits intofastapi:masterfrom
MaxwellPayne:bugfix/model-description-formfeed-inconsistency

Conversation

@MaxwellPayne
Copy link
Contributor

Problem

Generating openapi specs for models with a formfeed (\f) in the docstring yields inconsistent results. For example, in the case of:

classAddress(BaseModel):"""    This is a public description of an Address\f    You can't see this part of the docstring, it's private!    """    ...

Sometimes the openapidescription ofAddress correctly renders asThis is a public description of an Address\n. But other times, you get the entire docstring even though the\f should be keeping the remainder of the docstring private.

The bug seemed to be in the following function:

defget_model_definitions(*,flat_models:Set[Union[Type[BaseModel],Type[Enum]]],model_name_map:Dict[Union[Type[BaseModel],Type[Enum]],str],)->Dict[str,Any]:definitions:Dict[str,Dict[str,Any]]= {}formodelinflat_models:m_schema,m_definitions,m_nested_models=model_process_schema(model,model_name_map=model_name_map,ref_prefix=REF_PREFIX        )definitions.update(m_definitions)model_name=model_name_map[model]if"description"inm_schema:m_schema["description"]=m_schema["description"].split("\f")[0]definitions[model_name]=m_schemareturndefinitions

The issue is that thedefinitions dict has its entries updated in two different places:

  1. definitions.update(m_definitions)
  2. definitions[model_name] = m_schema

When a model definition is written in line (2), the proper formfeed escape of the docstring is persisted. But if the same model is subsequently written by line (1), the previous docstring fix is clobbered over and we see the entire docstring.

This is a non-deterministic error, sinceflat_models is an unordered set. Depending on order of models in iteration, you could end up with either (1) or (2) as the final edit to a given model.

Solution

This fix works around the bug by handling the formfeed escape at theend of model processing. By that point ourdefinitions dict will be final, so any edits to the models are guaranteed to make it into the return value.

Related issues

Questions & Alternatives

andrew222651 reacted with thumbs up emoji
@github-actions

This comment was marked as outdated.

@MaxwellPayneMaxwellPayneforce-pushed thebugfix/model-description-formfeed-inconsistency branch from8a90482 to5d3b953CompareFebruary 23, 2023 19:08
@github-actions

This comment was marked as outdated.

@MaxwellPayneMaxwellPayneforce-pushed thebugfix/model-description-formfeed-inconsistency branch from0eef5f7 toa4ea039CompareFebruary 23, 2023 19:18
@github-actions
Copy link
Contributor

📝 Docs preview for commit3a15194 at:https://63f7bcb8cac94d008f451d7c--fastapi.netlify.app

@tiangolotiangolo added the featureNew feature or request labelOct 2, 2023
Copy link
Member

@YuriiMotovYuriiMotov left a comment

Choose a reason for hiding this comment

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

Preconditions:

  • Pydantic V1
  • Nested model has description with formfeed character

Symptoms:
Generated openapi schema will be inconsistent (sometimes the part after\f will be truncated, sometimes not).
test_openapi_schema (fromtest_get_model_definitions_formfeed_escape.py) will fail sometimes.
test_model_description_escaped_with_formfeed will always fail forsort_reversed=False.

Tests intest_get_model_definitions_formfeed_escape.py prove that the result of_compat.get_model_definitions depends on the order of models passed inflat_models parameter.

Explanation:

  • Address is nested intoFacility.
  • WhenAddress model goes beforeFacility inflat_models (input parameter of_compat.get_model_definitions), it's added todefinitions and itsdescription is updated (truncated by formfeed charecter).
  • But on the second iteration of for-loop, we haveAddress inm_definitions (sinceAddress is nested intoFacility), anddefinitions.update(m_definitions) overrides existing schema ofAddress indefinitions.
  • So,definitions now contain theAddress schema with originaldescription (not truncated).

The idea of the fix is to add all models todefinitions first and only then updatedescription's of all models.

Looks good to me.

svlandeg reacted with thumbs up emoji
@YuriiMotovYuriiMotov changed the titleFix inconsistent processing of model docstring formfeed char🐛 Fix inconsistent processing of model docstring formfeed char with Pydantic V1Jul 18, 2025
@YuriiMotovYuriiMotov added bugSomething isn't working and removed featureNew feature or request labelsJul 18, 2025
Copy link
Member

@tiangolotiangolo left a comment

Choose a reason for hiding this comment

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

Nice, sounds good, thank you! 🚀

Comment on lines +141 to +156
class SortedTypeSet(set):
"""
Set of Types whose `__iter__()` method yields results sorted by the type names
"""

def __init__(self, seq: Set[Type[Any]], *, sort_reversed: bool):
super().__init__(seq)
self.sort_reversed = sort_reversed

def __iter__(self) -> Iterator[Type[Any]]:
members_sorted = sorted(
super().__iter__(),
key=lambda type_: type_.__name__,
reverse=self.sort_reversed,
)
yield from members_sorted
Copy link
Member

Choose a reason for hiding this comment

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

Very fancy! ✨ ✔️

@tiangolotiangolo merged commit86e5157 intofastapi:masterSep 20, 2025
29 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@tiangolotiangolotiangolo approved these changes

@YuriiMotovYuriiMotovYuriiMotov approved these changes

Assignees

No one assigned

Labels

bugSomething isn't working

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

3 participants

@MaxwellPayne@tiangolo@YuriiMotov

[8]ページ先頭

©2009-2026 Movatter.jp