Skip to content

Commit 7dc0f09

Browse files
authored
Merge pull request #288 from clamsproject/develop
releasing 1.0.17
2 parents ed7a1f9 + 79f43e1 commit 7dc0f09

File tree

9 files changed

+218
-141
lines changed

9 files changed

+218
-141
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,4 @@ mmif/vocabulary
8181
# sphinx/autodoc files
8282
documentation/_build/
8383

84+
/VERSION

documentation/target-versions.csv

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
1.0.13,"1.0.4"
66
1.0.12,"1.0.4"
77
1.0.11,"1.0.4"
8-
1.0.10.dev1,"1.0.3"
98
1.0.10,"1.0.2"
109
1.0.9,"1.1.0"
1110
1.0.8,"1.0.0"

mmif/serialize/annotation.py

+46-7
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import re
1515
import typing
1616
import warnings
17-
from typing import Union, Dict, List, Optional, Iterator, MutableMapping, TypeVar
17+
from typing import Union, Dict, Optional, Iterator, MutableMapping, TypeVar
1818
from urllib.parse import urlparse
1919

2020
from mmif.vocabulary import ThingTypesBase, DocumentTypesBase
@@ -46,19 +46,23 @@ class Annotation(MmifObject):
4646
MmifObject that represents an annotation in a MMIF view.
4747
"""
4848

49-
def __init__(self, anno_obj: Optional[Union[bytes, str, dict]] = None) -> None:
49+
def __init__(self, anno_obj: Optional[Union[bytes, str, dict]] = None, *_) -> None:
5050
self._type: ThingTypesBase = ThingTypesBase('')
5151
# to store the parent view ID
5252
self._parent_view_id = ''
5353
self._props_ephemeral: AnnotationProperties = AnnotationProperties()
54-
self.reserved_names.update(('_parent_view_id', '_props_ephemeral'))
54+
self._alignments = {} # to hold alignment information (Alignment anno long_id -> aligned anno long_id)
55+
self.reserved_names.update(('_parent_view_id', '_props_ephemeral', '_alignments'))
5556
if not hasattr(self, 'properties'): # don't overwrite DocumentProperties on super() call
5657
self.properties: AnnotationProperties = AnnotationProperties()
5758
self._attribute_classes = {'properties': AnnotationProperties}
5859
self.disallow_additional_properties()
5960
self._required_attributes = ["_type", "properties"]
6061
super().__init__(anno_obj)
6162

63+
def __hash__(self):
64+
return hash(self.serialize())
65+
6266
def _deserialize(self, input_dict: dict) -> None:
6367
self.at_type = input_dict.pop('_type', '')
6468
# TODO (krim @ 6/1/21): If annotation IDs must follow a certain string format,
@@ -69,6 +73,40 @@ def _deserialize(self, input_dict: dict) -> None:
6973
for k, v in self.properties.items():
7074
self._add_prop_aliases(k, v)
7175

76+
def _cache_alignment(self, alignment_ann: 'Annotation', alignedto_ann: 'Annotation') -> None:
77+
"""
78+
Cache alignment information. This cache will not be serialized.
79+
80+
:param alignment_ann: the Alignment annotation that has this annotation on one side
81+
:param alignedto_ann: the annotation that this annotation is aligned to (other side of Alignment)
82+
"""
83+
self._alignments[alignment_ann] = alignedto_ann
84+
85+
def aligned_to_by(self, alignment: 'Annotation') -> Optional['Annotation']:
86+
"""
87+
Retrieves the other side of ``Alignment`` annotation that has this annotation on one side.
88+
89+
:param alignment: ``Alignment`` annotation that has this annotation on one side
90+
:return: the annotation that this annotation is aligned to (other side of ``Alignment``),
91+
or None if this annotation is not used in the ``Alignment``.
92+
"""
93+
return self._alignments.get(alignment)
94+
95+
def get_all_aligned(self) -> Iterator['Annotation']:
96+
"""
97+
Generator to iterate through all alignments and aligned annotations. Note that this generator will yield
98+
the `Alignment` annotations as well. Every odd-numbered yield will be an `Alignment` annotation, and every
99+
even-numbered yield will be the aligned annotation. If there's a specific annotation type that you're looking
100+
for, you need to filter the generated results outside.
101+
102+
:return: yields the alignment annotation and the aligned annotation.
103+
The order is decided by the order of appearance of Alignment annotations in the MMIF
104+
"""
105+
for alignment, aligned in self._alignments.items():
106+
yield alignment
107+
yield aligned
108+
109+
72110
def _add_prop_aliases(self, key_to_add, val_to_add):
73111
"""
74112
Method to handle aliases of the same property.
@@ -163,6 +201,7 @@ def add_property(self, name: str,
163201
value: Union[PRMTV_TYPES, LIST_PRMTV, LIST_LIST_PRMTV, DICT_PRMTV, DICT_LIST_PRMTV]) -> None:
164202
"""
165203
Adds a property to the annotation's properties.
204+
166205
:param name: the name of the property
167206
:param value: the property's desired value
168207
:return: None
@@ -241,7 +280,7 @@ class Document(Annotation):
241280
242281
:param document_obj: the JSON data that defines the document
243282
"""
244-
def __init__(self, doc_obj: Optional[Union[bytes, str, dict]] = None) -> None:
283+
def __init__(self, doc_obj: Optional[Union[bytes, str, dict]] = None, *_) -> None:
245284
# see https://github.com/clamsproject/mmif-python/issues/226 for discussion
246285
# around the use of these three dictionaries
247286
# (names changed since, `existing` >> `ephemeral` and `temporary` >> `pending`)
@@ -434,7 +473,7 @@ def __getitem__(self, key):
434473
else:
435474
return self._unnamed_attributes[key]
436475

437-
def __init__(self, mmif_obj: Optional[Union[bytes, str, dict]] = None) -> None:
476+
def __init__(self, mmif_obj: Optional[Union[bytes, str, dict]] = None, *_) -> None:
438477
self.id: str = ''
439478
# any individual at_type (subclassing this class) can have its own set of required attributes
440479
self._required_attributes = ["id"]
@@ -451,7 +490,7 @@ class DocumentProperties(AnnotationProperties):
451490
:param mmif_obj: the JSON data that defines the properties
452491
"""
453492

454-
def __init__(self, mmif_obj: Optional[Union[bytes, str, dict]] = None) -> None:
493+
def __init__(self, mmif_obj: Optional[Union[bytes, str, dict]] = None, *_) -> None:
455494
self.mime: str = ''
456495
# note the trailing underscore here. I wanted to use the name `location`
457496
# for @property in this class and `Document` class, so had to use a diff
@@ -572,7 +611,7 @@ def location_path_literal(self) -> Optional[str]:
572611

573612
class Text(MmifObject):
574613

575-
def __init__(self, text_obj: Optional[Union[bytes, str, dict]] = None) -> None:
614+
def __init__(self, text_obj: Optional[Union[bytes, str, dict]] = None, *_) -> None:
576615
self._value: str = ''
577616
self._language: str = ''
578617
self.disallow_additional_properties()

0 commit comments

Comments
 (0)