Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions src/database/setups.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
from typing import TYPE_CHECKING

from sqlalchemy import text
from sqlalchemy.exc import IntegrityError

from database.exceptions import (
_DUPLICATE_ENTRY,
_FOREIGN_KEY_CONSTRAINT_FAILED,
DuplicatePrimaryKeyError,
ForeignKeyConstraintError,
)
from routers.types import Identifier, TagString

if TYPE_CHECKING:
Expand Down Expand Up @@ -88,12 +95,20 @@ async def tag(
connection: AsyncConnection,
) -> None:
"""Add tag `tag` to setup with id `setup_id`."""
await connection.execute(
text(
"""
INSERT INTO setup_tag (id, tag, uploader)
VALUES (:setup_id, :tag, :user_id)
""",
),
parameters={"setup_id": setup_id, "tag": tag, "user_id": user_id},
)
try:
await connection.execute(
text(
"""
INSERT INTO setup_tag (id, tag, uploader)
VALUES (:setup_id, :tag, :user_id)
""",
),
parameters={"setup_id": setup_id, "tag": tag, "user_id": user_id},
)
except IntegrityError as e:
code, msg = e.orig.args
if code == _FOREIGN_KEY_CONSTRAINT_FAILED:
raise ForeignKeyConstraintError(msg) from e
if code == _DUPLICATE_ENTRY:
raise DuplicatePrimaryKeyError(msg) from e
raise
24 changes: 11 additions & 13 deletions src/routers/openml/setups.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
TagNotFoundError,
TagNotOwnedError,
)
from database.exceptions import DuplicatePrimaryKeyError, ForeignKeyConstraintError
from database.users import User
from routers.dependencies import expdb_connection, fetch_user_or_raise
from routers.types import Identifier, TagString
Expand Down Expand Up @@ -54,22 +55,19 @@ async def tag_setup(
expdb_db: Annotated[AsyncConnection, Depends(expdb_connection)],
) -> dict[str, dict[str, str | list[str]]]:
"""Add tag `tag` to setup with id `setup_id`."""
setup, setup_tags = await asyncio.gather(
database.setups.get(setup_id, expdb_db),
database.setups.get_tags(setup_id, expdb_db),
)
if not setup:
try:
await database.setups.tag(setup_id, tag, user.user_id, expdb_db)
except ForeignKeyConstraintError:
msg = f"Setup {setup_id} not found."
raise SetupNotFoundError(msg)
matched_tag_row = next((t for t in setup_tags if t.tag.casefold() == tag.casefold()), None)
raise SetupNotFoundError(msg, code=472) from None
except DuplicatePrimaryKeyError:
msg = f"Setup {setup_id} already tagged with {tag!r}."
raise TagAlreadyExistsError(msg) from None

if matched_tag_row:
msg = f"Setup {setup_id} already has tag {tag!r}."
raise TagAlreadyExistsError(msg)

await database.setups.tag(setup_id, tag, user.user_id, expdb_db)
logger.info("Setup {setup_id} tagged '{tag}'.", setup_id=setup_id, tag=tag)
all_tags = [t.tag for t in setup_tags] + [tag]
all_tag_rows = await database.setups.get_tags(setup_id, expdb_db)
all_tags = [t.tag for t in all_tag_rows]

return {"setup_tag": {"id": str(setup_id), "tag": all_tags}}


Expand Down
4 changes: 2 additions & 2 deletions tests/routers/openml/setups_tag_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async def test_setup_tag_already_exists(expdb_test: AsyncConnection) -> None:
text("INSERT INTO setup_tag (id, tag, uploader) VALUES (1, :tag, 2);"),
parameters={"tag": tag},
)
with pytest.raises(TagAlreadyExistsError, match=rf"Setup 1 already has tag '{tag}'\."):
with pytest.raises(TagAlreadyExistsError, match=rf"Setup 1 already tagged with '{tag}'\."):
await tag_setup(
setup_id=1,
tag=tag,
Expand Down Expand Up @@ -203,4 +203,4 @@ async def test_setup_tag_response_is_identical_tag_already_exists(
assert php_response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
assert py_response.status_code == HTTPStatus.CONFLICT
assert php_response.json()["error"]["message"] == "Entity already tagged by this tag."
assert py_response.json()["detail"] == f"Setup {setup_id} already has tag {tag!r}."
assert py_response.json()["detail"] == f"Setup {setup_id} already tagged with {tag!r}."
Loading