Skip to content

MMIF annotation getter doesn't work on short ids #279

Closed

Description

@haydenmccormick

Bug Description

When using the native MMIF annotation getter mmif[anno.id], the SDK throws a KeyError. When using view-scoped long ids (mmif[anno.long_id]), it works as expected.

Reproduction steps

Using a MMIF file (version 1.0.4), try to access a given annotation via mmif[id], where id is a short annotation ID.

Expected behavior

>>> for anno in mmif["v_0"].annotations:
...     anno = mmif[anno.id]

Should successfully access a MMIF Annotation object in each iteration

Log output

>>> with open("spacy1.mmif", "r") as f:
...     mmif = Mmif(f.read())
... 
>>> for anno in mmif["v_0"].annotations:
...     anno = mmif[anno.id]
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/home/hmccormick/.local/lib/python3.9/site-packages/mmif/serialize/mmif.py", line 590, in __getitem__
    raise KeyError("ID not found: %s" % item)
KeyError: 'ID not found: to_1'

>>> for anno in mmif["v_0"].annotations:
...     anno = mmif[anno.long_id]

>>> # Works without error on long IDs

Screenshots

No response

Additional context

No response

Activity

  1. keighrim commented on Jun 6, 2024

    @keighrim
    Member

    Not sure this is actually a bug. Although the documentation isn't super clear,

    def __getitem__(self, item: str) -> Union[Document, View, Annotation]:
    """
    getitem implementation for Mmif. When nothing is found, this will raise an error
    rather than returning a None (although pytype doesn't think so...)
    :raises KeyError: if the item is not found or if the search results are ambiguous
    :param item: the search string, a document ID, a view ID, or a view-scoped annotation ID
    :return: the object searched for
    """
    if item in self._named_attributes():
    return self.__dict__[item]
    split_attempt = item.split(self.id_delimiter)
    document_result = self.documents.get(split_attempt[0])
    view_result = self.views.get(split_attempt[0])
    if len(split_attempt) == 1:
    anno_result = None
    elif view_result:
    anno_result = view_result[split_attempt[1]]
    else:
    raise KeyError("Tried to subscript into a view that doesn't exist")
    if view_result and document_result:
    raise KeyError("Ambiguous ID search result")
    if not (view_result or document_result):
    raise KeyError("ID not found: %s" % item)

    considering

    1. it says it expects a view-scoped annotation ID (short ID)
    2. it raises error when two objects with the same ID (when a document and a view have the same id, line 588)
    3. annotation IDs are only scoped within a view, so it's much more likely to have ID conflict by querying annotation ID only.

    I think an error when querying with a short ID is somewhat expected behavior. Easy workaround this limitation in the downstream is probably just using anno.long_id instead of anno.id.

    def long_id(self) -> str:
    if self.parent is not None and len(self.parent) > 0:
    return f"{self.parent}{self.id_delimiter}{self.id}"
    else:
    return self.id

  2. moved this from Todo to Done in infraon Jun 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐛BSomething isn't working

    Type

    No type

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions