aiteamutils 0.2.137__py3-none-any.whl → 0.2.138__py3-none-any.whl

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.
@@ -65,6 +65,31 @@ class BaseService(Generic[ModelType]):
65
65
  )
66
66
 
67
67
  try:
68
+ # 파일 데이터 분리
69
+ entity_data_copy = entity_data.copy()
70
+ separated_files = {}
71
+
72
+ # extra_data 내의 파일 필드 분리
73
+ if 'extra_data' in entity_data_copy and isinstance(entity_data_copy['extra_data'], dict):
74
+ extra_data = entity_data_copy['extra_data'].copy()
75
+ file_fields = {k: v for k, v in extra_data.items() if k.endswith('_files')}
76
+
77
+ if file_fields and not storage_dir:
78
+ raise CustomException(
79
+ ErrorCode.INVALID_INPUT,
80
+ detail="storage_dir is required for file upload",
81
+ source_function=f"base_service.{self.__class__.__name__}.create.file_fields"
82
+ )
83
+
84
+ # 파일 필드 분리 및 제거
85
+ for field_name, files in file_fields.items():
86
+ if files:
87
+ separated_files[field_name] = files
88
+ # extra_data에서 파일 필드 제거
89
+ del extra_data[field_name]
90
+
91
+ entity_data_copy['extra_data'] = extra_data
92
+
68
93
  async with self.db_session.begin():
69
94
  # 고유 검사 수행
70
95
  if unique_check:
@@ -73,35 +98,44 @@ class BaseService(Generic[ModelType]):
73
98
  if fk_check:
74
99
  await validate_unique_fields(self.db_session, fk_check, find_value=False)
75
100
 
76
- # _files로 끝나는 키 처리
77
- file_keys = [key for key in entity_data.keys() if key.endswith('_files')]
78
- file_infos = {}
79
-
80
- if file_keys and not storage_dir:
81
- raise CustomException(
82
- ErrorCode.INVALID_INPUT,
83
- detail="storage_dir is required for file upload",
84
- source_function=f"base_service.{self.__class__.__name__}.create.file_keys"
85
- )
86
-
87
- # 먼저 엔티티를 생성하여 ULID를 얻음
101
+ # 엔티티 생성
88
102
  result = await self.repository.create(
89
- entity_data=entity_data,
103
+ entity_data=entity_data_copy,
90
104
  exclude_entities=exclude_entities
91
105
  )
92
106
 
93
- # 파일 처리
94
- for file_key in file_keys:
95
- files_data = entity_data.pop(file_key) # 파일 데이터 추출 및 제거
96
- if files_data:
97
- from .files import FileHandler
98
- file_infos[file_key] = await FileHandler.save_files(
99
- files=files_data,
107
+ # 파일 처리 및 저장
108
+ file_infos = {}
109
+ if separated_files:
110
+ from .files import FileHandler
111
+ for field_name, files in separated_files.items():
112
+ saved_files = await FileHandler.save_files(
113
+ files=files,
100
114
  storage_dir=storage_dir,
101
115
  entity_name=self.model.__tablename__,
102
116
  entity_ulid=result.ulid,
103
117
  db_session=self.db_session
104
118
  )
119
+ file_infos[field_name] = saved_files
120
+
121
+ # extra_data 업데이트
122
+ if not hasattr(result, 'extra_data'):
123
+ result.extra_data = {}
124
+ if not result.extra_data:
125
+ result.extra_data = {}
126
+
127
+ result.extra_data[field_name] = [
128
+ {
129
+ 'original_name': f['original_name'],
130
+ 'storage_path': f['storage_path'],
131
+ 'mime_type': f['mime_type'],
132
+ 'size': f['size'],
133
+ 'checksum': f['checksum']
134
+ } for f in saved_files
135
+ ]
136
+
137
+ # extra_data 업데이트된 엔티티 저장
138
+ await self.db_session.flush()
105
139
 
106
140
  # 결과 반환
107
141
  if response_model:
aiteamutils/validators.py CHANGED
@@ -1,12 +1,12 @@
1
1
  """유효성 검사 관련 유틸리티 함수들을 모아둔 모듈입니다."""
2
2
 
3
- from typing import Type, Dict, Any, Callable, TypeVar, Optional, List, Union
3
+ from typing import Type, Dict, Any, Callable, TypeVar, Optional, List, Union, Annotated
4
4
  from functools import wraps
5
5
  from sqlalchemy import Table
6
6
  from sqlalchemy.ext.asyncio import AsyncSession
7
7
  from fastapi import Request
8
8
  from inspect import signature
9
- from pydantic import BaseModel, field_validator
9
+ from pydantic import BaseModel, field_validator, Field
10
10
  from datetime import datetime, date
11
11
  import re
12
12
 
@@ -234,64 +234,3 @@ class Validator:
234
234
  source_function="Validator.validate_datetime",
235
235
  original_error=str(e)
236
236
  )
237
-
238
- def _create_validator(field_names: tuple[str, ...],
239
- validate_func: Callable,
240
- field_type: Type,
241
- error_code: ErrorCode,
242
- source_prefix: str):
243
- """공통 validator 생성 함수
244
- Args:
245
- field_names: 검증할 필드명들
246
- validate_func: 실제 검증을 수행할 함수
247
- field_type: 필드 타입 (date 또는 datetime)
248
- error_code: 에러 발생시 사용할 에러 코드
249
- source_prefix: 에러 발생시 사용할 source_function 접두사
250
- """
251
- def decorator(cls):
252
- for field_name in field_names:
253
- field = cls.model_fields.get(field_name)
254
- if field:
255
- field.annotation = Optional[field_type]
256
- field.default = None
257
-
258
- @field_validator(field_name, mode='before')
259
- @classmethod
260
- def validate(cls, value: Any, info: Any) -> Any:
261
- # 빈 값 처리를 가장 먼저, 더 엄격하게
262
- if not value or str(value).strip() == "":
263
- return None
264
- try:
265
- return validate_func(value, field_name)
266
- except CustomException as e:
267
- raise e
268
- except Exception as e:
269
- raise CustomException(
270
- error_code=error_code,
271
- detail=f"{field_name}|{value}",
272
- source_function=f"{source_prefix}.{field_name}",
273
- original_error=str(e)
274
- )
275
- setattr(cls, f'validate_{field_name}', validate)
276
- return cls
277
- return decorator
278
-
279
- def date_validator(*field_names: str):
280
- """날짜 필드 유효성 검사 데코레이터"""
281
- return _create_validator(
282
- field_names=field_names,
283
- validate_func=Validator.validate_date,
284
- field_type=date,
285
- error_code=ErrorCode.VALIDATION_ERROR,
286
- source_prefix="date_validator"
287
- )
288
-
289
- def datetime_validator(*field_names: str):
290
- """날짜+시간 필드 유효성 검사 데코레이터"""
291
- return _create_validator(
292
- field_names=field_names,
293
- validate_func=Validator.validate_datetime,
294
- field_type=datetime,
295
- error_code=ErrorCode.VALIDATION_ERROR,
296
- source_prefix="datetime_validator"
297
- )
aiteamutils/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  """버전 정보"""
2
- __version__ = "0.2.137"
2
+ __version__ = "0.2.138"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiteamutils
3
- Version: 0.2.137
3
+ Version: 0.2.138
4
4
  Summary: AI Team Utilities
5
5
  Project-URL: Homepage, https://github.com/yourusername/aiteamutils
6
6
  Project-URL: Issues, https://github.com/yourusername/aiteamutils/issues
@@ -1,7 +1,7 @@
1
1
  aiteamutils/__init__.py,sha256=kRBpRjark0M8ZwFfmKiMFol6CbIILN3WE4f6_P6iIq0,1089
2
2
  aiteamutils/base_model.py,sha256=0rs4cjnF2ea3Q2vBTj6F64BGk7ZglJsChsS7ne_R_tg,4056
3
3
  aiteamutils/base_repository.py,sha256=Oy2zE1i5qx60Xf1tnsaKLyFWapiPqt5JH8NejwNrPWg,4647
4
- aiteamutils/base_service.py,sha256=LrmntqvNx8SxgNrumkkPMv0vaKMMPVJrHzoXmDdx83M,12839
4
+ aiteamutils/base_service.py,sha256=QSUzdIcV88EdmjEF7vMyrN5CjKhS6HTbsoXSp8P9Gag,14432
5
5
  aiteamutils/cache.py,sha256=07xBGlgAwOTAdY5mnMOQJ5EBxVwe8glVD7DkGEkxCtw,1373
6
6
  aiteamutils/config.py,sha256=YdalpJb70-txhGJAS4aaKglEZAFVWgfzw5BXSWpkUz4,3232
7
7
  aiteamutils/database.py,sha256=msvBKtxWeQVOo0v2Q9i2azuTNtnUItuNNar52gdRZTo,20418
@@ -9,8 +9,8 @@ aiteamutils/enums.py,sha256=7WLqlcJqQWtETAga2WAxNp3dJTQIAd2TW-4WzkoHHa8,2498
9
9
  aiteamutils/exceptions.py,sha256=pgf3ersezObyl17wAO3I2fb8m9t2OzWDX1mSjwAWm2Y,16035
10
10
  aiteamutils/files.py,sha256=tdvivl3XLNv7Al7H1gGFczmrHM8XlQpiZsEc2xQ_UTU,8829
11
11
  aiteamutils/security.py,sha256=McUl3t5Z5SyUDVUHymHdDkYyF4YSeg4g9fFMML4W6Kw,11630
12
- aiteamutils/validators.py,sha256=msOrha36xWsapm4VAh63YmFq1GVyC9tzZcjXYFCEZ_g,11949
13
- aiteamutils/version.py,sha256=paOXlTEx5pKbXz3iDW_A_JPzLhKBZg6PmXu5SqD_82I,43
14
- aiteamutils-0.2.137.dist-info/METADATA,sha256=4dfPUZv6C9Xoq8E0HbsY8ToWEx_lsCLpM8qawukEPz0,1719
15
- aiteamutils-0.2.137.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- aiteamutils-0.2.137.dist-info/RECORD,,
12
+ aiteamutils/validators.py,sha256=_WHN6jqJQzKM5uPTg-Da8U2qqevS84XeKMkCCF4C_lY,9591
13
+ aiteamutils/version.py,sha256=xZySMcOyLEq-gP55_1pxieeIS9BbYr1Tg7GT4OJHMjI,43
14
+ aiteamutils-0.2.138.dist-info/METADATA,sha256=Hc55YOzeewQdyvH7AGj17BxER6ZiOIptMcPCY87XyXE,1719
15
+ aiteamutils-0.2.138.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ aiteamutils-0.2.138.dist-info/RECORD,,