aiteamutils 0.2.31__py3-none-any.whl → 0.2.33__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
aiteamutils/config.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """설정 모듈."""
2
2
  from typing import Union
3
3
  from .database import init_database_service
4
+ from .exceptions import CustomException, ErrorCode
4
5
 
5
6
  class Settings:
6
7
  """기본 설정 클래스"""
@@ -74,8 +75,12 @@ def get_settings() -> Settings:
74
75
  Settings: 설정 객체
75
76
 
76
77
  Raises:
77
- RuntimeError: 설정이 초기화되지 않은 경우
78
+ CustomException: 설정이 초기화되지 않은 경우
78
79
  """
79
80
  if _settings is None:
80
- raise RuntimeError("Settings not initialized. Call init_settings first.")
81
+ raise CustomException(
82
+ ErrorCode.INTERNAL_ERROR,
83
+ detail="settings",
84
+ source_function="get_settings"
85
+ )
81
86
  return _settings
aiteamutils/database.py CHANGED
@@ -26,10 +26,14 @@ def get_database_service() -> 'DatabaseService':
26
26
  DatabaseService: DatabaseService 인스턴스
27
27
 
28
28
  Raises:
29
- RuntimeError: DatabaseService가 초기화되지 않은 경우
29
+ CustomException: DatabaseService가 초기화되지 않은 경우
30
30
  """
31
31
  if _database_service is None:
32
- raise RuntimeError("DatabaseService not initialized. Call init_settings with db_url first.")
32
+ raise CustomException(
33
+ ErrorCode.DB_CONNECTION_ERROR,
34
+ detail="database_service",
35
+ source_function="get_database_service"
36
+ )
33
37
  return _database_service
34
38
 
35
39
  async def get_db() -> AsyncGenerator[AsyncSession, None]:
@@ -100,13 +104,21 @@ class DatabaseService:
100
104
  )
101
105
  self.db = session
102
106
  else:
103
- raise ValueError("Either db_url or session must be provided")
107
+ raise CustomException(
108
+ ErrorCode.DB_CONNECTION_ERROR,
109
+ detail="db_url|session",
110
+ source_function="DatabaseService.__init__"
111
+ )
104
112
 
105
113
  @asynccontextmanager
106
114
  async def get_session(self) -> AsyncGenerator[AsyncSession, None]:
107
115
  """데이터베이스 세션을 생성하고 반환하는 비동기 컨텍스트 매니저."""
108
116
  if self.session_factory is None:
109
- raise RuntimeError("Session factory not initialized")
117
+ raise CustomException(
118
+ ErrorCode.DB_CONNECTION_ERROR,
119
+ detail="session_factory",
120
+ source_function="DatabaseService.get_session"
121
+ )
110
122
 
111
123
  async with self.session_factory() as session:
112
124
  try:
@@ -26,10 +26,14 @@ class ServiceRegistry:
26
26
  service_class (Type): Service 클래스
27
27
 
28
28
  Raises:
29
- ValueError: 이미 등록된 서비스인 경우
29
+ CustomException: 이미 등록된 서비스인 경우
30
30
  """
31
31
  if name in self._services:
32
- raise ValueError(f"Service '{name}' is already registered.")
32
+ raise CustomException(
33
+ ErrorCode.INTERNAL_ERROR,
34
+ detail=f"service|{name}",
35
+ source_function="ServiceRegistry.register"
36
+ )
33
37
  self._services[name] = (repository_class, service_class)
34
38
 
35
39
  def get(self, name: str) -> Tuple[Type, Type]:
@@ -42,10 +46,14 @@ class ServiceRegistry:
42
46
  Tuple[Type, Type]: (Repository 클래스, Service 클래스) 튜플
43
47
 
44
48
  Raises:
45
- ValueError: 등록되지 않은 서비스인 경우
49
+ CustomException: 등록되지 않은 서비스인 경우
46
50
  """
47
51
  if name not in self._services:
48
- raise ValueError(f"Service '{name}' is not registered.")
52
+ raise CustomException(
53
+ ErrorCode.NOT_FOUND,
54
+ detail=f"service|{name}",
55
+ source_function="ServiceRegistry.get"
56
+ )
49
57
  return self._services[name]
50
58
 
51
59
  # ServiceRegistry 초기화
@@ -60,10 +68,10 @@ def get_service(name: str):
60
68
  Returns:
61
69
  Callable: 서비스 인스턴스를 반환하는 의존성 함수
62
70
  """
63
- def _get_service(db: AsyncSession = Depends(get_db)):
71
+ def _get_service(db_service: DatabaseService = Depends(get_database_service)):
64
72
  repository_class, service_class = service_registry.get(name)
65
- repository = repository_class(db)
66
- return service_class(repository, db)
73
+ repository = repository_class(db_service)
74
+ return service_class(repository, db_service)
67
75
  return _get_service
68
76
 
69
77
  oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/token")
aiteamutils/security.py CHANGED
@@ -157,8 +157,19 @@ def verify_password(plain_password: str, hashed_password: str) -> bool:
157
157
 
158
158
  Returns:
159
159
  bool: 비밀번호 일치 여부
160
+
161
+ Raises:
162
+ CustomException: 비밀번호 검증 실패 시
160
163
  """
161
- return pwd_context.verify(plain_password, hashed_password)
164
+ try:
165
+ return pwd_context.verify(plain_password, hashed_password)
166
+ except Exception as e:
167
+ raise CustomException(
168
+ ErrorCode.INVALID_PASSWORD,
169
+ detail=plain_password,
170
+ source_function="security.verify_password",
171
+ original_error=e
172
+ )
162
173
 
163
174
  def hash_password(password: str) -> str:
164
175
  """비밀번호를 해시화합니다.
@@ -168,8 +179,19 @@ def hash_password(password: str) -> str:
168
179
 
169
180
  Returns:
170
181
  str: 해시된 비밀번호
182
+
183
+ Raises:
184
+ CustomException: 비밀번호 해시화 실패 시
171
185
  """
172
- return pwd_context.hash(password)
186
+ try:
187
+ return pwd_context.hash(password)
188
+ except Exception as e:
189
+ raise CustomException(
190
+ ErrorCode.INTERNAL_ERROR,
191
+ detail=password,
192
+ source_function="security.hash_password",
193
+ original_error=e
194
+ )
173
195
 
174
196
  def rate_limit(
175
197
  max_requests: int,
@@ -288,10 +310,10 @@ async def create_jwt_token(
288
310
  required_fields = {"username", "ulid"}
289
311
  missing_fields = required_fields - set(user_data.keys())
290
312
  if missing_fields:
291
- raise TokenCreationError(
292
- detail=f"Missing required fields: {', '.join(missing_fields)}",
293
- source_function="create_jwt_token",
294
- token_type=token_type
313
+ raise CustomException(
314
+ ErrorCode.REQUIRED_FIELD_MISSING,
315
+ detail="|".join(missing_fields),
316
+ source_function="security.create_jwt_token"
295
317
  )
296
318
 
297
319
  if token_type == "access":
@@ -337,10 +359,10 @@ async def create_jwt_token(
337
359
  algorithm=settings.JWT_ALGORITHM
338
360
  )
339
361
  except Exception as e:
340
- raise TokenCreationError(
341
- detail="Failed to encode JWT token",
342
- source_function="create_jwt_token",
343
- token_type=token_type,
362
+ raise CustomException(
363
+ ErrorCode.INTERNAL_ERROR,
364
+ detail=f"token|{token_type}",
365
+ source_function="security.create_jwt_token",
344
366
  original_error=e
345
367
  )
346
368
 
@@ -362,13 +384,13 @@ async def create_jwt_token(
362
384
 
363
385
  return token
364
386
 
365
- except (TokenCreationError, SecurityError) as e:
387
+ except CustomException as e:
366
388
  raise e
367
389
  except Exception as e:
368
- raise SecurityError(
390
+ raise CustomException(
369
391
  ErrorCode.INTERNAL_ERROR,
370
392
  detail=str(e),
371
- source_function="create_jwt_token",
393
+ source_function="security.create_jwt_token",
372
394
  original_error=e
373
395
  )
374
396
 
@@ -376,7 +398,18 @@ async def verify_jwt_token(
376
398
  token: str,
377
399
  expected_type: Optional[Literal["access", "refresh"]] = None
378
400
  ) -> Dict[str, Any]:
379
- """JWT 토큰을 검증합니다."""
401
+ """JWT 토큰을 검증합니다.
402
+
403
+ Args:
404
+ token: 검증할 JWT 토큰
405
+ expected_type: 예상되는 토큰 타입
406
+
407
+ Returns:
408
+ Dict[str, Any]: 토큰 페이로드
409
+
410
+ Raises:
411
+ CustomException: 토큰 검증 실패 시
412
+ """
380
413
  try:
381
414
  settings = get_settings()
382
415
  # 토큰 디코딩
@@ -390,25 +423,27 @@ async def verify_jwt_token(
390
423
 
391
424
  # 토큰 타입 검증 (expected_type이 주어진 경우에만)
392
425
  if expected_type and payload.get("token_type") != expected_type:
393
- raise TokenError(
394
- detail=f"Expected {expected_type} token but got {payload.get('token_type')}",
395
- source_function="verify_jwt_token"
426
+ raise CustomException(
427
+ ErrorCode.INVALID_TOKEN,
428
+ detail=f"token|{expected_type}|{payload.get('token_type')}",
429
+ source_function="security.verify_jwt_token"
396
430
  )
397
431
 
398
432
  return payload
399
433
 
400
434
  except JWTError as e:
401
- raise TokenError(
402
- detail=str(e),
403
- source_function="verify_jwt_token",
435
+ raise CustomException(
436
+ ErrorCode.INVALID_TOKEN,
437
+ detail=token[:10] + "...",
438
+ source_function="security.verify_jwt_token",
404
439
  original_error=e
405
440
  )
406
- except (TokenError, SecurityError) as e:
441
+ except CustomException as e:
407
442
  raise e
408
443
  except Exception as e:
409
- raise SecurityError(
444
+ raise CustomException(
410
445
  ErrorCode.INTERNAL_ERROR,
411
446
  detail=str(e),
412
- source_function="verify_jwt_token",
447
+ source_function="security.verify_jwt_token",
413
448
  original_error=e
414
449
  )
aiteamutils/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  """버전 정보"""
2
- __version__ = "0.2.31"
2
+ __version__ = "0.2.33"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiteamutils
3
- Version: 0.2.31
3
+ Version: 0.2.33
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
@@ -3,14 +3,14 @@ aiteamutils/base_model.py,sha256=ODEnjvUVoxQ1RPCfq8-uZTfTADIA4c7Z3E6G4EVsSX0,270
3
3
  aiteamutils/base_repository.py,sha256=qdwQ7Sj2fUqxpDg6cWM48n_QbwPK_VUlG9zTSem8iCk,18968
4
4
  aiteamutils/base_service.py,sha256=E4dHGE0DvhmRyFplh46SwKJOSF_nUL7OAsCkf_ZJF_8,24733
5
5
  aiteamutils/cache.py,sha256=tr0Yn8VPYA9QHiKCUzciVlQ2J1RAwNo2K9lGMH4rY3s,1334
6
- aiteamutils/config.py,sha256=7pJHBml8RRXC9FpoRBx0emofFkvtxsyk9_Rcur2F9hI,2724
7
- aiteamutils/database.py,sha256=raYKRZjEfefM3SnoPYozPu7OUGm62XWOUqZzN4_cayw,33479
8
- aiteamutils/dependencies.py,sha256=16Q_76gu9Vff-1XzYar_RREGEegIbUyZJzBbYf7HiR0,3943
6
+ aiteamutils/config.py,sha256=kFKMeIx1KcuEwwx4VjZdCgoTOHCkG3ySYVJ0G6cvMoA,2849
7
+ aiteamutils/database.py,sha256=CaH73g8PPNcmLCz4Xr0DBtNSrLcpRlyt0F1zO5Tigfo,33811
8
+ aiteamutils/dependencies.py,sha256=GgN8sFM7qGNmOfpLaFrhuHOgPlBVXWrEgxv29jxjEgI,4226
9
9
  aiteamutils/enums.py,sha256=ipZi6k_QD5-3QV7Yzv7bnL0MjDz-vqfO9I5L77biMKs,632
10
10
  aiteamutils/exceptions.py,sha256=YV-ISya4wQlHk4twvGo16I5r8h22-tXpn9wa-b3WwDM,15231
11
- aiteamutils/security.py,sha256=jxJsWSjJOMVlNaBFxroIXrAgseJYKl_vQ_kfmHblPIA,13498
11
+ aiteamutils/security.py,sha256=nqAyypyiZ26s-eKv7c6YPDTK6HcqimFnoCr12Wtg1DY,14449
12
12
  aiteamutils/validators.py,sha256=3N245cZFjgwtW_KzjESkizx5BBUDaJLbbxfNO4WOFZ0,7764
13
- aiteamutils/version.py,sha256=YK0jUv01ukicmNcU34hKfOfAtqr0QfPU2FTKHjSy49g,42
14
- aiteamutils-0.2.31.dist-info/METADATA,sha256=0j6hq7VMfiaw5f0W9IBD67LK2BSBaXRuRI4cP5_6Xw0,1718
15
- aiteamutils-0.2.31.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- aiteamutils-0.2.31.dist-info/RECORD,,
13
+ aiteamutils/version.py,sha256=0u62c8uMhBIqtJ4INrTiDbrTgFVL2CBQ_nfjWnhrldU,42
14
+ aiteamutils-0.2.33.dist-info/METADATA,sha256=DUbbkj6hQ_0C7ODwi8AuQJ1W1BYAMF8_45epV7wl27I,1718
15
+ aiteamutils-0.2.33.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ aiteamutils-0.2.33.dist-info/RECORD,,