helix.fhir.client.sdk 4.2.22__py3-none-any.whl → 4.2.24__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.
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import time
2
3
  from abc import ABC
3
4
  from collections.abc import AsyncGenerator
4
5
  from datetime import UTC, datetime
@@ -188,7 +189,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
188
189
 
189
190
  # Prepare parent bundle entries for further processing
190
191
  parent_bundle_entries: FhirBundleEntryList = parent_response.get_bundle_entries()
191
-
192
192
  if logger:
193
193
  logger.info(
194
194
  f"FhirClient.simulate_graph_async() got parent resources: {parent_response_resource_count} "
@@ -235,8 +235,11 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
235
235
  # Update parent link map for next iteration
236
236
  parent_link_map = new_parent_link_map
237
237
 
238
+ start_time = time.time()
238
239
  # Combine and process responses
239
240
  parent_response = cast(FhirGetBundleResponse, parent_response.extend(child_responses))
241
+ if logger:
242
+ logger.info(f"Parent_response.extend time: {time.time() - start_time}")
240
243
 
241
244
  # Optional resource sorting
242
245
  if sort_resources:
@@ -844,6 +847,7 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
844
847
  ) -> FhirGetResponse | None:
845
848
  result: FhirGetResponse | None = None
846
849
  non_cached_id_list: list[str] = []
850
+
847
851
  # first check to see if we can find these in the cache
848
852
  if ids:
849
853
  for resource_id in ids:
@@ -905,7 +909,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
905
909
  )
906
910
  if cache_updated and logger:
907
911
  logger.info(f"Inserted {result2.status} for {resource_type}/{single_id} into cache (1by1)")
908
-
909
912
  return result
910
913
 
911
914
  async def _get_resources_by_parameters_async(
@@ -970,7 +973,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
970
973
  if logger:
971
974
  logger.info(f"Cache entry not found for {resource_type}/{resource_id} (ByParam)")
972
975
  non_cached_id_list.append(resource_id)
973
-
974
976
  all_result: FhirGetResponse | None = None
975
977
  # either we have non-cached ids or this is a query without id but has other parameters
976
978
  if (
@@ -170,9 +170,8 @@ class FhirGetResponse:
170
170
  """
171
171
  result: FhirGetResponse = self._extend(others=others)
172
172
 
173
- latest_chunk_number: list[int] = sorted([o.chunk_number for o in others if o.chunk_number], reverse=True)
174
- if len(latest_chunk_number) > 0:
175
- result.chunk_number = latest_chunk_number[0]
173
+ if others and others[-1].chunk_number:
174
+ result.chunk_number = others[-1].chunk_number
176
175
  return result
177
176
 
178
177
  @abstractmethod
@@ -115,12 +115,13 @@ class FhirGetBundleResponse(FhirGetResponse):
115
115
  """
116
116
  other_response_entries: FhirBundleEntryList = other_response.get_bundle_entries()
117
117
 
118
- if len(other_response_entries):
118
+ if len(other_response_entries) > 0:
119
119
  # only append if there are entries in the other response
120
120
  if self._bundle_entries is None:
121
- self._bundle_entries = other_response_entries
122
- else:
123
- self._bundle_entries.extend(other_response_entries)
121
+ self._bundle_entries = FhirBundleEntryList()
122
+ from collections import deque
123
+
124
+ deque.extend(self._bundle_entries, other_response_entries)
124
125
 
125
126
  return self
126
127
 
@@ -134,7 +135,6 @@ class FhirGetBundleResponse(FhirGetResponse):
134
135
  """
135
136
  for other_response in others:
136
137
  self.append(other_response=other_response)
137
-
138
138
  return self
139
139
 
140
140
  @override
@@ -311,36 +311,51 @@ class FhirGetBundleResponse(FhirGetResponse):
311
311
  ) -> "FhirGetBundleResponse":
312
312
  """
313
313
  Removes the entries in the cache from the bundle
314
-
315
314
  :param request_cache: RequestCache object to remove the entries from
316
315
  :param compare_hash: if True, compare the hash of the resource with the hash in the cache
317
316
  :return: self
318
317
  """
319
- # remove all entries in the cache from the bundle
318
+ # Build a lookup of cache entries by (resource_type, id)
319
+ cache_map: dict[tuple[str, str], str | None] = {}
320
320
  async for cached_entry in request_cache.get_entries_async():
321
- if cached_entry.from_input_cache:
322
- for entry in self._bundle_entries:
323
- if (
324
- entry.resource
325
- and entry.resource.id is not None # only remove if resource has an id
326
- and entry.resource.id == cached_entry.id_
327
- and entry.resource.resource_type == cached_entry.resource_type
328
- and (
329
- not compare_hash
330
- or (
331
- ResourceHash().hash_value(json.dumps(json.loads(entry.resource.json()), sort_keys=True))
332
- == cached_entry.raw_hash
333
- )
334
- )
335
- ):
336
- if logger:
337
- logger.debug(
338
- f"Removing entry from bundle with id {entry.resource.id} and resource "
339
- f"type {entry.resource.resource_type}"
340
- )
341
- self._bundle_entries.remove(entry)
342
- break
321
+ if cached_entry.from_input_cache and cached_entry.resource_type and cached_entry.id_:
322
+ cache_map[(cached_entry.resource_type, cached_entry.id_)] = (
323
+ cached_entry.raw_hash if compare_hash else None
324
+ )
325
+
326
+ if not cache_map:
327
+ return self
328
+
329
+ resource_hash = ResourceHash() if compare_hash else None
330
+ removed_entries: list[FhirBundleEntry] = []
331
+
332
+ def should_remove(entry: FhirBundleEntry) -> bool:
333
+ resource = entry.resource
334
+ if not resource or resource.id is None or resource.resource_type is None:
335
+ return False
336
+ key = (resource.resource_type, resource.id)
337
+ if key not in cache_map:
338
+ return False
339
+ if not compare_hash:
340
+ return True
341
+ # Compare normalized JSON hash
342
+ if resource_hash is None:
343
+ return False
344
+ try:
345
+ entry_hash = resource_hash.hash_value(json.dumps(json.loads(resource.json()), sort_keys=True))
346
+ return entry_hash == cache_map[key]
347
+ except Exception:
348
+ return False
349
+
350
+ # One pass filter; rebuild list to avoid many deque.remove calls
351
+ kept: list[FhirBundleEntry] = []
352
+ for entry in self._bundle_entries:
353
+ if should_remove(entry):
354
+ removed_entries.append(entry)
355
+ else:
356
+ kept.append(entry)
343
357
 
358
+ self._bundle_entries = FhirBundleEntryList(kept)
344
359
  return self
345
360
 
346
361
  @classmethod
@@ -73,7 +73,7 @@ class TestFhirGetBundleResponse:
73
73
  assert response._bundle_metadata.id_ == "test-bundle-id"
74
74
  assert response._bundle_metadata.type_ == "searchset"
75
75
 
76
- def test_append_unique(self, sample_bundle_response: dict[str, Any]) -> None:
76
+ def test_append(self, sample_bundle_response: dict[str, Any]) -> None:
77
77
  """Test appending another response."""
78
78
  results_by_url: list[RetryableAioHttpUrlResult] = []
79
79
 
@@ -113,7 +113,8 @@ class TestFhirGetBundleResponse:
113
113
 
114
114
  first_response.append(second_response)
115
115
 
116
- assert len(first_response.get_bundle_entries()) == 2
116
+ # Updating it to 4 since we have integrated cache and do not do same lookups again so we do not need to remove duplicates here.
117
+ assert len(first_response.get_bundle_entries()) == 4
117
118
 
118
119
  def test_get_resources(self, sample_bundle_response: dict[str, Any]) -> None:
119
120
  """Test getting resources from the response."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: helix.fhir.client.sdk
3
- Version: 4.2.22
3
+ Version: 4.2.24
4
4
  Summary: helix.fhir.client.sdk
5
5
  Home-page: https://github.com/icanbwell/helix.fhir.client.sdk
6
6
  Author: Imran Qureshi
@@ -32,7 +32,7 @@ helix_fhir_client_sdk/graph/fhir_graph_mixin.py,sha256=z0j9FmO2bOnmzgQmczfkWC70u
32
32
  helix_fhir_client_sdk/graph/graph_definition.py,sha256=FTa1GLjJ6oooAhNw7SPk-Y8duB-5WtJtnwADao-afaI,3878
33
33
  helix_fhir_client_sdk/graph/graph_link_parameters.py,sha256=3rknHL6SBgpT2A1fr-AikEFrR_9nIJUotZ82XFzROLo,599
34
34
  helix_fhir_client_sdk/graph/graph_target_parameters.py,sha256=fdYQpPZxDnyWyevuwDwxeTXOJoE2PgS5QhPaXpwtFcU,705
35
- helix_fhir_client_sdk/graph/simulated_graph_processor_mixin.py,sha256=h8K4peHcoY_4_Ln4Vz54Ls87W7bXegm4SZV2s2L4cCM,60302
35
+ helix_fhir_client_sdk/graph/simulated_graph_processor_mixin.py,sha256=vNoiTL3wgo9slfwn-a8YsIeiwZIxVWVBaCQ-Ne1_4Gk,60460
36
36
  helix_fhir_client_sdk/graph/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  helix_fhir_client_sdk/graph/test/test_graph_mixin.py,sha256=LNd4LVjryVLgzWeTXMDpsbdauXl7u3LMfj9irnNfb_k,5469
38
38
  helix_fhir_client_sdk/graph/test/test_simulate_graph_processor_mixin.py,sha256=EQDfhqJfUrP6SptXRP7ayEN7g5cZQMA00ccXzeXiSXM,46312
@@ -46,7 +46,7 @@ helix_fhir_client_sdk/responses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
46
46
  helix_fhir_client_sdk/responses/bundle_expander.py,sha256=ilR5eMgciSgzsdQvKB6bHtn9jtpvn3uS-EBz-hrahzo,1065
47
47
  helix_fhir_client_sdk/responses/fhir_client_protocol.py,sha256=IWM7LNQ1ZbgaySLGqpCwWAKyArT5HgBdNhkmSEivNMo,7100
48
48
  helix_fhir_client_sdk/responses/fhir_delete_response.py,sha256=0K11vyfZ0LtL-G61NHzDqHrZgEHjMVZr00VWpWcktZA,2941
49
- helix_fhir_client_sdk/responses/fhir_get_response.py,sha256=3PXvFoMZ7ix2ZzucIjY-49RL3foLR07dD57BdulyMGI,17657
49
+ helix_fhir_client_sdk/responses/fhir_get_response.py,sha256=v0ndKFb6o8PNqYYxGlLETzQnxGmwK3YympH4gotXpY4,17550
50
50
  helix_fhir_client_sdk/responses/fhir_merge_response.py,sha256=uvUjEGJgMDlAkcc5_LjgAsTFZqREQMlV79sbxUZwtwE,2862
51
51
  helix_fhir_client_sdk/responses/fhir_response_processor.py,sha256=fOSvqWjVI1BA6aDxxu9aqEvcKxtnFRmU2hMrgtmUCUM,34056
52
52
  helix_fhir_client_sdk/responses/fhir_update_response.py,sha256=_6zZz85KQP69WFxejlX8BBWAKWtzsMGSJjR_zqhl_m4,2727
@@ -54,14 +54,14 @@ helix_fhir_client_sdk/responses/get_result.py,sha256=hkbZeu9h-01ZZckAuckn6UDR9GX
54
54
  helix_fhir_client_sdk/responses/paging_result.py,sha256=tpmfdgrtaAmmViVxlw-EBHoe0PVjSQW9zicwRmhUVpI,1360
55
55
  helix_fhir_client_sdk/responses/resource_separator.py,sha256=jugaEkJYunx8VGVFCLwWNSjrBlI8DDm61LzSx9oR8iE,3230
56
56
  helix_fhir_client_sdk/responses/get/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
- helix_fhir_client_sdk/responses/get/fhir_get_bundle_response.py,sha256=H-e-Rp_cwU508uJqQfDDCoJR5vN9-5DYsaW7K0yTsxM,18183
57
+ helix_fhir_client_sdk/responses/get/fhir_get_bundle_response.py,sha256=ryNaHVBZOxsf3uKMhKrFIUCnpmC8h_X7d3-0mzwoqhQ,18659
58
58
  helix_fhir_client_sdk/responses/get/fhir_get_error_response.py,sha256=oNdKs_r7K4qRHD7fyeDhZz3v0wGTT2esAPPtDhxOyeI,12325
59
59
  helix_fhir_client_sdk/responses/get/fhir_get_list_by_resource_type_response.py,sha256=ssfb1IB2QTvqwWRzFs_VqPKH6mwcnWNo3iVh82M-Jso,13775
60
60
  helix_fhir_client_sdk/responses/get/fhir_get_list_response.py,sha256=KT5g6MjB9yWWUaSZpx1jK9Tm2yVmcFyZMHBBnDDAPtU,11858
61
61
  helix_fhir_client_sdk/responses/get/fhir_get_response_factory.py,sha256=OrizzAVoXvxnQbBxszeS9PUtbzg97RGNEJfD4PuOLig,6815
62
62
  helix_fhir_client_sdk/responses/get/fhir_get_single_response.py,sha256=pLjjDyxBvA_FNI7sGU2hM9urue3Bzrrwo_RcrOD5yz8,9755
63
63
  helix_fhir_client_sdk/responses/get/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
- helix_fhir_client_sdk/responses/get/test/test_get_bundle_response.py,sha256=k66eMtb0e4QcWYeF_M3TUrwCXQgD5EOcpUaijzg7a2I,19545
64
+ helix_fhir_client_sdk/responses/get/test/test_get_bundle_response.py,sha256=DF4sjy074jiro8jASavd-2hMkjIR6sIdIytzhIyBRuU,19674
65
65
  helix_fhir_client_sdk/responses/get/test/test_get_error_response.py,sha256=8P4zGgeHe-6OaSX152ixFW4W0iG2scK89O0VY_YcxuY,7613
66
66
  helix_fhir_client_sdk/responses/get/test/test_get_list_by_resource_type_response.py,sha256=eIZlhTYg5Iqh0vTmVAlesenQDyT8eCmFs1U4JngIM8w,12942
67
67
  helix_fhir_client_sdk/responses/get/test/test_get_list_response.py,sha256=vOsdgqSd5TwwgbwEX_kYvDyOnqAaKBKGAZFr4EZpGDM,14428
@@ -130,7 +130,7 @@ helix_fhir_client_sdk/validators/async_fhir_validator.py,sha256=i1BC98hZF6JhMQQz
130
130
  helix_fhir_client_sdk/validators/fhir_validator.py,sha256=HWBldSEB9yeKIcnLcV8R-LoTzwT_OMu8SchtUUBKzys,2331
131
131
  helix_fhir_client_sdk/validators/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
132
132
  helix_fhir_client_sdk/validators/test/test_async_fhir_validator.py,sha256=RmSowjPUdZee5nYuYujghxWyqJ20cu7U0lJFtFT-ZBs,3285
133
- helix_fhir_client_sdk-4.2.22.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
133
+ helix_fhir_client_sdk-4.2.24.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
134
134
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
135
135
  tests/logger_for_test.py,sha256=UC-7F6w6fDsUIYf37aRnvUdiUUVk8qkJEUSuO17NQnI,1525
136
136
  tests/test_fhir_client_clone.py,sha256=c5y1rWJ32nBSUnK1FfyymY005dNowd4Nf1xrbuQolNk,5368
@@ -213,7 +213,7 @@ tests_integration/test_emr_server_auth.py,sha256=2I4QUAspQN89uGf6JB2aVuYaBeDnRJz
213
213
  tests_integration/test_firely_fhir.py,sha256=ll6-plwQrKfdrEyfbw0wLTC1jB-Qei1Mj-81tYTl5eQ,697
214
214
  tests_integration/test_merge_vs_smart_merge_behavior.py,sha256=LrIuyxzw0YLaTjcRtG0jzy0M6xSv9qebmdBtMPDcacQ,3733
215
215
  tests_integration/test_staging_server_graph.py,sha256=5RfMxjhdX9o4-n_ZRvze4Sm8u8NjRijRLDpqiz8qD_0,7132
216
- helix_fhir_client_sdk-4.2.22.dist-info/METADATA,sha256=rixhdJJj1F1Cmo582ikppItEzirbEiOnYjYsuHW79F4,7210
217
- helix_fhir_client_sdk-4.2.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
218
- helix_fhir_client_sdk-4.2.22.dist-info/top_level.txt,sha256=BRnDS6ceQxs-4u2jXznATObgP8G2cGAerlH0ZS4sJ6M,46
219
- helix_fhir_client_sdk-4.2.22.dist-info/RECORD,,
216
+ helix_fhir_client_sdk-4.2.24.dist-info/METADATA,sha256=cRV2bCk9JHlcp77O6pjLf6xQLzhsTLBheoVsA4plp0o,7210
217
+ helix_fhir_client_sdk-4.2.24.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
218
+ helix_fhir_client_sdk-4.2.24.dist-info/top_level.txt,sha256=BRnDS6ceQxs-4u2jXznATObgP8G2cGAerlH0ZS4sJ6M,46
219
+ helix_fhir_client_sdk-4.2.24.dist-info/RECORD,,