helix.fhir.client.sdk 4.2.20__tar.gz → 4.2.22__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.20/helix.fhir.client.sdk.egg-info → helix_fhir_client_sdk-4.2.22}/PKG-INFO +1 -1
- helix_fhir_client_sdk-4.2.22/VERSION +1 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22/helix.fhir.client.sdk.egg-info}/PKG-INFO +1 -1
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/simulated_graph_processor_mixin.py +25 -147
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/fhir_get_response.py +3 -2
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/fhir_get_bundle_response.py +28 -62
- helix_fhir_client_sdk-4.2.22/helix_fhir_client_sdk/responses/resource_separator.py +72 -0
- helix_fhir_client_sdk-4.2.20/VERSION +0 -1
- helix_fhir_client_sdk-4.2.20/helix_fhir_client_sdk/responses/resource_separator.py +0 -67
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/LICENSE +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/MANIFEST.in +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/Makefile +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/README.md +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix.fhir.client.sdk.egg-info/SOURCES.txt +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix.fhir.client.sdk.egg-info/dependency_links.txt +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix.fhir.client.sdk.egg-info/not-zip-safe +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix.fhir.client.sdk.egg-info/requires.txt +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix.fhir.client.sdk.egg-info/top_level.txt +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/dictionary_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/dictionary_writer.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/exceptions/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/exceptions/fhir_get_exception.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/exceptions/fhir_sender_exception.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/exceptions/fhir_validation_exception.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/fhir_auth_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/fhir_bundle_appender.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/fhir_client.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/fhir_delete_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/fhir_merge_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/fhir_merge_resources_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/fhir_patch_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/fhir_update_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/base_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/identifier_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/last_updated_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/property_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/property_missing_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/security_access_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/security_owner_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/sort_field.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/source_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/filters/version_filter.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/function_types.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/fhir_graph_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/graph_definition.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/graph_link_parameters.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/graph_target_parameters.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/test/test_graph_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/test/test_simulate_graph_processor_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/graph/test/test_simulate_graph_processor_mixin_caching.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/open_telemetry/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/open_telemetry/attribute_names.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/open_telemetry/span_names.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/py.typed +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/queue/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/queue/request_queue_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/bundle_expander.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/fhir_client_protocol.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/fhir_delete_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/fhir_merge_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/fhir_response_processor.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/fhir_update_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/fhir_get_error_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/fhir_get_list_by_resource_type_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/fhir_get_list_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/fhir_get_response_factory.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/fhir_get_single_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/test/test_get_bundle_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/test/test_get_error_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/test/test_get_list_by_resource_type_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/test/test_get_list_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/test/test_get_response_factory.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get/test/test_get_single_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/get_result.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/merge/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/merge/base_fhir_merge_resource_response_entry.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/merge/fhir_merge_resource_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/merge/fhir_merge_resource_response_entry.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/merge/fhir_merge_response_entry_issue.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/paging_result.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/fhir_response_processor/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_expand_or_separate_bundle_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200_non_streaming.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/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.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_200_streaming.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/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.20 → helix_fhir_client_sdk-4.2.22}/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.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/fhir_response_processor/test_handle_response_404.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/test_bundle_expander.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/test_fhir_get_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/responses/test/test_resource_separator.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/structures/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/structures/get_access_token_result.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/test/test_delete_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/test/test_fhir_auth_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/test/test_fhir_bundle_appender.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/test/test_merge_mixin.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/test/test_merge_mixin_resources.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/async_parallel_processor/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/async_parallel_processor/v1/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/async_parallel_processor/v1/async_parallel_processor.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/async_runner.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/cache/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/cache/request_cache.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/cache/request_cache_entry.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/fhir_client_logger.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/fhir_helper.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/fhir_scope_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/fhir_scope_parser_result.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/fhir_server_helpers.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/hash_util.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/list_chunker.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/ndjson_chunk_streaming_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/practitioner_generator.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/retryable_aiohttp_client.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/retryable_aiohttp_response.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/retryable_aiohttp_url_result.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/size_calculator/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/size_calculator/size_calculator.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/test_async_runner.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/test_fhir_scope_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/test_fhir_scope_parser_can_parse_scopes.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/test_fhir_scope_parser_correct_allow.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/test_json_helpers.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/test_list_chunker.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/test_ndjson_chunk_streaming_parser.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/test/test_retryable_aiohttp_client.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/utilities/url_checker.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/validators/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/validators/async_fhir_validator.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/validators/fhir_validator.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/validators/test/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/validators/test/test_async_fhir_validator.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/helix_fhir_client_sdk/well_known_configuration.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/pyproject.toml +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/setup.cfg +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/setup.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/fhir_server/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/fhir_server/test_async_real_fhir_server_get_graph_large.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/fhir_server/test_async_real_fhir_server_get_patients_large.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/graph/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/graph/test_fhir_graph.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/graph/test_fhir_graph_multiple_ids.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/graph/test_fhir_graph_multiple_ids_in_batches.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_caching_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_caching_input_cache_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_caching_input_cache_if_modified_since_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_caching_scope_parser_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_separate_resources_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_with_errors_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_with_operation_outcomes_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph/test_fhir_simulated_graph_with_url_column_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph_practitioner/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_multiple_practitioner_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_multiple_practitioner_in_one_call_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/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.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_practitioner_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/simulated_graph_practitioner/test_fhir_simulated_graph_practitioner_separate_resources_async.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_bundle/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_bundle/not_expanded/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_bundle/not_expanded/test_fhir_client_bundle_not_expanded.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_bundle/not_separated/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_bundle/not_separated/test_fhir_client_bundle_not_separated.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_bundle/separated/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_bundle/separated/test_fhir_client_bundle_separated.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_fetch_response_in_chunks.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_by_id.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_by_identifier_missing.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_delete.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_list.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_list_auth_fail.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_list_auth_fail_retry.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_list_auth_fail_retry_custom_refresh_function.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_list_resource_streaming.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_list_streaming.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_merge.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_merge_with_validate.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_fhir_client_patient_update.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_real_fhir_server_get_patients.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_async_real_fhir_server_get_patients_error.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_benchmark_compress.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_benchmark_merge.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/async/test_retryable_client_session_management.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/logger_for_test.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/graph/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/graph/test_fhir_graph.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_bundle/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_bundle/not_expanded/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_bundle/not_expanded/test_fhir_client_bundle_not_expanded.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_bundle/not_separated/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_bundle/not_separated/test_fhir_client_bundle_not_separated.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_bundle/separated/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_bundle/separated/test_fhir_client_bundle_separated.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_logs_not_contains_secret_information.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_patient_by_id.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_patient_delete.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_patient_list.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_patient_list_auth_fail.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_patient_list_auth_fail_retry.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_patient_merge.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_patient_update.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/sync/test_fhir_client_patient_update_patch.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/test_fhir_client_clone.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests/test_get_nested_property.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/__init__.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_aetna_server_auth.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_aetna_server_auth_aiohttp.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_aetna_server_auth_httpx.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_dev_server_auth.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_dev_server_no_auth.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_emr_server_auth.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_firely_fhir.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_merge_vs_smart_merge_behavior.py +0 -0
- {helix_fhir_client_sdk-4.2.20 → helix_fhir_client_sdk-4.2.22}/tests_integration/test_staging_server_graph.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.2.22
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import time
|
|
3
2
|
from abc import ABC
|
|
4
3
|
from collections.abc import AsyncGenerator
|
|
5
4
|
from datetime import UTC, datetime
|
|
@@ -124,15 +123,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
124
123
|
Yields:
|
|
125
124
|
FhirGetResponse objects representing retrieved resources
|
|
126
125
|
"""
|
|
127
|
-
|
|
128
|
-
profiling: dict[str, Any] = {
|
|
129
|
-
"function": "process_simulate_graph_async",
|
|
130
|
-
"start_time": time.perf_counter(),
|
|
131
|
-
"steps": {},
|
|
132
|
-
"extend_calls": [],
|
|
133
|
-
"append_calls": [],
|
|
134
|
-
}
|
|
135
|
-
|
|
136
126
|
# Validate graph definition input
|
|
137
127
|
assert graph_json, "Graph JSON must be provided"
|
|
138
128
|
graph_definition: GraphDefinition = GraphDefinition.from_dict(graph_json)
|
|
@@ -168,7 +158,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
168
158
|
cache: RequestCache = input_cache if input_cache is not None else RequestCache()
|
|
169
159
|
async with cache:
|
|
170
160
|
# Retrieve start resources based on graph definition
|
|
171
|
-
step_start = time.perf_counter()
|
|
172
161
|
start: str = graph_definition.start
|
|
173
162
|
parent_response: FhirGetResponse
|
|
174
163
|
cache_hits: int
|
|
@@ -182,18 +171,10 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
182
171
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
183
172
|
compare_hash=compare_hash,
|
|
184
173
|
)
|
|
185
|
-
profiling["steps"]["get_start_resources"] = time.perf_counter() - step_start
|
|
186
174
|
|
|
187
175
|
# If no parent resources found, yield empty response and exit
|
|
188
176
|
parent_response_resource_count = parent_response.get_resource_count()
|
|
189
177
|
if parent_response_resource_count == 0:
|
|
190
|
-
profiling["total_time"] = time.perf_counter() - profiling["start_time"]
|
|
191
|
-
if logger:
|
|
192
|
-
logger.info(
|
|
193
|
-
f"[PROFILING] process_simulate_graph_async: total={profiling['total_time']:.3f}s, "
|
|
194
|
-
f"get_start_resources={profiling['steps'].get('get_start_resources', 0):.3f}s, "
|
|
195
|
-
f"no parent resources found"
|
|
196
|
-
)
|
|
197
178
|
yield parent_response
|
|
198
179
|
return # no resources to process
|
|
199
180
|
|
|
@@ -215,7 +196,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
215
196
|
)
|
|
216
197
|
|
|
217
198
|
# now process the graph links
|
|
218
|
-
step_start = time.perf_counter()
|
|
219
199
|
child_responses: list[FhirGetResponse] = []
|
|
220
200
|
parent_link_map: list[tuple[list[GraphDefinitionLink], FhirBundleEntryList]] = []
|
|
221
201
|
|
|
@@ -224,7 +204,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
224
204
|
parent_link_map.append((graph_definition.link, parent_bundle_entries))
|
|
225
205
|
|
|
226
206
|
# Process graph links in parallel
|
|
227
|
-
link_processing_count = 0
|
|
228
207
|
while len(parent_link_map):
|
|
229
208
|
new_parent_link_map: list[tuple[list[GraphDefinitionLink], FhirBundleEntryList]] = []
|
|
230
209
|
|
|
@@ -251,38 +230,19 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
251
230
|
add_cached_bundles_to_result=add_cached_bundles_to_result,
|
|
252
231
|
ifModifiedSince=ifModifiedSince,
|
|
253
232
|
):
|
|
254
|
-
# Track extend operation
|
|
255
|
-
extend_start = time.perf_counter()
|
|
256
233
|
child_responses.extend(link_responses)
|
|
257
|
-
extend_time = time.perf_counter() - extend_start
|
|
258
|
-
profiling["extend_calls"].append(
|
|
259
|
-
{"location": "child_responses.extend", "count": len(link_responses), "time": extend_time}
|
|
260
|
-
)
|
|
261
|
-
link_processing_count += 1
|
|
262
234
|
|
|
263
235
|
# Update parent link map for next iteration
|
|
264
236
|
parent_link_map = new_parent_link_map
|
|
265
237
|
|
|
266
|
-
profiling["steps"]["process_graph_links"] = time.perf_counter() - step_start
|
|
267
|
-
profiling["steps"]["link_processing_iterations"] = link_processing_count
|
|
268
|
-
|
|
269
238
|
# Combine and process responses
|
|
270
|
-
step_start = time.perf_counter()
|
|
271
239
|
parent_response = cast(FhirGetBundleResponse, parent_response.extend(child_responses))
|
|
272
|
-
extend_time = time.perf_counter() - step_start
|
|
273
|
-
profiling["steps"]["parent_response.extend"] = extend_time
|
|
274
|
-
profiling["extend_calls"].append(
|
|
275
|
-
{"location": "parent_response.extend", "count": len(child_responses), "time": extend_time}
|
|
276
|
-
)
|
|
277
240
|
|
|
278
241
|
# Optional resource sorting
|
|
279
242
|
if sort_resources:
|
|
280
|
-
step_start = time.perf_counter()
|
|
281
243
|
parent_response = parent_response.sort_resources()
|
|
282
|
-
profiling["steps"]["sort_resources"] = time.perf_counter() - step_start
|
|
283
244
|
|
|
284
245
|
# Prepare final response based on bundling preferences
|
|
285
|
-
step_start = time.perf_counter()
|
|
286
246
|
full_response: FhirGetResponse
|
|
287
247
|
if separate_bundle_resources:
|
|
288
248
|
full_response = FhirGetListByResourceTypeResponse.from_response(other_response=parent_response)
|
|
@@ -290,38 +250,10 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
290
250
|
full_response = FhirGetListResponse.from_response(other_response=parent_response)
|
|
291
251
|
else:
|
|
292
252
|
full_response = parent_response
|
|
293
|
-
profiling["steps"]["prepare_final_response"] = time.perf_counter() - step_start
|
|
294
253
|
|
|
295
254
|
# Set response URL
|
|
296
255
|
full_response.url = url or parent_response.url
|
|
297
256
|
|
|
298
|
-
# Calculate profiling summary
|
|
299
|
-
profiling["total_time"] = time.perf_counter() - profiling["start_time"]
|
|
300
|
-
total_extend_time = sum(call["time"] for call in profiling["extend_calls"])
|
|
301
|
-
total_extend_count = sum(call["count"] for call in profiling["extend_calls"])
|
|
302
|
-
|
|
303
|
-
# Log profiling information
|
|
304
|
-
if logger:
|
|
305
|
-
logger.info(
|
|
306
|
-
f"[PROFILING] process_simulate_graph_async for id={id_}: "
|
|
307
|
-
f"total={profiling['total_time']:.3f}s, "
|
|
308
|
-
f"get_start_resources={profiling['steps'].get('get_start_resources', 0):.3f}s, "
|
|
309
|
-
f"process_graph_links={profiling['steps'].get('process_graph_links', 0):.3f}s, "
|
|
310
|
-
f"parent_response.extend={profiling['steps'].get('parent_response.extend', 0):.3f}s, "
|
|
311
|
-
f"sort_resources={profiling['steps'].get('sort_resources', 0):.3f}s, "
|
|
312
|
-
f"prepare_final_response={profiling['steps'].get('prepare_final_response', 0):.3f}s"
|
|
313
|
-
)
|
|
314
|
-
logger.info(
|
|
315
|
-
f"[PROFILING] process_simulate_graph_async extend operations: "
|
|
316
|
-
f"total_calls={len(profiling['extend_calls'])}, "
|
|
317
|
-
f"total_items={total_extend_count}, "
|
|
318
|
-
f"total_time={total_extend_time:.3f}s"
|
|
319
|
-
)
|
|
320
|
-
for call in profiling["extend_calls"]:
|
|
321
|
-
logger.info(
|
|
322
|
-
f"[PROFILING] extend at {call['location']}: items={call['count']}, time={call['time']:.3f}s"
|
|
323
|
-
)
|
|
324
|
-
|
|
325
257
|
# Log cache performance
|
|
326
258
|
if logger:
|
|
327
259
|
logger.info(
|
|
@@ -344,9 +276,26 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
344
276
|
) -> list[FhirGetResponse]:
|
|
345
277
|
"""
|
|
346
278
|
Parallel processing function for graph definition links.
|
|
347
|
-
"""
|
|
348
|
-
profiling_start = time.perf_counter()
|
|
349
279
|
|
|
280
|
+
This method is designed to be used with AsyncParallelProcessor to process
|
|
281
|
+
graph links concurrently, improving performance for complex FHIR resource
|
|
282
|
+
graph traversals.
|
|
283
|
+
|
|
284
|
+
Key Responsibilities:
|
|
285
|
+
- Process individual graph links in parallel
|
|
286
|
+
- Track and log processing details
|
|
287
|
+
- Handle resource retrieval for each link
|
|
288
|
+
- Manage parallel processing context
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
context: Parallel processing context information
|
|
292
|
+
row: Current GraphDefinitionLink being processed
|
|
293
|
+
parameters: Parameters for link processing
|
|
294
|
+
additional_parameters: Extra parameters for extended processing
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
List of FhirGetResponse objects retrieved during link processing
|
|
298
|
+
"""
|
|
350
299
|
# Record the start time for performance tracking
|
|
351
300
|
start_time: datetime = datetime.now()
|
|
352
301
|
|
|
@@ -377,8 +326,11 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
377
326
|
logger=parameters.logger,
|
|
378
327
|
cache=parameters.cache,
|
|
379
328
|
scope_parser=parameters.scope_parser,
|
|
329
|
+
# Handle parent link map from additional parameters
|
|
380
330
|
parent_link_map=(additional_parameters["parent_link_map"] if additional_parameters else []),
|
|
331
|
+
# Determine request size, default to 1 if not specified
|
|
381
332
|
request_size=(additional_parameters["request_size"] if additional_parameters else 1),
|
|
333
|
+
# Track unsupported resources for ID-based search
|
|
382
334
|
id_search_unsupported_resources=(
|
|
383
335
|
additional_parameters["id_search_unsupported_resources"] if additional_parameters else []
|
|
384
336
|
),
|
|
@@ -394,8 +346,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
394
346
|
# Record end time for performance tracking
|
|
395
347
|
end_time: datetime = datetime.now()
|
|
396
348
|
|
|
397
|
-
total_time = time.perf_counter() - profiling_start
|
|
398
|
-
|
|
399
349
|
# Log detailed processing information
|
|
400
350
|
if parameters.logger:
|
|
401
351
|
parameters.logger.debug(
|
|
@@ -407,11 +357,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
407
357
|
+ f" | duration: {end_time - start_time}"
|
|
408
358
|
+ f" | resource_count: {len(result)}"
|
|
409
359
|
)
|
|
410
|
-
parameters.logger.info(
|
|
411
|
-
f"[PROFILING] process_link_async_parallel_function for path={row.path}: "
|
|
412
|
-
f"total={total_time:.3f}s, "
|
|
413
|
-
f"results={len(result)}"
|
|
414
|
-
)
|
|
415
360
|
|
|
416
361
|
# Return the list of retrieved responses
|
|
417
362
|
return result
|
|
@@ -897,18 +842,9 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
897
842
|
logger: Logger | None,
|
|
898
843
|
compare_hash: bool = True,
|
|
899
844
|
) -> FhirGetResponse | None:
|
|
900
|
-
profiling_start = time.perf_counter()
|
|
901
|
-
http_request_time = 0.0
|
|
902
|
-
http_request_count = 0
|
|
903
|
-
cache_check_time = 0.0
|
|
904
|
-
cache_update_time = 0.0
|
|
905
|
-
append_time = 0.0
|
|
906
|
-
|
|
907
845
|
result: FhirGetResponse | None = None
|
|
908
846
|
non_cached_id_list: list[str] = []
|
|
909
|
-
|
|
910
847
|
# first check to see if we can find these in the cache
|
|
911
|
-
cache_check_start = time.perf_counter()
|
|
912
848
|
if ids:
|
|
913
849
|
for resource_id in ids:
|
|
914
850
|
cache_entry: RequestCacheEntry | None = await cache.get_async(
|
|
@@ -921,12 +857,9 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
921
857
|
if logger:
|
|
922
858
|
logger.info(f"Cache entry not found for {resource_type}/{resource_id} (1by1)")
|
|
923
859
|
non_cached_id_list.append(resource_id)
|
|
924
|
-
cache_check_time = time.perf_counter() - cache_check_start
|
|
925
860
|
|
|
926
|
-
cache_update_start = time.perf_counter()
|
|
927
861
|
for single_id in non_cached_id_list:
|
|
928
862
|
result2: FhirGetResponse
|
|
929
|
-
http_start = time.perf_counter()
|
|
930
863
|
async for result2 in self._get_with_session_async(
|
|
931
864
|
page_number=None,
|
|
932
865
|
ids=[single_id],
|
|
@@ -935,15 +868,10 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
935
868
|
fn_handle_streaming_chunk=None,
|
|
936
869
|
resource_type=resource_type,
|
|
937
870
|
):
|
|
938
|
-
http_request_time += time.perf_counter() - http_start
|
|
939
|
-
http_request_count += 1
|
|
940
|
-
|
|
941
871
|
if result2.resource_type == "OperationOutcome":
|
|
942
872
|
result2 = FhirGetErrorResponse.from_response(other_response=result2)
|
|
943
873
|
if result:
|
|
944
|
-
append_start = time.perf_counter()
|
|
945
874
|
result = result.append(result2)
|
|
946
|
-
append_time += time.perf_counter() - append_start
|
|
947
875
|
else:
|
|
948
876
|
result = result2
|
|
949
877
|
if result2.successful:
|
|
@@ -977,21 +905,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
977
905
|
)
|
|
978
906
|
if cache_updated and logger:
|
|
979
907
|
logger.info(f"Inserted {result2.status} for {resource_type}/{single_id} into cache (1by1)")
|
|
980
|
-
cache_update_time = time.perf_counter() - cache_update_start - http_request_time - append_time
|
|
981
|
-
|
|
982
|
-
total_time = time.perf_counter() - profiling_start
|
|
983
|
-
processing_time = total_time - http_request_time - cache_check_time - cache_update_time - append_time
|
|
984
|
-
|
|
985
|
-
if logger and http_request_count > 0:
|
|
986
|
-
logger.info(
|
|
987
|
-
f"[PROFILING] _get_resources_by_id_one_by_one_async for {resource_type}: "
|
|
988
|
-
f"total={total_time:.3f}s, "
|
|
989
|
-
f"http_requests={http_request_time:.3f}s ({http_request_count} calls), "
|
|
990
|
-
f"cache_check={cache_check_time:.3f}s, "
|
|
991
|
-
f"cache_update={cache_update_time:.3f}s, "
|
|
992
|
-
f"append={append_time:.3f}s, "
|
|
993
|
-
f"processing={processing_time:.3f}s"
|
|
994
|
-
)
|
|
995
908
|
|
|
996
909
|
return result
|
|
997
910
|
|
|
@@ -1008,13 +921,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1008
921
|
add_cached_bundles_to_result: bool = True,
|
|
1009
922
|
compare_hash: bool = True,
|
|
1010
923
|
) -> tuple[FhirGetResponse, int]:
|
|
1011
|
-
profiling_start = time.perf_counter()
|
|
1012
|
-
http_request_time = 0.0
|
|
1013
|
-
http_request_count = 0
|
|
1014
|
-
cache_check_time = 0.0
|
|
1015
|
-
cache_update_time = 0.0
|
|
1016
|
-
append_time = 0.0
|
|
1017
|
-
|
|
1018
924
|
assert resource_type
|
|
1019
925
|
if not scope_parser.scope_allows(resource_type=resource_type):
|
|
1020
926
|
if logger:
|
|
@@ -1048,13 +954,14 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1048
954
|
|
|
1049
955
|
non_cached_id_list: list[str] = []
|
|
1050
956
|
# get any cached resources
|
|
1051
|
-
cache_check_start = time.perf_counter()
|
|
1052
957
|
if id_list:
|
|
1053
958
|
for resource_id in id_list:
|
|
1054
959
|
cache_entry: RequestCacheEntry | None = await cache.get_async(
|
|
1055
960
|
resource_type=resource_type, resource_id=resource_id
|
|
1056
961
|
)
|
|
1057
962
|
if cache_entry:
|
|
963
|
+
# if there is an entry then it means we tried to get it in the past
|
|
964
|
+
# so don't get it again whether we were successful or not
|
|
1058
965
|
if logger:
|
|
1059
966
|
logger.info(
|
|
1060
967
|
f"{cache_entry.status} Returning {resource_type}/{resource_id} from cache (ByParam)"
|
|
@@ -1063,7 +970,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1063
970
|
if logger:
|
|
1064
971
|
logger.info(f"Cache entry not found for {resource_type}/{resource_id} (ByParam)")
|
|
1065
972
|
non_cached_id_list.append(resource_id)
|
|
1066
|
-
cache_check_time = time.perf_counter() - cache_check_start
|
|
1067
973
|
|
|
1068
974
|
all_result: FhirGetResponse | None = None
|
|
1069
975
|
# either we have non-cached ids or this is a query without id but has other parameters
|
|
@@ -1075,7 +981,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1075
981
|
# call the server to get the resources
|
|
1076
982
|
result1: FhirGetResponse
|
|
1077
983
|
result: FhirGetResponse | None
|
|
1078
|
-
http_start = time.perf_counter()
|
|
1079
984
|
async for result1 in self._get_with_session_async(
|
|
1080
985
|
page_number=None,
|
|
1081
986
|
ids=non_cached_id_list,
|
|
@@ -1084,8 +989,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1084
989
|
fn_handle_streaming_chunk=None,
|
|
1085
990
|
resource_type=resource_type,
|
|
1086
991
|
):
|
|
1087
|
-
http_request_time += time.perf_counter() - http_start
|
|
1088
|
-
http_request_count += 1
|
|
1089
992
|
result = result1
|
|
1090
993
|
# if we got a failure then check if we can get it one by one
|
|
1091
994
|
if (not result or result.status != 200) and len(non_cached_id_list) > 1:
|
|
@@ -1098,7 +1001,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1098
1001
|
f" Fetching one by one ids: {non_cached_id_list}"
|
|
1099
1002
|
)
|
|
1100
1003
|
# For some resources if search by _id doesn't work then fetch one by one.
|
|
1101
|
-
one_by_one_start = time.perf_counter()
|
|
1102
1004
|
result = await self._get_resources_by_id_one_by_one_async(
|
|
1103
1005
|
resource_type=resource_type,
|
|
1104
1006
|
ids=non_cached_id_list,
|
|
@@ -1107,9 +1009,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1107
1009
|
logger=logger,
|
|
1108
1010
|
compare_hash=compare_hash,
|
|
1109
1011
|
)
|
|
1110
|
-
one_by_one_time = time.perf_counter() - one_by_one_start
|
|
1111
|
-
http_request_time += one_by_one_time
|
|
1112
|
-
http_request_count += len(non_cached_id_list)
|
|
1113
1012
|
else:
|
|
1114
1013
|
if logger:
|
|
1115
1014
|
logger.info(f"Fetched {resource_type} resources using _id for url {self._url}")
|
|
@@ -1125,14 +1024,11 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1125
1024
|
|
|
1126
1025
|
# append to the response
|
|
1127
1026
|
if all_result:
|
|
1128
|
-
append_start = time.perf_counter()
|
|
1129
1027
|
all_result = all_result.append(result)
|
|
1130
|
-
append_time += time.perf_counter() - append_start
|
|
1131
1028
|
else:
|
|
1132
1029
|
all_result = result
|
|
1133
1030
|
# If non_cached_id_list is not empty and resource_type does not support ?_id search then fetch it one by one
|
|
1134
1031
|
elif len(non_cached_id_list):
|
|
1135
|
-
one_by_one_start = time.perf_counter()
|
|
1136
1032
|
all_result = await self._get_resources_by_id_one_by_one_async(
|
|
1137
1033
|
resource_type=resource_type,
|
|
1138
1034
|
ids=non_cached_id_list,
|
|
@@ -1141,13 +1037,10 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1141
1037
|
logger=logger,
|
|
1142
1038
|
compare_hash=compare_hash,
|
|
1143
1039
|
)
|
|
1144
|
-
http_request_time += time.perf_counter() - one_by_one_start
|
|
1145
|
-
http_request_count += len(non_cached_id_list)
|
|
1146
1040
|
|
|
1147
1041
|
# This list tracks the non-cached ids that were found
|
|
1148
1042
|
found_non_cached_id_list: list[str] = []
|
|
1149
1043
|
# Cache the fetched entries
|
|
1150
|
-
cache_update_start = time.perf_counter()
|
|
1151
1044
|
if all_result:
|
|
1152
1045
|
non_cached_bundle_entry: FhirBundleEntry
|
|
1153
1046
|
for non_cached_bundle_entry in all_result.get_bundle_entries():
|
|
@@ -1181,6 +1074,7 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1181
1074
|
logger.debug(f"Inserted {resource_type}/{non_cached_resource_id} into cache (ByParam)")
|
|
1182
1075
|
found_non_cached_id_list.append(non_cached_resource_id)
|
|
1183
1076
|
|
|
1077
|
+
# now add all the non-cached ids that were NOT found to the cache too so we don't look for them again
|
|
1184
1078
|
for non_cached_id in non_cached_id_list:
|
|
1185
1079
|
if non_cached_id not in found_non_cached_id_list:
|
|
1186
1080
|
cache_updated = await cache.add_async(
|
|
@@ -1195,7 +1089,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1195
1089
|
)
|
|
1196
1090
|
if cache_updated and logger:
|
|
1197
1091
|
logger.info(f"Inserted 404 for {resource_type}/{non_cached_id} into cache (ByParam)")
|
|
1198
|
-
cache_update_time = time.perf_counter() - cache_update_start
|
|
1199
1092
|
|
|
1200
1093
|
bundle_response: FhirGetBundleResponse = (
|
|
1201
1094
|
FhirGetBundleResponse.from_response(other_response=all_result)
|
|
@@ -1237,21 +1130,6 @@ class SimulatedGraphProcessorMixin(ABC, FhirClientProtocol):
|
|
|
1237
1130
|
storage_mode=self._storage_mode,
|
|
1238
1131
|
)
|
|
1239
1132
|
)
|
|
1240
|
-
|
|
1241
|
-
total_time = time.perf_counter() - profiling_start
|
|
1242
|
-
processing_time = total_time - http_request_time - cache_check_time - cache_update_time - append_time
|
|
1243
|
-
|
|
1244
|
-
if logger and http_request_count > 0:
|
|
1245
|
-
logger.info(
|
|
1246
|
-
f"[PROFILING] _get_resources_by_parameters_async for {resource_type}: "
|
|
1247
|
-
f"total={total_time:.3f}s, "
|
|
1248
|
-
f"http_requests={http_request_time:.3f}s ({http_request_count} calls), "
|
|
1249
|
-
f"cache_check={cache_check_time:.3f}s, "
|
|
1250
|
-
f"cache_update={cache_update_time:.3f}s, "
|
|
1251
|
-
f"append={append_time:.3f}s, "
|
|
1252
|
-
f"processing={processing_time:.3f}s"
|
|
1253
|
-
)
|
|
1254
|
-
|
|
1255
1133
|
return bundle_response, cache.cache_hits
|
|
1256
1134
|
|
|
1257
1135
|
# noinspection PyPep8Naming
|
|
@@ -170,8 +170,9 @@ class FhirGetResponse:
|
|
|
170
170
|
"""
|
|
171
171
|
result: FhirGetResponse = self._extend(others=others)
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
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]
|
|
175
176
|
return result
|
|
176
177
|
|
|
177
178
|
@abstractmethod
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import logging
|
|
3
2
|
from collections.abc import AsyncGenerator, Generator
|
|
4
3
|
from datetime import datetime
|
|
5
4
|
from logging import Logger
|
|
@@ -133,21 +132,8 @@ class FhirGetBundleResponse(FhirGetResponse):
|
|
|
133
132
|
:param others: list of FhirGetResponse objects
|
|
134
133
|
:return: self
|
|
135
134
|
"""
|
|
136
|
-
if not others:
|
|
137
|
-
return self
|
|
138
|
-
|
|
139
|
-
all_entries: list[FhirBundleEntry] = []
|
|
140
135
|
for other_response in others:
|
|
141
|
-
|
|
142
|
-
if len(other_response_entries) > 0:
|
|
143
|
-
all_entries.extend(other_response_entries)
|
|
144
|
-
|
|
145
|
-
# Now extend with all entries at once instead of one response at a time
|
|
146
|
-
if all_entries:
|
|
147
|
-
if self._bundle_entries is None:
|
|
148
|
-
self._bundle_entries = FhirBundleEntryList(all_entries)
|
|
149
|
-
else:
|
|
150
|
-
self._bundle_entries.extend(all_entries)
|
|
136
|
+
self.append(other_response=other_response)
|
|
151
137
|
|
|
152
138
|
return self
|
|
153
139
|
|
|
@@ -325,56 +311,36 @@ class FhirGetBundleResponse(FhirGetResponse):
|
|
|
325
311
|
) -> "FhirGetBundleResponse":
|
|
326
312
|
"""
|
|
327
313
|
Removes the entries in the cache from the bundle
|
|
314
|
+
|
|
315
|
+
:param request_cache: RequestCache object to remove the entries from
|
|
316
|
+
:param compare_hash: if True, compare the hash of the resource with the hash in the cache
|
|
317
|
+
:return: self
|
|
328
318
|
"""
|
|
329
|
-
#
|
|
330
|
-
cache_map: dict[tuple[str, str], str | None] = {}
|
|
319
|
+
# remove all entries in the cache from the bundle
|
|
331
320
|
async for cached_entry in request_cache.get_entries_async():
|
|
332
|
-
if cached_entry.from_input_cache
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
return False
|
|
355
|
-
try:
|
|
356
|
-
entry_hash = resource_hash.hash_value(json.dumps(json.loads(resource.json()), sort_keys=True))
|
|
357
|
-
return entry_hash == cache_map[key]
|
|
358
|
-
except Exception:
|
|
359
|
-
return False
|
|
360
|
-
|
|
361
|
-
# One pass filter; rebuild list to avoid many deque.remove calls
|
|
362
|
-
kept: list[FhirBundleEntry] = []
|
|
363
|
-
for entry in self._bundle_entries:
|
|
364
|
-
if should_remove(entry):
|
|
365
|
-
removed_entries.append(entry)
|
|
366
|
-
else:
|
|
367
|
-
kept.append(entry)
|
|
368
|
-
|
|
369
|
-
if logger and removed_entries and logger.isEnabledFor(logging.DEBUG):
|
|
370
|
-
for entry in removed_entries:
|
|
371
|
-
if entry.resource:
|
|
372
|
-
logger.debug(
|
|
373
|
-
f"Removing entry from bundle with id {entry.resource.id} and resource "
|
|
374
|
-
f"type {entry.resource.resource_type}"
|
|
375
|
-
)
|
|
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
|
|
376
343
|
|
|
377
|
-
self._bundle_entries = FhirBundleEntryList(kept)
|
|
378
344
|
return self
|
|
379
345
|
|
|
380
346
|
@classmethod
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
from copy import deepcopy
|
|
3
|
+
from typing import Any, cast
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclasses.dataclass(slots=True)
|
|
7
|
+
class ResourceSeparatorResult:
|
|
8
|
+
"""
|
|
9
|
+
ResourceSeparatorResult class for encapsulating the response from FHIR server when separating resources
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
resources_dicts: list[dict[str, str | None | list[dict[str, Any]]]]
|
|
13
|
+
total_count: int
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ResourceSeparator:
|
|
17
|
+
"""
|
|
18
|
+
ResourceSeparator class for separating resources from contained resources
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
async def separate_contained_resources_async(
|
|
23
|
+
*,
|
|
24
|
+
resources: list[dict[str, Any]],
|
|
25
|
+
access_token: str | None,
|
|
26
|
+
url: str | None,
|
|
27
|
+
extra_context_to_return: dict[str, Any] | None,
|
|
28
|
+
) -> ResourceSeparatorResult:
|
|
29
|
+
"""
|
|
30
|
+
Given a list of resources, return a list of resources with the contained resources separated out.
|
|
31
|
+
|
|
32
|
+
:param resources: The resources list.
|
|
33
|
+
:param access_token: The access token.
|
|
34
|
+
:param url: The URL.
|
|
35
|
+
:param extra_context_to_return: The extra context to return.
|
|
36
|
+
|
|
37
|
+
:return: None
|
|
38
|
+
"""
|
|
39
|
+
resources_dicts: list[dict[str, str | None | list[dict[str, Any]]]] = []
|
|
40
|
+
resource_count: int = 0
|
|
41
|
+
resource: dict[str, Any]
|
|
42
|
+
for resource in resources:
|
|
43
|
+
# make a copy so we are not changing the original resource
|
|
44
|
+
cloned_resource: dict[str, Any] = deepcopy(resource)
|
|
45
|
+
# This dict will hold the separated resources where the key is resourceType
|
|
46
|
+
# have to split these here otherwise when Spark loads them
|
|
47
|
+
# it can't handle that items in the entry array can have different schemas
|
|
48
|
+
resources_dict: dict[str, str | None | list[dict[str, Any]]] = {}
|
|
49
|
+
# add the parent resource to the resources_dict
|
|
50
|
+
resource_type = str(cloned_resource["resourceType"]).lower()
|
|
51
|
+
if resource_type not in resources_dict:
|
|
52
|
+
resources_dict[resource_type] = []
|
|
53
|
+
if isinstance(resources_dict[resource_type], list):
|
|
54
|
+
cast(list[dict[str, Any]], resources_dict[resource_type]).append(cloned_resource)
|
|
55
|
+
resource_count += 1
|
|
56
|
+
# now see if this resource has a contained array and if so, add those to the resources_dict
|
|
57
|
+
if "contained" in cloned_resource:
|
|
58
|
+
contained_resources = cloned_resource.pop("contained")
|
|
59
|
+
for contained_resource in contained_resources:
|
|
60
|
+
resource_type = str(contained_resource["resourceType"]).lower()
|
|
61
|
+
if resource_type not in resources_dict:
|
|
62
|
+
resources_dict[resource_type] = []
|
|
63
|
+
if isinstance(resources_dict[resource_type], list):
|
|
64
|
+
cast(list[dict[str, Any]], resources_dict[resource_type]).append(contained_resource)
|
|
65
|
+
resource_count += 1
|
|
66
|
+
resources_dict["token"] = access_token
|
|
67
|
+
resources_dict["url"] = url
|
|
68
|
+
if extra_context_to_return:
|
|
69
|
+
resources_dict.update(extra_context_to_return)
|
|
70
|
+
resources_dicts.append(resources_dict)
|
|
71
|
+
|
|
72
|
+
return ResourceSeparatorResult(resources_dicts=resources_dicts, total_count=resource_count)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
4.2.20
|