error.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. # coding: utf-8
  2. from __future__ import absolute_import
  3. import warnings
  4. import textwrap
  5. from ruamel.yaml.compat import utf8
  6. if False: # MYPY
  7. from typing import Any, Dict, Optional, List, Text # NOQA
  8. __all__ = [
  9. 'FileMark',
  10. 'StringMark',
  11. 'CommentMark',
  12. 'YAMLError',
  13. 'MarkedYAMLError',
  14. 'ReusedAnchorWarning',
  15. 'UnsafeLoaderWarning',
  16. 'MarkedYAMLWarning',
  17. 'MarkedYAMLFutureWarning',
  18. ]
  19. class StreamMark(object):
  20. __slots__ = 'name', 'index', 'line', 'column'
  21. def __init__(self, name, index, line, column):
  22. # type: (Any, int, int, int) -> None
  23. self.name = name
  24. self.index = index
  25. self.line = line
  26. self.column = column
  27. def __str__(self):
  28. # type: () -> Any
  29. where = ' in "%s", line %d, column %d' % (self.name, self.line + 1, self.column + 1)
  30. return where
  31. def __eq__(self, other):
  32. # type: (Any) -> bool
  33. if self.line != other.line or self.column != other.column:
  34. return False
  35. if self.name != other.name or self.index != other.index:
  36. return False
  37. return True
  38. def __ne__(self, other):
  39. # type: (Any) -> bool
  40. return not self.__eq__(other)
  41. class FileMark(StreamMark):
  42. __slots__ = ()
  43. class StringMark(StreamMark):
  44. __slots__ = 'name', 'index', 'line', 'column', 'buffer', 'pointer'
  45. def __init__(self, name, index, line, column, buffer, pointer):
  46. # type: (Any, int, int, int, Any, Any) -> None
  47. StreamMark.__init__(self, name, index, line, column)
  48. self.buffer = buffer
  49. self.pointer = pointer
  50. def get_snippet(self, indent=4, max_length=75):
  51. # type: (int, int) -> Any
  52. if self.buffer is None: # always False
  53. return None
  54. head = ""
  55. start = self.pointer
  56. while start > 0 and self.buffer[start - 1] not in u'\0\r\n\x85\u2028\u2029':
  57. start -= 1
  58. if self.pointer - start > max_length / 2 - 1:
  59. head = ' ... '
  60. start += 5
  61. break
  62. tail = ""
  63. end = self.pointer
  64. while end < len(self.buffer) and self.buffer[end] not in u'\0\r\n\x85\u2028\u2029':
  65. end += 1
  66. if end - self.pointer > max_length / 2 - 1:
  67. tail = ' ... '
  68. end -= 5
  69. break
  70. snippet = utf8(self.buffer[start:end])
  71. caret = '^'
  72. caret = '^ (line: {})'.format(self.line + 1)
  73. return (
  74. ' ' * indent
  75. + head
  76. + snippet
  77. + tail
  78. + '\n'
  79. + ' ' * (indent + self.pointer - start + len(head))
  80. + caret
  81. )
  82. def __str__(self):
  83. # type: () -> Any
  84. snippet = self.get_snippet()
  85. where = ' in "%s", line %d, column %d' % (self.name, self.line + 1, self.column + 1)
  86. if snippet is not None:
  87. where += ':\n' + snippet
  88. return where
  89. class CommentMark(object):
  90. __slots__ = ('column',)
  91. def __init__(self, column):
  92. # type: (Any) -> None
  93. self.column = column
  94. class YAMLError(Exception):
  95. pass
  96. class MarkedYAMLError(YAMLError):
  97. def __init__(
  98. self,
  99. context=None,
  100. context_mark=None,
  101. problem=None,
  102. problem_mark=None,
  103. note=None,
  104. warn=None,
  105. ):
  106. # type: (Any, Any, Any, Any, Any, Any) -> None
  107. self.context = context
  108. self.context_mark = context_mark
  109. self.problem = problem
  110. self.problem_mark = problem_mark
  111. self.note = note
  112. # warn is ignored
  113. def __str__(self):
  114. # type: () -> Any
  115. lines = [] # type: List[str]
  116. if self.context is not None:
  117. lines.append(self.context)
  118. if self.context_mark is not None and (
  119. self.problem is None
  120. or self.problem_mark is None
  121. or self.context_mark.name != self.problem_mark.name
  122. or self.context_mark.line != self.problem_mark.line
  123. or self.context_mark.column != self.problem_mark.column
  124. ):
  125. lines.append(str(self.context_mark))
  126. if self.problem is not None:
  127. lines.append(self.problem)
  128. if self.problem_mark is not None:
  129. lines.append(str(self.problem_mark))
  130. if self.note is not None and self.note:
  131. note = textwrap.dedent(self.note)
  132. lines.append(note)
  133. return '\n'.join(lines)
  134. class YAMLStreamError(Exception):
  135. pass
  136. class YAMLWarning(Warning):
  137. pass
  138. class MarkedYAMLWarning(YAMLWarning):
  139. def __init__(
  140. self,
  141. context=None,
  142. context_mark=None,
  143. problem=None,
  144. problem_mark=None,
  145. note=None,
  146. warn=None,
  147. ):
  148. # type: (Any, Any, Any, Any, Any, Any) -> None
  149. self.context = context
  150. self.context_mark = context_mark
  151. self.problem = problem
  152. self.problem_mark = problem_mark
  153. self.note = note
  154. self.warn = warn
  155. def __str__(self):
  156. # type: () -> Any
  157. lines = [] # type: List[str]
  158. if self.context is not None:
  159. lines.append(self.context)
  160. if self.context_mark is not None and (
  161. self.problem is None
  162. or self.problem_mark is None
  163. or self.context_mark.name != self.problem_mark.name
  164. or self.context_mark.line != self.problem_mark.line
  165. or self.context_mark.column != self.problem_mark.column
  166. ):
  167. lines.append(str(self.context_mark))
  168. if self.problem is not None:
  169. lines.append(self.problem)
  170. if self.problem_mark is not None:
  171. lines.append(str(self.problem_mark))
  172. if self.note is not None and self.note:
  173. note = textwrap.dedent(self.note)
  174. lines.append(note)
  175. if self.warn is not None and self.warn:
  176. warn = textwrap.dedent(self.warn)
  177. lines.append(warn)
  178. return '\n'.join(lines)
  179. class ReusedAnchorWarning(YAMLWarning):
  180. pass
  181. class UnsafeLoaderWarning(YAMLWarning):
  182. text = """
  183. The default 'Loader' for 'load(stream)' without further arguments can be unsafe.
  184. Use 'load(stream, Loader=ruamel.yaml.Loader)' explicitly if that is OK.
  185. Alternatively include the following in your code:
  186. import warnings
  187. warnings.simplefilter('ignore', ruamel.yaml.error.UnsafeLoaderWarning)
  188. In most other cases you should consider using 'safe_load(stream)'"""
  189. pass
  190. warnings.simplefilter('once', UnsafeLoaderWarning)
  191. class MantissaNoDotYAML1_1Warning(YAMLWarning):
  192. def __init__(self, node, flt_str):
  193. # type: (Any, Any) -> None
  194. self.node = node
  195. self.flt = flt_str
  196. def __str__(self):
  197. # type: () -> Any
  198. line = self.node.start_mark.line
  199. col = self.node.start_mark.column
  200. return """
  201. In YAML 1.1 floating point values should have a dot ('.') in their mantissa.
  202. See the Floating-Point Language-Independent Type for YAML™ Version 1.1 specification
  203. ( http://yaml.org/type/float.html ). This dot is not required for JSON nor for YAML 1.2
  204. Correct your float: "{}" on line: {}, column: {}
  205. or alternatively include the following in your code:
  206. import warnings
  207. warnings.simplefilter('ignore', ruamel.yaml.error.MantissaNoDotYAML1_1Warning)
  208. """.format(
  209. self.flt, line, col
  210. )
  211. warnings.simplefilter('once', MantissaNoDotYAML1_1Warning)
  212. class YAMLFutureWarning(Warning):
  213. pass
  214. class MarkedYAMLFutureWarning(YAMLFutureWarning):
  215. def __init__(
  216. self,
  217. context=None,
  218. context_mark=None,
  219. problem=None,
  220. problem_mark=None,
  221. note=None,
  222. warn=None,
  223. ):
  224. # type: (Any, Any, Any, Any, Any, Any) -> None
  225. self.context = context
  226. self.context_mark = context_mark
  227. self.problem = problem
  228. self.problem_mark = problem_mark
  229. self.note = note
  230. self.warn = warn
  231. def __str__(self):
  232. # type: () -> Any
  233. lines = [] # type: List[str]
  234. if self.context is not None:
  235. lines.append(self.context)
  236. if self.context_mark is not None and (
  237. self.problem is None
  238. or self.problem_mark is None
  239. or self.context_mark.name != self.problem_mark.name
  240. or self.context_mark.line != self.problem_mark.line
  241. or self.context_mark.column != self.problem_mark.column
  242. ):
  243. lines.append(str(self.context_mark))
  244. if self.problem is not None:
  245. lines.append(self.problem)
  246. if self.problem_mark is not None:
  247. lines.append(str(self.problem_mark))
  248. if self.note is not None and self.note:
  249. note = textwrap.dedent(self.note)
  250. lines.append(note)
  251. if self.warn is not None and self.warn:
  252. warn = textwrap.dedent(self.warn)
  253. lines.append(warn)
  254. return '\n'.join(lines)