From 886a1a7ccd0bc6b19b562793b41d546587c57cf5 Mon Sep 17 00:00:00 2001 From: Tvrtko Sternak Date: Tue, 29 Apr 2025 08:54:19 +0200 Subject: [PATCH] Remove deprecated datamodel-code-generator patch --- fastapi_code_generator/__init__.py | 3 - fastapi_code_generator/patches.py | 257 ----------------------------- poetry.lock | 10 +- pyproject.toml | 2 +- 4 files changed, 6 insertions(+), 266 deletions(-) delete mode 100644 fastapi_code_generator/patches.py diff --git a/fastapi_code_generator/__init__.py b/fastapi_code_generator/__init__.py index c998a3db..e69de29b 100644 --- a/fastapi_code_generator/__init__.py +++ b/fastapi_code_generator/__init__.py @@ -1,3 +0,0 @@ -from .patches import patch_parse - -patch_parse() diff --git a/fastapi_code_generator/patches.py b/fastapi_code_generator/patches.py deleted file mode 100644 index f3f4dd37..00000000 --- a/fastapi_code_generator/patches.py +++ /dev/null @@ -1,257 +0,0 @@ -# todo: remove this file when the following PR is merged into datamodels-code-generator: -# -# https://github.com/koxudaxi/datamodel-code-generator/pull/2379 - -import logging -from itertools import groupby -from pathlib import Path -from typing import NamedTuple, Optional, Union - -from datamodel_code_generator.format import CodeFormatter -from datamodel_code_generator.imports import IMPORT_ANNOTATIONS, Import, Imports -from datamodel_code_generator.model.base import DataModel -from datamodel_code_generator.parser import base -from datamodel_code_generator.reference import ModelResolver - -logger = logging.getLogger(__name__) - -# Save the original method before patching -original_parse = base.Parser.parse - - -def patch_parse() -> None: # noqa: C901 - def __alias_shadowed_imports( - self: base.Parser, - models: list[DataModel], - all_model_field_names: set[str], - ) -> None: - for model in models: - for model_field in model.fields: - if model_field.data_type.type in all_model_field_names: - alias = model_field.data_type.type + "_aliased" - model_field.data_type.type = alias - if model_field.data_type.import_: - model_field.data_type.import_.alias = alias - - def _parse( # noqa: PLR0912, PLR0914, PLR0915 - self: base.Parser, - with_import: Optional[bool] = True, # noqa: FBT001, FBT002 - format_: Optional[bool] = True, # noqa: FBT001, FBT002 - settings_path: Optional[Path] = None, - ) -> Union[str, dict[tuple[str, ...], base.Result]]: - self.parse_raw() - - if with_import: - self.imports.append(IMPORT_ANNOTATIONS) - - if format_: - code_formatter: Optional[CodeFormatter] = CodeFormatter( - self.target_python_version, - settings_path, - self.wrap_string_literal, - skip_string_normalization=not self.use_double_quotes, - known_third_party=self.known_third_party, - custom_formatters=self.custom_formatter, - custom_formatters_kwargs=self.custom_formatters_kwargs, - encoding=self.encoding, - formatters=self.formatters, - ) - else: - code_formatter = None - - _, sorted_data_models, require_update_action_models = base.sort_data_models( - self.results - ) - - results: dict[tuple[str, ...], base.Result] = {} - - def module_key(data_model: DataModel) -> tuple[str, ...]: - return tuple(data_model.module_path) - - def sort_key(data_model: DataModel) -> tuple[int, tuple[str, ...]]: - return (len(data_model.module_path), tuple(data_model.module_path)) - - # process in reverse order to correctly establish module levels - grouped_models = groupby( - sorted(sorted_data_models.values(), key=sort_key, reverse=True), - key=module_key, - ) - - module_models: list[tuple[tuple[str, ...], list[DataModel]]] = [] - unused_models: list[DataModel] = [] - model_to_module_models: dict[ - DataModel, tuple[tuple[str, ...], list[DataModel]] - ] = {} - module_to_import: dict[tuple[str, ...], Imports] = {} - - previous_module: tuple[str, ...] = () - for module, models in ((k, [*v]) for k, v in grouped_models): - for model in models: - model_to_module_models[model] = module, models - self._Parser__delete_duplicate_models(models) # type: ignore[attr-defined] - self._Parser__replace_duplicate_name_in_module(models) # type: ignore[attr-defined] - if len(previous_module) - len(module) > 1: - module_models.extend( - ( - previous_module[:parts], - [], - ) - for parts in range(len(previous_module) - 1, len(module), -1) - ) - module_models.append( - ( - module, - models, - ) - ) - previous_module = module - - class Processed(NamedTuple): - module: tuple[str, ...] - models: list[DataModel] - init: bool - imports: Imports - scoped_model_resolver: ModelResolver - - processed_models: list[Processed] = [] - - for module_, models in module_models: - imports = module_to_import[module_] = Imports(self.use_exact_imports) - init = False - if module_: - parent = (*module_[:-1], "__init__.py") - if parent not in results: - results[parent] = base.Result(body="") - if (*module_, "__init__.py") in results: - module = (*module_, "__init__.py") - init = True - else: - module = tuple( - part.replace("-", "_") - for part in (*module_[:-1], f"{module_[-1]}.py") - ) - else: - module = ("__init__.py",) - - all_module_fields = { - field.name - for model in models - for field in model.fields - if field.name is not None - } - scoped_model_resolver = ModelResolver(exclude_names=all_module_fields) - - self.__alias_shadowed_imports(models, all_module_fields) # type: ignore[attr-defined] - self._Parser__override_required_field(models) # type: ignore[attr-defined] - self._Parser__replace_unique_list_to_set(models) # type: ignore[attr-defined] - self._Parser__change_from_import( # type: ignore[attr-defined] - models, imports, scoped_model_resolver, init - ) - self._Parser__extract_inherited_enum(models) # type: ignore[attr-defined] - self._Parser__set_reference_default_value_to_field(models) # type: ignore[attr-defined] - self._Parser__reuse_model(models, require_update_action_models) # type: ignore[attr-defined] - self._Parser__collapse_root_models( # type: ignore[attr-defined] - models, unused_models, imports, scoped_model_resolver - ) - self._Parser__set_default_enum_member(models) # type: ignore[attr-defined] - self._Parser__sort_models(models, imports) # type: ignore[attr-defined] - self._Parser__change_field_name(models) # type: ignore[attr-defined] - self._Parser__apply_discriminator_type(models, imports) # type: ignore[attr-defined] - self._Parser__set_one_literal_on_default(models) # type: ignore[attr-defined] - - processed_models.append( - Processed(module, models, init, imports, scoped_model_resolver) - ) - - for processed_model in processed_models: - for model in processed_model.models: - processed_model.imports.append(model.imports) - - for unused_model in unused_models: - module, models = model_to_module_models[unused_model] - if unused_model in models: # pragma: no cover - imports = module_to_import[module] - imports.remove(unused_model.imports) - models.remove(unused_model) - - for processed_model in processed_models: - # postprocess imports to remove unused imports. - model_code = str("\n".join([str(m) for m in processed_model.models])) - unused_imports = [ - (from_, import_) - for from_, imports_ in processed_model.imports.items() - for import_ in imports_ - if import_ not in model_code - ] - for from_, import_ in unused_imports: - processed_model.imports.remove(Import(from_=from_, import_=import_)) - - for ( - module, - models, - init, - imports, - scoped_model_resolver, - ) in processed_models: # noqa: B007 - # process after removing unused models - self._Parser__change_imported_model_name( # type: ignore[attr-defined] - models, imports, scoped_model_resolver - ) - - for ( - module, - models, - init, - imports, - scoped_model_resolver, - ) in processed_models: # noqa: B007 - result: list[str] = [] - if models: - if with_import: - result += [str(self.imports), str(imports), "\n"] - - code = base.dump_templates(models) - result += [code] - - if self.dump_resolve_reference_action is not None: - result += [ - "\n", - self.dump_resolve_reference_action( - m.reference.short_name - for m in models - if m.path in require_update_action_models - ), - ] - if not result and not init: - continue - body = "\n".join(result) - if code_formatter: - body = code_formatter.format_code(body) - - results[module] = base.Result( - body=body, source=models[0].file_path if models else None - ) - - # retain existing behaviour - if [*results] == [("__init__.py",)]: - return results["__init__.py",].body - - results = {tuple(i.replace("-", "_") for i in k): v for k, v in results.items()} - return ( - self._Parser__postprocess_result_modules(results) # type: ignore[attr-defined] - if self.treat_dot_as_module - else { - tuple( - ( - part[: part.rfind(".")].replace(".", "_") - + part[part.rfind(".") :] - ) - for part in k - ): v - for k, v in results.items() - } - ) - - base.Parser.parse = _parse # type: ignore[method-assign] - base.Parser.__alias_shadowed_imports = __alias_shadowed_imports # type: ignore[attr-defined] - logger.info("Patched Parser.parse method.") diff --git a/poetry.lock b/poetry.lock index e8b87169..15805dcd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -207,14 +207,14 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "datamodel-code-generator" -version = "0.28.5" +version = "0.30.1" description = "Datamodel Code Generator" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "datamodel_code_generator-0.28.5-py3-none-any.whl", hash = "sha256:f899c1da5af04b5d5b6e3edbd718c1bf3a00fc4b2fe8210cef609d93a9983e9e"}, - {file = "datamodel_code_generator-0.28.5.tar.gz", hash = "sha256:20e8b817d301d2d0bb15f436e81c97b25ad1c2ef922c99249c2444141ae15a6a"}, + {file = "datamodel_code_generator-0.30.1-py3-none-any.whl", hash = "sha256:9601dfa3da8aa8d8d54e182059f78836b1768a807d5c26df798db12d4054c8f3"}, + {file = "datamodel_code_generator-0.30.1.tar.gz", hash = "sha256:d125012face4cd1eca6c9300297a1f5775a9d5ff8fc3f68d34d0944a7beea105"}, ] [package.dependencies] @@ -222,7 +222,7 @@ argcomplete = ">=2.10.1,<4" black = ">=19.10b0" genson = ">=1.2.1,<2" httpx = {version = ">=0.24.1", optional = true, markers = "extra == \"http\""} -inflect = ">=4.1,<6" +inflect = ">=4.1,<8" isort = ">=4.3.21,<7" jinja2 = ">=2.10.1,<4" packaging = "*" @@ -1118,4 +1118,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = ">=3.9,<3.13" -content-hash = "4c877a8538b055a678c7b0389bbe91cb862a0ecbc41d8fbd843b43be7999b23d" +content-hash = "bccd26ae3de77265e6562e8d741884c06fb75fd4aa04aa515bf34292bda7df91" diff --git a/pyproject.toml b/pyproject.toml index d3726ecc..0d471115 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ fastapi-codegen = "fastapi_code_generator.__main__:app" [tool.poetry.dependencies] python = ">=3.9,<3.13" typer = {extras = ["all"], version = ">=0.2.1,<0.13.0"} -datamodel-code-generator = {extras = ["http"], version = "0.28.5"} +datamodel-code-generator = {extras = ["http"], version = "0.30.1"} stringcase = "^1.2.0" PySnooper = ">=0.4.1,<1.2.0" jinja2 = ">=2.11.2,<4.0.0"