pysof 0.2.1__tar.gz → 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (367) hide show
  1. {pysof-0.2.1 → pysof-0.2.4}/Cargo.toml +3 -2
  2. {pysof-0.2.1 → pysof-0.2.4}/PKG-INFO +40 -11
  3. {pysof-0.2.1/crates/pysof → pysof-0.2.4}/README.md +39 -10
  4. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/Cargo.toml +3 -3
  5. pysof-0.2.4/crates/fhir/src/compartment/loader.rs +178 -0
  6. pysof-0.2.4/crates/fhir/src/compartment/mod.rs +15 -0
  7. pysof-0.2.4/crates/fhir/src/compartment_expressions/r6.rs +711 -0
  8. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/lib.rs +120 -0
  9. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/r4.rs +277 -677
  10. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/r4b.rs +281 -681
  11. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/r5.rs +279 -679
  12. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/r6.rs +38891 -45996
  13. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/search/errors.rs +26 -0
  14. pysof-0.2.4/crates/fhir/src/search/loader.rs +1360 -0
  15. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/search/mod.rs +1 -1
  16. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/search/registry.rs +376 -11
  17. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir-macro/Cargo.toml +1 -1
  18. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir-macro/src/lib.rs +188 -290
  19. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/Cargo.toml +7 -2
  20. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/README.md +26 -6
  21. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/boundary_functions.rs +172 -11
  22. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/cli.rs +2 -2
  23. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/evaluator.rs +240 -71
  24. pysof-0.2.4/crates/fhirpath/src/functions.rs +711 -0
  25. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/handlers.rs +2 -0
  26. pysof-0.2.4/crates/fhirpath/src/lib.rs +872 -0
  27. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/not_function.rs +2 -3
  28. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/parser.rs +1 -1
  29. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/polymorphic_access.rs +612 -86
  30. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/reference_key_functions.rs +77 -0
  31. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/server.rs +24 -13
  32. pysof-0.2.4/crates/fhirpath/src/terminology_client.rs +1014 -0
  33. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/terminology_functions.rs +28 -5
  34. pysof-0.2.4/crates/fhirpath/tests/builtin_functions_evaluator_tests.rs +66 -0
  35. pysof-0.2.4/crates/fhirpath/tests/cli_version_test.rs +17 -0
  36. pysof-0.2.4/crates/fhirpath/tests/common/known_failures.rs +333 -0
  37. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/common/mod.rs +2 -0
  38. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/common/runner.rs +4 -1
  39. pysof-0.2.4/crates/fhirpath/tests/data/r4/rust-known-failures.json +5 -0
  40. pysof-0.2.4/crates/fhirpath/tests/data/r5/known-test-failures.json +71 -0
  41. pysof-0.2.4/crates/fhirpath/tests/data/r5/rust-known-failures.json +56 -0
  42. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/tests-fhir-r5.xml +47 -0
  43. pysof-0.2.4/crates/fhirpath/tests/environment_variables_tests.rs +72 -0
  44. pysof-0.2.4/crates/fhirpath/tests/external_constants_tests.rs +150 -0
  45. pysof-0.2.4/crates/fhirpath/tests/nesting_depth.rs +56 -0
  46. pysof-0.2.4/crates/fhirpath/tests/parse_expression_diagnostics_tests.rs +72 -0
  47. pysof-0.2.4/crates/fhirpath/tests/parse_expression_spanned_tests.rs +58 -0
  48. pysof-0.2.4/crates/fhirpath/tests/polymorphic_version_tests.rs +162 -0
  49. pysof-0.2.4/crates/fhirpath/tests/primitive_extension_tests.rs +567 -0
  50. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/r4_tests.rs +161 -164
  51. pysof-0.2.4/crates/fhirpath/tests/r5_tests.rs +601 -0
  52. pysof-0.2.4/crates/fhirpath/tests/terminology_config_tests.rs +174 -0
  53. pysof-0.2.4/crates/fhirpath/tests/valueless_primitive_tests.rs +118 -0
  54. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath-support/src/lib.rs +90 -1
  55. pysof-0.2.4/crates/observability/Cargo.toml +64 -0
  56. pysof-0.2.4/crates/observability/src/composite_metrics.rs +101 -0
  57. pysof-0.2.4/crates/observability/src/dashboard.rs +1105 -0
  58. pysof-0.2.4/crates/observability/src/dashboard_counters.rs +2311 -0
  59. pysof-0.2.4/crates/observability/src/dashboard_metrics.rs +231 -0
  60. pysof-0.2.4/crates/observability/src/lib.rs +67 -0
  61. pysof-0.2.4/crates/observability/src/metrics.rs +107 -0
  62. pysof-0.2.4/crates/observability/src/middleware.rs +315 -0
  63. pysof-0.2.4/crates/observability/src/mode.rs +188 -0
  64. pysof-0.2.4/crates/observability/src/reqlog.rs +404 -0
  65. pysof-0.2.4/crates/observability/src/shutdown.rs +96 -0
  66. pysof-0.2.4/crates/observability/src/subscriptions.rs +126 -0
  67. pysof-0.2.4/crates/observability/src/telemetry.rs +166 -0
  68. pysof-0.2.4/crates/observability/src/uptime.rs +56 -0
  69. pysof-0.2.4/crates/observability/tests/middleware.rs +65 -0
  70. pysof-0.2.4/crates/observability/tests/middleware_full.rs +36 -0
  71. pysof-0.2.4/crates/observability/tests/middleware_off.rs +36 -0
  72. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/.gitignore +5 -0
  73. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/Cargo.toml +3 -2
  74. {pysof-0.2.1 → pysof-0.2.4/crates/pysof}/README.md +39 -10
  75. pysof-0.2.4/crates/pysof/build.rs +13 -0
  76. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/test_core_functions.py +13 -5
  77. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/test_error_handling.py +6 -5
  78. pysof-0.2.4/crates/pysof/python-tests/test_json_string_input.py +116 -0
  79. pysof-0.2.4/crates/pysof/python-tests/test_ndjson_exports.py +85 -0
  80. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/test_package_metadata.py +2 -2
  81. pysof-0.2.4/crates/pysof/python-tests/test_threading.py +108 -0
  82. pysof-0.2.4/crates/pysof/scripts/bench_threading.py +192 -0
  83. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/src/lib.rs +145 -316
  84. {pysof-0.2.1 → pysof-0.2.4/crates/pysof}/src/pysof/__init__.py +96 -27
  85. {pysof-0.2.1 → pysof-0.2.4/crates/pysof}/src/pysof/_pysof.pyi +38 -9
  86. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/integration/content_types.rs +66 -65
  87. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/integration.rs +2 -1
  88. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/lib_coverage_tests.rs +3 -1
  89. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/uv.lock +1 -1
  90. {pysof-0.2.1 → pysof-0.2.4}/crates/serde-support/Cargo.toml +4 -0
  91. {pysof-0.2.1 → pysof-0.2.4}/crates/serde-support/src/lib.rs +179 -0
  92. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/Cargo.toml +21 -12
  93. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/README.md +84 -43
  94. pysof-0.2.4/crates/sof/scripts/bench_arrow_client.py +126 -0
  95. pysof-0.2.1/crates/sof/src/server.rs → pysof-0.2.4/crates/sof/src/app.rs +60 -313
  96. pysof-0.2.4/crates/sof/src/canonical.rs +80 -0
  97. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/cli.rs +23 -8
  98. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/error.rs +42 -1
  99. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/handlers.rs +404 -193
  100. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/lib.rs +769 -222
  101. pysof-0.2.4/crates/sof/src/lint/tests.rs +1918 -0
  102. pysof-0.2.4/crates/sof/src/lint.rs +2026 -0
  103. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/models.rs +75 -40
  104. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/params.rs +120 -40
  105. pysof-0.2.4/crates/sof/src/server.rs +259 -0
  106. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/sqlquery/bind.rs +71 -0
  107. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/sqlquery/engine.rs +311 -19
  108. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/sqlquery/library.rs +68 -10
  109. pysof-0.2.4/crates/sof/src/sqlquery/mod.rs +166 -0
  110. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/sqlquery/params.rs +33 -45
  111. pysof-0.2.4/crates/sof/src/sqlquery/scan.rs +524 -0
  112. pysof-0.2.4/crates/sof/tests/common/mod.rs +11 -0
  113. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/run_foreach_tests.rs +1 -1
  114. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/server_tests.rs +415 -191
  115. pysof-0.2.4/crates/sof/tests/spec_examples.rs +220 -0
  116. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/README.md +22 -3
  117. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-CodeSystemHierarchy.json +43 -0
  118. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-ConditionFlat.json +72 -0
  119. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-EncounterFlat.json +76 -0
  120. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-PatientAddresses.json +40 -0
  121. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-PatientAndContactAddressUnion.json +62 -0
  122. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-PatientDemographics.json +36 -0
  123. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-PatientNamesWithIndex.json +41 -0
  124. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-QuestionnaireResponseItems.json +71 -0
  125. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-ShareablePatientDemographics.json +51 -0
  126. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-UsCoreBloodPressures.json +88 -0
  127. pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/test-bundle.json +9 -0
  128. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/repeat.json +2 -1
  129. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/sql_on_fhir_tests.rs +17 -37
  130. pysof-0.2.4/crates/sof/tests/test_arrow_ipc_export.rs +249 -0
  131. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_base64_binary_constant.rs +1 -1
  132. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_chunked_processing.rs +35 -0
  133. pysof-0.2.4/crates/sof/tests/test_cli_version.rs +17 -0
  134. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_format_parameter_body.rs +14 -23
  135. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_header_parameter_body.rs +19 -28
  136. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_limit_parameter_body.rs +12 -12
  137. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_parameter_validation.rs +3 -3
  138. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_patient_reference_formats.rs +37 -8
  139. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_query_parameter_combinations.rs +74 -32
  140. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_run_operation_parameters.rs +2 -2
  141. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_runner_integration.rs +78 -13
  142. {pysof-0.2.1 → pysof-0.2.4}/pyproject.toml +1 -1
  143. {pysof-0.2.1 → pysof-0.2.4}/src/lib.rs +145 -316
  144. {pysof-0.2.1/crates/pysof → pysof-0.2.4}/src/pysof/__init__.py +96 -27
  145. pysof-0.2.4/src/pysof/_pysof.cpython-314-x86_64-linux-gnu.so +4 -0
  146. {pysof-0.2.1/crates/pysof → pysof-0.2.4}/src/pysof/_pysof.pyi +38 -9
  147. pysof-0.2.1/crates/fhir/src/compartment_expressions/r6.rs +0 -743
  148. pysof-0.2.1/crates/fhir/src/search/loader.rs +0 -729
  149. pysof-0.2.1/crates/fhirpath/src/lib.rs +0 -385
  150. pysof-0.2.1/crates/fhirpath/src/terminology_client.rs +0 -545
  151. pysof-0.2.1/crates/fhirpath/tests/data/r5/known-test-failures.json +0 -66
  152. pysof-0.2.1/crates/fhirpath/tests/primitive_extension_tests.rs +0 -199
  153. pysof-0.2.1/crates/fhirpath/tests/r5_tests.rs +0 -396
  154. pysof-0.2.1/crates/pysof/multithreading_example.py +0 -100
  155. pysof-0.2.1/crates/pysof/test_multithreading.py +0 -125
  156. pysof-0.2.1/crates/sof/src/sqlquery/mod.rs +0 -63
  157. pysof-0.2.1/crates/sof/tests/common/mod.rs +0 -749
  158. pysof-0.2.1/src/pysof/_pysof.cpython-311-darwin.so +0 -4
  159. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/README.md +0 -0
  160. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/build.rs +0 -0
  161. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/mod.rs +0 -0
  162. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/r4.rs +0 -0
  163. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/r4b.rs +0 -0
  164. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/r5.rs +0 -0
  165. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/parameters.rs +0 -0
  166. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/r6.rs.template +0 -0
  167. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/src/search/types.rs +0 -0
  168. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/tests/integer_string_integration.rs +0 -0
  169. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/tests/simple_null_test.rs +0 -0
  170. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir/tests/test_contained_stack.rs +0 -0
  171. {pysof-0.2.1 → pysof-0.2.4}/crates/fhir-macro/README.md +0 -0
  172. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/PRECISION_LIMITATION.md +0 -0
  173. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/benches/cli_benches.rs +0 -0
  174. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/benches/evaluator_benches.rs +0 -0
  175. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/benches/parser_benches.rs +0 -0
  176. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/benches/server_benches.rs +0 -0
  177. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/examples/test_ucum.rs +0 -0
  178. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/grammar/fhirpath.g4 +0 -0
  179. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/server-api.md +0 -0
  180. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/aggregate_function.rs +0 -0
  181. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/aggregate_math_functions.rs +0 -0
  182. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/bin/fhirpath-cli.rs +0 -0
  183. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/bin/fhirpath-server.rs +0 -0
  184. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/boolean_functions.rs +0 -0
  185. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/collection_functions.rs +0 -0
  186. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/collection_navigation.rs +0 -0
  187. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/contains_function.rs +0 -0
  188. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/conversion_functions.rs +0 -0
  189. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/date_operation.rs +0 -0
  190. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/datetime_impl.rs +0 -0
  191. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/debug_trace.rs +0 -0
  192. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/distinct_functions.rs +0 -0
  193. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/error.rs +0 -0
  194. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/extension_function.rs +0 -0
  195. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/fhir_type_hierarchy.rs +0 -0
  196. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/format_functions.rs +0 -0
  197. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/interval_functions.rs +0 -0
  198. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/json_utils.rs +0 -0
  199. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/long_conversion.rs +0 -0
  200. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/models.rs +0 -0
  201. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/parse_debug.rs +0 -0
  202. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/repeat_all_function.rs +0 -0
  203. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/repeat_function.rs +0 -0
  204. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/resolve_function.rs +0 -0
  205. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/resource_type.rs +0 -0
  206. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/set_operations.rs +0 -0
  207. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/subset_functions.rs +0 -0
  208. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/trace_function.rs +0 -0
  209. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/type_function.rs +0 -0
  210. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/type_inference.rs +0 -0
  211. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/src/ucum.rs +0 -0
  212. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/all_function_tests.rs +0 -0
  213. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/boundary_debug_tests.rs +0 -0
  214. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/boundary_function_integration_tests.rs +0 -0
  215. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/comment_test.rs +0 -0
  216. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/common/context.rs +0 -0
  217. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/common/parser.rs +0 -0
  218. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/context_trace_test.rs +0 -0
  219. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/observation-example.json +0 -0
  220. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/observation-example.xml +0 -0
  221. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/patient-example.json +0 -0
  222. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/patient-example.xml +0 -0
  223. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/questionnaire-example.json +0 -0
  224. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/questionnaire-example.xml +0 -0
  225. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/valueset-example-expansion.json +0 -0
  226. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/valueset-example-expansion.xml +0 -0
  227. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/tests-fhir-r4.xml +0 -0
  228. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/appointment-examplereq.json +0 -0
  229. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/ccda.json +0 -0
  230. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/codesystem-example.json +0 -0
  231. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/conceptmap-example.json +0 -0
  232. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/diagnosticreport-eric.json +0 -0
  233. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/explanationofbenefit-example.json +0 -0
  234. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/observation-example.json +0 -0
  235. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/observation-example.xml +0 -0
  236. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/parameters-example-types.json +0 -0
  237. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-container-example.json +0 -0
  238. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-example-name.json +0 -0
  239. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-example-period.json +0 -0
  240. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-example.json +0 -0
  241. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-name-extensions.json +0 -0
  242. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/questionnaire-example.json +0 -0
  243. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/valueset-example-expansion.json +0 -0
  244. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/data/testSchema.xsd +0 -0
  245. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/date_operation_tests.rs +0 -0
  246. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/datetime_boundary_tests.rs +0 -0
  247. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/debug_datetime_boundary.rs +0 -0
  248. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/debug_string_boundary_tests.rs +0 -0
  249. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/define_variable_test.rs +0 -0
  250. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/enhanced_variable_tests.rs +0 -0
  251. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/evaluator_tests.rs +0 -0
  252. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/extension_tests.rs +0 -0
  253. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/fhir_boundary_tests.rs +0 -0
  254. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/http_compression.rs +0 -0
  255. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/is_as_method_tests.rs +0 -0
  256. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/join_function_test.rs +0 -0
  257. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/oftype_datetime_tests.rs +0 -0
  258. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/parse_debug_test.rs +0 -0
  259. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/parser_tests.rs +0 -0
  260. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/polymorphic_r4_tests.rs +0 -0
  261. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/polymorphic_tests.rs +0 -0
  262. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/precision_tests.rs +0 -0
  263. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/reference_key_debug.rs +0 -0
  264. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/test_boundary_zero.rs +0 -0
  265. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/trace_api_test.rs +0 -0
  266. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/trace_tests.rs +0 -0
  267. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/tree_navigation_tests.rs +0 -0
  268. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/truncate_tests.rs +0 -0
  269. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/type_operation_tests.rs +0 -0
  270. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/type_preservation_integration_test.rs +0 -0
  271. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/type_reflection_tests.rs +0 -0
  272. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/unicode_scalar_value_tests.rs +0 -0
  273. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/uri_type_test.rs +0 -0
  274. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath/tests/uuid_type_preservation_test.rs +0 -0
  275. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath-support/Cargo.toml +0 -0
  276. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath-support/README.md +0 -0
  277. {pysof-0.2.1 → pysof-0.2.4}/crates/fhirpath-support/src/type_info.rs +0 -0
  278. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/Cargo.lock +0 -0
  279. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/Makefile +0 -0
  280. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/PYPI_CHECKLIST.md +0 -0
  281. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/WHEEL_BUILDING.md +0 -0
  282. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/__init__.py +0 -0
  283. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/test_content_types.py +0 -0
  284. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/test_fhir_versions.py +0 -0
  285. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/test_import.py +0 -0
  286. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/test_remote_resolve.py +0 -0
  287. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/python-tests/test_source_errors.py +0 -0
  288. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/scripts/build-wheels.py +0 -0
  289. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/src/pysof/py.typed +0 -0
  290. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/integration/error_handling.rs +0 -0
  291. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/integration/fhir_versions.rs +0 -0
  292. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/integration/mod.rs +0 -0
  293. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/lib_tests.rs +0 -0
  294. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/multithreading_integration.rs +0 -0
  295. {pysof-0.2.1 → pysof-0.2.4}/crates/pysof/tests/threading_test.rs +0 -0
  296. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/benches/parallel_processing_bench.rs +0 -0
  297. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/compartment.rs +0 -0
  298. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/constants.rs +0 -0
  299. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/data_source.rs +0 -0
  300. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/fhir_format.rs +0 -0
  301. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/mod.rs +0 -0
  302. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/parquet_schema.rs +0 -0
  303. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/parquet_zip.rs +0 -0
  304. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/reference_collector.rs +0 -0
  305. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/remote_fetch.rs +0 -0
  306. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/remote_resolver.rs +0 -0
  307. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/sqlquery/output.rs +0 -0
  308. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/src/traits.rs +0 -0
  309. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_boolean_test.rs +0 -0
  310. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_column_ordering.rs +0 -0
  311. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_datetime_instant_constants.rs +0 -0
  312. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_datetime_type_info.rs +0 -0
  313. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_enum_conversion.rs +0 -0
  314. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_evaluation_result_conversion.rs +0 -0
  315. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_extension_function.rs +0 -0
  316. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_extension_macro_fix.rs +0 -0
  317. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_extension_simple.rs +0 -0
  318. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_fhir_resource_structure.rs +0 -0
  319. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_foreach_combinations.rs +0 -0
  320. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_inequality.rs +0 -0
  321. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_instant_constant.rs +0 -0
  322. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_instant_type_info.rs +0 -0
  323. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_raw_resource.rs +0 -0
  324. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/debug_reference_key_types.rs +0 -0
  325. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/extension_debug_test.rs +0 -0
  326. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/foreach_test.rs +0 -0
  327. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/multiselect_test.rs +0 -0
  328. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/resolve_remote_tests.rs +0 -0
  329. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/resolve_tests.rs +0 -0
  330. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/basic.json +0 -0
  331. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/collection.json +0 -0
  332. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/combinations.json +0 -0
  333. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/constant.json +0 -0
  334. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/constant_types.json +0 -0
  335. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fhirpath.json +0 -0
  336. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fhirpath_numbers.json +0 -0
  337. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fn_boundary.json +0 -0
  338. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fn_empty.json +0 -0
  339. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fn_extension.json +0 -0
  340. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fn_first.json +0 -0
  341. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fn_join.json +0 -0
  342. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fn_oftype.json +0 -0
  343. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/fn_reference_keys.json +0 -0
  344. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/foreach.json +0 -0
  345. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/logic.json +0 -0
  346. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/row_index.json +0 -0
  347. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/union.json +0 -0
  348. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/validate.json +0 -0
  349. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/view_resource.json +0 -0
  350. {pysof-0.2.1/crates/sof/tests/sql-on-fhir-v2 → pysof-0.2.4/crates/sof/tests/sql-on-fhir}/tests/where.json +0 -0
  351. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_boolean_constant_debug.rs +0 -0
  352. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_boolean_constant_debug2.rs +0 -0
  353. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_boolean_constant_debug3.rs +0 -0
  354. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_boolean_validation.rs +0 -0
  355. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_cli_file_source.rs +0 -0
  356. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_csv_quote_handling.rs +0 -0
  357. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_extension_fix_verification.rs +0 -0
  358. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_extension_value_access.rs +0 -0
  359. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_ndjson_input.rs +0 -0
  360. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_parallel_working.rs +0 -0
  361. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_parquet_export.rs +0 -0
  362. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_parquet_large_dataset.rs +0 -0
  363. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_parquet_server_options.rs +0 -0
  364. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_shortened_format_names.rs +0 -0
  365. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_where_clause_validation.rs +0 -0
  366. {pysof-0.2.1 → pysof-0.2.4}/crates/sof/tests/test_x_ndjson_support.rs +0 -0
  367. {pysof-0.2.1 → pysof-0.2.4}/src/pysof/py.typed +0 -0
@@ -17,8 +17,8 @@ crate-type = ["cdylib"]
17
17
 
18
18
  [dependencies]
19
19
  pyo3 = { version = ">=0.29", features = ["extension-module", "generate-import-lib"] }
20
- helios-sof = { path = "../sof", version = "0.2.1", default-features = false }
21
- helios-fhir = { path = "../fhir", version = "0.2.1", default-features = false }
20
+ helios-sof = { path = "../sof", version = "0.2.4", default-features = false }
21
+ helios-fhir = { path = "../fhir", version = "0.2.4", default-features = false }
22
22
  serde = { workspace = true }
23
23
  serde_json = { workspace = true }
24
24
  chrono = { version = "0.4", features = ["serde"] }
@@ -27,6 +27,7 @@ csv = "1.3"
27
27
  # Drives helios-sof's async remote-resolve functions from the synchronous
28
28
  # PyO3 entry points via a current-thread runtime.
29
29
  tokio = { version = "1", default-features = false, features = ["rt", "net", "time"] }
30
+ mimalloc = "0.1.52"
30
31
 
31
32
  [features]
32
33
  default = ["R4"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pysof
3
- Version: 0.2.1
3
+ Version: 0.2.4
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.10
6
6
  Classifier: Programming Language :: Python :: 3.11
@@ -34,7 +34,7 @@ Project-URL: Source, https://github.com/HeliosSoftware/hfs/tree/main/crates/pyso
34
34
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
35
35
  [![Downloads](https://pepy.tech/badge/pysof)](https://pepy.tech/project/pysof)
36
36
 
37
- **High-performance FHIR data transformation for Python.** Transform FHIR resources into tabular formats (CSV, JSON, Parquet) using declarative ViewDefinitions from the [SQL on FHIR specification](https://build.fhir.org/ig/FHIR/sql-on-fhir-v2/).
37
+ **High-performance FHIR data transformation for Python.** Transform FHIR resources into tabular formats (CSV, JSON, Parquet) using declarative ViewDefinitions from the [SQL on FHIR specification](http://hl7.org/fhir/uv/sql-on-fhir/).
38
38
 
39
39
  Built in Rust for speed, exposed to Python with a simple, Pythonic API. Part of the [Helios FHIR Server](https://github.com/HeliosSoftware/hfs) project.
40
40
 
@@ -46,7 +46,8 @@ Built in Rust for speed, exposed to Python with a simple, Pythonic API. Part of
46
46
  - 📦 **Streaming Support**: Memory-efficient chunked processing for large NDJSON files
47
47
  - 🌐 **Multi-Version FHIR**: Supports R4, R4B, R5, and R6 (based on build features)
48
48
  - 🎯 **Type-Safe**: Leverages Rust's type safety with a Pythonic interface
49
- - ⚡ **GIL-Free**: Python GIL released during processing for true parallelism
49
+ - ⚡ **GIL-Friendly**: the GIL is released during parsing and processing, so other Python threads stay responsive
50
+ - 📨 **Flexible Input**: ViewDefinitions and Bundles as Python dicts or pre-serialized JSON (`str`/`bytes`)
50
51
 
51
52
  ## 🎯 Why pysof?
52
53
 
@@ -314,18 +315,46 @@ pysof automatically processes FHIR resources in parallel using rayon:
314
315
  - **5-7x speedup** on typical batch workloads with multi-core CPUs
315
316
  - **Streaming benefits**: `ChunkedProcessor` and `process_ndjson_to_file` also use parallel processing
316
317
  - **Zero configuration** - parallelization is always enabled
317
- - **Python GIL released** during processing for true parallel execution
318
+ - **Python GIL released** during parsing and processing, so other Python threads stay responsive
319
+
320
+ Because each call already fans out across all cores via rayon's shared thread
321
+ pool, running pysof from multiple Python threads does **not** multiply
322
+ throughput — one call can saturate the machine. Use Python threads for
323
+ concurrency (overlapping I/O, serving requests), not to speed up transforms.
324
+
325
+ ### Pass Pre-Serialized JSON for Maximum Speed
326
+
327
+ If your data is already JSON text (from a file, an HTTP body, a database), pass
328
+ the `str` or `bytes` directly instead of `json.loads`-ing it first:
329
+
330
+ ```python
331
+ view_json: str = load_view_definition_text()
332
+ bundle_json: bytes = fetch_bundle_bytes()
333
+
334
+ result = pysof.run_view_definition(view_json, bundle_json, "csv")
335
+ ```
336
+
337
+ This skips the Python-dict conversion entirely and parses the JSON with the
338
+ GIL released — measured 20-27% faster per call on large bundles, with GIL hold
339
+ time dropping from tens of milliseconds to microseconds.
318
340
 
319
341
  ### Performance Benchmarks
320
342
 
321
- | Mode | Dataset | Time | Memory | Notes |
322
- |------|---------|------|--------|-------|
323
- | **Batch** | 10k Patients | ~2.7s | 1.6 GB | All resources in memory |
324
- | **Streaming** | 10k Patients | ~0.9s | 45 MB | 35x less memory, 2.9x faster |
325
- | **Batch** | 93k Encounters | ~4s | 3.9 GB | All resources in memory |
326
- | **Streaming** | 93k Encounters | ~2.8s | 25 MB | 155x less memory, 1.4x faster |
343
+ Measured with `scripts/bench_threading.py` (a 7-column Patient ViewDefinition;
344
+ Windows 11, 12 logical CPUs, Python 3.11, release build with mimalloc):
345
+
346
+ | Path | Dataset | Throughput |
347
+ |------|---------|-----------|
348
+ | **Batch** (dict input) | 2,000-patient bundle | ~28k patients/sec |
349
+ | **Batch** (JSON `str` input) | 2,000-patient bundle | ~31k patients/sec |
350
+ | **Streaming** (`process_ndjson_to_file`) | 5,000-patient NDJSON | ~31k patients/sec |
351
+
352
+ Numbers vary with hardware and ViewDefinition complexity — re-run
353
+ `scripts/bench_threading.py` on your target machine.
327
354
 
328
- Streaming mode (`ChunkedProcessor`, `process_ndjson_to_file`) is recommended for large NDJSON files.
355
+ Streaming mode (`ChunkedProcessor`, `process_ndjson_to_file`) keeps memory
356
+ bounded by `chunk_size` regardless of input size, so it is recommended for
357
+ large NDJSON files; batch mode holds the whole bundle and result in memory.
329
358
 
330
359
  ### Controlling Thread Count (RAYON_NUM_THREADS)
331
360
 
@@ -5,7 +5,7 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
  [![Downloads](https://pepy.tech/badge/pysof)](https://pepy.tech/project/pysof)
7
7
 
8
- **High-performance FHIR data transformation for Python.** Transform FHIR resources into tabular formats (CSV, JSON, Parquet) using declarative ViewDefinitions from the [SQL on FHIR specification](https://build.fhir.org/ig/FHIR/sql-on-fhir-v2/).
8
+ **High-performance FHIR data transformation for Python.** Transform FHIR resources into tabular formats (CSV, JSON, Parquet) using declarative ViewDefinitions from the [SQL on FHIR specification](http://hl7.org/fhir/uv/sql-on-fhir/).
9
9
 
10
10
  Built in Rust for speed, exposed to Python with a simple, Pythonic API. Part of the [Helios FHIR Server](https://github.com/HeliosSoftware/hfs) project.
11
11
 
@@ -17,7 +17,8 @@ Built in Rust for speed, exposed to Python with a simple, Pythonic API. Part of
17
17
  - 📦 **Streaming Support**: Memory-efficient chunked processing for large NDJSON files
18
18
  - 🌐 **Multi-Version FHIR**: Supports R4, R4B, R5, and R6 (based on build features)
19
19
  - 🎯 **Type-Safe**: Leverages Rust's type safety with a Pythonic interface
20
- - ⚡ **GIL-Free**: Python GIL released during processing for true parallelism
20
+ - ⚡ **GIL-Friendly**: the GIL is released during parsing and processing, so other Python threads stay responsive
21
+ - 📨 **Flexible Input**: ViewDefinitions and Bundles as Python dicts or pre-serialized JSON (`str`/`bytes`)
21
22
 
22
23
  ## 🎯 Why pysof?
23
24
 
@@ -285,18 +286,46 @@ pysof automatically processes FHIR resources in parallel using rayon:
285
286
  - **5-7x speedup** on typical batch workloads with multi-core CPUs
286
287
  - **Streaming benefits**: `ChunkedProcessor` and `process_ndjson_to_file` also use parallel processing
287
288
  - **Zero configuration** - parallelization is always enabled
288
- - **Python GIL released** during processing for true parallel execution
289
+ - **Python GIL released** during parsing and processing, so other Python threads stay responsive
290
+
291
+ Because each call already fans out across all cores via rayon's shared thread
292
+ pool, running pysof from multiple Python threads does **not** multiply
293
+ throughput — one call can saturate the machine. Use Python threads for
294
+ concurrency (overlapping I/O, serving requests), not to speed up transforms.
295
+
296
+ ### Pass Pre-Serialized JSON for Maximum Speed
297
+
298
+ If your data is already JSON text (from a file, an HTTP body, a database), pass
299
+ the `str` or `bytes` directly instead of `json.loads`-ing it first:
300
+
301
+ ```python
302
+ view_json: str = load_view_definition_text()
303
+ bundle_json: bytes = fetch_bundle_bytes()
304
+
305
+ result = pysof.run_view_definition(view_json, bundle_json, "csv")
306
+ ```
307
+
308
+ This skips the Python-dict conversion entirely and parses the JSON with the
309
+ GIL released — measured 20-27% faster per call on large bundles, with GIL hold
310
+ time dropping from tens of milliseconds to microseconds.
289
311
 
290
312
  ### Performance Benchmarks
291
313
 
292
- | Mode | Dataset | Time | Memory | Notes |
293
- |------|---------|------|--------|-------|
294
- | **Batch** | 10k Patients | ~2.7s | 1.6 GB | All resources in memory |
295
- | **Streaming** | 10k Patients | ~0.9s | 45 MB | 35x less memory, 2.9x faster |
296
- | **Batch** | 93k Encounters | ~4s | 3.9 GB | All resources in memory |
297
- | **Streaming** | 93k Encounters | ~2.8s | 25 MB | 155x less memory, 1.4x faster |
314
+ Measured with `scripts/bench_threading.py` (a 7-column Patient ViewDefinition;
315
+ Windows 11, 12 logical CPUs, Python 3.11, release build with mimalloc):
316
+
317
+ | Path | Dataset | Throughput |
318
+ |------|---------|-----------|
319
+ | **Batch** (dict input) | 2,000-patient bundle | ~28k patients/sec |
320
+ | **Batch** (JSON `str` input) | 2,000-patient bundle | ~31k patients/sec |
321
+ | **Streaming** (`process_ndjson_to_file`) | 5,000-patient NDJSON | ~31k patients/sec |
322
+
323
+ Numbers vary with hardware and ViewDefinition complexity — re-run
324
+ `scripts/bench_threading.py` on your target machine.
298
325
 
299
- Streaming mode (`ChunkedProcessor`, `process_ndjson_to_file`) is recommended for large NDJSON files.
326
+ Streaming mode (`ChunkedProcessor`, `process_ndjson_to_file`) keeps memory
327
+ bounded by `chunk_size` regardless of input size, so it is recommended for
328
+ large NDJSON files; batch mode holds the whole bundle and result in memory.
300
329
 
301
330
  ### Controlling Thread Count (RAYON_NUM_THREADS)
302
331
 
@@ -24,9 +24,9 @@ xml = ["helios-serde-support/xml"]
24
24
  serde = { workspace = true }
25
25
  serde_json = { workspace = true, features = ["raw_value"] }
26
26
  clap = { version = "4.0", features = ["derive"] }
27
- helios-fhir-macro = { path = "../fhir-macro", version = "0.2.1" }
28
- helios-serde-support = { path = "../serde-support", version = "0.2.1" }
29
- helios-fhirpath-support = { path = "../fhirpath-support", version = "0.2.1" }
27
+ helios-fhir-macro = { path = "../fhir-macro", version = "0.2.4" }
28
+ helios-serde-support = { path = "../serde-support", version = "0.2.4" }
29
+ helios-fhirpath-support = { path = "../fhirpath-support", version = "0.2.4" }
30
30
  time = "0.3"
31
31
  chrono = { workspace = true }
32
32
  # Re-add serde-with-arbitrary-precision, keep macros
@@ -0,0 +1,178 @@
1
+ //! CompartmentDefinition loader.
2
+ //!
3
+ //! Reads the FHIR spec `CompartmentDefinition` resources from the data
4
+ //! directory, as stored-shape JSON ready to seed into storage. This is the
5
+ //! compartment analogue of
6
+ //! [`SearchParameterLoader::load_spec_resources`](crate::search::loader::SearchParameterLoader::load_spec_resources):
7
+ //! the server seeds these into primary storage at startup so
8
+ //! `GET /CompartmentDefinition` and the web UI read the same definitions the
9
+ //! codegen'd membership table (`crate::get_compartment_params`) is built from.
10
+
11
+ use std::path::Path;
12
+
13
+ use serde_json::Value;
14
+
15
+ use crate::FhirVersion;
16
+ use crate::search::errors::LoaderError;
17
+
18
+ /// Loader for CompartmentDefinition spec resources.
19
+ pub struct CompartmentDefinitionLoader {
20
+ fhir_version: FhirVersion,
21
+ }
22
+
23
+ impl CompartmentDefinitionLoader {
24
+ /// Creates a new loader for the specified FHIR version.
25
+ pub fn new(fhir_version: FhirVersion) -> Self {
26
+ Self { fhir_version }
27
+ }
28
+
29
+ /// Returns the FHIR version.
30
+ pub fn version(&self) -> FhirVersion {
31
+ self.fhir_version
32
+ }
33
+
34
+ /// Returns the spec bundle filename for the configured FHIR version.
35
+ ///
36
+ /// Mirrors the `compartment-definitions-{version}.json` bundles shipped
37
+ /// under the data directory, alongside `search-parameters-{version}.json`.
38
+ #[allow(unreachable_patterns)]
39
+ pub fn spec_filename(&self) -> &'static str {
40
+ match self.fhir_version {
41
+ #[cfg(feature = "R4")]
42
+ FhirVersion::R4 => "compartment-definitions-r4.json",
43
+ #[cfg(feature = "R4B")]
44
+ FhirVersion::R4B => "compartment-definitions-r4b.json",
45
+ #[cfg(feature = "R5")]
46
+ FhirVersion::R5 => "compartment-definitions-r5.json",
47
+ #[cfg(feature = "R6")]
48
+ FhirVersion::R6 => "compartment-definitions-r6.json",
49
+ _ => "compartment-definitions-r4.json",
50
+ }
51
+ }
52
+
53
+ /// Returns the raw CompartmentDefinition resources from the spec bundle,
54
+ /// as stored-shape JSON.
55
+ ///
56
+ /// The seeding companion the server hands to storage: each entry carries
57
+ /// its bundle id (`patient`, `encounter`, …), so re-seeding is idempotent
58
+ /// via `create`'s `AlreadyExists`.
59
+ pub fn load_spec_resources(&self, data_dir: &Path) -> Result<Vec<Value>, LoaderError> {
60
+ let path = data_dir.join(self.spec_filename());
61
+ let content =
62
+ std::fs::read_to_string(&path).map_err(|e| LoaderError::ConfigLoadFailed {
63
+ path: path.display().to_string(),
64
+ message: e.to_string(),
65
+ })?;
66
+ let json: Value =
67
+ serde_json::from_str(&content).map_err(|e| LoaderError::ConfigLoadFailed {
68
+ path: path.display().to_string(),
69
+ message: format!("Invalid JSON: {}", e),
70
+ })?;
71
+
72
+ let mut resources = Vec::new();
73
+ if let Some(entries) = json.get("entry").and_then(|e| e.as_array()) {
74
+ for entry in entries {
75
+ if let Some(resource) = entry.get("resource")
76
+ && resource.get("resourceType").and_then(|t| t.as_str())
77
+ == Some("CompartmentDefinition")
78
+ {
79
+ resources.push(resource.clone());
80
+ }
81
+ }
82
+ }
83
+ Ok(resources)
84
+ }
85
+ }
86
+
87
+ #[cfg(test)]
88
+ mod tests {
89
+ use super::*;
90
+ use std::path::PathBuf;
91
+
92
+ /// Repo-root `data/` directory, from this crate's manifest dir.
93
+ fn workspace_data_dir() -> PathBuf {
94
+ PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../data")
95
+ }
96
+
97
+ #[cfg(feature = "R4")]
98
+ #[test]
99
+ fn loads_r4_compartment_definitions() {
100
+ let loader = CompartmentDefinitionLoader::new(FhirVersion::R4);
101
+ let resources = loader.load_spec_resources(&workspace_data_dir()).unwrap();
102
+ // Device, Encounter, Patient, Practitioner, RelatedPerson (questionnaire
103
+ // has no code and is excluded from the bundle).
104
+ assert_eq!(resources.len(), 5);
105
+ assert!(
106
+ resources
107
+ .iter()
108
+ .all(|r| r["resourceType"] == "CompartmentDefinition")
109
+ );
110
+ assert!(resources.iter().any(|r| r["code"] == "Patient"));
111
+ assert!(
112
+ resources
113
+ .iter()
114
+ .all(|r| r.get("id").and_then(|i| i.as_str()).is_some())
115
+ );
116
+ }
117
+
118
+ #[test]
119
+ fn missing_dir_errors() {
120
+ let loader = CompartmentDefinitionLoader::new(FhirVersion::default_enabled());
121
+ assert!(
122
+ loader
123
+ .load_spec_resources(Path::new("/nonexistent/data/dir"))
124
+ .is_err()
125
+ );
126
+ }
127
+
128
+ /// The shipped `data/compartment-definitions-*.json` bundles must say
129
+ /// exactly what the codegen'd `get_compartment_params` table says — every
130
+ /// `(compartment, resource)` slot, every version. This is the guard against
131
+ /// the seeded copies drifting from `crates/fhir-gen/resources/`.
132
+ fn assert_parity(version: FhirVersion) {
133
+ let loader = CompartmentDefinitionLoader::new(version);
134
+ let defs = loader.load_spec_resources(&workspace_data_dir()).unwrap();
135
+ assert!(!defs.is_empty(), "{version:?} bundle is empty");
136
+ for def in &defs {
137
+ let code = def["code"].as_str().unwrap();
138
+ for resource in def["resource"].as_array().unwrap() {
139
+ let rtype = resource["code"].as_str().unwrap();
140
+ let params: Vec<&str> = resource
141
+ .get("param")
142
+ .and_then(|p| p.as_array())
143
+ .map(|a| a.iter().filter_map(|v| v.as_str()).collect())
144
+ .unwrap_or_default();
145
+ let runtime = crate::get_compartment_params(version, code, rtype);
146
+ assert_eq!(
147
+ runtime,
148
+ params.as_slice(),
149
+ "{version:?} compartment {code} / {rtype}"
150
+ );
151
+ }
152
+ }
153
+ }
154
+
155
+ #[cfg(feature = "R4")]
156
+ #[test]
157
+ fn r4_bundle_matches_codegen_table() {
158
+ assert_parity(FhirVersion::R4);
159
+ }
160
+
161
+ #[cfg(feature = "R4B")]
162
+ #[test]
163
+ fn r4b_bundle_matches_codegen_table() {
164
+ assert_parity(FhirVersion::R4B);
165
+ }
166
+
167
+ #[cfg(feature = "R5")]
168
+ #[test]
169
+ fn r5_bundle_matches_codegen_table() {
170
+ assert_parity(FhirVersion::R5);
171
+ }
172
+
173
+ #[cfg(feature = "R6")]
174
+ #[test]
175
+ fn r6_bundle_matches_codegen_table() {
176
+ assert_parity(FhirVersion::R6);
177
+ }
178
+ }
@@ -0,0 +1,15 @@
1
+ //! FHIR CompartmentDefinition spec data.
2
+ //!
3
+ //! Companion to [`crate::search`]: where SearchParameters drive search
4
+ //! resolution, CompartmentDefinitions describe the compartment membership the
5
+ //! REST compartment-search handler enforces (via the codegen'd
6
+ //! [`crate::get_compartment_params`] table). This module only *loads* the spec
7
+ //! resources so the server can seed them into storage — the source of truth the
8
+ //! `GET /CompartmentDefinition` route and the web UI read from. Membership
9
+ //! itself stays codegen-driven.
10
+ //!
11
+ //! - [`loader`] – [`CompartmentDefinitionLoader`] for reading the spec bundle.
12
+
13
+ pub mod loader;
14
+
15
+ pub use loader::CompartmentDefinitionLoader;