documente_shared 0.1.160__tar.gz → 0.1.161b1__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.
Files changed (108) hide show
  1. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/PKG-INFO +1 -1
  2. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/query_params.py +0 -0
  3. documente_shared-0.1.161b1/documente_shared/domain/entities/workspace.py +63 -0
  4. documente_shared-0.1.161b1/documente_shared/domain/entities/workspace_document.py +138 -0
  5. documente_shared-0.1.161b1/documente_shared/domain/entities/workspace_document_page.py +70 -0
  6. documente_shared-0.1.161b1/documente_shared/domain/enums/workspace.py +19 -0
  7. documente_shared-0.1.161b1/documente_shared/domain/repositories/workspace.py +31 -0
  8. documente_shared-0.1.161b1/documente_shared/domain/repositories/workspace_document.py +42 -0
  9. documente_shared-0.1.161b1/documente_shared/domain/repositories/workspace_document_page.py +41 -0
  10. documente_shared-0.1.161b1/documente_shared/infrastructure/repositories/http_workspace.py +89 -0
  11. documente_shared-0.1.161b1/documente_shared/infrastructure/repositories/http_workspace_document.py +113 -0
  12. documente_shared-0.1.161b1/documente_shared/infrastructure/repositories/http_workspace_document_page.py +107 -0
  13. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/pyproject.toml +1 -1
  14. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/uv.lock +1 -1
  15. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/.github/workflows/publish.yml +0 -0
  16. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/.gitignore +0 -0
  17. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/Dockerfile +0 -0
  18. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/Makefile +0 -0
  19. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/README.md +0 -0
  20. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/__init__.py +0 -0
  21. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/cases.py +0 -0
  22. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/docker-compose.yml +0 -0
  23. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/__init__.py +0 -0
  24. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/__init__.py +0 -0
  25. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/dates.py +0 -0
  26. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/digest.py +0 -0
  27. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/exceptions.py +0 -0
  28. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/files.py +0 -0
  29. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/json.py +0 -0
  30. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/numbers.py +0 -0
  31. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/payloads.py +0 -0
  32. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/retry_utils.py +0 -0
  33. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/time_utils.py +0 -0
  34. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/application/timezone.py +0 -0
  35. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/__init__.py +0 -0
  36. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/base_enum.py +0 -0
  37. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/constants.py +0 -0
  38. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/__init__.py +0 -0
  39. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/document.py +0 -0
  40. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/document_metadata.py +0 -0
  41. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/in_memory_document.py +0 -0
  42. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/processing_case.py +0 -0
  43. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/processing_case_filters.py +0 -0
  44. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/processing_case_item.py +0 -0
  45. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/processing_case_item_filters.py +0 -0
  46. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/processing_documents.py +0 -0
  47. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/processing_event.py +0 -0
  48. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/processing_record.py +0 -0
  49. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/entities/scaling.py +0 -0
  50. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/enums/__init__.py +0 -0
  51. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/enums/circular_oficio.py +0 -0
  52. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/enums/common.py +0 -0
  53. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/enums/document.py +0 -0
  54. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/enums/document_type_record.py +0 -0
  55. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/enums/processing_case.py +0 -0
  56. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/enums/processing_case_validator.py +0 -0
  57. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/exceptions.py +0 -0
  58. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/helpers/__init__.py +0 -0
  59. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/helpers/values.py +0 -0
  60. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/interfaces/__init__.py +0 -0
  61. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/interfaces/queue.py +0 -0
  62. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/interfaces/scaling.py +0 -0
  63. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/repositories/__init__.py +0 -0
  64. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/repositories/document.py +0 -0
  65. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/repositories/processing_case.py +0 -0
  66. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/repositories/processing_case_item.py +0 -0
  67. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/domain/repositories/processing_record.py +0 -0
  68. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/__init__.py +0 -0
  69. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/batch_queue.py +0 -0
  70. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/documente_client.py +0 -0
  71. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/dynamo_table.py +0 -0
  72. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/lambdas.py +0 -0
  73. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/__init__.py +0 -0
  74. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/dynamo_document.py +0 -0
  75. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/dynamo_processing_case.py +0 -0
  76. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/dynamo_processing_case_item.py +0 -0
  77. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/http_document.py +0 -0
  78. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/http_processing_case.py +0 -0
  79. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/http_processing_case_item.py +0 -0
  80. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/http_processing_record.py +0 -0
  81. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/mem_document.py +0 -0
  82. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/mem_processing_case.py +0 -0
  83. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/mem_processing_case_item.py +0 -0
  84. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/repositories/mem_processing_record.py +0 -0
  85. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/s3_bucket.py +0 -0
  86. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/services/__init__.py +0 -0
  87. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/services/http_scaling.py +0 -0
  88. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/infrastructure/sqs_queue.py +0 -0
  89. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/presentation/__init__.py +0 -0
  90. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/documente_shared/presentation/presenters.py +0 -0
  91. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/publish.sh +0 -0
  92. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/__init__.py +0 -0
  93. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/__init__.py +0 -0
  94. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/application/__init__.py +0 -0
  95. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/application/test_files.py +0 -0
  96. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/application/test_payloads.py +0 -0
  97. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/conftest.py +0 -0
  98. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/domain/__init__.py +0 -0
  99. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/domain/entities/__init__.py +0 -0
  100. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/domain/entities/test_in_memory_document.py +0 -0
  101. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/domain/entities/test_processing_case.py +0 -0
  102. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/domain/entities/test_processing_case_item.py +0 -0
  103. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/domain/entities/test_processing_record.py +0 -0
  104. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/domain/enums/test_processing_case_validator.py +0 -0
  105. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/infrastructure/__init__.py +0 -0
  106. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/infrastructure/repositories/__init__.py +0 -0
  107. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documente_shared/infrastructure/repositories/test_http_processing_record.py +0 -0
  108. {documente_shared-0.1.160 → documente_shared-0.1.161b1}/tests/documents.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: documente_shared
3
- Version: 0.1.160
3
+ Version: 0.1.161b1
4
4
  Summary: Shared utilities for Documente AI projects
5
5
  Author-email: Tech <tech@llamitai.com>
6
6
  License: MIT
@@ -0,0 +1,63 @@
1
+ from dataclasses import dataclass
2
+ from datetime import datetime
3
+ from typing import Optional
4
+ from uuid import UUID
5
+
6
+ from documente_shared.application.time_utils import get_datetime_from_data
7
+
8
+
9
+ @dataclass
10
+ class Workspace(object):
11
+ uuid: UUID
12
+ name: str
13
+ tenant_id: UUID
14
+ is_archived: bool = False
15
+ metadata: Optional[dict] = None
16
+ created_at: Optional[datetime] = None
17
+ updated_at: Optional[datetime] = None
18
+ document_types: Optional[list] = None
19
+
20
+ def __post_init__(self):
21
+ self.metadata = self.metadata or {}
22
+ self.document_types = self.document_types or []
23
+
24
+ @property
25
+ def to_persist_dict(self) -> dict:
26
+ return {
27
+ "tenant_id": str(self.tenant_id),
28
+ "name": self.name,
29
+ "is_archived": self.is_archived,
30
+ "metadata": self.metadata or {},
31
+ }
32
+
33
+ @property
34
+ def to_dict(self) -> dict:
35
+ return {
36
+ "uuid": str(self.uuid),
37
+ "name": self.name,
38
+ "tenant_id": str(self.tenant_id),
39
+ "is_archived": self.is_archived,
40
+ "metadata": self.metadata,
41
+ "created_at": (
42
+ self.created_at.isoformat()
43
+ if self.created_at else None
44
+ ),
45
+ "updated_at": (
46
+ self.updated_at.isoformat()
47
+ if self.updated_at else None
48
+ ),
49
+ "document_types": self.document_types,
50
+ }
51
+
52
+ @classmethod
53
+ def from_dict(cls, data: dict) -> 'Workspace':
54
+ return cls(
55
+ uuid=data.get('uuid'),
56
+ name=data.get('name'),
57
+ tenant_id=data.get('tenant_id'),
58
+ is_archived=data.get('is_archived', False),
59
+ metadata=data.get('metadata', {}),
60
+ created_at=get_datetime_from_data(input_datetime=data.get('created_at')),
61
+ updated_at=get_datetime_from_data(input_datetime=data.get('updated_at')),
62
+ document_types=data.get('document_types', []),
63
+ )
@@ -0,0 +1,138 @@
1
+ from dataclasses import dataclass
2
+ from datetime import datetime
3
+ from decimal import Decimal
4
+ from typing import Optional
5
+ from uuid import UUID
6
+
7
+ from documente_shared.application.time_utils import get_datetime_from_data
8
+ from documente_shared.domain.entities.in_memory_document import InMemoryDocument
9
+ from documente_shared.domain.enums.common import ProcessingStatus
10
+ from documente_shared.domain.enums.workspace import WorkspaceSource
11
+ from documente_shared.domain.helpers.values import optional_str
12
+
13
+
14
+ @dataclass
15
+ class WorkspaceDocument(object):
16
+ uuid: UUID
17
+ name: str
18
+ status: ProcessingStatus
19
+ tenant_id: UUID
20
+ workspace_id: UUID
21
+ digest: Optional[str] = None
22
+ document_type_id: Optional[UUID] = None
23
+ source: Optional[WorkspaceSource] = None
24
+ document: Optional[InMemoryDocument] = None
25
+ document_url: Optional[str] = None
26
+ processing_time: Optional[Decimal] = None
27
+ metadata: Optional[dict] = None
28
+ extraction: Optional[dict] = None
29
+ uploaded_at: Optional[datetime] = None
30
+ created_at: Optional[datetime] = None
31
+ updated_at: Optional[datetime] = None
32
+ started_at: Optional[datetime] = None
33
+ completed_at: Optional[datetime] = None
34
+ failed_at: Optional[datetime] = None
35
+
36
+ def __post_init__(self):
37
+ self.metadata = self.metadata or {}
38
+ self.extraction = self.extraction or {}
39
+
40
+ @property
41
+ def to_persist_dict(self) -> dict:
42
+ return {
43
+ "tenant_id": str(self.tenant_id),
44
+ "workspace_id": str(self.workspace_id),
45
+ "doctype_id": str(self.document_type_id) if self.document_type_id else None,
46
+ "name": self.name,
47
+ "digest": self.digest,
48
+ "status": str(self.status),
49
+ "source": optional_str(self.source),
50
+ "uploaded_at": self.uploaded_at,
51
+ "started_at": self.started_at,
52
+ "completed_at": self.completed_at,
53
+ "failed_at": self.failed_at,
54
+ "processing_time": self.processing_time,
55
+ "metadata": self.metadata or {},
56
+ "extraction": self.extraction or {},
57
+ }
58
+
59
+ @property
60
+ def to_dict(self) -> dict:
61
+ return {
62
+ "uuid": str(self.uuid),
63
+ "name": self.name,
64
+ "digest": self.digest,
65
+ "status": str(self.status),
66
+ "tenant_id": str(self.tenant_id),
67
+ "workspace_id": str(self.workspace_id),
68
+ "document_type_id": str(self.document_type_id) if self.document_type_id else None,
69
+ "source": optional_str(self.source),
70
+ "document": (
71
+ self.document.to_dict
72
+ if self.document else None
73
+ ),
74
+ "document_url": self.document_url,
75
+ "processing_time": (
76
+ str(self.processing_time)
77
+ if self.processing_time else None
78
+ ),
79
+ "metadata": self.metadata,
80
+ "extraction": self.extraction,
81
+ "uploaded_at": (
82
+ self.uploaded_at.isoformat()
83
+ if self.uploaded_at else None
84
+ ),
85
+ "created_at": (
86
+ self.created_at.isoformat()
87
+ if self.created_at else None
88
+ ),
89
+ "updated_at": (
90
+ self.updated_at.isoformat()
91
+ if self.updated_at else None
92
+ ),
93
+ "started_at": (
94
+ self.started_at.isoformat()
95
+ if self.started_at else None
96
+ ),
97
+ "completed_at": (
98
+ self.completed_at.isoformat()
99
+ if self.completed_at else None
100
+ ),
101
+ "failed_at": (
102
+ self.failed_at.isoformat()
103
+ if self.failed_at else None
104
+ ),
105
+ }
106
+
107
+ @classmethod
108
+ def from_dict(cls, data: dict) -> 'WorkspaceDocument':
109
+ return cls(
110
+ uuid=data.get('uuid'),
111
+ name=data.get('name'),
112
+ digest=data.get('digest'),
113
+ status=ProcessingStatus.from_value(data.get('status')),
114
+ tenant_id=data.get('tenant_id'),
115
+ workspace_id=data.get('workspace_id'),
116
+ document_type_id=data.get('document_type_id'),
117
+ source=(
118
+ WorkspaceSource.from_value(data.get('source'))
119
+ if data.get('source') else None
120
+ ),
121
+ document=(
122
+ InMemoryDocument.from_dict(data.get('document'))
123
+ if data.get('document') else None
124
+ ),
125
+ document_url=data.get('document_url'),
126
+ processing_time=(
127
+ Decimal(data.get('processing_time'))
128
+ if data.get('processing_time') else None
129
+ ),
130
+ metadata=data.get('metadata', {}),
131
+ extraction=data.get('extraction', {}),
132
+ uploaded_at=get_datetime_from_data(input_datetime=data.get('uploaded_at')),
133
+ created_at=get_datetime_from_data(input_datetime=data.get('created_at')),
134
+ updated_at=get_datetime_from_data(input_datetime=data.get('updated_at')),
135
+ started_at=get_datetime_from_data(input_datetime=data.get('started_at')),
136
+ completed_at=get_datetime_from_data(input_datetime=data.get('completed_at')),
137
+ failed_at=get_datetime_from_data(input_datetime=data.get('failed_at')),
138
+ )
@@ -0,0 +1,70 @@
1
+ from dataclasses import dataclass
2
+ from datetime import datetime
3
+ from typing import Optional
4
+ from uuid import UUID
5
+
6
+ from documente_shared.application.time_utils import get_datetime_from_data
7
+ from documente_shared.domain.entities.in_memory_document import InMemoryDocument
8
+
9
+
10
+ @dataclass
11
+ class WorkspaceDocumentPage(object):
12
+ uuid: UUID
13
+ tenant_id: UUID
14
+ workspace_id: UUID
15
+ workspace_document_id: UUID
16
+ page_number: int
17
+ page_file: Optional[InMemoryDocument] = None
18
+ page_file_url: Optional[str] = None
19
+ created_at: Optional[datetime] = None
20
+ synced_at: Optional[datetime] = None
21
+
22
+ @property
23
+ def to_persist_dict(self) -> dict:
24
+ return {
25
+ "tenant_id": str(self.tenant_id),
26
+ "workspace_id": str(self.workspace_id),
27
+ "workspace_document_id": str(self.workspace_document_id),
28
+ "page_number": self.page_number,
29
+ "synced_at": self.synced_at,
30
+ }
31
+
32
+ @property
33
+ def to_dict(self) -> dict:
34
+ return {
35
+ "uuid": str(self.uuid),
36
+ "tenant_id": str(self.tenant_id),
37
+ "workspace_id": str(self.workspace_id),
38
+ "workspace_document_id": str(self.workspace_document_id),
39
+ "page_number": self.page_number,
40
+ "page_file": (
41
+ self.page_file.to_dict
42
+ if self.page_file else None
43
+ ),
44
+ "page_file_url": self.page_file_url,
45
+ "created_at": (
46
+ self.created_at.isoformat()
47
+ if self.created_at else None
48
+ ),
49
+ "synced_at": (
50
+ self.synced_at.isoformat()
51
+ if self.synced_at else None
52
+ ),
53
+ }
54
+
55
+ @classmethod
56
+ def from_dict(cls, data: dict) -> 'WorkspaceDocumentPage':
57
+ return cls(
58
+ uuid=data.get('uuid'),
59
+ tenant_id=data.get('tenant_id'),
60
+ workspace_id=data.get('workspace_id'),
61
+ workspace_document_id=data.get('workspace_document_id'),
62
+ page_number=data.get('page_number'),
63
+ page_file=(
64
+ InMemoryDocument.from_dict(data.get('page_file'))
65
+ if data.get('page_file') else None
66
+ ),
67
+ page_file_url=data.get('page_file_url'),
68
+ created_at=get_datetime_from_data(input_datetime=data.get('created_at')),
69
+ synced_at=get_datetime_from_data(input_datetime=data.get('synced_at')),
70
+ )
@@ -0,0 +1,19 @@
1
+ from documente_shared.domain.base_enum import BaseEnum
2
+
3
+
4
+ class WorkspaceSource(BaseEnum):
5
+ WEB = "WEB"
6
+ MOBILE = "MOBILE"
7
+ TOOLS = "TOOLS"
8
+
9
+ @property
10
+ def is_web(self):
11
+ return self == self.WEB
12
+
13
+ @property
14
+ def is_mobile(self):
15
+ return self == self.MOBILE
16
+
17
+ @property
18
+ def is_tools(self):
19
+ return self == self.TOOLS
@@ -0,0 +1,31 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Optional
3
+ from uuid import UUID
4
+
5
+ from documente_shared.domain.entities.workspace import Workspace
6
+
7
+
8
+ class WorkspaceRepository(ABC):
9
+ @abstractmethod
10
+ def find(self, uuid: UUID) -> Optional[Workspace]:
11
+ raise NotImplementedError
12
+
13
+ @abstractmethod
14
+ def find_by_tenant(self, tenant_id: UUID, include_archived: bool = False) -> list[Workspace]:
15
+ raise NotImplementedError
16
+
17
+ @abstractmethod
18
+ def filter(self, tenant_id: UUID) -> list[Workspace]:
19
+ raise NotImplementedError
20
+
21
+ @abstractmethod
22
+ def filter_paginated(self, tenant_id: UUID, page_params: Any) -> Any:
23
+ raise NotImplementedError
24
+
25
+ @abstractmethod
26
+ def persist(self, instance: Workspace) -> Workspace:
27
+ raise NotImplementedError
28
+
29
+ @abstractmethod
30
+ def delete(self, uuid: UUID) -> None:
31
+ raise NotImplementedError
@@ -0,0 +1,42 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Optional
3
+ from uuid import UUID
4
+
5
+ from documente_shared.domain.entities.workspace_document import WorkspaceDocument
6
+ from documente_shared.domain.enums.common import ProcessingStatus
7
+
8
+
9
+ class WorkspaceDocumentRepository(ABC):
10
+ @abstractmethod
11
+ def find(self, uuid: UUID) -> Optional[WorkspaceDocument]:
12
+ raise NotImplementedError
13
+
14
+ @abstractmethod
15
+ def find_by_digest(self, workspace_id: UUID, digest: str) -> Optional[WorkspaceDocument]:
16
+ raise NotImplementedError
17
+
18
+ @abstractmethod
19
+ def filter_by_workspace(
20
+ self,
21
+ workspace_id: UUID,
22
+ status: Optional[ProcessingStatus] = None,
23
+ limit: Optional[int] = None,
24
+ offset: int = 0,
25
+ ) -> list[WorkspaceDocument]:
26
+ raise NotImplementedError
27
+
28
+ @abstractmethod
29
+ def filter(self, workspace_id: UUID) -> list[WorkspaceDocument]:
30
+ raise NotImplementedError
31
+
32
+ @abstractmethod
33
+ def filter_paginated(self, workspace_id: UUID, page_params: Any) -> Any:
34
+ raise NotImplementedError
35
+
36
+ @abstractmethod
37
+ def persist(self, instance: WorkspaceDocument) -> WorkspaceDocument:
38
+ raise NotImplementedError
39
+
40
+ @abstractmethod
41
+ def delete(self, uuid: UUID) -> None:
42
+ raise NotImplementedError
@@ -0,0 +1,41 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Optional
3
+ from uuid import UUID
4
+
5
+ from documente_shared.domain.entities.workspace_document_page import WorkspaceDocumentPage
6
+
7
+
8
+ class WorkspaceDocumentPageRepository(ABC):
9
+ @abstractmethod
10
+ def find(self, uuid: UUID) -> Optional[WorkspaceDocumentPage]:
11
+ raise NotImplementedError
12
+
13
+ @abstractmethod
14
+ def find_by_document(self, workspace_document_id: UUID) -> list[WorkspaceDocumentPage]:
15
+ raise NotImplementedError
16
+
17
+ @abstractmethod
18
+ def find_by_document_and_page_number(
19
+ self, workspace_document_id: UUID, page_number: int
20
+ ) -> Optional[WorkspaceDocumentPage]:
21
+ raise NotImplementedError
22
+
23
+ @abstractmethod
24
+ def filter(self, workspace_document_id: UUID) -> list[WorkspaceDocumentPage]:
25
+ raise NotImplementedError
26
+
27
+ @abstractmethod
28
+ def filter_paginated(self, workspace_document_id: UUID, page_params: Any) -> Any:
29
+ raise NotImplementedError
30
+
31
+ @abstractmethod
32
+ def persist(self, instance: WorkspaceDocumentPage) -> WorkspaceDocumentPage:
33
+ raise NotImplementedError
34
+
35
+ @abstractmethod
36
+ def delete(self, uuid: UUID) -> None:
37
+ raise NotImplementedError
38
+
39
+ @abstractmethod
40
+ def delete_by_document(self, workspace_document_id: UUID) -> None:
41
+ raise NotImplementedError
@@ -0,0 +1,89 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, List, Optional
3
+ from uuid import UUID
4
+
5
+ from loguru import logger
6
+ from requests import Response
7
+
8
+ from documente_shared.application.payloads import camel_to_snake
9
+ from documente_shared.domain.entities.workspace import Workspace
10
+ from documente_shared.domain.repositories.workspace import WorkspaceRepository
11
+ from documente_shared.infrastructure.documente_client import DocumenteClientMixin
12
+
13
+
14
+ @dataclass
15
+ class HttpWorkspaceRepository(
16
+ DocumenteClientMixin,
17
+ WorkspaceRepository,
18
+ ):
19
+ def find(self, uuid: UUID) -> Optional[Workspace]:
20
+ response = self.session.get(
21
+ url=f"{self.api_url}/v1/workspaces/{uuid}/",
22
+ )
23
+ if response.status_code not in [200, 201]:
24
+ return None
25
+ return self._build_workspace(response)
26
+
27
+ def find_by_tenant(
28
+ self,
29
+ tenant_id: UUID,
30
+ include_archived: bool = False,
31
+ ) -> List[Workspace]:
32
+ params = {}
33
+ if include_archived:
34
+ params["include_archived"] = "true"
35
+ response = self.session.get(
36
+ url=f"{self.api_url}/v1/workspaces/",
37
+ params=params,
38
+ )
39
+ if response.status_code not in [200, 201]:
40
+ return []
41
+ raw_response = response.json()
42
+ return [
43
+ Workspace.from_dict(camel_to_snake(item_data))
44
+ for item_data in raw_response.get('data', [])
45
+ ]
46
+
47
+ def filter(self, tenant_id: UUID) -> List[Workspace]:
48
+ response = self.session.get(
49
+ url=f"{self.api_url}/v1/workspaces/",
50
+ )
51
+ if response.status_code not in [200, 201]:
52
+ return []
53
+ raw_response = response.json()
54
+ return [
55
+ Workspace.from_dict(camel_to_snake(item_data))
56
+ for item_data in raw_response.get('data', [])
57
+ ]
58
+
59
+ def filter_paginated(self, tenant_id: UUID, page_params: Any) -> Any:
60
+ params = {}
61
+ if isinstance(page_params, dict):
62
+ params.update(page_params)
63
+ response = self.session.get(
64
+ url=f"{self.api_url}/v1/workspaces/",
65
+ params=params,
66
+ )
67
+ if response.status_code not in [200, 201]:
68
+ return {"data": [], "count": 0}
69
+ return response.json()
70
+
71
+ def persist(self, instance: Workspace) -> Workspace:
72
+ logger.info(f"PERSISTING_WORKSPACE: data={instance.to_persist_dict}")
73
+ response: Response = self.session.post(
74
+ url=f"{self.api_url}/v1/workspaces/",
75
+ json=instance.to_persist_dict,
76
+ )
77
+ if response.status_code not in [200, 201]:
78
+ logger.info(f"PERSISTING_WORKSPACE ERROR: data={response.text}")
79
+ return instance
80
+ return self._build_workspace(response)
81
+
82
+ def delete(self, uuid: UUID) -> None:
83
+ self.session.delete(f"{self.api_url}/v1/workspaces/{uuid}/")
84
+
85
+ @classmethod
86
+ def _build_workspace(cls, response: Response) -> Workspace:
87
+ response_json = response.json()
88
+ instance_data = response_json.get('data', {})
89
+ return Workspace.from_dict(camel_to_snake(instance_data))
@@ -0,0 +1,113 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, List, Optional
3
+ from uuid import UUID
4
+
5
+ from loguru import logger
6
+ from requests import Response
7
+
8
+ from documente_shared.application.payloads import camel_to_snake
9
+ from documente_shared.domain.entities.workspace_document import WorkspaceDocument
10
+ from documente_shared.domain.repositories.workspace_document import WorkspaceDocumentRepository
11
+ from documente_shared.infrastructure.documente_client import DocumenteClientMixin
12
+
13
+
14
+ @dataclass
15
+ class HttpWorkspaceDocumentRepository(
16
+ DocumenteClientMixin,
17
+ WorkspaceDocumentRepository,
18
+ ):
19
+ def find(self, uuid: UUID) -> Optional[WorkspaceDocument]:
20
+ response = self.session.get(
21
+ url=f"{self.api_url}/v1/workspace-documents/{uuid}/",
22
+ )
23
+ if response.status_code not in [200, 201]:
24
+ return None
25
+ return self._build_workspace_document(response)
26
+
27
+ def find_by_digest(
28
+ self,
29
+ workspace_id: UUID,
30
+ digest: str,
31
+ ) -> Optional[WorkspaceDocument]:
32
+ params = {"digest": digest}
33
+ response = self.session.get(
34
+ url=f"{self.api_url}/v1/workspaces/{workspace_id}/documents/",
35
+ params=params,
36
+ )
37
+ if response.status_code not in [200, 201]:
38
+ return None
39
+ raw_response = response.json()
40
+ results = raw_response.get('data', [])
41
+ if not results:
42
+ return None
43
+ return WorkspaceDocument.from_dict(camel_to_snake(results[0]))
44
+
45
+ def filter_by_workspace(
46
+ self,
47
+ workspace_id: UUID,
48
+ status: Optional[ProcessingStatus] = None,
49
+ limit: Optional[int] = None,
50
+ offset: int = 0,
51
+ ) -> List[WorkspaceDocument]:
52
+ params = {}
53
+ if status:
54
+ params["status"] = str(status)
55
+ if limit is not None:
56
+ params["limit"] = limit
57
+ if offset:
58
+ params["offset"] = offset
59
+ response = self.session.get(
60
+ url=f"{self.api_url}/v1/workspaces/{workspace_id}/documents/",
61
+ params=params,
62
+ )
63
+ if response.status_code not in [200, 201]:
64
+ return []
65
+ raw_response = response.json()
66
+ return [
67
+ WorkspaceDocument.from_dict(camel_to_snake(item_data))
68
+ for item_data in raw_response.get('data', [])
69
+ ]
70
+
71
+ def filter(self, workspace_id: UUID) -> List[WorkspaceDocument]:
72
+ response = self.session.get(
73
+ url=f"{self.api_url}/v1/workspaces/{workspace_id}/documents/",
74
+ )
75
+ if response.status_code not in [200, 201]:
76
+ return []
77
+ raw_response = response.json()
78
+ return [
79
+ WorkspaceDocument.from_dict(camel_to_snake(item_data))
80
+ for item_data in raw_response.get('data', [])
81
+ ]
82
+
83
+ def filter_paginated(self, workspace_id: UUID, page_params: Any) -> Any:
84
+ params = {}
85
+ if isinstance(page_params, dict):
86
+ params.update(page_params)
87
+ response = self.session.get(
88
+ url=f"{self.api_url}/v1/workspaces/{workspace_id}/documents/",
89
+ params=params,
90
+ )
91
+ if response.status_code not in [200, 201]:
92
+ return {"data": [], "count": 0}
93
+ return response.json()
94
+
95
+ def persist(self, instance: WorkspaceDocument) -> WorkspaceDocument:
96
+ logger.info(f"PERSISTING_WORKSPACE_DOCUMENT: data={instance.to_persist_dict}")
97
+ response: Response = self.session.post(
98
+ url=f"{self.api_url}/v1/workspaces/{instance.workspace_id}/documents/",
99
+ json=instance.to_persist_dict,
100
+ )
101
+ if response.status_code not in [200, 201]:
102
+ logger.info(f"PERSISTING_WORKSPACE_DOCUMENT ERROR: data={response.text}")
103
+ return instance
104
+ return self._build_workspace_document(response)
105
+
106
+ def delete(self, uuid: UUID) -> None:
107
+ self.session.delete(f"{self.api_url}/v1/workspace-documents/{uuid}/")
108
+
109
+ @classmethod
110
+ def _build_workspace_document(cls, response: Response) -> WorkspaceDocument:
111
+ response_json = response.json()
112
+ instance_data = response_json.get('data', {})
113
+ return WorkspaceDocument.from_dict(camel_to_snake(instance_data))
@@ -0,0 +1,107 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, List, Optional
3
+ from uuid import UUID
4
+
5
+ from loguru import logger
6
+ from requests import Response
7
+
8
+ from documente_shared.application.payloads import camel_to_snake
9
+ from documente_shared.domain.entities.workspace_document_page import WorkspaceDocumentPage
10
+ from documente_shared.domain.repositories.workspace_document_page import WorkspaceDocumentPageRepository
11
+ from documente_shared.infrastructure.documente_client import DocumenteClientMixin
12
+
13
+
14
+ @dataclass
15
+ class HttpWorkspaceDocumentPageRepository(
16
+ DocumenteClientMixin,
17
+ WorkspaceDocumentPageRepository,
18
+ ):
19
+ def find(self, uuid: UUID) -> Optional[WorkspaceDocumentPage]:
20
+ response = self.session.get(
21
+ url=f"{self.api_url}/v1/workspace-document-pages/{uuid}/",
22
+ )
23
+ if response.status_code not in [200, 201]:
24
+ return None
25
+ return self._build_workspace_document_page(response)
26
+
27
+ def find_by_document(
28
+ self,
29
+ workspace_document_id: UUID,
30
+ ) -> List[WorkspaceDocumentPage]:
31
+ response = self.session.get(
32
+ url=f"{self.api_url}/v1/workspace-documents/{workspace_document_id}/pages/",
33
+ )
34
+ if response.status_code not in [200, 201]:
35
+ return []
36
+ raw_response = response.json()
37
+ return [
38
+ WorkspaceDocumentPage.from_dict(camel_to_snake(item_data))
39
+ for item_data in raw_response.get('data', [])
40
+ ]
41
+
42
+ def find_by_document_and_page_number(
43
+ self,
44
+ workspace_document_id: UUID,
45
+ page_number: int,
46
+ ) -> Optional[WorkspaceDocumentPage]:
47
+ params = {"page_number": page_number}
48
+ response = self.session.get(
49
+ url=f"{self.api_url}/v1/workspace-documents/{workspace_document_id}/pages/",
50
+ params=params,
51
+ )
52
+ if response.status_code not in [200, 201]:
53
+ return None
54
+ raw_response = response.json()
55
+ results = raw_response.get('data', [])
56
+ if not results:
57
+ return None
58
+ return WorkspaceDocumentPage.from_dict(camel_to_snake(results[0]))
59
+
60
+ def filter(self, workspace_document_id: UUID) -> List[WorkspaceDocumentPage]:
61
+ response = self.session.get(
62
+ url=f"{self.api_url}/v1/workspace-documents/{workspace_document_id}/pages/",
63
+ )
64
+ if response.status_code not in [200, 201]:
65
+ return []
66
+ raw_response = response.json()
67
+ return [
68
+ WorkspaceDocumentPage.from_dict(camel_to_snake(item_data))
69
+ for item_data in raw_response.get('data', [])
70
+ ]
71
+
72
+ def filter_paginated(self, workspace_document_id: UUID, page_params: Any) -> Any:
73
+ params = {}
74
+ if isinstance(page_params, dict):
75
+ params.update(page_params)
76
+ response = self.session.get(
77
+ url=f"{self.api_url}/v1/workspace-documents/{workspace_document_id}/pages/",
78
+ params=params,
79
+ )
80
+ if response.status_code not in [200, 201]:
81
+ return {"data": [], "count": 0}
82
+ return response.json()
83
+
84
+ def persist(self, instance: WorkspaceDocumentPage) -> WorkspaceDocumentPage:
85
+ logger.info(f"PERSISTING_WORKSPACE_DOCUMENT_PAGE: data={instance.to_persist_dict}")
86
+ response: Response = self.session.post(
87
+ url=f"{self.api_url}/v1/workspace-documents/{instance.workspace_document_id}/pages/",
88
+ json=instance.to_persist_dict,
89
+ )
90
+ if response.status_code not in [200, 201]:
91
+ logger.info(f"PERSISTING_WORKSPACE_DOCUMENT_PAGE ERROR: data={response.text}")
92
+ return instance
93
+ return self._build_workspace_document_page(response)
94
+
95
+ def delete(self, uuid: UUID) -> None:
96
+ self.session.delete(f"{self.api_url}/v1/workspace-document-pages/{uuid}/")
97
+
98
+ def delete_by_document(self, workspace_document_id: UUID) -> None:
99
+ pages = self.find_by_document(workspace_document_id)
100
+ for page in pages:
101
+ self.delete(page.uuid)
102
+
103
+ @classmethod
104
+ def _build_workspace_document_page(cls, response: Response) -> WorkspaceDocumentPage:
105
+ response_json = response.json()
106
+ instance_data = response_json.get('data', {})
107
+ return WorkspaceDocumentPage.from_dict(camel_to_snake(instance_data))
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "documente_shared"
3
- version = "0.1.160"
3
+ version = "0.1.161b1"
4
4
  description = "Shared utilities for Documente AI projects"
5
5
  authors = [{ name = "Tech", email = "tech@llamitai.com" }]
6
6
  license = { text = "MIT" }
@@ -129,7 +129,7 @@ wheels = [
129
129
 
130
130
  [[package]]
131
131
  name = "documente-shared"
132
- version = "0.1.160"
132
+ version = "0.1.161b1"
133
133
  source = { editable = "." }
134
134
  dependencies = [
135
135
  { name = "boto3" },