helix.fhir.client.sdk 4.2.15__tar.gz → 4.2.16__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.
- {helix_fhir_client_sdk-4.2.15/helix.fhir.client.sdk.egg-info → helix_fhir_client_sdk-4.2.16}/PKG-INFO +39 -2
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/README.md +38 -1
- helix_fhir_client_sdk-4.2.16/VERSION +1 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16/helix.fhir.client.sdk.egg-info}/PKG-INFO +39 -2
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix.fhir.client.sdk.egg-info/SOURCES.txt +1 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/fhir_client.py +31 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/fhir_delete_mixin.py +58 -43
- helix_fhir_client_sdk-4.2.16/helix_fhir_client_sdk/fhir_merge_mixin.py +329 -0
- helix_fhir_client_sdk-4.2.16/helix_fhir_client_sdk/fhir_patch_mixin.py +145 -0
- helix_fhir_client_sdk-4.2.16/helix_fhir_client_sdk/fhir_update_mixin.py +151 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/open_telemetry/attribute_names.py +3 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/open_telemetry/span_names.py +4 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/retryable_aiohttp_client.py +31 -5
- helix_fhir_client_sdk-4.2.16/tests/async/test_retryable_client_session_management.py +155 -0
- helix_fhir_client_sdk-4.2.15/VERSION +0 -1
- helix_fhir_client_sdk-4.2.15/helix_fhir_client_sdk/fhir_merge_mixin.py +0 -307
- helix_fhir_client_sdk-4.2.15/helix_fhir_client_sdk/fhir_patch_mixin.py +0 -130
- helix_fhir_client_sdk-4.2.15/helix_fhir_client_sdk/fhir_update_mixin.py +0 -136
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/LICENSE +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/MANIFEST.in +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/Makefile +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix.fhir.client.sdk.egg-info/dependency_links.txt +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix.fhir.client.sdk.egg-info/not-zip-safe +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix.fhir.client.sdk.egg-info/requires.txt +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix.fhir.client.sdk.egg-info/top_level.txt +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/dictionary_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/dictionary_writer.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/exceptions/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/exceptions/fhir_get_exception.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/exceptions/fhir_sender_exception.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/exceptions/fhir_validation_exception.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/fhir_auth_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/fhir_bundle_appender.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/fhir_merge_resources_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/base_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/identifier_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/last_updated_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/property_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/property_missing_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/security_access_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/security_owner_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/sort_field.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/source_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/filters/version_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/function_types.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/fhir_graph_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/graph_definition.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/graph_link_parameters.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/graph_target_parameters.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/simulated_graph_processor_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/test/test_graph_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/test/test_simulate_graph_processor_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/graph/test/test_simulate_graph_processor_mixin_caching.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/open_telemetry/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/py.typed +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/queue/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/queue/request_queue_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/bundle_expander.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/fhir_client_protocol.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/fhir_delete_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/fhir_get_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/fhir_merge_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/fhir_response_processor.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/fhir_update_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/fhir_get_bundle_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/fhir_get_error_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/fhir_get_list_by_resource_type_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/fhir_get_list_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/fhir_get_response_factory.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/fhir_get_single_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/test/test_get_bundle_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/test/test_get_error_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/test/test_get_list_by_resource_type_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/test/test_get_list_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/test/test_get_response_factory.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get/test/test_get_single_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/get_result.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/merge/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/merge/base_fhir_merge_resource_response_entry.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/merge/fhir_merge_resource_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/merge/fhir_merge_resource_response_entry.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/merge/fhir_merge_response_entry_issue.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/paging_result.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/resource_separator.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_expand_or_separate_bundle_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200_non_streaming.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200_non_streaming_separate_bundle.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200_streaming.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200_streaming_separate_bundle.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200_streaming_separate_bundle_ndjson.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_404.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/test_bundle_expander.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/test_fhir_get_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/responses/test/test_resource_separator.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/structures/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/structures/get_access_token_result.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/test/test_delete_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/test/test_fhir_auth_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/test/test_fhir_bundle_appender.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/test/test_merge_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/test/test_merge_mixin_resources.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/async_parallel_processor/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/async_parallel_processor/v1/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/async_parallel_processor/v1/async_parallel_processor.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/async_runner.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/cache/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/cache/request_cache.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/cache/request_cache_entry.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/fhir_client_logger.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/fhir_helper.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/fhir_scope_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/fhir_scope_parser_result.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/fhir_server_helpers.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/hash_util.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/list_chunker.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/ndjson_chunk_streaming_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/practitioner_generator.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/retryable_aiohttp_response.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/retryable_aiohttp_url_result.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/size_calculator/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/size_calculator/size_calculator.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/test_async_runner.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/test_fhir_scope_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/test_fhir_scope_parser_can_parse_scopes.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/test_fhir_scope_parser_correct_allow.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/test_json_helpers.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/test_list_chunker.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/test_ndjson_chunk_streaming_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/test/test_retryable_aiohttp_client.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/utilities/url_checker.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/validators/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/validators/async_fhir_validator.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/validators/fhir_validator.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/validators/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/validators/test/test_async_fhir_validator.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/well_known_configuration.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/pyproject.toml +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/setup.cfg +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/setup.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/fhir_server/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/fhir_server/test_async_real_fhir_server_get_graph_large.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/fhir_server/test_async_real_fhir_server_get_patients_large.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/graph/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/graph/test_fhir_graph.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/graph/test_fhir_graph_multiple_ids.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/graph/test_fhir_graph_multiple_ids_in_batches.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_caching_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_caching_input_cache_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_caching_input_cache_if_modified_since_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_caching_scope_parser_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_separate_resources_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_with_errors_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_with_operation_outcomes_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph/test_fhir_simulated_graph_with_url_column_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph_practitioner/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_multiple_practitioner_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_multiple_practitioner_in_one_call_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_multiple_practitioner_in_one_call_async_with_request_size.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_practitioner_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_practitioner_separate_resources_async.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_bundle/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_bundle/not_expanded/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_bundle/not_expanded/test_fhir_client_bundle_not_expanded.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_bundle/not_separated/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_bundle/not_separated/test_fhir_client_bundle_not_separated.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_bundle/separated/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_bundle/separated/test_fhir_client_bundle_separated.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_fetch_response_in_chunks.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_by_id.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_by_identifier_missing.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_delete.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_list.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_list_auth_fail.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_list_auth_fail_retry.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_list_auth_fail_retry_custom_refresh_function.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_list_resource_streaming.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_list_streaming.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_merge.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_merge_with_validate.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_fhir_client_patient_update.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_real_fhir_server_get_patients.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_async_real_fhir_server_get_patients_error.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_benchmark_compress.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/async/test_benchmark_merge.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/logger_for_test.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/graph/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/graph/test_fhir_graph.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_bundle/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_bundle/not_expanded/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_bundle/not_expanded/test_fhir_client_bundle_not_expanded.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_bundle/not_separated/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_bundle/not_separated/test_fhir_client_bundle_not_separated.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_bundle/separated/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_bundle/separated/test_fhir_client_bundle_separated.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_logs_not_contains_secret_information.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_patient_by_id.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_patient_delete.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_patient_list.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_patient_list_auth_fail.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_patient_list_auth_fail_retry.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_patient_merge.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_patient_update.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/sync/test_fhir_client_patient_update_patch.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/test_fhir_client_clone.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests/test_get_nested_property.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_aetna_server_auth.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_aetna_server_auth_aiohttp.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_aetna_server_auth_httpx.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_dev_server_auth.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_dev_server_no_auth.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_emr_server_auth.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_firely_fhir.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_merge_vs_smart_merge_behavior.py +0 -0
- {helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/tests_integration/test_staging_server_graph.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: helix.fhir.client.sdk
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.16
|
|
4
4
|
Summary: helix.fhir.client.sdk
|
|
5
5
|
Home-page: https://github.com/icanbwell/helix.fhir.client.sdk
|
|
6
6
|
Author: Imran Qureshi
|
|
@@ -111,9 +111,46 @@ response: Optional[FhirGetResponse] = await FhirGetResponse.from_async_generator
|
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
# Data Streaming
|
|
114
|
-
For FHIR servers that support data streaming (e.g., b.well FHIR server), you can just set the `use_data_streaming` parameter to stream the data as it
|
|
114
|
+
For FHIR servers that support data streaming (e.g., b.well FHIR server), you can just set the `use_data_streaming` parameter to stream the data as it is received.
|
|
115
115
|
The data will be streamed in AsyncGenerators as described above.
|
|
116
116
|
|
|
117
|
+
# Persistent Sessions (Connection Reuse)
|
|
118
|
+
By default, the SDK creates a new HTTP session for each request. For better performance (~4× faster),
|
|
119
|
+
you can use persistent sessions to reuse connections across multiple requests.
|
|
120
|
+
|
|
121
|
+
**Important**: When you provide a custom session factory using `use_http_session()`, YOU are responsible
|
|
122
|
+
for managing the session lifecycle, including closing it when done. The SDK will NOT automatically close
|
|
123
|
+
user-provided sessions.
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
import aiohttp
|
|
127
|
+
from helix_fhir_client_sdk.fhir_client import FhirClient
|
|
128
|
+
|
|
129
|
+
# Create a persistent session for connection reuse
|
|
130
|
+
session = aiohttp.ClientSession()
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
# Configure FhirClient to use persistent session
|
|
134
|
+
fhir_client = (
|
|
135
|
+
FhirClient()
|
|
136
|
+
.url("https://fhir.example.com")
|
|
137
|
+
.resource("Patient")
|
|
138
|
+
.use_http_session(lambda: session) # User provides session factory
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Multiple requests reuse the same connection (~4× performance boost)
|
|
142
|
+
response1 = await fhir_client.get_async()
|
|
143
|
+
response2 = await fhir_client.clone().resource("Observation").get_async()
|
|
144
|
+
|
|
145
|
+
finally:
|
|
146
|
+
# User must close the session when done
|
|
147
|
+
await session.close()
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Session Lifecycle Rules**:
|
|
151
|
+
- **No custom factory** (default): SDK creates and closes the session automatically
|
|
152
|
+
- **Custom factory provided**: User is responsible for closing the session
|
|
153
|
+
|
|
117
154
|
# Storage Compression
|
|
118
155
|
The FHIR client SDK supports two types of compression:
|
|
119
156
|
|
|
@@ -75,9 +75,46 @@ response: Optional[FhirGetResponse] = await FhirGetResponse.from_async_generator
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
# Data Streaming
|
|
78
|
-
For FHIR servers that support data streaming (e.g., b.well FHIR server), you can just set the `use_data_streaming` parameter to stream the data as it
|
|
78
|
+
For FHIR servers that support data streaming (e.g., b.well FHIR server), you can just set the `use_data_streaming` parameter to stream the data as it is received.
|
|
79
79
|
The data will be streamed in AsyncGenerators as described above.
|
|
80
80
|
|
|
81
|
+
# Persistent Sessions (Connection Reuse)
|
|
82
|
+
By default, the SDK creates a new HTTP session for each request. For better performance (~4× faster),
|
|
83
|
+
you can use persistent sessions to reuse connections across multiple requests.
|
|
84
|
+
|
|
85
|
+
**Important**: When you provide a custom session factory using `use_http_session()`, YOU are responsible
|
|
86
|
+
for managing the session lifecycle, including closing it when done. The SDK will NOT automatically close
|
|
87
|
+
user-provided sessions.
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
import aiohttp
|
|
91
|
+
from helix_fhir_client_sdk.fhir_client import FhirClient
|
|
92
|
+
|
|
93
|
+
# Create a persistent session for connection reuse
|
|
94
|
+
session = aiohttp.ClientSession()
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
# Configure FhirClient to use persistent session
|
|
98
|
+
fhir_client = (
|
|
99
|
+
FhirClient()
|
|
100
|
+
.url("https://fhir.example.com")
|
|
101
|
+
.resource("Patient")
|
|
102
|
+
.use_http_session(lambda: session) # User provides session factory
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Multiple requests reuse the same connection (~4× performance boost)
|
|
106
|
+
response1 = await fhir_client.get_async()
|
|
107
|
+
response2 = await fhir_client.clone().resource("Observation").get_async()
|
|
108
|
+
|
|
109
|
+
finally:
|
|
110
|
+
# User must close the session when done
|
|
111
|
+
await session.close()
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Session Lifecycle Rules**:
|
|
115
|
+
- **No custom factory** (default): SDK creates and closes the session automatically
|
|
116
|
+
- **Custom factory provided**: User is responsible for closing the session
|
|
117
|
+
|
|
81
118
|
# Storage Compression
|
|
82
119
|
The FHIR client SDK supports two types of compression:
|
|
83
120
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.2.16
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: helix.fhir.client.sdk
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.16
|
|
4
4
|
Summary: helix.fhir.client.sdk
|
|
5
5
|
Home-page: https://github.com/icanbwell/helix.fhir.client.sdk
|
|
6
6
|
Author: Imran Qureshi
|
|
@@ -111,9 +111,46 @@ response: Optional[FhirGetResponse] = await FhirGetResponse.from_async_generator
|
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
# Data Streaming
|
|
114
|
-
For FHIR servers that support data streaming (e.g., b.well FHIR server), you can just set the `use_data_streaming` parameter to stream the data as it
|
|
114
|
+
For FHIR servers that support data streaming (e.g., b.well FHIR server), you can just set the `use_data_streaming` parameter to stream the data as it is received.
|
|
115
115
|
The data will be streamed in AsyncGenerators as described above.
|
|
116
116
|
|
|
117
|
+
# Persistent Sessions (Connection Reuse)
|
|
118
|
+
By default, the SDK creates a new HTTP session for each request. For better performance (~4× faster),
|
|
119
|
+
you can use persistent sessions to reuse connections across multiple requests.
|
|
120
|
+
|
|
121
|
+
**Important**: When you provide a custom session factory using `use_http_session()`, YOU are responsible
|
|
122
|
+
for managing the session lifecycle, including closing it when done. The SDK will NOT automatically close
|
|
123
|
+
user-provided sessions.
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
import aiohttp
|
|
127
|
+
from helix_fhir_client_sdk.fhir_client import FhirClient
|
|
128
|
+
|
|
129
|
+
# Create a persistent session for connection reuse
|
|
130
|
+
session = aiohttp.ClientSession()
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
# Configure FhirClient to use persistent session
|
|
134
|
+
fhir_client = (
|
|
135
|
+
FhirClient()
|
|
136
|
+
.url("https://fhir.example.com")
|
|
137
|
+
.resource("Patient")
|
|
138
|
+
.use_http_session(lambda: session) # User provides session factory
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Multiple requests reuse the same connection (~4× performance boost)
|
|
142
|
+
response1 = await fhir_client.get_async()
|
|
143
|
+
response2 = await fhir_client.clone().resource("Observation").get_async()
|
|
144
|
+
|
|
145
|
+
finally:
|
|
146
|
+
# User must close the session when done
|
|
147
|
+
await session.close()
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Session Lifecycle Rules**:
|
|
151
|
+
- **No custom factory** (default): SDK creates and closes the session automatically
|
|
152
|
+
- **Custom factory provided**: User is responsible for closing the session
|
|
153
|
+
|
|
117
154
|
# Storage Compression
|
|
118
155
|
The FHIR client SDK supports two types of compression:
|
|
119
156
|
|
|
@@ -166,6 +166,7 @@ tests/async/test_async_real_fhir_server_get_patients.py
|
|
|
166
166
|
tests/async/test_async_real_fhir_server_get_patients_error.py
|
|
167
167
|
tests/async/test_benchmark_compress.py
|
|
168
168
|
tests/async/test_benchmark_merge.py
|
|
169
|
+
tests/async/test_retryable_client_session_management.py
|
|
169
170
|
tests/async/fhir_server/__init__.py
|
|
170
171
|
tests/async/fhir_server/test_async_real_fhir_server_get_graph_large.py
|
|
171
172
|
tests/async/fhir_server/test_async_real_fhir_server_get_patients_large.py
|
{helix_fhir_client_sdk-4.2.15 → helix_fhir_client_sdk-4.2.16}/helix_fhir_client_sdk/fhir_client.py
RENAMED
|
@@ -488,6 +488,37 @@ class FhirClient(
|
|
|
488
488
|
implementation. This allows for custom session management, connection pooling,
|
|
489
489
|
or persistent session support.
|
|
490
490
|
|
|
491
|
+
**Important**: When you provide a custom session factory, YOU are responsible
|
|
492
|
+
for managing the session lifecycle, including closing it when done. The SDK
|
|
493
|
+
will NOT automatically close user-provided sessions.
|
|
494
|
+
|
|
495
|
+
Example with a persistent session for connection reuse (~4× performance boost):
|
|
496
|
+
|
|
497
|
+
.. code-block:: python
|
|
498
|
+
|
|
499
|
+
import aiohttp
|
|
500
|
+
from helix_fhir_client_sdk.fhir_client import FhirClient
|
|
501
|
+
|
|
502
|
+
# Create persistent session
|
|
503
|
+
session = aiohttp.ClientSession()
|
|
504
|
+
|
|
505
|
+
try:
|
|
506
|
+
# Configure FhirClient to use persistent session
|
|
507
|
+
fhir_client = (
|
|
508
|
+
FhirClient()
|
|
509
|
+
.url("http://fhir.example.com")
|
|
510
|
+
.resource("Patient")
|
|
511
|
+
.use_http_session(lambda: session) # User provides session
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
# Multiple requests reuse the same connection
|
|
515
|
+
response1 = await fhir_client.get_async()
|
|
516
|
+
response2 = await fhir_client.clone().resource("Observation").get_async()
|
|
517
|
+
|
|
518
|
+
finally:
|
|
519
|
+
# User must close the session when done
|
|
520
|
+
await session.close()
|
|
521
|
+
|
|
491
522
|
:param fn_create_http_session: callable that returns a ClientSession, or None to use default
|
|
492
523
|
"""
|
|
493
524
|
self._fn_create_http_session = fn_create_http_session
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
2
|
|
|
3
3
|
from furl import furl
|
|
4
|
+
from opentelemetry import trace
|
|
5
|
+
from opentelemetry.trace import Status, StatusCode
|
|
4
6
|
|
|
7
|
+
from helix_fhir_client_sdk.open_telemetry.attribute_names import FhirClientSdkOpenTelemetryAttributeNames
|
|
8
|
+
from helix_fhir_client_sdk.open_telemetry.span_names import FhirClientSdkOpenTelemetrySpanNames
|
|
5
9
|
from helix_fhir_client_sdk.responses.fhir_client_protocol import FhirClientProtocol
|
|
6
10
|
from helix_fhir_client_sdk.responses.fhir_delete_response import FhirDeleteResponse
|
|
7
11
|
from helix_fhir_client_sdk.structures.get_access_token_result import (
|
|
@@ -15,6 +19,8 @@ from helix_fhir_client_sdk.utilities.retryable_aiohttp_response import (
|
|
|
15
19
|
RetryableAioHttpResponse,
|
|
16
20
|
)
|
|
17
21
|
|
|
22
|
+
TRACER = trace.get_tracer(__name__)
|
|
23
|
+
|
|
18
24
|
|
|
19
25
|
class FhirDeleteMixin(FhirClientProtocol):
|
|
20
26
|
async def delete_async(self) -> FhirDeleteResponse:
|
|
@@ -29,50 +35,59 @@ class FhirDeleteMixin(FhirClientProtocol):
|
|
|
29
35
|
raise ValueError("delete requires the ID of FHIR object to delete")
|
|
30
36
|
if not self._resource:
|
|
31
37
|
raise ValueError("delete requires a FHIR resource type")
|
|
32
|
-
full_uri: furl = furl(self._url)
|
|
33
|
-
full_uri /= self._resource
|
|
34
|
-
full_uri /= id_list
|
|
35
|
-
# setup retry
|
|
36
|
-
# set up headers
|
|
37
|
-
headers: dict[str, str] = {}
|
|
38
|
-
headers.update(self._additional_request_headers)
|
|
39
|
-
self._internal_logger.debug(f"Request headers: {headers}")
|
|
40
|
-
|
|
41
|
-
access_token_result: GetAccessTokenResult = await self.get_access_token_async()
|
|
42
|
-
access_token: str | None = access_token_result.access_token
|
|
43
|
-
# set access token in request if present
|
|
44
|
-
if access_token:
|
|
45
|
-
headers["Authorization"] = f"Bearer {access_token}"
|
|
46
|
-
|
|
47
|
-
async with RetryableAioHttpClient(
|
|
48
|
-
fn_get_session=lambda: self.create_http_session(),
|
|
49
|
-
refresh_token_func=self._refresh_token_function,
|
|
50
|
-
retries=self._retry_count,
|
|
51
|
-
exclude_status_codes_from_retry=self._exclude_status_codes_from_retry,
|
|
52
|
-
use_data_streaming=self._use_data_streaming,
|
|
53
|
-
compress=False,
|
|
54
|
-
throw_exception_on_error=self._throw_exception_on_error,
|
|
55
|
-
log_all_url_results=self._log_all_response_urls,
|
|
56
|
-
access_token=self._access_token,
|
|
57
|
-
access_token_expiry_date=self._access_token_expiry_date,
|
|
58
|
-
tracer_request_func=self._trace_request_function,
|
|
59
|
-
) as client:
|
|
60
|
-
response: RetryableAioHttpResponse = await client.delete(url=full_uri.tostr(), headers=headers)
|
|
61
|
-
request_id = response.response_headers.get("X-Request-ID", None)
|
|
62
|
-
self._internal_logger.debug(f"X-Request-ID={request_id}")
|
|
63
|
-
if response.status == 200:
|
|
64
|
-
if self._logger:
|
|
65
|
-
self._logger.info(f"Successfully deleted: {full_uri}")
|
|
66
38
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
39
|
+
with TRACER.start_as_current_span(FhirClientSdkOpenTelemetrySpanNames.DELETE) as span:
|
|
40
|
+
span.set_attribute(FhirClientSdkOpenTelemetryAttributeNames.URL, self._url or "")
|
|
41
|
+
span.set_attribute(FhirClientSdkOpenTelemetryAttributeNames.RESOURCE, self._resource or "")
|
|
42
|
+
try:
|
|
43
|
+
full_uri: furl = furl(self._url)
|
|
44
|
+
full_uri /= self._resource
|
|
45
|
+
full_uri /= id_list
|
|
46
|
+
# setup retry
|
|
47
|
+
# set up headers
|
|
48
|
+
headers: dict[str, str] = {}
|
|
49
|
+
headers.update(self._additional_request_headers)
|
|
50
|
+
self._internal_logger.debug(f"Request headers: {headers}")
|
|
51
|
+
|
|
52
|
+
access_token_result: GetAccessTokenResult = await self.get_access_token_async()
|
|
53
|
+
access_token: str | None = access_token_result.access_token
|
|
54
|
+
# set access token in request if present
|
|
55
|
+
if access_token:
|
|
56
|
+
headers["Authorization"] = f"Bearer {access_token}"
|
|
57
|
+
|
|
58
|
+
async with RetryableAioHttpClient(
|
|
59
|
+
fn_get_session=lambda: self.create_http_session(),
|
|
60
|
+
refresh_token_func=self._refresh_token_function,
|
|
61
|
+
retries=self._retry_count,
|
|
62
|
+
exclude_status_codes_from_retry=self._exclude_status_codes_from_retry,
|
|
63
|
+
use_data_streaming=self._use_data_streaming,
|
|
64
|
+
compress=False,
|
|
65
|
+
throw_exception_on_error=self._throw_exception_on_error,
|
|
66
|
+
log_all_url_results=self._log_all_response_urls,
|
|
67
|
+
access_token=self._access_token,
|
|
68
|
+
access_token_expiry_date=self._access_token_expiry_date,
|
|
69
|
+
tracer_request_func=self._trace_request_function,
|
|
70
|
+
) as client:
|
|
71
|
+
response: RetryableAioHttpResponse = await client.delete(url=full_uri.tostr(), headers=headers)
|
|
72
|
+
request_id = response.response_headers.get("X-Request-ID", None)
|
|
73
|
+
self._internal_logger.debug(f"X-Request-ID={request_id}")
|
|
74
|
+
if response.status == 200:
|
|
75
|
+
if self._logger:
|
|
76
|
+
self._logger.info(f"Successfully deleted: {full_uri}")
|
|
77
|
+
|
|
78
|
+
return FhirDeleteResponse(
|
|
79
|
+
request_id=request_id,
|
|
80
|
+
url=full_uri.tostr(),
|
|
81
|
+
responses=await response.get_text_async(),
|
|
82
|
+
error=f"{response.status}" if not response.status == 200 else None,
|
|
83
|
+
access_token=access_token,
|
|
84
|
+
status=response.status,
|
|
85
|
+
resource_type=self._resource,
|
|
86
|
+
)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
span.record_exception(e)
|
|
89
|
+
span.set_status(Status(StatusCode.ERROR, str(e)))
|
|
90
|
+
raise
|
|
76
91
|
|
|
77
92
|
def delete(self) -> FhirDeleteResponse:
|
|
78
93
|
"""
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
from collections.abc import AsyncGenerator, Generator
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
cast,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
import requests
|
|
10
|
+
from furl import furl
|
|
11
|
+
from opentelemetry import trace
|
|
12
|
+
from opentelemetry.trace import Status, StatusCode
|
|
13
|
+
|
|
14
|
+
from helix_fhir_client_sdk.dictionary_writer import convert_dict_to_str
|
|
15
|
+
from helix_fhir_client_sdk.exceptions.fhir_sender_exception import FhirSenderException
|
|
16
|
+
from helix_fhir_client_sdk.exceptions.fhir_validation_exception import (
|
|
17
|
+
FhirValidationException,
|
|
18
|
+
)
|
|
19
|
+
from helix_fhir_client_sdk.open_telemetry.attribute_names import FhirClientSdkOpenTelemetryAttributeNames
|
|
20
|
+
from helix_fhir_client_sdk.open_telemetry.span_names import FhirClientSdkOpenTelemetrySpanNames
|
|
21
|
+
from helix_fhir_client_sdk.responses.fhir_client_protocol import FhirClientProtocol
|
|
22
|
+
from helix_fhir_client_sdk.responses.fhir_merge_response import FhirMergeResponse
|
|
23
|
+
from helix_fhir_client_sdk.structures.get_access_token_result import (
|
|
24
|
+
GetAccessTokenResult,
|
|
25
|
+
)
|
|
26
|
+
from helix_fhir_client_sdk.utilities.async_runner import AsyncRunner
|
|
27
|
+
from helix_fhir_client_sdk.utilities.fhir_client_logger import FhirClientLogger
|
|
28
|
+
from helix_fhir_client_sdk.utilities.list_chunker import ListChunker
|
|
29
|
+
from helix_fhir_client_sdk.utilities.retryable_aiohttp_client import (
|
|
30
|
+
RetryableAioHttpClient,
|
|
31
|
+
)
|
|
32
|
+
from helix_fhir_client_sdk.utilities.retryable_aiohttp_response import (
|
|
33
|
+
RetryableAioHttpResponse,
|
|
34
|
+
)
|
|
35
|
+
from helix_fhir_client_sdk.validators.async_fhir_validator import AsyncFhirValidator
|
|
36
|
+
|
|
37
|
+
TRACER = trace.get_tracer(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class FhirMergeMixin(FhirClientProtocol):
|
|
41
|
+
async def validate_content(
|
|
42
|
+
self,
|
|
43
|
+
*,
|
|
44
|
+
errors: list[dict[str, Any]],
|
|
45
|
+
resource_json_list_incoming: list[dict[str, Any]],
|
|
46
|
+
) -> list[dict[str, Any]]:
|
|
47
|
+
resource_json_list_clean: list[dict[str, Any]] = []
|
|
48
|
+
assert self._validation_server_url
|
|
49
|
+
# if there is only resource then just validate that individually
|
|
50
|
+
if len(resource_json_list_incoming) == 1:
|
|
51
|
+
resource_json: dict[str, Any] = resource_json_list_incoming[0]
|
|
52
|
+
try:
|
|
53
|
+
access_token_result: GetAccessTokenResult = await self.get_access_token_async()
|
|
54
|
+
access_token: str | None = access_token_result.access_token
|
|
55
|
+
|
|
56
|
+
await AsyncFhirValidator.validate_fhir_resource(
|
|
57
|
+
fn_get_session=lambda: self.create_http_session(),
|
|
58
|
+
json_data=json.dumps(resource_json),
|
|
59
|
+
resource_name=cast(str | None, resource_json.get("resourceType")) or self._resource or "",
|
|
60
|
+
validation_server_url=self._validation_server_url,
|
|
61
|
+
access_token=access_token,
|
|
62
|
+
)
|
|
63
|
+
resource_json_list_clean.append(resource_json)
|
|
64
|
+
except FhirValidationException as e:
|
|
65
|
+
errors.append(
|
|
66
|
+
{
|
|
67
|
+
"id": (resource_json.get("id") if resource_json.get("id") else None),
|
|
68
|
+
"resourceType": resource_json.get("resourceType"),
|
|
69
|
+
"issue": e.issue,
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
for resource_json in resource_json_list_incoming:
|
|
74
|
+
try:
|
|
75
|
+
access_token_result1: GetAccessTokenResult = await self.get_access_token_async()
|
|
76
|
+
access_token1: str | None = access_token_result1.access_token
|
|
77
|
+
await AsyncFhirValidator.validate_fhir_resource(
|
|
78
|
+
fn_get_session=lambda: self.create_http_session(),
|
|
79
|
+
json_data=json.dumps(resource_json),
|
|
80
|
+
resource_name=resource_json.get("resourceType") or self._resource or "",
|
|
81
|
+
validation_server_url=self._validation_server_url,
|
|
82
|
+
access_token=access_token1,
|
|
83
|
+
)
|
|
84
|
+
resource_json_list_clean.append(resource_json)
|
|
85
|
+
except FhirValidationException as e:
|
|
86
|
+
errors.append(
|
|
87
|
+
{
|
|
88
|
+
"id": resource_json.get("id"),
|
|
89
|
+
"resourceType": resource_json.get("resourceType"),
|
|
90
|
+
"issue": e.issue,
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
return resource_json_list_clean
|
|
94
|
+
|
|
95
|
+
async def merge_async(
|
|
96
|
+
self,
|
|
97
|
+
*,
|
|
98
|
+
id_: str | None = None,
|
|
99
|
+
json_data_list: list[str],
|
|
100
|
+
batch_size: int | None = None,
|
|
101
|
+
) -> AsyncGenerator[FhirMergeResponse, None]:
|
|
102
|
+
"""
|
|
103
|
+
Calls $merge function on FHIR server
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
:param json_data_list: list of resources to send
|
|
107
|
+
:param id_: id of the resource to merge
|
|
108
|
+
:param batch_size: size of each batch
|
|
109
|
+
:return: response
|
|
110
|
+
"""
|
|
111
|
+
assert self._url, "No FHIR server url was set"
|
|
112
|
+
assert isinstance(json_data_list, list), "This function requires a list"
|
|
113
|
+
|
|
114
|
+
with TRACER.start_as_current_span(FhirClientSdkOpenTelemetrySpanNames.MERGE) as span:
|
|
115
|
+
span.set_attribute(FhirClientSdkOpenTelemetryAttributeNames.URL, self._url or "")
|
|
116
|
+
span.set_attribute(FhirClientSdkOpenTelemetryAttributeNames.RESOURCE, self._resource or "")
|
|
117
|
+
span.set_attribute(FhirClientSdkOpenTelemetryAttributeNames.BATCH_SIZE, batch_size or 0)
|
|
118
|
+
span.set_attribute(FhirClientSdkOpenTelemetryAttributeNames.JSON_DATA_COUNT, len(json_data_list))
|
|
119
|
+
try:
|
|
120
|
+
self._internal_logger.debug(
|
|
121
|
+
f"Calling $merge on {self._url} with client_id={self._client_id} and scopes={self._auth_scopes}"
|
|
122
|
+
)
|
|
123
|
+
instance_variables_text = convert_dict_to_str(FhirClientLogger.get_variables_to_log(vars(self)))
|
|
124
|
+
if self._internal_logger:
|
|
125
|
+
self._internal_logger.info(f"parameters: {instance_variables_text}")
|
|
126
|
+
else:
|
|
127
|
+
self._internal_logger.info(f"LOGLEVEL (InternalLogger): {self._log_level}")
|
|
128
|
+
self._internal_logger.info(f"parameters: {instance_variables_text}")
|
|
129
|
+
|
|
130
|
+
request_id: str | None = None
|
|
131
|
+
response_status: int | None = None
|
|
132
|
+
full_uri: furl = furl(self._url)
|
|
133
|
+
assert self._resource
|
|
134
|
+
full_uri /= self._resource
|
|
135
|
+
headers = {"Content-Type": "application/fhir+json"}
|
|
136
|
+
headers.update(self._additional_request_headers)
|
|
137
|
+
self._internal_logger.debug(f"Request headers: {headers}")
|
|
138
|
+
|
|
139
|
+
responses: list[dict[str, Any]] = []
|
|
140
|
+
start_time: float = time.time()
|
|
141
|
+
# set access token in request if present
|
|
142
|
+
access_token_result: GetAccessTokenResult = await self.get_access_token_async()
|
|
143
|
+
access_token: str | None = access_token_result.access_token
|
|
144
|
+
if access_token:
|
|
145
|
+
headers["Authorization"] = f"Bearer {access_token}"
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
resource_json_list_incoming: list[dict[str, Any]] = [
|
|
149
|
+
json.loads(json_data) for json_data in json_data_list
|
|
150
|
+
]
|
|
151
|
+
resource_json_list_clean: list[dict[str, Any]]
|
|
152
|
+
errors: list[dict[str, Any]] = []
|
|
153
|
+
if self._validation_server_url:
|
|
154
|
+
resource_json_list_clean = await self.validate_content(
|
|
155
|
+
errors=errors,
|
|
156
|
+
resource_json_list_incoming=resource_json_list_incoming,
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
resource_json_list_clean = resource_json_list_incoming
|
|
160
|
+
|
|
161
|
+
if len(resource_json_list_clean) > 0:
|
|
162
|
+
chunks: Generator[list[dict[str, Any]], None, None] = ListChunker.divide_into_chunks(
|
|
163
|
+
resource_json_list_clean, chunk_size=batch_size
|
|
164
|
+
)
|
|
165
|
+
chunk: list[dict[str, Any]]
|
|
166
|
+
for chunk in chunks:
|
|
167
|
+
resource_uri: furl = full_uri.copy()
|
|
168
|
+
# if there is only item in the list then send it instead of having it in a list
|
|
169
|
+
json_payload: str = json.dumps(chunk[0]) if len(chunk) == 1 else json.dumps(chunk)
|
|
170
|
+
# json_payload_bytes: str = json_payload
|
|
171
|
+
obj_id = id_ or 1 # TODO: remove this once the node fhir accepts merge without a parameter
|
|
172
|
+
assert obj_id
|
|
173
|
+
|
|
174
|
+
if obj_id is not None and str(obj_id).strip():
|
|
175
|
+
resource_uri.path.segments.append(str(obj_id))
|
|
176
|
+
# Always append $merge
|
|
177
|
+
resource_uri.path.segments.append("$merge")
|
|
178
|
+
|
|
179
|
+
# Conditionally add the query parameter
|
|
180
|
+
if self._smart_merge is False:
|
|
181
|
+
resource_uri.add({"smartMerge": "false"})
|
|
182
|
+
|
|
183
|
+
response_text: str | None = None
|
|
184
|
+
try:
|
|
185
|
+
async with RetryableAioHttpClient(
|
|
186
|
+
fn_get_session=lambda: self.create_http_session(),
|
|
187
|
+
refresh_token_func=self._refresh_token_function,
|
|
188
|
+
tracer_request_func=self._trace_request_function,
|
|
189
|
+
retries=self._retry_count,
|
|
190
|
+
exclude_status_codes_from_retry=self._exclude_status_codes_from_retry,
|
|
191
|
+
use_data_streaming=self._use_data_streaming,
|
|
192
|
+
send_data_as_chunked=self._send_data_as_chunked,
|
|
193
|
+
compress=self._compress,
|
|
194
|
+
throw_exception_on_error=self._throw_exception_on_error,
|
|
195
|
+
log_all_url_results=self._log_all_response_urls,
|
|
196
|
+
access_token=self._access_token,
|
|
197
|
+
access_token_expiry_date=self._access_token_expiry_date,
|
|
198
|
+
) as client:
|
|
199
|
+
# should we check if it exists and do a POST then?
|
|
200
|
+
response: RetryableAioHttpResponse = await client.post(
|
|
201
|
+
url=resource_uri.url,
|
|
202
|
+
data=json_payload,
|
|
203
|
+
headers=headers,
|
|
204
|
+
)
|
|
205
|
+
response_status = response.status
|
|
206
|
+
request_id = response.response_headers.get("X-Request-ID", None)
|
|
207
|
+
self._internal_logger.debug(f"X-Request-ID={request_id}")
|
|
208
|
+
if response and response.status == 200:
|
|
209
|
+
response_text = await response.get_text_async()
|
|
210
|
+
if response_text:
|
|
211
|
+
try:
|
|
212
|
+
raw_response: list[dict[str, Any]] | dict[str, Any] = json.loads(
|
|
213
|
+
response_text
|
|
214
|
+
)
|
|
215
|
+
if isinstance(raw_response, list):
|
|
216
|
+
responses = raw_response
|
|
217
|
+
else:
|
|
218
|
+
responses = [raw_response]
|
|
219
|
+
except ValueError as e:
|
|
220
|
+
responses = [{"issue": str(e)}]
|
|
221
|
+
else:
|
|
222
|
+
responses = []
|
|
223
|
+
yield FhirMergeResponse(
|
|
224
|
+
request_id=request_id,
|
|
225
|
+
url=resource_uri.url,
|
|
226
|
+
responses=responses + errors,
|
|
227
|
+
error=(json.dumps(responses + errors) if response_status != 200 else None),
|
|
228
|
+
access_token=self._access_token,
|
|
229
|
+
status=response_status if response_status else 500,
|
|
230
|
+
json_data=json_payload,
|
|
231
|
+
)
|
|
232
|
+
else: # other HTTP errors
|
|
233
|
+
self._internal_logger.info(
|
|
234
|
+
f"POST response for {resource_uri.url}: {response.status}"
|
|
235
|
+
)
|
|
236
|
+
response_text = await response.get_text_async()
|
|
237
|
+
yield FhirMergeResponse(
|
|
238
|
+
request_id=request_id,
|
|
239
|
+
url=resource_uri.url or self._url or "",
|
|
240
|
+
json_data=json_payload,
|
|
241
|
+
responses=[
|
|
242
|
+
{
|
|
243
|
+
"issue": [
|
|
244
|
+
{
|
|
245
|
+
"severity": "error",
|
|
246
|
+
"code": "exception",
|
|
247
|
+
"diagnostics": response_text,
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
],
|
|
252
|
+
error=(json.dumps(response_text) if response_text else None),
|
|
253
|
+
access_token=self._access_token,
|
|
254
|
+
status=response.status if response.status else 500,
|
|
255
|
+
)
|
|
256
|
+
except requests.exceptions.HTTPError as e:
|
|
257
|
+
raise FhirSenderException(
|
|
258
|
+
request_id=request_id,
|
|
259
|
+
url=resource_uri.url,
|
|
260
|
+
headers=headers,
|
|
261
|
+
json_data=json_payload,
|
|
262
|
+
response_text=response_text,
|
|
263
|
+
response_status_code=response_status,
|
|
264
|
+
exception=e,
|
|
265
|
+
variables=FhirClientLogger.get_variables_to_log(vars(self)),
|
|
266
|
+
message=f"HttpError: {e}",
|
|
267
|
+
elapsed_time=time.time() - start_time,
|
|
268
|
+
) from e
|
|
269
|
+
except Exception as e:
|
|
270
|
+
raise FhirSenderException(
|
|
271
|
+
request_id=request_id,
|
|
272
|
+
url=resource_uri.url,
|
|
273
|
+
headers=headers,
|
|
274
|
+
json_data=json_payload,
|
|
275
|
+
response_text=response_text,
|
|
276
|
+
response_status_code=response_status,
|
|
277
|
+
exception=e,
|
|
278
|
+
variables=FhirClientLogger.get_variables_to_log(vars(self)),
|
|
279
|
+
message=f"Unknown Error: {e}",
|
|
280
|
+
elapsed_time=time.time() - start_time,
|
|
281
|
+
) from e
|
|
282
|
+
else:
|
|
283
|
+
json_payload = json.dumps(json_data_list)
|
|
284
|
+
yield FhirMergeResponse(
|
|
285
|
+
request_id=request_id,
|
|
286
|
+
url=full_uri.url,
|
|
287
|
+
responses=responses + errors,
|
|
288
|
+
error=(json.dumps(responses + errors) if response_status != 200 else None),
|
|
289
|
+
access_token=self._access_token,
|
|
290
|
+
status=response_status if response_status else 500,
|
|
291
|
+
json_data=json_payload,
|
|
292
|
+
)
|
|
293
|
+
except AssertionError as e:
|
|
294
|
+
if self._logger:
|
|
295
|
+
self._logger.error(
|
|
296
|
+
Exception(
|
|
297
|
+
f"Assertion: FHIR send failed: {str(e)} for resource: {json_data_list}. "
|
|
298
|
+
+ f"variables={convert_dict_to_str(FhirClientLogger.get_variables_to_log(vars(self)))}"
|
|
299
|
+
)
|
|
300
|
+
)
|
|
301
|
+
raise e
|
|
302
|
+
except Exception as e:
|
|
303
|
+
span.record_exception(e)
|
|
304
|
+
span.set_status(Status(StatusCode.ERROR, str(e)))
|
|
305
|
+
raise
|
|
306
|
+
|
|
307
|
+
def merge(
|
|
308
|
+
self,
|
|
309
|
+
*,
|
|
310
|
+
id_: str | None = None,
|
|
311
|
+
json_data_list: list[str],
|
|
312
|
+
batch_size: int | None = None,
|
|
313
|
+
) -> FhirMergeResponse | None:
|
|
314
|
+
"""
|
|
315
|
+
Calls $merge function on FHIR server
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
:param json_data_list: list of resources to send
|
|
319
|
+
:param batch_size: size of each batch
|
|
320
|
+
:param id_: id of the resource to merge
|
|
321
|
+
:return: response
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
result: FhirMergeResponse | None = AsyncRunner.run(
|
|
325
|
+
FhirMergeResponse.from_async_generator(
|
|
326
|
+
self.merge_async(id_=id_, json_data_list=json_data_list, batch_size=batch_size)
|
|
327
|
+
)
|
|
328
|
+
)
|
|
329
|
+
return result
|