aury-boot 0.0.27__py3-none-any.whl → 0.0.29__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.
- aury/boot/_version.py +2 -2
- aury/boot/commands/templates/project/AGENTS.md.tpl +13 -1
- aury/boot/commands/templates/project/aury_docs/02-repository.md.tpl +31 -0
- aury/boot/commands/templates/project/aury_docs/03-service.md.tpl +60 -0
- aury/boot/domain/repository/impl.py +164 -0
- aury/boot/domain/transaction/__init__.py +57 -0
- {aury_boot-0.0.27.dist-info → aury_boot-0.0.29.dist-info}/METADATA +1 -1
- {aury_boot-0.0.27.dist-info → aury_boot-0.0.29.dist-info}/RECORD +10 -10
- {aury_boot-0.0.27.dist-info → aury_boot-0.0.29.dist-info}/WHEEL +0 -0
- {aury_boot-0.0.27.dist-info → aury_boot-0.0.29.dist-info}/entry_points.txt +0 -0
aury/boot/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.29'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 29)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -75,6 +75,8 @@ mypy {package_name}/
|
|
|
75
75
|
2. **[aury_docs/02-repository.md](./aury_docs/02-repository.md)** - Repository 使用
|
|
76
76
|
- BaseRepository API
|
|
77
77
|
- Filters 语法(__gt, __like 等)
|
|
78
|
+
- Cursor 分页(推荐,性能更优)
|
|
79
|
+
- 流式查询(大数据处理)
|
|
78
80
|
- 自动提交机制
|
|
79
81
|
|
|
80
82
|
3. **[aury_docs/03-service.md](./aury_docs/03-service.md)** - Service 编写与事务
|
|
@@ -162,15 +164,25 @@ class User(Base): ...
|
|
|
162
164
|
- 写操作**必须**使用 `@transactional` 装饰器
|
|
163
165
|
- 只读操作可以不加事务装饰器
|
|
164
166
|
- 跨 Service 调用通过共享 session 实现事务共享
|
|
167
|
+
- **后台任务必须**使用 `@isolated_task` 装饰器
|
|
165
168
|
|
|
166
169
|
```python
|
|
167
|
-
from aury.boot.domain.transaction import transactional
|
|
170
|
+
from aury.boot.domain.transaction import transactional, isolated_task
|
|
168
171
|
|
|
169
172
|
class UserService(BaseService):
|
|
170
173
|
@transactional
|
|
171
174
|
async def create(self, data: UserCreate) -> User:
|
|
172
175
|
# 自动事务管理
|
|
173
176
|
return await self.repo.create(data.model_dump())
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# 后台任务必须加 @isolated_task,否则事务不会提交
|
|
180
|
+
@isolated_task
|
|
181
|
+
async def background_upload(space_id: int, url: str):
|
|
182
|
+
async with db.session() as session:
|
|
183
|
+
async with transactional_context(session):
|
|
184
|
+
repo = SpaceRepository(session, Space)
|
|
185
|
+
await repo.update(...)
|
|
174
186
|
```
|
|
175
187
|
|
|
176
188
|
### Manager API 规范
|
|
@@ -72,6 +72,37 @@ result = await repo.paginate(
|
|
|
72
72
|
# - result.has_next: bool # 是否有下一页
|
|
73
73
|
# - result.has_prev: bool # 是否有上一页
|
|
74
74
|
|
|
75
|
+
# === Cursor 分页(推荐,性能更优) ===
|
|
76
|
+
from aury.boot.domain.pagination import CursorPaginationParams
|
|
77
|
+
|
|
78
|
+
# 第一页
|
|
79
|
+
result = await repo.cursor_paginate(
|
|
80
|
+
CursorPaginationParams(limit=20),
|
|
81
|
+
is_active=True,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# 下一页(带上 cursor)
|
|
85
|
+
result = await repo.cursor_paginate(
|
|
86
|
+
CursorPaginationParams(cursor=result.next_cursor, limit=20),
|
|
87
|
+
is_active=True,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# CursorPaginationResult 结构:
|
|
91
|
+
# - result.items: list[T] # 数据列表
|
|
92
|
+
# - result.next_cursor: str | None # 下一页游标
|
|
93
|
+
# - result.prev_cursor: str | None # 上一页游标
|
|
94
|
+
# - result.has_next: bool # 是否有下一页
|
|
95
|
+
# - result.has_prev: bool # 是否有上一页
|
|
96
|
+
|
|
97
|
+
# === 流式查询(大数据处理) ===
|
|
98
|
+
# 逐条流式处理,不会一次性加载到内存
|
|
99
|
+
async for user in repo.stream(batch_size=1000, is_active=True):
|
|
100
|
+
await process(user)
|
|
101
|
+
|
|
102
|
+
# 批量流式处理
|
|
103
|
+
async for batch in repo.stream_batches(batch_size=1000):
|
|
104
|
+
await bulk_sync_to_es(batch)
|
|
105
|
+
|
|
75
106
|
# === 创建 ===
|
|
76
107
|
user = await repo.create({{"name": "Alice", "email": "a@b.com"}})
|
|
77
108
|
users = await repo.batch_create([{{"name": "A"}}, {{"name": "B"}}]) # 返回实体
|
|
@@ -396,3 +396,63 @@ DATABASE_ISOLATION_LEVEL=REPEATABLE READ
|
|
|
396
396
|
- 大多数场景:`READ COMMITTED`(平衡性能和一致性)
|
|
397
397
|
- 报表/统计查询:`REPEATABLE READ`(保证读取一致性)
|
|
398
398
|
- 金融交易:`SERIALIZABLE`(最强一致性,性能较低)
|
|
399
|
+
|
|
400
|
+
### 3.12 后台任务事务隔离(重要)
|
|
401
|
+
|
|
402
|
+
在 `@transactional` 装饰的 Service 方法中 spawn 后台任务时,**必须**使用 `@isolated_task` 或 `isolated_context`,否则事务不会提交。
|
|
403
|
+
|
|
404
|
+
**问题背景**:
|
|
405
|
+
`asyncio.create_task()` 会继承父协程的 `contextvars`。如果父协程在 `@transactional` 中,子任务会继承事务深度标记,导致:
|
|
406
|
+
- `auto_commit` 失效
|
|
407
|
+
- `transactional_context` 也不会提交
|
|
408
|
+
- session 关闭时数据被 rollback
|
|
409
|
+
|
|
410
|
+
**解决方案 1:装饰器(推荐)**
|
|
411
|
+
|
|
412
|
+
```python
|
|
413
|
+
import asyncio
|
|
414
|
+
from aury.boot.domain.transaction import isolated_task, transactional_context
|
|
415
|
+
from aury.boot.infrastructure.database import DatabaseManager
|
|
416
|
+
|
|
417
|
+
db = DatabaseManager.get_instance()
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
@isolated_task
|
|
421
|
+
async def upload_cover(space_id: int, cover_url: str):
|
|
422
|
+
"""后台任务:上传封面。"""
|
|
423
|
+
async with db.session() as session:
|
|
424
|
+
async with transactional_context(session):
|
|
425
|
+
repo = SpaceRepository(session, Space)
|
|
426
|
+
space = await repo.get(space_id)
|
|
427
|
+
if space:
|
|
428
|
+
await repo.update(space, {{"cover": cover_url}})
|
|
429
|
+
# 现在会正常 commit
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
class SpaceService(BaseService):
|
|
433
|
+
@transactional
|
|
434
|
+
async def create(self, data: SpaceCreate) -> Space:
|
|
435
|
+
space = await self.repo.create(data.model_dump())
|
|
436
|
+
|
|
437
|
+
# spawn 后台任务
|
|
438
|
+
asyncio.create_task(upload_cover(space.id, data.cover_url))
|
|
439
|
+
|
|
440
|
+
return space
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**解决方案 2:上下文管理器**
|
|
444
|
+
|
|
445
|
+
```python
|
|
446
|
+
from aury.boot.domain.transaction import isolated_context
|
|
447
|
+
|
|
448
|
+
async def background_job():
|
|
449
|
+
async with isolated_context():
|
|
450
|
+
async with db.session() as session:
|
|
451
|
+
async with transactional_context(session):
|
|
452
|
+
# 正常的事务处理
|
|
453
|
+
...
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
**注意事项**:
|
|
457
|
+
- 后台任务必须新开 session(`db.session()`),不能复用主请求的 `self.session`
|
|
458
|
+
- 后台任务的事务与主请求独立,主请求回滚不影响后台任务
|
|
@@ -18,6 +18,8 @@ from aury.boot.common.logging import logger
|
|
|
18
18
|
from aury.boot.domain.exceptions import VersionConflictError
|
|
19
19
|
from aury.boot.domain.models import GUID, Base
|
|
20
20
|
from aury.boot.domain.pagination import (
|
|
21
|
+
CursorPaginationParams,
|
|
22
|
+
CursorPaginationResult,
|
|
21
23
|
PaginationParams,
|
|
22
24
|
PaginationResult,
|
|
23
25
|
SortParams,
|
|
@@ -263,6 +265,168 @@ class BaseRepository[ModelType: Base](IRepository[ModelType]):
|
|
|
263
265
|
pagination_params=pagination_params,
|
|
264
266
|
)
|
|
265
267
|
|
|
268
|
+
async def cursor_paginate(
|
|
269
|
+
self,
|
|
270
|
+
params: CursorPaginationParams,
|
|
271
|
+
cursor_field: str = "id",
|
|
272
|
+
**filters
|
|
273
|
+
) -> CursorPaginationResult[ModelType]:
|
|
274
|
+
"""基于游标的分页查询。
|
|
275
|
+
|
|
276
|
+
适用于无限滚动、大数据集等场景,性能优于 offset 分页。
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
params: 游标分页参数(cursor, limit, direction)
|
|
280
|
+
cursor_field: 游标字段名,默认 "id",必须是有序且唯一的字段
|
|
281
|
+
**filters: 过滤条件
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
CursorPaginationResult: 包含 items, next_cursor, prev_cursor, has_next, has_prev
|
|
285
|
+
|
|
286
|
+
示例:
|
|
287
|
+
# 第一页
|
|
288
|
+
result = await repo.cursor_paginate(
|
|
289
|
+
CursorPaginationParams(limit=20),
|
|
290
|
+
status="active"
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
# 下一页
|
|
294
|
+
result = await repo.cursor_paginate(
|
|
295
|
+
CursorPaginationParams(cursor=result.next_cursor, limit=20),
|
|
296
|
+
status="active"
|
|
297
|
+
)
|
|
298
|
+
"""
|
|
299
|
+
import base64
|
|
300
|
+
import json
|
|
301
|
+
|
|
302
|
+
query = self._build_base_query()
|
|
303
|
+
query = self._apply_filters(query, **filters)
|
|
304
|
+
|
|
305
|
+
cursor_attr = _get_model_attr(self._model_class, cursor_field)
|
|
306
|
+
if cursor_attr is None:
|
|
307
|
+
raise AttributeError(f"模型 {self._model_class.__name__} 没有 '{cursor_field}' 字段")
|
|
308
|
+
|
|
309
|
+
# 解码 cursor
|
|
310
|
+
cursor_value = None
|
|
311
|
+
if params.cursor:
|
|
312
|
+
try:
|
|
313
|
+
decoded = base64.urlsafe_b64decode(params.cursor.encode()).decode()
|
|
314
|
+
cursor_value = json.loads(decoded)
|
|
315
|
+
except Exception:
|
|
316
|
+
raise ValueError("无效的游标") from None
|
|
317
|
+
|
|
318
|
+
# 根据方向决定查询条件和排序
|
|
319
|
+
is_next = params.direction == "next"
|
|
320
|
+
if cursor_value is not None:
|
|
321
|
+
if is_next:
|
|
322
|
+
query = query.where(cursor_attr > cursor_value)
|
|
323
|
+
else:
|
|
324
|
+
query = query.where(cursor_attr < cursor_value)
|
|
325
|
+
|
|
326
|
+
# 排序
|
|
327
|
+
if is_next:
|
|
328
|
+
query = query.order_by(cursor_attr)
|
|
329
|
+
else:
|
|
330
|
+
query = query.order_by(cursor_attr.desc())
|
|
331
|
+
|
|
332
|
+
# 多取一条判断是否有更多
|
|
333
|
+
query = query.limit(params.limit + 1)
|
|
334
|
+
result = await self._session.execute(query)
|
|
335
|
+
items = list(result.scalars().all())
|
|
336
|
+
|
|
337
|
+
has_more = len(items) > params.limit
|
|
338
|
+
if has_more:
|
|
339
|
+
items = items[:params.limit]
|
|
340
|
+
|
|
341
|
+
# 反向查询时反转结果
|
|
342
|
+
if not is_next:
|
|
343
|
+
items = list(reversed(items))
|
|
344
|
+
|
|
345
|
+
# 生成游标
|
|
346
|
+
def encode_cursor(value) -> str:
|
|
347
|
+
return base64.urlsafe_b64encode(json.dumps(value).encode()).decode()
|
|
348
|
+
|
|
349
|
+
next_cursor = None
|
|
350
|
+
prev_cursor = None
|
|
351
|
+
|
|
352
|
+
if items:
|
|
353
|
+
last_value = getattr(items[-1], cursor_field)
|
|
354
|
+
first_value = getattr(items[0], cursor_field)
|
|
355
|
+
|
|
356
|
+
if is_next:
|
|
357
|
+
if has_more:
|
|
358
|
+
next_cursor = encode_cursor(last_value)
|
|
359
|
+
if cursor_value is not None:
|
|
360
|
+
prev_cursor = encode_cursor(first_value)
|
|
361
|
+
else:
|
|
362
|
+
if cursor_value is not None:
|
|
363
|
+
next_cursor = encode_cursor(last_value)
|
|
364
|
+
if has_more:
|
|
365
|
+
prev_cursor = encode_cursor(first_value)
|
|
366
|
+
|
|
367
|
+
return CursorPaginationResult.create(
|
|
368
|
+
items=items,
|
|
369
|
+
next_cursor=next_cursor,
|
|
370
|
+
prev_cursor=prev_cursor,
|
|
371
|
+
limit=params.limit,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
async def stream(
|
|
375
|
+
self,
|
|
376
|
+
batch_size: int = 1000,
|
|
377
|
+
**filters
|
|
378
|
+
):
|
|
379
|
+
"""流式查询,使用数据库原生 server-side cursor。
|
|
380
|
+
|
|
381
|
+
适用于大数据集处理,避免一次性加载所有数据到内存。
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
batch_size: 每批次获取的记录数,默认 1000
|
|
385
|
+
**filters: 过滤条件
|
|
386
|
+
|
|
387
|
+
Yields:
|
|
388
|
+
ModelType: 模型实例
|
|
389
|
+
|
|
390
|
+
示例:
|
|
391
|
+
async for user in repo.stream(batch_size=500, status="active"):
|
|
392
|
+
process(user)
|
|
393
|
+
"""
|
|
394
|
+
query = self._build_base_query()
|
|
395
|
+
query = self._apply_filters(query, **filters)
|
|
396
|
+
|
|
397
|
+
async with self._session.stream_scalars(
|
|
398
|
+
query.execution_options(yield_per=batch_size)
|
|
399
|
+
) as result:
|
|
400
|
+
async for item in result:
|
|
401
|
+
yield item
|
|
402
|
+
|
|
403
|
+
async def stream_batches(
|
|
404
|
+
self,
|
|
405
|
+
batch_size: int = 1000,
|
|
406
|
+
**filters
|
|
407
|
+
):
|
|
408
|
+
"""批量流式查询,每次返回一批数据。
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
batch_size: 每批次的记录数,默认 1000
|
|
412
|
+
**filters: 过滤条件
|
|
413
|
+
|
|
414
|
+
Yields:
|
|
415
|
+
list[ModelType]: 一批模型实例
|
|
416
|
+
|
|
417
|
+
示例:
|
|
418
|
+
async for batch in repo.stream_batches(batch_size=500):
|
|
419
|
+
bulk_process(batch)
|
|
420
|
+
"""
|
|
421
|
+
query = self._build_base_query()
|
|
422
|
+
query = self._apply_filters(query, **filters)
|
|
423
|
+
|
|
424
|
+
async with self._session.stream_scalars(
|
|
425
|
+
query.execution_options(yield_per=batch_size)
|
|
426
|
+
) as result:
|
|
427
|
+
async for partition in result.partitions():
|
|
428
|
+
yield list(partition)
|
|
429
|
+
|
|
266
430
|
async def count(self, **filters) -> int:
|
|
267
431
|
query = select(func.count()).select_from(self._model_class)
|
|
268
432
|
if hasattr(self._model_class, "deleted_at"):
|
|
@@ -390,11 +390,68 @@ def requires_transaction(func: Callable) -> Callable:
|
|
|
390
390
|
return wrapper
|
|
391
391
|
|
|
392
392
|
|
|
393
|
+
def isolated_task[T](func: Callable[..., T]) -> Callable[..., T]:
|
|
394
|
+
"""后台任务隔离装饰器。
|
|
395
|
+
|
|
396
|
+
重置事务上下文,避免从父协程继承 _transaction_depth 导致 auto_commit 失效。
|
|
397
|
+
|
|
398
|
+
问题背景:
|
|
399
|
+
asyncio.create_task() 会继承父协程的 contextvars。如果父协程在 @transactional 中,
|
|
400
|
+
_transaction_depth > 0,子任务的 auto_commit 和 transactional_context 都会认为
|
|
401
|
+
"在事务中" 而跳过 commit,导致 session 关闭时 rollback。
|
|
402
|
+
|
|
403
|
+
用法:
|
|
404
|
+
@isolated_task
|
|
405
|
+
async def upload_cover(space_id: int, cover_url: str):
|
|
406
|
+
async with db.session() as session:
|
|
407
|
+
async with transactional_context(session):
|
|
408
|
+
repo = SpaceRepository(session, Space)
|
|
409
|
+
space = await repo.get(space_id)
|
|
410
|
+
await repo.update(space, {"cover": cover_url})
|
|
411
|
+
# 现在会正常 commit
|
|
412
|
+
|
|
413
|
+
# 在 Service 中 spawn
|
|
414
|
+
asyncio.create_task(upload_cover(space.id, url))
|
|
415
|
+
"""
|
|
416
|
+
@wraps(func)
|
|
417
|
+
async def wrapper(*args, **kwargs):
|
|
418
|
+
# 重置事务深度,让当前任务成为独立的事务上下文
|
|
419
|
+
token = _transaction_depth.set(0)
|
|
420
|
+
try:
|
|
421
|
+
return await func(*args, **kwargs)
|
|
422
|
+
finally:
|
|
423
|
+
_transaction_depth.reset(token)
|
|
424
|
+
|
|
425
|
+
return wrapper
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
@asynccontextmanager
|
|
429
|
+
async def isolated_context() -> AsyncGenerator[None]:
|
|
430
|
+
"""后台任务隔离上下文管理器。
|
|
431
|
+
|
|
432
|
+
与 @isolated_task 作用相同,但用于上下文管理器形式。
|
|
433
|
+
|
|
434
|
+
用法:
|
|
435
|
+
async def background_job():
|
|
436
|
+
async with isolated_context():
|
|
437
|
+
async with db.session() as session:
|
|
438
|
+
async with transactional_context(session):
|
|
439
|
+
...
|
|
440
|
+
"""
|
|
441
|
+
token = _transaction_depth.set(0)
|
|
442
|
+
try:
|
|
443
|
+
yield
|
|
444
|
+
finally:
|
|
445
|
+
_transaction_depth.reset(token)
|
|
446
|
+
|
|
447
|
+
|
|
393
448
|
__all__ = [
|
|
394
449
|
"TransactionManager",
|
|
395
450
|
"TransactionRequiredError",
|
|
396
451
|
"_transaction_depth", # 内部使用,不对外文档化
|
|
397
452
|
"ensure_transaction",
|
|
453
|
+
"isolated_context",
|
|
454
|
+
"isolated_task",
|
|
398
455
|
"on_commit",
|
|
399
456
|
"requires_transaction",
|
|
400
457
|
"transactional",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
aury/boot/__init__.py,sha256=pCno-EInnpIBa1OtxNYF-JWf9j95Cd2h6vmu0xqa_-4,1791
|
|
2
|
-
aury/boot/_version.py,sha256=
|
|
2
|
+
aury/boot/_version.py,sha256=p4kcB0BmpcnphBIseH7188jNCCOqFZSly7Pka9LrUDM,706
|
|
3
3
|
aury/boot/application/__init__.py,sha256=0o_XmiwFCeAu06VHggS8I1e7_nSMoRq0Hcm0fYfCywU,3071
|
|
4
4
|
aury/boot/application/adapter/__init__.py,sha256=e1bcSb1bxUMfofTwiCuHBZJk5-STkMCWPF2EJXHQ7UU,3976
|
|
5
5
|
aury/boot/application/adapter/base.py,sha256=Ar_66fiHPDEmV-1DKnqXKwc53p3pozG31bgTJTEUriY,15763
|
|
@@ -61,7 +61,7 @@ aury/boot/commands/templates/generate/model.py.tpl,sha256=knFwMyGZ7wMpzH4_bQD_V1
|
|
|
61
61
|
aury/boot/commands/templates/generate/repository.py.tpl,sha256=xoEg6lPAaLIRDeFy4I0FBsPPVLSy91h6xosAlaCL_mM,590
|
|
62
62
|
aury/boot/commands/templates/generate/schema.py.tpl,sha256=HIaY5B0UG_S188nQLrZDEJ0q73WPdb7BmCdc0tseZA4,545
|
|
63
63
|
aury/boot/commands/templates/generate/service.py.tpl,sha256=2hwQ8e4a5d_bIMx_jGDobdmKPMFLBlfQrQVQH4Ym5k4,1842
|
|
64
|
-
aury/boot/commands/templates/project/AGENTS.md.tpl,sha256=
|
|
64
|
+
aury/boot/commands/templates/project/AGENTS.md.tpl,sha256=SpqoXZXCyWmitBV6Mt0VvXWdPZAZXsLoU-vDEyJyQDc,8269
|
|
65
65
|
aury/boot/commands/templates/project/README.md.tpl,sha256=oCeBiukk6Pa3hrCKybkfM2sIRHsPZ15nlwuFTUSFDwY,2459
|
|
66
66
|
aury/boot/commands/templates/project/admin_console_init.py.tpl,sha256=K81L14thyEhRA8lFCQJVZL_NU22-sBz0xS68MJPeoCo,1541
|
|
67
67
|
aury/boot/commands/templates/project/config.py.tpl,sha256=H_B05FypBJxTjb7qIL91zC1C9e37Pk7C9gO0-b3CqNs,1009
|
|
@@ -70,8 +70,8 @@ aury/boot/commands/templates/project/gitignore.tpl,sha256=OI0nt9u2E9EC-jAMoh3gpq
|
|
|
70
70
|
aury/boot/commands/templates/project/main.py.tpl,sha256=Q61ve3o1VkNPv8wcQK7lUosne18JWYeItxoXVNNoYJM,1070
|
|
71
71
|
aury/boot/commands/templates/project/aury_docs/00-overview.md.tpl,sha256=8Aept3yEAe9cVdRvkddr_oEF-lr2riPXYRzBuw_6DBA,2138
|
|
72
72
|
aury/boot/commands/templates/project/aury_docs/01-model.md.tpl,sha256=1mQ3hGDxqEZjev4CD5-3dzYRFVonPNcAaStI1UBEUyM,6811
|
|
73
|
-
aury/boot/commands/templates/project/aury_docs/02-repository.md.tpl,sha256=
|
|
74
|
-
aury/boot/commands/templates/project/aury_docs/03-service.md.tpl,sha256=
|
|
73
|
+
aury/boot/commands/templates/project/aury_docs/02-repository.md.tpl,sha256=JfUVdrIgW7_J6JGCcB-_uP_x-gCtjKiewwGv4Xr44QI,7803
|
|
74
|
+
aury/boot/commands/templates/project/aury_docs/03-service.md.tpl,sha256=SgfPAgLVi_RbMjSAe-m49jQOIr6vfUT8VF2V1E-qa3w,15098
|
|
75
75
|
aury/boot/commands/templates/project/aury_docs/04-schema.md.tpl,sha256=ZwwKhUbLI--PEEmwnuo2fIZrhCEZagBN6fRNDTFCnNk,2891
|
|
76
76
|
aury/boot/commands/templates/project/aury_docs/05-api.md.tpl,sha256=oPzda3V6ZPDDEW-5MwyzmsMRuu5mXrsRGEq3lj0M-58,2997
|
|
77
77
|
aury/boot/commands/templates/project/aury_docs/06-exception.md.tpl,sha256=Tv_Q5lsScHzvtcaFWmuQzN4YqvpcWZIdXS8jw99K29E,3340
|
|
@@ -124,13 +124,13 @@ aury/boot/domain/models/mixins.py,sha256=7s4m4fzt0vWX71aTHgsoagjxSZZZ4_xSea_m0D8
|
|
|
124
124
|
aury/boot/domain/models/models.py,sha256=hNze58wPZkZ8QG2_pyszDsyKNjz2UgiRDzmneiCWLQs,2728
|
|
125
125
|
aury/boot/domain/pagination/__init__.py,sha256=HSU_NyLP-ij7ZDUi-ARSSvNkvhW1_wON2Zvu2QlF6HM,11890
|
|
126
126
|
aury/boot/domain/repository/__init__.py,sha256=dnmN8xFu1ASbLnzL6vx8gMoch7xBGxkJkxs9G1iGLGg,490
|
|
127
|
-
aury/boot/domain/repository/impl.py,sha256=
|
|
127
|
+
aury/boot/domain/repository/impl.py,sha256=BeWe6pMBP_OvxX91FmckxAZlM2qejol06If_UBy8FtU,22016
|
|
128
128
|
aury/boot/domain/repository/interceptors.py,sha256=SCTjRmBYwevAMlJ8U1uw-_McsDetNNQ7q0Da5lmfj_E,1238
|
|
129
129
|
aury/boot/domain/repository/interface.py,sha256=CmkiqVhhHPx_xcpuBCz11Vr26-govwYBxFsQ8myEVyw,2904
|
|
130
130
|
aury/boot/domain/repository/query_builder.py,sha256=pFErMzsBql-T6gBX0S4FxIheCkNaGjpSewzcJ2DxrUU,10890
|
|
131
131
|
aury/boot/domain/service/__init__.py,sha256=ZRotaBlqJXn7ebPTQjjoHtorpQREk8AgTD69UCcRd1k,118
|
|
132
132
|
aury/boot/domain/service/base.py,sha256=6sN0nf8r5yUZsE6AcZOiOXFCqzb61oCxTfrWlqjIo9I,2035
|
|
133
|
-
aury/boot/domain/transaction/__init__.py,sha256=
|
|
133
|
+
aury/boot/domain/transaction/__init__.py,sha256=EKnjJ235SYjMCvGIuLVlTdYRzU35RxNMejRGUExYqqE,15488
|
|
134
134
|
aury/boot/infrastructure/__init__.py,sha256=ppP1-suaDICMNvBSXj_4DVSH3h0D8e0qZhtENCr16m8,3007
|
|
135
135
|
aury/boot/infrastructure/cache/__init__.py,sha256=G40uCkpJ1jSs2fc_CBDem73iQQzCcp-4GG1WpDJzwaA,658
|
|
136
136
|
aury/boot/infrastructure/cache/backends.py,sha256=9QMQ8G9DtZgzVXZ_Ng7n1gXRu-_OQZgw4FHPOfr1qco,13585
|
|
@@ -192,7 +192,7 @@ aury/boot/testing/client.py,sha256=KOg1EemuIVsBG68G5y0DjSxZGcIQVdWQ4ASaHE3o1R0,4
|
|
|
192
192
|
aury/boot/testing/factory.py,sha256=8GvwX9qIDu0L65gzJMlrWB0xbmJ-7zPHuwk3eECULcg,5185
|
|
193
193
|
aury/boot/toolkit/__init__.py,sha256=AcyVb9fDf3CaEmJPNkWC4iGv32qCPyk4BuFKSuNiJRQ,334
|
|
194
194
|
aury/boot/toolkit/http/__init__.py,sha256=zIPmpIZ9Qbqe25VmEr7jixoY2fkRbLm7NkCB9vKpg6I,11039
|
|
195
|
-
aury_boot-0.0.
|
|
196
|
-
aury_boot-0.0.
|
|
197
|
-
aury_boot-0.0.
|
|
198
|
-
aury_boot-0.0.
|
|
195
|
+
aury_boot-0.0.29.dist-info/METADATA,sha256=EaL1z6pE7pRmQ6YSAytT91uPj34ejAyuzeTpWWpAI-g,7695
|
|
196
|
+
aury_boot-0.0.29.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
197
|
+
aury_boot-0.0.29.dist-info/entry_points.txt,sha256=f9KXEkDIGc0BGkgBvsNx_HMz9VhDjNxu26q00jUpDwQ,49
|
|
198
|
+
aury_boot-0.0.29.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|