util.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. # -*- coding: utf-8
  2. """
  3. Module containing general utility functions.
  4. """
  5. def format_cardinality(in_val):
  6. """
  7. Checks an input value and formats it towards a custom tuple format
  8. used in odml Section, Property and Values cardinality.
  9. The following cases are supported:
  10. (n, n) - default, no restriction
  11. (d, n) - minimally d entries, no maximum
  12. (n, d) - maximally d entries, no minimum
  13. (d, d) - minimally d entries, maximally d entries
  14. Only positive integers are supported. 'None' is used to denote
  15. no restrictions on a maximum or minimum.
  16. :param in_val: Can either be 'None', a positive integer, which will set
  17. the maximum or an integer 2-tuple of the format '(min, max)'.
  18. :returns: None or the value as tuple. A ValueError is raised, if the
  19. provided value was not in an acceptable format.
  20. """
  21. exc_msg = "Can only assign positive single int or int-tuples of the format '(min, max)'"
  22. # Empty values reset the cardinality to None.
  23. if not in_val:
  24. return None
  25. # Catch tuple edge cases (0, 0); (None, None); (0, None); (None, 0)
  26. if isinstance(in_val, (tuple, list)) and len(in_val) == 2 and not in_val[0] and not in_val[1]:
  27. return None
  28. # Providing a single integer sets the maximum value in a tuple.
  29. if isinstance(in_val, int) and in_val > 0:
  30. return None, in_val
  31. # Integer 2-tuples of the format '(min, max)' are supported to set the cardinality.
  32. # Also support lists with a length of 2 without advertising it.
  33. if isinstance(in_val, (tuple, list)) and len(in_val) == 2:
  34. v_min = in_val[0]
  35. v_max = in_val[1]
  36. min_int = isinstance(v_min, int) and v_min >= 0
  37. max_int = isinstance(v_max, int) and v_max >= 0
  38. if max_int and min_int and v_max >= v_min:
  39. return v_min, v_max
  40. if max_int and not v_min:
  41. return None, v_max
  42. if min_int and not v_max:
  43. return v_min, None
  44. # Use helpful exception message in the following case:
  45. if max_int and min_int and v_max < v_min:
  46. exc_msg = "Minimum larger than maximum (min=%s, max=%s)" % (v_min, v_max)
  47. raise ValueError(exc_msg)