matchbox-db 0.7.14.dev45__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.
- {matchbox_db-0.7.14.dev45/src/matchbox_db.egg-info → matchbox_db-0.7.14.dev51}/PKG-INFO +1 -1
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/_handler.py +4 -4
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/_settings.py +1 -1
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/app.py +5 -7
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/eval/samples.py +8 -6
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/arrow.py +1 -1
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/dtos.py +59 -52
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/eval.py +1 -1
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/exceptions.py +22 -4
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/auth.py +1 -3
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/eval.py +2 -2
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/base.py +173 -5
- matchbox_db-0.7.14.dev51/src/matchbox/server/postgresql/adapter/admin.py +570 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/eval.py +2 -2
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/evaluation.py +14 -10
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51/src/matchbox_db.egg-info}/PKG-INFO +1 -1
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/cli/eval/test_app.py +0 -1
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/test_eval.py +6 -6
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/test_handler.py +1 -1
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/test_eval.py +3 -3
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/e2e/test_e2e_evaluation.py +1 -1
- matchbox_db-0.7.14.dev51/test/server/adapter/test_adapter_admin.py +782 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/adapter/test_adapter_eval.py +24 -21
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_auth.py +2 -3
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_eval.py +7 -7
- matchbox_db-0.7.14.dev45/src/matchbox/server/postgresql/adapter/admin.py +0 -139
- matchbox_db-0.7.14.dev45/test/server/adapter/test_adapter_admin.py +0 -169
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.github/pull_request_template.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.github/workflows/ci.yml +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.github/workflows/codeql.yml +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.github/workflows/prerelease.yml +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.github/workflows/release.yml +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.gitignore +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.pre-commit-config.yaml +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.vscode/launch.json +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/.vscode/settings.json +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/CODEOWNERS +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/LICENSE +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/README.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docker-compose.yml +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/client/dags.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/client/eval.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/client/index.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/client/locations.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/client/models.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/client/queries.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/client/results.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/client/sources.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/arrow.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/db.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/dtos.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/eval.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/exceptions.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/entities.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/index.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/models.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/scenarios.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/factories/sources.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/hash.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/index.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/logging.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/common/transform.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/server/api.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/server/backends/postgresql.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/server/index.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/api/server/uploads.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/assets/matchbox-icon-dark.png +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/assets/matchbox-icon.svg +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/assets/matchbox-logo-dark.svg +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/assets/matchbox-logo-light.svg +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/client/cli.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/client/evaluation.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/client/explore-dags.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/client/install.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/client/link-data.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/client/look-up.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/contributing.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/index.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/server/concepts.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/server/install.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/server/risks.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/stylesheets/extra.css +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/docs/use-cases.md +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/environments/containers.env +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/environments/development.env +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/environments/sample_client.env +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/environments/sample_server.env +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/justfile +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/mkdocs.yml +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/pyproject.toml +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/setup.cfg +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/auth.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/modals.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/run.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/styles.tcss +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/widgets/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/widgets/assignment.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/widgets/styling.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/eval/widgets/table.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/main.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/cli/server.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/dags.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/eval/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/locations.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/comparison.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/dedupers/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/dedupers/base.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/dedupers/naive.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/base.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/deterministic.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/splinklinker.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/linkers/weighteddeterministic.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/models/models.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/queries.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/results.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/client/sources.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/db.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/dags.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/entities.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/models.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/scenarios.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/factories/sources.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/hash.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/logging.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/common/transform.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/Dockerfile +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/dependencies.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/main.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/collection.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/static/favicon.png +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/static/swagger-ui-bundle.js +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/static/swagger-ui.css +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/.gitkeep +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/collections.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/main.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/adapter/query.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/env.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/script.py.mako +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/05cc4181a0ad_removed_source_key_reference_and_added_.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/13095b44ff09_add_user_model_groups_and_permissions_.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/1907c34cfa1f_create_tables_given_schema.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/3754ae042254_move_orm_to_root_leaf_contains_structure.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/40a8e5ed48f2_create_schema_without_tables.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/4a7c35f86405_move_sourceconfigs_from_sourceaddress_.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/7a2d1b10ac0f_switch_from_location_uri_to_name.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/83b134a86713_simplify_resolution_naming_and_hashing.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/8c7f757b1046_remove_human_resolution_type.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/95c0b5c23446_renaming_sources_to_source_config.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/ae63f79f6b39_renamed_sourcecolumns_to_sourcefields.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/b38d61ab11cc_add_index_to_the_clustersourcekey_table.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/b694eb292dea_add_an_index_to_the_probabilities_.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/beba75a24962_add_pkspace_table.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/c4cb937d00f4_add_modelconfigs.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/c774fd4b69f8_add_upload_stage_to_resolutions.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/dd0c3a9ecdf9_add_migrations_for_first_eval_tables.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/e4122bdf9b0d_renamed_primary_keys_to_just_keys.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/f3c9279437f4_add_content_hash_to_resolutions.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic/versions/f500f7d832fe_adds_collections_and_versions_to_scope_.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/alembic.ini +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/db.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/justfile +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/mixin.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/orm.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/db.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/insert.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/query.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/postgresql/utils/results.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/uploads.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/SOURCES.txt +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/dependency_links.txt +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/entry_points.txt +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/requires.txt +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox_db.egg-info/top_level.txt +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/cli/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/cli/eval/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/cli/eval/test_widgets.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/cli/test_main.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/models/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/models/methodologies/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/models/methodologies/test_dedupers_deterministic.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/models/methodologies/test_linkers_deterministic.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/models/methodologies/test_linkers_probabilistic.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/models/test_comparison.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/test_dags.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/test_locations.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/test_models.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/test_queries.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/test_results.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/client/test_sources.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/factories/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/factories/test_entity_factory.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/factories/test_linked_factory.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/factories/test_model_factory.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/factories/test_probability_generation.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/factories/test_scenarios.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/factories/test_source_factory.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/factories/test_testkit_dag.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/test_dto.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/test_hash.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/test_results.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/common/test_transform.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/conftest.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/data/all_companies.csv +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/e2e/test_e2e_dag.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/e2e/test_e2e_methodologies.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/fixtures/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/fixtures/client.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/fixtures/db.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/justfile +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/scripts/authorisation.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/scripts/eval.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/adapter/test_adapter_collections.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/adapter/test_adapter_main.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/adapter/test_adapter_query.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/api/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/api/routes/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_collection.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_main.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/api/routes/test_routes_resolution.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/postgresql/__init__.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/postgresql/test_pg_core.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/postgresql/test_pg_migrations.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/postgresql/test_pg_sql.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/server/test_uploads.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/test/utils.py +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/trufflehog-exclude.txt +0 -0
- {matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: matchbox-db
|
|
3
|
-
Version: 0.7.14.
|
|
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/
|
|
@@ -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()).
|
|
192
|
+
return User.model_validate(response.json()).user_name
|
|
193
193
|
|
|
194
194
|
|
|
195
195
|
@http_retry
|
|
@@ -515,7 +515,7 @@ def delete_resolution(
|
|
|
515
515
|
|
|
516
516
|
|
|
517
517
|
@http_retry
|
|
518
|
-
def sample_for_eval(n: int, resolution: ModelResolutionPath,
|
|
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
|
-
"
|
|
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.
|
|
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:
|
|
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
|
-
|
|
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.
|
|
374
|
-
raise RuntimeError("User
|
|
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.
|
|
374
|
+
current.item, current.assignments, self.user_name
|
|
377
375
|
)
|
|
378
376
|
_handler.send_eval_judgement(judgement)
|
|
379
377
|
except Exception as exc:
|
|
@@ -73,14 +73,14 @@ class EvaluationItem(BaseModel):
|
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
def create_judgement(
|
|
76
|
-
item: EvaluationItem, assignments: dict[int, str],
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
166
|
+
_handler.sample_for_eval(
|
|
167
|
+
n=n, resolution=resolution_path, user_name=user_name
|
|
168
|
+
)
|
|
167
169
|
),
|
|
168
170
|
)
|
|
169
171
|
|
|
@@ -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:
|
|
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.
|
|
275
|
+
"""A permission on a resource.
|
|
224
276
|
|
|
225
|
-
|
|
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
|
-
|
|
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__(
|
|
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
|
|
182
|
-
message = f"User {
|
|
183
|
+
if user_name is not None:
|
|
184
|
+
message = f"User {user_name} not found."
|
|
183
185
|
|
|
184
186
|
super().__init__(message)
|
|
185
|
-
self.
|
|
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
|
|
{matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/auth.py
RENAMED
|
@@ -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
|
|
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")
|
{matchbox_db-0.7.14.dev45 → matchbox_db-0.7.14.dev51}/src/matchbox/server/api/routers/eval.py
RENAMED
|
@@ -115,7 +115,7 @@ def sample(
|
|
|
115
115
|
run_id: RunID,
|
|
116
116
|
resolution: ModelResolutionName,
|
|
117
117
|
n: int,
|
|
118
|
-
|
|
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
|
-
|
|
127
|
+
user_name=user_name,
|
|
128
128
|
)
|
|
129
129
|
buffer = table_to_buffer(sample)
|
|
130
130
|
return ParquetResponse(buffer.getvalue())
|
|
@@ -12,16 +12,22 @@ from pydantic import BaseModel, Field, SecretStr, field_validator, model_validat
|
|
|
12
12
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
13
13
|
|
|
14
14
|
from matchbox.common.dtos import (
|
|
15
|
+
BackendResourceType,
|
|
15
16
|
Collection,
|
|
16
17
|
CollectionName,
|
|
18
|
+
Group,
|
|
19
|
+
GroupName,
|
|
17
20
|
Match,
|
|
18
21
|
ModelResolutionPath,
|
|
22
|
+
PermissionGrant,
|
|
23
|
+
PermissionType,
|
|
19
24
|
Resolution,
|
|
20
25
|
ResolutionPath,
|
|
21
26
|
Run,
|
|
22
27
|
RunID,
|
|
23
28
|
SourceResolutionPath,
|
|
24
29
|
UploadStage,
|
|
30
|
+
User,
|
|
25
31
|
)
|
|
26
32
|
from matchbox.common.eval import Judgement, ModelComparison
|
|
27
33
|
from matchbox.common.logging import LogLevelType
|
|
@@ -32,6 +38,25 @@ else:
|
|
|
32
38
|
S3Client = Any
|
|
33
39
|
|
|
34
40
|
|
|
41
|
+
PERMISSION_GRANTS: dict[PermissionType, list[PermissionType]] = {
|
|
42
|
+
PermissionType.READ: [
|
|
43
|
+
PermissionType.READ,
|
|
44
|
+
PermissionType.WRITE,
|
|
45
|
+
PermissionType.ADMIN,
|
|
46
|
+
],
|
|
47
|
+
PermissionType.WRITE: [PermissionType.WRITE, PermissionType.ADMIN],
|
|
48
|
+
PermissionType.ADMIN: [PermissionType.ADMIN],
|
|
49
|
+
}
|
|
50
|
+
"""A global variable that defines the permission hierarchy.
|
|
51
|
+
|
|
52
|
+
Keys are the permission, values are a list of permissions that would
|
|
53
|
+
grant the permission.
|
|
54
|
+
|
|
55
|
+
For example, only `PermissionType.ADMIN` can grant `PermissionType.ADMIN`,
|
|
56
|
+
but any permission implies `PermissionType.READ`.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
|
|
35
60
|
class MatchboxBackends(StrEnum):
|
|
36
61
|
"""The available backends for Matchbox."""
|
|
37
62
|
|
|
@@ -584,12 +609,153 @@ class MatchboxDBAdapter(ABC):
|
|
|
584
609
|
Orphan clusters are clusters recorded in the Clusters table but that are
|
|
585
610
|
not referenced in other tables.
|
|
586
611
|
"""
|
|
612
|
+
...
|
|
613
|
+
|
|
614
|
+
# User, group and permissions management
|
|
615
|
+
|
|
616
|
+
@abstractmethod
|
|
617
|
+
def login(self, user: User) -> User:
|
|
618
|
+
"""Upserts the user to the database.
|
|
619
|
+
|
|
620
|
+
Args:
|
|
621
|
+
user: A User with a username and optionally an email
|
|
622
|
+
"""
|
|
623
|
+
...
|
|
624
|
+
|
|
625
|
+
@abstractmethod
|
|
626
|
+
def get_user_groups(self, user_name: str) -> list[GroupName]:
|
|
627
|
+
"""Get names of all groups a user belongs to.
|
|
628
|
+
|
|
629
|
+
Args:
|
|
630
|
+
user_name: The username to get the groups of
|
|
631
|
+
"""
|
|
632
|
+
...
|
|
633
|
+
|
|
634
|
+
@abstractmethod
|
|
635
|
+
def list_groups(self) -> list[Group]:
|
|
636
|
+
"""List all groups."""
|
|
637
|
+
...
|
|
638
|
+
|
|
639
|
+
@abstractmethod
|
|
640
|
+
def get_group(self, name: GroupName) -> Group:
|
|
641
|
+
"""Get group details including members.
|
|
642
|
+
|
|
643
|
+
Args:
|
|
644
|
+
name: The name of the group to fetch.
|
|
645
|
+
|
|
646
|
+
Raises:
|
|
647
|
+
MatchboxGroupNotFoundError: If group doesn't exist.
|
|
648
|
+
"""
|
|
649
|
+
...
|
|
650
|
+
|
|
651
|
+
@abstractmethod
|
|
652
|
+
def create_group(self, group: Group) -> None:
|
|
653
|
+
"""Create a new group.
|
|
654
|
+
|
|
655
|
+
Arg:
|
|
656
|
+
group: The group to create
|
|
657
|
+
|
|
658
|
+
Raises:
|
|
659
|
+
MatchboxGroupAlreadyExistsError: If group name taken.
|
|
660
|
+
"""
|
|
661
|
+
...
|
|
662
|
+
|
|
663
|
+
@abstractmethod
|
|
664
|
+
def delete_group(self, name: GroupName, certain: bool = False) -> None:
|
|
665
|
+
"""Delete a group.
|
|
666
|
+
|
|
667
|
+
Args:
|
|
668
|
+
name: The name of the group to delete
|
|
669
|
+
certain: Whether to delete the group without confirmation.
|
|
670
|
+
|
|
671
|
+
Raises:
|
|
672
|
+
MatchboxGroupNotFoundError: If group doesn't exist.
|
|
673
|
+
MatchboxSystemGroupError: If attempting to delete a system group.
|
|
674
|
+
MatchboxDeletionNotConfirmed: If certain=False.
|
|
675
|
+
"""
|
|
676
|
+
...
|
|
677
|
+
|
|
678
|
+
@abstractmethod
|
|
679
|
+
def add_user_to_group(self, user_name: str, group_name: GroupName) -> None:
|
|
680
|
+
"""Add a user to a group. Creates user if they don't exist.
|
|
681
|
+
|
|
682
|
+
Raises:
|
|
683
|
+
MatchboxGroupNotFoundError: If group doesn't exist.
|
|
684
|
+
"""
|
|
685
|
+
...
|
|
686
|
+
|
|
687
|
+
@abstractmethod
|
|
688
|
+
def remove_user_from_group(self, user_name: str, group_name: GroupName) -> None:
|
|
689
|
+
"""Remove a user from a group.
|
|
690
|
+
|
|
691
|
+
Raises:
|
|
692
|
+
MatchboxGroupNotFoundError: If group doesn't exist.
|
|
693
|
+
MatchboxUserNotFoundError: If user doesn't exist.
|
|
694
|
+
"""
|
|
695
|
+
...
|
|
696
|
+
|
|
697
|
+
@abstractmethod
|
|
698
|
+
def check_permission(
|
|
699
|
+
self,
|
|
700
|
+
user_name: str,
|
|
701
|
+
permission: PermissionType,
|
|
702
|
+
resource: Literal[BackendResourceType.SYSTEM] | CollectionName,
|
|
703
|
+
) -> bool:
|
|
704
|
+
"""Check user permission against a resource.
|
|
705
|
+
|
|
706
|
+
Args:
|
|
707
|
+
user_name: The username to check.
|
|
708
|
+
permission: The permission type to check
|
|
709
|
+
resource: The resource to check. One of "system" or a collection name
|
|
710
|
+
"""
|
|
711
|
+
...
|
|
712
|
+
|
|
713
|
+
@abstractmethod
|
|
714
|
+
def get_permissions(
|
|
715
|
+
self,
|
|
716
|
+
resource: Literal[BackendResourceType.SYSTEM] | CollectionName,
|
|
717
|
+
) -> list[PermissionGrant]:
|
|
718
|
+
"""Get all granted permissions against a resource.
|
|
719
|
+
|
|
720
|
+
Args:
|
|
721
|
+
resource: The resource to get permissions for. One of "system" or a
|
|
722
|
+
collection name
|
|
723
|
+
"""
|
|
724
|
+
...
|
|
587
725
|
|
|
588
|
-
|
|
726
|
+
@abstractmethod
|
|
727
|
+
def grant_permission(
|
|
728
|
+
self,
|
|
729
|
+
group_name: GroupName,
|
|
730
|
+
permission: PermissionType,
|
|
731
|
+
resource: Literal[BackendResourceType.SYSTEM] | CollectionName,
|
|
732
|
+
) -> None:
|
|
733
|
+
"""Grants a permission on a resource.
|
|
734
|
+
|
|
735
|
+
Args:
|
|
736
|
+
group_name: The name of the group to grant permission to
|
|
737
|
+
permission: The permission to grant
|
|
738
|
+
resource: The resource to grant permission on. One of "system" or a
|
|
739
|
+
collection name
|
|
740
|
+
"""
|
|
741
|
+
...
|
|
589
742
|
|
|
590
743
|
@abstractmethod
|
|
591
|
-
def
|
|
592
|
-
|
|
744
|
+
def revoke_permission(
|
|
745
|
+
self,
|
|
746
|
+
group_name: GroupName,
|
|
747
|
+
permission: PermissionType,
|
|
748
|
+
resource: Literal[BackendResourceType.SYSTEM] | CollectionName,
|
|
749
|
+
) -> None:
|
|
750
|
+
"""Revoke permission on a resource.
|
|
751
|
+
|
|
752
|
+
Args:
|
|
753
|
+
group_name: The name of the group to revoke permission of
|
|
754
|
+
permission: The permission to revoke
|
|
755
|
+
resource: The resource to revoke permission from. One of "system" or a
|
|
756
|
+
collection name
|
|
757
|
+
"""
|
|
758
|
+
...
|
|
593
759
|
|
|
594
760
|
# Evaluation management
|
|
595
761
|
|
|
@@ -625,13 +791,15 @@ class MatchboxDBAdapter(ABC):
|
|
|
625
791
|
...
|
|
626
792
|
|
|
627
793
|
@abstractmethod
|
|
628
|
-
def sample_for_eval(
|
|
794
|
+
def sample_for_eval(
|
|
795
|
+
self, n: int, path: ModelResolutionPath, user_name: str
|
|
796
|
+
) -> Table:
|
|
629
797
|
"""Sample a cluster to validate.
|
|
630
798
|
|
|
631
799
|
Args:
|
|
632
800
|
n: Number of clusters to sample
|
|
633
801
|
path: Path of resolution from which to sample
|
|
634
|
-
|
|
802
|
+
user_name: Name of user requesting the sample
|
|
635
803
|
|
|
636
804
|
Returns:
|
|
637
805
|
An Arrow table with the same schema as returned by `query()`
|