aiteamutils 0.2.58__py3-none-any.whl → 0.2.60__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/__init__.py +0 -5
- aiteamutils/base_repository.py +36 -190
- aiteamutils/base_service.py +17 -628
- aiteamutils/database.py +40 -199
- aiteamutils/version.py +1 -1
- {aiteamutils-0.2.58.dist-info → aiteamutils-0.2.60.dist-info}/METADATA +1 -1
- aiteamutils-0.2.60.dist-info/RECORD +15 -0
- aiteamutils/dependencies.py +0 -227
- aiteamutils-0.2.58.dist-info/RECORD +0 -16
- {aiteamutils-0.2.58.dist-info → aiteamutils-0.2.60.dist-info}/WHEEL +0 -0
aiteamutils/database.py
CHANGED
@@ -1,207 +1,48 @@
|
|
1
|
-
|
2
|
-
from typing import
|
3
|
-
from sqlalchemy import select, and_
|
1
|
+
#기본 라이브러리
|
2
|
+
from typing import TypeVar, Generic, Type, Any, Dict, List, Optional
|
4
3
|
from sqlalchemy.ext.asyncio import AsyncSession
|
5
|
-
from sqlalchemy
|
4
|
+
from sqlalchemy import select, and_
|
5
|
+
from sqlalchemy.orm import DeclarativeBase
|
6
|
+
from sqlalchemy.exc import SQLAlchemyError
|
6
7
|
|
7
|
-
|
8
|
-
from .base_model import Base
|
8
|
+
ModelType = TypeVar("ModelType", bound=DeclarativeBase)
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
"""DatabaseService 초기화
|
13
|
-
|
14
|
-
Args:
|
15
|
-
session (AsyncSession): 외부에서 주입받은 데이터베이스 세션
|
16
|
-
"""
|
17
|
-
self._session = session
|
18
|
-
|
19
|
-
@property
|
20
|
-
def session(self) -> AsyncSession:
|
21
|
-
"""현재 세션을 반환합니다."""
|
22
|
-
if self._session is None:
|
23
|
-
raise CustomException(
|
24
|
-
ErrorCode.DB_CONNECTION_ERROR,
|
25
|
-
detail="session",
|
26
|
-
source_function="DatabaseService.session"
|
27
|
-
)
|
28
|
-
return self._session
|
10
|
+
#패키지 라이브러리
|
11
|
+
from .exceptions import ErrorCode, CustomException
|
29
12
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
Raises:
|
45
|
-
CustomException: 엔티티 생성 실패 시
|
46
|
-
"""
|
47
|
-
try:
|
48
|
-
entity = model(**entity_data)
|
49
|
-
self.session.add(entity)
|
50
|
-
await self.session.flush()
|
51
|
-
await self.session.refresh(entity)
|
52
|
-
return entity
|
53
|
-
except IntegrityError as e:
|
54
|
-
await self.session.rollback()
|
55
|
-
raise CustomException(
|
56
|
-
ErrorCode.DB_INTEGRITY_ERROR,
|
57
|
-
detail=str(e),
|
58
|
-
source_function="DatabaseService.create_entity",
|
59
|
-
original_error=e
|
60
|
-
)
|
61
|
-
except Exception as e:
|
62
|
-
await self.session.rollback()
|
63
|
-
raise CustomException(
|
64
|
-
ErrorCode.DB_CREATE_ERROR,
|
65
|
-
detail=str(e),
|
66
|
-
source_function="DatabaseService.create_entity",
|
67
|
-
original_error=e
|
68
|
-
)
|
13
|
+
##################
|
14
|
+
# 1. 쿼리 실행 #
|
15
|
+
##################
|
16
|
+
async def list_entities(
|
17
|
+
session: AsyncSession,
|
18
|
+
model: Type[ModelType],
|
19
|
+
skip: int = 0,
|
20
|
+
limit: int = 100,
|
21
|
+
filters: Optional[Dict[str, Any]] = None,
|
22
|
+
joins: Optional[List[Any]] = None
|
23
|
+
) -> List[Dict[str, Any]]:
|
24
|
+
try:
|
25
|
+
query = select(model)
|
69
26
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
) -> Optional[Any]:
|
75
|
-
"""필터 조건으로 엔티티를 조회합니다.
|
76
|
-
|
77
|
-
Args:
|
78
|
-
model: 모델 클래스
|
79
|
-
filters: 필터 조건
|
80
|
-
|
81
|
-
Returns:
|
82
|
-
조회된 엔티티 또는 None
|
83
|
-
|
84
|
-
Raises:
|
85
|
-
CustomException: 조회 실패 시
|
86
|
-
"""
|
87
|
-
try:
|
88
|
-
stmt = select(model).filter_by(**filters)
|
89
|
-
result = await self.session.execute(stmt)
|
90
|
-
return result.scalars().first()
|
91
|
-
except Exception as e:
|
92
|
-
raise CustomException(
|
93
|
-
ErrorCode.DB_QUERY_ERROR,
|
94
|
-
detail=str(e),
|
95
|
-
source_function="DatabaseService.get_entity",
|
96
|
-
original_error=e
|
97
|
-
)
|
27
|
+
# 필터 조건 적용
|
28
|
+
if filters:
|
29
|
+
conditions = [getattr(model, key) == value for key, value in filters.items()]
|
30
|
+
query = query.where(and_(*conditions))
|
98
31
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
skip: int = 0,
|
104
|
-
limit: int = 100
|
105
|
-
) -> List[Any]:
|
106
|
-
"""엔티티 목록을 조회합니다.
|
107
|
-
|
108
|
-
Args:
|
109
|
-
model: 모델 클래스
|
110
|
-
filters: 필터 조건
|
111
|
-
skip: 건너뛸 레코드 수
|
112
|
-
limit: 조회할 최대 레코드 수
|
113
|
-
|
114
|
-
Returns:
|
115
|
-
엔티티 목록
|
116
|
-
|
117
|
-
Raises:
|
118
|
-
CustomException: 조회 실패 시
|
119
|
-
"""
|
120
|
-
try:
|
121
|
-
stmt = select(model)
|
122
|
-
if filters:
|
123
|
-
stmt = stmt.filter_by(**filters)
|
124
|
-
stmt = stmt.offset(skip).limit(limit)
|
125
|
-
result = await self.session.execute(stmt)
|
126
|
-
return result.scalars().all()
|
127
|
-
except Exception as e:
|
128
|
-
raise CustomException(
|
129
|
-
ErrorCode.DB_QUERY_ERROR,
|
130
|
-
detail=str(e),
|
131
|
-
source_function="DatabaseService.list_entities",
|
132
|
-
original_error=e
|
133
|
-
)
|
32
|
+
# 조인 로딩 적용
|
33
|
+
if joins:
|
34
|
+
for join_option in joins:
|
35
|
+
query = query.options(join_option)
|
134
36
|
|
135
|
-
|
136
|
-
|
137
|
-
entity: Base,
|
138
|
-
update_data: Dict[str, Any]
|
139
|
-
) -> Any:
|
140
|
-
"""엔티티를 수정합니다.
|
141
|
-
|
142
|
-
Args:
|
143
|
-
entity: 수정할 엔티티
|
144
|
-
update_data: 수정할 데이터
|
145
|
-
|
146
|
-
Returns:
|
147
|
-
수정된 엔티티
|
148
|
-
|
149
|
-
Raises:
|
150
|
-
CustomException: 수정 실패 시
|
151
|
-
"""
|
152
|
-
try:
|
153
|
-
for key, value in update_data.items():
|
154
|
-
setattr(entity, key, value)
|
155
|
-
await self.session.flush()
|
156
|
-
await self.session.refresh(entity)
|
157
|
-
return entity
|
158
|
-
except IntegrityError as e:
|
159
|
-
await self.session.rollback()
|
160
|
-
raise CustomException(
|
161
|
-
ErrorCode.DB_INTEGRITY_ERROR,
|
162
|
-
detail=str(e),
|
163
|
-
source_function="DatabaseService.update_entity",
|
164
|
-
original_error=e
|
165
|
-
)
|
166
|
-
except Exception as e:
|
167
|
-
await self.session.rollback()
|
168
|
-
raise CustomException(
|
169
|
-
ErrorCode.DB_UPDATE_ERROR,
|
170
|
-
detail=str(e),
|
171
|
-
source_function="DatabaseService.update_entity",
|
172
|
-
original_error=e
|
173
|
-
)
|
37
|
+
# 페이지네이션 적용
|
38
|
+
query = query.limit(limit).offset(skip)
|
174
39
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
soft_delete: 소프트 삭제 여부
|
185
|
-
|
186
|
-
Returns:
|
187
|
-
삭제 성공 여부
|
188
|
-
|
189
|
-
Raises:
|
190
|
-
CustomException: 삭제 실패 시
|
191
|
-
"""
|
192
|
-
try:
|
193
|
-
if soft_delete:
|
194
|
-
entity.is_deleted = True
|
195
|
-
await self.session.flush()
|
196
|
-
else:
|
197
|
-
await self.session.delete(entity)
|
198
|
-
await self.session.flush()
|
199
|
-
return True
|
200
|
-
except Exception as e:
|
201
|
-
await self.session.rollback()
|
202
|
-
raise CustomException(
|
203
|
-
ErrorCode.DB_DELETE_ERROR,
|
204
|
-
detail=str(e),
|
205
|
-
source_function="DatabaseService.delete_entity",
|
206
|
-
original_error=e
|
207
|
-
)
|
40
|
+
result = await session.execute(query)
|
41
|
+
return result.scalars().unique().all()
|
42
|
+
except SQLAlchemyError as e:
|
43
|
+
raise CustomException(
|
44
|
+
ErrorCode.DB_READ_ERROR,
|
45
|
+
detail=f"{model.__name__}|{str(e)}",
|
46
|
+
source_function="database.list_entities",
|
47
|
+
original_error=e
|
48
|
+
)
|
aiteamutils/version.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
"""버전 정보"""
|
2
|
-
__version__ = "0.2.
|
2
|
+
__version__ = "0.2.60"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
aiteamutils/__init__.py,sha256=h7iFifWvRlaComsk4VPapRr16YhD19Kp1LuBzLHqdgQ,1170
|
2
|
+
aiteamutils/base_model.py,sha256=ODEnjvUVoxQ1RPCfq8-uZTfTADIA4c7Z3E6G4EVsSX0,2708
|
3
|
+
aiteamutils/base_repository.py,sha256=ir2ftophKKd_9BQ9B0LbszMqUyFeWkQ1MmFF6WBLcWc,1682
|
4
|
+
aiteamutils/base_service.py,sha256=Ncomi5yBUL4oHrMx_J1yUKVrUIYo6YmnYJWAWOIwQx8,2217
|
5
|
+
aiteamutils/cache.py,sha256=07xBGlgAwOTAdY5mnMOQJ5EBxVwe8glVD7DkGEkxCtw,1373
|
6
|
+
aiteamutils/config.py,sha256=YdalpJb70-txhGJAS4aaKglEZAFVWgfzw5BXSWpkUz4,3232
|
7
|
+
aiteamutils/database.py,sha256=MtmrX_pDzKFQM-P3OAfm2mALvhRg-v5JWtGBoiegeU0,1484
|
8
|
+
aiteamutils/enums.py,sha256=ipZi6k_QD5-3QV7Yzv7bnL0MjDz-vqfO9I5L77biMKs,632
|
9
|
+
aiteamutils/exceptions.py,sha256=_lKWXq_ujNj41xN6LDE149PwsecAP7lgYWbOBbLOntg,15368
|
10
|
+
aiteamutils/security.py,sha256=xFVrjttxwXB1TTjqgRQQgQJQohQBT28vuW8FVLjvi-M,10103
|
11
|
+
aiteamutils/validators.py,sha256=3N245cZFjgwtW_KzjESkizx5BBUDaJLbbxfNO4WOFZ0,7764
|
12
|
+
aiteamutils/version.py,sha256=W0y4-03EvxLX9F9qSLA2iCovEsiyhT86gHqCOTRNhGU,42
|
13
|
+
aiteamutils-0.2.60.dist-info/METADATA,sha256=Gu1bs923MYkC_xKFhMKgS8PrSsK2ne2UJRUxBBeflRI,1718
|
14
|
+
aiteamutils-0.2.60.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
15
|
+
aiteamutils-0.2.60.dist-info/RECORD,,
|
aiteamutils/dependencies.py
DELETED
@@ -1,227 +0,0 @@
|
|
1
|
-
"""의존성 관리 모듈."""
|
2
|
-
from typing import Type, TypeVar, Dict, Any, Optional, Callable, List, AsyncGenerator
|
3
|
-
from fastapi import Request, Depends, HTTPException, status
|
4
|
-
from sqlalchemy.ext.asyncio import AsyncSession
|
5
|
-
from jose import jwt, JWTError
|
6
|
-
import logging
|
7
|
-
|
8
|
-
from .exceptions import CustomException, ErrorCode
|
9
|
-
from .config import get_settings
|
10
|
-
from .base_service import BaseService
|
11
|
-
from .base_repository import BaseRepository
|
12
|
-
from .database import DatabaseService
|
13
|
-
|
14
|
-
T = TypeVar("T", bound=BaseService)
|
15
|
-
R = TypeVar("R", bound=BaseRepository)
|
16
|
-
|
17
|
-
_service_registry: Dict[str, Dict[str, Any]] = {}
|
18
|
-
_session_provider = None
|
19
|
-
|
20
|
-
__all__ = [
|
21
|
-
"setup_dependencies",
|
22
|
-
"register_service",
|
23
|
-
"get_service",
|
24
|
-
"get_current_user"
|
25
|
-
]
|
26
|
-
|
27
|
-
def setup_dependencies(session_provider: Callable[[], AsyncGenerator[AsyncSession, None]]) -> None:
|
28
|
-
"""의존성 설정을 초기화합니다.
|
29
|
-
|
30
|
-
Args:
|
31
|
-
session_provider: 데이터베이스 세션을 제공하는 함수
|
32
|
-
"""
|
33
|
-
global _session_provider
|
34
|
-
_session_provider = session_provider
|
35
|
-
|
36
|
-
def register_service(
|
37
|
-
service_class: Type[T],
|
38
|
-
repository_class: Optional[Type[R]] = None,
|
39
|
-
**kwargs
|
40
|
-
) -> None:
|
41
|
-
"""서비스를 등록합니다.
|
42
|
-
|
43
|
-
Args:
|
44
|
-
service_class: 서비스 클래스
|
45
|
-
repository_class: 저장소 클래스 (선택)
|
46
|
-
**kwargs: 추가 의존성
|
47
|
-
"""
|
48
|
-
if _session_provider is None:
|
49
|
-
raise CustomException(
|
50
|
-
ErrorCode.INTERNAL_ERROR,
|
51
|
-
detail="Dependencies not initialized",
|
52
|
-
source_function="dependencies.register_service"
|
53
|
-
)
|
54
|
-
|
55
|
-
service_name = service_class.__name__
|
56
|
-
_service_registry[service_name] = {
|
57
|
-
"service_class": service_class,
|
58
|
-
"repository_class": repository_class,
|
59
|
-
"dependencies": kwargs
|
60
|
-
}
|
61
|
-
|
62
|
-
async def _get_service(
|
63
|
-
service_name: str,
|
64
|
-
session: AsyncSession,
|
65
|
-
request: Request
|
66
|
-
) -> BaseService:
|
67
|
-
"""서비스 인스턴스를 생성합니다.
|
68
|
-
|
69
|
-
Args:
|
70
|
-
service_name: 서비스 이름
|
71
|
-
session: 데이터베이스 세션
|
72
|
-
request: FastAPI 요청 객체
|
73
|
-
|
74
|
-
Returns:
|
75
|
-
BaseService: 서비스 인스턴스
|
76
|
-
|
77
|
-
Raises:
|
78
|
-
CustomException: 서비스 생성 실패 시
|
79
|
-
"""
|
80
|
-
try:
|
81
|
-
service_info = _service_registry.get(service_name)
|
82
|
-
if not service_info:
|
83
|
-
raise CustomException(
|
84
|
-
ErrorCode.SERVICE_NOT_FOUND,
|
85
|
-
detail=service_name,
|
86
|
-
source_function="dependencies._get_service"
|
87
|
-
)
|
88
|
-
|
89
|
-
service_class = service_info["service_class"]
|
90
|
-
repository_class = service_info["repository_class"]
|
91
|
-
dependencies = service_info["dependencies"]
|
92
|
-
|
93
|
-
# 데이터베이스 서비스 생성
|
94
|
-
db_service = DatabaseService(session=session)
|
95
|
-
|
96
|
-
# 저장소 인스턴스 생성
|
97
|
-
repository = None
|
98
|
-
if repository_class:
|
99
|
-
repository = repository_class(session=session)
|
100
|
-
|
101
|
-
# 서비스 인스턴스 생성
|
102
|
-
service = service_class(
|
103
|
-
db=db_service,
|
104
|
-
repository=repository,
|
105
|
-
request=request,
|
106
|
-
**dependencies
|
107
|
-
)
|
108
|
-
|
109
|
-
return service
|
110
|
-
|
111
|
-
except CustomException as e:
|
112
|
-
raise e
|
113
|
-
except Exception as e:
|
114
|
-
raise CustomException(
|
115
|
-
ErrorCode.INTERNAL_ERROR,
|
116
|
-
detail=str(e),
|
117
|
-
source_function="dependencies._get_service",
|
118
|
-
original_error=e
|
119
|
-
)
|
120
|
-
|
121
|
-
def get_service(service_name: str) -> Callable:
|
122
|
-
"""서비스 의존성을 반환합니다.
|
123
|
-
|
124
|
-
Args:
|
125
|
-
service_name: 서비스 이름
|
126
|
-
|
127
|
-
Returns:
|
128
|
-
Callable: 서비스 의존성 함수
|
129
|
-
"""
|
130
|
-
if _session_provider is None:
|
131
|
-
raise CustomException(
|
132
|
-
ErrorCode.INTERNAL_ERROR,
|
133
|
-
detail="Dependencies not initialized",
|
134
|
-
source_function="dependencies.get_service"
|
135
|
-
)
|
136
|
-
|
137
|
-
async def _get_service_dependency(
|
138
|
-
request: Request,
|
139
|
-
session: AsyncSession = Depends(_session_provider)
|
140
|
-
) -> BaseService:
|
141
|
-
return await _get_service(service_name, session, request)
|
142
|
-
return _get_service_dependency
|
143
|
-
|
144
|
-
async def get_current_user(
|
145
|
-
request: Request,
|
146
|
-
session: AsyncSession,
|
147
|
-
auth_service: BaseService = Depends(get_service("AuthService"))
|
148
|
-
) -> Dict[str, Any]:
|
149
|
-
"""현재 사용자 정보를 반환합니다.
|
150
|
-
|
151
|
-
Args:
|
152
|
-
request: FastAPI 요청 객체
|
153
|
-
session: 데이터베이스 세션
|
154
|
-
auth_service: 인증 서비스
|
155
|
-
|
156
|
-
Returns:
|
157
|
-
Dict[str, Any]: 사용자 정보
|
158
|
-
|
159
|
-
Raises:
|
160
|
-
HTTPException: 인증 실패 시
|
161
|
-
"""
|
162
|
-
settings = get_settings()
|
163
|
-
|
164
|
-
# Authorization 헤더 검증
|
165
|
-
authorization = request.headers.get("Authorization")
|
166
|
-
if not authorization or not authorization.startswith("Bearer "):
|
167
|
-
raise HTTPException(
|
168
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
169
|
-
detail="Not authenticated",
|
170
|
-
headers={"WWW-Authenticate": "Bearer"}
|
171
|
-
)
|
172
|
-
|
173
|
-
token = authorization.split(" ")[1]
|
174
|
-
|
175
|
-
try:
|
176
|
-
# JWT 토큰 디코딩
|
177
|
-
payload = jwt.decode(
|
178
|
-
token,
|
179
|
-
settings.jwt_secret,
|
180
|
-
algorithms=[settings.jwt_algorithm],
|
181
|
-
issuer=settings.token_issuer,
|
182
|
-
audience=settings.token_audience
|
183
|
-
)
|
184
|
-
|
185
|
-
# 토큰 타입 검증
|
186
|
-
token_type = payload.get("token_type")
|
187
|
-
if token_type != "access":
|
188
|
-
raise HTTPException(
|
189
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
190
|
-
detail="Invalid token type",
|
191
|
-
headers={"WWW-Authenticate": "Bearer"}
|
192
|
-
)
|
193
|
-
|
194
|
-
# 사용자 조회
|
195
|
-
user_ulid = payload.get("user_ulid")
|
196
|
-
if not user_ulid:
|
197
|
-
raise HTTPException(
|
198
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
199
|
-
detail="Invalid token payload",
|
200
|
-
headers={"WWW-Authenticate": "Bearer"}
|
201
|
-
)
|
202
|
-
|
203
|
-
user = await auth_service.get_by_ulid(user_ulid)
|
204
|
-
if not user:
|
205
|
-
raise HTTPException(
|
206
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
207
|
-
detail="User not found",
|
208
|
-
headers={"WWW-Authenticate": "Bearer"}
|
209
|
-
)
|
210
|
-
|
211
|
-
return user
|
212
|
-
|
213
|
-
except JWTError as e:
|
214
|
-
raise HTTPException(
|
215
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
216
|
-
detail=str(e),
|
217
|
-
headers={"WWW-Authenticate": "Bearer"}
|
218
|
-
)
|
219
|
-
except HTTPException as e:
|
220
|
-
raise e
|
221
|
-
except Exception as e:
|
222
|
-
logging.error(f"Error in get_current_user: {str(e)}")
|
223
|
-
raise HTTPException(
|
224
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
225
|
-
detail="Authentication failed",
|
226
|
-
headers={"WWW-Authenticate": "Bearer"}
|
227
|
-
)
|
@@ -1,16 +0,0 @@
|
|
1
|
-
aiteamutils/__init__.py,sha256=U9UEyU0AqpLZzbPJiBvwDEh-s2405y1IeWZ0zCqFSl0,1307
|
2
|
-
aiteamutils/base_model.py,sha256=ODEnjvUVoxQ1RPCfq8-uZTfTADIA4c7Z3E6G4EVsSX0,2708
|
3
|
-
aiteamutils/base_repository.py,sha256=vqsundoN0h7FVvgqTBEnnJNMcFpvMK0s_nxBWdIYg-U,7846
|
4
|
-
aiteamutils/base_service.py,sha256=s2AcA-6_ogOQKgt2xf_3AG2s6tqBceU4nJoXO1II7S8,24588
|
5
|
-
aiteamutils/cache.py,sha256=07xBGlgAwOTAdY5mnMOQJ5EBxVwe8glVD7DkGEkxCtw,1373
|
6
|
-
aiteamutils/config.py,sha256=YdalpJb70-txhGJAS4aaKglEZAFVWgfzw5BXSWpkUz4,3232
|
7
|
-
aiteamutils/database.py,sha256=x0x5gnSyGfwo_klL9O65RnGOQID6c9tH2miwFveVyoE,6326
|
8
|
-
aiteamutils/dependencies.py,sha256=UjHGgee4qKxPwHJnfMZ3YKB7m7UQNIvKNr7IdOx590c,6899
|
9
|
-
aiteamutils/enums.py,sha256=ipZi6k_QD5-3QV7Yzv7bnL0MjDz-vqfO9I5L77biMKs,632
|
10
|
-
aiteamutils/exceptions.py,sha256=_lKWXq_ujNj41xN6LDE149PwsecAP7lgYWbOBbLOntg,15368
|
11
|
-
aiteamutils/security.py,sha256=xFVrjttxwXB1TTjqgRQQgQJQohQBT28vuW8FVLjvi-M,10103
|
12
|
-
aiteamutils/validators.py,sha256=3N245cZFjgwtW_KzjESkizx5BBUDaJLbbxfNO4WOFZ0,7764
|
13
|
-
aiteamutils/version.py,sha256=57HkAV8pVrmV03eTVINw5qTQURkXwGPl2H--uJC4OWs,42
|
14
|
-
aiteamutils-0.2.58.dist-info/METADATA,sha256=yULGE3mtpwvWXzHDczGJfqu52urFzknJhm5V9PgCOGc,1718
|
15
|
-
aiteamutils-0.2.58.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
16
|
-
aiteamutils-0.2.58.dist-info/RECORD,,
|
File without changes
|