resolvekit 0.1.7__tar.gz → 0.1.9__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.7 → resolvekit-0.1.9}/PKG-INFO +10 -1
  2. {resolvekit-0.1.7 → resolvekit-0.1.9}/README.md +8 -0
  3. {resolvekit-0.1.7 → resolvekit-0.1.9}/pyproject.toml +4 -1
  4. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_polars_integration.py +4 -4
  5. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/bulk.py +63 -28
  6. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/containment_api.py +5 -3
  7. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/_stages.py +2 -2
  8. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/interfaces.py +4 -0
  9. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/multi_runner.py +4 -0
  10. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/runner.py +29 -9
  11. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/offsets.py +4 -2
  12. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/store/interface.py +9 -0
  13. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/store/sqlite.py +20 -8
  14. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/store/store_view.py +23 -2
  15. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/fuzzy_retrieval.py +11 -0
  16. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/symspell.py +9 -0
  17. {resolvekit-0.1.7 → resolvekit-0.1.9}/LICENSE +0 -0
  18. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/NOTICE.md +0 -0
  19. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/__init__.py +0 -0
  20. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_convenience.py +0 -0
  21. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/admin1/metadata.json +0 -0
  22. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/admin2/metadata.json +0 -0
  23. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/admin3/metadata.json +0 -0
  24. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/admin4/metadata.json +0 -0
  25. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/admin5/metadata.json +0 -0
  26. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/cities/metadata.json +0 -0
  27. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/continental_unions/entities.sqlite +0 -0
  28. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/continental_unions/metadata.json +0 -0
  29. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/continental_unions/symspell.dict +0 -0
  30. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/continents/entities.sqlite +0 -0
  31. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/continents/metadata.json +0 -0
  32. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/continents/symspell.dict +0 -0
  33. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/countries/entities.sqlite +0 -0
  34. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/countries/geo_calibrator.json +0 -0
  35. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/countries/metadata.json +0 -0
  36. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/countries/symspell.dict +0 -0
  37. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/regions/entities.sqlite +0 -0
  38. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/regions/metadata.json +0 -0
  39. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/geo/regions/symspell.dict +0 -0
  40. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/manifest.json +0 -0
  41. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/companies/entities.sqlite +0 -0
  42. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/companies/metadata.json +0 -0
  43. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/companies/symspell.dict +0 -0
  44. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/data_sources/entities.sqlite +0 -0
  45. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/data_sources/metadata.json +0 -0
  46. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/data_sources/symspell.dict +0 -0
  47. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/governments/entities.sqlite +0 -0
  48. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/governments/metadata.json +0 -0
  49. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/governments/symspell.dict +0 -0
  50. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/lenders/entities.sqlite +0 -0
  51. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/lenders/metadata.json +0 -0
  52. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/lenders/symspell.dict +0 -0
  53. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/political_parties/entities.sqlite +0 -0
  54. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/political_parties/metadata.json +0 -0
  55. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/political_parties/symspell.dict +0 -0
  56. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/providers/entities.sqlite +0 -0
  57. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/providers/metadata.json +0 -0
  58. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/org/providers/symspell.dict +0 -0
  59. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_data/parse/deny_list.json +0 -0
  60. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/_pandas_integration.py +0 -0
  61. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/__init__.py +0 -0
  62. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/_outcomes.py +0 -0
  63. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/api.py +0 -0
  64. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/containment.py +0 -0
  65. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/country_geonames_aliases.py +0 -0
  66. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/datapack_layout.py +0 -0
  67. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/entity_validity.py +0 -0
  68. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/formal_names.py +0 -0
  69. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/geo_shared.py +0 -0
  70. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/groups.py +0 -0
  71. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/inspection.py +0 -0
  72. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/models.py +0 -0
  73. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/module_catalog.py +0 -0
  74. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/oecd_dac.py +0 -0
  75. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/__init__.py +0 -0
  76. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/build_report.py +0 -0
  77. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/changelog.py +0 -0
  78. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/chunk.py +0 -0
  79. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/contribution.py +0 -0
  80. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/core.py +0 -0
  81. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/discover.py +0 -0
  82. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/enrich.py +0 -0
  83. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/geo_staging.py +0 -0
  84. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/packaging.py +0 -0
  85. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/promote.py +0 -0
  86. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/qa.py +0 -0
  87. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/reconcile.py +0 -0
  88. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/stages.py +0 -0
  89. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/pipeline/types.py +0 -0
  90. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/presets.py +0 -0
  91. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/registry.py +0 -0
  92. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/__init__.py +0 -0
  93. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/__init__.py +0 -0
  94. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/adapter.py +0 -0
  95. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/base_dc_api.py +0 -0
  96. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/bundle.py +0 -0
  97. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/canonicalize.py +0 -0
  98. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/client.py +0 -0
  99. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/constants.py +0 -0
  100. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/__init__.py +0 -0
  101. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/_admin_walk.py +0 -0
  102. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/_chunk_callback.py +0 -0
  103. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/_geo_regions.py +0 -0
  104. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/_ordered_emitter.py +0 -0
  105. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/_progress_context.py +0 -0
  106. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/_streaming.py +0 -0
  107. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/_type_mappings.py +0 -0
  108. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/adapter.py +0 -0
  109. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/dc_api.py +0 -0
  110. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/discovery.py +0 -0
  111. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/fetch.py +0 -0
  112. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/mappings.py +0 -0
  113. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/profile.py +0 -0
  114. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/geo/prominence.py +0 -0
  115. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/models.py +0 -0
  116. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/node.py +0 -0
  117. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/org/__init__.py +0 -0
  118. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/org/adapter.py +0 -0
  119. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/org/dc_api.py +0 -0
  120. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/org/discovery.py +0 -0
  121. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/org/fetch.py +0 -0
  122. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/org/mappings.py +0 -0
  123. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/org/profile.py +0 -0
  124. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/rows.py +0 -0
  125. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/specs.py +0 -0
  126. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/datacommons/text.py +0 -0
  127. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/discovery_events.py +0 -0
  128. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/protocol.py +0 -0
  129. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/seed/__init__.py +0 -0
  130. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/seed/continents.py +0 -0
  131. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/seed/m49.py +0 -0
  132. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/wikidata/__init__.py +0 -0
  133. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/wikidata/aliases.py +0 -0
  134. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sources/wikidata/sitelinks.py +0 -0
  135. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sqlite/__init__.py +0 -0
  136. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sqlite/constants.py +0 -0
  137. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sqlite/context.py +0 -0
  138. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sqlite/diff.py +0 -0
  139. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sqlite/export.py +0 -0
  140. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sqlite/specs.py +0 -0
  141. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sqlite/validate.py +0 -0
  142. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/sqlite/write.py +0 -0
  143. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/state.py +0 -0
  144. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/builder/utils.py +0 -0
  145. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/__init__.py +0 -0
  146. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/__init__.py +0 -0
  147. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/_cldr_source.py +0 -0
  148. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/_latin_filter.py +0 -0
  149. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/_wikidata_client.py +0 -0
  150. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/cldr.py +0 -0
  151. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/geonames.py +0 -0
  152. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/multilingual_names.py +0 -0
  153. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/synthetic.py +0 -0
  154. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/adapters/wikidata.py +0 -0
  155. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/dataset.py +0 -0
  156. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/evaluation.py +0 -0
  157. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/fitting.py +0 -0
  158. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/models.py +0 -0
  159. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/scoring_model.py +0 -0
  160. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/train.py +0 -0
  161. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/calibration/vectorize.py +0 -0
  162. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/__init__.py +0 -0
  163. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/__init__.py +0 -0
  164. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/_byod.py +0 -0
  165. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/_pivot.py +0 -0
  166. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/batch.py +0 -0
  167. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/cache.py +0 -0
  168. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/code_lookup.py +0 -0
  169. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/context_input.py +0 -0
  170. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/diagnostics.py +0 -0
  171. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/entity_lookup.py +0 -0
  172. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/group_api.py +0 -0
  173. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/info.py +0 -0
  174. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/inspect.py +0 -0
  175. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/loading/__init__.py +0 -0
  176. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/loading/module_catalog.py +0 -0
  177. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/loading/pack_loader.py +0 -0
  178. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/loading/paths.py +0 -0
  179. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/loading/store_builder.py +0 -0
  180. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/modules.py +0 -0
  181. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/output_spec.py +0 -0
  182. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/output_view.py +0 -0
  183. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/query_prep.py +0 -0
  184. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/resolve_flow.py +0 -0
  185. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/resolver.py +0 -0
  186. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/snap.py +0 -0
  187. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/api/suggest_flow.py +0 -0
  188. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/byod/__init__.py +0 -0
  189. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/byod/build.py +0 -0
  190. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/byod/builder.py +0 -0
  191. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/byod/cache.py +0 -0
  192. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/byod/intake.py +0 -0
  193. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/byod/result.py +0 -0
  194. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/config.py +0 -0
  195. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/datapack.py +0 -0
  196. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/download_api.py +0 -0
  197. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/__init__.py +0 -0
  198. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/config.py +0 -0
  199. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/decision.py +0 -0
  200. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/enrichment.py +0 -0
  201. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/router.py +0 -0
  202. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/suggest_rank.py +0 -0
  203. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/engine/tier_utils.py +0 -0
  204. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/errors.py +0 -0
  205. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/errors_base.py +0 -0
  206. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/__init__.py +0 -0
  207. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/events.py +0 -0
  208. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/feature_text.py +0 -0
  209. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/helpers.py +0 -0
  210. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/protocol.py +0 -0
  211. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/renderers.py +0 -0
  212. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/result_html.py +0 -0
  213. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/result_types.py +0 -0
  214. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/scorecard.py +0 -0
  215. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/explain/sink.py +0 -0
  216. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/linking/__init__.py +0 -0
  217. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/linking/base_linker.py +0 -0
  218. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/linking/base_normalizer.py +0 -0
  219. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/linking/linker.py +0 -0
  220. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/linking/normalizer.py +0 -0
  221. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/merge.py +0 -0
  222. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/__init__.py +0 -0
  223. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/_repr.py +0 -0
  224. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/bulk_result.py +0 -0
  225. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/candidate.py +0 -0
  226. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/crosswalk.py +0 -0
  227. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/entity.py +0 -0
  228. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/entity_attributes.py +0 -0
  229. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/features.py +0 -0
  230. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/generation.py +0 -0
  231. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/inspection.py +0 -0
  232. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/name_grammar.py +0 -0
  233. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/query.py +0 -0
  234. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/model/result.py +0 -0
  235. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/module_registry.py +0 -0
  236. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/overlay_loader.py +0 -0
  237. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/__init__.py +0 -0
  238. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/_pivot.py +0 -0
  239. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/automaton.py +0 -0
  240. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/denylist.py +0 -0
  241. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/detect.py +0 -0
  242. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/engine.py +0 -0
  243. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/link.py +0 -0
  244. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/parse/result.py +0 -0
  245. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/registry.py +0 -0
  246. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/remote.py +0 -0
  247. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/store/__init__.py +0 -0
  248. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/store/composed_sqlite.py +0 -0
  249. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/store/composite.py +0 -0
  250. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/store/merging.py +0 -0
  251. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/store/sqlite_helpers.py +0 -0
  252. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/util/__init__.py +0 -0
  253. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/util/iso_codes.py +0 -0
  254. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/util/normalization.py +0 -0
  255. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/util/sentinel.py +0 -0
  256. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/core/version.py +0 -0
  257. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/diagnostics/__init__.py +0 -0
  258. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/errors/__init__.py +0 -0
  259. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/extensions.py +0 -0
  260. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/__init__.py +0 -0
  261. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/_artifacts.py +0 -0
  262. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/__init__.py +0 -0
  263. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/decision.py +0 -0
  264. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/extractor.py +0 -0
  265. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/features.py +0 -0
  266. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/normalizer.py +0 -0
  267. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/pack.py +0 -0
  268. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/scoring.py +0 -0
  269. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/sources/__init__.py +0 -0
  270. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/sources/exact_code.py +0 -0
  271. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/sources/exact_name.py +0 -0
  272. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/sources/fts.py +0 -0
  273. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/sources/fuzzy.py +0 -0
  274. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/custom/sources/fuzzy_retrieval.py +0 -0
  275. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/__init__.py +0 -0
  276. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/_specificity.py +0 -0
  277. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/build/__init__.py +0 -0
  278. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/build/builder.py +0 -0
  279. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/constraints/__init__.py +0 -0
  280. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/constraints/containment.py +0 -0
  281. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/constraints/membership.py +0 -0
  282. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/constraints/temporal.py +0 -0
  283. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/constraints/type_constraint.py +0 -0
  284. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/data/.gitkeep +0 -0
  285. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/decision.py +0 -0
  286. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/extractor.py +0 -0
  287. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/features.py +0 -0
  288. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/linker.py +0 -0
  289. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/normalizer.py +0 -0
  290. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/pack.py +0 -0
  291. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/routing.py +0 -0
  292. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/scoring.py +0 -0
  293. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/__init__.py +0 -0
  294. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/_short_input.py +0 -0
  295. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/exact_code.py +0 -0
  296. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/exact_name.py +0 -0
  297. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/fts.py +0 -0
  298. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/fuzzy.py +0 -0
  299. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/geo/sources/query_shapes.py +0 -0
  300. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/__init__.py +0 -0
  301. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/_acronym.py +0 -0
  302. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/build/__init__.py +0 -0
  303. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/build/builder.py +0 -0
  304. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/constraints/__init__.py +0 -0
  305. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/constraints/country_relevance.py +0 -0
  306. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/constraints/parent_org.py +0 -0
  307. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/constraints/temporal.py +0 -0
  308. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/constraints/type_constraint.py +0 -0
  309. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/data/.gitkeep +0 -0
  310. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/decision.py +0 -0
  311. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/feature_extractor.py +0 -0
  312. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/features.py +0 -0
  313. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/linker.py +0 -0
  314. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/normalizer.py +0 -0
  315. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/pack.py +0 -0
  316. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/routing.py +0 -0
  317. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/scoring.py +0 -0
  318. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/sources/__init__.py +0 -0
  319. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/sources/acronym.py +0 -0
  320. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/sources/exact_code.py +0 -0
  321. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/sources/exact_name.py +0 -0
  322. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/sources/fts.py +0 -0
  323. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/sources/fuzzy.py +0 -0
  324. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/packs/org/sources/symspell.py +0 -0
  325. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/pandas/__init__.py +0 -0
  326. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/polars/__init__.py +0 -0
  327. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/py.typed +0 -0
  328. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/__init__.py +0 -0
  329. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/build/__init__.py +0 -0
  330. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/build/base_builder.py +0 -0
  331. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/build/schema.py +0 -0
  332. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/constraints/__init__.py +0 -0
  333. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/constraints/temporal_constraint.py +0 -0
  334. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/constraints/type_constraint.py +0 -0
  335. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/scoring_base.py +0 -0
  336. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/sources/__init__.py +0 -0
  337. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/sources/code_helpers.py +0 -0
  338. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/sources/fts_base.py +0 -0
  339. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/sources/fuzzy_base.py +0 -0
  340. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/sources/fuzzy_retrieval_base.py +0 -0
  341. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/sources/fuzzy_retrieval_brute_base.py +0 -0
  342. {resolvekit-0.1.7 → resolvekit-0.1.9}/src/resolvekit/shared/sources/symspell_base.py +0 -0
  343. {resolvekit-0.1.7 → resolvekit-0.1.9}/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.7
3
+ Version: 0.1.9
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
@@ -14,6 +14,7 @@ Classifier: Operating System :: OS Independent
14
14
  Classifier: Programming Language :: Python :: 3
15
15
  Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
17
18
  Classifier: Programming Language :: Python :: 3 :: Only
18
19
  Classifier: Topic :: Scientific/Engineering :: GIS
19
20
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
@@ -49,6 +50,14 @@ Description-Content-Type: text/markdown
49
50
 
50
51
  # resolvekit
51
52
 
53
+ [![PyPI version](https://img.shields.io/pypi/v/resolvekit.svg)](https://pypi.org/project/resolvekit/)
54
+ [![Python versions](https://img.shields.io/pypi/pyversions/resolvekit.svg)](https://pypi.org/project/resolvekit/)
55
+ [![License: MIT](https://img.shields.io/pypi/l/resolvekit.svg)](https://github.com/jm-rivera/resolvekit/blob/main/LICENSE)
56
+ [![Tests](https://github.com/jm-rivera/resolvekit/actions/workflows/test.yml/badge.svg)](https://github.com/jm-rivera/resolvekit/actions/workflows/test.yml)
57
+ [![Docs](https://img.shields.io/badge/docs-jm--rivera.github.io-blue.svg)](https://jm-rivera.github.io/resolvekit/)
58
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
59
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
60
+
52
61
  Resolve messy place and entity strings — and codes — to canonical entity IDs, offline and deterministically. Feed it `"Brasil"`, `"Cote dIvoire"`, or `"Republic of Korea"` and get back `country/BRA`, `country/CIV`, `country/KOR`.
53
62
 
54
63
  - **Offline and deterministic.** No network call, no LLM, no external service at resolution time. The same input gives the same output, today and next year.
@@ -1,5 +1,13 @@
1
1
  # resolvekit
2
2
 
3
+ [![PyPI version](https://img.shields.io/pypi/v/resolvekit.svg)](https://pypi.org/project/resolvekit/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/resolvekit.svg)](https://pypi.org/project/resolvekit/)
5
+ [![License: MIT](https://img.shields.io/pypi/l/resolvekit.svg)](https://github.com/jm-rivera/resolvekit/blob/main/LICENSE)
6
+ [![Tests](https://github.com/jm-rivera/resolvekit/actions/workflows/test.yml/badge.svg)](https://github.com/jm-rivera/resolvekit/actions/workflows/test.yml)
7
+ [![Docs](https://img.shields.io/badge/docs-jm--rivera.github.io-blue.svg)](https://jm-rivera.github.io/resolvekit/)
8
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
9
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
10
+
3
11
  Resolve messy place and entity strings — and codes — to canonical entity IDs, offline and deterministically. Feed it `"Brasil"`, `"Cote dIvoire"`, or `"Republic of Korea"` and get back `country/BRA`, `country/CIV`, `country/KOR`.
4
12
 
5
13
  - **Offline and deterministic.** No network call, no LLM, no external service at resolution time. The same input gives the same output, today and next year.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "resolvekit"
3
- version = "0.1.7"
3
+ version = "0.1.9"
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
 
@@ -19,6 +19,7 @@ classifiers = [
19
19
  "Programming Language :: Python :: 3",
20
20
  "Programming Language :: Python :: 3.12",
21
21
  "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
22
23
  "Programming Language :: Python :: 3 :: Only",
23
24
  "Topic :: Scientific/Engineering :: GIS",
24
25
  "Topic :: Scientific/Engineering :: Information Analysis",
@@ -158,6 +159,8 @@ dev = [
158
159
  "ruff>=0.15.12",
159
160
  "ty>=0.0.32",
160
161
  "pandas-stubs>=3.0.0.260204",
162
+ "pandas>=2.0",
163
+ "polars>=1.40.1",
161
164
  ]
162
165
  test = [
163
166
  "pytest>=9.0.3",
@@ -203,14 +203,14 @@ def register() -> None:
203
203
  struct_expr = pl.struct([self._expr.alias("__value__"), *ctx_exprs])
204
204
 
205
205
  def _apply_struct(struct_series: pl.Series) -> pl.Series:
206
- # Unpack struct fields back into individual Series.
207
- rows = struct_series.to_list() # list[dict]
208
- value_list = [r["__value__"] for r in rows]
206
+ # Unpack struct fields column-oriented; avoids materialising N dicts.
207
+ unpacked = struct_series.to_frame("__s").unnest("__s")
208
+ value_list = unpacked["__value__"].to_list()
209
209
 
210
210
  # Build a per-row context dict where per-row keys map to lists.
211
211
  per_row_ctx: dict[str, object] = dict(_scalar_ctx)
212
212
  for k in ctx_field_names:
213
- per_row_ctx[k] = [r[f"__ctx_{k}"] for r in rows]
213
+ per_row_ctx[k] = unpacked[f"__ctx_{k}"].to_list()
214
214
 
215
215
  result = _bulk_dispatch(
216
216
  resolver=resolver,
@@ -839,23 +839,23 @@ def _bulk_dispatch(
839
839
  # Warn only when the column is wholly empty among resolved rows — a partial
840
840
  # miss (some resolved rows have a value) is not warned.
841
841
  if spec_active and effective_spec is not None:
842
- resolved_indices = [
843
- i for i, r in enumerate(out_source) if r.status == ResolutionStatus.RESOLVED
844
- ]
845
- if resolved_indices:
846
- n_missing = sum(1 for i in resolved_indices if out_values[i] is None)
847
- if n_missing > 0 and n_missing == len(resolved_indices):
848
- chain_repr = [t.raw for t in effective_spec.chain]
849
- # stacklevel=4 points at Resolver.bulk for the direct path;
850
- # the module-level resolvekit.bulk convenience adds one more frame.
851
- warnings.warn(
852
- f"default output {chain_repr!r}: {n_missing} resolved value(s) "
853
- f"had no output (column wholly empty among resolved rows)",
854
- UserWarning,
855
- stacklevel=4,
856
- )
842
+ n_resolved = n_missing = 0
843
+ for r, v in zip(out_source, out_values, strict=True):
844
+ if r.status == ResolutionStatus.RESOLVED:
845
+ n_resolved += 1
846
+ if v is None:
847
+ n_missing += 1
848
+ if n_resolved > 0 and n_missing == n_resolved:
849
+ chain_repr = [t.raw for t in effective_spec.chain]
850
+ # stacklevel=4 points at Resolver.bulk for the direct path;
851
+ # the module-level resolvekit.bulk convenience adds one more frame.
852
+ warnings.warn(
853
+ f"default output {chain_repr!r}: {n_missing} resolved value(s) "
854
+ f"had no output (column wholly empty among resolved rows)",
855
+ UserWarning,
856
+ stacklevel=4,
857
+ )
857
858
 
858
- # Return a native series (not BulkResult) when pivoting and output="series".
859
859
  scalar_to = (has_pivot or spec_active) and output == "series"
860
860
 
861
861
  if scalar_to:
@@ -886,12 +886,9 @@ def _bulk_dispatch(
886
886
  return BulkResult(values=native, source=out_source, kind=kind)
887
887
 
888
888
  if output == "frame":
889
- # Flat DataFrame: one column per record field.
890
- records = [
891
- _record_from_result(r, v)
892
- for r, v in zip(out_source, out_values, strict=True)
893
- ]
894
- native = _build_frame_native(records, kind, orig_index=orig_index)
889
+ # Flat DataFrame: one column per record field, built column-oriented.
890
+ frame_cols = _frame_columns_from_output(out_source, out_values)
891
+ native = _build_frame_native(frame_cols, kind, orig_index=orig_index)
895
892
  return BulkResult(values=native, source=out_source, kind=kind)
896
893
 
897
894
  # Default: wrap the native series of pivot/result values in BulkResult.
@@ -964,27 +961,65 @@ def _build_records_native(
964
961
  return records
965
962
 
966
963
 
964
+ def _frame_columns_from_output(
965
+ out_source: list[ResolutionResult],
966
+ out_values: list[Any],
967
+ ) -> dict[str, list[Any]]:
968
+ """Build column-oriented data for ``output='frame'`` without a N-dict intermediate."""
969
+ col_value: list[Any] = []
970
+ col_status: list[Any] = []
971
+ col_entity_id: list[Any] = []
972
+ col_confidence: list[Any] = []
973
+ col_pack_id: list[Any] = []
974
+ col_query_text: list[Any] = []
975
+ for r, v in zip(out_source, out_values, strict=True):
976
+ if isinstance(v, ResolutionResult):
977
+ col_value.append(v.entity_id)
978
+ else:
979
+ col_value.append(v)
980
+ col_status.append(r.status.value)
981
+ col_entity_id.append(r.entity_id)
982
+ col_confidence.append(r.confidence)
983
+ col_pack_id.append(r.pack_id)
984
+ col_query_text.append(r.query_text)
985
+ return {
986
+ "value": col_value,
987
+ "status": col_status,
988
+ "entity_id": col_entity_id,
989
+ "confidence": col_confidence,
990
+ "pack_id": col_pack_id,
991
+ "query_text": col_query_text,
992
+ }
993
+
994
+
967
995
  def _build_frame_native(
968
- records: list[dict[str, Any]],
996
+ columns: dict[str, list[Any]],
969
997
  kind: _InputKind,
970
998
  *,
971
999
  orig_index: Any,
972
1000
  ) -> Any:
973
1001
  """DataFrame assembly for ``output='frame'``.
974
1002
 
1003
+ Accepts column-oriented data (dict of column-name → value list) rather than
1004
+ a list-of-dicts, so no N-dict intermediate is ever allocated.
1005
+
975
1006
  For pandas/polars, returns a DataFrame. For non-DataFrame inputs (list,
976
- tuple, numpy), falls back to the same list-of-dicts representation as
977
- ``output='record'``.
1007
+ tuple, numpy), falls back to a list-of-dicts to preserve existing behaviour.
978
1008
  """
979
1009
  if kind == "pandas":
980
1010
  import pandas as pd
981
1011
 
982
- return pd.DataFrame.from_records(records, index=orig_index)
1012
+ return pd.DataFrame(columns, index=orig_index)
983
1013
  if kind == "polars":
984
1014
  import polars as pl
985
1015
 
986
- return pl.DataFrame(records)
987
- return records
1016
+ return pl.DataFrame(columns)
1017
+ # Non-DataFrame kinds: reconstruct list-of-dicts for backward compatibility.
1018
+ col_names = list(columns)
1019
+ col_lists = [columns[k] for k in col_names]
1020
+ return [
1021
+ dict(zip(col_names, row, strict=True)) for row in zip(*col_lists, strict=True)
1022
+ ]
988
1023
 
989
1024
 
990
1025
  def _build_native(
@@ -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:
@@ -299,7 +299,7 @@ def add_evidence_to_candidates(
299
299
  if candidate is None:
300
300
  continue
301
301
 
302
- candidate.sources = [*candidate.sources, ev]
302
+ candidate.sources.append(ev)
303
303
  merged_signals = {**candidate.retrieval.signals, **ev.signals}
304
304
 
305
305
  # Check if new evidence has better score
@@ -384,7 +384,7 @@ def should_stop_generation(
384
384
  Returns:
385
385
  True if pipeline should stop generating candidates.
386
386
  """
387
- if not config:
387
+ if not config or not config.stop_conditions:
388
388
  return False
389
389
 
390
390
  candidate_count = len(evidence_by_entity)
@@ -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:
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  import logging
6
6
  import time
7
7
  import traceback
8
- from collections import defaultdict
8
+ from collections import OrderedDict, defaultdict
9
9
  from collections.abc import Callable
10
10
  from datetime import date
11
11
  from typing import TYPE_CHECKING, Literal
@@ -46,6 +46,11 @@ from resolvekit.core.store.store_view import StoreView
46
46
 
47
47
  logger = logging.getLogger(__name__)
48
48
 
49
+ # Maximum number of distinct entity_type_prefixes filter keys retained in the
50
+ # per-runner suggest-names LRU cache. Each slot can hold ~1-7 MB of name
51
+ # tuples; 8 slots is well under typical process RSS budgets.
52
+ _SUGGEST_NAMES_CACHE_MAX = 8
53
+
49
54
 
50
55
  class PipelineRunner:
51
56
  """The core resolution pipeline runner.
@@ -114,11 +119,12 @@ class PipelineRunner:
114
119
  country_relation_prefixes=country_relation_prefixes,
115
120
  )
116
121
  self._view = StoreView([(pack_id, store)] if store is not None else [])
117
- # Lazy cache for suggest_prefix: maps entity_type_prefixes key → name list.
118
- # Built on first suggest call; never warmed in __init__ (cold-start is measured).
119
- self._suggest_names_cache: dict[
122
+ # Bounded LRU cache for suggest names: maps entity_type_prefixes key →
123
+ # name list. Capped at _SUGGEST_NAMES_CACHE_MAX entries; oldest entry
124
+ # evicted when full. Each entry holds up to ~25k tuples (~1-7 MB).
125
+ self._suggest_names_cache: OrderedDict[
120
126
  frozenset[str] | None, list[tuple[str, str, str, bool, str]]
121
- ] = {}
127
+ ] = OrderedDict()
122
128
 
123
129
  def warm(self) -> None:
124
130
  """Eagerly build all lazily-constructed source indexes.
@@ -178,6 +184,10 @@ class PipelineRunner:
178
184
  """Fetch a fully hydrated entity record from the configured store."""
179
185
  return self._view.get_entity(entity_id)
180
186
 
187
+ def bulk_get_entities(self, entity_ids: list[str]) -> dict[str, EntityRecord]:
188
+ """Fetch multiple entities by ID; missing IDs are omitted from the result."""
189
+ return self._view.bulk_get_entities(entity_ids)
190
+
181
191
  def normalize_code_value(
182
192
  self, system: str, value: str, *, pack_filter: frozenset[str] | None = None
183
193
  ) -> str:
@@ -482,7 +492,7 @@ class PipelineRunner:
482
492
  # store's entity_type_exclude_prefixes parameter
483
493
  # so the size check reflects only fuzzy-eligible
484
494
  # name rows.
485
- self._suggest_names_cache[names_key] = list(
495
+ _names = list(
486
496
  store.iter_suggest_names(
487
497
  entity_type_exclude_prefixes=FUZZY_DENYLIST_PREFIXES
488
498
  )
@@ -491,20 +501,30 @@ class PipelineRunner:
491
501
  # Store doesn't support the exclude param — fall
492
502
  # back to unfiltered. This means auto-fuzzy will
493
503
  # be suppressed on packs with > 20k total names.
494
- self._suggest_names_cache[names_key] = list(
504
+ _names = list(
495
505
  store.iter_suggest_names(entity_type_prefixes=None)
496
506
  )
507
+ self._suggest_names_cache[names_key] = _names
508
+ if len(self._suggest_names_cache) > _SUGGEST_NAMES_CACHE_MAX:
509
+ self._suggest_names_cache.popitem(last=False)
510
+ else:
511
+ self._suggest_names_cache.move_to_end(names_key)
497
512
  else:
498
513
  names_key = entity_type_prefixes
499
514
  if names_key not in self._suggest_names_cache:
500
515
  try:
501
- self._suggest_names_cache[names_key] = list(
516
+ _names = list(
502
517
  store.iter_suggest_names(
503
518
  entity_type_prefixes=entity_type_prefixes
504
519
  )
505
520
  )
506
521
  except NotImplementedError:
507
- self._suggest_names_cache[names_key] = []
522
+ _names = []
523
+ self._suggest_names_cache[names_key] = _names
524
+ if len(self._suggest_names_cache) > _SUGGEST_NAMES_CACHE_MAX:
525
+ self._suggest_names_cache.popitem(last=False)
526
+ else:
527
+ self._suggest_names_cache.move_to_end(names_key)
508
528
  names_list = self._suggest_names_cache[names_key]
509
529
 
510
530
  run_fuzzy = fuzzy == "always" or (
@@ -69,6 +69,9 @@ from resolvekit.core.util.normalization import (
69
69
  _WHITESPACE: re.Pattern[str] = re.compile(r"\s+")
70
70
  _PUNCTUATION: re.Pattern[str] = re.compile(r"[^\w\s\-']")
71
71
  _DIGITS: re.Pattern[str] = re.compile(r"\d")
72
+ _HTML_ENTITY_RE: re.Pattern[str] = re.compile(
73
+ r"&(?:[a-zA-Z][a-zA-Z0-9]*|#[0-9]+|#x[0-9a-fA-F]+);"
74
+ )
72
75
 
73
76
 
74
77
  def _assert_supported_profile(profile: NormalizationProfile) -> None:
@@ -162,12 +165,11 @@ def _apply_html_unescape(text: str, starts: list[int], ends: list[int]) -> _Stat
162
165
  Each entity (``&``, ``'``, etc.) decodes to one or more chars that
163
166
  all carry the raw span of the whole entity token.
164
167
  """
165
- _entity_re = re.compile(r"&(?:[a-zA-Z][a-zA-Z0-9]*|#[0-9]+|#x[0-9a-fA-F]+);")
166
168
 
167
169
  def _decode(m: re.Match[str]) -> str:
168
170
  return html.unescape(m.group(0))
169
171
 
170
- return _apply_regex_sub(text, starts, ends, _entity_re, _decode)
172
+ return _apply_regex_sub(text, starts, ends, _HTML_ENTITY_RE, _decode)
171
173
 
172
174
 
173
175
  def _apply_markdown_strip(text: str, starts: list[int], ends: list[int]) -> _State:
@@ -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
 
@@ -403,7 +403,9 @@ class SQLiteEntityStore(EntityStore):
403
403
  return None
404
404
 
405
405
  name_rows = conn.execute(
406
- "SELECT * FROM names WHERE entity_id = ?", (entity_id,)
406
+ "SELECT value, value_norm, name_kind, lang, is_preferred"
407
+ " FROM names WHERE entity_id = ?",
408
+ (entity_id,),
407
409
  ).fetchall()
408
410
 
409
411
  names = [
@@ -451,10 +453,9 @@ class SQLiteEntityStore(EntityStore):
451
453
  for r in relation_rows
452
454
  ]
453
455
 
454
- # Parse attrs_json if present
456
+ # Parse attrs_json if present (column absent in older stores).
455
457
  attrs: dict[str, Any] = {}
456
- row_dict = dict(row)
457
- if attrs_json := row_dict.get("attrs_json"):
458
+ if "attrs_json" in row.keys() and (attrs_json := row["attrs_json"]): # noqa: SIM118 — sqlite3.Row iterates values, not keys
458
459
  with contextlib.suppress(json.JSONDecodeError):
459
460
  attrs = json.loads(attrs_json)
460
461
 
@@ -494,6 +495,17 @@ class SQLiteEntityStore(EntityStore):
494
495
  rows = conn.execute("SELECT DISTINCT system FROM codes").fetchall()
495
496
  return frozenset(r["system"] for r in rows)
496
497
 
498
+ @override
499
+ def relation_types(self) -> frozenset[str]:
500
+ with self._connection() as conn:
501
+ try:
502
+ rows = conn.execute(
503
+ "SELECT DISTINCT relation_type FROM relations"
504
+ ).fetchall()
505
+ except sqlite3.OperationalError:
506
+ return frozenset() # legacy DB with no relations table
507
+ return frozenset(r["relation_type"] for r in rows)
508
+
497
509
  def lookup_name_exact(
498
510
  self, value_norm: str, name_kinds: set[str] | None = None
499
511
  ) -> list[str]:
@@ -593,7 +605,8 @@ class SQLiteEntityStore(EntityStore):
593
605
  ).fetchall()
594
606
 
595
607
  name_rows = conn.execute(
596
- f"SELECT * FROM names WHERE entity_id IN ({placeholders})",
608
+ f"SELECT entity_id, value, value_norm, name_kind, lang,"
609
+ f" is_preferred FROM names WHERE entity_id IN ({placeholders})",
597
610
  chunk,
598
611
  ).fetchall()
599
612
 
@@ -650,10 +663,9 @@ class SQLiteEntityStore(EntityStore):
650
663
  for r in relations_by_entity.get(eid, [])
651
664
  ]
652
665
 
653
- # Parse attrs_json if present
666
+ # Parse attrs_json if present (column absent in older stores).
654
667
  attrs: dict[str, Any] = {}
655
- row_dict = dict(row)
656
- if attrs_json := row_dict.get("attrs_json"):
668
+ if "attrs_json" in row.keys() and (attrs_json := row["attrs_json"]): # noqa: SIM118 — sqlite3.Row iterates values, not keys
657
669
  with contextlib.suppress(json.JSONDecodeError):
658
670
  attrs = json.loads(attrs_json)
659
671
 
@@ -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
 
@@ -1,5 +1,7 @@
1
1
  """Fuzzy retrieval source for geo entities."""
2
2
 
3
+ from typing import override
4
+
3
5
  from resolvekit.core.model import CandidateEvidence, GenerationContext, MatchTier
4
6
  from resolvekit.packs.geo.sources._short_input import short_input_blocked
5
7
  from resolvekit.packs.geo.sources.symspell import _is_small_only_entity_types
@@ -39,6 +41,15 @@ class GeoFuzzyRetrievalSource(FuzzyRetrievalSource):
39
41
  )
40
42
  self._large_tier = large_tier
41
43
 
44
+ @override
45
+ def warm(self) -> None:
46
+ # The LARGE tier (admin2-5 / cities) is built lazily on first use; eagerly
47
+ # warming it loads ~800 MB for workloads that never issue a LARGE-tier
48
+ # query. SMALL tier is cheap and warms normally.
49
+ if self._large_tier:
50
+ return
51
+ super().warm()
52
+
42
53
  def generate(self, ctx: GenerationContext) -> list[CandidateEvidence]:
43
54
  """Skip retrieval for degenerate inputs that should never match a geo
44
55
  entity (single letters, lowercase short alpha, ``#N/A``-style noise).
@@ -216,6 +216,15 @@ class GeoSymSpellSource(SymSpellSource):
216
216
  )
217
217
  return records
218
218
 
219
+ @override
220
+ def warm(self) -> None:
221
+ # The LARGE tier (admin2-5 / cities) is built lazily on first use; eagerly
222
+ # warming it loads ~800 MB for workloads that never issue a LARGE-tier
223
+ # query. SMALL tier is cheap and warms normally.
224
+ if self._large_tier:
225
+ return
226
+ super().warm()
227
+
219
228
  def generate(self, ctx: GenerationContext) -> list[CandidateEvidence]:
220
229
  """Skip typo correction for obvious code-like inputs and degenerate
221
230
  short/noise inputs (single letters, ``#N/A``).
File without changes