Files
2026-07-13 13:22:34 +08:00

691 lines
28 KiB
Python

import time
from pathlib import Path
import pytest
from mlflow import MlflowClient
from mlflow.entities.model_registry import ModelVersion, RegisteredModel
from mlflow.exceptions import MlflowException
from mlflow.server import handlers
from mlflow.server.fastapi_app import app
from mlflow.server.handlers import initialize_backend_stores
from mlflow.utils.time import get_current_time_millis
from tests.helper_functions import get_safe_port
from tests.tracking.integration_test_utils import ServerThread
@pytest.fixture(params=["file", "sqlalchemy"])
def client(request: pytest.FixtureRequest, tmp_path: Path, db_uri: str):
"""Provides an MLflow Tracking API client pointed at the local tracking server."""
if request.param == "file":
pytest.skip("FileStore is no longer supported.")
backend_uri = tmp_path.joinpath("file").as_uri() if request.param == "file" else db_uri
# Force-reset backend stores before each test
handlers._tracking_store = None
handlers._model_registry_store = None
initialize_backend_stores(
backend_uri, default_artifact_root=tmp_path.joinpath("artifacts").as_uri()
)
with ServerThread(app, get_safe_port()) as url:
yield MlflowClient(url)
def assert_is_between(start_time, end_time, expected_time):
assert expected_time >= start_time
assert expected_time <= end_time
def test_create_and_query_registered_model_flow(client):
name = "CreateRMTest"
tags = {"key": "value", "another key": "some other value", "numeric value": 12345}
start_time = get_current_time_millis()
registered_model = client.create_registered_model(name, tags)
end_time = get_current_time_millis()
assert isinstance(registered_model, RegisteredModel)
assert registered_model.name == name
assert registered_model.tags == {
"key": "value",
"another key": "some other value",
"numeric value": "12345",
}
registered_model_detailed = client.get_registered_model(name)
assert isinstance(registered_model_detailed, RegisteredModel)
assert registered_model_detailed.name == name
assert registered_model_detailed.tags == {
"key": "value",
"another key": "some other value",
"numeric value": "12345",
}
assert str(registered_model_detailed.description) == ""
assert registered_model_detailed.latest_versions == []
assert_is_between(start_time, end_time, registered_model_detailed.creation_timestamp)
assert_is_between(start_time, end_time, registered_model_detailed.last_updated_timestamp)
assert [rm.name for rm in client.search_registered_models() if rm.name == name] == [name]
assert [rm.name for rm in client.search_registered_models() if rm.name == name] == [name]
assert [
rm.name for rm in client.search_registered_models(filter_string="") if rm.name == name
] == [name]
assert [
rm.name
for rm in client.search_registered_models("name = 'CreateRMTest'")
if rm.name == name
] == [name]
def _verify_pagination(rm_getter_with_token, expected_rms):
result_rms = []
result = rm_getter_with_token(None)
result_rms.extend(result)
first_page_size = len(result)
while result.token:
result = rm_getter_with_token(result.token)
result_rms.extend(result)
assert len(result) == first_page_size or result.token == ""
assert [rm.name for rm in expected_rms] == [rm.name for rm in result_rms]
@pytest.mark.parametrize("max_results", [1, 8, 100])
@pytest.mark.parametrize(
("filter_string", "filter_func"),
[
(None, lambda rm: True),
("", lambda rm: True),
("name LIKE '%7'", lambda rm: rm.name.endswith("7")),
("name ILIKE '%rm%00%'", lambda rm: "00" in rm.name),
("name LIKE '%rm%00%'", lambda rm: False),
("name = 'badname'", lambda rm: False),
("name = 'CreateRMsearch023'", lambda rm: rm.name == "CreateRMsearch023"),
],
)
def test_search_registered_model_flow_paginated(client, max_results, filter_string, filter_func):
names = [f"CreateRMsearch{i:03}" for i in range(29)]
rms = [client.create_registered_model(name) for name in names]
for rm in rms:
assert isinstance(rm, RegisteredModel)
def verify_pagination(rm_getter_with_token, expected_rms):
result_rms = []
result = rm_getter_with_token(None)
result_rms.extend(result)
while result.token:
result = rm_getter_with_token(result.token)
result_rms.extend(result)
assert [rm.name for rm in expected_rms] == [rm.name for rm in result_rms]
verify_pagination(
lambda tok: client.search_registered_models(
filter_string=filter_string, max_results=max_results, page_token=tok
),
filter(filter_func, rms),
)
def test_update_registered_model_flow(client):
name = "UpdateRMTest"
start_time_1 = get_current_time_millis()
client.create_registered_model(name)
end_time_1 = get_current_time_millis()
registered_model_detailed_1 = client.get_registered_model(name)
assert registered_model_detailed_1.name == name
assert str(registered_model_detailed_1.description) == ""
assert_is_between(start_time_1, end_time_1, registered_model_detailed_1.creation_timestamp)
assert_is_between(start_time_1, end_time_1, registered_model_detailed_1.last_updated_timestamp)
# update name
new_name = "UpdateRMTest 2"
start_time_2 = get_current_time_millis()
client.rename_registered_model(name=name, new_name=new_name)
end_time_2 = get_current_time_millis()
with pytest.raises(MlflowException, match="Registered Model with name=UpdateRMTest not found"):
client.get_registered_model(name)
registered_model_detailed_2 = client.get_registered_model(new_name)
assert registered_model_detailed_2.name == new_name
assert str(registered_model_detailed_2.description) == ""
assert_is_between(start_time_1, end_time_1, registered_model_detailed_2.creation_timestamp)
assert_is_between(start_time_2, end_time_2, registered_model_detailed_2.last_updated_timestamp)
# update description
start_time_3 = get_current_time_millis()
client.update_registered_model(name=new_name, description="This is a test")
end_time_3 = get_current_time_millis()
registered_model_detailed_3 = client.get_registered_model(new_name)
assert registered_model_detailed_3.name == new_name
assert registered_model_detailed_3.description == "This is a test"
assert_is_between(start_time_1, end_time_1, registered_model_detailed_3.creation_timestamp)
assert_is_between(start_time_3, end_time_3, registered_model_detailed_3.last_updated_timestamp)
# update name and description
another_new = "UpdateRMTest 4"
start_time_4 = get_current_time_millis()
client.update_registered_model(new_name, "4th update")
client.rename_registered_model(new_name, another_new)
end_time_4 = get_current_time_millis()
registered_model_detailed_4 = client.get_registered_model(another_new)
assert registered_model_detailed_4.name == another_new
assert registered_model_detailed_4.description == "4th update"
assert_is_between(start_time_1, end_time_1, registered_model_detailed_4.creation_timestamp)
assert_is_between(start_time_4, end_time_4, registered_model_detailed_4.last_updated_timestamp)
# using rename
previous_name = another_new
another_new = "UpdateRMTest 5"
start_time_5 = get_current_time_millis()
client.rename_registered_model(previous_name, another_new)
end_time_5 = get_current_time_millis()
registered_model_detailed_5 = client.get_registered_model(another_new)
assert registered_model_detailed_5.name == another_new
assert registered_model_detailed_5.description == "4th update"
assert_is_between(start_time_1, end_time_1, registered_model_detailed_5.creation_timestamp)
assert_is_between(start_time_5, end_time_5, registered_model_detailed_5.last_updated_timestamp)
# old named models are not accessible
for old_name in [previous_name, name, new_name]:
with pytest.raises(
MlflowException, match=r"Registered Model with name=UpdateRMTest( \d)? not found"
):
client.get_registered_model(old_name)
def test_delete_registered_model_flow(client):
name = "DeleteRMTest"
start_time_1 = get_current_time_millis()
client.create_registered_model(name)
end_time_1 = get_current_time_millis()
registered_model_detailed_1 = client.get_registered_model(name)
assert registered_model_detailed_1.name == name
assert_is_between(start_time_1, end_time_1, registered_model_detailed_1.creation_timestamp)
assert_is_between(start_time_1, end_time_1, registered_model_detailed_1.last_updated_timestamp)
assert [rm.name for rm in client.search_registered_models() if rm.name == name] == [name]
# cannot create a model with same name
with pytest.raises(MlflowException, match=r"Registered Model .+ already exists"):
client.create_registered_model(name)
client.delete_registered_model(name)
# cannot get a deleted model
with pytest.raises(MlflowException, match=r"Registered Model .+ not found"):
client.get_registered_model(name)
# cannot update a deleted model
with pytest.raises(MlflowException, match=r"Registered Model .+ not found"):
client.rename_registered_model(name=name, new_name="something else")
# list does not include deleted model
assert [rm.name for rm in client.search_registered_models() if rm.name == name] == []
# recreate model with same name
start_time_2 = get_current_time_millis()
client.create_registered_model(name)
end_time_2 = get_current_time_millis()
registered_model_detailed_2 = client.get_registered_model(name)
assert registered_model_detailed_2.name == name
assert_is_between(start_time_2, end_time_2, registered_model_detailed_2.creation_timestamp)
assert_is_between(start_time_2, end_time_2, registered_model_detailed_2.last_updated_timestamp)
assert [rm.name for rm in client.search_registered_models() if rm.name == name] == [name]
def test_set_delete_registered_model_tag_flow(client):
name = "SetDeleteRMTagTest"
client.create_registered_model(name)
registered_model_detailed = client.get_registered_model(name)
assert registered_model_detailed.tags == {}
tags = {"key": "value", "numeric value": 12345}
for key, value in tags.items():
client.set_registered_model_tag(name, key, value)
registered_model_detailed = client.get_registered_model(name)
assert registered_model_detailed.tags == {"key": "value", "numeric value": "12345"}
client.delete_registered_model_tag(name, "key")
registered_model_detailed = client.get_registered_model(name)
assert registered_model_detailed.tags == {"numeric value": "12345"}
def test_set_registered_model_tag_with_empty_string_as_value(client):
name = "SetRMTagEmptyValueTest"
client.create_registered_model(name)
client.set_registered_model_tag(name, "tag_key", "")
assert {"tag_key": ""}.items() <= client.get_registered_model(name).tags.items()
@pytest.mark.parametrize(
("filter_string", "filter_func"),
[
(None, lambda mv: True),
("", lambda mv: True),
("name LIKE '%2'", lambda mv: mv.name.endswith("2")),
("name ILIKE '%rm%00%'", lambda mv: "00" in mv.name),
("name LIKE '%rm%00%'", lambda mv: False),
("name = 'badname'", lambda mv: False),
("name = 'CreateRMsearchForMV03'", lambda mv: mv.name == "CreateRMsearchForMV03"),
],
)
def test_search_model_versions_filter_string(
client,
filter_string,
filter_func,
):
names = [f"CreateRMsearchForMV{i:03}" for i in range(29)]
for name in names:
client.create_registered_model(name)
mvs = []
for name in names + names[:10]:
# Sleep for unique creation_time to make search results deterministic
time.sleep(0.001)
mvs.append(client.create_model_version(name, "runs:/run_id/model", "run_id"))
for mv in mvs:
assert isinstance(mv, ModelVersion)
mvs = mvs[::-1]
def verify_pagination(mv_getter_with_token, expected_mvs):
result_mvs = []
result = mv_getter_with_token(None)
result_mvs.extend(result)
while result.token:
result = mv_getter_with_token(result.token)
result_mvs.extend(result)
assert [mv.name for mv in expected_mvs] == [mv.name for mv in result_mvs]
assert [mv.version for mv in expected_mvs] == [mv.version for mv in result_mvs]
expected_mvs = sorted(
filter(filter_func, mvs), key=lambda x: x.last_updated_timestamp, reverse=True
)
verify_pagination(
lambda tok: client.search_model_versions(
filter_string=filter_string,
page_token=tok,
),
expected_mvs,
)
@pytest.mark.parametrize("max_results", [1, 8, 100])
def test_search_model_versions_max_results(client, max_results):
names = [f"CreateRMsearchForMV{i:03}" for i in range(29)]
for name in names:
client.create_registered_model(name)
mvs = []
for name in names + names[:10]:
# Sleep for unique creation_time to make search results deterministic
time.sleep(0.001)
mvs.append(client.create_model_version(name, "runs:/run_id/model", "run_id"))
for mv in mvs:
assert isinstance(mv, ModelVersion)
mvs = mvs[::-1]
def verify_pagination(mv_getter_with_token, expected_mvs):
result_mvs = []
result = mv_getter_with_token(None)
result_mvs.extend(result)
while result.token:
result = mv_getter_with_token(result.token)
result_mvs.extend(result)
assert [mv.name for mv in expected_mvs] == [mv.name for mv in result_mvs]
assert [mv.version for mv in expected_mvs] == [mv.version for mv in result_mvs]
expected_mvs = sorted(mvs, key=lambda x: x.last_updated_timestamp, reverse=True)
verify_pagination(
lambda tok: client.search_model_versions(
max_results=max_results,
page_token=tok,
),
expected_mvs,
)
@pytest.mark.parametrize(
("order_by", "order_by_key", "order_by_desc"),
[
(None, None, False),
(["name DESC"], lambda mv: (mv.name, mv.version), True),
(
["version_number DESC"],
lambda mv: (-int(mv.version), mv.name),
False,
),
],
)
def test_search_model_versions_order_by(
client,
order_by,
order_by_key,
order_by_desc,
):
names = [f"CreateRMsearchForMV{i:03}" for i in range(29)]
for name in names:
client.create_registered_model(name)
mvs = []
for name in names + names[:10]:
# Sleep for unique creation_time to make search results deterministic
time.sleep(0.001)
mvs.append(client.create_model_version(name, "runs:/run_id/model", "run_id"))
for mv in mvs:
assert isinstance(mv, ModelVersion)
mvs = mvs[::-1]
def verify_pagination(mv_getter_with_token, expected_mvs):
result_mvs = []
result = mv_getter_with_token(None)
result_mvs.extend(result)
while result.token:
result = mv_getter_with_token(result.token)
result_mvs.extend(result)
assert [mv.name for mv in expected_mvs] == [mv.name for mv in result_mvs]
assert [mv.version for mv in expected_mvs] == [mv.version for mv in result_mvs]
if order_by_key:
expected_mvs = sorted(mvs, key=order_by_key, reverse=order_by_desc)
else:
expected_mvs = sorted(
mvs, key=lambda x: (-int(x.last_updated_timestamp), x.name, -int(x.version))
)
verify_pagination(
lambda tok: client.search_model_versions(
order_by=order_by,
page_token=tok,
),
expected_mvs,
)
def test_create_and_query_model_version_flow(client):
name = "CreateMVTest"
tags = {"key": "value", "another key": "some other value", "numeric value": 12345}
client.create_registered_model(name)
mv1 = client.create_model_version(name, "runs:/run_id/model", "run_id_1", tags)
assert mv1.version == "1"
assert mv1.name == name
assert mv1.tags == {"key": "value", "another key": "some other value", "numeric value": "12345"}
mvd1 = client.get_model_version(name, "1")
assert mvd1.tags == {
"key": "value",
"another key": "some other value",
"numeric value": "12345",
}
assert [rm.latest_versions for rm in client.search_registered_models() if rm.name == name] == [
[mvd1]
]
mv2 = client.create_model_version(name, "runs:/run_id/another_model", "run_id_1")
assert mv2.version == "2"
assert mv2.name == name
mvd2 = client.get_model_version(name, "2")
assert [rm.latest_versions for rm in client.search_registered_models() if rm.name == name] == [
[mvd2]
]
model_versions_by_name = client.search_model_versions(f"name = '{name}'")
assert {mv.version for mv in model_versions_by_name} == {"1", "2"}
assert {mv.name for mv in model_versions_by_name} == {name}
mv3 = client.create_model_version(name, "runs:/run_id/another_model", "run_id_2")
assert mv3.version == "3"
assert client.search_model_versions("source_path = 'runs:/run_id/model'") == [mvd1]
assert client.search_model_versions("run_id = 'run_id_1'") == [mvd2, mvd1]
assert client.get_model_version_download_uri(name, "1") == "runs:/run_id/model"
def test_get_model_version(client):
name = "GetModelVersionTest"
client.create_registered_model(name)
client.create_model_version(name, "runs:/run_id/model", "run_id_1")
model_version = client.get_model_version(name, "1")
assert model_version.name == name
assert model_version.version == "1"
error_message = "Parameter 'version' must be an integer, got 'something not correct'."
with pytest.raises(
MlflowException,
match=f"INVALID_PARAMETER_VALUE: {error_message}",
):
client.get_model_version(name=name, version="something not correct")
def test_update_model_version_flow(client):
name = "UpdateMVTest"
start_time_0 = get_current_time_millis()
client.create_registered_model(name)
end_time_0 = get_current_time_millis()
rmd1 = client.get_registered_model(name)
assert_is_between(start_time_0, end_time_0, rmd1.creation_timestamp)
assert_is_between(start_time_0, end_time_0, rmd1.last_updated_timestamp)
start_time_1 = get_current_time_millis()
mv1 = client.create_model_version(name, "runs:/run_id/model", "run_id_1")
end_time_1 = get_current_time_millis()
assert mv1.version == "1"
assert mv1.name == name
mvd1 = client.get_model_version(name, "1")
assert str(mvd1.description) == ""
assert_is_between(start_time_1, end_time_1, mvd1.creation_timestamp)
assert_is_between(start_time_1, end_time_1, mvd1.last_updated_timestamp)
# creating model version changes last_updated_timestamp for registered model
rmd2 = client.get_registered_model(name)
assert_is_between(start_time_0, end_time_0, rmd2.creation_timestamp)
assert_is_between(start_time_1, end_time_1, rmd2.last_updated_timestamp)
assert [rm.latest_versions for rm in client.search_registered_models() if rm.name == name] == [
[mvd1]
]
mv2 = client.create_model_version(name, "runs:/run_id/another_model", "run_id_1")
assert mv2.version == "2"
assert mv2.name == name
mvd2 = client.get_model_version(name, "2")
assert [rm.latest_versions for rm in client.search_registered_models() if rm.name == name] == [
[mvd2]
]
start_time_2 = get_current_time_millis()
client.transition_model_version_stage(name=name, version=1, stage="Staging")
end_time_2 = get_current_time_millis()
mvd1b = client.get_model_version(name, 1)
assert_is_between(start_time_1, end_time_1, mvd1b.creation_timestamp)
assert_is_between(start_time_2, end_time_2, mvd1b.last_updated_timestamp)
# updating model version's stage changes last_updated_timestamp for registered model
rmd3 = client.get_registered_model(name)
assert_is_between(start_time_0, end_time_0, rmd3.creation_timestamp)
assert_is_between(start_time_2, end_time_2, rmd3.last_updated_timestamp)
model_versions_detailed = [
rm.latest_versions for rm in client.search_registered_models() if rm.name == name
]
assert len(model_versions_detailed) == 1
assert {mvd.version for mvd in model_versions_detailed[0]} == {"1", "2"}
assert {mvd.name for mvd in model_versions_detailed[0]} == {name}
# update description
start_time_3 = get_current_time_millis()
client.update_model_version(name=name, version=1, description="This is a test model")
end_time_3 = get_current_time_millis()
mvd1c = client.get_model_version(name, "1")
assert str(mvd1c.description) == "This is a test model"
assert_is_between(start_time_1, end_time_1, mvd1c.creation_timestamp)
assert_is_between(start_time_3, end_time_3, mvd1c.last_updated_timestamp)
# changing description for model version does not affect last_updated_timestamp for registered
# model
rmd4 = client.get_registered_model(name)
assert_is_between(start_time_0, end_time_0, rmd4.creation_timestamp)
assert_is_between(start_time_2, end_time_2, rmd4.last_updated_timestamp)
def test_latest_models(client):
version_stage_mapping = (
("1", "Archived"),
("2", "Production"),
("3", "Archived"),
("4", "Production"),
("5", "Staging"),
("6", "Staging"),
("7", "None"),
)
name = "LatestVersionTest"
client.create_registered_model(name)
for version, stage in version_stage_mapping:
# Sleep for unique creation_time to make search results deterministic
time.sleep(0.001)
mv = client.create_model_version(name, "runs:/run_id/model", "run_id")
assert mv.version == version
if stage != "None":
client.transition_model_version_stage(name, version, stage=stage)
mvd = client.get_model_version(name, version)
assert mvd.current_stage == stage
def get_latest(stages):
latest = client.get_latest_versions(name, stages)
return {mvd.current_stage: mvd.version for mvd in latest}
assert get_latest(["None"]) == {"None": "7"}
assert get_latest(["Staging"]) == {"Staging": "6"}
assert get_latest(["None", "Staging"]) == {"None": "7", "Staging": "6"}
assert get_latest(None) == {"Production": "4", "Staging": "6", "Archived": "3", "None": "7"}
assert get_latest([]) == {"Production": "4", "Staging": "6", "Archived": "3", "None": "7"}
def test_delete_model_version_flow(client):
name = "DeleteMVTest"
start_time_0 = get_current_time_millis()
client.create_registered_model(name)
end_time_0 = get_current_time_millis()
rmd1 = client.get_registered_model(name)
assert_is_between(start_time_0, end_time_0, rmd1.creation_timestamp)
assert_is_between(start_time_0, end_time_0, rmd1.last_updated_timestamp)
start_time_1 = get_current_time_millis()
mv1 = client.create_model_version(name, "runs:/run_id/model", "run_id_1")
end_time_1 = get_current_time_millis()
assert mv1.version == "1"
assert mv1.name == name
mvd1 = client.get_model_version(name, 1)
assert_is_between(start_time_1, end_time_1, mvd1.creation_timestamp)
assert_is_between(start_time_1, end_time_1, mvd1.last_updated_timestamp)
# creating model version changes last_updated_timestamp for registered model
rmd2 = client.get_registered_model(name)
assert_is_between(start_time_0, end_time_0, rmd2.creation_timestamp)
assert_is_between(start_time_1, end_time_1, rmd2.last_updated_timestamp)
mv2 = client.create_model_version(name, "runs:/run_id/another_model", "run_id_1")
assert mv2.version == "2"
assert mv2.name == name
mv3 = client.create_model_version(name, "runs:/run_id_2/a/b/c", "run_id_2")
assert mv3.version == "3"
assert mv3.name == name
model_versions_detailed = [
rm.latest_versions for rm in client.search_registered_models() if rm.name == name
]
assert len(model_versions_detailed) == 1
assert model_versions_detailed[0][0].version == "3"
assert {mv.version for mv in client.search_model_versions(f"name = '{name}'")} == {
"1",
"2",
"3",
}
start_time_2 = get_current_time_millis()
client.delete_model_version(name, "1")
end_time_2 = get_current_time_millis()
assert {mv.version for mv in client.search_model_versions(f"name = '{name}'")} == {
"2",
"3",
}
rmd3 = client.get_registered_model(name)
# deleting model versions changes last_updated_timestamp for registered model
assert_is_between(start_time_0, end_time_0, rmd3.creation_timestamp)
assert_is_between(start_time_2, end_time_2, rmd3.last_updated_timestamp)
# cannot get a deleted model version
with pytest.raises(MlflowException, match=r"Model Version .+ not found"):
client.delete_model_version(name, "1")
# cannot update a deleted model version
with pytest.raises(MlflowException, match=r"Model Version .+ not found"):
client.update_model_version(name=name, version=1, description="Test model")
with pytest.raises(MlflowException, match=r"Model Version .+ not found"):
client.transition_model_version_stage(name=name, version=1, stage="Staging")
client.delete_model_version(name, 3)
assert {mv.version for mv in client.search_model_versions(f"name = '{name}'")} == {"2"}
# new model versions will not reuse existing version numbers
mv4 = client.create_model_version(name, "runs:/run_id_2/a/b/c", "run_id_2")
assert mv4.version == "4"
assert mv4.name == name
assert {mv.version for mv in client.search_model_versions(f"name = '{name}'")} == {
"2",
"4",
}
def test_set_delete_model_version_tag_flow(client):
name = "SetDeleteMVTagTest"
client.create_registered_model(name)
client.create_model_version(name, "runs:/run_id/model", "run_id_1")
model_version_detailed = client.get_model_version(name, "1")
assert model_version_detailed.tags == {}
tags = {"key": "value", "numeric value": 12345}
for key, value in tags.items():
client.set_model_version_tag(name, "1", key, value)
model_version_detailed = client.get_model_version(name, "1")
assert model_version_detailed.tags == {"key": "value", "numeric value": "12345"}
client.delete_model_version_tag(name, "1", "key")
model_version_detailed = client.get_model_version(name, "1")
assert model_version_detailed.tags == {"numeric value": "12345"}
def test_set_model_version_tag_with_empty_string_as_value(client):
name = "SetMVTagEmptyValueTest"
client.create_registered_model(name)
client.create_model_version(name, "runs:/run_id/model", "run_id_1")
client.set_model_version_tag(name, "1", "tag_key", "")
assert {"tag_key": ""}.items() <= client.get_model_version(name, "1").tags.items()
def test_set_delete_registered_model_alias_and_get_model_version_by_alias_flow(client):
name = "SetDeleteGetRMAliasTest"
client.create_registered_model(name)
client.create_model_version(name, "runs:/run_id/model", "run_id_1")
model = client.get_registered_model(name)
assert model.aliases == {}
mv = client.get_model_version(name, "1")
assert mv.aliases == []
client.set_registered_model_alias(name, "test_alias", "1")
model = client.get_registered_model(name)
assert model.aliases == {"test_alias": "1"}
mv = client.get_model_version(name, "1")
assert mv.aliases == ["test_alias"]
mv_alias = client.get_model_version_by_alias(name, "test_alias")
assert mv == mv_alias
client.delete_registered_model_alias(name, "test_alias")
model = client.get_registered_model(name)
assert model.aliases == {}
mv = client.get_model_version(name, "1")
assert mv.aliases == []
def test_copy_model_version_flow(client):
name = "CopyMVTest"
client.create_registered_model(name)
src_mv = client.create_model_version(
name, "runs:/run_id/model", "run_id_1", description="dummy", tags={"hello": "world"}
)
client.set_registered_model_alias(name, "test_alias", "1")
copy_mv = client.copy_model_version(f"models:/{name}@test_alias", name)
assert copy_mv.version == "2"
assert copy_mv.name == name
copy_mv = client.get_model_version(name, 2)
assert copy_mv.source == f"models:/{name}/1"
assert copy_mv.description == "dummy"
assert copy_mv.run_id == "run_id_1"
assert copy_mv.tags == {"hello": "world"}
copy_download_uri = client.get_model_version_download_uri(name, 2)
assert copy_download_uri == src_mv.source