documente_shared 0.1.70__py3-none-any.whl → 0.1.72__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.

Potentially problematic release.


This version of documente_shared might be problematic. Click here for more details.

@@ -4,19 +4,18 @@ from datetime import datetime, tzinfo
4
4
  from decimal import Decimal
5
5
  from typing import Optional, List
6
6
 
7
- from documente_shared.application.files import remove_slash_from_path, split_file_params, get_filename_from_path
7
+ from documente_shared.application.files import remove_slash_from_path, get_filename_from_path
8
8
  from documente_shared.application.time_utils import get_datetime_from_data
9
9
  from documente_shared.domain.constants import la_paz_tz
10
10
  from documente_shared.domain.entities.document_metadata import DocumentProcessingMetadata
11
- from documente_shared.domain.enums import (
11
+ from documente_shared.domain.enums.document import (
12
12
  DocumentProcessingStatus,
13
+ DocumentProcessingCategory,
13
14
  DocumentProcessingSubCategory,
14
- DocumentProcessingCategory, DocumentProcessingSource,
15
+ DocumentProcessingSource,
15
16
  )
16
17
 
17
18
 
18
-
19
-
20
19
  @dataclass
21
20
  class DocumentProcessing(object):
22
21
  digest: str
@@ -11,7 +11,8 @@ from documente_shared.domain.enums.processing_case import ProcessingCaseCategory
11
11
 
12
12
  @dataclass
13
13
  class ProcessingCase(object):
14
- id: str
14
+ uuid: str
15
+ label: str
15
16
  status: ProcessingStatus
16
17
  category: Optional[ProcessingCaseCategory] = None
17
18
  enqueued_at: Optional[datetime] = None
@@ -61,21 +62,23 @@ class ProcessingCase(object):
61
62
  return False
62
63
 
63
64
  return (
64
- self.id == other.id
65
- and self.status == other.status
66
- and self.category == other.category
67
- and self.enqueued_at == other.enqueued_at
68
- and self.started_at == other.started_at
69
- and self.failed_at == other.failed_at
70
- and self.feedback == other.feedback
71
- and self.completed_at == other.completed_at
72
- and self.metadata == other.metadata
65
+ self.uuid == other.uuid
66
+ and self.label == other.label
67
+ and self.status == other.status
68
+ and self.category == other.category
69
+ and self.enqueued_at == other.enqueued_at
70
+ and self.started_at == other.started_at
71
+ and self.failed_at == other.failed_at
72
+ and self.feedback == other.feedback
73
+ and self.completed_at == other.completed_at
74
+ and self.metadata == other.metadata
73
75
  )
74
76
 
75
77
  @property
76
78
  def to_dict(self) -> dict:
77
79
  return {
78
- 'id': self.id,
80
+ 'uuid': self.uuid,
81
+ 'label': self.label,
79
82
  'status': str(self.status),
80
83
  'category': (
81
84
  str(self.category)
@@ -100,6 +103,7 @@ class ProcessingCase(object):
100
103
  properties: List[str] = None,
101
104
  ):
102
105
  instance_properties = properties or [
106
+ 'label',
103
107
  'status',
104
108
  'category',
105
109
  'enqueued_at',
@@ -120,7 +124,8 @@ class ProcessingCase(object):
120
124
  @classmethod
121
125
  def from_dict(cls, data: dict) -> 'ProcessingCase':
122
126
  return cls(
123
- id=data.get('id'),
127
+ uuid=data.get('uuid'),
128
+ label=data.get('label'),
124
129
  status=ProcessingStatus.from_value(data.get('status')),
125
130
  category=(
126
131
  ProcessingCaseCategory.from_value(data.get('category'))
@@ -12,7 +12,7 @@ from documente_shared.domain.enums.processing_case import ProcessingDocumentType
12
12
 
13
13
  @dataclass
14
14
  class ProcessingCaseItem(object):
15
- id: str
15
+ uuid: str
16
16
  case_id: str
17
17
  digest: str
18
18
  status: ProcessingStatus
@@ -24,6 +24,7 @@ class ProcessingCaseItem(object):
24
24
  processed_json: Optional[InMemoryDocument] = None
25
25
  processing_time: Optional[Decimal] = None
26
26
  processing_confidence: Optional[Decimal] = None
27
+ uploaded_at: Optional[datetime] = None
27
28
  started_at: Optional[datetime] = None
28
29
  failed_at: Optional[datetime] = None
29
30
  completed_at: Optional[datetime] = None
@@ -85,12 +86,14 @@ class ProcessingCaseItem(object):
85
86
  return False
86
87
 
87
88
  return (
88
- self.digest == other.digest
89
+ self.uuid == other.uuid
90
+ and self.digest == other.digest
89
91
  and self.status == other.status
90
92
  and self.document_type == other.document_type
91
93
  and self.document == other.document
92
94
  and self.processing_time == other.processing_time
93
95
  and self.processing_confidence == other.processing_confidence
96
+ and self.uploaded_at == other.uploaded_at
94
97
  and self.started_at == other.started_at
95
98
  and self.failed_at == other.failed_at
96
99
  and self.completed_at == other.completed_at
@@ -99,12 +102,12 @@ class ProcessingCaseItem(object):
99
102
  @property
100
103
  def to_dict(self) -> dict:
101
104
  return {
102
- 'id': self.id,
105
+ 'uuid': self.uuid,
103
106
  'case_id': self.case_id,
104
107
  'digest': self.digest,
105
108
  'status': str(self.status),
106
109
  'document': self.document.to_dict,
107
- 'document_type': self.document_type,
110
+ 'document_type': str(self.document_type),
108
111
  'uploaded_from': (
109
112
  str(self.uploaded_from)
110
113
  if self.uploaded_from else None
@@ -129,6 +132,7 @@ class ProcessingCaseItem(object):
129
132
  str(self.processing_confidence.quantize(Decimal('0.001')))
130
133
  if self.processing_confidence else None
131
134
  ),
135
+ 'uploaded_at': self.uploaded_at.isoformat() if self.uploaded_at else None,
132
136
  'started_at': self.started_at.isoformat() if self.started_at else None,
133
137
  'failed_at': self.failed_at.isoformat() if self.failed_at else None,
134
138
  'feedback': self.feedback,
@@ -139,7 +143,6 @@ class ProcessingCaseItem(object):
139
143
  @property
140
144
  def to_simple_dict(self) -> dict:
141
145
  simple_dict = self.to_dict.copy()
142
- simple_dict.pop('metadata_items')
143
146
  return simple_dict
144
147
 
145
148
  def overload(
@@ -157,6 +160,7 @@ class ProcessingCaseItem(object):
157
160
  'processed_json',
158
161
  'processing_time',
159
162
  'processing_confidence',
163
+ 'uploaded_at',
160
164
  'started_at',
161
165
  'failed_at',
162
166
  'completed_at',
@@ -173,7 +177,7 @@ class ProcessingCaseItem(object):
173
177
  @classmethod
174
178
  def from_dict(cls, data: dict) -> 'ProcessingCaseItem':
175
179
  return cls(
176
- id=data.get('id'),
180
+ uuid=data.get('uuid'),
177
181
  case_id=data.get('case_id'),
178
182
  digest=data.get('digest'),
179
183
  status=ProcessingStatus.from_value(data.get('status')),
@@ -203,6 +207,7 @@ class ProcessingCaseItem(object):
203
207
  Decimal(data.get('processing_confidence'))
204
208
  if data.get('processing_confidence') else None
205
209
  ),
210
+ uploaded_at=get_datetime_from_data(input_datetime=data.get('uploaded_at')),
206
211
  started_at=get_datetime_from_data(input_datetime=data.get('started_at')),
207
212
  failed_at=get_datetime_from_data(input_datetime=data.get('failed_at')),
208
213
  feedback=data.get('feedback'),
File without changes
@@ -2,13 +2,13 @@ from abc import ABC, abstractmethod
2
2
  from typing import Optional, List
3
3
 
4
4
  from documente_shared.domain.entities.document import DocumentProcessing
5
- from documente_shared.domain.enums import DocumentProcessingStatus
5
+ from documente_shared.domain.enums.document import DocumentProcessingStatus
6
6
 
7
7
 
8
8
  class DocumentProcessingRepository(ABC):
9
9
 
10
10
  @abstractmethod
11
- def find(self, digest: str) ->Optional[DocumentProcessing]:
11
+ def find(self, digest: str) -> Optional[DocumentProcessing]:
12
12
  raise NotImplementedError
13
13
 
14
14
  @abstractmethod
@@ -19,7 +19,6 @@ class DocumentProcessingRepository(ABC):
19
19
  def remove(self, instance: DocumentProcessing):
20
20
  raise NotImplementedError
21
21
 
22
-
23
22
  @abstractmethod
24
23
  def filter(self, statuses: List[DocumentProcessingStatus]) -> List[DocumentProcessing]:
25
- raise NotImplementedError
24
+ raise NotImplementedError
@@ -0,0 +1,24 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Optional, List
3
+
4
+ from documente_shared.domain.entities.processing_case import ProcessingCase
5
+ from documente_shared.domain.enums.common import ProcessingStatus
6
+
7
+
8
+ class ProcessingCaseRepository(ABC):
9
+
10
+ @abstractmethod
11
+ def find(self, case_id: str) -> Optional[ProcessingCase]:
12
+ raise NotImplementedError
13
+
14
+ @abstractmethod
15
+ def persist(self, instance: ProcessingCase) -> ProcessingCase:
16
+ raise NotImplementedError
17
+
18
+ @abstractmethod
19
+ def remove(self, instance: ProcessingCase):
20
+ raise NotImplementedError
21
+
22
+ @abstractmethod
23
+ def filter(self, statuses: List[ProcessingStatus]) -> List[ProcessingCase]:
24
+ raise NotImplementedError
@@ -0,0 +1,29 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Optional, List
3
+
4
+ from documente_shared.domain.entities.processing_case import ProcessingCase
5
+ from documente_shared.domain.entities.processing_case_item import ProcessingCaseItem
6
+ from documente_shared.domain.enums.common import ProcessingStatus
7
+
8
+
9
+ class ProcessingCaseItemRepository(ABC):
10
+
11
+ @abstractmethod
12
+ def find(self, digest: str) -> Optional[ProcessingCaseItem]:
13
+ raise NotImplementedError
14
+
15
+ @abstractmethod
16
+ def persist(self, instance: ProcessingCaseItem) -> ProcessingCaseItem:
17
+ raise NotImplementedError
18
+
19
+ @abstractmethod
20
+ def remove(self, instance: ProcessingCaseItem):
21
+ raise NotImplementedError
22
+
23
+ @abstractmethod
24
+ def filter(self, statuses: List[ProcessingStatus]) -> List[ProcessingCase]:
25
+ raise NotImplementedError
26
+
27
+ @abstractmethod
28
+ def filter_by_case_id(self, case_id: str) -> List[ProcessingCase]:
29
+ raise NotImplementedError
@@ -1,11 +1,12 @@
1
- from dataclasses import dataclass
2
-
3
1
  import boto3
2
+
3
+ from dataclasses import dataclass
4
4
  from boto3.dynamodb.conditions import Key
5
5
 
6
6
 
7
7
  RETURN_VALUES = 'UPDATED_NEW'
8
8
 
9
+
9
10
  @dataclass
10
11
  class DynamoDBTable(object):
11
12
  table_name: str
@@ -50,7 +51,6 @@ class DynamoDBTable(object):
50
51
  def count(self) -> int:
51
52
  return self._table.item_count
52
53
 
53
-
54
54
  @classmethod
55
55
  def _update_expression(cls, attributes):
56
56
  return 'SET {param}'.format(
@@ -3,10 +3,10 @@ from typing import Optional, List
3
3
  from boto3.dynamodb.conditions import Key
4
4
 
5
5
  from documente_shared.domain.entities.document import DocumentProcessing
6
- from documente_shared.domain.enums import DocumentProcessingStatus, DocumentProcessingCategory
7
- from documente_shared.domain.repositories import DocumentProcessingRepository
8
- from documente_shared.infrastructure.dynamo_table import DynamoDBTable
6
+ from documente_shared.domain.enums.document import DocumentProcessingStatus
7
+ from documente_shared.domain.repositories.document import DocumentProcessingRepository
9
8
 
9
+ from documente_shared.infrastructure.dynamo_table import DynamoDBTable
10
10
 
11
11
 
12
12
  class DynamoDocumentProcessingRepository(
@@ -0,0 +1,43 @@
1
+ from typing import Optional, List
2
+
3
+ from boto3.dynamodb.conditions import Key
4
+
5
+ from documente_shared.domain.entities.processing_case import ProcessingCase
6
+ from documente_shared.domain.enums.common import ProcessingStatus
7
+ from documente_shared.domain.repositories.processing_case import ProcessingCaseRepository
8
+
9
+ from documente_shared.infrastructure.dynamo_table import DynamoDBTable
10
+
11
+
12
+ class DynamoProcessingCaseRepository(
13
+ DynamoDBTable,
14
+ ProcessingCaseRepository,
15
+ ):
16
+ def find(self, case_id: str) -> Optional[ProcessingCase]:
17
+ item = self.get(key={'case_id': case_id})
18
+ if item:
19
+ return ProcessingCase.from_dict(item)
20
+ return None
21
+
22
+ def persist(self, instance: ProcessingCase) -> ProcessingCase:
23
+ self.put(instance.to_persist_dict)
24
+ return instance
25
+
26
+ def remove(self, instance: ProcessingCase):
27
+ self.delete(key={'case_id': instance.case_id})
28
+
29
+ def filter(self, statuses: List[ProcessingStatus]) -> List[ProcessingCase]:
30
+ items = []
31
+
32
+ for status in statuses:
33
+ response = self._table.query(
34
+ IndexName='status',
35
+ KeyConditionExpression=Key('status').eq(status.value),
36
+ )
37
+ status_items = response.get('Items', [])
38
+ items.extend(status_items)
39
+
40
+ return [
41
+ ProcessingCase.from_dict(item)
42
+ for item in items
43
+ ]
@@ -0,0 +1,54 @@
1
+ from typing import Optional, List
2
+
3
+ from boto3.dynamodb.conditions import Key
4
+
5
+ from documente_shared.domain.entities.processing_case_item import ProcessingCaseItem
6
+ from documente_shared.domain.enums.common import ProcessingStatus
7
+ from documente_shared.domain.repositories.processing_case_item import ProcessingCaseItemRepository
8
+
9
+ from documente_shared.infrastructure.dynamo_table import DynamoDBTable
10
+
11
+
12
+ class DynamoProcessingCaseItemRepository(
13
+ DynamoDBTable,
14
+ ProcessingCaseItemRepository,
15
+ ):
16
+ def find(self, digest: str) -> Optional[ProcessingCaseItem]:
17
+ item = self.get(key={'digest': digest})
18
+ if item:
19
+ return ProcessingCaseItem.from_dict(item)
20
+ return None
21
+
22
+ def persist(self, instance: ProcessingCaseItem) -> ProcessingCaseItem:
23
+ self.put(instance.to_simple_dict)
24
+ return instance
25
+
26
+ def remove(self, instance: ProcessingCaseItem):
27
+ self.delete(key={'case_id': instance.case_id})
28
+
29
+ def filter(self, statuses: List[ProcessingStatus]) -> List[ProcessingCaseItem]:
30
+ items = []
31
+
32
+ for status in statuses:
33
+ response = self._table.query(
34
+ IndexName='status',
35
+ KeyConditionExpression=Key('status').eq(status.value),
36
+ )
37
+ status_items = response.get('Items', [])
38
+ items.extend(status_items)
39
+
40
+ return [
41
+ ProcessingCaseItem.from_dict(item)
42
+ for item in items
43
+ ]
44
+
45
+ def filter_by_case_id(self, case_id: str) -> List[ProcessingCaseItem]:
46
+ response = self._table.query(
47
+ IndexName='case_id',
48
+ KeyConditionExpression=Key('case_id').eq(case_id),
49
+ )
50
+ items = response.get('Items', [])
51
+ return [
52
+ ProcessingCaseItem.from_dict(item)
53
+ for item in items
54
+ ]
@@ -7,7 +7,7 @@ from dataclasses import dataclass
7
7
  @dataclass
8
8
  class SQSQueue(object):
9
9
  queue_url: str
10
- visibility_timeout: int = 60 * 10
10
+ visibility_timeout: int = 60 * 10
11
11
  waiting_timeout: int = 20
12
12
 
13
13
  def __post_init__(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: documente_shared
3
- Version: 0.1.70
3
+ Version: 0.1.72
4
4
  Summary: Shared utilities for Documente AI projects
5
5
  License: MIT
6
6
  Author: Tech
@@ -11,8 +11,9 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
- Requires-Dist: boto3 (>=1.34.80,<2.0.0)
15
- Requires-Dist: botocore (>=1.34.80,<2.0.0)
14
+ Requires-Dist: boto3 (>=1.37.19,<2.0.0)
15
+ Requires-Dist: botocore (>=1.37.19,<2.0.0)
16
+ Requires-Dist: pytz (>=2025.2,<2026.0)
16
17
  Requires-Dist: sentry-sdk (>=2.19.2,<3.0.0)
17
18
  Description-Content-Type: text/markdown
18
19
 
@@ -9,22 +9,28 @@ documente_shared/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
9
9
  documente_shared/domain/base_enum.py,sha256=DojAfn-zQdtjtImeHUpBzE6TBTm07XrbMOdW3h8RVd8,1449
10
10
  documente_shared/domain/constants.py,sha256=jOlMKFq12FgiYMJcQHku8IVwuOE5t-HEPuSV_zEeIFo,56
11
11
  documente_shared/domain/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- documente_shared/domain/entities/document.py,sha256=kaLuVJ-LVQMUdQhCReQ2Mkl7-Kmws6-TNxKnlXogYSk,12603
12
+ documente_shared/domain/entities/document.py,sha256=AthTUyA-QZE3WAT7lMoKVr_Z8mO_3qERuCnZge0DTLQ,12595
13
13
  documente_shared/domain/entities/document_metadata.py,sha256=ygyFIC5qwxlm8DUM5kvVFny9zJfPQS8vNLM2br5XsQ8,2353
14
14
  documente_shared/domain/entities/in_memory_result.py,sha256=Q1E9vnLL5Hz5xunOqWtQmJOMjoK5KN42LZr18GlBAZo,1246
15
- documente_shared/domain/entities/processing_case.py,sha256=PuwWQuXIIP5wlkWBCrkF-61TfgKSYwc9HZl1JR13xhk,4955
16
- documente_shared/domain/entities/processing_case_item.py,sha256=5wuZylIc_Lanh5PnY4ghEgbQhCtBDCExh4KRW6ZGK_4,7684
15
+ documente_shared/domain/entities/processing_case.py,sha256=rGbFs3XhKppGOfH3XMa2BiCyr7lnqRMjhDXM6oUwKXE,5157
16
+ documente_shared/domain/entities/processing_case_item.py,sha256=hglyPhZBSjlMKVdEVccyHXU3aQRdZ8hfZlXDJnkf7wA,7996
17
17
  documente_shared/domain/entities/processing_event.py,sha256=m1O0gcNaE_SszeIhxM3uYPHSpyOUmize6mfRw1_bYZo,1723
18
18
  documente_shared/domain/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  documente_shared/domain/enums/common.py,sha256=vXldMUPhhWo0PfTgYwDSjI8bur_lYcImZYiV7yAO7DQ,2262
20
20
  documente_shared/domain/enums/document.py,sha256=NltZA1YVgJ7dVfSQdJFIE0ZUGf9Y-nxNXsVQ6GiPLL4,1827
21
21
  documente_shared/domain/enums/processing_case.py,sha256=DLVk0VnVzrKs1CvXVGHV9p8mBUHLUrOSJJ1POE-Ek3o,1546
22
- documente_shared/domain/repositories.py,sha256=g3qLUy2kT8esmvU4VxxSVnDaXeySKKQ7mUvIvxOwh9A,757
22
+ documente_shared/domain/repositories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ documente_shared/domain/repositories/document.py,sha256=vJzr6c92gqBzyhaEdjrvnoneKRrWmJ0AsvocPnhxiLU,767
24
+ documente_shared/domain/repositories/processing_case.py,sha256=7WE5RdLr04ysGXAdkJYmbfcLpMyOMeuDJGounZKMZqs,729
25
+ documente_shared/domain/repositories/processing_case_item.py,sha256=yD-v_24UzHwNdq75KRJGwHemTVFpO9LMIPSup4GbyKs,959
23
26
  documente_shared/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- documente_shared/infrastructure/dynamo_repositories.py,sha256=SEad_HLppp2h_BKDSzb9oo1VlAVRZWelOPvJPlDwbzQ,1453
25
- documente_shared/infrastructure/dynamo_table.py,sha256=dK05KgFvIYCmOdMpq9-OV_OBrP6cCngiUikCJrxlwt4,2112
27
+ documente_shared/infrastructure/dynamo_table.py,sha256=TMQbcuty7wjDMbuhI8PbT0IGXelgELsNTtqTEQeZ824,2112
28
+ documente_shared/infrastructure/repositories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ documente_shared/infrastructure/repositories/dynamo_document.py,sha256=_Yp4gtA-n-hJ2w2wAM5BMCs2Mf46Q2Kq3eHqlxudkL4,1443
30
+ documente_shared/infrastructure/repositories/dynamo_processing_case.py,sha256=Wt0di0402mrnvYNqe5ywDtFFdXjnHHvLDG4k_MQfmTE,1401
31
+ documente_shared/infrastructure/repositories/dynamo_processing_case_item.py,sha256=gG7H7hyeKTPMywTUmnq0nClrpaOqVPy7bh1OLBzV4pE,1816
26
32
  documente_shared/infrastructure/s3_bucket.py,sha256=vT_yN42RFQXubtUn8ln-j13Os_-25UGClVtXg5Bkv6I,1932
27
- documente_shared/infrastructure/sqs_queue.py,sha256=PSiTAnjXvQ-W-9mzLpH2UjbQJTvYkMiaxNaMecF-cR4,1505
28
- documente_shared-0.1.70.dist-info/METADATA,sha256=JCm5S835mggDqZMKE320WqYbKgyH79nvdZMXIIaMnEU,800
29
- documente_shared-0.1.70.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
30
- documente_shared-0.1.70.dist-info/RECORD,,
33
+ documente_shared/infrastructure/sqs_queue.py,sha256=KZWeHZ9zmXmrxoNpOQX7GEdDhZ1knbPXgwSwFwJblGg,1504
34
+ documente_shared-0.1.72.dist-info/METADATA,sha256=k9oTLxK2WigrpoZx6Psxtqs_OOBWWM-6VuAXZ_kjUVc,839
35
+ documente_shared-0.1.72.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
36
+ documente_shared-0.1.72.dist-info/RECORD,,