errors.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. from collections import defaultdict
  2. import six
  3. __all__ = ('NotRegistered', 'InvalidDocumentError', 'LookUpError',
  4. 'DoesNotExist', 'MultipleObjectsReturned', 'InvalidQueryError',
  5. 'OperationError', 'NotUniqueError', 'FieldDoesNotExist',
  6. 'ValidationError', 'SaveConditionError')
  7. class NotRegistered(Exception):
  8. pass
  9. class InvalidDocumentError(Exception):
  10. pass
  11. class LookUpError(AttributeError):
  12. pass
  13. class DoesNotExist(Exception):
  14. pass
  15. class MultipleObjectsReturned(Exception):
  16. pass
  17. class InvalidQueryError(Exception):
  18. pass
  19. class OperationError(Exception):
  20. pass
  21. class NotUniqueError(OperationError):
  22. pass
  23. class SaveConditionError(OperationError):
  24. pass
  25. class FieldDoesNotExist(Exception):
  26. """Raised when trying to set a field
  27. not declared in a :class:`~mongoengine.Document`
  28. or an :class:`~mongoengine.EmbeddedDocument`.
  29. To avoid this behavior on data loading,
  30. you should set the :attr:`strict` to ``False``
  31. in the :attr:`meta` dictionary.
  32. """
  33. class ValidationError(AssertionError):
  34. """Validation exception.
  35. May represent an error validating a field or a
  36. document containing fields with validation errors.
  37. :ivar errors: A dictionary of errors for fields within this
  38. document or list, or None if the error is for an
  39. individual field.
  40. """
  41. errors = {}
  42. field_name = None
  43. _message = None
  44. def __init__(self, message='', **kwargs):
  45. super(ValidationError, self).__init__(message)
  46. self.errors = kwargs.get('errors', {})
  47. self.field_name = kwargs.get('field_name')
  48. self.message = message
  49. def __str__(self):
  50. return six.text_type(self.message)
  51. def __repr__(self):
  52. return '%s(%s,)' % (self.__class__.__name__, self.message)
  53. def __getattribute__(self, name):
  54. message = super(ValidationError, self).__getattribute__(name)
  55. if name == 'message':
  56. if self.field_name:
  57. message = '%s' % message
  58. if self.errors:
  59. message = '%s(%s)' % (message, self._format_errors())
  60. return message
  61. def _get_message(self):
  62. return self._message
  63. def _set_message(self, message):
  64. self._message = message
  65. message = property(_get_message, _set_message)
  66. def to_dict(self):
  67. """Returns a dictionary of all errors within a document
  68. Keys are field names or list indices and values are the
  69. validation error messages, or a nested dictionary of
  70. errors for an embedded document or list.
  71. """
  72. def build_dict(source):
  73. errors_dict = {}
  74. if not source:
  75. return errors_dict
  76. if isinstance(source, dict):
  77. for field_name, error in source.iteritems():
  78. errors_dict[field_name] = build_dict(error)
  79. elif isinstance(source, ValidationError) and source.errors:
  80. return build_dict(source.errors)
  81. else:
  82. return six.text_type(source)
  83. return errors_dict
  84. if not self.errors:
  85. return {}
  86. return build_dict(self.errors)
  87. def _format_errors(self):
  88. """Returns a string listing all errors within a document"""
  89. def generate_key(value, prefix=''):
  90. if isinstance(value, list):
  91. value = ' '.join([generate_key(k) for k in value])
  92. elif isinstance(value, dict):
  93. value = ' '.join(
  94. [generate_key(v, k) for k, v in value.iteritems()])
  95. results = '%s.%s' % (prefix, value) if prefix else value
  96. return results
  97. error_dict = defaultdict(list)
  98. for k, v in self.to_dict().iteritems():
  99. error_dict[generate_key(v)].append(k)
  100. return ' '.join(['%s: %s' % (k, v) for k, v in error_dict.iteritems()])