mirror of
https://github.com/Donkie/Spoolman.git
synced 2026-10-22 01:52:17 -05:00
A tag can now be linked to a filament type, not just to one spool of it. The
tag table already carried filament_id and target_type for exactly this, so
there is no migration.
API, all additive:
POST /filament/{id}/tag link; 409 if anything else holds the UID
DELETE /filament/{id}/tag/{uid} unlink
GET /filament?tag=<uid> exact lookup on the normalized UID
Filament.tags also inside every spool's embedded filament
TagScan.matched_filament_id always present, like matched_spool_id
TagConflictMessage.filament_id names a filament holder on a 409
One UID still identifies one thing across both kinds: a spool's tag cannot be
linked to a filament or the reverse, and neither ?tag= lookup answers with the
other kind. The scan debounce key now includes the kind, since spool 7 and
filament 7 are different answers.
SpoolTag and SpoolTagParameters are renamed Tag and TagLinkParameters while
they are unreleased, so the schema does not describe filament tags as spool
tags forever.
client_v2: the filament inspector gets the Tags section, the link dialog names
and moves a tag held by either kind, and scanning a filament's tag opens that
filament when auto-navigate is on.
Tag having two delete-orphan parents was checked on SQLAlchemy 2.0.51: new tags
flush, unlinking deletes the row, and deleting either parent cascades.
Proven on sqlite, postgres, mariadb and cockroachdb: 558 integration tests
each. Unit tests, svelte-check and the Playwright tag specs pass.
37 lines
1.1 KiB
Python
37 lines
1.1 KiB
Python
"""Various exceptions used."""
|
|
|
|
|
|
class ItemNotFoundError(Exception):
|
|
pass
|
|
|
|
|
|
class ItemDeleteError(Exception):
|
|
pass
|
|
|
|
|
|
class ItemCreateError(Exception):
|
|
pass
|
|
|
|
|
|
class SpoolMeasureError(Exception):
|
|
pass
|
|
|
|
|
|
class TagConflictError(Exception):
|
|
"""A tag UID is already linked to something else.
|
|
|
|
Carries the holder's ID rather than only a message, so the API can hand it to the
|
|
client and the client can offer "move the tag here instead" without a second lookup.
|
|
|
|
At most one of `spool_id` and `filament_id` is set, naming whichever holds the tag.
|
|
Both are None when the holder is not a row at all (see `database.models.Tag`); the
|
|
message says what in that case, and a client with nothing to offer beyond it simply
|
|
reports it.
|
|
"""
|
|
|
|
def __init__(self, message: str, spool_id: int | None = None, filament_id: int | None = None) -> None:
|
|
"""Initialize with the message and the ID of the spool or filament holding the tag."""
|
|
super().__init__(message)
|
|
self.spool_id = spool_id
|
|
self.filament_id = filament_id
|