aiteamutils 0.2.162__py3-none-any.whl → 0.2.163__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.
aiteamutils/database.py CHANGED
@@ -8,7 +8,8 @@ from typing import (
8
8
  List,
9
9
  Optional,
10
10
  AsyncGenerator,
11
- Union
11
+ Union,
12
+ Tuple
12
13
  )
13
14
  from sqlalchemy.ext.asyncio import AsyncSession
14
15
  from sqlalchemy import select, and_, or_
@@ -20,12 +21,19 @@ from sqlalchemy.ext.asyncio import AsyncSession
20
21
  from fastapi import Request
21
22
  from ulid import ULID
22
23
  from sqlalchemy import MetaData, Table, insert
24
+ from sqlalchemy.sql.elements import BinaryExpression
23
25
 
24
26
  #패키지 라이브러리
25
27
  from .exceptions import ErrorCode, CustomException
26
28
 
27
29
  ModelType = TypeVar("ModelType", bound=DeclarativeBase)
28
30
 
31
+ JoinTarget = Union[
32
+ DeclarativeBase, # 모델
33
+ Tuple[DeclarativeBase, BinaryExpression], # (모델, 조인 조건)
34
+ Tuple[DeclarativeBase, BinaryExpression, str] # (모델, 조인 조건, 조인 타입)
35
+ ]
36
+
29
37
  ##################
30
38
  # 전처리 #
31
39
  ##################
@@ -255,6 +263,61 @@ def build_conditions(
255
263
  ##################
256
264
  # 쿼리 실행 #
257
265
  ##################
266
+ async def execute_query(
267
+ session: AsyncSession,
268
+ model: Type[ModelType],
269
+ explicit_joins: Optional[List[JoinTarget]] = None,
270
+ loading_joins: Optional[List[Any]] = None,
271
+ conditions: Optional[List[BinaryExpression]] = None,
272
+ ) -> Select:
273
+ """
274
+ 쿼리 실행을 위한 공통 함수
275
+
276
+ Args:
277
+ session: 데이터베이스 세션
278
+ model: 기본 모델
279
+ explicit_joins: 명시적 조인 설정
280
+ - 모델만 전달: 기본 outer join
281
+ - (모델, 조건): 조건부 outer join
282
+ - (모델, 조건, 'inner'/'left'/'right'): 조인 타입 지정
283
+ loading_joins: Relationship 로딩 설정 (joinedload, selectinload 등)
284
+ conditions: WHERE 조건들
285
+ """
286
+ # 1. 기본 쿼리 생성
287
+ query = select(model)
288
+
289
+ # 2. 명시적 조인 처리
290
+ if explicit_joins:
291
+ for join_target in explicit_joins:
292
+ if isinstance(join_target, DeclarativeBase):
293
+ # 모델만 전달된 경우
294
+ query = query.outerjoin(join_target)
295
+ elif isinstance(join_target, tuple):
296
+ if len(join_target) == 2:
297
+ # (모델, 조건)이 전달된 경우
298
+ target_model, join_condition = join_target
299
+ query = query.outerjoin(target_model, join_condition)
300
+ elif len(join_target) == 3:
301
+ # (모델, 조건, 조인타입)이 전달된 경우
302
+ target_model, join_condition, join_type = join_target
303
+ if join_type == 'inner':
304
+ query = query.join(target_model, join_condition)
305
+ elif join_type == 'left':
306
+ query = query.outerjoin(target_model, join_condition)
307
+ elif join_type == 'right':
308
+ query = query.outerjoin(target_model, join_condition, full=True)
309
+
310
+ # 3. Relationship 로딩 설정
311
+ if loading_joins:
312
+ for join_option in loading_joins:
313
+ query = query.options(join_option)
314
+
315
+ # 4. 조건 적용
316
+ if conditions:
317
+ query = query.where(and_(*conditions))
318
+
319
+ return query
320
+
258
321
  async def create_entity(
259
322
  session: AsyncSession,
260
323
  model: Type[ModelType],
@@ -428,49 +491,22 @@ async def list_entities(
428
491
  skip: int = 0,
429
492
  limit: int = 100,
430
493
  filters: Optional[List[Dict[str, Any]]] = None,
431
- explicit_joins: Optional[List[Any]] = None,
494
+ explicit_joins: Optional[List[JoinTarget]] = None,
432
495
  loading_joins: Optional[List[Any]] = None,
433
496
  order: Optional[List[Dict[str, str]]] = None
434
497
  ) -> List[Dict[str, Any]]:
435
- """
436
- 엔터티 리스트를 필터 및 조건에 따라 가져오는 함수.
437
-
438
- Args:
439
- session: SQLAlchemy AsyncSession.
440
- model: SQLAlchemy 모델.
441
- skip: 페이지네이션 시작 위치.
442
- limit: 페이지네이션 크기.
443
- filters: 필터 조건 딕셔너리.
444
- 예시:
445
- filters = {
446
- "search": {"field": "username", "operator": "like", "value": "%admin%"},
447
- "name": {"field": "name", "operator": "like", "value": "%John%"},
448
- "role_ulid": {"field": "role_ulid", "operator": "eq", "value": "1234"}
449
- }
450
-
451
- joins: 조인 옵션.
452
- 예시:
453
- joins = [
454
- selectinload(YourModel.related_field), # 관련된 필드를 함께 로드
455
- joinedload(YourModel.another_related_field) # 다른 관계된 필드를 조인
456
- ]
457
-
458
- Returns:
459
- List[Dict[str, Any]]: 쿼리 결과 리스트.
460
- """
461
498
  try:
499
+ # 필터 조건 생성
500
+ conditions = build_conditions(filters, model) if filters else None
501
+
462
502
  # 기본 쿼리 생성
463
- if explicit_joins:
464
- query = select(model, *explicit_joins)
465
- for join_target in explicit_joins:
466
- query = query.outerjoin(join_target)
467
- else:
468
- query = select(model)
469
-
470
- # 필터 조건 적용
471
- if filters:
472
- conditions = build_conditions(filters, model)
473
- query = query.where(and_(*conditions))
503
+ query = await execute_query(
504
+ session=session,
505
+ model=model,
506
+ explicit_joins=explicit_joins,
507
+ loading_joins=loading_joins,
508
+ conditions=conditions
509
+ )
474
510
 
475
511
  # 정렬 조건 적용
476
512
  if order:
@@ -505,25 +541,21 @@ async def get_entity(
505
541
  session: AsyncSession,
506
542
  model: Type[ModelType],
507
543
  conditions: Dict[str, Any],
508
- explicit_joins: Optional[List[Any]] = None,
544
+ explicit_joins: Optional[List[JoinTarget]] = None,
509
545
  loading_joins: Optional[List[Any]] = None
510
546
  ) -> ModelType:
511
547
  try:
512
- query = select(model)
513
-
514
- # 명시적 조인 적용
515
- if explicit_joins:
516
- for join_target in explicit_joins:
517
- query = query.outerjoin(join_target)
518
-
519
- # 조인 로딩 적용
520
- if loading_joins:
521
- for join_option in loading_joins:
522
- query = query.options(join_option)
523
-
524
- if conditions:
525
- for key, value in conditions.items():
526
- query = query.where(getattr(model, key) == value)
548
+ # 조건을 리스트로 변환
549
+ condition_list = [getattr(model, key) == value for key, value in conditions.items()]
550
+
551
+ # 쿼리 실행
552
+ query = await execute_query(
553
+ session=session,
554
+ model=model,
555
+ explicit_joins=explicit_joins,
556
+ loading_joins=loading_joins,
557
+ conditions=condition_list
558
+ )
527
559
 
528
560
  result = await session.execute(query)
529
561
  return result.scalars().unique().one_or_none()
aiteamutils/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  """버전 정보"""
2
- __version__ = "0.2.162"
2
+ __version__ = "0.2.163"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiteamutils
3
- Version: 0.2.162
3
+ Version: 0.2.163
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
@@ -4,13 +4,13 @@ aiteamutils/base_repository.py,sha256=Oy2zE1i5qx60Xf1tnsaKLyFWapiPqt5JH8NejwNrPW
4
4
  aiteamutils/base_service.py,sha256=JIeRtFn1Ll4Qcq3v88pgS9lmEQLQoVyyOKqYR8n02S4,21192
5
5
  aiteamutils/cache.py,sha256=07xBGlgAwOTAdY5mnMOQJ5EBxVwe8glVD7DkGEkxCtw,1373
6
6
  aiteamutils/config.py,sha256=YdalpJb70-txhGJAS4aaKglEZAFVWgfzw5BXSWpkUz4,3232
7
- aiteamutils/database.py,sha256=msvBKtxWeQVOo0v2Q9i2azuTNtnUItuNNar52gdRZTo,20418
7
+ aiteamutils/database.py,sha256=zXYhdUVgAisz4BuXZPPbvVLZ9lwRe7aVQP8J1AVE88Y,21771
8
8
  aiteamutils/enums.py,sha256=7WLqlcJqQWtETAga2WAxNp3dJTQIAd2TW-4WzkoHHa8,2498
9
9
  aiteamutils/exceptions.py,sha256=sgIVulllKMM9InTltaB7VD6i7DiQvCoycexsV-BiIBY,16570
10
10
  aiteamutils/files.py,sha256=fxnCu9rErd4vCovMi0jy4adLUiA7rx_q4RdOL4wSgsU,14258
11
11
  aiteamutils/security.py,sha256=McUl3t5Z5SyUDVUHymHdDkYyF4YSeg4g9fFMML4W6Kw,11630
12
12
  aiteamutils/validators.py,sha256=_WHN6jqJQzKM5uPTg-Da8U2qqevS84XeKMkCCF4C_lY,9591
13
- aiteamutils/version.py,sha256=vAvqE9V77cH7vOSwbqingOdyP4KA12olJ1Dj_9Br2jQ,43
14
- aiteamutils-0.2.162.dist-info/METADATA,sha256=LS01DV_fpROE_i2VnNwkeRx0KQ82VBeRAi4XveycukA,1743
15
- aiteamutils-0.2.162.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- aiteamutils-0.2.162.dist-info/RECORD,,
13
+ aiteamutils/version.py,sha256=MbP3Sxzx6eYugMlpPFw2qfjDxYmMdJwa_4K4MStAl1s,43
14
+ aiteamutils-0.2.163.dist-info/METADATA,sha256=pgSEMmDcvxJrKq3Y-CmLEuXgd2K5vKvm8SQfa3jIuvA,1743
15
+ aiteamutils-0.2.163.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ aiteamutils-0.2.163.dist-info/RECORD,,