exceptions.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. ''' Put all exceptions here. '''
  2. class ResourceError(RuntimeError):
  3. '''
  4. Raised in an attempt to create a resource a URI that already exists and is
  5. not supposed to.
  6. This usually surfaces at the HTTP level as a 409.
  7. '''
  8. def __init__(self, uid, msg=None):
  9. self.uid = uid
  10. self.msg = msg.format(uid) if msg else None
  11. class ResourceExistsError(ResourceError):
  12. '''
  13. Raised in an attempt to create a resource a URI that already exists and is
  14. not supposed to.
  15. This usually surfaces at the HTTP level as a 409.
  16. '''
  17. def __str__(self):
  18. return self.msg or 'Resource {} already exists.'.format(self.uid)
  19. class ChecksumValidationError(ResourceError):
  20. '''
  21. Raised in an attempt to create a resource a URI that already exists and is
  22. not supposed to.
  23. This usually surfaces at the HTTP level as a 409.
  24. '''
  25. def __init__(self, uid, prov_cksum, calc_cksum, msg=None):
  26. self.uid = uid
  27. self.prov_cksum = prov_cksum
  28. self.calc_cksum = calc_cksum
  29. self.msg = msg.format(uid) if msg else None
  30. def __str__(self):
  31. return self.msg or (f'validation failed for resource {self.uid}. '
  32. f'provided checksum: {self.prov_cksum}; '
  33. f'calculated checksum: {self.calc_cksum}')
  34. class IndigestibleError(ResourceError):
  35. """
  36. Raised when an unsupported digest algorithm is requested.
  37. """
  38. pass
  39. class ResourceNotExistsError(ResourceError):
  40. '''
  41. Raised in an attempt to create a resource a URN that does not exist and is
  42. supposed to.
  43. This usually surfaces at the HTTP level as a 404.
  44. '''
  45. def __str__(self):
  46. return self.msg or 'Resource {} not found.'.format(self.uid)
  47. class InvalidResourceError(ResourceError):
  48. '''
  49. Raised when an invalid resource is found.
  50. This usually surfaces at the HTTP level as a 409 or other error.
  51. '''
  52. def __str__(self):
  53. return self.msg or 'Resource {} is invalid.'.format(self.uid)
  54. class IncompatibleLdpTypeError(ResourceError):
  55. '''
  56. Raised when a LDP-NR resource is PUT in place of a LDP-RS and vice versa.
  57. This usually surfaces at the HTTP level as a 415.
  58. '''
  59. def __init__(self, uid, mimetype, msg=None):
  60. super().__init__(uid, msg)
  61. self.mimetype = mimetype
  62. def __str__(self):
  63. return self.msg or 'Invalid content type \'{}\' for resource {}'.\
  64. format(self.mimetype, self.uid)
  65. class PathSegmentError(ResourceError):
  66. '''
  67. Raised when a LDP-NR resource is a path segment.
  68. This may be an expected result and may be handled to return a 200.
  69. '''
  70. def __str__(self):
  71. return self.msg or 'Resource \'{}\' is a path segment.'.format(
  72. self.uid)
  73. class ServerManagedTermError(RuntimeError):
  74. '''
  75. Raised in an attempt to change a triple containing a server-managed term.
  76. This usually surfaces at the HTTP level as a 409 or other error.
  77. '''
  78. def __init__(self, terms, term_type=None):
  79. if term_type == 's':
  80. term_name = 'subject'
  81. elif term_type == 'p':
  82. term_name = 'predicate'
  83. elif term_type == 't':
  84. term_name = 'RDF type'
  85. else:
  86. term_name = 'term'
  87. self.terms = terms
  88. self.term_name = term_name
  89. def __str__(self):
  90. return 'Some {}s are server managed and cannot be modified: {}'\
  91. .format(self.term_name, ' , '.join(self.terms))
  92. class RdfParsingError(ValueError):
  93. """
  94. Raised when a string cannot be parsed as RDF in the given format.
  95. """
  96. def __init__(self, fmt, parser_msg=''):
  97. self.fmt = fmt
  98. self.parser_msg = parser_msg
  99. def __str__(self):
  100. return (f'Error parsing RDF in {self.fmt} format: {self.parser_msg}')
  101. class InvalidTripleError(ValueError):
  102. '''
  103. Raised when a triple in a delta is not valid.
  104. This does not necessarily that it is not valid RDF, but rather that it may
  105. not be valid for the context it is meant to be utilized.
  106. '''
  107. def __init__(self, t):
  108. self.t = t
  109. def __str__(self):
  110. return '{} is not a valid triple.'.format(self.t)
  111. class RefIntViolationError(RuntimeError):
  112. '''
  113. Raised when a provided data set has a link to a non-existing repository
  114. resource. With some setups this is handled silently, with a strict setting
  115. it raises this exception that should return a 412 HTTP code.
  116. '''
  117. def __init__(self, o):
  118. self.o = o
  119. def __str__(self):
  120. return 'Resource {} does not exist in repository. Linking to it '\
  121. 'constitutes an integrity violation under the current setup.'\
  122. .format(self.o)
  123. class SingleSubjectError(RuntimeError):
  124. '''
  125. Raised when a SPARQL-Update query or a RDF payload for a PUT contain
  126. subjects that do not correspond to the resource being operated on.
  127. '''
  128. def __init__(self, uid, subject):
  129. self.uid = uid
  130. self.subject = subject
  131. def __str__(self):
  132. return '{} is not in the topic of this RDF, which is {}'.format(
  133. self.uid, self.subject)
  134. class TombstoneError(RuntimeError):
  135. '''
  136. Raised when a tombstone resource is found.
  137. It is up to the caller to handle this which may be a benign and expected
  138. result.
  139. '''
  140. def __init__(self, uid, ts):
  141. self.uid = uid
  142. self.ts = ts
  143. def __str__(self):
  144. return (
  145. 'Discovered tombstone resource at {}, departed: {}\n'
  146. 'To resurrect this resource, send a POST request to its tombstone.'
  147. .format(self.uid, self.ts)
  148. )