Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/datamodel_code_generator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ def generate( # noqa: PLR0912, PLR0913, PLR0914, PLR0915
no_alias: bool = False,
formatters: list[Formatter] = DEFAULT_FORMATTERS,
parent_scoped_naming: bool = False,
exclude_typename_field: bool = False,
) -> None:
remote_text_cache: DefaultPutDict[str, str] = DefaultPutDict()
if isinstance(input_, str):
Expand Down Expand Up @@ -331,6 +332,7 @@ def generate( # noqa: PLR0912, PLR0913, PLR0914, PLR0915
from datamodel_code_generator.parser.graphql import GraphQLParser # noqa: PLC0415

parser_class: type[Parser] = GraphQLParser
kwargs["exclude_typename_field"] = exclude_typename_field
else:
from datamodel_code_generator.parser.jsonschema import JsonSchemaParser # noqa: PLC0415

Expand Down
2 changes: 2 additions & 0 deletions src/datamodel_code_generator/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ def validate_root(cls, values: Any) -> Any: # noqa: N805
no_alias: bool = False
formatters: list[Formatter] = DEFAULT_FORMATTERS
parent_scoped_naming: bool = False
exclude_typename_field: bool = False

def merge_args(self, args: Namespace) -> None:
set_args = {f: getattr(args, f) for f in self.get_fields() if getattr(args, f) is not None}
Expand Down Expand Up @@ -531,6 +532,7 @@ def main(args: Sequence[str] | None = None) -> Exit: # noqa: PLR0911, PLR0912,
no_alias=config.no_alias,
formatters=config.formatters,
parent_scoped_naming=config.parent_scoped_naming,
exclude_typename_field=config.exclude_typename_field,
)
except InvalidClassNameError as e:
print(f"{e} You have to set `--class-name` option", file=sys.stderr) # noqa: T201
Expand Down
7 changes: 7 additions & 0 deletions src/datamodel_code_generator/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,13 @@ def start_section(self, heading: str | None) -> None:
action="store_true",
default=None,
)
field_options.add_argument(
"--exclude-typename-field",
"--exclude_typename_field",
help="Exclude __typename field from the generated model",
action="store_true",
default=None,
)

# ======================================================================================
# Options for templating output
Expand Down
6 changes: 4 additions & 2 deletions src/datamodel_code_generator/parser/graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ def __init__( # noqa: PLR0913
no_alias: bool = False,
formatters: list[Formatter] = DEFAULT_FORMATTERS,
parent_scoped_naming: bool = False,
exclude_typename_field: bool = False,
) -> None:
super().__init__(
source=source,
Expand Down Expand Up @@ -241,6 +242,7 @@ def __init__( # noqa: PLR0913
self.data_model_union_type = data_model_union_type
self.use_standard_collections = use_standard_collections
self.use_union_operator = use_union_operator
self.exclude_typename_field = exclude_typename_field

def _get_context_source_path_parts(self) -> Iterator[tuple[Source, list[str]]]:
# TODO (denisart): Temporarily this method duplicates
Expand Down Expand Up @@ -450,8 +452,8 @@ def parse_object_like(

data_model_field_type = self.parse_field(field_name_, alias, field)
fields.append(data_model_field_type)

fields.append(self._typename_field(obj.name))
if not self.exclude_typename_field:
fields.append(self._typename_field(obj.name))

base_classes = []
if hasattr(obj, "interfaces"): # pragma: no cover
Expand Down
24 changes: 24 additions & 0 deletions tests/data/expected/parser/graphql/exclude_typename_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# generated by datamodel-codegen:
# filename: exclude-typename-field.graphql
# timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import TypeAlias

from pydantic import BaseModel

Boolean: TypeAlias = bool
"""
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.
"""


class A(BaseModel):
field: String
3 changes: 3 additions & 0 deletions tests/data/graphql/exclude-typename-field.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type A {
field: String!
}
17 changes: 17 additions & 0 deletions tests/parser/test_graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,20 @@ def test_graphql_union_aliased_bug() -> None:
if actual != expected:
pass
assert actual == expected


@freeze_time("2019-07-26")
def test_main_graphql_exclude_typename_field() -> None:
with TemporaryDirectory() as output_dir:
output_file: Path = Path(output_dir) / "output.py"
return_code: Exit = main([
"--input",
str(GRAPHQL_DATA_PATH / "exclude-typename-field.graphql"),
"--output",
str(output_file),
"--input-file-type",
"graphql",
"--exclude-typename-field",
])
assert return_code == Exit.OK
assert output_file.read_text() == (EXPECTED_GRAPHQL_PATH / "exclude_typename_field.py").read_text()
Loading