fastapi-sqlalchemy-toolkit 0.7.18__tar.gz → 0.7.19__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/PKG-INFO +1 -1
  2. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/fastapi_sqlalchemy_toolkit/model_manager.py +50 -18
  3. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/pyproject.toml +1 -1
  4. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/tests/test_public_methods.py +2 -2
  5. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/.flake8 +0 -0
  6. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/.github/workflows/docker-test.yml +0 -0
  7. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/.github/workflows/python-publish.yml +0 -0
  8. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/.gitignore +0 -0
  9. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/.pylintrc +0 -0
  10. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/AUTHORS +0 -0
  11. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/LICENSE +0 -0
  12. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/Makefile +0 -0
  13. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/README.md +0 -0
  14. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/benefits.md +0 -0
  15. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/db_validation.md +0 -0
  16. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/extension.md +0 -0
  17. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/filtering.md +0 -0
  18. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/index.md +0 -0
  19. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/benefits.md +0 -0
  20. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/db_validation.md +0 -0
  21. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/extension.md +0 -0
  22. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/filtering.md +0 -0
  23. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/index.md +0 -0
  24. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/sorting.md +0 -0
  25. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/transactions.md +0 -0
  26. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/usage.md +0 -0
  27. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/ru/utils.md +0 -0
  28. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/sorting.md +0 -0
  29. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/transactions.md +0 -0
  30. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/usage.md +0 -0
  31. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/docs/utils.md +0 -0
  32. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/.env +0 -0
  33. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/__init__.py +0 -0
  34. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/api/__init__.py +0 -0
  35. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/api/api.py +0 -0
  36. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/api/deps.py +0 -0
  37. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/api/endpoints/__init__.py +0 -0
  38. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/api/endpoints/child.py +0 -0
  39. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/config.py +0 -0
  40. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/db.py +0 -0
  41. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/main.py +0 -0
  42. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/managers.py +0 -0
  43. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/models.py +0 -0
  44. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/examples/app/schemas.py +0 -0
  45. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/fastapi_sqlalchemy_toolkit/__init__.py +0 -0
  46. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/fastapi_sqlalchemy_toolkit/filters.py +0 -0
  47. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/fastapi_sqlalchemy_toolkit/ordering.py +0 -0
  48. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/fastapi_sqlalchemy_toolkit/utils.py +0 -0
  49. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/mkdocs.yml +0 -0
  50. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/requirements/base.txt +0 -0
  51. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/requirements/docs.txt +0 -0
  52. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/requirements/lint.txt +0 -0
  53. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/requirements/test.txt +0 -0
  54. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/tests/Dockerfile +0 -0
  55. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/tests/__init__.py +0 -0
  56. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/tests/conftest.py +0 -0
  57. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/tests/db.py +0 -0
  58. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/tests/docker-compose.yml +0 -0
  59. {fastapi_sqlalchemy_toolkit-0.7.18 → fastapi_sqlalchemy_toolkit-0.7.19}/tests/models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi_sqlalchemy_toolkit
3
- Version: 0.7.18
3
+ Version: 0.7.19
4
4
  Summary: FastAPI SQLAlchemy Toolkit
5
5
  Project-URL: Homepage, https://github.com/e-kondr01/fastapi-sqlalchemy-toolkit
6
6
  Author-email: Egor Kondrashov <e.kondr01@gmail.com>
@@ -1051,6 +1051,37 @@ class ModelManager(Generic[ModelT, CreateSchemaT, UpdateSchemaT]):
1051
1051
 
1052
1052
  return stmt
1053
1053
 
1054
+ @staticmethod
1055
+ def get_error_msg(
1056
+ tablename: str,
1057
+ fields: List[str],
1058
+ *,
1059
+ exists: bool = True,
1060
+ field_values: List[Any] | None = None,
1061
+ ) -> str:
1062
+ """
1063
+ Формирует сообщение об ошибке, которое будет возвращаться при ошибках валидации.
1064
+ """
1065
+
1066
+ error_msg = tablename
1067
+ error_msg += " с "
1068
+ if field_values:
1069
+ fields_with_values = []
1070
+ for field, value in zip(fields, field_values, strict=True):
1071
+ fields_with_values.append(f"{field} {value}")
1072
+ error_msg += ", ".join(fields_with_values)
1073
+ else:
1074
+ error_msg += "таким"
1075
+ if len(fields) > 1:
1076
+ error_msg += "и"
1077
+ error_msg += " "
1078
+ error_msg += ", ".join(fields)
1079
+ if exists:
1080
+ error_msg += " уже существует."
1081
+ else:
1082
+ error_msg += " не существует."
1083
+ return error_msg
1084
+
1054
1085
  async def validate_fk_exists(
1055
1086
  self, session: AsyncSession, in_obj: ModelDict
1056
1087
  ) -> None:
@@ -1068,9 +1099,11 @@ class ModelManager(Generic[ModelT, CreateSchemaT, UpdateSchemaT]):
1068
1099
  if not related_object_exists:
1069
1100
  raise HTTPException(
1070
1101
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
1071
- detail=(
1072
- f"{self.fk_name_to_model[key].__tablename__} с id "
1073
- f"{in_obj[key]} не существует."
1102
+ detail=self.get_error_msg(
1103
+ self.fk_name_to_model[key].__tablename__,
1104
+ ["id"],
1105
+ field_values=[in_obj[key]],
1106
+ exists=False,
1074
1107
  ),
1075
1108
  )
1076
1109
 
@@ -1096,13 +1129,10 @@ class ModelManager(Generic[ModelT, CreateSchemaT, UpdateSchemaT]):
1096
1129
  session, **query, where=(self.model.id != in_obj.get("id"))
1097
1130
  )
1098
1131
  if object_exists:
1099
- conflicting_fields = ", ".join(unique_constraint)
1100
1132
  raise HTTPException(
1101
1133
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
1102
- detail=(
1103
- f"{self.model.__tablename__} с такими "
1104
- + conflicting_fields
1105
- + " уже существует."
1134
+ detail=self.get_error_msg(
1135
+ self.model.__tablename__, unique_constraint
1106
1136
  ),
1107
1137
  )
1108
1138
 
@@ -1132,9 +1162,10 @@ class ModelManager(Generic[ModelT, CreateSchemaT, UpdateSchemaT]):
1132
1162
  if object_exists:
1133
1163
  raise HTTPException(
1134
1164
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
1135
- detail=(
1136
- f"{self.model.__tablename__} c {column.name} "
1137
- f"{in_obj[column.name]} уже существует"
1165
+ detail=self.get_error_msg(
1166
+ self.model.__tablename__,
1167
+ [column.name],
1168
+ field_values=[in_obj[column.name]],
1138
1169
  ),
1139
1170
  )
1140
1171
 
@@ -1166,10 +1197,9 @@ class ModelManager(Generic[ModelT, CreateSchemaT, UpdateSchemaT]):
1166
1197
  if object_exists:
1167
1198
  raise HTTPException(
1168
1199
  status_code=status.HTTP_400_BAD_REQUEST,
1169
- detail=(
1170
- f"{self.model.__tablename__} с такими "
1171
- + ", ".join([column.name for column in index.columns])
1172
- + " уже существует."
1200
+ detail=self.get_error_msg(
1201
+ self.model.__tablename__,
1202
+ [column.name for column in index.columns],
1173
1203
  ),
1174
1204
  )
1175
1205
 
@@ -1183,9 +1213,11 @@ class ModelManager(Generic[ModelT, CreateSchemaT, UpdateSchemaT]):
1183
1213
  if not related_object:
1184
1214
  raise HTTPException(
1185
1215
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
1186
- detail=(
1187
- f"{related_model.__tablename__} с id "
1188
- f"{related_object_id} не существует."
1216
+ detail=self.get_error_msg(
1217
+ related_model.__tablename__,
1218
+ ["id"],
1219
+ field_values=[related_object_id],
1220
+ exists=False,
1189
1221
  ),
1190
1222
  )
1191
1223
  related_objects.append(related_object)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "fastapi_sqlalchemy_toolkit"
7
- version = "0.7.18"
7
+ version = "0.7.19"
8
8
  authors = [
9
9
  { name="Egor Kondrashov", email="e.kondr01@gmail.com" },
10
10
  ]
@@ -288,7 +288,7 @@ async def test_create_unique_filed_validation(session: AsyncSession):
288
288
  )
289
289
  with pytest.raises(
290
290
  HTTPException,
291
- match="422: category c title test-create-category-title уже существует",
291
+ match="422: category с title test-create-category-title уже существует.",
292
292
  ):
293
293
  await category_manager.create(
294
294
  session=session, title="test-create-category-title"
@@ -353,7 +353,7 @@ async def test_update_unique_filed_validation(session: AsyncSession):
353
353
  )
354
354
  with pytest.raises(
355
355
  HTTPException,
356
- match="422: category c title test-category-title1 уже существует",
356
+ match="422: category с title test-category-title1 уже существует.",
357
357
  ):
358
358
  await category_manager.update(
359
359
  session=session,