documente_shared 0.1.161b5__tar.gz → 0.1.162__tar.gz
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.
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/.gitignore +2 -1
- documente_shared-0.1.162/.vscode/settings.json +11 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/Dockerfile +1 -1
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/Makefile +6 -2
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/PKG-INFO +7 -7
- documente_shared-0.1.162/documente_shared/application/dates.py +5 -0
- documente_shared-0.1.162/documente_shared/application/logging.py +47 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/query_params.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/retry_utils.py +24 -7
- documente_shared-0.1.162/documente_shared/domain/constants.py +10 -0
- documente_shared-0.1.162/documente_shared/domain/entities/document_type.py +49 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/workspace.py +23 -23
- documente_shared-0.1.162/documente_shared/domain/entities/workspace_document.py +116 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/workspace_document_page.py +13 -10
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/workspace_filters.py +2 -1
- documente_shared-0.1.162/documente_shared/domain/filters/document_type.py +24 -0
- documente_shared-0.1.162/documente_shared/domain/filters/workspace.py +28 -0
- documente_shared-0.1.162/documente_shared/domain/filters/workspace_document.py +46 -0
- documente_shared-0.1.162/documente_shared/domain/filters/workspace_document_page.py +27 -0
- documente_shared-0.1.162/documente_shared/domain/helpers/dicts.py +71 -0
- documente_shared-0.1.162/documente_shared/domain/helpers/encoding.py +13 -0
- documente_shared-0.1.162/documente_shared/domain/helpers/lists.py +113 -0
- documente_shared-0.1.162/documente_shared/domain/pagination/entities.py +88 -0
- documente_shared-0.1.162/documente_shared/domain/pagination/response.py +17 -0
- documente_shared-0.1.162/documente_shared/domain/repositories/document_type.py +44 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/repositories/workspace.py +7 -7
- documente_shared-0.1.162/documente_shared/domain/repositories/workspace_document.py +40 -0
- documente_shared-0.1.162/documente_shared/domain/repositories/workspace_document_page.py +59 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/batch_queue.py +4 -2
- documente_shared-0.1.162/documente_shared/infrastructure/documente_client.py +44 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/http_document.py +4 -2
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/http_processing_case.py +4 -2
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/http_processing_case_item.py +5 -3
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/http_processing_record.py +5 -3
- documente_shared-0.1.162/documente_shared/infrastructure/repositories/http_workspace.py +65 -0
- documente_shared-0.1.162/documente_shared/infrastructure/repositories/http_workspace_document.py +71 -0
- documente_shared-0.1.162/documente_shared/infrastructure/repositories/http_workspace_document_page.py +96 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/services/http_scaling.py +5 -3
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/pyproject.toml +7 -7
- documente_shared-0.1.162/tests/documente_shared/domain/entities/__init__.py +0 -0
- documente_shared-0.1.162/tests/documente_shared/infrastructure/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/uv.lock +141 -48
- documente_shared-0.1.161b5/documente_shared/application/dates.py +0 -7
- documente_shared-0.1.161b5/documente_shared/domain/constants.py +0 -8
- documente_shared-0.1.161b5/documente_shared/domain/entities/workspace_document.py +0 -138
- documente_shared-0.1.161b5/documente_shared/domain/entities/workspace_document_filters.py +0 -45
- documente_shared-0.1.161b5/documente_shared/domain/entities/workspace_document_page_filters.py +0 -32
- documente_shared-0.1.161b5/documente_shared/domain/repositories/workspace_document.py +0 -28
- documente_shared-0.1.161b5/documente_shared/domain/repositories/workspace_document_page.py +0 -28
- documente_shared-0.1.161b5/documente_shared/infrastructure/documente_client.py +0 -27
- documente_shared-0.1.161b5/documente_shared/infrastructure/repositories/http_workspace.py +0 -71
- documente_shared-0.1.161b5/documente_shared/infrastructure/repositories/http_workspace_document.py +0 -71
- documente_shared-0.1.161b5/documente_shared/infrastructure/repositories/http_workspace_document_page.py +0 -71
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/.github/workflows/publish.yml +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/README.md +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/cases.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/docker-compose.yml +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/digest.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/exceptions.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/files.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/json.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/numbers.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/payloads.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/time_utils.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/timezone.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/base_enum.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/document.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/document_metadata.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/in_memory_document.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/processing_case.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/processing_case_filters.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/processing_case_item.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/processing_case_item_filters.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/processing_documents.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/processing_event.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/processing_record.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/entities/scaling.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/enums/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/enums/circular_oficio.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/enums/common.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/enums/document.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/enums/document_type_record.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/enums/processing_case.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/enums/processing_case_validator.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/enums/workspace.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/exceptions.py +0 -0
- {documente_shared-0.1.161b5/documente_shared/domain/helpers → documente_shared-0.1.162/documente_shared/domain/filters}/__init__.py +0 -0
- {documente_shared-0.1.161b5/documente_shared/domain/interfaces → documente_shared-0.1.162/documente_shared/domain/helpers}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/helpers/values.py +0 -0
- {documente_shared-0.1.161b5/documente_shared/domain/repositories → documente_shared-0.1.162/documente_shared/domain/interfaces}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/interfaces/queue.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/interfaces/scaling.py +0 -0
- {documente_shared-0.1.161b5/documente_shared/infrastructure → documente_shared-0.1.162/documente_shared/domain/pagination}/__init__.py +0 -0
- {documente_shared-0.1.161b5/documente_shared/infrastructure → documente_shared-0.1.162/documente_shared/domain}/repositories/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/repositories/document.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/repositories/processing_case.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/repositories/processing_case_item.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/domain/repositories/processing_record.py +0 -0
- {documente_shared-0.1.161b5/documente_shared/infrastructure/services → documente_shared-0.1.162/documente_shared/infrastructure}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/dynamo_table.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/lambdas.py +0 -0
- {documente_shared-0.1.161b5/documente_shared/presentation → documente_shared-0.1.162/documente_shared/infrastructure/repositories}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/dynamo_document.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/dynamo_processing_case.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/dynamo_processing_case_item.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/mem_document.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/mem_processing_case.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/mem_processing_case_item.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/repositories/mem_processing_record.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/s3_bucket.py +0 -0
- {documente_shared-0.1.161b5/tests → documente_shared-0.1.162/documente_shared/infrastructure/services}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/infrastructure/sqs_queue.py +0 -0
- {documente_shared-0.1.161b5/tests/documente_shared → documente_shared-0.1.162/documente_shared/presentation}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/presentation/presenters.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/publish.sh +0 -0
- {documente_shared-0.1.161b5/tests/documente_shared/application → documente_shared-0.1.162/tests}/__init__.py +0 -0
- {documente_shared-0.1.161b5/tests/documente_shared/domain → documente_shared-0.1.162/tests/documente_shared}/__init__.py +0 -0
- {documente_shared-0.1.161b5/tests/documente_shared/domain/entities → documente_shared-0.1.162/tests/documente_shared/application}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/application/test_files.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/application/test_payloads.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/conftest.py +0 -0
- {documente_shared-0.1.161b5/tests/documente_shared/infrastructure → documente_shared-0.1.162/tests/documente_shared/domain}/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/domain/entities/test_in_memory_document.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/domain/entities/test_processing_case.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/domain/entities/test_processing_case_item.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/domain/entities/test_processing_record.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/domain/enums/test_processing_case_validator.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/infrastructure/repositories/__init__.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documente_shared/infrastructure/repositories/test_http_processing_record.py +0 -0
- {documente_shared-0.1.161b5 → documente_shared-0.1.162}/tests/documents.py +0 -0
|
@@ -5,6 +5,10 @@ COMPOSE_PACKAGE := @docker compose -f docker-compose.yml run --rm package
|
|
|
5
5
|
|
|
6
6
|
ARG=
|
|
7
7
|
|
|
8
|
+
setup:
|
|
9
|
+
uv sync --all-groups
|
|
10
|
+
|
|
11
|
+
|
|
8
12
|
build:
|
|
9
13
|
$(COMPOSE) build
|
|
10
14
|
|
|
@@ -22,7 +26,7 @@ clean:
|
|
|
22
26
|
docker ps -aq | xargs docker rm
|
|
23
27
|
|
|
24
28
|
test:
|
|
25
|
-
$(COMPOSE_PACKAGE) bash -c "pytest --pyargs $(ARG)"
|
|
29
|
+
$(COMPOSE_PACKAGE) bash -c "uv run pytest --pyargs $(ARG)"
|
|
26
30
|
|
|
27
31
|
test_single:
|
|
28
|
-
$(COMPOSE_PACKAGE) bash -c "pytest --pyargs -m single"
|
|
32
|
+
$(COMPOSE_PACKAGE) bash -c "uv run pytest --pyargs -m single"
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: documente_shared
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary: Shared utilities for
|
|
3
|
+
Version: 0.1.162
|
|
4
|
+
Summary: Shared utilities for LlamitAI projects
|
|
5
5
|
Author-email: Tech <tech@llamitai.com>
|
|
6
6
|
License: MIT
|
|
7
7
|
Requires-Python: <3.13,>=3.10
|
|
8
|
-
Requires-Dist: boto3>=1.42.
|
|
9
|
-
Requires-Dist: botocore>=1.42.
|
|
10
|
-
Requires-Dist:
|
|
11
|
-
Requires-Dist: pytz>=2025.2
|
|
8
|
+
Requires-Dist: boto3>=1.42.46
|
|
9
|
+
Requires-Dist: botocore>=1.42.46
|
|
10
|
+
Requires-Dist: pydantic>=2.12.5
|
|
12
11
|
Requires-Dist: requests>=2.32.5
|
|
13
|
-
Requires-Dist: sentry-sdk>=2.
|
|
12
|
+
Requires-Dist: sentry-sdk>=2.52.0
|
|
13
|
+
Requires-Dist: structlog>=25.5.0
|
|
14
14
|
Requires-Dist: unidecode>=1.4.0
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import logging
|
|
3
|
+
import structlog
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def configure_logging(environment: str = "dev") -> None:
|
|
7
|
+
is_production = environment in ("production", "staging")
|
|
8
|
+
|
|
9
|
+
shared_processors = [
|
|
10
|
+
structlog.contextvars.merge_contextvars,
|
|
11
|
+
structlog.stdlib.add_log_level,
|
|
12
|
+
structlog.stdlib.add_logger_name,
|
|
13
|
+
structlog.processors.TimeStamper(fmt="iso"),
|
|
14
|
+
structlog.processors.StackInfoRenderer(),
|
|
15
|
+
structlog.processors.UnicodeDecoder(),
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
if is_production:
|
|
19
|
+
renderer = structlog.processors.JSONRenderer()
|
|
20
|
+
else:
|
|
21
|
+
renderer = structlog.dev.ConsoleRenderer()
|
|
22
|
+
|
|
23
|
+
structlog.configure(
|
|
24
|
+
processors=[
|
|
25
|
+
*shared_processors,
|
|
26
|
+
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
|
|
27
|
+
],
|
|
28
|
+
logger_factory=structlog.stdlib.LoggerFactory(),
|
|
29
|
+
wrapper_class=structlog.stdlib.BoundLogger, # type: ignore[arg-type]
|
|
30
|
+
cache_logger_on_first_use=True,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
formatter = structlog.stdlib.ProcessorFormatter(
|
|
34
|
+
processors=[
|
|
35
|
+
structlog.stdlib.ProcessorFormatter.remove_processors_meta,
|
|
36
|
+
renderer,
|
|
37
|
+
],
|
|
38
|
+
foreign_pre_chain=shared_processors,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
handler = logging.StreamHandler(sys.stdout)
|
|
42
|
+
handler.setFormatter(formatter)
|
|
43
|
+
|
|
44
|
+
root_logger = logging.getLogger()
|
|
45
|
+
root_logger.handlers.clear()
|
|
46
|
+
root_logger.addHandler(handler)
|
|
47
|
+
root_logger.setLevel(logging.INFO)
|
{documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/query_params.py
RENAMED
|
File without changes
|
{documente_shared-0.1.161b5 → documente_shared-0.1.162}/documente_shared/application/retry_utils.py
RENAMED
|
@@ -2,7 +2,9 @@ import time
|
|
|
2
2
|
import random
|
|
3
3
|
from functools import wraps
|
|
4
4
|
from typing import Optional, Callable
|
|
5
|
-
|
|
5
|
+
import structlog
|
|
6
|
+
|
|
7
|
+
logger = structlog.get_logger()
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
def retry_on_size_integrity(base_delay: float = 0.8, max_retries: int = 3):
|
|
@@ -15,7 +17,10 @@ def retry_on_size_integrity(base_delay: float = 0.8, max_retries: int = 3):
|
|
|
15
17
|
|
|
16
18
|
if not file_context:
|
|
17
19
|
logger.warning(
|
|
18
|
-
|
|
20
|
+
"[shared.retry.file_context_none]",
|
|
21
|
+
attempt=attempt + 1,
|
|
22
|
+
max_retries=max_retries,
|
|
23
|
+
file_key=file_key,
|
|
19
24
|
)
|
|
20
25
|
if attempt < max_retries - 1:
|
|
21
26
|
delay = base_delay * (2 ** attempt) + random.uniform(0, base_delay)
|
|
@@ -25,7 +30,10 @@ def retry_on_size_integrity(base_delay: float = 0.8, max_retries: int = 3):
|
|
|
25
30
|
|
|
26
31
|
if 'Body' not in file_context:
|
|
27
32
|
logger.warning(
|
|
28
|
-
|
|
33
|
+
"[shared.retry.body_not_found]",
|
|
34
|
+
attempt=attempt + 1,
|
|
35
|
+
max_retries=max_retries,
|
|
36
|
+
file_key=file_key,
|
|
29
37
|
)
|
|
30
38
|
if attempt < max_retries - 1:
|
|
31
39
|
delay = base_delay * (2 ** attempt) + random.uniform(0, base_delay)
|
|
@@ -40,12 +48,16 @@ def retry_on_size_integrity(base_delay: float = 0.8, max_retries: int = 3):
|
|
|
40
48
|
if expected_size == actual_size:
|
|
41
49
|
file_context['Body'] = body
|
|
42
50
|
if attempt > 0:
|
|
43
|
-
logger.info(
|
|
51
|
+
logger.info("[shared.retry.download_success]", file_key=file_key, attempts=attempt + 1)
|
|
44
52
|
return file_context
|
|
45
53
|
|
|
46
54
|
logger.warning(
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
"[shared.retry.size_mismatch]",
|
|
56
|
+
attempt=attempt + 1,
|
|
57
|
+
max_retries=max_retries,
|
|
58
|
+
file_key=file_key,
|
|
59
|
+
expected_size=expected_size,
|
|
60
|
+
actual_size=actual_size,
|
|
49
61
|
)
|
|
50
62
|
|
|
51
63
|
if attempt < max_retries - 1:
|
|
@@ -54,7 +66,12 @@ def retry_on_size_integrity(base_delay: float = 0.8, max_retries: int = 3):
|
|
|
54
66
|
|
|
55
67
|
except Exception as e:
|
|
56
68
|
logger.error(
|
|
57
|
-
|
|
69
|
+
"[shared.retry.download_error]",
|
|
70
|
+
attempt=attempt + 1,
|
|
71
|
+
max_retries=max_retries,
|
|
72
|
+
file_key=file_key,
|
|
73
|
+
error_type=type(e).__name__,
|
|
74
|
+
error=str(e),
|
|
58
75
|
)
|
|
59
76
|
if attempt < max_retries - 1:
|
|
60
77
|
delay = base_delay * (2 ** attempt) + random.uniform(0, base_delay)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from uuid import UUID
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
from documente_shared.domain.enums.processing_case import ProcessingDocumentType
|
|
7
|
+
from documente_shared.domain.helpers.values import optional_str
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DocumentType(BaseModel):
|
|
11
|
+
uuid: UUID
|
|
12
|
+
name: str
|
|
13
|
+
tenant_id: UUID | None = Field(default=None)
|
|
14
|
+
is_shareable: bool = False
|
|
15
|
+
processing_document_type: ProcessingDocumentType | None = Field(default=None)
|
|
16
|
+
metadata: dict | None = Field(default=None)
|
|
17
|
+
created_at: datetime | None = Field(default=None)
|
|
18
|
+
updated_at: datetime | None = Field(default=None)
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def to_persist_dict(self) -> dict:
|
|
22
|
+
return {
|
|
23
|
+
"tenant_id": self.tenant_id,
|
|
24
|
+
"name": self.name,
|
|
25
|
+
"is_shareable": self.is_shareable,
|
|
26
|
+
"processing_document_type": optional_str(self.processing_document_type),
|
|
27
|
+
"metadata": self.metadata or {},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def to_dict(self) -> dict:
|
|
32
|
+
return {
|
|
33
|
+
"uuid": str(self.uuid),
|
|
34
|
+
"name": self.name,
|
|
35
|
+
"tenant_id": self
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def from_dict(cls, data: dict) -> 'DocumentType':
|
|
40
|
+
return cls(
|
|
41
|
+
uuid=data.get('uuid'),
|
|
42
|
+
name=data.get('name'),
|
|
43
|
+
tenant_id=data.get('tenant_id'),
|
|
44
|
+
is_shareable=data.get('is_shareable', False),
|
|
45
|
+
processing_document_type=ProcessingDocumentType.from_value(data.get('processing_document_type')),
|
|
46
|
+
metadata=data.get('metadata', {}),
|
|
47
|
+
created_at=data.get('created_at'),
|
|
48
|
+
updated_at=data.get('updated_at'),
|
|
49
|
+
)
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
1
|
from datetime import datetime
|
|
3
|
-
from typing import Optional
|
|
4
2
|
from uuid import UUID
|
|
5
3
|
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
6
|
from documente_shared.application.time_utils import get_datetime_from_data
|
|
7
|
+
from documente_shared.domain.entities.document_type import DocumentType
|
|
8
|
+
from documente_shared.domain.helpers.values import optional_datetime_str
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
class Workspace(object):
|
|
12
|
+
class Workspace(BaseModel):
|
|
11
13
|
uuid: UUID
|
|
12
14
|
name: str
|
|
13
|
-
|
|
15
|
+
tenant_id: UUID | None = Field(default=None)
|
|
16
|
+
tenant_slug: str | None = Field(default=None)
|
|
14
17
|
is_archived: bool = False
|
|
15
|
-
metadata:
|
|
16
|
-
created_at:
|
|
17
|
-
updated_at:
|
|
18
|
-
document_types:
|
|
18
|
+
metadata: dict | None = Field(default_factory=dict)
|
|
19
|
+
created_at: datetime | None = Field(default=None)
|
|
20
|
+
updated_at: datetime | None = Field(default=None)
|
|
21
|
+
document_types: list[DocumentType] | None = Field(default_factory=list)
|
|
19
22
|
|
|
20
|
-
def __post_init__(self):
|
|
21
|
-
self.metadata = self.metadata or {}
|
|
22
|
-
self.document_types = self.document_types or []
|
|
23
23
|
|
|
24
24
|
@property
|
|
25
25
|
def to_persist_dict(self) -> dict:
|
|
26
26
|
return {
|
|
27
|
-
"
|
|
27
|
+
"tenant_id": self.tenant_id,
|
|
28
28
|
"name": self.name,
|
|
29
29
|
"is_archived": self.is_archived,
|
|
30
30
|
"metadata": self.metadata or {},
|
|
@@ -35,29 +35,29 @@ class Workspace(object):
|
|
|
35
35
|
return {
|
|
36
36
|
"uuid": str(self.uuid),
|
|
37
37
|
"name": self.name,
|
|
38
|
+
"tenant_id": self.tenant_id,
|
|
38
39
|
"tenant_slug": self.tenant_slug,
|
|
39
40
|
"is_archived": self.is_archived,
|
|
40
41
|
"metadata": self.metadata,
|
|
41
|
-
"created_at": (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
),
|
|
45
|
-
"updated_at": (
|
|
46
|
-
self.updated_at.isoformat()
|
|
47
|
-
if self.updated_at else None
|
|
48
|
-
),
|
|
49
|
-
"document_types": self.document_types,
|
|
42
|
+
"created_at": optional_datetime_str(self.created_at),
|
|
43
|
+
"updated_at": optional_datetime_str(self.updated_at),
|
|
44
|
+
"document_types": [dt.to_dict for dt in self.document_types] if self.document_types else [],
|
|
50
45
|
}
|
|
51
46
|
|
|
52
47
|
@classmethod
|
|
53
48
|
def from_dict(cls, data: dict) -> 'Workspace':
|
|
49
|
+
document_types = data.get('document_types', [])
|
|
54
50
|
return cls(
|
|
55
51
|
uuid=data.get('uuid'),
|
|
56
52
|
name=data.get('name'),
|
|
53
|
+
tenant_id=data.get('tenant_id'),
|
|
57
54
|
tenant_slug=data.get('tenant_slug'),
|
|
58
55
|
is_archived=data.get('is_archived', False),
|
|
59
56
|
metadata=data.get('metadata', {}),
|
|
60
57
|
created_at=get_datetime_from_data(input_datetime=data.get('created_at')),
|
|
61
58
|
updated_at=get_datetime_from_data(input_datetime=data.get('updated_at')),
|
|
62
|
-
document_types=
|
|
59
|
+
document_types=[
|
|
60
|
+
DocumentType.from_dict(dt)
|
|
61
|
+
for dt in document_types
|
|
62
|
+
],
|
|
63
63
|
)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from dataclasses import Field, dataclass
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from documente_shared.application.time_utils import get_datetime_from_data
|
|
9
|
+
from documente_shared.domain.entities.in_memory_document import InMemoryDocument
|
|
10
|
+
from documente_shared.domain.enums.common import ProcessingStatus
|
|
11
|
+
from documente_shared.domain.enums.workspace import WorkspaceSource
|
|
12
|
+
from documente_shared.domain.helpers.values import optional_str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WorkspaceDocument(BaseModel):
|
|
16
|
+
uuid: UUID
|
|
17
|
+
name: str
|
|
18
|
+
status: ProcessingStatus
|
|
19
|
+
workspace_id: UUID
|
|
20
|
+
tenant_id: UUID | None = Field(default=None)
|
|
21
|
+
tenant_slug: str | None = Field(default=None)
|
|
22
|
+
digest: str | None = Field(default=None)
|
|
23
|
+
document_type_id: UUID | None = Field(default=None)
|
|
24
|
+
source: WorkspaceSource | None = Field(default=None)
|
|
25
|
+
document: InMemoryDocument | None = Field(default=None)
|
|
26
|
+
document_url: str | None = Field(default=None)
|
|
27
|
+
processing_time: Decimal | None = Field(default=None)
|
|
28
|
+
metadata: dict | None = Field(default_factory=dict)
|
|
29
|
+
extraction: dict | None = Field(default_factory=dict)
|
|
30
|
+
uploaded_at: datetime | None = Field(default=None)
|
|
31
|
+
created_at: datetime | None = Field(default=None)
|
|
32
|
+
updated_at: datetime | None = Field(default=None)
|
|
33
|
+
started_at: datetime | None = Field(default=None)
|
|
34
|
+
completed_at: datetime | None = Field(default=None)
|
|
35
|
+
failed_at: datetime | None = Field(default=None)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def to_persist_dict(self) -> dict:
|
|
40
|
+
return {
|
|
41
|
+
"tenant_id": self.tenant_id,
|
|
42
|
+
"workspace_id": str(self.workspace_id),
|
|
43
|
+
"document_type_id": optional_str(self.document_type_id),
|
|
44
|
+
"name": self.name,
|
|
45
|
+
"digest": self.digest,
|
|
46
|
+
"status": str(self.status),
|
|
47
|
+
"source": optional_str(self.source),
|
|
48
|
+
"uploaded_at": self.uploaded_at,
|
|
49
|
+
"started_at": self.started_at,
|
|
50
|
+
"completed_at": self.completed_at,
|
|
51
|
+
"failed_at": self.failed_at,
|
|
52
|
+
"processing_time": self.processing_time,
|
|
53
|
+
"metadata": self.metadata or {},
|
|
54
|
+
"extraction": self.extraction or {},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def to_dict(self) -> dict:
|
|
59
|
+
return {
|
|
60
|
+
"uuid": str(self.uuid),
|
|
61
|
+
"name": self.name,
|
|
62
|
+
"digest": self.digest,
|
|
63
|
+
"status": str(self.status),
|
|
64
|
+
"tenant_id": self.tenant_id,
|
|
65
|
+
"tenant_slug": self.tenant_slug,
|
|
66
|
+
"workspace_id": str(self.workspace_id),
|
|
67
|
+
"document_type_id": optional_str(self.document_type_id),
|
|
68
|
+
"source": optional_str(self.source),
|
|
69
|
+
"document": (self.document.to_dict if self.document else None),
|
|
70
|
+
"document_url": self.document_url,
|
|
71
|
+
"processing_time": optional_str(self.processing_time),
|
|
72
|
+
"metadata": self.metadata,
|
|
73
|
+
"extraction": self.extraction,
|
|
74
|
+
"uploaded_at": (self.uploaded_at.isoformat() if self.uploaded_at else None),
|
|
75
|
+
"created_at": (self.created_at.isoformat() if self.created_at else None),
|
|
76
|
+
"updated_at": (self.updated_at.isoformat() if self.updated_at else None),
|
|
77
|
+
"started_at": (self.started_at.isoformat() if self.started_at else None),
|
|
78
|
+
"completed_at": (
|
|
79
|
+
self.completed_at.isoformat() if self.completed_at else None
|
|
80
|
+
),
|
|
81
|
+
"failed_at": (self.failed_at.isoformat() if self.failed_at else None),
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def from_dict(cls, data: dict) -> "WorkspaceDocument":
|
|
86
|
+
return cls(
|
|
87
|
+
uuid=data.get("uuid"),
|
|
88
|
+
name=data.get("name"),
|
|
89
|
+
digest=data.get("digest"),
|
|
90
|
+
status=ProcessingStatus.from_value(data.get("status")),
|
|
91
|
+
tenant_slug=data.get("tenant_slug"),
|
|
92
|
+
workspace_id=data.get("workspace_id"),
|
|
93
|
+
document_type_id=data.get("document_type_id"),
|
|
94
|
+
source=WorkspaceSource.from_value(data.get("source")),
|
|
95
|
+
document=(
|
|
96
|
+
InMemoryDocument.from_dict(data.get("document"))
|
|
97
|
+
if data.get("document")
|
|
98
|
+
else None
|
|
99
|
+
),
|
|
100
|
+
document_url=data.get("document_url"),
|
|
101
|
+
processing_time=(
|
|
102
|
+
Decimal(data.get("processing_time"))
|
|
103
|
+
if data.get("processing_time")
|
|
104
|
+
else None
|
|
105
|
+
),
|
|
106
|
+
metadata=data.get("metadata", {}),
|
|
107
|
+
extraction=data.get("extraction", {}),
|
|
108
|
+
uploaded_at=get_datetime_from_data(input_datetime=data.get("uploaded_at")),
|
|
109
|
+
created_at=get_datetime_from_data(input_datetime=data.get("created_at")),
|
|
110
|
+
updated_at=get_datetime_from_data(input_datetime=data.get("updated_at")),
|
|
111
|
+
started_at=get_datetime_from_data(input_datetime=data.get("started_at")),
|
|
112
|
+
completed_at=get_datetime_from_data(
|
|
113
|
+
input_datetime=data.get("completed_at")
|
|
114
|
+
),
|
|
115
|
+
failed_at=get_datetime_from_data(input_datetime=data.get("failed_at")),
|
|
116
|
+
)
|
|
@@ -1,28 +1,29 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
1
|
from datetime import datetime
|
|
3
|
-
from typing import Optional
|
|
4
2
|
from uuid import UUID
|
|
5
3
|
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
6
|
from documente_shared.application.time_utils import get_datetime_from_data
|
|
7
7
|
from documente_shared.domain.entities.in_memory_document import InMemoryDocument
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
class WorkspaceDocumentPage(
|
|
10
|
+
|
|
11
|
+
class WorkspaceDocumentPage(BaseModel):
|
|
12
12
|
uuid: UUID
|
|
13
|
-
tenant_slug: str
|
|
14
13
|
workspace_id: UUID
|
|
15
14
|
workspace_document_id: UUID
|
|
16
15
|
page_number: int
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
tenant_id: UUID | None = Field(default=None)
|
|
17
|
+
tenant_slug: str | None = Field(default=None)
|
|
18
|
+
page_file: InMemoryDocument | None = Field(default=None)
|
|
19
|
+
page_file_url: str | None = Field(default=None)
|
|
20
|
+
created_at: datetime | None = Field(default=None)
|
|
21
|
+
synced_at: datetime | None = Field(default=None)
|
|
21
22
|
|
|
22
23
|
@property
|
|
23
24
|
def to_persist_dict(self) -> dict:
|
|
24
25
|
return {
|
|
25
|
-
"
|
|
26
|
+
"tenant_id": self.tenant_id,
|
|
26
27
|
"workspace_id": str(self.workspace_id),
|
|
27
28
|
"workspace_document_id": str(self.workspace_document_id),
|
|
28
29
|
"page_number": self.page_number,
|
|
@@ -33,6 +34,7 @@ class WorkspaceDocumentPage(object):
|
|
|
33
34
|
def to_dict(self) -> dict:
|
|
34
35
|
return {
|
|
35
36
|
"uuid": str(self.uuid),
|
|
37
|
+
"tenant_id": self.tenant_id,
|
|
36
38
|
"tenant_slug": self.tenant_slug,
|
|
37
39
|
"workspace_id": str(self.workspace_id),
|
|
38
40
|
"workspace_document_id": str(self.workspace_document_id),
|
|
@@ -56,6 +58,7 @@ class WorkspaceDocumentPage(object):
|
|
|
56
58
|
def from_dict(cls, data: dict) -> 'WorkspaceDocumentPage':
|
|
57
59
|
return cls(
|
|
58
60
|
uuid=data.get('uuid'),
|
|
61
|
+
tenant_id=data.get('tenant_id'),
|
|
59
62
|
tenant_slug=data.get('tenant_slug'),
|
|
60
63
|
workspace_id=data.get('workspace_id'),
|
|
61
64
|
workspace_document_id=data.get('workspace_document_id'),
|
|
@@ -2,6 +2,7 @@ from dataclasses import dataclass
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
from documente_shared.application.query_params import QueryParams
|
|
5
|
+
from documente_shared.domain.helpers.dicts import filter_none_values
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
@dataclass
|
|
@@ -20,7 +21,7 @@ class WorkspaceFilters(object):
|
|
|
20
21
|
"search": self.search,
|
|
21
22
|
"include_archived": str(self.include_archived).lower(),
|
|
22
23
|
}
|
|
23
|
-
return
|
|
24
|
+
return filter_none_values(params)
|
|
24
25
|
|
|
25
26
|
@classmethod
|
|
26
27
|
def from_params(cls, params: QueryParams) -> "WorkspaceFilters":
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from uuid import UUID
|
|
2
|
+
from pydantic import Field
|
|
3
|
+
|
|
4
|
+
from documente_shared.application.query_params import QueryParams
|
|
5
|
+
from documente_shared.domain.helpers.dicts import filter_none_values
|
|
6
|
+
from documente_shared.domain.pagination.entities import ListFilters
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DocumentTypeFilters(ListFilters):
|
|
10
|
+
tenant_ids: list[UUID] | None = Field(default_factory=list)
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def to_params(self) -> dict:
|
|
14
|
+
return filter_none_values({
|
|
15
|
+
**super().to_dict,
|
|
16
|
+
"tenant_ids": self.tenant_ids,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def from_params(cls, params: QueryParams) -> "DocumentTypeFilters":
|
|
21
|
+
return cls(
|
|
22
|
+
cursor=params.get("cursor", None),
|
|
23
|
+
limit=params.get_int(key="limit", default=None),
|
|
24
|
+
)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from uuid import UUID
|
|
2
|
+
from pydantic import Field
|
|
3
|
+
|
|
4
|
+
from documente_shared.application.query_params import QueryParams
|
|
5
|
+
from documente_shared.domain.helpers.dicts import filter_none_values
|
|
6
|
+
from documente_shared.domain.pagination.entities import ListFilters
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WorkspaceFilters(ListFilters):
|
|
10
|
+
tenant_ids: list[UUID] | None = Field(default_factory=list)
|
|
11
|
+
search: str | None = Field(default=None)
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def to_params(self) -> dict:
|
|
15
|
+
return filter_none_values({
|
|
16
|
+
**super().to_dict,
|
|
17
|
+
"tenant_ids": self.tenant_ids,
|
|
18
|
+
"search": self.search,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def from_params(cls, params: QueryParams) -> "WorkspaceFilters":
|
|
23
|
+
search_term = params.get_str(key="search", default=None)
|
|
24
|
+
return cls(
|
|
25
|
+
cursor=params.get("cursor", None),
|
|
26
|
+
limit=params.get_int(key="limit", default=None),
|
|
27
|
+
search=search_term.strip() if search_term else None,
|
|
28
|
+
)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from uuid import UUID
|
|
2
|
+
from pydantic import Field
|
|
3
|
+
|
|
4
|
+
from documente_shared.application.query_params import QueryParams
|
|
5
|
+
from documente_shared.domain.enums.common import ProcessingStatus
|
|
6
|
+
from documente_shared.domain.helpers.dicts import filter_none_values
|
|
7
|
+
from documente_shared.domain.helpers.lists import enum_list_to_comma_string
|
|
8
|
+
from documente_shared.domain.pagination.entities import ListFilters
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class WorkspaceDocumentFilters(ListFilters):
|
|
12
|
+
workspace_id: UUID | None = Field(default=None)
|
|
13
|
+
tenant_ids: list[UUID] | None = Field(default_factory=list)
|
|
14
|
+
workspace_ids: list[UUID] | None = Field(default_factory=list)
|
|
15
|
+
statuses: list[ProcessingStatus] | None = Field(default_factory=list)
|
|
16
|
+
search: str | None = Field(default=None)
|
|
17
|
+
digest: str | None = Field(default=None)
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def to_params(self) -> dict:
|
|
21
|
+
return filter_none_values({
|
|
22
|
+
**super().to_dict,
|
|
23
|
+
"tenant_ids": self.tenant_ids,
|
|
24
|
+
"workspace_ids": self.workspace_ids,
|
|
25
|
+
"search": self.search,
|
|
26
|
+
"digest": self.digest,
|
|
27
|
+
"statuses": enum_list_to_comma_string(self.statuses),
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def from_params(cls, params: QueryParams) -> "WorkspaceDocumentFilters":
|
|
32
|
+
search_term = params.get_str(key="search", default=None)
|
|
33
|
+
return cls(
|
|
34
|
+
cursor=params.get("cursor", None),
|
|
35
|
+
limit=params.get_int(key="limit", default=None),
|
|
36
|
+
workspace_id=params.get_uuid(key="workspace_id", default=None),
|
|
37
|
+
tenant_ids=params.get_uuid_list(key="tenant_ids", default=None),
|
|
38
|
+
workspace_ids=params.get_uuid_list(key="workspace_ids", default=None),
|
|
39
|
+
search=search_term.strip() if search_term else None,
|
|
40
|
+
digest=params.get_str(key="digest", default=None),
|
|
41
|
+
statuses=params.get_enum_list(
|
|
42
|
+
key="statuses",
|
|
43
|
+
enum_class=ProcessingStatus,
|
|
44
|
+
default=None,
|
|
45
|
+
),
|
|
46
|
+
)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from uuid import UUID
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
5
|
+
from documente_shared.application.query_params import QueryParams
|
|
6
|
+
from documente_shared.domain.helpers.dicts import filter_none_values
|
|
7
|
+
from documente_shared.domain.helpers.values import optional_str
|
|
8
|
+
from documente_shared.domain.pagination.entities import ListFilters
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class WorkspaceDocumentPageFilters(ListFilters):
|
|
12
|
+
workspace_document_id: UUID | None = Field(default=None)
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def to_params(self) -> dict:
|
|
16
|
+
return filter_none_values({
|
|
17
|
+
**super().to_dict,
|
|
18
|
+
"workspace_document_id": optional_str(self.workspace_document_id),
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def from_params(cls, params: QueryParams) -> "WorkspaceDocumentPageFilters":
|
|
23
|
+
return cls(
|
|
24
|
+
cursor=params.get("cursor", None),
|
|
25
|
+
limit=params.get_int(key="limit", default=None),
|
|
26
|
+
workspace_document_id=params.get_uuid(key="workspace_document_id", default=None),
|
|
27
|
+
)
|