mmif-python 1.0.13__tar.gz → 1.0.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {mmif-python-1.0.13/mmif_python.egg-info → mmif-python-1.0.14}/PKG-INFO +1 -1
  2. mmif-python-1.0.14/VERSION +1 -0
  3. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/serialize/annotation.py +19 -14
  4. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/serialize/mmif.py +29 -3
  5. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/serialize/model.py +22 -18
  6. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/serialize/view.py +39 -1
  7. mmif-python-1.0.14/mmif/ver/__init__.py +2 -0
  8. {mmif-python-1.0.13 → mmif-python-1.0.14/mmif_python.egg-info}/PKG-INFO +1 -1
  9. mmif-python-1.0.13/VERSION +0 -1
  10. mmif-python-1.0.13/mmif/ver/__init__.py +0 -2
  11. {mmif-python-1.0.13 → mmif-python-1.0.14}/LICENSE +0 -0
  12. {mmif-python-1.0.13 → mmif-python-1.0.14}/MANIFEST.in +0 -0
  13. {mmif-python-1.0.13 → mmif-python-1.0.14}/README.md +0 -0
  14. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/__init__.py +0 -0
  15. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/res/__init__.py +0 -0
  16. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/res/clams.vocabulary.yaml +0 -0
  17. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/res/do-not-edit.txt +0 -0
  18. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/res/mmif.json +0 -0
  19. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/serialize/__init__.py +0 -0
  20. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/utils/__init__.py +0 -0
  21. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/utils/sequence_helper.py +0 -0
  22. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/utils/timeunit_helper.py +0 -0
  23. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/utils/video_document_helper.py +0 -0
  24. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/ver/do-not-edit.txt +0 -0
  25. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/vocabulary/__init__.py +0 -0
  26. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/vocabulary/annotation_types.py +0 -0
  27. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/vocabulary/base_types.py +0 -0
  28. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/vocabulary/do-not-edit.txt +0 -0
  29. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif/vocabulary/document_types.py +0 -0
  30. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif_docloc_http/__init__.py +0 -0
  31. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif_python.egg-info/SOURCES.txt +0 -0
  32. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif_python.egg-info/dependency_links.txt +0 -0
  33. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif_python.egg-info/requires.txt +0 -0
  34. {mmif-python-1.0.13 → mmif-python-1.0.14}/mmif_python.egg-info/top_level.txt +0 -0
  35. {mmif-python-1.0.13 → mmif-python-1.0.14}/requirements.cv +0 -0
  36. {mmif-python-1.0.13 → mmif-python-1.0.14}/requirements.seq +0 -0
  37. {mmif-python-1.0.13 → mmif-python-1.0.14}/requirements.txt +0 -0
  38. {mmif-python-1.0.13 → mmif-python-1.0.14}/setup.cfg +0 -0
  39. {mmif-python-1.0.13 → mmif-python-1.0.14}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mmif-python
3
- Version: 1.0.13
3
+ Version: 1.0.14
4
4
  Summary: Python implementation of MultiMedia Interchange Format specification. (https://mmif.clams.ai)
5
5
  Home-page: https://mmif.clams.ai
6
6
  Author: Brandeis Lab for Linguistics and Computation
@@ -0,0 +1 @@
1
+ 1.0.14
@@ -415,26 +415,31 @@ class AnnotationProperties(MmifObject, MutableMapping[str, T]):
415
415
 
416
416
  def __iter__(self) -> Iterator[str]:
417
417
  """
418
- ``__iter__`` on Mapping should basically work as ``keys()`` method of vanilla dict
419
- however, when MMIF objects are serialized, all optional (not in ``_req_atts``),
420
- empty props are ignored (note that emtpy but required props are serialized
421
- with the *emtpy* value).
422
- Hence, this ``__iter__`` method should also work in the same way and
423
- ignore empty optional props.
418
+ ``__iter__`` on Mapping should basically work as ``keys()`` method
419
+ of vanilla dict.
424
420
  """
425
421
  for key in itertools.chain(self._named_attributes(), self._unnamed_attributes):
426
- if key in self._required_attributes:
427
- yield key
428
- else:
429
- try:
430
- self.__getitem__(key)
431
- yield key
432
- except KeyError:
433
- pass
422
+ yield key
423
+
424
+ def __getitem__(self, key):
425
+ """
426
+ Parent MmifObject class has a __getitem__ method that checks if
427
+ the value is empty when asked for an unnamed attribute. But for
428
+ AnnotationProperties, any arbitrary property that's added
429
+ explicitly by the user (developer) should not be ignored and
430
+ returned even the value is empty.
431
+ """
432
+ if key in self._named_attributes():
433
+ return self.__dict__[key]
434
+ else:
435
+ return self._unnamed_attributes[key]
434
436
 
435
437
  def __init__(self, mmif_obj: Optional[Union[bytes, str, dict]] = None) -> None:
436
438
  self.id: str = ''
439
+ # any individual at_type (subclassing this class) can have its own set of required attributes
437
440
  self._required_attributes = ["id"]
441
+ # allowing additional attributes for arbitrary annotation properties
442
+ self._unnamed_attributes = {}
438
443
  super().__init__(mmif_obj)
439
444
 
440
445
 
@@ -447,6 +447,16 @@ class Mmif(MmifObject):
447
447
  pass
448
448
  return views
449
449
 
450
+ def get_all_views_with_error(self) -> List[View]:
451
+ """
452
+ Returns the list of all views in the MMIF that have errors.
453
+
454
+ :return: the list of views that contain errors but no annotations
455
+ """
456
+ return [v for v in self.views if v.has_error()]
457
+
458
+ get_views_with_error = get_all_views_with_error
459
+
450
460
  def get_all_views_contain(self, at_types: Union[ThingTypesBase, str, List[Union[str, ThingTypesBase]]]) -> List[View]:
451
461
  """
452
462
  Returns the list of all views in the MMIF if given types
@@ -461,11 +471,27 @@ class Mmif(MmifObject):
461
471
  else:
462
472
  return [view for view in self.views if at_types in view.metadata.contains]
463
473
 
464
- def get_views_contain(self, at_types: Union[ThingTypesBase, str, List[Union[str, ThingTypesBase]]]) -> List[View]:
474
+ get_views_contain = get_all_views_contain
475
+
476
+ def get_view_with_error(self) -> Optional[View]:
477
+ """
478
+ Returns the last view appended that contains an error.
479
+
480
+ :return: the view, or None if no error is found
465
481
  """
466
- An alias to `get_all_views_contain` method.
482
+ for view in reversed(self.views):
483
+ if view.has_error():
484
+ return view
485
+ return None
486
+
487
+ def get_last_error(self) -> Optional[str]:
488
+ """
489
+ Returns the last error message found in the views.
490
+
491
+ :return: the error message in human-readable format, or None if no error is found
467
492
  """
468
- return self.get_all_views_contain(at_types)
493
+ v = self.get_view_with_error()
494
+ return v.get_error() if v is not None else None
469
495
 
470
496
  def get_view_contains(self, at_types: Union[ThingTypesBase, str, List[Union[str, ThingTypesBase]]]) -> Optional[View]:
471
497
  """
@@ -44,35 +44,39 @@ class MmifObject(object):
44
44
 
45
45
  1. _unnamed_attributes:
46
46
  Only can be either None or an empty dictionary. If it's set to None,
47
- it means the class won't take any ``Additional Attributes`` in the JSON
48
- schema sense. If it's a dict, users can throw any k-v pairs to the
49
- class, EXCEPT for the reserved two key names.
47
+ it means the class won't take any ``Additional Attributes`` in the
48
+ JSON schema sense. If it's an empty dict, users can throw any k-v
49
+ pairs to the class, as long as the key is not a "reserved" name,
50
+ and those additional attributes will be stored in this dict while
51
+ in memory.
50
52
  2. _attribute_classes:
51
53
  This is a dict from a key name to a specific python class to use for
52
54
  deserialize the value. Note that a key name in this dict does NOT
53
55
  have to be a *named* attribute, but is recommended to be one.
54
56
  3. _required_attributes:
55
- This is a simple list of names of attributes that are required in the object.
56
- When serialize, an object will skip its *empty* (e.g. zero-length, or None)
57
- attributes unless they are in this list. Otherwise, the serialized JSON
58
- string would have empty representations (e.g. ``""``, ``[]``).
57
+ This is a simple list of names of attributes that are required in
58
+ the object. When serialize, an object will skip its *empty* (e.g.
59
+ zero-length, or None) attributes unless they are in this list.
60
+ Otherwise, the serialized JSON string would have empty
61
+ representations (e.g. ``""``, ``[]``).
59
62
  4. _exclude_from_diff:
60
- This is a simple list of names of attributes that should be excluded from
61
- the diff calculation in ``__eq__``.
63
+ This is a simple list of names of attributes that should be excluded
64
+ from the diff calculation in ``__eq__``.
62
65
 
63
66
  # TODO (krim @ 8/17/20): this dict is however, a duplicate with the type hints in the class definition.
64
- Maybe there is a better way to utilize type hints (e.g. getting them as a programmatically), but for now
65
- developers should be careful to add types to hints as well as to this dict.
67
+ Maybe there is a better way to utilize type hints (e.g. getting them
68
+ as a programmatically), but for now developers should be careful to
69
+ add types to hints as well as to this dict.
66
70
 
67
71
  Also note that those special attributes MUST be set in the __init__()
68
72
  before calling super method, otherwise deserialization will not work.
69
73
 
70
74
  And also, a subclass that has one or more *named* attributes, it must
71
- set those attributes in the __init__() before calling super method. When
72
- serializing a MmifObject, all *empty* attributes will be ignored, so for
73
- optional named attributes, you must leave the values empty (len == 0), but
74
- NOT None. Any None-valued named attributes will cause issues with current
75
- implementation.
75
+ set those attributes in the __init__() before calling super method.
76
+ When serializing a MmifObject, all *empty* attributes will be ignored,
77
+ so for optional named attributes, you must leave the values empty
78
+ (len == 0), but NOT None. Any None-valued named attributes will cause
79
+ issues with current implementation.
76
80
 
77
81
  :param mmif_obj: JSON string or `dict` to initialize an object.
78
82
  If not given, an empty object will be initialized, sometimes with
@@ -272,8 +276,8 @@ class MmifObject(object):
272
276
  """
273
277
  Returns number of attributes that are not *empty*.
274
278
  """
275
- return sum([named in self and not self.is_empty(self[named]) for named in self._named_attributes()]) \
276
- + (len(self._unnamed_attributes) if self._unnamed_attributes else 0)
279
+ return (sum([named in self and not self.is_empty(self[named]) for named in self._named_attributes()])
280
+ + (len(self._unnamed_attributes) if self._unnamed_attributes else 0))
277
281
 
278
282
  def __setitem__(self, key, value) -> None:
279
283
  if key in self.reserved_names:
@@ -5,6 +5,7 @@ as a live Python object.
5
5
  In MMIF, views are created by apps in a pipeline that are annotating
6
6
  data that was previously present in the MMIF file.
7
7
  """
8
+ import json
8
9
  from datetime import datetime
9
10
  from typing import Dict, Union, Optional, Generator, List, cast
10
11
 
@@ -230,6 +231,23 @@ class View(MmifObject):
230
231
  def set_error(self, err_message: str, err_trace: str) -> None:
231
232
  self.metadata.set_error(err_message, err_trace)
232
233
  self.annotations.empty()
234
+
235
+ def get_error(self) -> Optional[str]:
236
+ """
237
+ Get the "text" representation of the error occurred during
238
+ processing. Text representation is supposed to be human-readable.
239
+ When ths view does not have any error, returns None.
240
+ """
241
+ if self.has_error():
242
+ return self.metadata.get_error_as_text()
243
+ else:
244
+ return None
245
+
246
+ def has_error(self) -> bool:
247
+ return self.metadata.has_error()
248
+
249
+ def has_warnings(self):
250
+ return self.metadata.has_warnings()
233
251
 
234
252
 
235
253
  class ViewMetadata(MmifObject):
@@ -267,7 +285,24 @@ class ViewMetadata(MmifObject):
267
285
  if not (self.contains.items() or self.error or self.warnings):
268
286
  serialized['contains'] = {}
269
287
  return serialized
270
-
288
+
289
+ def has_error(self) -> bool:
290
+ return len(self.error) > 0
291
+
292
+ def has_warnings(self):
293
+ return len(self.warnings) > 0
294
+
295
+ def get_error_as_text(self) -> str:
296
+ if self.has_error():
297
+ if isinstance(self.error, ErrorDict):
298
+ return str(self.error)
299
+ elif isinstance(self.error, dict):
300
+ return f"Error: {json.dumps(self.error, indent=2)}"
301
+ else:
302
+ return f"Error (unknown error format): {self.error}"
303
+ else:
304
+ raise KeyError(f"No error found")
305
+
271
306
  def new_contain(self, at_type: Union[str, ThingTypesBase], **contains_metadata) -> Optional['Contain']:
272
307
  """
273
308
  Adds a new element to the ``contains`` dictionary.
@@ -346,6 +381,9 @@ class ErrorDict(MmifObject):
346
381
  self.message: str = ''
347
382
  self.stackTrace: str = ''
348
383
  super().__init__(error_obj)
384
+
385
+ def __str__(self):
386
+ return f"({self.message})\n\n{self.stackTrace}"
349
387
 
350
388
 
351
389
  class Contain(DataDict[str, str]):
@@ -0,0 +1,2 @@
1
+ __version__ = "1.0.14"
2
+ __specver__ = "1.0.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mmif-python
3
- Version: 1.0.13
3
+ Version: 1.0.14
4
4
  Summary: Python implementation of MultiMedia Interchange Format specification. (https://mmif.clams.ai)
5
5
  Home-page: https://mmif.clams.ai
6
6
  Author: Brandeis Lab for Linguistics and Computation
@@ -1 +0,0 @@
1
- 1.0.13
@@ -1,2 +0,0 @@
1
- __version__ = "1.0.13"
2
- __specver__ = "1.0.4"
File without changes
File without changes
File without changes
File without changes
File without changes