kodexa 7.0.1a10177063353__py3-none-any.whl → 7.0.1a11915814268__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.
@@ -4,7 +4,7 @@ import pathlib
4
4
  import sqlite3
5
5
  import tempfile
6
6
  import uuid
7
- from typing import List
7
+ from typing import List, Optional
8
8
 
9
9
  import msgpack
10
10
 
@@ -13,8 +13,9 @@ from kodexa.model.model import (
13
13
  DocumentMetadata,
14
14
  ContentFeature,
15
15
  ContentException,
16
- ModelInsight,
16
+ ModelInsight, ProcessingStep,
17
17
  )
18
+ from kodexa.model.objects import DocumentTaxonValidation
18
19
 
19
20
  logger = logging.getLogger()
20
21
 
@@ -1122,6 +1123,131 @@ class SqliteDocumentPersistence(object):
1122
1123
 
1123
1124
  return content_nodes
1124
1125
 
1126
+ def __ensure_ed_table_exists(self):
1127
+ """
1128
+ Ensure the 'ed' table exists in the database.
1129
+ Creates the table if it does not exist.
1130
+ """
1131
+ self.cursor.execute("""
1132
+ CREATE TABLE IF NOT EXISTS ed (
1133
+ obj BLOB
1134
+ )
1135
+ """)
1136
+
1137
+ # Check if the table has any rows, if not, insert an initial empty row
1138
+ result = self.cursor.execute("SELECT COUNT(*) FROM ed").fetchone()
1139
+ if result[0] == 0:
1140
+ self.cursor.execute("INSERT INTO ed (obj) VALUES (?)", [sqlite3.Binary(msgpack.packb({}))])
1141
+
1142
+ def __ensure_validations_table_exists(self):
1143
+ """
1144
+ Ensure the 'validations' table exists in the database.
1145
+ Creates the table if it does not exist and initializes it with an empty list.
1146
+ """
1147
+ self.cursor.execute("""
1148
+ CREATE TABLE IF NOT EXISTS validations (
1149
+ obj BLOB
1150
+ )
1151
+ """)
1152
+
1153
+ # Check if the table has any rows, if not, insert an initial empty row
1154
+ result = self.cursor.execute("SELECT COUNT(*) FROM validations").fetchone()
1155
+ if result[0] == 0:
1156
+ self.cursor.execute("INSERT INTO validations (obj) VALUES (?)", [sqlite3.Binary(msgpack.packb([]))])
1157
+
1158
+ def set_validations(self, validations: List[DocumentTaxonValidation]):
1159
+ """
1160
+ Sets the validations for the document.
1161
+
1162
+ Args:
1163
+ validations (List[DocumentTaxonValidation]): The validations to store.
1164
+ """
1165
+ self.__ensure_validations_table_exists()
1166
+ serialized_data = sqlite3.Binary(msgpack.packb([v.model_dump(by_alias=True) for v in validations]))
1167
+ self.cursor.execute("UPDATE validations SET obj = ? WHERE rowid = 1", [serialized_data])
1168
+ self.connection.commit()
1169
+
1170
+ def get_validations(self) -> List[DocumentTaxonValidation]:
1171
+ """
1172
+ Gets the validations associated with this document.
1173
+
1174
+ Returns:
1175
+ List[DocumentTaxonValidation]: The list of validations stored in the validations table.
1176
+ """
1177
+ self.__ensure_validations_table_exists()
1178
+ result = self.cursor.execute("SELECT obj FROM validations WHERE rowid = 1").fetchone()
1179
+ if result and result[0]:
1180
+ return [DocumentTaxonValidation.model_validate(v) for v in msgpack.unpackb(result[0])]
1181
+ return []
1182
+
1183
+ def set_external_data(self, external_data: dict):
1184
+ """
1185
+ Sets the external data for the document.
1186
+
1187
+ Args:
1188
+ external_data (dict): The external data to store, must be JSON serializable.
1189
+ """
1190
+ self.__ensure_ed_table_exists()
1191
+ serialized_data = sqlite3.Binary(msgpack.packb(external_data))
1192
+ self.cursor.execute("UPDATE ed SET obj = ? WHERE rowid = 1", [serialized_data])
1193
+ self.connection.commit()
1194
+
1195
+ def get_external_data(self) -> dict:
1196
+ """
1197
+ Gets the external data associated with this document.
1198
+
1199
+ Returns:
1200
+ dict: The external data stored in the ed table.
1201
+ """
1202
+ self.__ensure_ed_table_exists()
1203
+ result = self.cursor.execute("SELECT obj FROM ed WHERE rowid = 1").fetchone()
1204
+ if result and result[0]:
1205
+ return msgpack.unpackb(result[0])
1206
+ return {}
1207
+
1208
+ def __ensure_steps_table_exists(self):
1209
+ """
1210
+ Ensure the 'steps' table exists in the database.
1211
+ Creates the table if it does not exist.
1212
+ """
1213
+ self.cursor.execute("""
1214
+ CREATE TABLE IF NOT EXISTS steps (
1215
+ obj BLOB
1216
+ )
1217
+ """)
1218
+
1219
+ # Check if the table has any rows, if not, insert an initial empty row
1220
+ result = self.cursor.execute("SELECT COUNT(*) FROM steps").fetchone()
1221
+ if result[0] == 0:
1222
+ self.cursor.execute("INSERT INTO steps (obj) VALUES (?)", [sqlite3.Binary(msgpack.packb([]))])
1223
+
1224
+ def set_steps(self, steps: List[ProcessingStep]):
1225
+ """
1226
+ Sets the processing steps for the document.
1227
+
1228
+ Args:
1229
+ steps (List[ProcessingStep]): A list of ProcessingStep objects to store.
1230
+ """
1231
+ self.__ensure_steps_table_exists()
1232
+ serialized_steps = [step.to_dict() for step in steps]
1233
+ packed_data = sqlite3.Binary(msgpack.packb(serialized_steps))
1234
+ self.cursor.execute("UPDATE steps SET obj = ? WHERE rowid = 1", [packed_data])
1235
+ self.connection.commit()
1236
+
1237
+ def get_steps(self) -> List[ProcessingStep]:
1238
+ """
1239
+ Gets the processing steps associated with this document.
1240
+
1241
+ Returns:
1242
+ List[ProcessingStep]: A list of ProcessingStep objects.
1243
+ """
1244
+ self.__ensure_steps_table_exists()
1245
+ result = self.cursor.execute("SELECT obj FROM steps WHERE rowid = 1").fetchone()
1246
+ if result and result[0]:
1247
+ unpacked_data = msgpack.unpackb(result[0])
1248
+ return [ProcessingStep(**step) for step in unpacked_data]
1249
+ return []
1250
+
1125
1251
 
1126
1252
  class SimpleObjectCache(object):
1127
1253
  """
@@ -1146,7 +1272,7 @@ class SimpleObjectCache(object):
1146
1272
  self.next_id = 1
1147
1273
  self.dirty_objs = set()
1148
1274
 
1149
- def get_obj(self, obj_id):
1275
+ def get_obj(self, obj_id) -> Optional[ContentNode]:
1150
1276
  """
1151
1277
  Get the object with the given ID.
1152
1278
 
@@ -1161,7 +1287,7 @@ class SimpleObjectCache(object):
1161
1287
 
1162
1288
  return None
1163
1289
 
1164
- def add_obj(self, obj):
1290
+ def add_obj(self, obj: ContentNode):
1165
1291
  """
1166
1292
  Add an object to the cache.
1167
1293
 
@@ -1186,7 +1312,7 @@ class SimpleObjectCache(object):
1186
1312
  if obj.uuid in self.dirty_objs:
1187
1313
  self.dirty_objs.remove(obj.uuid)
1188
1314
 
1189
- def get_dirty_objs(self):
1315
+ def get_dirty_objs(self) -> list[ContentNode]:
1190
1316
  """
1191
1317
  Get all dirty objects in the cache.
1192
1318
 
@@ -1260,6 +1386,40 @@ class PersistenceManager(object):
1260
1386
  document, filename, delete_on_close, inmemory=inmemory
1261
1387
  )
1262
1388
 
1389
+ def get_steps(self) -> list[ProcessingStep]:
1390
+ """
1391
+ Gets the processing steps for this document
1392
+
1393
+ :return:
1394
+ """
1395
+ return self._underlying_persistence.get_steps()
1396
+
1397
+ def set_steps(self, steps: list[ProcessingStep]):
1398
+ self._underlying_persistence.set_steps(steps)
1399
+
1400
+ def set_validations(self, validations: list[DocumentTaxonValidation]):
1401
+ self._underlying_persistence.set_validations(validations)
1402
+
1403
+ def get_validations(self) -> list[DocumentTaxonValidation]:
1404
+ return self._underlying_persistence.get_validations()
1405
+
1406
+ def get_external_data(self) -> dict:
1407
+ """
1408
+ Gets the external data object associated with this document
1409
+
1410
+ :return: dict of the external data
1411
+ """
1412
+ return self._underlying_persistence.get_external_data()
1413
+
1414
+ def set_external_data(self, external_data:dict):
1415
+ """
1416
+ Sets the external data for this document
1417
+
1418
+ :param external_data: dict representing the external data, must be JSON serializable
1419
+ :return:
1420
+ """
1421
+ self._underlying_persistence.set_external_data(external_data)
1422
+
1263
1423
  def get_nodes_by_type(self, node_type: str) -> List[ContentNode]:
1264
1424
  """
1265
1425
  Retrieves all nodes of a given type from the underlying persistence layer.
@@ -1283,7 +1443,10 @@ class PersistenceManager(object):
1283
1443
  ContentNode: The node with the given uuid.
1284
1444
  """
1285
1445
  if self.node_cache.get_obj(uuid) is None:
1286
- self.node_cache.add_obj(self._underlying_persistence.get_node(uuid))
1446
+ node = self._underlying_persistence.get_node(uuid)
1447
+ if node:
1448
+ self.node_cache.add_obj(node)
1449
+ return node
1287
1450
 
1288
1451
  return self.node_cache.get_obj(uuid) # return the cached version
1289
1452
 
kodexa/platform/client.py CHANGED
@@ -86,7 +86,7 @@ from kodexa.model.objects import (
86
86
  PageExtensionPack,
87
87
  PageOrganization,
88
88
  DocumentFamilyStatistics, MessageContext, PagePrompt, Prompt, GuidanceSet, PageGuidanceSet, DocumentEmbedding,
89
- DocumentExternalData,
89
+ DocumentExternalData, Task, PageTask, RetainedGuidance, PageRetainedGuidance,
90
90
  )
91
91
 
92
92
  logger = logging.getLogger()
@@ -494,7 +494,7 @@ class ComponentEndpoint(ClientEndpoint, OrganizationOwned):
494
494
  self.get_page_class(list_response.json())
495
495
  .model_validate(list_response.json())
496
496
  .set_client(self.client)
497
- .to_endpoints()
497
+ .to_endpoints().content
498
498
  ):
499
499
  yield endpoint
500
500
 
@@ -1173,6 +1173,35 @@ class PagePipelineEndpoint(PagePipeline, PageEndpoint):
1173
1173
  return "pipeline"
1174
1174
 
1175
1175
 
1176
+ class PageTaskEndpoint(PageTask, PageEndpoint):
1177
+ def get_type(self) -> Optional[str]:
1178
+ return "task"
1179
+
1180
+
1181
+ class PageRetainedGuidanceEndpoint(PageRetainedGuidance, PageEndpoint):
1182
+ """Represents a page retained guidance endpoint.
1183
+
1184
+ This class is used to represent a page retained guidance endpoint which is a
1185
+ combination of a page retained guidance and a page endpoint.
1186
+
1187
+ Attributes:
1188
+ None
1189
+ """
1190
+
1191
+ """Represents a page retained guidance endpoint"""
1192
+
1193
+ def get_type(self) -> Optional[str]:
1194
+ """Get the type of the endpoint.
1195
+
1196
+ This method is used to get the type of the endpoint. In this case,
1197
+ it will always return "retainedGuidance".
1198
+
1199
+ Returns:
1200
+ str: The type of the endpoint, which is "retainedGuidance".
1201
+ """
1202
+ return "retainedGuidance"
1203
+
1204
+
1176
1205
  class PageProjectEndpoint(PageProject, PageEndpoint):
1177
1206
  """Represents a page project endpoint.
1178
1207
 
@@ -2517,14 +2546,42 @@ class WorkspaceEndpoint(EntityEndpoint, Workspace):
2517
2546
  raise ValueError("Workspace has no channel")
2518
2547
 
2519
2548
 
2549
+ class TaskEndpoint(EntityEndpoint, Task):
2550
+ """Represents a task endpoint.
2551
+
2552
+ This class is used to interact with the task endpoint of the API.
2553
+ """
2554
+
2555
+ def get_type(self) -> str:
2556
+ """Get the type of the endpoint.
2557
+
2558
+ Returns:
2559
+ str: The type of the endpoint, in this case "projects".
2560
+ """
2561
+ return "tasks"
2562
+
2563
+
2564
+ class RetainedGuidanceEndpoint(EntityEndpoint, RetainedGuidance):
2565
+ """Represents a retained guidance endpoint.
2566
+
2567
+ This class is used to interact with the retained guidance endpoint of the API.
2568
+ """
2569
+
2570
+ def get_type(self) -> str:
2571
+ """Get the type of the endpoint.
2572
+
2573
+ Returns:
2574
+ str: The type of the endpoint, in this case "retainedGuidance".
2575
+ """
2576
+ return "retainedGuidance"
2577
+
2578
+
2520
2579
  class ProjectEndpoint(EntityEndpoint, Project):
2521
2580
  """Represents a project endpoint.
2522
2581
 
2523
2582
  This class is used to interact with the project endpoint of the API.
2524
2583
  """
2525
2584
 
2526
- """Represents a project endpoint"""
2527
-
2528
2585
  def get_type(self) -> str:
2529
2586
  """Get the type of the endpoint.
2530
2587
 
@@ -2849,6 +2906,72 @@ class AssistantsEndpoint(EntitiesEndpoint):
2849
2906
  return PageAssistantEndpoint
2850
2907
 
2851
2908
 
2909
+ class TasksEndpoint(EntitiesEndpoint):
2910
+ """Represents a projects endpoint"""
2911
+
2912
+ """Represents a projects endpoint"""
2913
+
2914
+ def get_type(self) -> str:
2915
+ """
2916
+ Get the type of the endpoint.
2917
+
2918
+ Returns:
2919
+ str: The type of the endpoint.
2920
+ """
2921
+ return "tasks"
2922
+
2923
+ def get_instance_class(self, object_dict=None):
2924
+ """
2925
+ Get the instance class of the endpoint.
2926
+
2927
+ Returns:
2928
+ ProjectEndpoint: The instance class of the endpoint.
2929
+ """
2930
+ return TaskEndpoint
2931
+
2932
+ def get_page_class(self, object_dict=None):
2933
+ """
2934
+ Get the page class of the endpoint.
2935
+
2936
+ Returns:
2937
+ PageProjectEndpoint: The page class of the endpoint.
2938
+ """
2939
+ return PageTaskEndpoint
2940
+
2941
+
2942
+ class RetainedGuidancesEndpoint(EntitiesEndpoint):
2943
+ """Represents a projects endpoint"""
2944
+
2945
+ """Represents a projects endpoint"""
2946
+
2947
+ def get_type(self) -> str:
2948
+ """
2949
+ Get the type of the endpoint.
2950
+
2951
+ Returns:
2952
+ str: The type of the endpoint.
2953
+ """
2954
+ return "retainedGuidance"
2955
+
2956
+ def get_instance_class(self, object_dict=None):
2957
+ """
2958
+ Get the instance class of the endpoint.
2959
+
2960
+ Returns:
2961
+ ProjectEndpoint: The instance class of the endpoint.
2962
+ """
2963
+ return RetainedGuidanceEndpoint
2964
+
2965
+ def get_page_class(self, object_dict=None):
2966
+ """
2967
+ Get the page class of the endpoint.
2968
+
2969
+ Returns:
2970
+ PageProjectEndpoint: The page class of the endpoint.
2971
+ """
2972
+ return PageRetainedGuidanceEndpoint
2973
+
2974
+
2852
2975
  class ProjectsEndpoint(EntitiesEndpoint):
2853
2976
  """Represents a projects endpoint"""
2854
2977
 
@@ -3946,6 +4069,18 @@ class TaxonomyEndpoint(ComponentInstanceEndpoint, Taxonomy):
3946
4069
  params={"format": "xsd"},
3947
4070
  ).text
3948
4071
 
4072
+ def to_json_schema(self) -> dict:
4073
+ """
4074
+ Convert the taxonomy to an XSD.
4075
+
4076
+ Returns:
4077
+ str: The XSD representation of the taxonomy.
4078
+ """
4079
+ return self.client.get(
4080
+ f'/api/taxonomies/{self.ref.replace(":", "/")}/export',
4081
+ params={"format": "json-schema"},
4082
+ ).json()
4083
+
3949
4084
  def get_taxon_by_path(self, path) -> Optional[Taxon]:
3950
4085
  """
3951
4086
  Get a taxon by its path.
@@ -4457,7 +4592,7 @@ class DocumentFamilyEndpoint(DocumentFamily, ClientEndpoint):
4457
4592
  response = self.client.get(url)
4458
4593
  process_response(response)
4459
4594
 
4460
- def get_external_data(self) -> DocumentExternalData:
4595
+ def get_external_data(self) -> dict:
4461
4596
  """
4462
4597
  Get the external data of the document family.
4463
4598
 
@@ -4466,18 +4601,21 @@ class DocumentFamilyEndpoint(DocumentFamily, ClientEndpoint):
4466
4601
  """
4467
4602
  url = f"/api/documentFamilies/{self.id}/externalData"
4468
4603
  response = self.client.get(url)
4469
- return DocumentExternalData.model_validate(response.json())
4604
+ return response.json()
4470
4605
 
4471
- def update_external_data(self, external_data: DocumentExternalData):
4606
+ def set_external_data(self, external_data: dict) -> dict:
4472
4607
  """
4473
- Update the external data of the document family.
4608
+ Set the external data of the document family.
4474
4609
 
4475
4610
  Args:
4476
- external_data (DocumentExternalData): The external data to update.
4611
+ external_data (dict): The external data to set for the document family.
4612
+
4613
+ Returns:
4614
+ dict: The updated external data of the document family.
4477
4615
  """
4478
4616
  url = f"/api/documentFamilies/{self.id}/externalData"
4479
- response = self.client.put(url, body=external_data.model_dump(mode="json", by_alias=True))
4480
- process_response(response)
4617
+ response = self.client.put(url, body=external_data)
4618
+ return response.json()
4481
4619
 
4482
4620
  def export(self) -> bytes:
4483
4621
  """
@@ -5289,6 +5427,7 @@ class DocumentStoreEndpoint(StoreEndpoint):
5289
5427
  object_path: Optional[str] = None,
5290
5428
  replace=False,
5291
5429
  additional_metadata: Optional[dict] = None,
5430
+ external_data: Optional[dict] = None,
5292
5431
  ):
5293
5432
  """
5294
5433
  Upload a file to the store.
@@ -5298,6 +5437,7 @@ class DocumentStoreEndpoint(StoreEndpoint):
5298
5437
  object_path (Optional[str]): The path to the object (Default is the same the file path).
5299
5438
  replace (bool): Replace the file if it already exists (Default False).
5300
5439
  additional_metadata (Optional[dict]): Additional metadata to add to the file (Default None).
5440
+ external_data (Optional[dict]): External data to add to the file (Default None).
5301
5441
  """
5302
5442
  if Path(file_path).is_file():
5303
5443
  logger.info(f"Uploading {file_path}")
@@ -5307,6 +5447,7 @@ class DocumentStoreEndpoint(StoreEndpoint):
5307
5447
  content=path_content,
5308
5448
  replace=replace,
5309
5449
  additional_metadata=additional_metadata,
5450
+ external_data=external_data
5310
5451
  )
5311
5452
  else:
5312
5453
  raise Exception(f"{file_path} is not a file")
@@ -5317,6 +5458,7 @@ class DocumentStoreEndpoint(StoreEndpoint):
5317
5458
  content,
5318
5459
  replace=False,
5319
5460
  additional_metadata: Optional[dict] = None,
5461
+ external_data: Optional[dict] = None,
5320
5462
  ) -> DocumentFamilyEndpoint:
5321
5463
  """
5322
5464
  Put the content into the store at the given path.
@@ -5326,6 +5468,7 @@ class DocumentStoreEndpoint(StoreEndpoint):
5326
5468
  content: The content for that object.
5327
5469
  replace (bool): Replace the content if it exists.
5328
5470
  additional_metadata (Optional[dict]): Additional metadata to store with the document (not it can't include 'path').
5471
+ external_data (Optional[dict]): External data to store with the document.
5329
5472
 
5330
5473
  Returns:
5331
5474
  DocumentFamilyEndpoint: The document family that was created.
@@ -5335,6 +5478,9 @@ class DocumentStoreEndpoint(StoreEndpoint):
5335
5478
  if additional_metadata is None:
5336
5479
  additional_metadata = {}
5337
5480
 
5481
+ if external_data is not None:
5482
+ additional_metadata["externalData"] = json.dumps(external_data)
5483
+
5338
5484
  if replace and self.client.exists(
5339
5485
  f"/api/stores/{self.ref.replace(':', '/')}/fs", params={"path": path}
5340
5486
  ):
@@ -6332,6 +6478,10 @@ class KodexaClient:
6332
6478
  executions (ExecutionsEndpoint): An endpoint for executions.
6333
6479
  channels (ChannelsEndpoint): An endpoint for channels.
6334
6480
  messages (MessagesEndpoint): An endpoint for messages.
6481
+ assistants (AssistantsEndpoint): An endpoint for assistants.
6482
+ products (ProductsEndpoint): An endpoint for products.
6483
+ tasks (TasksEndpoint): An endpoint for tasks.
6484
+ retained_guidances (RetainedGuidancesEndpoint): An endpoint for retained guidances.
6335
6485
  """
6336
6486
 
6337
6487
  def __init__(self, url=None, access_token=None, profile=None):
@@ -6354,6 +6504,8 @@ class KodexaClient:
6354
6504
  self.messages = MessagesEndpoint(self)
6355
6505
  from kodexa.model.entities.product import ProductsEndpoint
6356
6506
  self.products = ProductsEndpoint(self)
6507
+ self.tasks = TasksEndpoint(self)
6508
+ self.retained_guidances = RetainedGuidancesEndpoint(self)
6357
6509
 
6358
6510
  @staticmethod
6359
6511
  def login(url, token):
@@ -6370,7 +6522,6 @@ class KodexaClient:
6370
6522
  Raises:
6371
6523
  Exception: If the status code is not 200.
6372
6524
  """
6373
- from requests.auth import HTTPBasicAuth
6374
6525
 
6375
6526
  obj_response = requests.get(
6376
6527
  f"{url}/api/account/me",
@@ -6751,7 +6902,6 @@ class KodexaClient:
6751
6902
  )
6752
6903
  )
6753
6904
 
6754
-
6755
6905
  def import_project(self, organization: OrganizationEndpoint, import_path: str):
6756
6906
  """
6757
6907
  A method to import a project.
@@ -6947,8 +7097,10 @@ class KodexaClient:
6947
7097
  "message": MessageEndpoint,
6948
7098
  "prompt": PromptEndpoint,
6949
7099
  "guidance": GuidanceSetEndpoint,
7100
+ "retainedGuidance": RetainedGuidanceEndpoint,
6950
7101
  "channel": ChannelEndpoint,
6951
7102
  "product": ProductEndpoint,
7103
+ "task": TaskEndpoint,
6952
7104
  "productSubscription": ProductSubscriptionEndpoint,
6953
7105
  "checkResponse": CheckResponseEndpoint
6954
7106
  }
kodexa/platform/kodexa.py CHANGED
@@ -29,7 +29,7 @@ from kodexa.model.objects import (
29
29
  DocumentFamilyEvent,
30
30
  ChannelEvent,
31
31
  DataObjectEvent,
32
- WorkspaceEvent,
32
+ WorkspaceEvent, DocumentFamily,
33
33
  )
34
34
  from kodexa.pipeline import PipelineContext, PipelineStatistics
35
35
  from kodexa.platform.client import DocumentStoreEndpoint, KodexaClient, process_response
@@ -327,7 +327,7 @@ class KodexaPlatform:
327
327
  dict: The server information.
328
328
  """
329
329
  r = requests.get(
330
- f"{KodexaPlatform.get_url()}/api",
330
+ f"{KodexaPlatform.get_url()}/api/overview",
331
331
  headers={
332
332
  "x-access-token": KodexaPlatform.get_access_token(),
333
333
  "cf-access-token": os.environ.get("CF_TOKEN", ""),
@@ -884,7 +884,7 @@ class EventHelper:
884
884
  ContentObject: The posted content object.
885
885
  """
886
886
  files = {"content": content}
887
- data = {"contentObjectJson": json.dumps(content_object.dict(by_alias=True))}
887
+ data = {"contentObjectJson": json.dumps(content_object.model_dump(by_alias=True))}
888
888
  logger.info("Posting back content object to execution object")
889
889
  co_response = requests.post(
890
890
  f"{KodexaPlatform.get_url()}/api/sessions/{self.event.session_id}/executions/{self.event.execution.id}/objects",
@@ -901,7 +901,7 @@ class EventHelper:
901
901
 
902
902
  return ContentObject.model_validate(co_response.json())
903
903
 
904
- def build_pipeline_context(self) -> PipelineContext:
904
+ def build_pipeline_context(self, event) -> PipelineContext:
905
905
  """Builds a pipeline context.
906
906
 
907
907
  Returns:
@@ -911,16 +911,25 @@ class EventHelper:
911
911
  context={}, content_provider=self, execution_id=self.event.execution.id
912
912
  )
913
913
 
914
- if self.event.store_ref and self.event.document_family_id:
915
- logger.info("We have storeRef and document family")
916
- rds: DocumentStoreEndpoint = KodexaClient().get_object_by_ref(
917
- "store", self.event.store_ref
918
- )
919
- document_family = rds.get_family(self.event.document_family_id)
920
-
921
- context.document_family = document_family
922
- context.document_store = rds
923
-
914
+ if isinstance(event, dict):
915
+ event = self.get_base_event(event)
916
+
917
+ if isinstance(event, DocumentFamilyEvent):
918
+ # Can we get the document family
919
+ dfe:DocumentFamilyEvent = self.event
920
+ if dfe.document_family:
921
+ logger.info(f"Setting document family for context: {dfe.document_family}")
922
+ context.document_family = dfe.document_family
923
+ logger.info(f"Getting document store for family: {context.document_family.store_ref}")
924
+ context.document_store = KodexaClient().get_object_by_ref("store", context.document_family.store_ref)
925
+ if isinstance(event, ContentEvent):
926
+ ce:ContentEvent = self.event
927
+ if ce.content_object:
928
+ logger.info(f"Setting content object for context: {ce.content_object}")
929
+ context.content_object = ce.content_object
930
+ logger.info(f"Getting document store for content object: {context.content_object.store_ref}")
931
+ context.document_store = KodexaClient().get_object_by_ref("store", context.content_object.store_ref)
932
+ logger.info("Returning context")
924
933
  return context
925
934
 
926
935
  def get_input_document(self, context):