matchbox-db 0.7.14.dev46__tar.gz → 0.7.14.dev51__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 (245) hide show
  1. {matchbox_db-0.7.14.dev46/src/matchbox_db.egg-info → matchbox_db-0.7.14.dev51}/PKG-INFO +2 -2
  2. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/pyproject.toml +1 -1
  3. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/_handler.py +8 -8
  4. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/_settings.py +1 -1
  5. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/app.py +5 -7
  6. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/dags.py +2 -2
  7. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/eval/samples.py +8 -6
  8. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/models.py +3 -5
  9. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/sources.py +4 -6
  10. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/arrow.py +1 -1
  11. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/dtos.py +59 -52
  12. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/eval.py +1 -1
  13. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/exceptions.py +22 -4
  14. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/logging.py +2 -46
  15. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/auth.py +1 -3
  16. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/eval.py +2 -2
  17. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/base.py +173 -5
  18. matchbox_db-0.7.14.dev51/src/matchbox/server/postgresql/adapter/admin.py +570 -0
  19. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/eval.py +2 -2
  20. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/evaluation.py +14 -10
  21. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51/src/matchbox_db.egg-info}/PKG-INFO +2 -2
  22. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/requires.txt +1 -1
  23. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/cli/eval/test_app.py +0 -1
  24. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/test_eval.py +6 -6
  25. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/test_handler.py +1 -1
  26. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/test_eval.py +3 -3
  27. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/e2e/test_e2e_evaluation.py +1 -1
  28. matchbox_db-0.7.14.dev51/test/server/adapter/test_adapter_admin.py +782 -0
  29. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/adapter/test_adapter_eval.py +24 -21
  30. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_auth.py +2 -3
  31. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_eval.py +7 -7
  32. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/uv.lock +2 -2
  33. matchbox_db-0.7.14.dev46/src/matchbox/server/postgresql/adapter/admin.py +0 -139
  34. matchbox_db-0.7.14.dev46/test/server/adapter/test_adapter_admin.py +0 -169
  35. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.github/pull_request_template.md +0 -0
  36. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.github/workflows/ci.yml +0 -0
  37. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.github/workflows/codeql.yml +0 -0
  38. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.github/workflows/prerelease.yml +0 -0
  39. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.github/workflows/release.yml +0 -0
  40. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.gitignore +0 -0
  41. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.pre-commit-config.yaml +0 -0
  42. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.vscode/launch.json +0 -0
  43. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/.vscode/settings.json +0 -0
  44. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/CODEOWNERS +0 -0
  45. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/LICENSE +0 -0
  46. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/README.md +0 -0
  47. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docker-compose.yml +0 -0
  48. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/client/dags.md +0 -0
  49. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/client/eval.md +0 -0
  50. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/client/index.md +0 -0
  51. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/client/locations.md +0 -0
  52. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/client/models.md +0 -0
  53. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/client/queries.md +0 -0
  54. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/client/results.md +0 -0
  55. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/client/sources.md +0 -0
  56. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/arrow.md +0 -0
  57. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/db.md +0 -0
  58. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/dtos.md +0 -0
  59. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/eval.md +0 -0
  60. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/exceptions.md +0 -0
  61. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/entities.md +0 -0
  62. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/index.md +0 -0
  63. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/models.md +0 -0
  64. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/scenarios.md +0 -0
  65. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/sources.md +0 -0
  66. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/hash.md +0 -0
  67. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/index.md +0 -0
  68. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/logging.md +0 -0
  69. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/common/transform.md +0 -0
  70. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/server/api.md +0 -0
  71. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/server/backends/postgresql.md +0 -0
  72. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/server/index.md +0 -0
  73. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/api/server/uploads.md +0 -0
  74. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/assets/matchbox-icon-dark.png +0 -0
  75. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/assets/matchbox-icon.svg +0 -0
  76. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/assets/matchbox-logo-dark.svg +0 -0
  77. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/assets/matchbox-logo-light.svg +0 -0
  78. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/client/cli.md +0 -0
  79. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/client/evaluation.md +0 -0
  80. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/client/explore-dags.md +0 -0
  81. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/client/install.md +0 -0
  82. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/client/link-data.md +0 -0
  83. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/client/look-up.md +0 -0
  84. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/contributing.md +0 -0
  85. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/index.md +0 -0
  86. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/server/concepts.md +0 -0
  87. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/server/install.md +0 -0
  88. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/server/risks.md +0 -0
  89. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/stylesheets/extra.css +0 -0
  90. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/docs/use-cases.md +0 -0
  91. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/environments/containers.env +0 -0
  92. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/environments/development.env +0 -0
  93. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/environments/sample_client.env +0 -0
  94. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/environments/sample_server.env +0 -0
  95. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/justfile +0 -0
  96. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/mkdocs.yml +0 -0
  97. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/setup.cfg +0 -0
  98. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/__init__.py +0 -0
  99. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/__init__.py +0 -0
  100. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/__init__.py +0 -0
  101. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/auth.py +0 -0
  102. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/__init__.py +0 -0
  103. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/modals.py +0 -0
  104. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/run.py +0 -0
  105. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/styles.tcss +0 -0
  106. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/widgets/__init__.py +0 -0
  107. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/widgets/assignment.py +0 -0
  108. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/widgets/styling.py +0 -0
  109. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/widgets/table.py +0 -0
  110. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/main.py +0 -0
  111. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/server.py +0 -0
  112. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/eval/__init__.py +0 -0
  113. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/locations.py +0 -0
  114. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/__init__.py +0 -0
  115. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/comparison.py +0 -0
  116. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/dedupers/__init__.py +0 -0
  117. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/dedupers/base.py +0 -0
  118. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/dedupers/naive.py +0 -0
  119. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/__init__.py +0 -0
  120. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/base.py +0 -0
  121. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/deterministic.py +0 -0
  122. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/splinklinker.py +0 -0
  123. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/weighteddeterministic.py +0 -0
  124. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/queries.py +0 -0
  125. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/client/results.py +0 -0
  126. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/__init__.py +0 -0
  127. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/db.py +0 -0
  128. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/__init__.py +0 -0
  129. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/dags.py +0 -0
  130. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/entities.py +0 -0
  131. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/models.py +0 -0
  132. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/scenarios.py +0 -0
  133. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/sources.py +0 -0
  134. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/hash.py +0 -0
  135. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/common/transform.py +0 -0
  136. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/Dockerfile +0 -0
  137. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/__init__.py +0 -0
  138. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/__init__.py +0 -0
  139. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/dependencies.py +0 -0
  140. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/main.py +0 -0
  141. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/__init__.py +0 -0
  142. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/collection.py +0 -0
  143. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/static/favicon.png +0 -0
  144. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/static/swagger-ui-bundle.js +0 -0
  145. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/static/swagger-ui.css +0 -0
  146. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/.gitkeep +0 -0
  147. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/__init__.py +0 -0
  148. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/__init__.py +0 -0
  149. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/collections.py +0 -0
  150. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/main.py +0 -0
  151. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/query.py +0 -0
  152. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/env.py +0 -0
  153. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/script.py.mako +0 -0
  154. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/05cc4181a0ad_removed_source_key_reference_and_added_.py +0 -0
  155. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/13095b44ff09_add_user_model_groups_and_permissions_.py +0 -0
  156. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/1907c34cfa1f_create_tables_given_schema.py +0 -0
  157. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/3754ae042254_move_orm_to_root_leaf_contains_structure.py +0 -0
  158. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/40a8e5ed48f2_create_schema_without_tables.py +0 -0
  159. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/4a7c35f86405_move_sourceconfigs_from_sourceaddress_.py +0 -0
  160. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/7a2d1b10ac0f_switch_from_location_uri_to_name.py +0 -0
  161. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/83b134a86713_simplify_resolution_naming_and_hashing.py +0 -0
  162. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/8c7f757b1046_remove_human_resolution_type.py +0 -0
  163. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/95c0b5c23446_renaming_sources_to_source_config.py +0 -0
  164. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/ae63f79f6b39_renamed_sourcecolumns_to_sourcefields.py +0 -0
  165. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/b38d61ab11cc_add_index_to_the_clustersourcekey_table.py +0 -0
  166. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/b694eb292dea_add_an_index_to_the_probabilities_.py +0 -0
  167. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/beba75a24962_add_pkspace_table.py +0 -0
  168. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/c4cb937d00f4_add_modelconfigs.py +0 -0
  169. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/c774fd4b69f8_add_upload_stage_to_resolutions.py +0 -0
  170. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/dd0c3a9ecdf9_add_migrations_for_first_eval_tables.py +0 -0
  171. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/e4122bdf9b0d_renamed_primary_keys_to_just_keys.py +0 -0
  172. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/f3c9279437f4_add_content_hash_to_resolutions.py +0 -0
  173. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/f500f7d832fe_adds_collections_and_versions_to_scope_.py +0 -0
  174. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic.ini +0 -0
  175. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/db.py +0 -0
  176. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/justfile +0 -0
  177. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/mixin.py +0 -0
  178. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/orm.py +0 -0
  179. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/__init__.py +0 -0
  180. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/db.py +0 -0
  181. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/insert.py +0 -0
  182. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/query.py +0 -0
  183. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/results.py +0 -0
  184. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox/server/uploads.py +0 -0
  185. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/SOURCES.txt +0 -0
  186. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/dependency_links.txt +0 -0
  187. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/entry_points.txt +0 -0
  188. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/top_level.txt +0 -0
  189. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/__init__.py +0 -0
  190. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/__init__.py +0 -0
  191. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/cli/__init__.py +0 -0
  192. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/cli/eval/__init__.py +0 -0
  193. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/cli/eval/test_widgets.py +0 -0
  194. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/cli/test_main.py +0 -0
  195. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/models/__init__.py +0 -0
  196. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/models/methodologies/__init__.py +0 -0
  197. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/models/methodologies/test_dedupers_deterministic.py +0 -0
  198. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/models/methodologies/test_linkers_deterministic.py +0 -0
  199. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/models/methodologies/test_linkers_probabilistic.py +0 -0
  200. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/models/test_comparison.py +0 -0
  201. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/test_dags.py +0 -0
  202. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/test_locations.py +0 -0
  203. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/test_models.py +0 -0
  204. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/test_queries.py +0 -0
  205. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/test_results.py +0 -0
  206. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/client/test_sources.py +0 -0
  207. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/__init__.py +0 -0
  208. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/factories/__init__.py +0 -0
  209. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/factories/test_entity_factory.py +0 -0
  210. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/factories/test_linked_factory.py +0 -0
  211. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/factories/test_model_factory.py +0 -0
  212. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/factories/test_probability_generation.py +0 -0
  213. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/factories/test_scenarios.py +0 -0
  214. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/factories/test_source_factory.py +0 -0
  215. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/factories/test_testkit_dag.py +0 -0
  216. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/test_dto.py +0 -0
  217. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/test_hash.py +0 -0
  218. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/test_results.py +0 -0
  219. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/common/test_transform.py +0 -0
  220. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/conftest.py +0 -0
  221. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/data/all_companies.csv +0 -0
  222. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/e2e/test_e2e_dag.py +0 -0
  223. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/e2e/test_e2e_methodologies.py +0 -0
  224. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/fixtures/__init__.py +0 -0
  225. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/fixtures/client.py +0 -0
  226. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/fixtures/db.py +0 -0
  227. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/justfile +0 -0
  228. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/scripts/authorisation.py +0 -0
  229. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/scripts/eval.py +0 -0
  230. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/__init__.py +0 -0
  231. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/adapter/test_adapter_collections.py +0 -0
  232. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/adapter/test_adapter_main.py +0 -0
  233. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/adapter/test_adapter_query.py +0 -0
  234. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/api/__init__.py +0 -0
  235. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/api/routes/__init__.py +0 -0
  236. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_collection.py +0 -0
  237. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_main.py +0 -0
  238. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_resolution.py +0 -0
  239. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/postgresql/__init__.py +0 -0
  240. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/postgresql/test_pg_core.py +0 -0
  241. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/postgresql/test_pg_migrations.py +0 -0
  242. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/postgresql/test_pg_sql.py +0 -0
  243. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/server/test_uploads.py +0 -0
  244. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/test/utils.py +0 -0
  245. {matchbox_db-0.7.14.dev46 → matchbox_db-0.7.14.dev51}/trufflehog-exclude.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matchbox-db
3
- Version: 0.7.14.dev46
3
+ Version: 0.7.14.dev51
4
4
  Summary: A framework for orchestrating and comparing data linking and deduplication methodologies.
5
5
  Author: Department for Business and Trade
6
6
  Project-URL: Documentation, https://uktrade.github.io/matchbox/
@@ -11,6 +11,7 @@ License-File: LICENSE
11
11
  Requires-Dist: click>=8.1.7
12
12
  Requires-Dist: cryptography>=44.0.2
13
13
  Requires-Dist: duckdb>=1.1.1
14
+ Requires-Dist: email-validator>=2.3.0
14
15
  Requires-Dist: faker>=36.1.1
15
16
  Requires-Dist: frozendict>=2.4.6
16
17
  Requires-Dist: httpx>=0.28.0
@@ -29,7 +30,6 @@ Requires-Dist: sqlglot[rs]>=26.12.1
29
30
  Requires-Dist: tenacity>=9.1.2
30
31
  Requires-Dist: textual>=0.87.1
31
32
  Requires-Dist: typer>=0.15.0
32
- Requires-Dist: psutil>=7.1.3
33
33
  Provides-Extra: server
34
34
  Requires-Dist: adbc-driver-postgresql>=1.5.0; extra == "server"
35
35
  Requires-Dist: alembic>=1.15.2; extra == "server"
@@ -10,6 +10,7 @@ dependencies = [
10
10
  "click>=8.1.7",
11
11
  "cryptography>=44.0.2",
12
12
  "duckdb>=1.1.1",
13
+ "email-validator>=2.3.0",
13
14
  "faker>=36.1.1",
14
15
  "frozendict>=2.4.6",
15
16
  "httpx>=0.28.0",
@@ -28,7 +29,6 @@ dependencies = [
28
29
  "tenacity>=9.1.2",
29
30
  "textual>=0.87.1",
30
31
  "typer>=0.15.0",
31
- "psutil>=7.1.3"
32
32
  ]
33
33
 
34
34
  [project.optional-dependencies]
@@ -65,7 +65,7 @@ from matchbox.common.exceptions import (
65
65
  MatchboxUserNotFoundError,
66
66
  )
67
67
  from matchbox.common.hash import hash_to_base64
68
- from matchbox.common.logging import logger, profile_time
68
+ from matchbox.common.logging import logger, profile
69
69
 
70
70
  URLEncodeHandledType = str | int | float | bytes | StrEnum
71
71
 
@@ -189,7 +189,7 @@ def login(user_name: str) -> int:
189
189
  """Log into Matchbox and return the user ID."""
190
190
  logger.debug(f"Log in attempt for {user_name}")
191
191
  response = CLIENT.post("/auth/login", json=User(user_name=user_name).model_dump())
192
- return User.model_validate(response.json()).user_id
192
+ return User.model_validate(response.json()).user_name
193
193
 
194
194
 
195
195
  @http_retry
@@ -422,7 +422,7 @@ def update_resolution(
422
422
  return ResourceOperationStatus.model_validate(res.json())
423
423
 
424
424
 
425
- @profile_time(kwarg="path")
425
+ @profile(kwarg="path")
426
426
  @http_retry
427
427
  def get_resolution(path: ResolutionPath) -> Resolution | None:
428
428
  """Get a resolution from Matchbox."""
@@ -435,7 +435,7 @@ def get_resolution(path: ResolutionPath) -> Resolution | None:
435
435
  return Resolution.model_validate(res.json())
436
436
 
437
437
 
438
- @profile_time(kwarg="path")
438
+ @profile(kwarg="path")
439
439
  @http_retry
440
440
  def set_data(path: ResolutionPath, data: pl.DataFrame | Table) -> None:
441
441
  """Upload source hashes or model results to server."""
@@ -482,7 +482,7 @@ def get_resolution_stage(path: ResolutionPath) -> UploadStage:
482
482
  return upload_info.stage
483
483
 
484
484
 
485
- @profile_time(kwarg="path")
485
+ @profile(kwarg="path")
486
486
  @http_retry
487
487
  def get_results(path: ModelResolutionPath) -> Table:
488
488
  """Get model results from Matchbox."""
@@ -515,7 +515,7 @@ def delete_resolution(
515
515
 
516
516
 
517
517
  @http_retry
518
- def sample_for_eval(n: int, resolution: ModelResolutionPath, user_id: int) -> Table:
518
+ def sample_for_eval(n: int, resolution: ModelResolutionPath, user_name: str) -> Table:
519
519
  """Sample model results for evaluation."""
520
520
  res = CLIENT.get(
521
521
  "/eval/samples",
@@ -525,7 +525,7 @@ def sample_for_eval(n: int, resolution: ModelResolutionPath, user_id: int) -> Ta
525
525
  "collection": resolution.collection,
526
526
  "run_id": resolution.run,
527
527
  "resolution": resolution.name,
528
- "user_id": user_id,
528
+ "user_name": user_name,
529
529
  }
530
530
  ),
531
531
  )
@@ -548,7 +548,7 @@ def send_eval_judgement(judgement: Judgement) -> None:
548
548
  """Send judgements to the server."""
549
549
  logger.debug(
550
550
  f"Submitting judgement {judgement.shown}:{judgement.endorsed} "
551
- f"for {judgement.user_id}"
551
+ f"for {judgement.user_name}"
552
552
  )
553
553
  CLIENT.post("/eval/judgements", json=judgement.model_dump())
554
554
 
@@ -42,7 +42,7 @@ class ClientSettings(BaseSettings):
42
42
  # Decode header and payload
43
43
  header = json.loads(base64.urlsafe_b64decode(parts[0] + "=="))
44
44
  payload = json.loads(base64.urlsafe_b64decode(parts[1] + "=="))
45
- except Exception as e: # noqa: BLE0001
45
+ except Exception as e: # noqa: BLE001
46
46
  raise ValueError("Invalid JWT.") from e
47
47
 
48
48
  # Basic header checks
@@ -108,7 +108,6 @@ class EntityResolutionApp(App):
108
108
 
109
109
  sample_limit: int
110
110
  resolution: ModelResolutionPath
111
- user_id: int
112
111
  user_name: str
113
112
  dag: DAG
114
113
  show_help: bool
@@ -304,8 +303,7 @@ class EntityResolutionApp(App):
304
303
  if not user_name:
305
304
  raise MatchboxClientSettingsException("User name is unset.")
306
305
 
307
- self.user_name = user_name
308
- self.user_id = _handler.login(user_name=user_name)
306
+ self.user_name = _handler.login(user_name=user_name)
309
307
 
310
308
  async def load_samples(self) -> None:
311
309
  """Load evaluation samples from the server."""
@@ -326,7 +324,7 @@ class EntityResolutionApp(App):
326
324
  new_samples_dict = get_samples(
327
325
  n=needed,
328
326
  resolution=self.resolution.name,
329
- user_id=self.user_id,
327
+ user_name=self.user_name,
330
328
  dag=self.dag,
331
329
  )
332
330
  except Exception as e: # noqa: BLE001
@@ -370,10 +368,10 @@ class EntityResolutionApp(App):
370
368
  return
371
369
 
372
370
  try:
373
- if self.user_id is None:
374
- raise RuntimeError("User ID is not set")
371
+ if self.user_name is None:
372
+ raise RuntimeError("User name is not set")
375
373
  judgement = create_judgement(
376
- current.item, current.assignments, self.user_id
374
+ current.item, current.assignments, self.user_name
377
375
  )
378
376
  _handler.send_eval_judgement(judgement)
379
377
  except Exception as exc:
@@ -28,7 +28,7 @@ from matchbox.common.exceptions import (
28
28
  MatchboxCollectionNotFoundError,
29
29
  MatchboxResolutionNotFoundError,
30
30
  )
31
- from matchbox.common.logging import logger, profile_time
31
+ from matchbox.common.logging import logger, profile
32
32
  from matchbox.common.transform import truth_int_to_float
33
33
 
34
34
 
@@ -561,7 +561,7 @@ class DAG:
561
561
  # If no matches, _handler will raise
562
562
  return {from_source: list(matches[0].source_id), **to_sources_results}
563
563
 
564
- @profile_time(kwarg="node")
564
+ @profile(kwarg="node")
565
565
  def resolve(
566
566
  self,
567
567
  node: ResolutionName | None = None,
@@ -73,14 +73,14 @@ class EvaluationItem(BaseModel):
73
73
 
74
74
 
75
75
  def create_judgement(
76
- item: EvaluationItem, assignments: dict[int, str], user_id: int
76
+ item: EvaluationItem, assignments: dict[int, str], user_name: str
77
77
  ) -> Judgement:
78
78
  """Convert item assignments to Judgement - no default group assignment.
79
79
 
80
80
  Args:
81
81
  item: Evaluation item
82
82
  assignments: Column assignments (group_idx -> group_letter)
83
- user_id: User ID for the judgement
83
+ user_name: User name for the judgement
84
84
 
85
85
  Returns:
86
86
  Judgement with endorsed groups based on assignments
@@ -93,7 +93,7 @@ def create_judgement(
93
93
  groups.setdefault(group, []).extend(leaf_ids)
94
94
 
95
95
  endorsed = [sorted(set(leaf_ids)) for leaf_ids in groups.values()]
96
- return Judgement(user_id=user_id, shown=item.cluster_id, endorsed=endorsed)
96
+ return Judgement(user_name=user_name, shown=item.cluster_id, endorsed=endorsed)
97
97
 
98
98
 
99
99
  def create_evaluation_item(
@@ -136,7 +136,7 @@ def create_evaluation_item(
136
136
  def get_samples(
137
137
  n: int,
138
138
  dag: DAG,
139
- user_id: int,
139
+ user_name: str,
140
140
  resolution: ModelResolutionName | None = None,
141
141
  ) -> dict[int, EvaluationItem]:
142
142
  """Retrieve samples enriched with source data as EvaluationItems.
@@ -144,7 +144,7 @@ def get_samples(
144
144
  Args:
145
145
  n: Number of clusters to sample
146
146
  dag: DAG for which to retrieve samples
147
- user_id: ID of the user requesting the samples
147
+ user_name: Name of the user requesting the samples
148
148
  resolution: The optional resolution from which to sample. If not provided,
149
149
  the final step in the DAG is used
150
150
 
@@ -163,7 +163,9 @@ def get_samples(
163
163
  samples: pl.DataFrame = cast(
164
164
  pl.DataFrame,
165
165
  pl.from_arrow(
166
- _handler.sample_for_eval(n=n, resolution=resolution_path, user_id=user_id)
166
+ _handler.sample_for_eval(
167
+ n=n, resolution=resolution_path, user_name=user_name
168
+ )
167
169
  ),
168
170
  )
169
171
 
@@ -24,7 +24,7 @@ from matchbox.common.dtos import (
24
24
  )
25
25
  from matchbox.common.exceptions import MatchboxResolutionNotFoundError
26
26
  from matchbox.common.hash import hash_model_results
27
- from matchbox.common.logging import logger, profile_mem, profile_time
27
+ from matchbox.common.logging import logger, profile
28
28
  from matchbox.common.transform import truth_float_to_int, truth_int_to_float
29
29
 
30
30
  if TYPE_CHECKING:
@@ -234,8 +234,7 @@ class Model:
234
234
  result = _handler.delete_resolution(path=self.resolution_path, certain=certain)
235
235
  return result.success
236
236
 
237
- @profile_mem()
238
- @profile_time(attr="name")
237
+ @profile(attr="name")
239
238
  def run(
240
239
  self, for_validation: bool = False, cache_queries: bool = False
241
240
  ) -> ModelResults:
@@ -285,8 +284,7 @@ class Model:
285
284
  return self.results
286
285
 
287
286
  @post_run
288
- @profile_mem()
289
- @profile_time(attr="name")
287
+ @profile(attr="name")
290
288
  def sync(self) -> None:
291
289
  """Send the model config and results to the server.
292
290
 
@@ -24,7 +24,7 @@ from matchbox.common.dtos import (
24
24
  )
25
25
  from matchbox.common.exceptions import MatchboxResolutionNotFoundError
26
26
  from matchbox.common.hash import HashMethod, hash_arrow_table, hash_rows
27
- from matchbox.common.logging import logger, profile_mem, profile_time
27
+ from matchbox.common.logging import logger, profile
28
28
 
29
29
  if TYPE_CHECKING:
30
30
  from matchbox.client.dags import DAG
@@ -223,7 +223,7 @@ class Source:
223
223
  return False
224
224
  return self.config == other.config
225
225
 
226
- @profile_time(attr="name")
226
+ @profile(attr="name")
227
227
  def fetch(
228
228
  self,
229
229
  qualify_names: bool = False,
@@ -270,8 +270,7 @@ class Source:
270
270
  return_type=return_type,
271
271
  )
272
272
 
273
- @profile_mem()
274
- @profile_time(attr="name")
273
+ @profile(attr="name")
275
274
  def run(self, batch_size: int | None = None) -> ArrowTable:
276
275
  """Hash a dataset from its warehouse, ready to be inserted, and cache hashes.
277
276
 
@@ -376,8 +375,7 @@ class Source:
376
375
  return self.config.f(self.name, fields)
377
376
 
378
377
  @post_run
379
- @profile_mem()
380
- @profile_time(attr="name")
378
+ @profile(attr="name")
381
379
  def sync(self) -> None:
382
380
  """Send the source config and hashes to the server.
383
381
 
@@ -36,7 +36,7 @@ SCHEMA_RESULTS: Final[pa.Schema] = pa.schema(
36
36
 
37
37
  SCHEMA_JUDGEMENTS: Final[pa.Schema] = pa.schema(
38
38
  [
39
- ("user_id", pa.uint64()),
39
+ ("user_name", pa.large_string()),
40
40
  ("endorsed", pa.uint64()),
41
41
  ("shown", pa.uint64()),
42
42
  ]
@@ -30,6 +30,54 @@ from matchbox.common.exceptions import MatchboxNameError
30
30
  from matchbox.common.hash import base64_to_hash, hash_to_base64
31
31
 
32
32
 
33
+ class MatchboxName(str):
34
+ """Sub-class of string which validates names for the Matchbox DB."""
35
+
36
+ PATTERN = r"^[a-zA-Z0-9_.-]+$"
37
+
38
+ def __new__(cls, value: str) -> Self:
39
+ """Creates new instance of validated name."""
40
+ if not isinstance(value, str):
41
+ raise MatchboxNameError("Name must be a string")
42
+ if not re.match(cls.PATTERN, value):
43
+ raise MatchboxNameError(
44
+ f"Name '{value}' is invalid. It can only include "
45
+ "alphanumeric characters, underscores, dots or hyphens."
46
+ )
47
+
48
+ return super().__new__(cls, value)
49
+
50
+ @classmethod
51
+ def __get_pydantic_core_schema__(
52
+ cls,
53
+ source_type: Any, # noqa: ANN401
54
+ handler: GetCoreSchemaHandler,
55
+ ) -> core_schema.CoreSchema:
56
+ """Generate core schema for Pydantic compatibility."""
57
+ return core_schema.no_info_plain_validator_function(
58
+ cls,
59
+ serialization=core_schema.plain_serializer_function_ser_schema(
60
+ lambda x: x, return_schema=core_schema.str_schema()
61
+ ),
62
+ )
63
+
64
+ @classmethod
65
+ def __get_pydantic_json_schema__(
66
+ cls,
67
+ schema: core_schema.CoreSchema,
68
+ handler: GetJsonSchemaHandler,
69
+ ) -> JsonSchemaValue:
70
+ """Generate JSON schema for OpenAPI documentation."""
71
+ json_schema = handler(core_schema.str_schema())
72
+ json_schema.update(
73
+ {
74
+ "type": "string",
75
+ "pattern": cls.PATTERN,
76
+ }
77
+ )
78
+ return json_schema
79
+
80
+
33
81
  class DataTypes(StrEnum):
34
82
  """Enumeration of supported data types.
35
83
 
@@ -169,6 +217,7 @@ class BackendResourceType(StrEnum):
169
217
  CLUSTER = "cluster"
170
218
  USER = "user"
171
219
  JUDGEMENT = "judgement"
220
+ SYSTEM = "system"
172
221
 
173
222
 
174
223
  class BackendParameterType(StrEnum):
@@ -205,24 +254,30 @@ class User(BaseModel):
205
254
 
206
255
  model_config = ConfigDict(populate_by_name=True)
207
256
 
208
- user_id: int | None = None
209
257
  user_name: str = Field(alias="sub")
210
258
  email: EmailStr | None = None
211
259
 
212
260
 
261
+ GroupName: TypeAlias = MatchboxName
262
+ """Type alias for group names."""
263
+
264
+
213
265
  class Group(BaseModel):
214
266
  """Group definition."""
215
267
 
216
- name: str
268
+ name: GroupName
217
269
  description: str | None = None
218
270
  is_system: bool = False
219
271
  members: list[User] = []
220
272
 
221
273
 
222
274
  class PermissionGrant(BaseModel):
223
- """A permission on a resource. Resource context comes from URL."""
275
+ """A permission on a resource.
224
276
 
225
- group_name: str
277
+ Resource context should always be supplied.
278
+ """
279
+
280
+ group_name: GroupName
226
281
  permission: PermissionType
227
282
 
228
283
 
@@ -234,54 +289,6 @@ class AuthStatusResponse(BaseModel):
234
289
  token: str | None = None
235
290
 
236
291
 
237
- class MatchboxName(str):
238
- """Sub-class of string which validates names for the Matchbox DB."""
239
-
240
- PATTERN = r"^[a-zA-Z0-9_.-]+$"
241
-
242
- def __new__(cls, value: str) -> Self:
243
- """Creates new instance of validated name."""
244
- if not isinstance(value, str):
245
- raise MatchboxNameError("Name must be a string")
246
- if not re.match(cls.PATTERN, value):
247
- raise MatchboxNameError(
248
- f"Name '{value}' is invalid. It can only include "
249
- "alphanumeric characters, underscores, dots or hyphens."
250
- )
251
-
252
- return super().__new__(cls, value)
253
-
254
- @classmethod
255
- def __get_pydantic_core_schema__(
256
- cls,
257
- source_type: Any, # noqa: ANN401
258
- handler: GetCoreSchemaHandler,
259
- ) -> core_schema.CoreSchema:
260
- """Generate core schema for Pydantic compatibility."""
261
- return core_schema.no_info_plain_validator_function(
262
- cls,
263
- serialization=core_schema.plain_serializer_function_ser_schema(
264
- lambda x: x, return_schema=core_schema.str_schema()
265
- ),
266
- )
267
-
268
- @classmethod
269
- def __get_pydantic_json_schema__(
270
- cls,
271
- schema: core_schema.CoreSchema,
272
- handler: GetJsonSchemaHandler,
273
- ) -> JsonSchemaValue:
274
- """Generate JSON schema for OpenAPI documentation."""
275
- json_schema = handler(core_schema.str_schema())
276
- json_schema.update(
277
- {
278
- "type": "string",
279
- "pattern": cls.PATTERN,
280
- }
281
- )
282
- return json_schema
283
-
284
-
285
292
  CollectionName: TypeAlias = MatchboxName
286
293
  """Type alias for collection names."""
287
294
 
@@ -18,7 +18,7 @@ ModelComparison: TypeAlias = dict[ModelResolutionPath, PrecisionRecall]
18
18
  class Judgement(BaseModel):
19
19
  """User determination on how to group source clusters from a model cluster."""
20
20
 
21
- user_id: int
21
+ user_name: str
22
22
  shown: int = Field(description="ID of the model cluster shown to the user")
23
23
  endorsed: list[list[int]] = Field(
24
24
  description="""Groups of source cluster IDs that user thinks belong together"""
@@ -174,15 +174,17 @@ class MatchboxServerFileError(MatchboxException):
174
174
  class MatchboxUserNotFoundError(MatchboxException):
175
175
  """User not found."""
176
176
 
177
- def __init__(self, message: str | None = None, user_id: str | None = None) -> None:
177
+ def __init__(
178
+ self, message: str | None = None, user_name: str | None = None
179
+ ) -> None:
178
180
  """Initialise the exception."""
179
181
  if message is None:
180
182
  message = "User not found."
181
- if user_id is not None:
182
- message = f"User {user_id} not found."
183
+ if user_name is not None:
184
+ message = f"User {user_name} not found."
183
185
 
184
186
  super().__init__(message)
185
- self.user_id = user_id
187
+ self.user_name = user_name
186
188
 
187
189
 
188
190
  class MatchboxResolutionNotFoundError(MatchboxException):
@@ -260,6 +262,10 @@ class MatchboxConnectionError(MatchboxException):
260
262
  """Connection to Matchbox's backend database failed."""
261
263
 
262
264
 
265
+ class MatchboxPermissionDeniedError(MatchboxException):
266
+ """Raised when a user lacks permission for an action."""
267
+
268
+
263
269
  class MatchboxDeletionNotConfirmed(MatchboxException):
264
270
  """Deletion must be confirmed: if certain, rerun with certain=True."""
265
271
 
@@ -319,6 +325,18 @@ class MatchboxTooManySamplesRequested(MatchboxException):
319
325
  """Too many samples have been requested from the server."""
320
326
 
321
327
 
328
+ class MatchboxGroupNotFoundError(MatchboxException):
329
+ """Raised when a group is not found."""
330
+
331
+
332
+ class MatchboxGroupAlreadyExistsError(MatchboxException):
333
+ """Raised when attempting to create a group that already exists."""
334
+
335
+
336
+ class MatchboxSystemGroupError(MatchboxException):
337
+ """Raised when attempting to modify or delete a system group."""
338
+
339
+
322
340
  # -- Adapter DB exceptions --
323
341
 
324
342
 
@@ -4,11 +4,9 @@ import functools
4
4
  import importlib.metadata
5
5
  import logging
6
6
  import time
7
- import tracemalloc
8
7
  from collections.abc import Callable
9
8
  from typing import Any, Final, Literal, ParamSpec, TypeVar
10
9
 
11
- import psutil
12
10
  from rich.console import Console
13
11
  from rich.progress import (
14
12
  BarColumn,
@@ -117,14 +115,14 @@ T = TypeVar("T")
117
115
  P = ParamSpec("P")
118
116
 
119
117
 
120
- def profile_time(
118
+ def profile(
121
119
  logger: PrefixedLoggerAdapter = logger,
122
120
  level: int = logging.INFO,
123
121
  prefix: str | None = "Profiling",
124
122
  attr: str | None = None,
125
123
  kwarg: str | None = None,
126
124
  ) -> Callable[[Callable[P, T]], Callable[P, T]]:
127
- """Decorator to profile running time of functions and methods using logger.
125
+ """Decorator to profile functions and methods using logger.
128
126
 
129
127
  Args:
130
128
  logger: The logger to use.
@@ -172,45 +170,3 @@ def profile_time(
172
170
  return wrapper
173
171
 
174
172
  return decorator
175
-
176
-
177
- def profile_mem(
178
- logger: PrefixedLoggerAdapter = logger,
179
- level: int = logging.DEBUG,
180
- prefix: str | None = "Memory",
181
- ) -> Callable[[Callable[P, T]], Callable[P, T]]:
182
- """Decorator to profile memory use of functions and methods using logger.
183
-
184
- Args:
185
- logger: The logger to use.
186
- level: The level to use to log the profiling information. It defaults to INFO.
187
- prefix: Prefix to pass to the logged message.
188
- """
189
-
190
- def decorator(func: Callable[P, T]) -> Callable[P, T]:
191
- @functools.wraps(func)
192
- def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
193
- tracemalloc.start()
194
-
195
- try:
196
- return func(*args, **kwargs)
197
- finally:
198
- # Final and peak mem use of decorated function
199
- curr, peak = tracemalloc.get_traced_memory()
200
- tracemalloc.stop()
201
- # OS memory availability after function run
202
- mem = psutil.virtual_memory()
203
-
204
- msg = (
205
- f"Memory usage of {func.__name__}: "
206
- f"current {round(curr / 10**6, 2)} MB, "
207
- f"peak {round(peak / 10**6, 2)} MB. "
208
- f"Total memory: {round(mem[0] / 10**6, 2)} MB, "
209
- f"available memory: {round(mem[1] / 10**6, 2)} MB."
210
- )
211
-
212
- logger.log(level, msg, prefix=prefix)
213
-
214
- return wrapper
215
-
216
- return decorator
@@ -48,9 +48,7 @@ def login(
48
48
  credentials: User,
49
49
  ) -> User:
50
50
  """Receive a User with a username and returns it with a user ID."""
51
- return User(
52
- user_id=backend.login(credentials.user_name), user_name=credentials.user_name
53
- )
51
+ return backend.login(credentials)
54
52
 
55
53
 
56
54
  @router.get("/status")
@@ -115,7 +115,7 @@ def sample(
115
115
  run_id: RunID,
116
116
  resolution: ModelResolutionName,
117
117
  n: int,
118
- user_id: int,
118
+ user_name: str,
119
119
  ) -> ParquetResponse:
120
120
  """Sample n cluster to validate."""
121
121
  try:
@@ -124,7 +124,7 @@ def sample(
124
124
  collection=collection, run=run_id, name=resolution
125
125
  ),
126
126
  n=n,
127
- user_id=user_id,
127
+ user_name=user_name,
128
128
  )
129
129
  buffer = table_to_buffer(sample)
130
130
  return ParquetResponse(buffer.getvalue())