kodexa 7.4.416992731072__tar.gz → 7.4.417109101181__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 (51) hide show
  1. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/PKG-INFO +1 -1
  2. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/persistence.py +39 -2
  3. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/platform/client.py +171 -0
  4. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/pyproject.toml +2 -2
  5. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/LICENSE +0 -0
  6. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/README.md +0 -0
  7. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/__init__.py +0 -0
  8. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/assistant/__init__.py +0 -0
  9. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/assistant/assistant.py +0 -0
  10. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/connectors/__init__.py +0 -0
  11. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/connectors/connectors.py +0 -0
  12. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/dataclasses/__init__.py +0 -0
  13. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/dataclasses/templates/llm_data_class.j2 +0 -0
  14. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/__init__.py +0 -0
  15. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/base.py +0 -0
  16. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/entities/__init__.py +0 -0
  17. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/entities/check_response.py +0 -0
  18. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/entities/product.py +0 -0
  19. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/entities/product_group.py +0 -0
  20. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/entities/product_subscription.py +0 -0
  21. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/model.py +0 -0
  22. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/objects.py +0 -0
  23. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/model/utils.py +0 -0
  24. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/pipeline/__init__.py +0 -0
  25. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/pipeline/pipeline.py +0 -0
  26. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/platform/__init__.py +0 -0
  27. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/platform/interaction.py +0 -0
  28. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/platform/kodexa.py +0 -0
  29. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/platform/manifest.py +0 -0
  30. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/__init__.py +0 -0
  31. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/ast.py +0 -0
  32. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/core.py +0 -0
  33. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/lexrules.py +0 -0
  34. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/lextab.py +0 -0
  35. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/lextab.pyi +0 -0
  36. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/parserules.py +0 -0
  37. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/parserules.pyi +0 -0
  38. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/parsetab.py +0 -0
  39. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/selectors/parsetab.pyi +0 -0
  40. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/spatial/__init__.py +0 -0
  41. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/spatial/azure_models.py +0 -0
  42. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/spatial/bbox_common.py +0 -0
  43. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/spatial/table_form_common.py +0 -0
  44. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/steps/__init__.py +0 -0
  45. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/steps/common.py +0 -0
  46. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/testing/__init__.py +0 -0
  47. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/testing/test_components.py +0 -0
  48. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/testing/test_utils.py +0 -0
  49. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/training/__init__.py +0 -0
  50. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/training/train_utils.py +0 -0
  51. {kodexa-7.4.416992731072 → kodexa-7.4.417109101181}/kodexa/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: kodexa
3
- Version: 7.4.416992731072
3
+ Version: 7.4.417109101181
4
4
  Summary: Python SDK for the Kodexa Platform
5
5
  Author: Austin Redenbaugh
6
6
  Author-email: austin@kodexa.com
@@ -1172,6 +1172,36 @@ class SqliteDocumentPersistence(object):
1172
1172
  if result[0] == 0:
1173
1173
  self.cursor.execute("INSERT INTO validations (obj) VALUES (?)", [sqlite3.Binary(msgpack.packb([]))])
1174
1174
 
1175
+ def __deduplicate_document_taxon_validations(self, taxon_validations: List[DocumentTaxonValidation]) -> List[DocumentTaxonValidation]:
1176
+ """
1177
+ Deduplicate DocumentTaxonValidation objects based on taxon_path and exception_id.
1178
+
1179
+ Args:
1180
+ taxon_validations: List of DocumentTaxonValidation objects to deduplicate.
1181
+
1182
+ Returns:
1183
+ List of deduplicated DocumentTaxonValidation objects.
1184
+ """
1185
+ if taxon_validations is None or len(taxon_validations) == 0:
1186
+ return []
1187
+
1188
+ seen_keys = set()
1189
+ deduplicated = []
1190
+
1191
+ for tv in taxon_validations:
1192
+ if tv is None:
1193
+ continue
1194
+
1195
+ taxon_path = tv.taxon_path if tv.taxon_path is not None else ""
1196
+ exception_id = tv.validation.exception_id if tv.validation and tv.validation.exception_id else ""
1197
+ key = f"{taxon_path}|{exception_id}"
1198
+
1199
+ if key not in seen_keys:
1200
+ seen_keys.add(key)
1201
+ deduplicated.append(tv)
1202
+
1203
+ return deduplicated
1204
+
1175
1205
  def set_validations(self, validations: List[DocumentTaxonValidation]):
1176
1206
  """
1177
1207
  Sets the validations for the document.
@@ -1180,7 +1210,12 @@ class SqliteDocumentPersistence(object):
1180
1210
  validations (List[DocumentTaxonValidation]): The validations to store.
1181
1211
  """
1182
1212
  self.__ensure_validations_table_exists()
1183
- serialized_data = sqlite3.Binary(msgpack.packb([v.model_dump(by_alias=True) for v in validations]))
1213
+ # Handle None input
1214
+ if validations is None:
1215
+ validations = []
1216
+ # Deduplicate validations before storing
1217
+ deduplicated_validations = self.__deduplicate_document_taxon_validations(validations)
1218
+ serialized_data = sqlite3.Binary(msgpack.packb([v.model_dump(by_alias=True) for v in deduplicated_validations]))
1184
1219
  self.cursor.execute("UPDATE validations SET obj = ? WHERE rowid = 1", [serialized_data])
1185
1220
  self.connection.commit()
1186
1221
 
@@ -1194,7 +1229,9 @@ class SqliteDocumentPersistence(object):
1194
1229
  self.__ensure_validations_table_exists()
1195
1230
  result = self.cursor.execute("SELECT obj FROM validations WHERE rowid = 1").fetchone()
1196
1231
  if result and result[0]:
1197
- return [DocumentTaxonValidation.model_validate(v) for v in msgpack.unpackb(result[0])]
1232
+ validations = [DocumentTaxonValidation.model_validate(v) for v in msgpack.unpackb(result[0])]
1233
+ # Deduplicate validations before returning
1234
+ return self.__deduplicate_document_taxon_validations(validations)
1198
1235
  return []
1199
1236
 
1200
1237
  def set_external_data(self, external_data: dict, key: str = "default"):
@@ -1205,6 +1205,177 @@ class PageTaskEndpoint(PageTask, PageEndpoint):
1205
1205
  def get_type(self) -> Optional[str]:
1206
1206
  return "task"
1207
1207
 
1208
+ class PageTaskActivityEndpoint(PageEndpoint):
1209
+ """
1210
+ Represents a page of task activities.
1211
+ """
1212
+ def get_type(self) -> Optional[str]:
1213
+ return "taskActivities"
1214
+
1215
+ class PageTaskDocumentFamilyEndpoint(PageEndpoint):
1216
+ """
1217
+ Represents a page of task document families.
1218
+ """
1219
+ def get_type(self) -> Optional[str]:
1220
+ return "taskDocumentFamilies"
1221
+
1222
+ class PageTaskTagEndpoint(PageEndpoint):
1223
+ """
1224
+ Represents a page of task tags.
1225
+ """
1226
+ def get_type(self) -> Optional[str]:
1227
+ return "taskTags"
1228
+
1229
+ class TaskEndpoint(EntityEndpoint, Task):
1230
+ """
1231
+ Represents a task endpoint.
1232
+ """
1233
+ def get_type(self) -> str:
1234
+ return "tasks"
1235
+
1236
+ def create_with_request(self, task: Task, task_template: Optional[TaskTemplate] = None, document_families: Optional[List[DocumentFamily]] = None):
1237
+ """Create a task with the given request."""
1238
+ url = "/api/tasks/createTaskWithRequest"
1239
+ response = self.client.post(url, body={
1240
+ "task": task.model_dump(mode="json", by_alias=True),
1241
+ "taskTemplate": task_template.model_dump(mode="json", by_alias=True) if task_template else None,
1242
+ "documentFamilies": [df.model_dump(mode="json", by_alias=True) for df in document_families] if document_families else None
1243
+ })
1244
+ return TaskEndpoint.model_validate(response.json()).set_client(self.client)
1245
+
1246
+ def update_status(self, status: TaskStatus):
1247
+ """Update the status of the task."""
1248
+ url = f"/api/tasks/{self.id}/status"
1249
+ response = self.client.put(url, body=status)
1250
+ return TaskEndpoint.model_validate(response.json()).set_client(self.client)
1251
+
1252
+ def remove_status(self):
1253
+ """Remove the task status."""
1254
+ url = f"/api/tasks/{self.id}/status"
1255
+ response = self.client.delete(url)
1256
+ return TaskEndpoint.model_validate(response.json()).set_client(self.client)
1257
+
1258
+ def update_assignee(self, assignee: User):
1259
+ """Update the assignee of the task."""
1260
+ url = f"/api/tasks/{self.id}/assignee"
1261
+ response = self.client.put(url, body=assignee.model_dump(mode="json", by_alias=True))
1262
+ return TaskEndpoint.model_validate(response.json()).set_client(self.client)
1263
+
1264
+ def remove_assignee(self):
1265
+ """Remove the task assignee."""
1266
+ url = f"/api/tasks/{self.id}/assignee"
1267
+ response = self.client.delete(url)
1268
+ return TaskEndpoint.model_validate(response.json()).set_client(self.client)
1269
+
1270
+ class TasksEndpoint(EntitiesEndpoint):
1271
+ """
1272
+ Represents tasks endpoints.
1273
+ """
1274
+ def get_type(self) -> str:
1275
+ return "tasks"
1276
+
1277
+ def get_instance_class(self, object_dict=None):
1278
+ return TaskEndpoint
1279
+
1280
+ def get_page_class(self, object_dict=None):
1281
+ return PageTaskEndpoint
1282
+
1283
+ def create_with_template(self, task: Task, task_template: Optional[TaskTemplate] = None, document_families: Optional[List[DocumentFamily]] = None) -> TaskEndpoint:
1284
+ """Create a task with the given template."""
1285
+ url = "/api/tasks/createTaskWithRequest"
1286
+ create_body = {
1287
+ "task": task.model_dump(mode="json", by_alias=True),
1288
+ "taskTemplate": task_template.model_dump(mode="json", by_alias=True) if task_template else None,
1289
+ "documentFamilies": [df.model_dump(mode="json", by_alias=True) for df in document_families] if document_families else None
1290
+ }
1291
+ response = self.client.post(url, create_body)
1292
+ return TaskEndpoint.model_validate(response.json()).set_client(self.client)
1293
+
1294
+ class TaskTemplateEndpoint(EntityEndpoint, TaskTemplate):
1295
+ """
1296
+ Represents a task template endpoint.
1297
+ """
1298
+ def get_type(self) -> str:
1299
+ return "taskTemplates"
1300
+
1301
+ class TaskTemplatesEndpoint(EntitiesEndpoint):
1302
+ """
1303
+ Represents task templates endpoints.
1304
+ """
1305
+ def get_type(self) -> str:
1306
+ return "taskTemplates"
1307
+
1308
+ def get_instance_class(self, object_dict=None):
1309
+ return TaskTemplateEndpoint
1310
+
1311
+ def get_page_class(self, object_dict=None):
1312
+ return PageTaskTemplateEndpoint
1313
+
1314
+ class TaskActivityEndpoint(EntityEndpoint, TaskActivity):
1315
+ """
1316
+ Represents a task activity endpoint.
1317
+ """
1318
+ def get_type(self) -> str:
1319
+ return "taskActivities"
1320
+
1321
+ class TaskActivitiesEndpoint(EntitiesEndpoint):
1322
+ """
1323
+ Represents task activities endpoints.
1324
+ """
1325
+ def get_type(self) -> str:
1326
+ return "taskActivities"
1327
+
1328
+ def get_instance_class(self, object_dict=None):
1329
+ return TaskActivityEndpoint
1330
+
1331
+ def get_page_class(self, object_dict=None):
1332
+ return PageTaskActivityEndpoint
1333
+
1334
+ class TaskDocumentFamilyEndpoint(EntityEndpoint, TaskDocumentFamily):
1335
+ """
1336
+ Represents a task document family endpoint.
1337
+ """
1338
+ def get_type(self) -> str:
1339
+ return "taskDocumentFamilies"
1340
+
1341
+ class TaskDocumentFamiliesEndpoint(EntitiesEndpoint):
1342
+ """
1343
+ Represents task document families endpoints.
1344
+ """
1345
+ def get_type(self) -> str:
1346
+ return "taskDocumentFamilies"
1347
+
1348
+ def get_instance_class(self, object_dict=None):
1349
+ return TaskDocumentFamilyEndpoint
1350
+
1351
+ def get_page_class(self, object_dict=None):
1352
+ return PageTaskDocumentFamilyEndpoint
1353
+
1354
+ class TaskTagEndpoint(EntityEndpoint, TaskTag):
1355
+ """
1356
+ Represents a task tag endpoint.
1357
+ """
1358
+ def get_type(self) -> str:
1359
+ return "taskTags"
1360
+
1361
+ class TaskTagsEndpoint(EntitiesEndpoint):
1362
+ """
1363
+ Represents task tags endpoints.
1364
+ """
1365
+ def get_type(self) -> str:
1366
+ return "taskTags"
1367
+
1368
+ def get_instance_class(self, object_dict=None):
1369
+ return TaskTagEndpoint
1370
+
1371
+ def get_page_class(self, object_dict=None):
1372
+ return PageTaskTagEndpoint
1373
+
1374
+
1375
+ class PageTaskTemplateEndpoint(PageTask, PageEndpoint):
1376
+ def get_type(self) -> Optional[str]:
1377
+ return "taskTemplate"
1378
+
1208
1379
 
1209
1380
  class PageTaskActivityEndpoint(PageTaskActivity, PageEndpoint):
1210
1381
  """
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "kodexa"
3
- version = "7.4.416992731072"
3
+ version = "7.4.417109101181"
4
4
  description = "Python SDK for the Kodexa Platform"
5
5
  authors = ["Austin Redenbaugh <austin@kodexa.com>", "Philip Dodds <philip@kodexa.com>", "Romar Cablao <rcablao@kodexa.com>", "Amadea Paula Dodds <amadeapaula@kodexa.com>"]
6
6
  readme = "README.md"
@@ -43,7 +43,7 @@ pytest-runner = "^6.0.0"
43
43
  mypy = "^1.10.0"
44
44
  flake8 = "^7.0.0"
45
45
  pandas = "^2.2.3"
46
- setuptools = "^75.1.0"
46
+ setuptools = "^78.1.1"
47
47
  black = ">=23.7,<25.0"
48
48
  numpy = "2.2.2"
49
49