exceptions.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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 ResourceNotExistsError(ResourceError):
  35. '''
  36. Raised in an attempt to create a resource a URN that does not exist and is
  37. supposed to.
  38. This usually surfaces at the HTTP level as a 404.
  39. '''
  40. def __str__(self):
  41. return self.msg or 'Resource {} not found.'.format(self.uid)
  42. class InvalidResourceError(ResourceError):
  43. '''
  44. Raised when an invalid resource is found.
  45. This usually surfaces at the HTTP level as a 409 or other error.
  46. '''
  47. def __str__(self):
  48. return self.msg or 'Resource {} is invalid.'.format(self.uid)
  49. class IncompatibleLdpTypeError(ResourceError):
  50. '''
  51. Raised when a LDP-NR resource is PUT in place of a LDP-RS and vice versa.
  52. This usually surfaces at the HTTP level as a 415.
  53. '''
  54. def __init__(self, uid, mimetype, msg=None):
  55. super().__init__(uid, msg)
  56. self.mimetype = mimetype
  57. def __str__(self):
  58. return self.msg or 'Invalid content type \'{}\' for resource {}'.\
  59. format(self.mimetype, self.uid)
  60. class PathSegmentError(ResourceError):
  61. '''
  62. Raised when a LDP-NR resource is a path segment.
  63. This may be an expected result and may be handled to return a 200.
  64. '''
  65. def __str__(self):
  66. return self.msg or 'Resource \'{}\' is a path segment.'.format(
  67. self.uid)
  68. class ServerManagedTermError(RuntimeError):
  69. '''
  70. Raised in an attempt to change a triple containing a server-managed term.
  71. This usually surfaces at the HTTP level as a 409 or other error.
  72. '''
  73. def __init__(self, terms, term_type=None):
  74. if term_type == 's':
  75. term_name = 'subject'
  76. elif term_type == 'p':
  77. term_name = 'predicate'
  78. elif term_type == 't':
  79. term_name = 'RDF type'
  80. else:
  81. term_name = 'term'
  82. self.terms = terms
  83. self.term_name = term_name
  84. def __str__(self):
  85. return 'Some {}s are server managed and cannot be modified: {}'\
  86. .format(self.term_name, ' , '.join(self.terms))
  87. class InvalidTripleError(RuntimeError):
  88. '''
  89. Raised when a triple in a delta is not valid.
  90. This does not necessarily that it is not valid RDF, but rather that it may
  91. not be valid for the context it is meant to be utilized.
  92. '''
  93. def __init__(self, t):
  94. self.t = t
  95. def __str__(self):
  96. return '{} is not a valid triple.'.format(self.t)
  97. class RefIntViolationError(RuntimeError):
  98. '''
  99. Raised when a provided data set has a link to a non-existing repository
  100. resource. With some setups this is handled silently, with a strict setting
  101. it raises this exception that should return a 412 HTTP code.
  102. '''
  103. def __init__(self, o):
  104. self.o = o
  105. def __str__(self):
  106. return 'Resource {} does not exist in repository. Linking to it '\
  107. 'constitutes an integrity violation under the current setup.'\
  108. .format(self.o)
  109. class SingleSubjectError(RuntimeError):
  110. '''
  111. Raised when a SPARQL-Update query or a RDF payload for a PUT contain
  112. subjects that do not correspond to the resource being operated on.
  113. '''
  114. def __init__(self, uid, subject):
  115. self.uid = uid
  116. self.subject = subject
  117. def __str__(self):
  118. return '{} is not in the topic of this RDF, which is {}'.format(
  119. self.uid, self.subject)
  120. class TombstoneError(RuntimeError):
  121. '''
  122. Raised when a tombstone resource is found.
  123. It is up to the caller to handle this which may be a benign and expected
  124. result.
  125. '''
  126. def __init__(self, uid, ts):
  127. self.uid = uid
  128. self.ts = ts
  129. def __str__(self):
  130. return (
  131. 'Discovered tombstone resource at {}, departed: {}\n'
  132. 'To resurrect this resource, send a POST request to its tombstone.'
  133. .format(self.uid, self.ts)
  134. )