matchlab 0.1.0.dev3__tar.gz → 0.1.0.dev4__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 (206) hide show
  1. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/PKG-INFO +1 -1
  2. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/linkers/splinklinker.py +37 -6
  3. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab.egg-info/PKG-INFO +1 -1
  4. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab.egg-info/SOURCES.txt +1 -0
  5. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab.egg-info/scm_version.json +1 -1
  6. matchlab-0.1.0.dev4/test/models/test_linkers_splink.py +42 -0
  7. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/actions/setup-toolchain/action.yml +0 -0
  8. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/dependabot.yml +0 -0
  9. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/pull_request_template.md +0 -0
  10. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/skills/lucid-docs/README.md +0 -0
  11. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/skills/lucid-docs/SKILL.md +0 -0
  12. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/skills/lucid-docs/readability.py +0 -0
  13. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/workflows/cd.yml +0 -0
  14. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/workflows/ci.yml +0 -0
  15. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.github/workflows/codeql.yml +0 -0
  16. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.gitignore +0 -0
  17. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.pre-commit-config.yaml +0 -0
  18. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.vscode/launch.json +0 -0
  19. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/.vscode/settings.json +0 -0
  20. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/CODEOWNERS +0 -0
  21. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/LICENSE +0 -0
  22. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/README.md +0 -0
  23. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/README.md +0 -0
  24. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/__init__.py +0 -0
  25. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/__main__.py +0 -0
  26. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/cases.py +0 -0
  27. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/data.py +0 -0
  28. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/measure.py +0 -0
  29. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/measurements.py +0 -0
  30. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/report.py +0 -0
  31. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/results/.gitkeep +0 -0
  32. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/runner.py +0 -0
  33. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/benchmarks/topologies.py +0 -0
  34. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/adapters.md +0 -0
  35. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/core/exceptions.md +0 -0
  36. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/core/hash.md +0 -0
  37. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/core/resolver_output.md +0 -0
  38. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/core/schemas.md +0 -0
  39. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/core/transform.md +0 -0
  40. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/document.md +0 -0
  41. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/eval-judgements.md +0 -0
  42. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/eval-metrics.md +0 -0
  43. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/eval-sampling.md +0 -0
  44. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/eval-tui.md +0 -0
  45. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/lineage.md +0 -0
  46. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/locations.md +0 -0
  47. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/models.md +0 -0
  48. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/progress.md +0 -0
  49. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/recordstep.md +0 -0
  50. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/resolvers.md +0 -0
  51. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/resources.md +0 -0
  52. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/sources.md +0 -0
  53. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/specs.md +0 -0
  54. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/steps.md +0 -0
  55. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/testkit.md +0 -0
  56. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/api/transformers.md +0 -0
  57. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/assets/matchbox-icon-dark.png +0 -0
  58. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/assets/matchbox-icon.svg +0 -0
  59. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/assets/matchbox-logo-dark.svg +0 -0
  60. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/assets/matchbox-logo-light.svg +0 -0
  61. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/contributing.md +0 -0
  62. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/glossary.md +0 -0
  63. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/guide/build-a-plan.md +0 -0
  64. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/guide/evaluate.md +0 -0
  65. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/guide/install.md +0 -0
  66. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/guide/query.md +0 -0
  67. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/guide/serialise.md +0 -0
  68. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/index.md +0 -0
  69. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/migration/matchbox-to-matchlab.md +0 -0
  70. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/stylesheets/extra.css +0 -0
  71. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/use-cases.md +0 -0
  72. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/docs/why-matchlab.md +0 -0
  73. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/justfile +0 -0
  74. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/mkdocs.yml +0 -0
  75. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/personal-data-exclusions.txt +0 -0
  76. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/pyproject.toml +0 -0
  77. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/scripts/test_eval.py +0 -0
  78. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/setup.cfg +0 -0
  79. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/__init__.py +0 -0
  80. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/adapters/__init__.py +0 -0
  81. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/adapters/base.py +0 -0
  82. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/adapters/duckdb.py +0 -0
  83. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/cli.py +0 -0
  84. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/__init__.py +0 -0
  85. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/dataframes.py +0 -0
  86. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/dsu.py +0 -0
  87. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/exceptions.py +0 -0
  88. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/hash.py +0 -0
  89. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/kinds.py +0 -0
  90. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/logging.py +0 -0
  91. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/resolver_output.py +0 -0
  92. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/schemas.py +0 -0
  93. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/core/sql.py +0 -0
  94. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/document.py +0 -0
  95. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/__init__.py +0 -0
  96. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/judgements.py +0 -0
  97. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/metrics.py +0 -0
  98. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/samples.py +0 -0
  99. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/tui/__init__.py +0 -0
  100. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/tui/app.py +0 -0
  101. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/tui/modals.py +0 -0
  102. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/tui/styles.tcss +0 -0
  103. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/tui/widgets/__init__.py +0 -0
  104. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/tui/widgets/assignment.py +0 -0
  105. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/tui/widgets/styling.py +0 -0
  106. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/eval/tui/widgets/table.py +0 -0
  107. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/lineage.py +0 -0
  108. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/__init__.py +0 -0
  109. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/comparison.py +0 -0
  110. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/dedupers/__init__.py +0 -0
  111. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/dedupers/base.py +0 -0
  112. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/dedupers/naive.py +0 -0
  113. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/linkers/__init__.py +0 -0
  114. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/linkers/base.py +0 -0
  115. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/linkers/deterministic.py +0 -0
  116. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/linkers/weighteddeterministic.py +0 -0
  117. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/models/models.py +0 -0
  118. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/progress.py +0 -0
  119. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/recordstep.py +0 -0
  120. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/resolvers/__init__.py +0 -0
  121. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/resolvers/base.py +0 -0
  122. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/resolvers/components.py +0 -0
  123. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/resolvers/resolvers.py +0 -0
  124. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/resources.py +0 -0
  125. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/sources/__init__.py +0 -0
  126. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/sources/base.py +0 -0
  127. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/sources/dataframe.py +0 -0
  128. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/sources/relational.py +0 -0
  129. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/sources/sources.py +0 -0
  130. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/specs.py +0 -0
  131. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/steps.py +0 -0
  132. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/__init__.py +0 -0
  133. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/_generate.py +0 -0
  134. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/compare.py +0 -0
  135. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/entities.py +0 -0
  136. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/features.py +0 -0
  137. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/linked.py +0 -0
  138. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/matchers.py +0 -0
  139. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/models.py +0 -0
  140. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/testkit/sources.py +0 -0
  141. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/transformers/__init__.py +0 -0
  142. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/transformers/base.py +0 -0
  143. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/transformers/clean.py +0 -0
  144. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/transformers/explode.py +0 -0
  145. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/transformers/group.py +0 -0
  146. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/transformers/select.py +0 -0
  147. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab/transformers/transform.py +0 -0
  148. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab.egg-info/dependency_links.txt +0 -0
  149. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab.egg-info/entry_points.txt +0 -0
  150. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab.egg-info/requires.txt +0 -0
  151. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab.egg-info/scm_file_list.json +0 -0
  152. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/src/matchlab.egg-info/top_level.txt +0 -0
  153. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/README.md +0 -0
  154. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/__init__.py +0 -0
  155. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/adapters/__init__.py +0 -0
  156. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/adapters/conftest.py +0 -0
  157. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/adapters/test_base.py +0 -0
  158. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/adapters/test_contract.py +0 -0
  159. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/adapters/test_duckdb.py +0 -0
  160. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/conftest.py +0 -0
  161. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/core/__init__.py +0 -0
  162. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/core/test_dsu.py +0 -0
  163. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/core/test_eval.py +0 -0
  164. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/core/test_hash.py +0 -0
  165. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/core/test_resolver_output.py +0 -0
  166. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/eval/__init__.py +0 -0
  167. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/eval/test_samples.py +0 -0
  168. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/eval/tui/__init__.py +0 -0
  169. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/eval/tui/test_app.py +0 -0
  170. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/eval/tui/test_widgets.py +0 -0
  171. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/models/__init__.py +0 -0
  172. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/models/test_comparison.py +0 -0
  173. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/models/test_dedupers_deterministic.py +0 -0
  174. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/models/test_linkers_deterministic.py +0 -0
  175. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/models/test_linkers_probabilistic.py +0 -0
  176. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/models/test_models.py +0 -0
  177. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/plan/__init__.py +0 -0
  178. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/plan/test_ground_truth.py +0 -0
  179. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/plan/test_plan.py +0 -0
  180. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/plan/test_steps.py +0 -0
  181. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/resolvers/__init__.py +0 -0
  182. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/resolvers/test_components.py +0 -0
  183. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/resolvers/test_resolvers.py +0 -0
  184. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/sources/__init__.py +0 -0
  185. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/sources/conftest.py +0 -0
  186. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/sources/test_locations.py +0 -0
  187. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/test_benchmarks.py +0 -0
  188. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/test_cli.py +0 -0
  189. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/test_document.py +0 -0
  190. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/test_lineage.py +0 -0
  191. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/test_progress.py +0 -0
  192. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/test_resources.py +0 -0
  193. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/testkit/__init__.py +0 -0
  194. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/testkit/test_entities.py +0 -0
  195. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/testkit/test_linked.py +0 -0
  196. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/testkit/test_models.py +0 -0
  197. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/testkit/test_scores.py +0 -0
  198. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/testkit/test_sources.py +0 -0
  199. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/transformers/__init__.py +0 -0
  200. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/transformers/test_clean.py +0 -0
  201. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/transformers/test_explode.py +0 -0
  202. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/transformers/test_group.py +0 -0
  203. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/transformers/test_select.py +0 -0
  204. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/test/transformers/test_transform.py +0 -0
  205. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/trufflehog-exclude.txt +0 -0
  206. {matchlab-0.1.0.dev3 → matchlab-0.1.0.dev4}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matchlab
3
- Version: 0.1.0.dev3
3
+ Version: 0.1.0.dev4
4
4
  Summary: A local-first library for building, running and evaluating entity resolution pipelines.
5
5
  Author: Department for Business and Trade
6
6
  Project-URL: Documentation, https://uktrade.github.io/matchlab/
@@ -174,21 +174,52 @@ class SplinkLinker(Linker):
174
174
  _id_dtype_l: pl.DataType
175
175
  _id_dtype_r: pl.DataType
176
176
 
177
+ @staticmethod
178
+ def _schema_summary(data: pl.DataFrame) -> str:
179
+ """Render a compact column-to-dtype summary for diagnostics."""
180
+ return (
181
+ ", ".join(f"{column}={dtype}" for column, dtype in data.schema.items())
182
+ or "<empty>"
183
+ )
184
+
185
+ @classmethod
186
+ def _conformancy_error(cls, left: pl.DataFrame, right: pl.DataFrame) -> ValueError:
187
+ """Build a detailed error describing how the two inputs differ."""
188
+ left_only = [column for column in left.columns if column not in right.columns]
189
+ right_only = [column for column in right.columns if column not in left.columns]
190
+ shared = [column for column in left.columns if column in right.columns]
191
+ differing_dtypes = [
192
+ f"{column}: left={left.schema[column]}, right={right.schema[column]}"
193
+ for column in shared
194
+ if left.schema[column] != right.schema[column]
195
+ ]
196
+
197
+ details = [
198
+ "SplinkLinker requires input data to be conformant, meaning they "
199
+ "share the same column names and data formats.",
200
+ f"Left schema: {cls._schema_summary(left)}",
201
+ f"Right schema: {cls._schema_summary(right)}",
202
+ ]
203
+ if left_only:
204
+ details.append(f"Columns only on left: {left_only}")
205
+ if right_only:
206
+ details.append(f"Columns only on right: {right_only}")
207
+ if differing_dtypes:
208
+ details.append("Differing dtypes: " + "; ".join(differing_dtypes))
209
+ return ValueError("\n".join(details))
210
+
177
211
  def prepare(self, left: pl.DataFrame, right: pl.DataFrame) -> None:
178
212
  """Build the Splink linker over left and right, and run its training functions.
179
213
 
180
214
  Runs each function in `settings.linker_training_functions`, in order, against
181
215
  the built linker. `link()` then just predicts against the trained state.
182
216
  """
183
- if (set(left.columns) != set(right.columns)) or not left.dtypes == right.dtypes:
184
- raise ValueError(
185
- "SplinkLinker requires input data to be conformant, meaning they "
186
- "share the same column names and data formats."
187
- )
188
-
189
217
  self._id_dtype_l = left[self.left_id].dtype
190
218
  self._id_dtype_r = right[self.right_id].dtype
191
219
 
220
+ if (set(left.columns) != set(right.columns)) or not left.dtypes == right.dtypes:
221
+ raise self._conformancy_error(left, right)
222
+
192
223
  # Convert to pandas for Splink compatibility
193
224
  left_pd = left.with_columns(pl.col(self.left_id).cast(pl.String)).to_pandas()
194
225
  right_pd = right.with_columns(pl.col(self.right_id).cast(pl.String)).to_pandas()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matchlab
3
- Version: 0.1.0.dev3
3
+ Version: 0.1.0.dev4
4
4
  Summary: A local-first library for building, running and evaluating entity resolution pipelines.
5
5
  Author: Department for Business and Trade
6
6
  Project-URL: Documentation, https://uktrade.github.io/matchlab/
@@ -178,6 +178,7 @@ test/models/test_comparison.py
178
178
  test/models/test_dedupers_deterministic.py
179
179
  test/models/test_linkers_deterministic.py
180
180
  test/models/test_linkers_probabilistic.py
181
+ test/models/test_linkers_splink.py
181
182
  test/models/test_models.py
182
183
  test/plan/__init__.py
183
184
  test/plan/test_ground_truth.py
@@ -2,7 +2,7 @@
2
2
  "tag": "0.10.8",
3
3
  "distance": 124,
4
4
  "node": "g7e5c31cc44787c13778c651231dcaa28893314e6",
5
- "dirty": false,
5
+ "dirty": true,
6
6
  "branch": "matchlab",
7
7
  "node_date": "2026-08-19"
8
8
  }
@@ -0,0 +1,42 @@
1
+ """Direct unit tests for `SplinkLinker` behavior.
2
+
3
+ These tests cover Splink-specific schema handling and diagnostics, rather than the
4
+ shared match/no-match behavior exercised in the other linker suites.
5
+ """
6
+
7
+ import polars as pl
8
+ import pytest
9
+ from splink import SettingsCreator
10
+ from splink import blocking_rule_library as brl
11
+ from splink import comparison_library as cl
12
+
13
+ from matchlab.models.linkers.splinklinker import SplinkLinker
14
+
15
+
16
+ def test_splink_conformancy_error() -> None:
17
+ """Splink surfaces the concrete schema mismatch from the real prepare path."""
18
+ linker = SplinkLinker(
19
+ left_id="id",
20
+ right_id="id",
21
+ linker_training_functions=[],
22
+ linker_settings=SettingsCreator(
23
+ link_type="link_only",
24
+ blocking_rules_to_generate_predictions=[brl.block_on("id")],
25
+ comparisons=[cl.ExactMatch("id")],
26
+ ),
27
+ threshold=None,
28
+ )
29
+ left = pl.DataFrame({"id": [1], "company_name": ["left"]})
30
+ right = pl.DataFrame({"id": [2], "postcode": ["SW1A 1AA"]})
31
+
32
+ with pytest.raises(
33
+ ValueError,
34
+ match="SplinkLinker requires input data to be conformant",
35
+ ) as exc_info:
36
+ linker.prepare(left, right)
37
+
38
+ message = str(exc_info.value)
39
+ assert "Left schema: id=Int64, company_name=String" in message
40
+ assert "Right schema: id=Int64, postcode=String" in message
41
+ assert "Columns only on left: ['company_name']" in message
42
+ assert "Columns only on right: ['postcode']" in message
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes