From 4efce4ff16d6b1437234195339cde2c7ef1c0a22 Mon Sep 17 00:00:00 2001 From: Kevin Paulson Date: Mon, 27 Apr 2026 17:15:59 -0400 Subject: [PATCH 1/9] First try --- src/datamodel_code_generator/model/base.py | 53 +++++++++++++++++++ .../model/template/Enum.jinja2 | 8 +-- .../template/ScalarTypeAliasAnnotation.jinja2 | 4 +- .../model/template/ScalarTypeAliasType.jinja2 | 4 +- .../model/template/ScalarTypeStatement.jinja2 | 4 +- .../model/template/TypeAliasAnnotation.jinja2 | 12 ++--- .../model/template/TypeAliasType.jinja2 | 12 ++--- .../model/template/TypeStatement.jinja2 | 12 ++--- .../model/template/TypedDictClass.jinja2 | 8 +-- .../model/template/TypedDictFunction.jinja2 | 8 +-- .../model/template/dataclass.jinja2 | 8 +-- .../model/template/msgspec.jinja2 | 8 +-- .../template/pydantic_v2/BaseModel.jinja2 | 8 +-- .../template/pydantic_v2/RootModel.jinja2 | 8 +-- .../pydantic_v2/RootModelTypeAlias.jinja2 | 8 +-- .../template/pydantic_v2/dataclass.jinja2 | 8 +-- 16 files changed, 83 insertions(+), 90 deletions(-) diff --git a/src/datamodel_code_generator/model/base.py b/src/datamodel_code_generator/model/base.py index 7110f58bc..861a86820 100644 --- a/src/datamodel_code_generator/model/base.py +++ b/src/datamodel_code_generator/model/base.py @@ -66,6 +66,57 @@ def escape_docstring(value: str | None) -> str | None: return value.replace("\\", "\\\\").replace('"""', '\\"\\"\\"') +def format_pep257_docstring( + value: str | None, + quote_indent: int = 4, + continuation_indent: int | None = None, +) -> str: + """Format *value* as a triple-quoted Python string for generated code. + + Single-line text (no newline after escaping) uses a one-line docstring per + PEP 257. Multi-line text uses opening and closing quote lines with a body + in between. + + Args: + value: Raw description or docstring text. + quote_indent: Spaces before each opening or closing quote line and, in + uniform mode, before each body line. + continuation_indent: If set, multi-line bodies use a hanging layout: + the first body line is indented only by *quote_indent*; later lines + use *quote_indent* + *continuation_indent* extra spaces (matching + Jinja's ``indent(continuation_indent)`` with no leading prefix on + the first line). If ``None``, every body line uses the same indent + as the quote lines. + + Returns: + Empty string when *value* is falsy; otherwise the full docstring block + including a trailing newline. + """ + if not value: + return "" + escaped = escape_docstring(value) + if escaped is None: + return "" + qi = max(quote_indent, 0) + prefix = " " * qi + tail = "\n" + + if "\n" not in escaped: + return f'{prefix}"""{escaped}"""{tail}' + + lines = escaped.split("\n") + + if continuation_indent is None: + body = "\n".join(f"{prefix}{line}" for line in lines) + else: + ci = max(continuation_indent, 0) + cont = " " * (qi + ci) + first_body = f"{prefix}{lines[0]}" + body = first_body if len(lines) == 1 else first_body + "\n" + "\n".join(f"{cont}{line}" for line in lines[1:]) + + return f'{prefix}"""\n{body}\n{prefix}"""{tail}' + + ALL_MODEL: str = "#all#" GENERIC_BASE_CLASS_PATH: str = "#/__datamodel_code_generator__/generic_base_class__" GENERIC_BASE_CLASS_NAME: str = "__generic_base_class__" @@ -453,6 +504,7 @@ def _get_environment(template_subdir: Path, custom_template_dir: Path | None) -> autoescape=select_autoescape(["html", "xml"]), ) env.filters["escape_docstring"] = escape_docstring + env.filters["format_pep257_docstring"] = format_pep257_docstring return env @@ -486,6 +538,7 @@ def _get_environment_with_absolute_path(absolute_template_dir: Path, builtin_sub autoescape=select_autoescape(["html", "xml"]), ) env.filters["escape_docstring"] = escape_docstring + env.filters["format_pep257_docstring"] = format_pep257_docstring return env diff --git a/src/datamodel_code_generator/model/template/Enum.jinja2 b/src/datamodel_code_generator/model/template/Enum.jinja2 index 09a8e2207..d89bf2824 100644 --- a/src/datamodel_code_generator/model/template/Enum.jinja2 +++ b/src/datamodel_code_generator/model/template/Enum.jinja2 @@ -3,16 +3,12 @@ {% endfor -%} class {{ class_name }}({{ base_class }}): {%- if description %} - """ - {{ description | escape_docstring | indent(4) }} - """ +{{ description | format_pep257_docstring(4) }} {%- endif %} {%- for field in fields %} {{ field.name }} = {{ field.default }} {%- if field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ +{{ field.docstring | format_pep257_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 index a214eb596..d3e0b8443 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 @@ -1,6 +1,4 @@ {{ class_name }}: TypeAlias = {{ py_type }} {%- if description %} -""" -{{ description }} -""" +{{ description | format_pep257_docstring(0) }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 index ce30cf157..7d3fed59c 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 @@ -1,6 +1,4 @@ {{ class_name }} = TypeAliasType("{{ class_name }}", {{ py_type }}) {%- if description %} -""" -{{ description }} -""" +{{ description | format_pep257_docstring(0) }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 index 3299ab6d8..f70891d49 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 @@ -1,6 +1,4 @@ type {{ class_name }} = {{ py_type }} {%- if description %} -""" -{{ description }} -""" +{{ description | format_pep257_docstring(0) }} {%- endif %} \ No newline at end of file diff --git a/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 b/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 index 85265d402..ae16826a9 100644 --- a/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 @@ -11,19 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} {{ class_name }}: TypeAlias = {{ get_type_annotation(fields[0]) }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -""" -{{ description | escape_docstring | indent(0) }} -""" +{{ description | format_pep257_docstring(0) }} {%- elif fields[0].docstring %} -""" -{{ fields[0].docstring | escape_docstring | indent(0) }} -""" +{{ fields[0].docstring | format_pep257_docstring(0) }} {%- endif %} {%- else %} {{ class_name }}: TypeAlias = {{ base_class }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -""" -{{ description | escape_docstring | indent(0) }} -""" +{{ description | format_pep257_docstring(0) }} {%- endif %} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 b/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 index bd19b2a3f..b640afa6d 100644 --- a/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 @@ -11,19 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} {{ class_name }} = TypeAliasType("{{ class_name }}", {{ get_type_annotation(fields[0]) }}){% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -""" -{{ description | escape_docstring | indent(0) }} -""" +{{ description | format_pep257_docstring(0) }} {%- elif fields[0].docstring %} -""" -{{ fields[0].docstring | escape_docstring | indent(0) }} -""" +{{ fields[0].docstring | format_pep257_docstring(0) }} {%- endif %} {%- else %} {{ class_name }} = TypeAliasType("{{ class_name }}", {{ base_class }}){% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -""" -{{ description | escape_docstring | indent(0) }} -""" +{{ description | format_pep257_docstring(0) }} {%- endif %} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypeStatement.jinja2 b/src/datamodel_code_generator/model/template/TypeStatement.jinja2 index ce03c241b..ed8b6085c 100644 --- a/src/datamodel_code_generator/model/template/TypeStatement.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeStatement.jinja2 @@ -11,19 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} type {{ class_name }} = {{ get_type_annotation(fields[0]) }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -""" -{{ description | escape_docstring | indent(0) }} -""" +{{ description | format_pep257_docstring(0) }} {%- elif fields[0].docstring %} -""" -{{ fields[0].docstring | escape_docstring | indent(0) }} -""" +{{ fields[0].docstring | format_pep257_docstring(0) }} {%- endif %} {%- else %} type {{ class_name }} = {{ base_class }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -""" -{{ description | escape_docstring | indent(0) }} -""" +{{ description | format_pep257_docstring(0) }} {%- endif %} {%- endif %} \ No newline at end of file diff --git a/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 b/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 index 7087b924c..3dd4c84b4 100644 --- a/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 +++ b/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 @@ -1,8 +1,6 @@ class {{ class_name }}({{ base_class }}): {%- if description %} - """ - {{ description | escape_docstring | indent(4) }} - """ +{{ description | format_pep257_docstring(4) }} {%- endif %} {%- if not fields and not description %} pass @@ -10,9 +8,7 @@ class {{ class_name }}({{ base_class }}): {%- for field in fields %} {{ field.name }}: {{ field.type_hint }} {%- if field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ +{{ field.docstring | format_pep257_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 b/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 index 6ced50efd..84a48f8e0 100644 --- a/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 +++ b/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 @@ -1,15 +1,11 @@ {%- if description %} -""" -{{ description | escape_docstring | indent(4) }} -""" +{{ description | format_pep257_docstring(quote_indent=0, continuation_indent=4) }} {%- endif %} {{ class_name }} = TypedDict('{{ class_name }}', { {%- for field in all_fields %} '{{ field.key }}': {{ field.type_hint }}, {%- if field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ +{{ field.docstring | format_pep257_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/dataclass.jinja2 b/src/datamodel_code_generator/model/template/dataclass.jinja2 index ecd31bffa..b032425ab 100644 --- a/src/datamodel_code_generator/model/template/dataclass.jinja2 +++ b/src/datamodel_code_generator/model/template/dataclass.jinja2 @@ -18,9 +18,7 @@ class {{ class_name }}({{ base_class }}): class {{ class_name }}: {%- endif %} {%- if description %} - """ - {{ description | escape_docstring | indent(4) }} - """ +{{ description | format_pep257_docstring(4) }} {%- endif %} {%- if not fields and not description %} pass @@ -35,9 +33,7 @@ class {{ class_name }}: {%- endif -%} {%- endif %} {%- if field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ +{{ field.docstring | format_pep257_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/msgspec.jinja2 b/src/datamodel_code_generator/model/template/msgspec.jinja2 index 6ab0540d2..2e5c2b9dd 100644 --- a/src/datamodel_code_generator/model/template/msgspec.jinja2 +++ b/src/datamodel_code_generator/model/template/msgspec.jinja2 @@ -9,9 +9,7 @@ class {{ class_name }}({{ base_class }}{%- for key, value in (base_class_kwargs| class {{ class_name }}: {%- endif %} {%- if description %} - """ - {{ description | escape_docstring | indent(4) }} - """ +{{ description | format_pep257_docstring(4) }} {%- endif %} {%- set ns = namespace(has_rendered_field=false) -%} {%- for field in fields -%} @@ -37,9 +35,7 @@ class {{ class_name }}: {%- if not field.extras.get('is_classvar') and field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ +{{ field.docstring | format_pep257_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 index 828c4b416..05e2f6d3a 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 @@ -3,9 +3,7 @@ {% endfor -%} class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} - """ - {{ description | escape_docstring | indent(4) }} - """ +{{ description | format_pep257_docstring(4) }} {%- endif %} {%- if not fields and not description and not config and not class_body_lines %} pass @@ -32,9 +30,7 @@ class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comme {%- endif -%} {%- endif %} {%- if field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ +{{ field.docstring | format_pep257_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 index af5de33b7..e18c40571 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 @@ -18,9 +18,7 @@ {%- set use_base_type = config and config.regex_engine -%} class {{ class_name }}({{ base_class }}{%- if fields -%}[{{get_type_hint(fields, use_base_type)}}]{%- endif -%}):{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} - """ - {{ description | escape_docstring | indent(4) }} - """ +{{ description | format_pep257_docstring(4) }} {%- endif %} {%- if config %} {%- filter indent(4) %} @@ -47,9 +45,7 @@ class {{ class_name }}({{ base_class }}{%- if fields -%}[{{get_type_hint(fields, {%- endif -%} {%- endif %} {%- if field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ + {{ field.docstring | format_pep257_docstring(4) }} {%- elif field.inline_field_docstring %} {{ field.inline_field_docstring }} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 index 401d83f23..312a17d49 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 @@ -12,11 +12,7 @@ {%- set use_base_type = config and config.regex_engine -%} {{ class_name }} = RootModel[{{get_type_hint(fields, use_base_type)}}]{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -""" -{{ description }} -""" +{{ description | format_pep257_docstring(0) }} {%- elif fields and fields[0].docstring %} -""" -{{ fields[0].docstring }} -""" +{{ fields[0].docstring | format_pep257_docstring(0) }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 index 3fcc5ad83..56008cc49 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 @@ -25,9 +25,7 @@ class {{ class_name }}({{ base_class }}): class {{ class_name }}: {%- endif %} {%- if description %} - """ - {{ description | escape_docstring | indent(4) }} - """ +{{ description | format_pep257_docstring(4) }} {%- endif %} {%- if not fields and not description %} pass @@ -46,9 +44,7 @@ class {{ class_name }}: {%- endif -%} {%- endif %} {%- if field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ +{{ field.docstring | format_pep257_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} From e0b27793faff92060f2c9014ea76b7f087d03812 Mon Sep 17 00:00:00 2001 From: Kevin Paulson Date: Tue, 28 Apr 2026 15:20:40 -0400 Subject: [PATCH 2/9] format_docstring the way I want it --- src/datamodel_code_generator/model/base.py | 61 ++++++++-------------- 1 file changed, 23 insertions(+), 38 deletions(-) diff --git a/src/datamodel_code_generator/model/base.py b/src/datamodel_code_generator/model/base.py index 861a86820..b28944dfb 100644 --- a/src/datamodel_code_generator/model/base.py +++ b/src/datamodel_code_generator/model/base.py @@ -7,6 +7,7 @@ from __future__ import annotations import re +import textwrap from abc import ABC, abstractmethod from collections import defaultdict from copy import deepcopy @@ -66,55 +67,39 @@ def escape_docstring(value: str | None) -> str | None: return value.replace("\\", "\\\\").replace('"""', '\\"\\"\\"') -def format_pep257_docstring( - value: str | None, - quote_indent: int = 4, - continuation_indent: int | None = None, -) -> str: - """Format *value* as a triple-quoted Python string for generated code. +def format_docstring(value: str | None, indent_spaces: int = 0) -> str: + """Format *value* as a docstring as per PEP 257. - Single-line text (no newline after escaping) uses a one-line docstring per - PEP 257. Multi-line text uses opening and closing quote lines with a body - in between. + PEP 257 recommends that docstrings that can fit on one line should be formatted on a + single line, for consistency and readability. Leading and trailing whitespace will + be removed, and if after this the value is falsy, an empty string is returned. It is + assumed that the opening triple-quotes are indented appropriately in the template. + If it's a multi-line docstring, each line including the closing triple-quotes will + be indented as per indent_spaces. Args: - value: Raw description or docstring text. - quote_indent: Spaces before each opening or closing quote line and, in - uniform mode, before each body line. - continuation_indent: If set, multi-line bodies use a hanging layout: - the first body line is indented only by *quote_indent*; later lines - use *quote_indent* + *continuation_indent* extra spaces (matching - Jinja's ``indent(continuation_indent)`` with no leading prefix on - the first line). If ``None``, every body line uses the same indent - as the quote lines. + value: docstring text + indent_spaces: Spaces to indent for all lines after the opening triple-quotes Returns: - Empty string when *value* is falsy; otherwise the full docstring block + Empty string when `value` is falsy; otherwise the docstring block including a trailing newline. """ if not value: return "" - escaped = escape_docstring(value) - if escaped is None: - return "" - qi = max(quote_indent, 0) - prefix = " " * qi - tail = "\n" - if "\n" not in escaped: - return f'{prefix}"""{escaped}"""{tail}' + value = value.strip() + + if not value: + return "" - lines = escaped.split("\n") + escaped = escape_docstring(value) - if continuation_indent is None: - body = "\n".join(f"{prefix}{line}" for line in lines) - else: - ci = max(continuation_indent, 0) - cont = " " * (qi + ci) - first_body = f"{prefix}{lines[0]}" - body = first_body if len(lines) == 1 else first_body + "\n" + "\n".join(f"{cont}{line}" for line in lines[1:]) + if len(value.splitlines()) > 1: + return f'"""{escaped}"""\n' - return f'{prefix}"""\n{body}\n{prefix}"""{tail}' + indent_text = textwrap.indent(f'{escaped}\n"""', max(indent_spaces, 0) * " ") + return f'"""\n{indent_text}\n' ALL_MODEL: str = "#all#" @@ -504,7 +489,7 @@ def _get_environment(template_subdir: Path, custom_template_dir: Path | None) -> autoescape=select_autoescape(["html", "xml"]), ) env.filters["escape_docstring"] = escape_docstring - env.filters["format_pep257_docstring"] = format_pep257_docstring + env.filters["format_pep257_docstring"] = format_docstring return env @@ -538,7 +523,7 @@ def _get_environment_with_absolute_path(absolute_template_dir: Path, builtin_sub autoescape=select_autoescape(["html", "xml"]), ) env.filters["escape_docstring"] = escape_docstring - env.filters["format_pep257_docstring"] = format_pep257_docstring + env.filters["format_pep257_docstring"] = format_docstring return env From 7ffd3b477d5f2d04e80a1f63f63a7e22c47c0a69 Mon Sep 17 00:00:00 2001 From: Kevin Paulson Date: Tue, 28 Apr 2026 15:44:13 -0400 Subject: [PATCH 3/9] Ready for testing? --- src/datamodel_code_generator/model/base.py | 6 ++---- src/datamodel_code_generator/model/template/Enum.jinja2 | 4 ++-- .../model/template/ScalarTypeAliasAnnotation.jinja2 | 2 +- .../model/template/ScalarTypeAliasType.jinja2 | 2 +- .../model/template/ScalarTypeStatement.jinja2 | 2 +- .../model/template/TypeAliasAnnotation.jinja2 | 6 +++--- .../model/template/TypeAliasType.jinja2 | 6 +++--- .../model/template/TypeStatement.jinja2 | 6 +++--- .../model/template/TypedDictClass.jinja2 | 4 ++-- .../model/template/TypedDictFunction.jinja2 | 4 ++-- .../model/template/dataclass.jinja2 | 4 ++-- src/datamodel_code_generator/model/template/msgspec.jinja2 | 4 ++-- .../model/template/pydantic_v2/BaseModel.jinja2 | 4 ++-- .../model/template/pydantic_v2/RootModel.jinja2 | 4 ++-- .../model/template/pydantic_v2/RootModelTypeAlias.jinja2 | 4 ++-- .../model/template/pydantic_v2/dataclass.jinja2 | 4 ++-- 16 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/datamodel_code_generator/model/base.py b/src/datamodel_code_generator/model/base.py index b28944dfb..ddc4423f7 100644 --- a/src/datamodel_code_generator/model/base.py +++ b/src/datamodel_code_generator/model/base.py @@ -488,8 +488,7 @@ def _get_environment(template_subdir: Path, custom_template_dir: Path | None) -> loader=loader, autoescape=select_autoescape(["html", "xml"]), ) - env.filters["escape_docstring"] = escape_docstring - env.filters["format_pep257_docstring"] = format_docstring + env.filters["format_docstring"] = format_docstring return env @@ -522,8 +521,7 @@ def _get_environment_with_absolute_path(absolute_template_dir: Path, builtin_sub loader=ChoiceLoader(loaders), autoescape=select_autoescape(["html", "xml"]), ) - env.filters["escape_docstring"] = escape_docstring - env.filters["format_pep257_docstring"] = format_docstring + env.filters["format_docstring"] = format_docstring return env diff --git a/src/datamodel_code_generator/model/template/Enum.jinja2 b/src/datamodel_code_generator/model/template/Enum.jinja2 index d89bf2824..11c5f1e1d 100644 --- a/src/datamodel_code_generator/model/template/Enum.jinja2 +++ b/src/datamodel_code_generator/model/template/Enum.jinja2 @@ -3,12 +3,12 @@ {% endfor -%} class {{ class_name }}({{ base_class }}): {%- if description %} -{{ description | format_pep257_docstring(4) }} + {{ description | format_docstring(4) }} {%- endif %} {%- for field in fields %} {{ field.name }} = {{ field.default }} {%- if field.docstring %} -{{ field.docstring | format_pep257_docstring(4) }} + {{ field.docstring | format_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 index d3e0b8443..6fdb5bce9 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 @@ -1,4 +1,4 @@ {{ class_name }}: TypeAlias = {{ py_type }} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 index 7d3fed59c..f86a187ac 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 @@ -1,4 +1,4 @@ {{ class_name }} = TypeAliasType("{{ class_name }}", {{ py_type }}) {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 index f70891d49..09151a300 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 @@ -1,4 +1,4 @@ type {{ class_name }} = {{ py_type }} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- endif %} \ No newline at end of file diff --git a/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 b/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 index ae16826a9..a6dac9efc 100644 --- a/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 @@ -11,13 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} {{ class_name }}: TypeAlias = {{ get_type_annotation(fields[0]) }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- elif fields[0].docstring %} -{{ fields[0].docstring | format_pep257_docstring(0) }} +{{ fields[0].docstring | format_docstring(0) }} {%- endif %} {%- else %} {{ class_name }}: TypeAlias = {{ base_class }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- endif %} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 b/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 index b640afa6d..ecde5b7eb 100644 --- a/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 @@ -11,13 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} {{ class_name }} = TypeAliasType("{{ class_name }}", {{ get_type_annotation(fields[0]) }}){% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- elif fields[0].docstring %} -{{ fields[0].docstring | format_pep257_docstring(0) }} +{{ fields[0].docstring | format_docstring(0) }} {%- endif %} {%- else %} {{ class_name }} = TypeAliasType("{{ class_name }}", {{ base_class }}){% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- endif %} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypeStatement.jinja2 b/src/datamodel_code_generator/model/template/TypeStatement.jinja2 index ed8b6085c..7ce1bd9fa 100644 --- a/src/datamodel_code_generator/model/template/TypeStatement.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeStatement.jinja2 @@ -11,13 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} type {{ class_name }} = {{ get_type_annotation(fields[0]) }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- elif fields[0].docstring %} -{{ fields[0].docstring | format_pep257_docstring(0) }} +{{ fields[0].docstring | format_docstring(0) }} {%- endif %} {%- else %} type {{ class_name }} = {{ base_class }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- endif %} {%- endif %} \ No newline at end of file diff --git a/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 b/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 index 3dd4c84b4..6c531b298 100644 --- a/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 +++ b/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 @@ -1,6 +1,6 @@ class {{ class_name }}({{ base_class }}): {%- if description %} -{{ description | format_pep257_docstring(4) }} + {{ description | format_docstring(4) }} {%- endif %} {%- if not fields and not description %} pass @@ -8,7 +8,7 @@ class {{ class_name }}({{ base_class }}): {%- for field in fields %} {{ field.name }}: {{ field.type_hint }} {%- if field.docstring %} -{{ field.docstring | format_pep257_docstring(4) }} + {{ field.docstring | format_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 b/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 index 84a48f8e0..b7d3f2454 100644 --- a/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 +++ b/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 @@ -1,11 +1,11 @@ {%- if description %} -{{ description | format_pep257_docstring(quote_indent=0, continuation_indent=4) }} + {{ description | format_docstring(4) }} {%- endif %} {{ class_name }} = TypedDict('{{ class_name }}', { {%- for field in all_fields %} '{{ field.key }}': {{ field.type_hint }}, {%- if field.docstring %} -{{ field.docstring | format_pep257_docstring(4) }} + {{ field.docstring | format_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/dataclass.jinja2 b/src/datamodel_code_generator/model/template/dataclass.jinja2 index b032425ab..9e66e3c31 100644 --- a/src/datamodel_code_generator/model/template/dataclass.jinja2 +++ b/src/datamodel_code_generator/model/template/dataclass.jinja2 @@ -18,7 +18,7 @@ class {{ class_name }}({{ base_class }}): class {{ class_name }}: {%- endif %} {%- if description %} -{{ description | format_pep257_docstring(4) }} + {{ description | format_docstring(4) }} {%- endif %} {%- if not fields and not description %} pass @@ -33,7 +33,7 @@ class {{ class_name }}: {%- endif -%} {%- endif %} {%- if field.docstring %} -{{ field.docstring | format_pep257_docstring(4) }} + {{ field.docstring | format_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/msgspec.jinja2 b/src/datamodel_code_generator/model/template/msgspec.jinja2 index 2e5c2b9dd..2198d8d47 100644 --- a/src/datamodel_code_generator/model/template/msgspec.jinja2 +++ b/src/datamodel_code_generator/model/template/msgspec.jinja2 @@ -9,7 +9,7 @@ class {{ class_name }}({{ base_class }}{%- for key, value in (base_class_kwargs| class {{ class_name }}: {%- endif %} {%- if description %} -{{ description | format_pep257_docstring(4) }} + {{ description | format_docstring(4) }} {%- endif %} {%- set ns = namespace(has_rendered_field=false) -%} {%- for field in fields -%} @@ -35,7 +35,7 @@ class {{ class_name }}: {%- if not field.extras.get('is_classvar') and field.docstring %} -{{ field.docstring | format_pep257_docstring(4) }} + {{ field.docstring | format_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 index 05e2f6d3a..b42faf39d 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 @@ -3,7 +3,7 @@ {% endfor -%} class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(4) }} + {{ description | format_docstring(4) }} {%- endif %} {%- if not fields and not description and not config and not class_body_lines %} pass @@ -30,7 +30,7 @@ class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comme {%- endif -%} {%- endif %} {%- if field.docstring %} -{{ field.docstring | format_pep257_docstring(4) }} + {{ field.docstring | format_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 index e18c40571..aae81741a 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 @@ -18,7 +18,7 @@ {%- set use_base_type = config and config.regex_engine -%} class {{ class_name }}({{ base_class }}{%- if fields -%}[{{get_type_hint(fields, use_base_type)}}]{%- endif -%}):{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(4) }} + {{ description | format_docstring(4) }} {%- endif %} {%- if config %} {%- filter indent(4) %} @@ -45,7 +45,7 @@ class {{ class_name }}({{ base_class }}{%- if fields -%}[{{get_type_hint(fields, {%- endif -%} {%- endif %} {%- if field.docstring %} - {{ field.docstring | format_pep257_docstring(4) }} + {{ field.docstring | format_docstring(4) }} {%- elif field.inline_field_docstring %} {{ field.inline_field_docstring }} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 index 312a17d49..d8356ef03 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 @@ -12,7 +12,7 @@ {%- set use_base_type = config and config.regex_engine -%} {{ class_name }} = RootModel[{{get_type_hint(fields, use_base_type)}}]{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_pep257_docstring(0) }} +{{ description | format_docstring(0) }} {%- elif fields and fields[0].docstring %} -{{ fields[0].docstring | format_pep257_docstring(0) }} +{{ fields[0].docstring | format_docstring(0) }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 index 56008cc49..f11910254 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 @@ -25,7 +25,7 @@ class {{ class_name }}({{ base_class }}): class {{ class_name }}: {%- endif %} {%- if description %} -{{ description | format_pep257_docstring(4) }} + {{ description | format_docstring(4) }} {%- endif %} {%- if not fields and not description %} pass @@ -44,7 +44,7 @@ class {{ class_name }}: {%- endif -%} {%- endif %} {%- if field.docstring %} -{{ field.docstring | format_pep257_docstring(4) }} + {{ field.docstring | format_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} From caa1f492f8dd0ab4d54fbe2e1612ce7867e6971d Mon Sep 17 00:00:00 2001 From: Kevin Paulson Date: Tue, 28 Apr 2026 16:12:54 -0400 Subject: [PATCH 4/9] fix logic error --- src/datamodel_code_generator/model/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datamodel_code_generator/model/base.py b/src/datamodel_code_generator/model/base.py index ddc4423f7..7714d878b 100644 --- a/src/datamodel_code_generator/model/base.py +++ b/src/datamodel_code_generator/model/base.py @@ -95,7 +95,7 @@ def format_docstring(value: str | None, indent_spaces: int = 0) -> str: escaped = escape_docstring(value) - if len(value.splitlines()) > 1: + if len(value.splitlines()) == 1: return f'"""{escaped}"""\n' indent_text = textwrap.indent(f'{escaped}\n"""', max(indent_spaces, 0) * " ") From d15044324dc80db668ae193d15e4435a58fb0c7c Mon Sep 17 00:00:00 2001 From: Kevin Paulson Date: Tue, 28 Apr 2026 16:47:54 -0400 Subject: [PATCH 5/9] If single line and ends with " add a space so there isn't 4 " in a row --- src/datamodel_code_generator/model/base.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/datamodel_code_generator/model/base.py b/src/datamodel_code_generator/model/base.py index 7714d878b..2c5d085d0 100644 --- a/src/datamodel_code_generator/model/base.py +++ b/src/datamodel_code_generator/model/base.py @@ -82,8 +82,7 @@ def format_docstring(value: str | None, indent_spaces: int = 0) -> str: indent_spaces: Spaces to indent for all lines after the opening triple-quotes Returns: - Empty string when `value` is falsy; otherwise the docstring block - including a trailing newline. + Empty string when `value` is falsy; otherwise the docstring block. """ if not value: return "" @@ -96,10 +95,13 @@ def format_docstring(value: str | None, indent_spaces: int = 0) -> str: escaped = escape_docstring(value) if len(value.splitlines()) == 1: - return f'"""{escaped}"""\n' + if escaped.endswith('"'): + escaped = f"{escaped} " + + return f'"""{escaped}"""' indent_text = textwrap.indent(f'{escaped}\n"""', max(indent_spaces, 0) * " ") - return f'"""\n{indent_text}\n' + return f'"""\n{indent_text}' ALL_MODEL: str = "#all#" From 650aeef68cf6f20f93445cd7b323f40dc4e32b01 Mon Sep 17 00:00:00 2001 From: Kevin Paulson Date: Tue, 28 Apr 2026 17:07:14 -0400 Subject: [PATCH 6/9] Update test outputs --- .../main/graphql/additional_imports.py | 12 ++------ tests/data/expected/main/graphql/annotated.py | 8 ++---- .../main/graphql/annotated_field_aliases.py | 8 ++---- .../graphql/annotated_use_default_kwarg.py | 8 ++---- .../annotated_use_standard_collections.py | 8 ++---- ...standard_collections_use_union_operator.py | 8 ++---- .../graphql/annotated_use_union_operator.py | 8 ++---- tests/data/expected/main/graphql/casing.py | 12 ++------ .../main/graphql/custom_formatters.py | 12 ++------ .../main/graphql/custom_scalar_types.py | 12 ++------ .../default_values_required_use_default.py | 12 ++------ .../main/graphql/different_types_of_fields.py | 8 ++---- .../main/graphql/empty_list_default.py | 8 ++---- .../main/graphql/enum_literals_all.py | 12 ++------ .../main/graphql/enum_literals_one.py | 12 ++------ tests/data/expected/main/graphql/enums.py | 12 ++------ .../graphql/enums_ignore_enum_constraints.py | 12 ++------ .../main/graphql/enums_no_specialized.py | 12 ++------ .../main/graphql/enums_specialized.py | 12 ++------ .../expected/main/graphql/enums_typed_dict.py | 12 ++------ .../main/graphql/enums_using_subclass.py | 12 ++------ .../expected/main/graphql/field_aliases.py | 8 ++---- .../graphql_multiple_aliases_pydantic_v2.py | 8 ++---- .../expected/main/graphql/interface_mro.py | 12 ++------ .../data/expected/main/graphql/no_typename.py | 12 ++------ .../graphql/pydantic_v2_empty_list_default.py | 8 ++---- .../expected/main/graphql/simple_star_wars.py | 16 +++-------- .../simple_star_wars_class_name_prefix.py | 16 +++-------- .../graphql/simple_star_wars_dataclass.py | 16 +++-------- .../simple_star_wars_dataclass_arguments.py | 16 +++-------- ...mple_star_wars_dataclass_frozen_kw_only.py | 16 +++-------- .../simple_star_wars_extra_fields_allow.py | 16 +++-------- .../main/graphql/split_graphql_schemas.py | 12 ++------ .../data/expected/main/graphql/type_alias.py | 12 ++------ .../expected/main/graphql/type_alias_py312.py | 12 ++------ tests/data/expected/main/graphql/union.py | 16 +++-------- .../main/graphql/union_class_name_prefix.py | 16 +++-------- .../main/graphql/union_snake_case_field.py | 16 +++-------- .../main/graphql/use_standard_collections.py | 8 ++---- .../main/graphql/use_union_operator.py | 8 ++---- .../expected/main/jsonschema/allof_mro.py | 4 +-- .../type_alias_with_field_description.py | 4 +-- ...type_alias_with_field_description_py312.py | 4 +-- .../main/openapi/all_of_with_relative_ref.py | 8 ++---- .../main/openapi/allof_array_ref_override.py | 4 +-- .../expected/main/use_attribute_docstrings.py | 8 ++---- .../output.py | 8 ++---- .../main_docstring_special_chars/output.py | 28 +++++-------------- .../main_use_field_description/output.py | 12 ++------ .../output.py | 8 ++---- .../output.py | 4 +-- .../output.py | 4 +-- .../output.py | 4 +-- .../main_use_schema_description/output.py | 4 +-- .../parser/graphql/field-default-enum.py | 8 ++---- .../expected/parser/graphql/no_typename.py | 12 ++------ .../parser/graphql/union-aliased-bug.py | 8 ++---- .../parser/graphql/union-commented.py | 12 ++------ .../parser/graphql/union_with_prefix.py | 16 +++-------- 59 files changed, 156 insertions(+), 468 deletions(-) diff --git a/tests/data/expected/main/graphql/additional_imports.py b/tests/data/expected/main/graphql/additional_imports.py index f8f17778e..b2b03894e 100644 --- a/tests/data/expected/main/graphql/additional_imports.py +++ b/tests/data/expected/main/graphql/additional_imports.py @@ -12,27 +12,21 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" Date = TypeAliasType("Date", date) DateTime = TypeAliasType("DateTime", datetime) -""" -DateTime (ISO8601, example: 2020-01-01T10:11:12+00:00) -""" +"""DateTime (ISO8601, example: 2020-01-01T10:11:12+00:00)""" MyCustomClass = TypeAliasType("MyCustomClass", MyCustomPythonClass) String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated.py b/tests/data/expected/main/graphql/annotated.py index f86ff97ab..735fe6f3a 100644 --- a/tests/data/expected/main/graphql/annotated.py +++ b/tests/data/expected/main/graphql/annotated.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_field_aliases.py b/tests/data/expected/main/graphql/annotated_field_aliases.py index bda775eaa..0c3197d1d 100644 --- a/tests/data/expected/main/graphql/annotated_field_aliases.py +++ b/tests/data/expected/main/graphql/annotated_field_aliases.py @@ -10,18 +10,14 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" DateTime = TypeAliasType("DateTime", str) String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class DateTimePeriod(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_use_default_kwarg.py b/tests/data/expected/main/graphql/annotated_use_default_kwarg.py index ff90d9acb..b26d561a3 100644 --- a/tests/data/expected/main/graphql/annotated_use_default_kwarg.py +++ b/tests/data/expected/main/graphql/annotated_use_default_kwarg.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_use_standard_collections.py b/tests/data/expected/main/graphql/annotated_use_standard_collections.py index f86ff97ab..735fe6f3a 100644 --- a/tests/data/expected/main/graphql/annotated_use_standard_collections.py +++ b/tests/data/expected/main/graphql/annotated_use_standard_collections.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_use_standard_collections_use_union_operator.py b/tests/data/expected/main/graphql/annotated_use_standard_collections_use_union_operator.py index f86ff97ab..735fe6f3a 100644 --- a/tests/data/expected/main/graphql/annotated_use_standard_collections_use_union_operator.py +++ b/tests/data/expected/main/graphql/annotated_use_standard_collections_use_union_operator.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_use_union_operator.py b/tests/data/expected/main/graphql/annotated_use_union_operator.py index f86ff97ab..735fe6f3a 100644 --- a/tests/data/expected/main/graphql/annotated_use_union_operator.py +++ b/tests/data/expected/main/graphql/annotated_use_union_operator.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/casing.py b/tests/data/expected/main/graphql/casing.py index 2fb3406c0..cb76b1a1a 100644 --- a/tests/data/expected/main/graphql/casing.py +++ b/tests/data/expected/main/graphql/casing.py @@ -11,21 +11,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" Int = TypeAliasType("Int", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Lowercase(Enum): diff --git a/tests/data/expected/main/graphql/custom_formatters.py b/tests/data/expected/main/graphql/custom_formatters.py index 46e8a3070..0c8be84ed 100644 --- a/tests/data/expected/main/graphql/custom_formatters.py +++ b/tests/data/expected/main/graphql/custom_formatters.py @@ -11,24 +11,18 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Long = TypeAliasType("Long", str) String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/custom_scalar_types.py b/tests/data/expected/main/graphql/custom_scalar_types.py index 22eb6bf3f..6c2b6d30f 100644 --- a/tests/data/expected/main/graphql/custom_scalar_types.py +++ b/tests/data/expected/main/graphql/custom_scalar_types.py @@ -10,24 +10,18 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Long = TypeAliasType("Long", int) String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/default_values_required_use_default.py b/tests/data/expected/main/graphql/default_values_required_use_default.py index e9fed1bf3..3751d870d 100644 --- a/tests/data/expected/main/graphql/default_values_required_use_default.py +++ b/tests/data/expected/main/graphql/default_values_required_use_default.py @@ -10,21 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class User(BaseModel): diff --git a/tests/data/expected/main/graphql/different_types_of_fields.py b/tests/data/expected/main/graphql/different_types_of_fields.py index 28f2f2f9a..6a2eab555 100644 --- a/tests/data/expected/main/graphql/different_types_of_fields.py +++ b/tests/data/expected/main/graphql/different_types_of_fields.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/empty_list_default.py b/tests/data/expected/main/graphql/empty_list_default.py index 8def8a752..07b5dcd4f 100644 --- a/tests/data/expected/main/graphql/empty_list_default.py +++ b/tests/data/expected/main/graphql/empty_list_default.py @@ -9,15 +9,11 @@ from pydantic import BaseModel, Field type Boolean = bool -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" type String = str -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Container(BaseModel): diff --git a/tests/data/expected/main/graphql/enum_literals_all.py b/tests/data/expected/main/graphql/enum_literals_all.py index d242eafe2..83b50032f 100644 --- a/tests/data/expected/main/graphql/enum_literals_all.py +++ b/tests/data/expected/main/graphql/enum_literals_all.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Color(RootModel[Literal['BLUE', 'GREEN', 'RED']]): @@ -26,9 +22,7 @@ class Color(RootModel[Literal['BLUE', 'GREEN', 'RED']]): class EmployeeShiftStatus(RootModel[Literal['NOT_ON_SHIFT', 'ON_SHIFT']]): - """ - Employee shift status - """ + """Employee shift status""" root: Literal['NOT_ON_SHIFT', 'ON_SHIFT'] diff --git a/tests/data/expected/main/graphql/enum_literals_one.py b/tests/data/expected/main/graphql/enum_literals_one.py index dc8c62216..a2033517f 100644 --- a/tests/data/expected/main/graphql/enum_literals_one.py +++ b/tests/data/expected/main/graphql/enum_literals_one.py @@ -11,15 +11,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Color(Enum): @@ -29,9 +25,7 @@ class Color(Enum): class EmployeeShiftStatus(Enum): - """ - Employee shift status - """ + """Employee shift status""" NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/enums.py b/tests/data/expected/main/graphql/enums.py index 97e952c3e..d15a54f73 100644 --- a/tests/data/expected/main/graphql/enums.py +++ b/tests/data/expected/main/graphql/enums.py @@ -9,15 +9,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Color(Enum): @@ -27,9 +23,7 @@ class Color(Enum): class EmployeeShiftStatus(Enum): - """ - Employee shift status - """ + """Employee shift status""" NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/enums_ignore_enum_constraints.py b/tests/data/expected/main/graphql/enums_ignore_enum_constraints.py index 7e374b61c..5d9a233fa 100644 --- a/tests/data/expected/main/graphql/enums_ignore_enum_constraints.py +++ b/tests/data/expected/main/graphql/enums_ignore_enum_constraints.py @@ -8,15 +8,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Color(RootModel[str]): @@ -24,9 +20,7 @@ class Color(RootModel[str]): class EmployeeShiftStatus(RootModel[str]): - """ - Employee shift status - """ + """Employee shift status""" root: str diff --git a/tests/data/expected/main/graphql/enums_no_specialized.py b/tests/data/expected/main/graphql/enums_no_specialized.py index 97e952c3e..d15a54f73 100644 --- a/tests/data/expected/main/graphql/enums_no_specialized.py +++ b/tests/data/expected/main/graphql/enums_no_specialized.py @@ -9,15 +9,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Color(Enum): @@ -27,9 +23,7 @@ class Color(Enum): class EmployeeShiftStatus(Enum): - """ - Employee shift status - """ + """Employee shift status""" NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/enums_specialized.py b/tests/data/expected/main/graphql/enums_specialized.py index 40d7f5aa0..a04c6ca72 100644 --- a/tests/data/expected/main/graphql/enums_specialized.py +++ b/tests/data/expected/main/graphql/enums_specialized.py @@ -9,15 +9,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Color(StrEnum): @@ -27,9 +23,7 @@ class Color(StrEnum): class EmployeeShiftStatus(StrEnum): - """ - Employee shift status - """ + """Employee shift status""" NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/enums_typed_dict.py b/tests/data/expected/main/graphql/enums_typed_dict.py index 998360baf..bbca67530 100644 --- a/tests/data/expected/main/graphql/enums_typed_dict.py +++ b/tests/data/expected/main/graphql/enums_typed_dict.py @@ -7,24 +7,18 @@ from typing import Literal, TypeAlias Boolean: TypeAlias = bool -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String: TypeAlias = str -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" Color: TypeAlias = Literal['BLUE', 'GREEN', 'RED'] EmployeeShiftStatus: TypeAlias = Literal['NOT_ON_SHIFT', 'ON_SHIFT'] -""" -Employee shift status -""" +"""Employee shift status""" EnumWithOneField: TypeAlias = Literal['FIELD'] diff --git a/tests/data/expected/main/graphql/enums_using_subclass.py b/tests/data/expected/main/graphql/enums_using_subclass.py index bc73254ad..594bd66df 100644 --- a/tests/data/expected/main/graphql/enums_using_subclass.py +++ b/tests/data/expected/main/graphql/enums_using_subclass.py @@ -9,15 +9,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Color(str, Enum): @@ -27,9 +23,7 @@ class Color(str, Enum): class EmployeeShiftStatus(str, Enum): - """ - Employee shift status - """ + """Employee shift status""" NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/field_aliases.py b/tests/data/expected/main/graphql/field_aliases.py index 29da5df7a..a696b9340 100644 --- a/tests/data/expected/main/graphql/field_aliases.py +++ b/tests/data/expected/main/graphql/field_aliases.py @@ -10,18 +10,14 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" DateTime = TypeAliasType("DateTime", str) String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class DateTimePeriod(BaseModel): diff --git a/tests/data/expected/main/graphql/graphql_multiple_aliases_pydantic_v2.py b/tests/data/expected/main/graphql/graphql_multiple_aliases_pydantic_v2.py index 94b25ab17..9a85f5028 100644 --- a/tests/data/expected/main/graphql/graphql_multiple_aliases_pydantic_v2.py +++ b/tests/data/expected/main/graphql/graphql_multiple_aliases_pydantic_v2.py @@ -10,18 +10,14 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" DateTime = TypeAliasType("DateTime", str) String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Event(BaseModel): diff --git a/tests/data/expected/main/graphql/interface_mro.py b/tests/data/expected/main/graphql/interface_mro.py index 242fb66f2..d3aaec2f3 100644 --- a/tests/data/expected/main/graphql/interface_mro.py +++ b/tests/data/expected/main/graphql/interface_mro.py @@ -10,21 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class BaseInterface(BaseModel): diff --git a/tests/data/expected/main/graphql/no_typename.py b/tests/data/expected/main/graphql/no_typename.py index 5a8598d00..6f6f77a8b 100644 --- a/tests/data/expected/main/graphql/no_typename.py +++ b/tests/data/expected/main/graphql/no_typename.py @@ -8,21 +8,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Node(BaseModel): diff --git a/tests/data/expected/main/graphql/pydantic_v2_empty_list_default.py b/tests/data/expected/main/graphql/pydantic_v2_empty_list_default.py index 052c98f4d..c76096152 100644 --- a/tests/data/expected/main/graphql/pydantic_v2_empty_list_default.py +++ b/tests/data/expected/main/graphql/pydantic_v2_empty_list_default.py @@ -9,15 +9,11 @@ from pydantic import BaseModel, Field type Boolean = bool -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" type String = str -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Container(BaseModel): diff --git a/tests/data/expected/main/graphql/simple_star_wars.py b/tests/data/expected/main/graphql/simple_star_wars.py index 4593d1b32..148fb2da3 100644 --- a/tests/data/expected/main/graphql/simple_star_wars.py +++ b/tests/data/expected/main/graphql/simple_star_wars.py @@ -10,27 +10,19 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Int = TypeAliasType("Int", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Film(BaseModel): diff --git a/tests/data/expected/main/graphql/simple_star_wars_class_name_prefix.py b/tests/data/expected/main/graphql/simple_star_wars_class_name_prefix.py index 24121a1cb..7a26da4b6 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_class_name_prefix.py +++ b/tests/data/expected/main/graphql/simple_star_wars_class_name_prefix.py @@ -10,27 +10,19 @@ from typing_extensions import TypeAliasType FooBoolean = TypeAliasType("FooBoolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" FooID = TypeAliasType("FooID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" FooInt = TypeAliasType("FooInt", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" FooString = TypeAliasType("FooString", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class FooFilm(BaseModel): diff --git a/tests/data/expected/main/graphql/simple_star_wars_dataclass.py b/tests/data/expected/main/graphql/simple_star_wars_dataclass.py index 8fa8d3d0f..39177965e 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_dataclass.py +++ b/tests/data/expected/main/graphql/simple_star_wars_dataclass.py @@ -8,27 +8,19 @@ from typing import Literal, TypeAlias Boolean: TypeAlias = bool -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID: TypeAlias = str -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Int: TypeAlias = int -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String: TypeAlias = str -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" @dataclass diff --git a/tests/data/expected/main/graphql/simple_star_wars_dataclass_arguments.py b/tests/data/expected/main/graphql/simple_star_wars_dataclass_arguments.py index 9df4fe776..b4e6248e7 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_dataclass_arguments.py +++ b/tests/data/expected/main/graphql/simple_star_wars_dataclass_arguments.py @@ -8,27 +8,19 @@ from typing import Literal, TypeAlias Boolean: TypeAlias = bool -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID: TypeAlias = str -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Int: TypeAlias = int -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String: TypeAlias = str -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" @dataclass(order=True, slots=True) diff --git a/tests/data/expected/main/graphql/simple_star_wars_dataclass_frozen_kw_only.py b/tests/data/expected/main/graphql/simple_star_wars_dataclass_frozen_kw_only.py index 24d920fa6..6609e2e7d 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_dataclass_frozen_kw_only.py +++ b/tests/data/expected/main/graphql/simple_star_wars_dataclass_frozen_kw_only.py @@ -8,27 +8,19 @@ from typing import Literal, TypeAlias Boolean: TypeAlias = bool -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID: TypeAlias = str -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Int: TypeAlias = int -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String: TypeAlias = str -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" @dataclass(frozen=True, kw_only=True) diff --git a/tests/data/expected/main/graphql/simple_star_wars_extra_fields_allow.py b/tests/data/expected/main/graphql/simple_star_wars_extra_fields_allow.py index 2f0d53d9f..f4b5c5797 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_extra_fields_allow.py +++ b/tests/data/expected/main/graphql/simple_star_wars_extra_fields_allow.py @@ -10,27 +10,19 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Int = TypeAliasType("Int", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Film(BaseModel): diff --git a/tests/data/expected/main/graphql/split_graphql_schemas.py b/tests/data/expected/main/graphql/split_graphql_schemas.py index eb8bde6e3..35c8c1ef2 100644 --- a/tests/data/expected/main/graphql/split_graphql_schemas.py +++ b/tests/data/expected/main/graphql/split_graphql_schemas.py @@ -10,21 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" Int = TypeAliasType("Int", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Baz(BaseModel): diff --git a/tests/data/expected/main/graphql/type_alias.py b/tests/data/expected/main/graphql/type_alias.py index 9cc52bc39..596bef487 100644 --- a/tests/data/expected/main/graphql/type_alias.py +++ b/tests/data/expected/main/graphql/type_alias.py @@ -10,24 +10,18 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" Int = TypeAliasType("Int", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" SimpleString = TypeAliasType("SimpleString", str) String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Person(BaseModel): diff --git a/tests/data/expected/main/graphql/type_alias_py312.py b/tests/data/expected/main/graphql/type_alias_py312.py index cc7dc4aa8..e3c4977d5 100644 --- a/tests/data/expected/main/graphql/type_alias_py312.py +++ b/tests/data/expected/main/graphql/type_alias_py312.py @@ -9,24 +9,18 @@ from pydantic import BaseModel, Field type Boolean = bool -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" type Int = int -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" type SimpleString = str type String = str -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Person(BaseModel): diff --git a/tests/data/expected/main/graphql/union.py b/tests/data/expected/main/graphql/union.py index c4ca331c4..7d0874226 100644 --- a/tests/data/expected/main/graphql/union.py +++ b/tests/data/expected/main/graphql/union.py @@ -10,27 +10,19 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Int = TypeAliasType("Int", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class IResource(BaseModel): diff --git a/tests/data/expected/main/graphql/union_class_name_prefix.py b/tests/data/expected/main/graphql/union_class_name_prefix.py index 911faf1f5..ed1695038 100644 --- a/tests/data/expected/main/graphql/union_class_name_prefix.py +++ b/tests/data/expected/main/graphql/union_class_name_prefix.py @@ -10,27 +10,19 @@ from typing_extensions import TypeAliasType FooBoolean = TypeAliasType("FooBoolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" FooID = TypeAliasType("FooID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" FooInt = TypeAliasType("FooInt", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" FooString = TypeAliasType("FooString", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class FooIResource(BaseModel): diff --git a/tests/data/expected/main/graphql/union_snake_case_field.py b/tests/data/expected/main/graphql/union_snake_case_field.py index 71c9a4e39..55afd3ee8 100644 --- a/tests/data/expected/main/graphql/union_snake_case_field.py +++ b/tests/data/expected/main/graphql/union_snake_case_field.py @@ -10,27 +10,19 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" Int = TypeAliasType("Int", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class IResource(BaseModel): diff --git a/tests/data/expected/main/graphql/use_standard_collections.py b/tests/data/expected/main/graphql/use_standard_collections.py index 112130ab0..bb0ab34a3 100644 --- a/tests/data/expected/main/graphql/use_standard_collections.py +++ b/tests/data/expected/main/graphql/use_standard_collections.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/use_union_operator.py b/tests/data/expected/main/graphql/use_union_operator.py index 7c3a2b725..376a800bc 100644 --- a/tests/data/expected/main/graphql/use_union_operator.py +++ b/tests/data/expected/main/graphql/use_union_operator.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class A(BaseModel): diff --git a/tests/data/expected/main/jsonschema/allof_mro.py b/tests/data/expected/main/jsonschema/allof_mro.py index d4af7a11c..8ca0b4b59 100644 --- a/tests/data/expected/main/jsonschema/allof_mro.py +++ b/tests/data/expected/main/jsonschema/allof_mro.py @@ -20,9 +20,7 @@ class RightBranch(BaseInterface): class DiamondType(LeftBranch, RightBranch, BaseInterface): - """ - Diamond inheritance pattern - inherits from both LeftBranch and RightBranch which both inherit from BaseInterface - """ + """Diamond inheritance pattern - inherits from both LeftBranch and RightBranch which both inherit from BaseInterface""" diamond_value: str | None = None diff --git a/tests/data/expected/main/jsonschema/type_alias_with_field_description.py b/tests/data/expected/main/jsonschema/type_alias_with_field_description.py index e5a07bba4..677782d76 100644 --- a/tests/data/expected/main/jsonschema/type_alias_with_field_description.py +++ b/tests/data/expected/main/jsonschema/type_alias_with_field_description.py @@ -24,9 +24,7 @@ AnnotatedType = TypeAliasType( "AnnotatedType", Annotated[str | bool, Field(..., title='MyAnnotatedType')] ) -""" -An annotated union type -""" +"""An annotated union type""" class ModelWithTypeAliasField(BaseModel): diff --git a/tests/data/expected/main/jsonschema/type_alias_with_field_description_py312.py b/tests/data/expected/main/jsonschema/type_alias_with_field_description_py312.py index f089a40a6..78d3fbb57 100644 --- a/tests/data/expected/main/jsonschema/type_alias_with_field_description_py312.py +++ b/tests/data/expected/main/jsonschema/type_alias_with_field_description_py312.py @@ -21,9 +21,7 @@ type AnnotatedType = Annotated[str | bool, Field(..., title='MyAnnotatedType')] -""" -An annotated union type -""" +"""An annotated union type""" class ModelWithTypeAliasField(BaseModel): diff --git a/tests/data/expected/main/openapi/all_of_with_relative_ref.py b/tests/data/expected/main/openapi/all_of_with_relative_ref.py index f992cd4aa..841acbeb7 100644 --- a/tests/data/expected/main/openapi/all_of_with_relative_ref.py +++ b/tests/data/expected/main/openapi/all_of_with_relative_ref.py @@ -14,9 +14,7 @@ class Animal(BaseModel): extra='forbid', ) kind: Kind | None = None - """ - The kind of the animal - """ + """The kind of the animal""" class Animals(RootModel[Animal]): @@ -33,9 +31,7 @@ class Pet(BaseModel): extra='forbid', ) kind: Kind | None = None - """ - The kind of the pet - """ + """The kind of the pet""" class Pets(RootModel[Pet]): diff --git a/tests/data/expected/main/openapi/allof_array_ref_override.py b/tests/data/expected/main/openapi/allof_array_ref_override.py index 237732613..ba3d75187 100644 --- a/tests/data/expected/main/openapi/allof_array_ref_override.py +++ b/tests/data/expected/main/openapi/allof_array_ref_override.py @@ -30,9 +30,7 @@ class Metadata(BaseModel): class CollectionWrapper(BaseModel): - """ - Generic response wrapper containing a collection of items and pagination metadata. - """ + """Generic response wrapper containing a collection of items and pagination metadata.""" data: list[dict[str, Any]] = Field( ..., description='Array of items in the collection.' diff --git a/tests/data/expected/main/use_attribute_docstrings.py b/tests/data/expected/main/use_attribute_docstrings.py index d2cfc6fde..30e955dc1 100644 --- a/tests/data/expected/main/use_attribute_docstrings.py +++ b/tests/data/expected/main/use_attribute_docstrings.py @@ -12,10 +12,6 @@ class Person(BaseModel): use_attribute_docstrings=True, ) name: str - """ - The person's full name - """ + """The person's full name""" age: int | None = None - """ - The person's age in years - """ + """The person's age in years""" diff --git a/tests/data/expected/main_kr/main_allof_with_description_only/output.py b/tests/data/expected/main_kr/main_allof_with_description_only/output.py index 0fa45ba44..dd8164c67 100644 --- a/tests/data/expected/main_kr/main_allof_with_description_only/output.py +++ b/tests/data/expected/main_kr/main_allof_with_description_only/output.py @@ -8,14 +8,10 @@ class MyModel(BaseModel): - """ - A model that has a description. - """ + """A model that has a description.""" name: str | None = None class MyOtherModel(MyModel): - """ - Another model that should also have a description. - """ + """Another model that should also have a description.""" diff --git a/tests/data/expected/main_kr/main_docstring_special_chars/output.py b/tests/data/expected/main_kr/main_docstring_special_chars/output.py index fe46e1628..b94c05ea5 100644 --- a/tests/data/expected/main_kr/main_docstring_special_chars/output.py +++ b/tests/data/expected/main_kr/main_docstring_special_chars/output.py @@ -8,41 +8,27 @@ class ExampleWithBackslash(BaseModel): - """ - Observe the backslash \\ in this line - """ + """Observe the backslash \\ in this line""" name: str | None = None - """ - Path like C:\\Users\\name - """ + """Path like C:\\Users\\name""" class ExampleWithTripleQuotes(BaseModel): - """ - Contains \"\"\"triple quotes\"\"\" - """ + """Contains \"\"\"triple quotes\"\"\" """ value: str | None = None - """ - Field with \"\"\"quotes\"\"\" - """ + """Field with \"\"\"quotes\"\"\" """ class ExampleWithBoth(BaseModel): - """ - Has both \\ backslash and \"\"\"quotes\"\"\" - """ + """Has both \\ backslash and \"\"\"quotes\"\"\" """ data: str | None = None - """ - Data: C:\\path\\to\\\"\"\"file\"\"\" - """ + """Data: C:\\path\\to\\\"\"\"file\"\"\" """ class ExampleWithNewlineEscape(BaseModel): - """ - Text with \\n which looks like newline escape - """ + """Text with \\n which looks like newline escape""" text: str | None = None diff --git a/tests/data/expected/main_kr/main_use_field_description/output.py b/tests/data/expected/main_kr/main_use_field_description/output.py index 702db6dd6..d9136bec4 100644 --- a/tests/data/expected/main_kr/main_use_field_description/output.py +++ b/tests/data/expected/main_kr/main_use_field_description/output.py @@ -47,17 +47,11 @@ class Api(BaseModel): Now also with multi-line docstrings. """ apiVersionNumber: str | None = None - """ - To be used as a version parameter value - """ + """To be used as a version parameter value""" apiUrl: AnyUrl | None = None - """ - The URL describing the dataset's fields - """ + """The URL describing the dataset's fields""" apiDocumentationUrl: AnyUrl | None = None - """ - A URL to the API console for each API - """ + """A URL to the API console for each API""" class Apis(RootModel[list[Api]]): diff --git a/tests/data/expected/main_kr/main_use_field_description_example/output.py b/tests/data/expected/main_kr/main_use_field_description_example/output.py index 0cc0401a1..ddac79c75 100644 --- a/tests/data/expected/main_kr/main_use_field_description_example/output.py +++ b/tests/data/expected/main_kr/main_use_field_description_example/output.py @@ -9,9 +9,7 @@ class Extras(BaseModel): name: str | None = Field(None, description='normal key', examples=['example']) - """ - Example: 'example' - """ + """Example: 'example'""" age: int | None = Field(None, examples=[13, 20], json_schema_extra={'example': 12}) """ Examples: @@ -19,6 +17,4 @@ class Extras(BaseModel): - 20 """ status: str | None = Field(None, examples=['active']) - """ - Example: 'active' - """ + """Example: 'active'""" diff --git a/tests/data/expected/main_kr/main_use_field_description_example_dataclass/output.py b/tests/data/expected/main_kr/main_use_field_description_example_dataclass/output.py index f00f58f11..4ba38d523 100644 --- a/tests/data/expected/main_kr/main_use_field_description_example_dataclass/output.py +++ b/tests/data/expected/main_kr/main_use_field_description_example_dataclass/output.py @@ -10,6 +10,4 @@ @dataclass class SingleLineDescriptionWithExample: name: str | None = None - """ - Example: 'John Doe' - """ + """Example: 'John Doe'""" diff --git a/tests/data/expected/main_kr/main_use_field_description_with_example/output.py b/tests/data/expected/main_kr/main_use_field_description_with_example/output.py index 5a56077b8..121f5d6fb 100644 --- a/tests/data/expected/main_kr/main_use_field_description_with_example/output.py +++ b/tests/data/expected/main_kr/main_use_field_description_with_example/output.py @@ -21,6 +21,4 @@ class Extras(BaseModel): - 20 """ status: str | None = Field(None, examples=['active']) - """ - Example: 'active' - """ + """Example: 'active'""" diff --git a/tests/data/expected/main_kr/main_use_inline_field_description_example_only/output.py b/tests/data/expected/main_kr/main_use_inline_field_description_example_only/output.py index c6b7e405c..203f1c37c 100644 --- a/tests/data/expected/main_kr/main_use_inline_field_description_example_only/output.py +++ b/tests/data/expected/main_kr/main_use_inline_field_description_example_only/output.py @@ -9,6 +9,4 @@ class SingleLineDescriptionWithExample(BaseModel): name: str | None = Field(None, description='User name.', examples=['John Doe']) - """ - Example: 'John Doe' - """ + """Example: 'John Doe'""" diff --git a/tests/data/expected/main_kr/main_use_schema_description/output.py b/tests/data/expected/main_kr/main_use_schema_description/output.py index 62c2564ec..0e2802f11 100644 --- a/tests/data/expected/main_kr/main_use_schema_description/output.py +++ b/tests/data/expected/main_kr/main_use_schema_description/output.py @@ -66,9 +66,7 @@ class Apis(RootModel[list[Api]]): class Event(BaseModel): - """ - Event object - """ + """Event object""" name: str | None = None diff --git a/tests/data/expected/parser/graphql/field-default-enum.py b/tests/data/expected/parser/graphql/field-default-enum.py index b4adcfb21..5c44f7dc9 100644 --- a/tests/data/expected/parser/graphql/field-default-enum.py +++ b/tests/data/expected/parser/graphql/field-default-enum.py @@ -11,15 +11,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Color(Enum): diff --git a/tests/data/expected/parser/graphql/no_typename.py b/tests/data/expected/parser/graphql/no_typename.py index 5a8598d00..6f6f77a8b 100644 --- a/tests/data/expected/parser/graphql/no_typename.py +++ b/tests/data/expected/parser/graphql/no_typename.py @@ -8,21 +8,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" ID = TypeAliasType("ID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class Node(BaseModel): diff --git a/tests/data/expected/parser/graphql/union-aliased-bug.py b/tests/data/expected/parser/graphql/union-aliased-bug.py index 411cf3f13..2c19734d6 100644 --- a/tests/data/expected/parser/graphql/union-aliased-bug.py +++ b/tests/data/expected/parser/graphql/union-aliased-bug.py @@ -10,15 +10,11 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class GroupMetadata(BaseModel): diff --git a/tests/data/expected/parser/graphql/union-commented.py b/tests/data/expected/parser/graphql/union-commented.py index e7124330f..84dd10362 100644 --- a/tests/data/expected/parser/graphql/union-commented.py +++ b/tests/data/expected/parser/graphql/union-commented.py @@ -10,21 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" String = TypeAliasType("String", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class GroupMetadata(BaseModel): - """ - This is a test comment in a single line - """ + """This is a test comment in a single line""" name: String typename__: Literal['GroupMetadata'] | None = Field( diff --git a/tests/data/expected/parser/graphql/union_with_prefix.py b/tests/data/expected/parser/graphql/union_with_prefix.py index 7486c6233..da4207d53 100644 --- a/tests/data/expected/parser/graphql/union_with_prefix.py +++ b/tests/data/expected/parser/graphql/union_with_prefix.py @@ -10,27 +10,19 @@ from typing_extensions import TypeAliasType FooBoolean = TypeAliasType("FooBoolean", bool) -""" -The `Boolean` scalar type represents `true` or `false`. -""" +"""The `Boolean` scalar type represents `true` or `false`.""" FooID = TypeAliasType("FooID", str) -""" -The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. -""" +"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" FooInt = TypeAliasType("FooInt", int) -""" -The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. -""" +"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" FooString = TypeAliasType("FooString", str) -""" -The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. -""" +"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" class FooIResource(BaseModel): From 5a0ea266985d530d00fd3a70281c552c7747fa37 Mon Sep 17 00:00:00 2001 From: Kevin Paulson Date: Tue, 28 Apr 2026 17:23:39 -0400 Subject: [PATCH 7/9] Minor changes after initial review --- src/datamodel_code_generator/model/base.py | 7 +++---- .../model/template/ScalarTypeStatement.jinja2 | 2 +- .../model/template/TypeStatement.jinja2 | 2 +- .../data/templates_schema_id/pydantic_v2/BaseModel.jinja2 | 8 ++------ 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/datamodel_code_generator/model/base.py b/src/datamodel_code_generator/model/base.py index 2c5d085d0..e475f3146 100644 --- a/src/datamodel_code_generator/model/base.py +++ b/src/datamodel_code_generator/model/base.py @@ -84,10 +84,7 @@ def format_docstring(value: str | None, indent_spaces: int = 0) -> str: Returns: Empty string when `value` is falsy; otherwise the docstring block. """ - if not value: - return "" - - value = value.strip() + value = (value or "").strip() if not value: return "" @@ -490,6 +487,7 @@ def _get_environment(template_subdir: Path, custom_template_dir: Path | None) -> loader=loader, autoescape=select_autoescape(["html", "xml"]), ) + env.filters["escape_docstring"] = escape_docstring # For old custom templates env.filters["format_docstring"] = format_docstring return env @@ -523,6 +521,7 @@ def _get_environment_with_absolute_path(absolute_template_dir: Path, builtin_sub loader=ChoiceLoader(loaders), autoescape=select_autoescape(["html", "xml"]), ) + env.filters["escape_docstring"] = escape_docstring # For old custom templates env.filters["format_docstring"] = format_docstring return env diff --git a/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 index 09151a300..7b6798814 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 @@ -1,4 +1,4 @@ type {{ class_name }} = {{ py_type }} {%- if description %} {{ description | format_docstring(0) }} -{%- endif %} \ No newline at end of file +{%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypeStatement.jinja2 b/src/datamodel_code_generator/model/template/TypeStatement.jinja2 index 7ce1bd9fa..9c10a2c4a 100644 --- a/src/datamodel_code_generator/model/template/TypeStatement.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeStatement.jinja2 @@ -20,4 +20,4 @@ type {{ class_name }} = {{ base_class }}{% if comment is defined %} # {{ commen {%- if description %} {{ description | format_docstring(0) }} {%- endif %} -{%- endif %} \ No newline at end of file +{%- endif %} diff --git a/tests/data/templates_schema_id/pydantic_v2/BaseModel.jinja2 b/tests/data/templates_schema_id/pydantic_v2/BaseModel.jinja2 index 30f897675..a3501a0fc 100644 --- a/tests/data/templates_schema_id/pydantic_v2/BaseModel.jinja2 +++ b/tests/data/templates_schema_id/pydantic_v2/BaseModel.jinja2 @@ -11,9 +11,7 @@ an alias for Bar: every pydantic model class consumes considerable memory. #} {% endfor -%} class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} - """ - {{ description | escape_docstring | indent(4) }} - """ + {{ description | format_docstring(4) }} {%- endif %} {%- if schema_id is defined and schema_id %} __schema_id__ = "{{ schema_id }}" @@ -43,9 +41,7 @@ class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comme {%- endif -%} {%- endif %} {%- if field.docstring %} - """ - {{ field.docstring | escape_docstring | indent(4) }} - """ + {{ field.docstring | format_docstring(4) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} From 6398d9440330cdb34a6db8ed85252a2e3d198dc3 Mon Sep 17 00:00:00 2001 From: Kevin Paulson Date: Tue, 28 Apr 2026 17:29:55 -0400 Subject: [PATCH 8/9] inline_field_docstring to use same logic --- src/datamodel_code_generator/model/base.py | 7 ++++--- tests/model/test_base.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/datamodel_code_generator/model/base.py b/src/datamodel_code_generator/model/base.py index e475f3146..2f1a1b760 100644 --- a/src/datamodel_code_generator/model/base.py +++ b/src/datamodel_code_generator/model/base.py @@ -389,9 +389,10 @@ def inline_field_docstring(self) -> str | None: """Get the inline docstring for this field if single-line.""" if self.use_inline_field_description: description = self.extras.get("description", None) - if description is not None and "\n" not in description: - escaped = escape_docstring(description) - return f'"""{escaped}"""' + docstring = format_docstring(description, 0) + if docstring: + return docstring + return None @property diff --git a/tests/model/test_base.py b/tests/model/test_base.py index 2a0fbfe1e..c849ff381 100644 --- a/tests/model/test_base.py +++ b/tests/model/test_base.py @@ -417,7 +417,7 @@ def test_inline_field_docstring_escapes_triple_quotes() -> None: extras={"description": 'Contains """quotes"""'}, use_inline_field_description=True, ) - assert field.inline_field_docstring == r'"""Contains \"\"\"quotes\"\"\""""' + assert field.inline_field_docstring == r'"""Contains \"\"\"quotes\"\"\" """' def test_data_type_manager_unknown_type_raises_error() -> None: From caf9e5f55fdb75aeaf97762fcdf2c0e5f154e83c Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 2 May 2026 07:45:56 +0000 Subject: [PATCH 9/9] Add single-line docstring option --- docs/cli-reference/field-customization.md | 79 ++++++++++++++ docs/cli-reference/index.md | 3 +- docs/cli-reference/quick-reference.md | 2 + src/datamodel_code_generator/__init__.py | 1 + src/datamodel_code_generator/__main__.py | 2 + .../_types/generate_config_dict.py | 1 + .../_types/parser_config_dicts.py | 1 + src/datamodel_code_generator/arguments.py | 6 ++ src/datamodel_code_generator/cli_options.py | 1 + src/datamodel_code_generator/config.py | 2 + src/datamodel_code_generator/model/base.py | 100 ++++++++++++++---- .../pydantic_v2/root_model_type_alias.py | 2 + .../model/template/Enum.jinja2 | 4 +- .../template/ScalarTypeAliasAnnotation.jinja2 | 2 +- .../model/template/ScalarTypeAliasType.jinja2 | 2 +- .../model/template/ScalarTypeStatement.jinja2 | 2 +- .../model/template/TypeAliasAnnotation.jinja2 | 6 +- .../model/template/TypeAliasType.jinja2 | 6 +- .../model/template/TypeStatement.jinja2 | 6 +- .../model/template/TypedDictClass.jinja2 | 4 +- .../model/template/TypedDictFunction.jinja2 | 4 +- .../model/template/dataclass.jinja2 | 4 +- .../model/template/msgspec.jinja2 | 4 +- .../template/pydantic_v2/BaseModel.jinja2 | 4 +- .../template/pydantic_v2/RootModel.jinja2 | 4 +- .../pydantic_v2/RootModelTypeAlias.jinja2 | 4 +- .../template/pydantic_v2/dataclass.jinja2 | 4 +- .../model/type_alias.py | 2 + .../model/typed_dict.py | 5 +- src/datamodel_code_generator/model/union.py | 2 + src/datamodel_code_generator/parser/base.py | 3 + src/datamodel_code_generator/prompt_data.py | 1 + .../main/graphql/additional_imports.py | 12 ++- tests/data/expected/main/graphql/annotated.py | 8 +- .../main/graphql/annotated_field_aliases.py | 8 +- .../graphql/annotated_use_default_kwarg.py | 8 +- .../annotated_use_standard_collections.py | 8 +- ...standard_collections_use_union_operator.py | 8 +- .../graphql/annotated_use_union_operator.py | 8 +- tests/data/expected/main/graphql/casing.py | 12 ++- .../main/graphql/custom_formatters.py | 12 ++- .../main/graphql/custom_scalar_types.py | 12 ++- .../default_values_required_use_default.py | 12 ++- .../main/graphql/different_types_of_fields.py | 8 +- .../main/graphql/empty_list_default.py | 8 +- .../main/graphql/enum_literals_all.py | 12 ++- .../main/graphql/enum_literals_one.py | 12 ++- tests/data/expected/main/graphql/enums.py | 12 ++- .../graphql/enums_ignore_enum_constraints.py | 12 ++- .../main/graphql/enums_no_specialized.py | 12 ++- .../main/graphql/enums_specialized.py | 12 ++- .../expected/main/graphql/enums_typed_dict.py | 12 ++- .../main/graphql/enums_using_subclass.py | 12 ++- .../expected/main/graphql/field_aliases.py | 8 +- .../graphql_multiple_aliases_pydantic_v2.py | 8 +- .../expected/main/graphql/interface_mro.py | 12 ++- .../data/expected/main/graphql/no_typename.py | 12 ++- .../graphql/pydantic_v2_empty_list_default.py | 8 +- .../expected/main/graphql/simple_star_wars.py | 16 ++- .../simple_star_wars_class_name_prefix.py | 16 ++- .../graphql/simple_star_wars_dataclass.py | 16 ++- .../simple_star_wars_dataclass_arguments.py | 16 ++- ...mple_star_wars_dataclass_frozen_kw_only.py | 16 ++- .../simple_star_wars_extra_fields_allow.py | 16 ++- .../main/graphql/split_graphql_schemas.py | 12 ++- .../data/expected/main/graphql/type_alias.py | 12 ++- .../expected/main/graphql/type_alias_py312.py | 12 ++- tests/data/expected/main/graphql/union.py | 16 ++- .../main/graphql/union_class_name_prefix.py | 16 ++- .../main/graphql/union_snake_case_field.py | 16 ++- .../main/graphql/use_standard_collections.py | 8 +- .../main/graphql/use_union_operator.py | 8 +- tests/data/expected/main/help/color.txt | 3 + tests/data/expected/main/help/no_color.txt | 3 + .../expected/main/input_model/config_class.py | 1 + .../expected/main/jsonschema/allof_mro.py | 4 +- .../type_alias_with_field_description.py | 4 +- ...type_alias_with_field_description_py312.py | 4 +- .../main/openapi/all_of_with_relative_ref.py | 8 +- .../main/openapi/allof_array_ref_override.py | 4 +- .../expected/main/use_attribute_docstrings.py | 8 +- .../main/use_single_line_docstring.py | 20 ++++ .../main_kr/generate_prompt/basic.txt | 4 + .../generate_prompt/with_list_options.txt | 4 + .../main_kr/generate_prompt/with_options.txt | 4 + .../main_kr/generate_prompt/with_question.txt | 4 + .../main_kr/help_shows_new_options.txt | 3 + .../output.py | 8 +- .../main_docstring_special_chars/output.py | 28 +++-- .../main_use_field_description/output.py | 12 ++- .../output.py | 8 +- .../output.py | 4 +- .../output.py | 4 +- .../output.py | 4 +- .../main_use_schema_description/output.py | 4 +- .../parser/graphql/field-default-enum.py | 8 +- .../expected/parser/graphql/no_typename.py | 12 ++- .../parser/graphql/union-aliased-bug.py | 8 +- .../parser/graphql/union-commented.py | 12 ++- .../parser/graphql/union_with_prefix.py | 16 ++- .../pydantic_v2/BaseModel.jinja2 | 4 +- tests/main/test_main_general.py | 54 ++++++++++ .../test_public_api_signature_baseline.py | 2 + tests/model/test_base.py | 34 +++++- 104 files changed, 824 insertions(+), 213 deletions(-) create mode 100644 tests/data/expected/main/use_single_line_docstring.py diff --git a/docs/cli-reference/field-customization.md b/docs/cli-reference/field-customization.md index 1c9dbc872..041685965 100644 --- a/docs/cli-reference/field-customization.md +++ b/docs/cli-reference/field-customization.md @@ -27,6 +27,7 @@ | [`--use-inline-field-description`](#use-inline-field-description) | Add field descriptions as inline comments. | | [`--use-schema-description`](#use-schema-description) | Use schema description as class docstring. | | [`--use-serialization-alias`](#use-serialization-alias) | Use serialization_alias instead of alias for field aliasing ... | +| [`--use-single-line-docstring`](#use-single-line-docstring) | Emit short docstrings on a single line. | | [`--use-title-as-name`](#use-title-as-name) | Use schema title as the generated class name. | --- @@ -3527,6 +3528,84 @@ serializing to the original JSON property name. --- +## `--use-single-line-docstring` {#use-single-line-docstring} + +Emit short docstrings on a single line. + +The `--use-single-line-docstring` flag formats docstrings that fit on one line +as compact single-line docstrings while keeping the historical multi-line +format as the default. + +**Related:** [`--use-field-description`](field-customization.md#use-field-description), [`--use-schema-description`](field-customization.md#use-schema-description) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-field-description --use-single-line-docstring # (1)! + ``` + + 1. :material-arrow-left: `--use-single-line-docstring` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": ["string", "null"], + "description": "The person's last name." + }, + "age": { + "description": "Age in years which must be equal to or greater than zero.", + "type": "integer", + "minimum": 0 + }, + "friends": { + "type": "array" + }, + "comment": { + "type": "null" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: person.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel, conint + + + class Person(BaseModel): + firstName: str | None = None + """The person's first name.""" + lastName: str | None = None + """The person's last name.""" + age: conint(ge=0) | None = None + """Age in years which must be equal to or greater than zero.""" + friends: list[Any] | None = None + comment: None = None + ``` + +--- + ## `--use-title-as-name` {#use-title-as-name} Use schema title as the generated class name. diff --git a/docs/cli-reference/index.md b/docs/cli-reference/index.md index d481179dc..8d9a9d951 100644 --- a/docs/cli-reference/index.md +++ b/docs/cli-reference/index.md @@ -10,7 +10,7 @@ This documentation is auto-generated from test cases. |----------|---------|-------------| | 📁 [Base Options](base-options.md) | 10 | Input/output configuration | | 🔧 [Typing Customization](typing-customization.md) | 29 | Type annotation and import behavior | -| 🏷️ [Field Customization](field-customization.md) | 24 | Field naming and docstring behavior | +| 🏷️ [Field Customization](field-customization.md) | 25 | Field naming and docstring behavior | | 🏗️ [Model Customization](model-customization.md) | 39 | Model generation behavior | | 🎨 [Template Customization](template-customization.md) | 21 | Output formatting and custom rendering | | 📘 [OpenAPI-only Options](openapi-only-options.md) | 7 | OpenAPI-specific features | @@ -212,6 +212,7 @@ This documentation is auto-generated from test cases. - [`--use-schema-description`](field-customization.md#use-schema-description) - [`--use-serialization-alias`](field-customization.md#use-serialization-alias) - [`--use-serialize-as-any`](model-customization.md#use-serialize-as-any) +- [`--use-single-line-docstring`](field-customization.md#use-single-line-docstring) - [`--use-specialized-enum`](typing-customization.md#use-specialized-enum) - [`--use-standard-collections`](typing-customization.md#use-standard-collections) - [`--use-standard-primitive-types`](typing-customization.md#use-standard-primitive-types) diff --git a/docs/cli-reference/quick-reference.md b/docs/cli-reference/quick-reference.md index 95acfb3d6..64c41f6e2 100644 --- a/docs/cli-reference/quick-reference.md +++ b/docs/cli-reference/quick-reference.md @@ -88,6 +88,7 @@ datamodel-codegen [OPTIONS] | [`--use-inline-field-description`](field-customization.md#use-inline-field-description) | Add field descriptions as inline comments. | | [`--use-schema-description`](field-customization.md#use-schema-description) | Use schema description as class docstring. | | [`--use-serialization-alias`](field-customization.md#use-serialization-alias) | Use serialization_alias instead of alias for field aliasing (Pydantic v2 only). | +| [`--use-single-line-docstring`](field-customization.md#use-single-line-docstring) | Emit short docstrings on a single line. | | [`--use-title-as-name`](field-customization.md#use-title-as-name) | Use schema title as the generated class name. | ### 🏗️ Model Customization @@ -352,6 +353,7 @@ All options sorted alphabetically: - [`--use-schema-description`](field-customization.md#use-schema-description) - Use schema description as class docstring. - [`--use-serialization-alias`](field-customization.md#use-serialization-alias) - Use serialization_alias instead of alias for field aliasing ... - [`--use-serialize-as-any`](model-customization.md#use-serialize-as-any) - Wrap fields with subtypes in Pydantic's SerializeAsAny. +- [`--use-single-line-docstring`](field-customization.md#use-single-line-docstring) - Emit short docstrings on a single line. - [`--use-specialized-enum`](typing-customization.md#use-specialized-enum) - Generate StrEnum/IntEnum for string/integer enums (Python 3.... - [`--use-standard-collections`](typing-customization.md#use-standard-collections) - Use built-in dict/list instead of typing.Dict/List. - [`--use-standard-primitive-types`](typing-customization.md#use-standard-primitive-types) - Use Python standard library types for string formats instead... diff --git a/src/datamodel_code_generator/__init__.py b/src/datamodel_code_generator/__init__.py index 131782028..11ec3ef5a 100644 --- a/src/datamodel_code_generator/__init__.py +++ b/src/datamodel_code_generator/__init__.py @@ -727,6 +727,7 @@ def get_header_and_first_line(csv_file: IO[str]) -> dict[str, Any]: "dataclass_arguments": dataclass_arguments, "defer_formatting": defer_formatting, "use_type_checking_imports": config.use_type_checking_imports, + "use_single_line_docstring": config.use_single_line_docstring, "enum_field_as_literal": ( config.enum_field_as_literal if config.enum_field_as_literal is not None diff --git a/src/datamodel_code_generator/__main__.py b/src/datamodel_code_generator/__main__.py index e7225ea13..98e5f7bd0 100644 --- a/src/datamodel_code_generator/__main__.py +++ b/src/datamodel_code_generator/__main__.py @@ -453,6 +453,7 @@ def validate_class_name_affix_scope(cls, v: str | ClassNameAffixScope | None) -> use_field_description_example: bool = False use_attribute_docstrings: bool = False use_inline_field_description: bool = False + use_single_line_docstring: bool = False use_default_kwarg: bool = False reuse_model: bool = False reuse_scope: ReuseScope = ReuseScope.Module @@ -906,6 +907,7 @@ def run_generate_from_config( # noqa: PLR0913, PLR0917 use_field_description_example=config.use_field_description_example, use_attribute_docstrings=config.use_attribute_docstrings, use_inline_field_description=config.use_inline_field_description, + use_single_line_docstring=config.use_single_line_docstring, use_default_kwarg=config.use_default_kwarg, reuse_model=config.reuse_model, reuse_scope=config.reuse_scope, diff --git a/src/datamodel_code_generator/_types/generate_config_dict.py b/src/datamodel_code_generator/_types/generate_config_dict.py index c0c278d10..f95200b1b 100644 --- a/src/datamodel_code_generator/_types/generate_config_dict.py +++ b/src/datamodel_code_generator/_types/generate_config_dict.py @@ -78,6 +78,7 @@ class GenerateConfigDict(TypedDict, closed=True): use_field_description_example: NotRequired[bool] use_attribute_docstrings: NotRequired[bool] use_inline_field_description: NotRequired[bool] + use_single_line_docstring: NotRequired[bool] use_default_kwarg: NotRequired[bool] reuse_model: NotRequired[bool] reuse_scope: NotRequired[ReuseScope] diff --git a/src/datamodel_code_generator/_types/parser_config_dicts.py b/src/datamodel_code_generator/_types/parser_config_dicts.py index c99912474..1665e4f0c 100644 --- a/src/datamodel_code_generator/_types/parser_config_dicts.py +++ b/src/datamodel_code_generator/_types/parser_config_dicts.py @@ -79,6 +79,7 @@ class ParserConfigDict(TypedDict): use_field_description_example: NotRequired[bool] use_attribute_docstrings: NotRequired[bool] use_inline_field_description: NotRequired[bool] + use_single_line_docstring: NotRequired[bool] use_default_kwarg: NotRequired[bool] reuse_model: NotRequired[bool] reuse_scope: NotRequired[ReuseScope | None] diff --git a/src/datamodel_code_generator/arguments.py b/src/datamodel_code_generator/arguments.py index 7c8f7a7a0..1bd3f5cc3 100644 --- a/src/datamodel_code_generator/arguments.py +++ b/src/datamodel_code_generator/arguments.py @@ -853,6 +853,12 @@ def start_section(self, heading: str | None) -> None: action="store_true", default=None, ) +field_options.add_argument( + "--use-single-line-docstring", + help="Use single-line docstrings when the content fits on one line", + action="store_true", + default=None, +) field_options.add_argument( "--union-mode", help="Union mode for only pydantic v2 field", diff --git a/src/datamodel_code_generator/cli_options.py b/src/datamodel_code_generator/cli_options.py index ad64860d3..267f28f95 100644 --- a/src/datamodel_code_generator/cli_options.py +++ b/src/datamodel_code_generator/cli_options.py @@ -156,6 +156,7 @@ class CLIOptionMeta: "--use-inline-field-description": CLIOptionMeta( name="--use-inline-field-description", category=OptionCategory.FIELD ), + "--use-single-line-docstring": CLIOptionMeta(name="--use-single-line-docstring", category=OptionCategory.FIELD), "--field-constraints": CLIOptionMeta(name="--field-constraints", category=OptionCategory.FIELD), "--field-extra-keys": CLIOptionMeta(name="--field-extra-keys", category=OptionCategory.FIELD), "--field-extra-keys-without-x-prefix": CLIOptionMeta( diff --git a/src/datamodel_code_generator/config.py b/src/datamodel_code_generator/config.py index 4bd1ed9a3..5b82c4459 100644 --- a/src/datamodel_code_generator/config.py +++ b/src/datamodel_code_generator/config.py @@ -103,6 +103,7 @@ class GenerateConfig(BaseModel): use_field_description_example: bool = False use_attribute_docstrings: bool = False use_inline_field_description: bool = False + use_single_line_docstring: bool = False use_default_kwarg: bool = False reuse_model: bool = False reuse_scope: ReuseScope = ReuseScope.Module @@ -242,6 +243,7 @@ class ParserConfig(BaseModel): use_field_description_example: bool = False use_attribute_docstrings: bool = False use_inline_field_description: bool = False + use_single_line_docstring: bool = False use_default_kwarg: bool = False reuse_model: bool = False reuse_scope: ReuseScope | None = None diff --git a/src/datamodel_code_generator/model/base.py b/src/datamodel_code_generator/model/base.py index 6b2695efb..a33233aca 100644 --- a/src/datamodel_code_generator/model/base.py +++ b/src/datamodel_code_generator/model/base.py @@ -7,7 +7,6 @@ from __future__ import annotations import re -import textwrap from abc import ABC, abstractmethod from collections import defaultdict from copy import deepcopy @@ -67,38 +66,66 @@ def escape_docstring(value: str | None) -> str | None: return value.replace("\\", "\\\\").replace('"""', '\\"\\"\\"') -def format_docstring(value: str | None, indent_spaces: int = 0) -> str: +def _ends_with_unescaped_quote(value: str) -> bool: + """Return whether *value* ends with a double quote that is not escaped.""" + if not value.endswith('"'): + return False + + backslash_count = 0 + for char in reversed(value[:-1]): + if char != "\\": + break + backslash_count += 1 + return backslash_count % 2 == 0 + + +def format_docstring(value: str | None, indent_spaces: int = 0, *, use_single_line_docstring: bool = False) -> str: """Format *value* as a docstring as per PEP 257. PEP 257 recommends that docstrings that can fit on one line should be formatted on a - single line, for consistency and readability. Leading and trailing whitespace will - be removed, and if after this the value is falsy, an empty string is returned. It is - assumed that the opening triple-quotes are indented appropriately in the template. - If it's a multi-line docstring, each line including the closing triple-quotes will - be indented as per indent_spaces. + single line, for consistency and readability. When use_single_line_docstring is + false, docstrings retain the historical multi-line formatting. It is assumed that + the opening triple-quotes are indented appropriately in the template. If it's a + multi-line docstring, each line including the closing triple-quotes will be indented + as per indent_spaces. Args: value: docstring text indent_spaces: Spaces to indent for all lines after the opening triple-quotes + use_single_line_docstring: Use one-line docstrings when possible Returns: Empty string when `value` is falsy; otherwise the docstring block. """ - value = (value or "").strip() - - if not value: + if value is None or not value.strip(): return "" - escaped = escape_docstring(value) + escaped = escape_docstring(value) or "" - if len(value.splitlines()) == 1: - if escaped.endswith('"'): - escaped = f"{escaped} " + if use_single_line_docstring and "\n" not in value and "\r" not in value: + if _ends_with_unescaped_quote(escaped): + escaped = f'{escaped[:-1]}\\"' return f'"""{escaped}"""' - indent_text = textwrap.indent(f'{escaped}\n"""', max(indent_spaces, 0) * " ") - return f'"""\n{indent_text}' + indent = max(indent_spaces, 0) * " " + if indent: + escaped = "\n".join(f"{indent}{line}" if line else "" for line in escaped.split("\n")) + return f'"""\n{escaped}\n{indent}"""' + return f'"""\n{escaped}\n"""' + + +class _RenderedDataModelField: + """Proxy a field with a pre-rendered docstring for built-in templates.""" + + __slots__ = ("_field", "docstring") + + def __init__(self, field: DataModelFieldBase, docstring: str) -> None: + self._field = field + self.docstring = docstring + + def __getattr__(self, name: str) -> Any: + return getattr(self._field, name) ALL_MODEL: str = "#all#" @@ -390,9 +417,9 @@ def inline_field_docstring(self) -> str | None: """Get the inline docstring for this field if single-line.""" if self.use_inline_field_description: description = self.extras.get("description", None) - docstring = format_docstring(description, 0) - if docstring: - return docstring + if description is not None and "\n" not in description: + escaped = escape_docstring(description) + return f'"""{escaped}"""' return None @@ -636,6 +663,9 @@ class DataModel(TemplateBase, Nullable, ABC): # noqa: PLR0904 SUPPORTS_FIELD_RENAMING: ClassVar[bool] = False SUPPORTS_KW_ONLY: ClassVar[bool] = False REQUIRES_RUNTIME_IMPORTS_WITH_RUFF_CHECK: ClassVar[bool] = False + DOCSTRING_INDENT: ClassVar[int] = 4 + FIELD_DOCSTRING_INDENT: ClassVar[int] = 4 + FORMAT_DESCRIPTION_AS_DOCSTRING: ClassVar[bool] = True has_forward_reference: bool = False def __init__( # noqa: PLR0913 @@ -940,18 +970,46 @@ def set_reference_path(self, new_path: str) -> None: def render(self, *, class_name: str | None = None) -> str: """Render the model to a string using the template.""" + use_custom_template = self.template_file_path.is_absolute() return self._render( class_name=class_name or self.class_name, - fields=self.fields, + fields=self.fields if use_custom_template else self.rendered_fields, decorators=self.decorators, base_class=self.base_class, methods=self.methods, - description=self.description, + description=self.description + if use_custom_template or not self.FORMAT_DESCRIPTION_AS_DOCSTRING + else self.rendered_description, dataclass_arguments=self.dataclass_arguments, path=self.path, **self.extra_template_data, ) + @property + def use_single_line_docstring(self) -> bool: + """Whether single-line docstring formatting is enabled for this model.""" + return bool(self.extra_template_data.get("use_single_line_docstring")) + + def _format_docstring(self, value: str | None, indent_spaces: int) -> str: + return format_docstring( + value, + indent_spaces, + use_single_line_docstring=self.use_single_line_docstring, + ) + + @property + def rendered_description(self) -> str: + """Return the model description as a generated docstring literal.""" + return self._format_docstring(self.description, self.DOCSTRING_INDENT) + + @property + def rendered_fields(self) -> list[DataModelFieldBase | _RenderedDataModelField]: + """Return fields with docstrings prepared for built-in templates.""" + return [ + _RenderedDataModelField(field, self._format_docstring(field.docstring, self.FIELD_DOCSTRING_INDENT)) + for field in self.fields + ] + _rebuild_namespace = {"Union": Union, "DataModelFieldBase": DataModelFieldBase, "DataType": DataType} DataType.model_rebuild(_types_namespace=_rebuild_namespace) diff --git a/src/datamodel_code_generator/model/pydantic_v2/root_model_type_alias.py b/src/datamodel_code_generator/model/pydantic_v2/root_model_type_alias.py index 5674f69c4..97a5560c5 100644 --- a/src/datamodel_code_generator/model/pydantic_v2/root_model_type_alias.py +++ b/src/datamodel_code_generator/model/pydantic_v2/root_model_type_alias.py @@ -28,4 +28,6 @@ class RootModelTypeAlias(RootModel): TEMPLATE_FILE_PATH: ClassVar[str] = "pydantic_v2/RootModelTypeAlias.jinja2" IS_ALIAS: ClassVar[bool] = True + DOCSTRING_INDENT: ClassVar[int] = 0 + FIELD_DOCSTRING_INDENT: ClassVar[int] = 0 DEFAULT_IMPORTS: ClassVar[tuple[Import, ...]] = (IMPORT_ROOT_MODEL,) diff --git a/src/datamodel_code_generator/model/template/Enum.jinja2 b/src/datamodel_code_generator/model/template/Enum.jinja2 index 11c5f1e1d..7da31a3a5 100644 --- a/src/datamodel_code_generator/model/template/Enum.jinja2 +++ b/src/datamodel_code_generator/model/template/Enum.jinja2 @@ -3,12 +3,12 @@ {% endfor -%} class {{ class_name }}({{ base_class }}): {%- if description %} - {{ description | format_docstring(4) }} + {{ description }} {%- endif %} {%- for field in fields %} {{ field.name }} = {{ field.default }} {%- if field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 index 6fdb5bce9..adb65e94a 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeAliasAnnotation.jinja2 @@ -1,4 +1,4 @@ {{ class_name }}: TypeAlias = {{ py_type }} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 index f86a187ac..b319aa87a 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeAliasType.jinja2 @@ -1,4 +1,4 @@ {{ class_name }} = TypeAliasType("{{ class_name }}", {{ py_type }}) {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 b/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 index 7b6798814..81d26151f 100644 --- a/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 +++ b/src/datamodel_code_generator/model/template/ScalarTypeStatement.jinja2 @@ -1,4 +1,4 @@ type {{ class_name }} = {{ py_type }} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 b/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 index a6dac9efc..151828768 100644 --- a/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeAliasAnnotation.jinja2 @@ -11,13 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} {{ class_name }}: TypeAlias = {{ get_type_annotation(fields[0]) }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- elif fields[0].docstring %} -{{ fields[0].docstring | format_docstring(0) }} +{{ fields[0].docstring }} {%- endif %} {%- else %} {{ class_name }}: TypeAlias = {{ base_class }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- endif %} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 b/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 index ecde5b7eb..111dca508 100644 --- a/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeAliasType.jinja2 @@ -11,13 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} {{ class_name }} = TypeAliasType("{{ class_name }}", {{ get_type_annotation(fields[0]) }}){% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- elif fields[0].docstring %} -{{ fields[0].docstring | format_docstring(0) }} +{{ fields[0].docstring }} {%- endif %} {%- else %} {{ class_name }} = TypeAliasType("{{ class_name }}", {{ base_class }}){% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- endif %} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypeStatement.jinja2 b/src/datamodel_code_generator/model/template/TypeStatement.jinja2 index 9c10a2c4a..f1ea7d675 100644 --- a/src/datamodel_code_generator/model/template/TypeStatement.jinja2 +++ b/src/datamodel_code_generator/model/template/TypeStatement.jinja2 @@ -11,13 +11,13 @@ Annotated[{{ _field.type_hint }}, {{ _field.field }}] {%- if fields %} type {{ class_name }} = {{ get_type_annotation(fields[0]) }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- elif fields[0].docstring %} -{{ fields[0].docstring | format_docstring(0) }} +{{ fields[0].docstring }} {%- endif %} {%- else %} type {{ class_name }} = {{ base_class }}{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- endif %} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 b/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 index 6c531b298..f0c76ae82 100644 --- a/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 +++ b/src/datamodel_code_generator/model/template/TypedDictClass.jinja2 @@ -1,6 +1,6 @@ class {{ class_name }}({{ base_class }}): {%- if description %} - {{ description | format_docstring(4) }} + {{ description }} {%- endif %} {%- if not fields and not description %} pass @@ -8,7 +8,7 @@ class {{ class_name }}({{ base_class }}): {%- for field in fields %} {{ field.name }}: {{ field.type_hint }} {%- if field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 b/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 index b7d3f2454..82545f4e0 100644 --- a/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 +++ b/src/datamodel_code_generator/model/template/TypedDictFunction.jinja2 @@ -1,11 +1,11 @@ {%- if description %} - {{ description | format_docstring(4) }} + {{ description }} {%- endif %} {{ class_name }} = TypedDict('{{ class_name }}', { {%- for field in all_fields %} '{{ field.key }}': {{ field.type_hint }}, {%- if field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/dataclass.jinja2 b/src/datamodel_code_generator/model/template/dataclass.jinja2 index 015c8b78d..0460dcaa2 100644 --- a/src/datamodel_code_generator/model/template/dataclass.jinja2 +++ b/src/datamodel_code_generator/model/template/dataclass.jinja2 @@ -18,7 +18,7 @@ class {{ class_name }}({{ base_class }}): class {{ class_name }}: {%- endif %} {%- if description %} - {{ description | format_docstring(4) }} + {{ description }} {%- endif %} {%- if not fields and not description %} pass @@ -33,7 +33,7 @@ class {{ class_name }}: {%- endif -%} {%- endif %} {%- if field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/msgspec.jinja2 b/src/datamodel_code_generator/model/template/msgspec.jinja2 index fde328678..f1765b13f 100644 --- a/src/datamodel_code_generator/model/template/msgspec.jinja2 +++ b/src/datamodel_code_generator/model/template/msgspec.jinja2 @@ -9,7 +9,7 @@ class {{ class_name }}({{ base_class }}{%- for key, value in (base_class_kwargs| class {{ class_name }}: {%- endif %} {%- if description %} - {{ description | format_docstring(4) }} + {{ description }} {%- endif %} {%- set ns = namespace(has_rendered_field=false) -%} {%- for field in fields -%} @@ -35,7 +35,7 @@ class {{ class_name }}: {%- if not field.extras.get('is_classvar') and field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 index 67f945f6f..ae102e07b 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/BaseModel.jinja2 @@ -3,7 +3,7 @@ {% endfor -%} class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} - {{ description | format_docstring(4) }} + {{ description }} {%- endif %} {%- if not fields and not description and not config and not class_body_lines %} pass @@ -30,7 +30,7 @@ class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comme {%- endif -%} {%- endif %} {%- if field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 index aae81741a..446e8d122 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/RootModel.jinja2 @@ -18,7 +18,7 @@ {%- set use_base_type = config and config.regex_engine -%} class {{ class_name }}({{ base_class }}{%- if fields -%}[{{get_type_hint(fields, use_base_type)}}]{%- endif -%}):{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} - {{ description | format_docstring(4) }} + {{ description }} {%- endif %} {%- if config %} {%- filter indent(4) %} @@ -45,7 +45,7 @@ class {{ class_name }}({{ base_class }}{%- if fields -%}[{{get_type_hint(fields, {%- endif -%} {%- endif %} {%- if field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring }} {%- elif field.inline_field_docstring %} {{ field.inline_field_docstring }} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 index d8356ef03..95be3b71f 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/RootModelTypeAlias.jinja2 @@ -12,7 +12,7 @@ {%- set use_base_type = config and config.regex_engine -%} {{ class_name }} = RootModel[{{get_type_hint(fields, use_base_type)}}]{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} -{{ description | format_docstring(0) }} +{{ description }} {%- elif fields and fields[0].docstring %} -{{ fields[0].docstring | format_docstring(0) }} +{{ fields[0].docstring }} {%- endif %} diff --git a/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 b/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 index fda71980f..2ce858bf8 100644 --- a/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 +++ b/src/datamodel_code_generator/model/template/pydantic_v2/dataclass.jinja2 @@ -25,7 +25,7 @@ class {{ class_name }}({{ base_class }}): class {{ class_name }}: {%- endif %} {%- if description %} - {{ description | format_docstring(4) }} + {{ description }} {%- endif %} {%- if not fields and not description %} pass @@ -44,7 +44,7 @@ class {{ class_name }}: {%- endif -%} {%- endif %} {%- if field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/src/datamodel_code_generator/model/type_alias.py b/src/datamodel_code_generator/model/type_alias.py index 319b127cf..ff7e10360 100644 --- a/src/datamodel_code_generator/model/type_alias.py +++ b/src/datamodel_code_generator/model/type_alias.py @@ -23,6 +23,8 @@ class TypeAliasBase(DataModel): IS_ALIAS: ClassVar[bool] = True SUPPORTS_GENERIC_BASE_CLASS: ClassVar[bool] = False + DOCSTRING_INDENT: ClassVar[int] = 0 + FIELD_DOCSTRING_INDENT: ClassVar[int] = 0 @property def imports(self) -> tuple[Import, ...]: diff --git a/src/datamodel_code_generator/model/typed_dict.py b/src/datamodel_code_generator/model/typed_dict.py index afe1a7dd9..fb687163c 100644 --- a/src/datamodel_code_generator/model/typed_dict.py +++ b/src/datamodel_code_generator/model/typed_dict.py @@ -164,13 +164,14 @@ def all_fields(self) -> Iterator[DataModelFieldBase]: def render(self, *, class_name: str | None = None) -> str: """Render TypedDict class with appropriate syntax.""" + use_custom_template = self.template_file_path.is_absolute() return self._render( class_name=class_name or self.class_name, - fields=self.fields, + fields=self.fields if use_custom_template else self.rendered_fields, decorators=self.decorators, base_class=self.base_class, methods=self.methods, - description=self.description, + description=self.description if use_custom_template else self.rendered_description, is_functional_syntax=self.is_functional_syntax, all_fields=self.all_fields, **self.extra_template_data, diff --git a/src/datamodel_code_generator/model/union.py b/src/datamodel_code_generator/model/union.py index 1375c90fb..f2fabcdbf 100644 --- a/src/datamodel_code_generator/model/union.py +++ b/src/datamodel_code_generator/model/union.py @@ -26,6 +26,8 @@ class _DataTypeUnionBase(DataModel): """Base class for GraphQL union types with shared __init__ logic.""" + FORMAT_DESCRIPTION_AS_DOCSTRING: ClassVar[bool] = False + def __init__( # noqa: PLR0913 self, *, diff --git a/src/datamodel_code_generator/parser/base.py b/src/datamodel_code_generator/parser/base.py index ada2399b3..cc51863a0 100644 --- a/src/datamodel_code_generator/parser/base.py +++ b/src/datamodel_code_generator/parser/base.py @@ -985,6 +985,7 @@ def __init__( # noqa: PLR0912, PLR0915 self.use_field_description: bool = config.use_field_description self.use_field_description_example: bool = config.use_field_description_example self.use_inline_field_description: bool = config.use_inline_field_description + self.use_single_line_docstring: bool = config.use_single_line_docstring self.use_default_kwarg: bool = config.use_default_kwarg self.reuse_model: bool = config.reuse_model self.reuse_scope: ReuseScope | None = config.reuse_scope @@ -1068,6 +1069,8 @@ def __init__( # noqa: PLR0912, PLR0915 self.generic_base_class_config["use_attribute_docstrings"] = True else: self.extra_template_data[ALL_MODEL]["use_attribute_docstrings"] = True + if config.use_single_line_docstring: + self.extra_template_data[ALL_MODEL]["use_single_line_docstring"] = True if config.target_pydantic_version: if config.use_generic_base_class: diff --git a/src/datamodel_code_generator/prompt_data.py b/src/datamodel_code_generator/prompt_data.py index 21d442f9f..3dd5527f7 100644 --- a/src/datamodel_code_generator/prompt_data.py +++ b/src/datamodel_code_generator/prompt_data.py @@ -130,6 +130,7 @@ "--use-generic-base-class": "Generate a shared base class with model configuration to avoid repetition (DRY).", "--use-generic-container-types": "Use generic container types (Sequence, Mapping) for type hinting.", "--use-inline-field-description": "Add field descriptions as inline comments.", + "--use-single-line-docstring": "Use single-line docstrings when the content fits on one line.", "--use-non-positive-negative-number-constrained-types": "Use NonPositive/NonNegative types for number constraints.", "--use-one-literal-as-default": "Use single literal value as default when enum has only one option.", "--use-operation-id-as-name": "Use OpenAPI operationId as the generated function/class name.", diff --git a/tests/data/expected/main/graphql/additional_imports.py b/tests/data/expected/main/graphql/additional_imports.py index b2b03894e..f8f17778e 100644 --- a/tests/data/expected/main/graphql/additional_imports.py +++ b/tests/data/expected/main/graphql/additional_imports.py @@ -12,21 +12,27 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" Date = TypeAliasType("Date", date) DateTime = TypeAliasType("DateTime", datetime) -"""DateTime (ISO8601, example: 2020-01-01T10:11:12+00:00)""" +""" +DateTime (ISO8601, example: 2020-01-01T10:11:12+00:00) +""" MyCustomClass = TypeAliasType("MyCustomClass", MyCustomPythonClass) String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated.py b/tests/data/expected/main/graphql/annotated.py index 735fe6f3a..f86ff97ab 100644 --- a/tests/data/expected/main/graphql/annotated.py +++ b/tests/data/expected/main/graphql/annotated.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_field_aliases.py b/tests/data/expected/main/graphql/annotated_field_aliases.py index 0c3197d1d..bda775eaa 100644 --- a/tests/data/expected/main/graphql/annotated_field_aliases.py +++ b/tests/data/expected/main/graphql/annotated_field_aliases.py @@ -10,14 +10,18 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" DateTime = TypeAliasType("DateTime", str) String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class DateTimePeriod(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_use_default_kwarg.py b/tests/data/expected/main/graphql/annotated_use_default_kwarg.py index b26d561a3..ff90d9acb 100644 --- a/tests/data/expected/main/graphql/annotated_use_default_kwarg.py +++ b/tests/data/expected/main/graphql/annotated_use_default_kwarg.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_use_standard_collections.py b/tests/data/expected/main/graphql/annotated_use_standard_collections.py index 735fe6f3a..f86ff97ab 100644 --- a/tests/data/expected/main/graphql/annotated_use_standard_collections.py +++ b/tests/data/expected/main/graphql/annotated_use_standard_collections.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_use_standard_collections_use_union_operator.py b/tests/data/expected/main/graphql/annotated_use_standard_collections_use_union_operator.py index 735fe6f3a..f86ff97ab 100644 --- a/tests/data/expected/main/graphql/annotated_use_standard_collections_use_union_operator.py +++ b/tests/data/expected/main/graphql/annotated_use_standard_collections_use_union_operator.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/annotated_use_union_operator.py b/tests/data/expected/main/graphql/annotated_use_union_operator.py index 735fe6f3a..f86ff97ab 100644 --- a/tests/data/expected/main/graphql/annotated_use_union_operator.py +++ b/tests/data/expected/main/graphql/annotated_use_union_operator.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/casing.py b/tests/data/expected/main/graphql/casing.py index cb76b1a1a..2fb3406c0 100644 --- a/tests/data/expected/main/graphql/casing.py +++ b/tests/data/expected/main/graphql/casing.py @@ -11,15 +11,21 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" Int = TypeAliasType("Int", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Lowercase(Enum): diff --git a/tests/data/expected/main/graphql/custom_formatters.py b/tests/data/expected/main/graphql/custom_formatters.py index 0c8be84ed..46e8a3070 100644 --- a/tests/data/expected/main/graphql/custom_formatters.py +++ b/tests/data/expected/main/graphql/custom_formatters.py @@ -11,18 +11,24 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Long = TypeAliasType("Long", str) String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/custom_scalar_types.py b/tests/data/expected/main/graphql/custom_scalar_types.py index 6c2b6d30f..22eb6bf3f 100644 --- a/tests/data/expected/main/graphql/custom_scalar_types.py +++ b/tests/data/expected/main/graphql/custom_scalar_types.py @@ -10,18 +10,24 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Long = TypeAliasType("Long", int) String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/default_values_required_use_default.py b/tests/data/expected/main/graphql/default_values_required_use_default.py index 554c378d0..6dc4c1b3b 100644 --- a/tests/data/expected/main/graphql/default_values_required_use_default.py +++ b/tests/data/expected/main/graphql/default_values_required_use_default.py @@ -10,15 +10,21 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class User(BaseModel): diff --git a/tests/data/expected/main/graphql/different_types_of_fields.py b/tests/data/expected/main/graphql/different_types_of_fields.py index 6a2eab555..28f2f2f9a 100644 --- a/tests/data/expected/main/graphql/different_types_of_fields.py +++ b/tests/data/expected/main/graphql/different_types_of_fields.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/empty_list_default.py b/tests/data/expected/main/graphql/empty_list_default.py index 07b5dcd4f..8def8a752 100644 --- a/tests/data/expected/main/graphql/empty_list_default.py +++ b/tests/data/expected/main/graphql/empty_list_default.py @@ -9,11 +9,15 @@ from pydantic import BaseModel, Field type Boolean = bool -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" type String = str -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Container(BaseModel): diff --git a/tests/data/expected/main/graphql/enum_literals_all.py b/tests/data/expected/main/graphql/enum_literals_all.py index 83b50032f..d242eafe2 100644 --- a/tests/data/expected/main/graphql/enum_literals_all.py +++ b/tests/data/expected/main/graphql/enum_literals_all.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Color(RootModel[Literal['BLUE', 'GREEN', 'RED']]): @@ -22,7 +26,9 @@ class Color(RootModel[Literal['BLUE', 'GREEN', 'RED']]): class EmployeeShiftStatus(RootModel[Literal['NOT_ON_SHIFT', 'ON_SHIFT']]): - """Employee shift status""" + """ + Employee shift status + """ root: Literal['NOT_ON_SHIFT', 'ON_SHIFT'] diff --git a/tests/data/expected/main/graphql/enum_literals_one.py b/tests/data/expected/main/graphql/enum_literals_one.py index a2033517f..dc8c62216 100644 --- a/tests/data/expected/main/graphql/enum_literals_one.py +++ b/tests/data/expected/main/graphql/enum_literals_one.py @@ -11,11 +11,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Color(Enum): @@ -25,7 +29,9 @@ class Color(Enum): class EmployeeShiftStatus(Enum): - """Employee shift status""" + """ + Employee shift status + """ NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/enums.py b/tests/data/expected/main/graphql/enums.py index d15a54f73..97e952c3e 100644 --- a/tests/data/expected/main/graphql/enums.py +++ b/tests/data/expected/main/graphql/enums.py @@ -9,11 +9,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Color(Enum): @@ -23,7 +27,9 @@ class Color(Enum): class EmployeeShiftStatus(Enum): - """Employee shift status""" + """ + Employee shift status + """ NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/enums_ignore_enum_constraints.py b/tests/data/expected/main/graphql/enums_ignore_enum_constraints.py index 5d9a233fa..7e374b61c 100644 --- a/tests/data/expected/main/graphql/enums_ignore_enum_constraints.py +++ b/tests/data/expected/main/graphql/enums_ignore_enum_constraints.py @@ -8,11 +8,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Color(RootModel[str]): @@ -20,7 +24,9 @@ class Color(RootModel[str]): class EmployeeShiftStatus(RootModel[str]): - """Employee shift status""" + """ + Employee shift status + """ root: str diff --git a/tests/data/expected/main/graphql/enums_no_specialized.py b/tests/data/expected/main/graphql/enums_no_specialized.py index d15a54f73..97e952c3e 100644 --- a/tests/data/expected/main/graphql/enums_no_specialized.py +++ b/tests/data/expected/main/graphql/enums_no_specialized.py @@ -9,11 +9,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Color(Enum): @@ -23,7 +27,9 @@ class Color(Enum): class EmployeeShiftStatus(Enum): - """Employee shift status""" + """ + Employee shift status + """ NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/enums_specialized.py b/tests/data/expected/main/graphql/enums_specialized.py index a04c6ca72..40d7f5aa0 100644 --- a/tests/data/expected/main/graphql/enums_specialized.py +++ b/tests/data/expected/main/graphql/enums_specialized.py @@ -9,11 +9,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Color(StrEnum): @@ -23,7 +27,9 @@ class Color(StrEnum): class EmployeeShiftStatus(StrEnum): - """Employee shift status""" + """ + Employee shift status + """ NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/enums_typed_dict.py b/tests/data/expected/main/graphql/enums_typed_dict.py index bbca67530..998360baf 100644 --- a/tests/data/expected/main/graphql/enums_typed_dict.py +++ b/tests/data/expected/main/graphql/enums_typed_dict.py @@ -7,18 +7,24 @@ from typing import Literal, TypeAlias Boolean: TypeAlias = bool -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String: TypeAlias = str -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" Color: TypeAlias = Literal['BLUE', 'GREEN', 'RED'] EmployeeShiftStatus: TypeAlias = Literal['NOT_ON_SHIFT', 'ON_SHIFT'] -"""Employee shift status""" +""" +Employee shift status +""" EnumWithOneField: TypeAlias = Literal['FIELD'] diff --git a/tests/data/expected/main/graphql/enums_using_subclass.py b/tests/data/expected/main/graphql/enums_using_subclass.py index 594bd66df..bc73254ad 100644 --- a/tests/data/expected/main/graphql/enums_using_subclass.py +++ b/tests/data/expected/main/graphql/enums_using_subclass.py @@ -9,11 +9,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Color(str, Enum): @@ -23,7 +27,9 @@ class Color(str, Enum): class EmployeeShiftStatus(str, Enum): - """Employee shift status""" + """ + Employee shift status + """ NOT_ON_SHIFT = 'NOT_ON_SHIFT' ON_SHIFT = 'ON_SHIFT' diff --git a/tests/data/expected/main/graphql/field_aliases.py b/tests/data/expected/main/graphql/field_aliases.py index a696b9340..29da5df7a 100644 --- a/tests/data/expected/main/graphql/field_aliases.py +++ b/tests/data/expected/main/graphql/field_aliases.py @@ -10,14 +10,18 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" DateTime = TypeAliasType("DateTime", str) String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class DateTimePeriod(BaseModel): diff --git a/tests/data/expected/main/graphql/graphql_multiple_aliases_pydantic_v2.py b/tests/data/expected/main/graphql/graphql_multiple_aliases_pydantic_v2.py index 9a85f5028..94b25ab17 100644 --- a/tests/data/expected/main/graphql/graphql_multiple_aliases_pydantic_v2.py +++ b/tests/data/expected/main/graphql/graphql_multiple_aliases_pydantic_v2.py @@ -10,14 +10,18 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" DateTime = TypeAliasType("DateTime", str) String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Event(BaseModel): diff --git a/tests/data/expected/main/graphql/interface_mro.py b/tests/data/expected/main/graphql/interface_mro.py index d3aaec2f3..242fb66f2 100644 --- a/tests/data/expected/main/graphql/interface_mro.py +++ b/tests/data/expected/main/graphql/interface_mro.py @@ -10,15 +10,21 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class BaseInterface(BaseModel): diff --git a/tests/data/expected/main/graphql/no_typename.py b/tests/data/expected/main/graphql/no_typename.py index 6f6f77a8b..5a8598d00 100644 --- a/tests/data/expected/main/graphql/no_typename.py +++ b/tests/data/expected/main/graphql/no_typename.py @@ -8,15 +8,21 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Node(BaseModel): diff --git a/tests/data/expected/main/graphql/pydantic_v2_empty_list_default.py b/tests/data/expected/main/graphql/pydantic_v2_empty_list_default.py index 76cbf81dc..1f90a7edd 100644 --- a/tests/data/expected/main/graphql/pydantic_v2_empty_list_default.py +++ b/tests/data/expected/main/graphql/pydantic_v2_empty_list_default.py @@ -9,11 +9,15 @@ from pydantic import BaseModel, Field type Boolean = bool -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" type String = str -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Container(BaseModel): diff --git a/tests/data/expected/main/graphql/simple_star_wars.py b/tests/data/expected/main/graphql/simple_star_wars.py index 148fb2da3..4593d1b32 100644 --- a/tests/data/expected/main/graphql/simple_star_wars.py +++ b/tests/data/expected/main/graphql/simple_star_wars.py @@ -10,19 +10,27 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Int = TypeAliasType("Int", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Film(BaseModel): diff --git a/tests/data/expected/main/graphql/simple_star_wars_class_name_prefix.py b/tests/data/expected/main/graphql/simple_star_wars_class_name_prefix.py index 7a26da4b6..24121a1cb 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_class_name_prefix.py +++ b/tests/data/expected/main/graphql/simple_star_wars_class_name_prefix.py @@ -10,19 +10,27 @@ from typing_extensions import TypeAliasType FooBoolean = TypeAliasType("FooBoolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" FooID = TypeAliasType("FooID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" FooInt = TypeAliasType("FooInt", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" FooString = TypeAliasType("FooString", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class FooFilm(BaseModel): diff --git a/tests/data/expected/main/graphql/simple_star_wars_dataclass.py b/tests/data/expected/main/graphql/simple_star_wars_dataclass.py index 39177965e..8fa8d3d0f 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_dataclass.py +++ b/tests/data/expected/main/graphql/simple_star_wars_dataclass.py @@ -8,19 +8,27 @@ from typing import Literal, TypeAlias Boolean: TypeAlias = bool -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID: TypeAlias = str -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Int: TypeAlias = int -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String: TypeAlias = str -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" @dataclass diff --git a/tests/data/expected/main/graphql/simple_star_wars_dataclass_arguments.py b/tests/data/expected/main/graphql/simple_star_wars_dataclass_arguments.py index b4e6248e7..9df4fe776 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_dataclass_arguments.py +++ b/tests/data/expected/main/graphql/simple_star_wars_dataclass_arguments.py @@ -8,19 +8,27 @@ from typing import Literal, TypeAlias Boolean: TypeAlias = bool -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID: TypeAlias = str -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Int: TypeAlias = int -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String: TypeAlias = str -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" @dataclass(order=True, slots=True) diff --git a/tests/data/expected/main/graphql/simple_star_wars_dataclass_frozen_kw_only.py b/tests/data/expected/main/graphql/simple_star_wars_dataclass_frozen_kw_only.py index 6609e2e7d..24d920fa6 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_dataclass_frozen_kw_only.py +++ b/tests/data/expected/main/graphql/simple_star_wars_dataclass_frozen_kw_only.py @@ -8,19 +8,27 @@ from typing import Literal, TypeAlias Boolean: TypeAlias = bool -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID: TypeAlias = str -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Int: TypeAlias = int -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String: TypeAlias = str -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" @dataclass(frozen=True, kw_only=True) diff --git a/tests/data/expected/main/graphql/simple_star_wars_extra_fields_allow.py b/tests/data/expected/main/graphql/simple_star_wars_extra_fields_allow.py index f4b5c5797..2f0d53d9f 100644 --- a/tests/data/expected/main/graphql/simple_star_wars_extra_fields_allow.py +++ b/tests/data/expected/main/graphql/simple_star_wars_extra_fields_allow.py @@ -10,19 +10,27 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Int = TypeAliasType("Int", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Film(BaseModel): diff --git a/tests/data/expected/main/graphql/split_graphql_schemas.py b/tests/data/expected/main/graphql/split_graphql_schemas.py index 35c8c1ef2..eb8bde6e3 100644 --- a/tests/data/expected/main/graphql/split_graphql_schemas.py +++ b/tests/data/expected/main/graphql/split_graphql_schemas.py @@ -10,15 +10,21 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" Int = TypeAliasType("Int", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Baz(BaseModel): diff --git a/tests/data/expected/main/graphql/type_alias.py b/tests/data/expected/main/graphql/type_alias.py index 596bef487..9cc52bc39 100644 --- a/tests/data/expected/main/graphql/type_alias.py +++ b/tests/data/expected/main/graphql/type_alias.py @@ -10,18 +10,24 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" Int = TypeAliasType("Int", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" SimpleString = TypeAliasType("SimpleString", str) String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Person(BaseModel): diff --git a/tests/data/expected/main/graphql/type_alias_py312.py b/tests/data/expected/main/graphql/type_alias_py312.py index e3c4977d5..cc7dc4aa8 100644 --- a/tests/data/expected/main/graphql/type_alias_py312.py +++ b/tests/data/expected/main/graphql/type_alias_py312.py @@ -9,18 +9,24 @@ from pydantic import BaseModel, Field type Boolean = bool -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" type Int = int -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" type SimpleString = str type String = str -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Person(BaseModel): diff --git a/tests/data/expected/main/graphql/union.py b/tests/data/expected/main/graphql/union.py index 7d0874226..c4ca331c4 100644 --- a/tests/data/expected/main/graphql/union.py +++ b/tests/data/expected/main/graphql/union.py @@ -10,19 +10,27 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Int = TypeAliasType("Int", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class IResource(BaseModel): diff --git a/tests/data/expected/main/graphql/union_class_name_prefix.py b/tests/data/expected/main/graphql/union_class_name_prefix.py index ed1695038..911faf1f5 100644 --- a/tests/data/expected/main/graphql/union_class_name_prefix.py +++ b/tests/data/expected/main/graphql/union_class_name_prefix.py @@ -10,19 +10,27 @@ from typing_extensions import TypeAliasType FooBoolean = TypeAliasType("FooBoolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" FooID = TypeAliasType("FooID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" FooInt = TypeAliasType("FooInt", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" FooString = TypeAliasType("FooString", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class FooIResource(BaseModel): diff --git a/tests/data/expected/main/graphql/union_snake_case_field.py b/tests/data/expected/main/graphql/union_snake_case_field.py index 55afd3ee8..71c9a4e39 100644 --- a/tests/data/expected/main/graphql/union_snake_case_field.py +++ b/tests/data/expected/main/graphql/union_snake_case_field.py @@ -10,19 +10,27 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" Int = TypeAliasType("Int", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class IResource(BaseModel): diff --git a/tests/data/expected/main/graphql/use_standard_collections.py b/tests/data/expected/main/graphql/use_standard_collections.py index bb0ab34a3..112130ab0 100644 --- a/tests/data/expected/main/graphql/use_standard_collections.py +++ b/tests/data/expected/main/graphql/use_standard_collections.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/graphql/use_union_operator.py b/tests/data/expected/main/graphql/use_union_operator.py index 376a800bc..7c3a2b725 100644 --- a/tests/data/expected/main/graphql/use_union_operator.py +++ b/tests/data/expected/main/graphql/use_union_operator.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class A(BaseModel): diff --git a/tests/data/expected/main/help/color.txt b/tests/data/expected/main/help/color.txt index f34ce56d9..20ef08006 100644 --- a/tests/data/expected/main/help/color.txt +++ b/tests/data/expected/main/help/color.txt @@ -256,6 +256,9 @@ For detailed usage, see: https://datamodel-code-generator.koxudaxi.dev aliasing (Pydantic v2 only). This allows setting values using the Pythonic field name while serializing to the original name. + --use-single-line-docstring + Use single-line docstrings when the content fits on + one line Model customization: --all-exports-collision-strategy {error,minimal-prefix,full-prefix} diff --git a/tests/data/expected/main/help/no_color.txt b/tests/data/expected/main/help/no_color.txt index d31bbb398..1aa862595 100644 --- a/tests/data/expected/main/help/no_color.txt +++ b/tests/data/expected/main/help/no_color.txt @@ -256,6 +256,9 @@ Field customization: aliasing (Pydantic v2 only). This allows setting values using the Pythonic field name while serializing to the original name. + --use-single-line-docstring + Use single-line docstrings when the content fits on + one line Model customization: --all-exports-collision-strategy {error,minimal-prefix,full-prefix} diff --git a/tests/data/expected/main/input_model/config_class.py b/tests/data/expected/main/input_model/config_class.py index 02437ce39..308ad584d 100644 --- a/tests/data/expected/main/input_model/config_class.py +++ b/tests/data/expected/main/input_model/config_class.py @@ -155,6 +155,7 @@ class GenerateConfig(TypedDict, closed=True): use_field_description_example: NotRequired[bool] use_attribute_docstrings: NotRequired[bool] use_inline_field_description: NotRequired[bool] + use_single_line_docstring: NotRequired[bool] use_default_kwarg: NotRequired[bool] reuse_model: NotRequired[bool] reuse_scope: NotRequired[ReuseScope] diff --git a/tests/data/expected/main/jsonschema/allof_mro.py b/tests/data/expected/main/jsonschema/allof_mro.py index 8ca0b4b59..d4af7a11c 100644 --- a/tests/data/expected/main/jsonschema/allof_mro.py +++ b/tests/data/expected/main/jsonschema/allof_mro.py @@ -20,7 +20,9 @@ class RightBranch(BaseInterface): class DiamondType(LeftBranch, RightBranch, BaseInterface): - """Diamond inheritance pattern - inherits from both LeftBranch and RightBranch which both inherit from BaseInterface""" + """ + Diamond inheritance pattern - inherits from both LeftBranch and RightBranch which both inherit from BaseInterface + """ diamond_value: str | None = None diff --git a/tests/data/expected/main/jsonschema/type_alias_with_field_description.py b/tests/data/expected/main/jsonschema/type_alias_with_field_description.py index 677782d76..e5a07bba4 100644 --- a/tests/data/expected/main/jsonschema/type_alias_with_field_description.py +++ b/tests/data/expected/main/jsonschema/type_alias_with_field_description.py @@ -24,7 +24,9 @@ AnnotatedType = TypeAliasType( "AnnotatedType", Annotated[str | bool, Field(..., title='MyAnnotatedType')] ) -"""An annotated union type""" +""" +An annotated union type +""" class ModelWithTypeAliasField(BaseModel): diff --git a/tests/data/expected/main/jsonschema/type_alias_with_field_description_py312.py b/tests/data/expected/main/jsonschema/type_alias_with_field_description_py312.py index 78d3fbb57..f089a40a6 100644 --- a/tests/data/expected/main/jsonschema/type_alias_with_field_description_py312.py +++ b/tests/data/expected/main/jsonschema/type_alias_with_field_description_py312.py @@ -21,7 +21,9 @@ type AnnotatedType = Annotated[str | bool, Field(..., title='MyAnnotatedType')] -"""An annotated union type""" +""" +An annotated union type +""" class ModelWithTypeAliasField(BaseModel): diff --git a/tests/data/expected/main/openapi/all_of_with_relative_ref.py b/tests/data/expected/main/openapi/all_of_with_relative_ref.py index 841acbeb7..f992cd4aa 100644 --- a/tests/data/expected/main/openapi/all_of_with_relative_ref.py +++ b/tests/data/expected/main/openapi/all_of_with_relative_ref.py @@ -14,7 +14,9 @@ class Animal(BaseModel): extra='forbid', ) kind: Kind | None = None - """The kind of the animal""" + """ + The kind of the animal + """ class Animals(RootModel[Animal]): @@ -31,7 +33,9 @@ class Pet(BaseModel): extra='forbid', ) kind: Kind | None = None - """The kind of the pet""" + """ + The kind of the pet + """ class Pets(RootModel[Pet]): diff --git a/tests/data/expected/main/openapi/allof_array_ref_override.py b/tests/data/expected/main/openapi/allof_array_ref_override.py index ba3d75187..237732613 100644 --- a/tests/data/expected/main/openapi/allof_array_ref_override.py +++ b/tests/data/expected/main/openapi/allof_array_ref_override.py @@ -30,7 +30,9 @@ class Metadata(BaseModel): class CollectionWrapper(BaseModel): - """Generic response wrapper containing a collection of items and pagination metadata.""" + """ + Generic response wrapper containing a collection of items and pagination metadata. + """ data: list[dict[str, Any]] = Field( ..., description='Array of items in the collection.' diff --git a/tests/data/expected/main/use_attribute_docstrings.py b/tests/data/expected/main/use_attribute_docstrings.py index 30e955dc1..d2cfc6fde 100644 --- a/tests/data/expected/main/use_attribute_docstrings.py +++ b/tests/data/expected/main/use_attribute_docstrings.py @@ -12,6 +12,10 @@ class Person(BaseModel): use_attribute_docstrings=True, ) name: str - """The person's full name""" + """ + The person's full name + """ age: int | None = None - """The person's age in years""" + """ + The person's age in years + """ diff --git a/tests/data/expected/main/use_single_line_docstring.py b/tests/data/expected/main/use_single_line_docstring.py new file mode 100644 index 000000000..13760c888 --- /dev/null +++ b/tests/data/expected/main/use_single_line_docstring.py @@ -0,0 +1,20 @@ +# generated by datamodel-codegen: +# filename: person.json +# timestamp: 2019-07-26T00:00:00+00:00 + +from __future__ import annotations + +from typing import Any + +from pydantic import BaseModel, conint + + +class Person(BaseModel): + firstName: str | None = None + """The person's first name.""" + lastName: str | None = None + """The person's last name.""" + age: conint(ge=0) | None = None + """Age in years which must be equal to or greater than zero.""" + friends: list[Any] | None = None + comment: None = None diff --git a/tests/data/expected/main_kr/generate_prompt/basic.txt b/tests/data/expected/main_kr/generate_prompt/basic.txt index 90ebc7f90..509d6e3ee 100644 --- a/tests/data/expected/main_kr/generate_prompt/basic.txt +++ b/tests/data/expected/main_kr/generate_prompt/basic.txt @@ -75,6 +75,7 @@ - `--use-inline-field-description`: Add field descriptions as inline comments. - `--use-schema-description`: Use schema description as class docstring. - `--use-serialization-alias`: Use serialization_alias instead of alias for field aliasing (Pydantic v2 only). +- `--use-single-line-docstring`: Use single-line docstrings when the content fits on one line. - `--use-title-as-name`: Use schema title as the generated class name. ### Model Customization @@ -432,6 +433,9 @@ For detailed usage, see: https://datamodel-code-generator.koxudaxi.dev aliasing (Pydantic v2 only). This allows setting values using the Pythonic field name while serializing to the original name. + --use-single-line-docstring + Use single-line docstrings when the content fits on + one line Model customization: --all-exports-collision-strategy {error,minimal-prefix,full-prefix} diff --git a/tests/data/expected/main_kr/generate_prompt/with_list_options.txt b/tests/data/expected/main_kr/generate_prompt/with_list_options.txt index 820550c3a..f4f09a4a8 100644 --- a/tests/data/expected/main_kr/generate_prompt/with_list_options.txt +++ b/tests/data/expected/main_kr/generate_prompt/with_list_options.txt @@ -75,6 +75,7 @@ - `--use-inline-field-description`: Add field descriptions as inline comments. - `--use-schema-description`: Use schema description as class docstring. - `--use-serialization-alias`: Use serialization_alias instead of alias for field aliasing (Pydantic v2 only). +- `--use-single-line-docstring`: Use single-line docstrings when the content fits on one line. - `--use-title-as-name`: Use schema title as the generated class name. ### Model Customization @@ -432,6 +433,9 @@ For detailed usage, see: https://datamodel-code-generator.koxudaxi.dev aliasing (Pydantic v2 only). This allows setting values using the Pythonic field name while serializing to the original name. + --use-single-line-docstring + Use single-line docstrings when the content fits on + one line Model customization: --all-exports-collision-strategy {error,minimal-prefix,full-prefix} diff --git a/tests/data/expected/main_kr/generate_prompt/with_options.txt b/tests/data/expected/main_kr/generate_prompt/with_options.txt index 01f4ffb63..d34f82f54 100644 --- a/tests/data/expected/main_kr/generate_prompt/with_options.txt +++ b/tests/data/expected/main_kr/generate_prompt/with_options.txt @@ -81,6 +81,7 @@ What other options should I use? - `--use-inline-field-description`: Add field descriptions as inline comments. - `--use-schema-description`: Use schema description as class docstring. - `--use-serialization-alias`: Use serialization_alias instead of alias for field aliasing (Pydantic v2 only). +- `--use-single-line-docstring`: Use single-line docstrings when the content fits on one line. - `--use-title-as-name`: Use schema title as the generated class name. ### Model Customization @@ -438,6 +439,9 @@ For detailed usage, see: https://datamodel-code-generator.koxudaxi.dev aliasing (Pydantic v2 only). This allows setting values using the Pythonic field name while serializing to the original name. + --use-single-line-docstring + Use single-line docstrings when the content fits on + one line Model customization: --all-exports-collision-strategy {error,minimal-prefix,full-prefix} diff --git a/tests/data/expected/main_kr/generate_prompt/with_question.txt b/tests/data/expected/main_kr/generate_prompt/with_question.txt index d6285a325..1cb9f1148 100644 --- a/tests/data/expected/main_kr/generate_prompt/with_question.txt +++ b/tests/data/expected/main_kr/generate_prompt/with_question.txt @@ -79,6 +79,7 @@ How do I convert enums to Literal types? - `--use-inline-field-description`: Add field descriptions as inline comments. - `--use-schema-description`: Use schema description as class docstring. - `--use-serialization-alias`: Use serialization_alias instead of alias for field aliasing (Pydantic v2 only). +- `--use-single-line-docstring`: Use single-line docstrings when the content fits on one line. - `--use-title-as-name`: Use schema title as the generated class name. ### Model Customization @@ -436,6 +437,9 @@ For detailed usage, see: https://datamodel-code-generator.koxudaxi.dev aliasing (Pydantic v2 only). This allows setting values using the Pythonic field name while serializing to the original name. + --use-single-line-docstring + Use single-line docstrings when the content fits on + one line Model customization: --all-exports-collision-strategy {error,minimal-prefix,full-prefix} diff --git a/tests/data/expected/main_kr/help_shows_new_options.txt b/tests/data/expected/main_kr/help_shows_new_options.txt index f34ce56d9..20ef08006 100644 --- a/tests/data/expected/main_kr/help_shows_new_options.txt +++ b/tests/data/expected/main_kr/help_shows_new_options.txt @@ -256,6 +256,9 @@ For detailed usage, see: https://datamodel-code-generator.koxudaxi.dev aliasing (Pydantic v2 only). This allows setting values using the Pythonic field name while serializing to the original name. + --use-single-line-docstring + Use single-line docstrings when the content fits on + one line Model customization: --all-exports-collision-strategy {error,minimal-prefix,full-prefix} diff --git a/tests/data/expected/main_kr/main_allof_with_description_only/output.py b/tests/data/expected/main_kr/main_allof_with_description_only/output.py index dd8164c67..0fa45ba44 100644 --- a/tests/data/expected/main_kr/main_allof_with_description_only/output.py +++ b/tests/data/expected/main_kr/main_allof_with_description_only/output.py @@ -8,10 +8,14 @@ class MyModel(BaseModel): - """A model that has a description.""" + """ + A model that has a description. + """ name: str | None = None class MyOtherModel(MyModel): - """Another model that should also have a description.""" + """ + Another model that should also have a description. + """ diff --git a/tests/data/expected/main_kr/main_docstring_special_chars/output.py b/tests/data/expected/main_kr/main_docstring_special_chars/output.py index b94c05ea5..fe46e1628 100644 --- a/tests/data/expected/main_kr/main_docstring_special_chars/output.py +++ b/tests/data/expected/main_kr/main_docstring_special_chars/output.py @@ -8,27 +8,41 @@ class ExampleWithBackslash(BaseModel): - """Observe the backslash \\ in this line""" + """ + Observe the backslash \\ in this line + """ name: str | None = None - """Path like C:\\Users\\name""" + """ + Path like C:\\Users\\name + """ class ExampleWithTripleQuotes(BaseModel): - """Contains \"\"\"triple quotes\"\"\" """ + """ + Contains \"\"\"triple quotes\"\"\" + """ value: str | None = None - """Field with \"\"\"quotes\"\"\" """ + """ + Field with \"\"\"quotes\"\"\" + """ class ExampleWithBoth(BaseModel): - """Has both \\ backslash and \"\"\"quotes\"\"\" """ + """ + Has both \\ backslash and \"\"\"quotes\"\"\" + """ data: str | None = None - """Data: C:\\path\\to\\\"\"\"file\"\"\" """ + """ + Data: C:\\path\\to\\\"\"\"file\"\"\" + """ class ExampleWithNewlineEscape(BaseModel): - """Text with \\n which looks like newline escape""" + """ + Text with \\n which looks like newline escape + """ text: str | None = None diff --git a/tests/data/expected/main_kr/main_use_field_description/output.py b/tests/data/expected/main_kr/main_use_field_description/output.py index d9136bec4..702db6dd6 100644 --- a/tests/data/expected/main_kr/main_use_field_description/output.py +++ b/tests/data/expected/main_kr/main_use_field_description/output.py @@ -47,11 +47,17 @@ class Api(BaseModel): Now also with multi-line docstrings. """ apiVersionNumber: str | None = None - """To be used as a version parameter value""" + """ + To be used as a version parameter value + """ apiUrl: AnyUrl | None = None - """The URL describing the dataset's fields""" + """ + The URL describing the dataset's fields + """ apiDocumentationUrl: AnyUrl | None = None - """A URL to the API console for each API""" + """ + A URL to the API console for each API + """ class Apis(RootModel[list[Api]]): diff --git a/tests/data/expected/main_kr/main_use_field_description_example/output.py b/tests/data/expected/main_kr/main_use_field_description_example/output.py index ddac79c75..0cc0401a1 100644 --- a/tests/data/expected/main_kr/main_use_field_description_example/output.py +++ b/tests/data/expected/main_kr/main_use_field_description_example/output.py @@ -9,7 +9,9 @@ class Extras(BaseModel): name: str | None = Field(None, description='normal key', examples=['example']) - """Example: 'example'""" + """ + Example: 'example' + """ age: int | None = Field(None, examples=[13, 20], json_schema_extra={'example': 12}) """ Examples: @@ -17,4 +19,6 @@ class Extras(BaseModel): - 20 """ status: str | None = Field(None, examples=['active']) - """Example: 'active'""" + """ + Example: 'active' + """ diff --git a/tests/data/expected/main_kr/main_use_field_description_example_dataclass/output.py b/tests/data/expected/main_kr/main_use_field_description_example_dataclass/output.py index 4ba38d523..f00f58f11 100644 --- a/tests/data/expected/main_kr/main_use_field_description_example_dataclass/output.py +++ b/tests/data/expected/main_kr/main_use_field_description_example_dataclass/output.py @@ -10,4 +10,6 @@ @dataclass class SingleLineDescriptionWithExample: name: str | None = None - """Example: 'John Doe'""" + """ + Example: 'John Doe' + """ diff --git a/tests/data/expected/main_kr/main_use_field_description_with_example/output.py b/tests/data/expected/main_kr/main_use_field_description_with_example/output.py index 121f5d6fb..5a56077b8 100644 --- a/tests/data/expected/main_kr/main_use_field_description_with_example/output.py +++ b/tests/data/expected/main_kr/main_use_field_description_with_example/output.py @@ -21,4 +21,6 @@ class Extras(BaseModel): - 20 """ status: str | None = Field(None, examples=['active']) - """Example: 'active'""" + """ + Example: 'active' + """ diff --git a/tests/data/expected/main_kr/main_use_inline_field_description_example_only/output.py b/tests/data/expected/main_kr/main_use_inline_field_description_example_only/output.py index 203f1c37c..c6b7e405c 100644 --- a/tests/data/expected/main_kr/main_use_inline_field_description_example_only/output.py +++ b/tests/data/expected/main_kr/main_use_inline_field_description_example_only/output.py @@ -9,4 +9,6 @@ class SingleLineDescriptionWithExample(BaseModel): name: str | None = Field(None, description='User name.', examples=['John Doe']) - """Example: 'John Doe'""" + """ + Example: 'John Doe' + """ diff --git a/tests/data/expected/main_kr/main_use_schema_description/output.py b/tests/data/expected/main_kr/main_use_schema_description/output.py index 0e2802f11..62c2564ec 100644 --- a/tests/data/expected/main_kr/main_use_schema_description/output.py +++ b/tests/data/expected/main_kr/main_use_schema_description/output.py @@ -66,7 +66,9 @@ class Apis(RootModel[list[Api]]): class Event(BaseModel): - """Event object""" + """ + Event object + """ name: str | None = None diff --git a/tests/data/expected/parser/graphql/field-default-enum.py b/tests/data/expected/parser/graphql/field-default-enum.py index 5c44f7dc9..b4adcfb21 100644 --- a/tests/data/expected/parser/graphql/field-default-enum.py +++ b/tests/data/expected/parser/graphql/field-default-enum.py @@ -11,11 +11,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Color(Enum): diff --git a/tests/data/expected/parser/graphql/no_typename.py b/tests/data/expected/parser/graphql/no_typename.py index 6f6f77a8b..5a8598d00 100644 --- a/tests/data/expected/parser/graphql/no_typename.py +++ b/tests/data/expected/parser/graphql/no_typename.py @@ -8,15 +8,21 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" ID = TypeAliasType("ID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class Node(BaseModel): diff --git a/tests/data/expected/parser/graphql/union-aliased-bug.py b/tests/data/expected/parser/graphql/union-aliased-bug.py index 2c19734d6..411cf3f13 100644 --- a/tests/data/expected/parser/graphql/union-aliased-bug.py +++ b/tests/data/expected/parser/graphql/union-aliased-bug.py @@ -10,11 +10,15 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class GroupMetadata(BaseModel): diff --git a/tests/data/expected/parser/graphql/union-commented.py b/tests/data/expected/parser/graphql/union-commented.py index 84dd10362..e7124330f 100644 --- a/tests/data/expected/parser/graphql/union-commented.py +++ b/tests/data/expected/parser/graphql/union-commented.py @@ -10,15 +10,21 @@ from typing_extensions import TypeAliasType Boolean = TypeAliasType("Boolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" String = TypeAliasType("String", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class GroupMetadata(BaseModel): - """This is a test comment in a single line""" + """ + This is a test comment in a single line + """ name: String typename__: Literal['GroupMetadata'] | None = Field( diff --git a/tests/data/expected/parser/graphql/union_with_prefix.py b/tests/data/expected/parser/graphql/union_with_prefix.py index da4207d53..7486c6233 100644 --- a/tests/data/expected/parser/graphql/union_with_prefix.py +++ b/tests/data/expected/parser/graphql/union_with_prefix.py @@ -10,19 +10,27 @@ from typing_extensions import TypeAliasType FooBoolean = TypeAliasType("FooBoolean", bool) -"""The `Boolean` scalar type represents `true` or `false`.""" +""" +The `Boolean` scalar type represents `true` or `false`. +""" FooID = TypeAliasType("FooID", str) -"""The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.""" +""" +The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID. +""" FooInt = TypeAliasType("FooInt", int) -"""The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.""" +""" +The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. +""" FooString = TypeAliasType("FooString", str) -"""The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.""" +""" +The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +""" class FooIResource(BaseModel): diff --git a/tests/data/templates_schema_id/pydantic_v2/BaseModel.jinja2 b/tests/data/templates_schema_id/pydantic_v2/BaseModel.jinja2 index a3501a0fc..b6c635dc4 100644 --- a/tests/data/templates_schema_id/pydantic_v2/BaseModel.jinja2 +++ b/tests/data/templates_schema_id/pydantic_v2/BaseModel.jinja2 @@ -11,7 +11,7 @@ an alias for Bar: every pydantic model class consumes considerable memory. #} {% endfor -%} class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comment }}{% endif %} {%- if description %} - {{ description | format_docstring(4) }} + {{ description | format_docstring(4, use_single_line_docstring=use_single_line_docstring) }} {%- endif %} {%- if schema_id is defined and schema_id %} __schema_id__ = "{{ schema_id }}" @@ -41,7 +41,7 @@ class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comme {%- endif -%} {%- endif %} {%- if field.docstring %} - {{ field.docstring | format_docstring(4) }} + {{ field.docstring | format_docstring(4, use_single_line_docstring=use_single_line_docstring) }} {%- if field.use_inline_field_description and not loop.last %} {% endif %} diff --git a/tests/main/test_main_general.py b/tests/main/test_main_general.py index 3d848b5b6..b293f95dd 100644 --- a/tests/main/test_main_general.py +++ b/tests/main/test_main_general.py @@ -1930,6 +1930,60 @@ def test_generate_returns_string_with_dataclass() -> None: assert_output(result, EXPECTED_MAIN_PATH / "generate_returns_string_with_dataclass.py") +@pytest.mark.allow_direct_assert +def test_generate_uses_multiline_docstring_by_default() -> None: + """Test that schema descriptions keep the historical multi-line docstring format.""" + json_schema = '{"title": "Person", "description": "Person model", "type": "object", "properties": {}}' + result = generate( + json_schema, + input_file_type=InputFileType.JsonSchema, + input_filename="schema.json", + use_schema_description=True, + disable_timestamp=True, + ) + assert isinstance(result, str) + assert 'class Person(BaseModel):\n """\n Person model\n """' in result + + +@pytest.mark.allow_direct_assert +def test_generate_uses_single_line_docstring_when_enabled() -> None: + """Test that schema descriptions use one-line docstrings when requested.""" + json_schema = '{"title": "Person", "description": "Person model", "type": "object", "properties": {}}' + result = generate( + json_schema, + input_file_type=InputFileType.JsonSchema, + input_filename="schema.json", + use_schema_description=True, + use_single_line_docstring=True, + disable_timestamp=True, + ) + assert isinstance(result, str) + assert 'class Person(BaseModel):\n """Person model"""' in result + + +@pytest.mark.cli_doc( + options=["--use-single-line-docstring"], + option_description="""Emit short docstrings on a single line. + +The `--use-single-line-docstring` flag formats docstrings that fit on one line +as compact single-line docstrings while keeping the historical multi-line +format as the default.""", + input_schema="jsonschema/person.json", + cli_args=["--use-field-description", "--use-single-line-docstring"], + golden_output="main/use_single_line_docstring.py", + related_options=["--use-schema-description", "--use-field-description"], +) +def test_main_use_single_line_docstring(output_file: Path) -> None: + """Emit short docstrings on a single line.""" + run_main_and_assert( + input_path=DATA_PATH / "jsonschema" / "person.json", + output_path=output_file, + assert_func=assert_file_content, + expected_file="use_single_line_docstring.py", + extra_args=["--use-field-description", "--use-single-line-docstring"], + ) + + def test_generate_returns_none_when_output_path_provided(tmp_path: Path) -> None: """Test that generate() returns None when output path is provided.""" json_schema = '{"type": "object", "properties": {"name": {"type": "string"}}}' diff --git a/tests/main/test_public_api_signature_baseline.py b/tests/main/test_public_api_signature_baseline.py index b5511a070..46c36e47b 100644 --- a/tests/main/test_public_api_signature_baseline.py +++ b/tests/main/test_public_api_signature_baseline.py @@ -93,6 +93,7 @@ def _baseline_generate( use_field_description_example: bool = False, use_attribute_docstrings: bool = False, use_inline_field_description: bool = False, + use_single_line_docstring: bool = False, use_default_kwarg: bool = False, reuse_model: bool = False, reuse_scope: ReuseScope = ReuseScope.Module, @@ -234,6 +235,7 @@ def __init__( use_field_description_example: bool = False, use_attribute_docstrings: bool = False, use_inline_field_description: bool = False, + use_single_line_docstring: bool = False, use_default_kwarg: bool = False, reuse_model: bool = False, reuse_scope: ReuseScope | None = None, diff --git a/tests/model/test_base.py b/tests/model/test_base.py index c849ff381..86474b3e5 100644 --- a/tests/model/test_base.py +++ b/tests/model/test_base.py @@ -13,6 +13,7 @@ DataModelFieldBase, TemplateBase, escape_docstring, + format_docstring, get_module_path, sanitize_module_name, ) @@ -396,6 +397,37 @@ def test_escape_docstring(input_value: str | None, expected: str | None) -> None assert escape_docstring(input_value) == expected +def test_format_docstring_uses_multiline_format_by_default() -> None: + """Test format_docstring preserves historical multi-line formatting by default.""" + assert format_docstring("Description", 4) == '"""\n Description\n """' + + +@pytest.mark.parametrize("empty_value", [None, "", " "]) +def test_format_docstring_returns_empty_string_for_empty_values(empty_value: str | None) -> None: + """Test format_docstring returns an empty string for empty values.""" + assert not format_docstring(empty_value, 4) + + +def test_format_docstring_uses_single_line_when_enabled() -> None: + """Test format_docstring emits one-line docstrings when enabled.""" + assert format_docstring("Description", 4, use_single_line_docstring=True) == '"""Description"""' + + +def test_format_docstring_escapes_trailing_quote_without_changing_docstring() -> None: + """Test one-line docstrings ending with a quote preserve their value.""" + assert format_docstring('Description"', 4, use_single_line_docstring=True) == r'"""Description\""""' + + +def test_format_docstring_escapes_single_quote_docstring() -> None: + """Test a docstring consisting only of a quote is escaped.""" + assert format_docstring('"', 4, use_single_line_docstring=True) == r'"""\""""' + + +def test_format_docstring_keeps_escaped_triple_quotes_without_extra_escape() -> None: + """Test escaped triple quotes at the end are not double-escaped.""" + assert format_docstring('Description """', 4, use_single_line_docstring=True) == r'"""Description \"\"\""""' + + def test_inline_field_docstring_escapes_special_chars() -> None: """Test inline_field_docstring property escapes special characters.""" field = DataModelFieldBase( @@ -417,7 +449,7 @@ def test_inline_field_docstring_escapes_triple_quotes() -> None: extras={"description": 'Contains """quotes"""'}, use_inline_field_description=True, ) - assert field.inline_field_docstring == r'"""Contains \"\"\"quotes\"\"\" """' + assert field.inline_field_docstring == r'"""Contains \"\"\"quotes\"\"\""""' def test_data_type_manager_unknown_type_raises_error() -> None: