resolvekit 0.1.6__tar.gz → 0.1.8__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 (343) hide show
  1. {resolvekit-0.1.6 → resolvekit-0.1.8}/PKG-INFO +1 -1
  2. {resolvekit-0.1.6 → resolvekit-0.1.8}/pyproject.toml +1 -1
  3. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/containment_api.py +5 -3
  4. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/byod/cache.py +38 -12
  5. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/interfaces.py +4 -0
  6. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/multi_runner.py +4 -0
  7. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/runner.py +4 -0
  8. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/store/interface.py +9 -0
  9. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/store/sqlite.py +11 -0
  10. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/store/store_view.py +23 -2
  11. {resolvekit-0.1.6 → resolvekit-0.1.8}/LICENSE +0 -0
  12. {resolvekit-0.1.6 → resolvekit-0.1.8}/README.md +0 -0
  13. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/NOTICE.md +0 -0
  14. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/__init__.py +0 -0
  15. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_convenience.py +0 -0
  16. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/admin1/metadata.json +0 -0
  17. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/admin2/metadata.json +0 -0
  18. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/admin3/metadata.json +0 -0
  19. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/admin4/metadata.json +0 -0
  20. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/admin5/metadata.json +0 -0
  21. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/cities/metadata.json +0 -0
  22. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/continental_unions/entities.sqlite +0 -0
  23. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/continental_unions/metadata.json +0 -0
  24. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/continental_unions/symspell.dict +0 -0
  25. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/continents/entities.sqlite +0 -0
  26. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/continents/metadata.json +0 -0
  27. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/continents/symspell.dict +0 -0
  28. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/countries/entities.sqlite +0 -0
  29. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/countries/geo_calibrator.json +0 -0
  30. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/countries/metadata.json +0 -0
  31. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/countries/symspell.dict +0 -0
  32. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/regions/entities.sqlite +0 -0
  33. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/regions/metadata.json +0 -0
  34. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/geo/regions/symspell.dict +0 -0
  35. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/manifest.json +0 -0
  36. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/companies/entities.sqlite +0 -0
  37. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/companies/metadata.json +0 -0
  38. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/companies/symspell.dict +0 -0
  39. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/data_sources/entities.sqlite +0 -0
  40. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/data_sources/metadata.json +0 -0
  41. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/data_sources/symspell.dict +0 -0
  42. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/governments/entities.sqlite +0 -0
  43. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/governments/metadata.json +0 -0
  44. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/governments/symspell.dict +0 -0
  45. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/lenders/entities.sqlite +0 -0
  46. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/lenders/metadata.json +0 -0
  47. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/lenders/symspell.dict +0 -0
  48. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/political_parties/entities.sqlite +0 -0
  49. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/political_parties/metadata.json +0 -0
  50. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/political_parties/symspell.dict +0 -0
  51. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/providers/entities.sqlite +0 -0
  52. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/providers/metadata.json +0 -0
  53. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/org/providers/symspell.dict +0 -0
  54. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_data/parse/deny_list.json +0 -0
  55. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_pandas_integration.py +0 -0
  56. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/_polars_integration.py +0 -0
  57. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/__init__.py +0 -0
  58. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/_outcomes.py +0 -0
  59. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/api.py +0 -0
  60. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/containment.py +0 -0
  61. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/country_geonames_aliases.py +0 -0
  62. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/datapack_layout.py +0 -0
  63. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/entity_validity.py +0 -0
  64. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/formal_names.py +0 -0
  65. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/geo_shared.py +0 -0
  66. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/groups.py +0 -0
  67. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/inspection.py +0 -0
  68. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/models.py +0 -0
  69. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/module_catalog.py +0 -0
  70. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/oecd_dac.py +0 -0
  71. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/__init__.py +0 -0
  72. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/build_report.py +0 -0
  73. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/changelog.py +0 -0
  74. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/chunk.py +0 -0
  75. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/contribution.py +0 -0
  76. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/core.py +0 -0
  77. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/discover.py +0 -0
  78. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/enrich.py +0 -0
  79. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/geo_staging.py +0 -0
  80. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/packaging.py +0 -0
  81. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/promote.py +0 -0
  82. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/qa.py +0 -0
  83. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/reconcile.py +0 -0
  84. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/stages.py +0 -0
  85. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/pipeline/types.py +0 -0
  86. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/presets.py +0 -0
  87. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/registry.py +0 -0
  88. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/__init__.py +0 -0
  89. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/__init__.py +0 -0
  90. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/adapter.py +0 -0
  91. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/base_dc_api.py +0 -0
  92. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/bundle.py +0 -0
  93. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/canonicalize.py +0 -0
  94. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/client.py +0 -0
  95. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/constants.py +0 -0
  96. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/__init__.py +0 -0
  97. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/_admin_walk.py +0 -0
  98. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/_chunk_callback.py +0 -0
  99. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/_geo_regions.py +0 -0
  100. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/_ordered_emitter.py +0 -0
  101. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/_progress_context.py +0 -0
  102. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/_streaming.py +0 -0
  103. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/_type_mappings.py +0 -0
  104. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/adapter.py +0 -0
  105. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/dc_api.py +0 -0
  106. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/discovery.py +0 -0
  107. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/fetch.py +0 -0
  108. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/mappings.py +0 -0
  109. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/profile.py +0 -0
  110. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/geo/prominence.py +0 -0
  111. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/models.py +0 -0
  112. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/node.py +0 -0
  113. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/org/__init__.py +0 -0
  114. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/org/adapter.py +0 -0
  115. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/org/dc_api.py +0 -0
  116. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/org/discovery.py +0 -0
  117. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/org/fetch.py +0 -0
  118. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/org/mappings.py +0 -0
  119. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/org/profile.py +0 -0
  120. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/rows.py +0 -0
  121. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/specs.py +0 -0
  122. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/datacommons/text.py +0 -0
  123. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/discovery_events.py +0 -0
  124. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/protocol.py +0 -0
  125. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/seed/__init__.py +0 -0
  126. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/seed/continents.py +0 -0
  127. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/seed/m49.py +0 -0
  128. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/wikidata/__init__.py +0 -0
  129. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/wikidata/aliases.py +0 -0
  130. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sources/wikidata/sitelinks.py +0 -0
  131. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sqlite/__init__.py +0 -0
  132. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sqlite/constants.py +0 -0
  133. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sqlite/context.py +0 -0
  134. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sqlite/diff.py +0 -0
  135. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sqlite/export.py +0 -0
  136. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sqlite/specs.py +0 -0
  137. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sqlite/validate.py +0 -0
  138. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/sqlite/write.py +0 -0
  139. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/state.py +0 -0
  140. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/builder/utils.py +0 -0
  141. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/__init__.py +0 -0
  142. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/__init__.py +0 -0
  143. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/_cldr_source.py +0 -0
  144. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/_latin_filter.py +0 -0
  145. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/_wikidata_client.py +0 -0
  146. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/cldr.py +0 -0
  147. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/geonames.py +0 -0
  148. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/multilingual_names.py +0 -0
  149. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/synthetic.py +0 -0
  150. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/adapters/wikidata.py +0 -0
  151. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/dataset.py +0 -0
  152. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/evaluation.py +0 -0
  153. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/fitting.py +0 -0
  154. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/models.py +0 -0
  155. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/scoring_model.py +0 -0
  156. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/train.py +0 -0
  157. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/calibration/vectorize.py +0 -0
  158. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/__init__.py +0 -0
  159. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/__init__.py +0 -0
  160. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/_byod.py +0 -0
  161. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/_pivot.py +0 -0
  162. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/batch.py +0 -0
  163. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/bulk.py +0 -0
  164. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/cache.py +0 -0
  165. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/code_lookup.py +0 -0
  166. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/context_input.py +0 -0
  167. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/diagnostics.py +0 -0
  168. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/entity_lookup.py +0 -0
  169. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/group_api.py +0 -0
  170. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/info.py +0 -0
  171. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/inspect.py +0 -0
  172. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/loading/__init__.py +0 -0
  173. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/loading/module_catalog.py +0 -0
  174. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/loading/pack_loader.py +0 -0
  175. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/loading/paths.py +0 -0
  176. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/loading/store_builder.py +0 -0
  177. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/modules.py +0 -0
  178. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/output_spec.py +0 -0
  179. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/output_view.py +0 -0
  180. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/query_prep.py +0 -0
  181. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/resolve_flow.py +0 -0
  182. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/resolver.py +0 -0
  183. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/snap.py +0 -0
  184. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/api/suggest_flow.py +0 -0
  185. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/byod/__init__.py +0 -0
  186. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/byod/build.py +0 -0
  187. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/byod/builder.py +0 -0
  188. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/byod/intake.py +0 -0
  189. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/byod/result.py +0 -0
  190. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/config.py +0 -0
  191. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/datapack.py +0 -0
  192. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/download_api.py +0 -0
  193. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/__init__.py +0 -0
  194. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/_stages.py +0 -0
  195. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/config.py +0 -0
  196. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/decision.py +0 -0
  197. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/enrichment.py +0 -0
  198. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/router.py +0 -0
  199. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/suggest_rank.py +0 -0
  200. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/engine/tier_utils.py +0 -0
  201. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/errors.py +0 -0
  202. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/errors_base.py +0 -0
  203. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/__init__.py +0 -0
  204. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/events.py +0 -0
  205. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/feature_text.py +0 -0
  206. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/helpers.py +0 -0
  207. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/protocol.py +0 -0
  208. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/renderers.py +0 -0
  209. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/result_html.py +0 -0
  210. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/result_types.py +0 -0
  211. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/scorecard.py +0 -0
  212. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/explain/sink.py +0 -0
  213. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/linking/__init__.py +0 -0
  214. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/linking/base_linker.py +0 -0
  215. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/linking/base_normalizer.py +0 -0
  216. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/linking/linker.py +0 -0
  217. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/linking/normalizer.py +0 -0
  218. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/merge.py +0 -0
  219. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/__init__.py +0 -0
  220. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/_repr.py +0 -0
  221. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/bulk_result.py +0 -0
  222. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/candidate.py +0 -0
  223. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/crosswalk.py +0 -0
  224. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/entity.py +0 -0
  225. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/entity_attributes.py +0 -0
  226. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/features.py +0 -0
  227. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/generation.py +0 -0
  228. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/inspection.py +0 -0
  229. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/name_grammar.py +0 -0
  230. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/query.py +0 -0
  231. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/model/result.py +0 -0
  232. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/module_registry.py +0 -0
  233. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/overlay_loader.py +0 -0
  234. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/__init__.py +0 -0
  235. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/_pivot.py +0 -0
  236. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/automaton.py +0 -0
  237. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/denylist.py +0 -0
  238. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/detect.py +0 -0
  239. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/engine.py +0 -0
  240. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/link.py +0 -0
  241. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/offsets.py +0 -0
  242. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/parse/result.py +0 -0
  243. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/registry.py +0 -0
  244. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/remote.py +0 -0
  245. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/store/__init__.py +0 -0
  246. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/store/composed_sqlite.py +0 -0
  247. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/store/composite.py +0 -0
  248. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/store/merging.py +0 -0
  249. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/store/sqlite_helpers.py +0 -0
  250. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/util/__init__.py +0 -0
  251. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/util/iso_codes.py +0 -0
  252. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/util/normalization.py +0 -0
  253. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/util/sentinel.py +0 -0
  254. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/core/version.py +0 -0
  255. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/diagnostics/__init__.py +0 -0
  256. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/errors/__init__.py +0 -0
  257. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/extensions.py +0 -0
  258. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/__init__.py +0 -0
  259. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/_artifacts.py +0 -0
  260. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/__init__.py +0 -0
  261. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/decision.py +0 -0
  262. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/extractor.py +0 -0
  263. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/features.py +0 -0
  264. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/normalizer.py +0 -0
  265. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/pack.py +0 -0
  266. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/scoring.py +0 -0
  267. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/sources/__init__.py +0 -0
  268. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/sources/exact_code.py +0 -0
  269. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/sources/exact_name.py +0 -0
  270. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/sources/fts.py +0 -0
  271. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/sources/fuzzy.py +0 -0
  272. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/custom/sources/fuzzy_retrieval.py +0 -0
  273. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/__init__.py +0 -0
  274. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/_specificity.py +0 -0
  275. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/build/__init__.py +0 -0
  276. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/build/builder.py +0 -0
  277. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/constraints/__init__.py +0 -0
  278. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/constraints/containment.py +0 -0
  279. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/constraints/membership.py +0 -0
  280. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/constraints/temporal.py +0 -0
  281. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/constraints/type_constraint.py +0 -0
  282. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/data/.gitkeep +0 -0
  283. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/decision.py +0 -0
  284. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/extractor.py +0 -0
  285. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/features.py +0 -0
  286. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/linker.py +0 -0
  287. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/normalizer.py +0 -0
  288. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/pack.py +0 -0
  289. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/routing.py +0 -0
  290. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/scoring.py +0 -0
  291. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/__init__.py +0 -0
  292. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/_short_input.py +0 -0
  293. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/exact_code.py +0 -0
  294. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/exact_name.py +0 -0
  295. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/fts.py +0 -0
  296. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/fuzzy.py +0 -0
  297. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/fuzzy_retrieval.py +0 -0
  298. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/query_shapes.py +0 -0
  299. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/geo/sources/symspell.py +0 -0
  300. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/__init__.py +0 -0
  301. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/_acronym.py +0 -0
  302. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/build/__init__.py +0 -0
  303. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/build/builder.py +0 -0
  304. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/constraints/__init__.py +0 -0
  305. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/constraints/country_relevance.py +0 -0
  306. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/constraints/parent_org.py +0 -0
  307. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/constraints/temporal.py +0 -0
  308. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/constraints/type_constraint.py +0 -0
  309. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/data/.gitkeep +0 -0
  310. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/decision.py +0 -0
  311. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/feature_extractor.py +0 -0
  312. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/features.py +0 -0
  313. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/linker.py +0 -0
  314. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/normalizer.py +0 -0
  315. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/pack.py +0 -0
  316. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/routing.py +0 -0
  317. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/scoring.py +0 -0
  318. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/sources/__init__.py +0 -0
  319. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/sources/acronym.py +0 -0
  320. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/sources/exact_code.py +0 -0
  321. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/sources/exact_name.py +0 -0
  322. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/sources/fts.py +0 -0
  323. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/sources/fuzzy.py +0 -0
  324. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/packs/org/sources/symspell.py +0 -0
  325. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/pandas/__init__.py +0 -0
  326. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/polars/__init__.py +0 -0
  327. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/py.typed +0 -0
  328. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/__init__.py +0 -0
  329. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/build/__init__.py +0 -0
  330. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/build/base_builder.py +0 -0
  331. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/build/schema.py +0 -0
  332. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/constraints/__init__.py +0 -0
  333. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/constraints/temporal_constraint.py +0 -0
  334. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/constraints/type_constraint.py +0 -0
  335. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/scoring_base.py +0 -0
  336. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/sources/__init__.py +0 -0
  337. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/sources/code_helpers.py +0 -0
  338. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/sources/fts_base.py +0 -0
  339. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/sources/fuzzy_base.py +0 -0
  340. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/sources/fuzzy_retrieval_base.py +0 -0
  341. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/sources/fuzzy_retrieval_brute_base.py +0 -0
  342. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/shared/sources/symspell_base.py +0 -0
  343. {resolvekit-0.1.6 → resolvekit-0.1.8}/src/resolvekit/types/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: resolvekit
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Entity and place resolution system that maps messy place/entity strings and codes to canonical entities
5
5
  Keywords: entity-resolution,geocoding,place-names,data-commons,iso-codes,offline,disambiguation,normalization
6
6
  Author: Jorge Rivera
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "resolvekit"
3
- version = "0.1.6"
3
+ version = "0.1.8"
4
4
  description = "Entity and place resolution system that maps messy place/entity strings and codes to canonical entities"
5
5
  requires-python = ">=3.12"
6
6
 
@@ -91,10 +91,12 @@ class ContainmentAPI:
91
91
  break
92
92
  frontier = next_frontier
93
93
 
94
- # Hydrate — drop entities the store can't resolve.
94
+ # Hydrate in one batch bulk bypasses the per-entity SQLite LRU cache, which is
95
+ # acceptable here: within()'s result set is not reused across calls.
96
+ hydrated = self._runner.bulk_get_entities(result_ids)
95
97
  records: list[EntityRecord] = []
96
- for eid in result_ids:
97
- entity = self._runner.get_entity(eid)
98
+ for eid in result_ids: # preserve BFS-collected order pre-sort
99
+ entity = hydrated.get(eid) # None-on-missing: absent IDs skipped
98
100
  if entity is None:
99
101
  continue
100
102
  if entity_type is not None and entity.entity_type not in entity_type:
@@ -19,11 +19,11 @@ A cache hit is ``dir.exists() and (dir / "metadata.json").exists()``.
19
19
  Atomicity and cleanup
20
20
  ---------------------
21
21
  On a cache miss the build writes to a sibling ``<key>.tmp`` directory, then
22
- ``os.replace(tmp, dir)`` atomically moves it. The superseded temp dir is
23
- removed with ``shutil.rmtree(tmp, ignore_errors=True)`` (matching the pattern
24
- in ``composed_sqlite.py:326``). When ``cache=False``, the build writes to a
25
- fresh temp directory that is NOT moved into the cache it is kept for the
26
- resolver's lifetime.
22
+ ``commit_build`` promotes it to the final location (first-writer-wins: if a
23
+ valid pack already exists at the target it is kept and the redundant build is
24
+ discarded; a corrupt leftover without ``metadata.json`` is cleared first).
25
+ When ``cache=False``, the build writes to a fresh temp directory that is NOT
26
+ moved into the cache — it is kept for the resolver's lifetime.
27
27
  """
28
28
 
29
29
  from __future__ import annotations
@@ -168,20 +168,46 @@ def prepare_build_dir(key: str, *, cache: bool) -> tuple[Path, Path | None]:
168
168
 
169
169
 
170
170
  def commit_build(build_dir: Path, final_dir: Path) -> None:
171
- """Atomically promote *build_dir* to *final_dir* and clean up.
171
+ """Promote *build_dir* into *final_dir*, tolerating an existing pack.
172
172
 
173
- Uses ``os.replace(build_dir, final_dir)`` for an atomic last-writer-wins
174
- swap. If the parent of *final_dir* does not exist it is created first.
173
+ The cache key is a content hash, so a pack already present at *final_dir* —
174
+ left by a concurrent build, a retry, or a re-submit of identical content —
175
+ is equivalent to the one just built. First writer wins: an existing valid
176
+ pack is kept and *build_dir* is discarded. A corrupt leftover (a directory
177
+ without ``metadata.json``) is cleared and replaced.
178
+
179
+ ``os.replace`` cannot rename a directory onto a non-empty one (POSIX raises
180
+ ENOTEMPTY / EEXIST), so the swap is attempted optimistically and the
181
+ populated-target case is recovered below. An ``OSError`` that does not
182
+ correspond to a populated *final_dir* (e.g. ENOSPC, a permission error) is
183
+ re-raised rather than silently swallowed.
175
184
 
176
185
  Args:
177
186
  build_dir: Temp directory where the build was written.
178
187
  final_dir: Target cache directory (``cached_pack_dir(key)``).
179
188
  """
180
189
  final_dir.parent.mkdir(parents=True, exist_ok=True)
181
- os.replace(build_dir, final_dir)
182
- # Belt-and-suspenders cleanup: ``shutil.rmtree`` with ignore_errors=True
183
- # handles both cases (build_dir doesn't exist after replace, or final_dir
184
- # was clobbered by a concurrent write) without raising.
190
+ try:
191
+ os.replace(build_dir, final_dir)
192
+ except OSError:
193
+ if is_cache_hit(final_dir):
194
+ # A concurrent build, retry, or re-submit already committed an
195
+ # equivalent pack; keep it and drop our redundant build below.
196
+ pass
197
+ elif final_dir.exists():
198
+ # Corrupt/incomplete leftover (no metadata.json): clear it and move
199
+ # our build in. If another writer races a valid pack into the slot
200
+ # first, accept that pack rather than surfacing the error.
201
+ shutil.rmtree(final_dir, ignore_errors=True)
202
+ try:
203
+ os.replace(build_dir, final_dir)
204
+ except OSError:
205
+ if not is_cache_hit(final_dir):
206
+ raise
207
+ else:
208
+ # final_dir is absent, so the failure was not "target populated"
209
+ # (e.g. ENOSPC, EACCES). Surface it instead of hiding it.
210
+ raise
185
211
  shutil.rmtree(build_dir, ignore_errors=True)
186
212
 
187
213
 
@@ -132,6 +132,10 @@ class ResolverBackend(Protocol):
132
132
  """Look up a fully hydrated entity by ID."""
133
133
  ...
134
134
 
135
+ def bulk_get_entities(self, entity_ids: list[str]) -> dict[str, EntityRecord]:
136
+ """Fetch multiple entities by ID; missing IDs are omitted from the result."""
137
+ ...
138
+
135
139
  def lookup_code(
136
140
  self,
137
141
  system: str,
@@ -192,6 +192,10 @@ class MultiPackRunner:
192
192
  """Fetch a fully hydrated entity record from any backing store."""
193
193
  return self._view.get_entity(entity_id)
194
194
 
195
+ def bulk_get_entities(self, entity_ids: list[str]) -> dict[str, EntityRecord]:
196
+ """Fetch multiple entities by ID; missing IDs are omitted from the result."""
197
+ return self._view.bulk_get_entities(entity_ids)
198
+
195
199
  def normalize_code_value(
196
200
  self, system: str, value: str, *, pack_filter: frozenset[str] | None = None
197
201
  ) -> str:
@@ -178,6 +178,10 @@ class PipelineRunner:
178
178
  """Fetch a fully hydrated entity record from the configured store."""
179
179
  return self._view.get_entity(entity_id)
180
180
 
181
+ def bulk_get_entities(self, entity_ids: list[str]) -> dict[str, EntityRecord]:
182
+ """Fetch multiple entities by ID; missing IDs are omitted from the result."""
183
+ return self._view.bulk_get_entities(entity_ids)
184
+
181
185
  def normalize_code_value(
182
186
  self, system: str, value: str, *, pack_filter: frozenset[str] | None = None
183
187
  ) -> str:
@@ -176,6 +176,15 @@ class EntityStore(ABC):
176
176
  """
177
177
  return frozenset()
178
178
 
179
+ def relation_types(self) -> frozenset[str] | None:
180
+ """Return the distinct relation types stored, or None if unknown.
181
+
182
+ None means "this store cannot characterize its relation types, so callers
183
+ must not prune it" — the default. SQL backends override with a concrete set
184
+ (possibly empty, meaning known to hold no relations).
185
+ """
186
+ return None
187
+
179
188
  def close(self) -> None: # noqa: B027
180
189
  """Release resources held by this store.
181
190
 
@@ -494,6 +494,17 @@ class SQLiteEntityStore(EntityStore):
494
494
  rows = conn.execute("SELECT DISTINCT system FROM codes").fetchall()
495
495
  return frozenset(r["system"] for r in rows)
496
496
 
497
+ @override
498
+ def relation_types(self) -> frozenset[str]:
499
+ with self._connection() as conn:
500
+ try:
501
+ rows = conn.execute(
502
+ "SELECT DISTINCT relation_type FROM relations"
503
+ ).fetchall()
504
+ except sqlite3.OperationalError:
505
+ return frozenset() # legacy DB with no relations table
506
+ return frozenset(r["relation_type"] for r in rows)
507
+
497
508
  def lookup_name_exact(
498
509
  self, value_norm: str, name_kinds: set[str] | None = None
499
510
  ) -> list[str]:
@@ -23,6 +23,9 @@ class StoreView:
23
23
 
24
24
  def __init__(self, stores: list[tuple[str | None, EntityStore]]) -> None:
25
25
  self._stores = stores
26
+ self._relation_type_index: list[frozenset[str] | None] = [
27
+ store.relation_types() for _, store in self._stores
28
+ ]
26
29
 
27
30
  # ------------------------------------------------------------------
28
31
  # Entity fetch — first non-None wins; no dedup needed
@@ -36,6 +39,18 @@ class StoreView:
36
39
  return entity
37
40
  return None
38
41
 
42
+ def bulk_get_entities(self, entity_ids: list[str]) -> dict[str, EntityRecord]:
43
+ """Return entities for *entity_ids*, first store wins per ID; missing IDs omitted."""
44
+ result: dict[str, EntityRecord] = {}
45
+ remaining = list(entity_ids)
46
+ for _, store in self._stores:
47
+ if not remaining:
48
+ break
49
+ found = store.bulk_get_entities(remaining)
50
+ result.update(found)
51
+ remaining = [eid for eid in remaining if eid not in result]
52
+ return result
53
+
39
54
  # ------------------------------------------------------------------
40
55
  # Lookups — dedup by entity_id, preserve first-seen order
41
56
  # ------------------------------------------------------------------
@@ -118,7 +133,10 @@ class StoreView:
118
133
  """
119
134
  seen: set[str] = set()
120
135
  result: list[str] = []
121
- for _, store in self._stores:
136
+ for i, (_, store) in enumerate(self._stores):
137
+ rv = self._relation_type_index[i]
138
+ if rv is not None and relation_type not in rv:
139
+ continue
122
140
  for eid in store.get_reverse_relations(
123
141
  entity_id, relation_type, as_of=as_of
124
142
  ):
@@ -136,7 +154,10 @@ class StoreView:
136
154
  ) -> frozenset[str]:
137
155
  """Return target entity IDs for relations active on *as_of*, unioned."""
138
156
  result: set[str] = set()
139
- for _, store in self._stores:
157
+ for i, (_, store) in enumerate(self._stores):
158
+ rv = self._relation_type_index[i]
159
+ if rv is not None and relation_type not in rv:
160
+ continue
140
161
  result.update(store.get_relations_as_of(entity_id, relation_type, as_of))
141
162
  return frozenset(result)
142
163
 
File without changes
File without changes