documente_shared 0.1.80__tar.gz → 0.1.82__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.

Potentially problematic release.


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

Files changed (43) hide show
  1. {documente_shared-0.1.80 → documente_shared-0.1.82}/PKG-INFO +1 -1
  2. documente_shared-0.1.82/documente_shared/application/payloads.py +14 -0
  3. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/in_memory_result.py +15 -11
  4. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/processing_case.py +14 -24
  5. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/processing_case_item.py +8 -2
  6. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/repositories/http_processing_case.py +15 -5
  7. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/repositories/http_processing_case_item.py +20 -12
  8. {documente_shared-0.1.80 → documente_shared-0.1.82}/pyproject.toml +1 -1
  9. {documente_shared-0.1.80 → documente_shared-0.1.82}/README.md +0 -0
  10. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/__init__.py +0 -0
  11. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/application/__init__.py +0 -0
  12. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/application/digest.py +0 -0
  13. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/application/exceptions.py +0 -0
  14. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/application/files.py +0 -0
  15. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/application/query_params.py +0 -0
  16. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/application/time_utils.py +0 -0
  17. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/application/timezone.py +0 -0
  18. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/__init__.py +0 -0
  19. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/base_enum.py +0 -0
  20. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/constants.py +0 -0
  21. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/__init__.py +0 -0
  22. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/document.py +0 -0
  23. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/document_metadata.py +0 -0
  24. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/processing_case_filters.py +0 -0
  25. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/processing_case_item_filters.py +0 -0
  26. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/entities/processing_event.py +0 -0
  27. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/enums/__init__.py +0 -0
  28. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/enums/common.py +0 -0
  29. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/enums/document.py +0 -0
  30. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/enums/processing_case.py +0 -0
  31. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/repositories/__init__.py +0 -0
  32. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/repositories/document.py +0 -0
  33. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/repositories/processing_case.py +0 -0
  34. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/domain/repositories/processing_case_item.py +0 -0
  35. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/__init__.py +0 -0
  36. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/documente_client.py +0 -0
  37. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/dynamo_table.py +0 -0
  38. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/repositories/__init__.py +0 -0
  39. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/repositories/dynamo_document.py +0 -0
  40. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/repositories/dynamo_processing_case.py +0 -0
  41. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/repositories/dynamo_processing_case_item.py +0 -0
  42. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/s3_bucket.py +0 -0
  43. {documente_shared-0.1.80 → documente_shared-0.1.82}/documente_shared/infrastructure/sqs_queue.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: documente_shared
3
- Version: 0.1.80
3
+ Version: 0.1.82
4
4
  Summary: Shared utilities for Documente AI projects
5
5
  License: MIT
6
6
  Author: Tech
@@ -0,0 +1,14 @@
1
+ import re
2
+
3
+
4
+ def camel_to_snake_key(name: str) -> str:
5
+ s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
6
+ return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
7
+
8
+ def camel_to_snake(data: dict | list) -> dict | list:
9
+ if isinstance(data, dict):
10
+ return {camel_to_snake_key(k): camel_to_snake(v) for k, v in data.items()}
11
+ elif isinstance(data, list):
12
+ return [camel_to_snake(item) for item in data]
13
+ else:
14
+ return data
@@ -11,6 +11,7 @@ from documente_shared.application.files import (
11
11
  class InMemoryDocument(object):
12
12
  file_path: Optional[str] = None
13
13
  file_bytes: Optional[bytes] = None
14
+ file_base64: Optional[str] = None
14
15
 
15
16
  @property
16
17
  def is_valid(self) -> bool:
@@ -18,13 +19,7 @@ class InMemoryDocument(object):
18
19
 
19
20
  @property
20
21
  def has_content(self) -> bool:
21
- return bool(self.file_bytes)
22
-
23
- @property
24
- def file_key(self) -> Optional[str]:
25
- if not self.file_path:
26
- return None
27
- return remove_slash_from_path(self.file_path)
22
+ return bool(self.file_bytes) or bool(self.file_base64)
28
23
 
29
24
  @property
30
25
  def file_name(self) -> Optional[str]:
@@ -32,20 +27,29 @@ class InMemoryDocument(object):
32
27
  return None
33
28
  return get_filename_from_path(self.file_path)
34
29
 
30
+ @property
31
+ def file_key(self) -> Optional[str]:
32
+ return self.file_name
33
+
35
34
  @property
36
35
  def is_procesable(self) -> bool:
37
36
  return self.is_valid and self.has_content
38
37
 
39
38
  @property
40
39
  def to_dict(self) -> dict:
41
- return {
42
- 'file_path': self.file_path,
43
- 'file_bytes': self.file_bytes,
44
- }
40
+ data = dict()
41
+ if self.file_path:
42
+ data['file_path'] = remove_slash_from_path(self.file_path)
43
+ if self.file_bytes:
44
+ data['file_bytes'] = self.file_bytes.decode('utf-8')
45
+ if self.file_base64:
46
+ data['file_base64'] = self.file_base64
47
+ return data
45
48
 
46
49
  @classmethod
47
50
  def from_dict(cls, data: dict):
48
51
  return cls(
49
52
  file_path=data.get('file_path'),
50
53
  file_bytes=data.get('file_bytes'),
54
+ file_base64=data.get('file_base64'),
51
55
  )
@@ -96,37 +96,18 @@ class ProcessingCase(object):
96
96
 
97
97
  @property
98
98
  def to_persist_dict(self) -> dict:
99
- return self.to_dict
100
-
101
- def overload(
102
- self,
103
- new_instance: 'ProcessingCase',
104
- properties: List[str] = None,
105
- ):
106
- instance_properties = properties or [
107
- 'label',
108
- 'status',
109
- 'category',
110
- 'enqueued_at',
111
- 'started_at',
112
- 'failed_at',
113
- 'feedback',
114
- 'completed_at',
115
- 'metadata',
116
- 'items',
99
+ persist_data = self.to_dict
100
+ persist_data["items"] = [
101
+ item.to_dict for item in self.items
117
102
  ]
118
- for _property in instance_properties:
119
- property_value = getattr(new_instance, _property)
120
- if not hasattr(self, _property):
121
- continue
122
- setattr(self, _property, property_value)
123
- return self
103
+ return persist_data
124
104
 
125
105
  @classmethod
126
106
  def from_dict(cls, data: dict) -> 'ProcessingCase':
127
107
  return cls(
128
108
  uuid=data.get('uuid'),
129
109
  name=data.get('label'),
110
+ tenant_slug=data.get('tenant_slug'),
130
111
  status=ProcessingStatus.from_value(data.get('status')),
131
112
  case_type=(
132
113
  ProcessingCaseType.from_value(data.get('category'))
@@ -143,3 +124,12 @@ class ProcessingCase(object):
143
124
  for item_dict in data.get('items', [])
144
125
  ],
145
126
  )
127
+
128
+ @classmethod
129
+ def from_persist_dict(cls, data: dict) -> 'ProcessingCase':
130
+ instance = cls.from_dict(data)
131
+ instance.items = [
132
+ ProcessingCaseItem.from_persist_dict(item_dict)
133
+ for item_dict in data.get('items', [])
134
+ ]
135
+ return instance
@@ -106,7 +106,10 @@ class ProcessingCaseItem(object):
106
106
  'case_id': self.case_id,
107
107
  'digest': self.digest,
108
108
  'status': str(self.status),
109
- 'document': self.document.to_dict,
109
+ 'document':(
110
+ self.document.to_dict
111
+ if self.document else None
112
+ ),
110
113
  'document_type': (
111
114
  str(self.document_type)
112
115
  if self.document_type else None
@@ -205,7 +208,10 @@ class ProcessingCaseItem(object):
205
208
  case_id=data.get('case_id'),
206
209
  digest=data.get('digest'),
207
210
  status=ProcessingStatus.from_value(data.get('status')),
208
- document=InMemoryDocument.from_dict(data.get('document')),
211
+ document=(
212
+ InMemoryDocument.from_dict(data.get('document'))
213
+ if data.get('document') else None
214
+ ),
209
215
  document_type=(
210
216
  ProcessingDocumentType.from_value(data.get('document_type'))
211
217
  if data.get('document_type') else None
@@ -1,6 +1,9 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import List, Optional
3
3
 
4
+ from requests import Response
5
+
6
+ from documente_shared.application.payloads import camel_to_snake
4
7
  from documente_shared.domain.entities.processing_case import ProcessingCase
5
8
  from documente_shared.domain.entities.processing_case_filters import ProcessingCaseFilters
6
9
  from documente_shared.domain.repositories.processing_case import ProcessingCaseRepository
@@ -15,7 +18,7 @@ class HttpProcessingCaseRepository(
15
18
  def find(self, uuid: str, include_items: bool = False) -> Optional[ProcessingCase]:
16
19
  response = self.session.get(f"{self.api_url}/v1/processing-cases/{uuid}/")
17
20
  if response.status_code == 200:
18
- return ProcessingCase.from_dict(response.json())
21
+ return self._build_processing_case(response)
19
22
  return None
20
23
 
21
24
  def persist(self, instance: ProcessingCase) -> ProcessingCase:
@@ -25,7 +28,8 @@ class HttpProcessingCaseRepository(
25
28
  )
26
29
  if response.status_code not in [200, 201]:
27
30
  raise Exception(f'Error persisting processing case: {response.text}')
28
- return ProcessingCase.from_dict(response.json())
31
+
32
+ return self._build_processing_case(response)
29
33
 
30
34
  def remove(self, instance: ProcessingCase):
31
35
  self.session.delete(f"{self.api_url}/v1/processing-cases/{instance.uuid}/")
@@ -40,7 +44,13 @@ class HttpProcessingCaseRepository(
40
44
  if response.status_code == 200:
41
45
  raw_response = response.json()
42
46
  return [
43
- ProcessingCase.from_dict(item)
44
- for item in raw_response.get('data', [])
47
+ ProcessingCase.from_persist_dict(camel_to_snake(item_data))
48
+ for item_data in raw_response.get('data', [])
45
49
  ]
46
- return []
50
+ return []
51
+
52
+ @classmethod
53
+ def _build_processing_case(cls, response: Response) -> ProcessingCase:
54
+ response_json = response.json()
55
+ instance_data = response_json.get('data', {})
56
+ return ProcessingCase.from_persist_dict(camel_to_snake(instance_data))
@@ -1,6 +1,9 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import List, Optional
3
3
 
4
+ from requests import Response
5
+
6
+ from documente_shared.application.payloads import camel_to_snake
4
7
  from documente_shared.domain.entities.processing_case_item import ProcessingCaseItem
5
8
  from documente_shared.domain.entities.processing_case_item_filters import ProcessingCaseItemFilters
6
9
  from documente_shared.domain.repositories.processing_case_item import ProcessingCaseItemRepository
@@ -12,41 +15,46 @@ class HttpProcessingCaseItemRepository(
12
15
  DocumenteClientMixin,
13
16
  ProcessingCaseItemRepository,
14
17
  ):
15
-
16
18
  def find(self, uuid: str) -> Optional[ProcessingCaseItem]:
17
- response = self.session.get(f"{self.api_url}/processing-case-items/{uuid}/")
19
+ response = self.session.get(f"{self.api_url}/v1/processing-case-items/{uuid}/")
18
20
  if response.status_code == 200:
19
- return ProcessingCaseItem.from_persist_dict(response.json())
21
+ return self._build_processing_case_item(response)
20
22
  return None
21
23
 
22
24
  def find_by_digest(self, digest: str) -> Optional[ProcessingCaseItem]:
23
- response = self.session.get(f"{self.api_url}/processing-case-items/{digest}/")
25
+ response = self.session.get(f"{self.api_url}/v1/processing-case-items/{digest}/")
24
26
  if response.status_code == 200:
25
- return ProcessingCaseItem.from_persist_dict(response.json())
27
+ return self._build_processing_case_item(response)
26
28
  return None
27
29
 
28
30
  def persist(self, instance: ProcessingCaseItem) -> ProcessingCaseItem:
29
- response = self.session.put(
30
- url=f"{self.api_url}/processing-case-items/{instance.uuid}/",
31
+ response: Response = self.session.put(
32
+ url=f"{self.api_url}/v1/processing-case-items/{instance.uuid}/",
31
33
  json=instance.to_persist_dict,
32
34
  )
33
35
  if response.status_code in [200, 201]:
34
- return ProcessingCaseItem.from_dict(response.json())
36
+ return self._build_processing_case_item(response)
35
37
  return instance
36
38
 
37
39
  def remove(self, instance: ProcessingCaseItem):
38
- self.session.delete(f"{self.api_url}/processing-case-items/{instance.uuid}/")
40
+ self.session.delete(f"{self.api_url}/v1/processing-case-items/{instance.uuid}/")
39
41
 
40
42
  def filter(
41
43
  self,
42
44
  tenant_slug: str,
43
45
  filters: ProcessingCaseItemFilters,
44
46
  ) -> List[ProcessingCaseItem]:
45
- response = self.session.get(f"{self.api_url}/processing-case-items/")
47
+ response = self.session.get(f"{self.api_url}/v1/processing-case-items/")
46
48
  if response.status_code == 200:
47
49
  raw_response = response.json()
48
50
  return [
49
- ProcessingCaseItem.from_persist_dict(item)
50
- for item in raw_response.get('data', [])
51
+ ProcessingCaseItem.from_dict(camel_to_snake(item_data))
52
+ for item_data in raw_response.get('data', [])
51
53
  ]
52
54
  return []
55
+
56
+ @classmethod
57
+ def _build_processing_case_item(cls, response: Response) -> ProcessingCaseItem:
58
+ response_json = response.json()
59
+ instance_data = response_json.get('data', {})
60
+ return ProcessingCaseItem.from_dict(camel_to_snake(instance_data))
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "documente_shared"
3
- version = "0.1.80"
3
+ version = "0.1.82"
4
4
  description = "Shared utilities for Documente AI projects"
5
5
  authors = ["Tech <tech@llamitai.com>"]
6
6
  license = "MIT"