PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/documentor/libraries/Sphinx-1.1.3-py3.2/sphinx/util/jsdump.py

https://github.com/tictactatic/Superdesk
Python | 195 lines | 172 code | 10 blank | 13 comment | 4 complexity | 7d0efda28602a7f23a188533de405267 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0, GPL-2.0
  1. # -*- coding: utf-8 -*-
  2. """
  3. sphinx.util.jsdump
  4. ~~~~~~~~~~~~~~~~~~
  5. This module implements a simple JavaScript serializer.
  6. Uses the basestring encode function from simplejson by Bob Ippolito.
  7. :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
  8. :license: BSD, see LICENSE for details.
  9. """
  10. import re
  11. from sphinx.util.pycompat import u
  12. _str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
  13. _int_re = re.compile(r'\d+')
  14. _name_re = re.compile(r'[a-zA-Z]\w*')
  15. _nameonly_re = re.compile(r'[a-zA-Z]\w*$')
  16. # escape \, ", control characters and everything outside ASCII
  17. ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
  18. ESCAPE_DICT = {
  19. '\\': '\\\\',
  20. '"': '\\"',
  21. '\b': '\\b',
  22. '\f': '\\f',
  23. '\n': '\\n',
  24. '\r': '\\r',
  25. '\t': '\\t',
  26. }
  27. ESCAPED = re.compile(r'\\u.{4}|\\.')
  28. def encode_string(s):
  29. def replace(match):
  30. s = match.group(0)
  31. try:
  32. return ESCAPE_DICT[s]
  33. except KeyError:
  34. n = ord(s)
  35. if n < 0x10000:
  36. return '\\u%04x' % (n,)
  37. else:
  38. # surrogate pair
  39. n -= 0x10000
  40. s1 = 0xd800 | ((n >> 10) & 0x3ff)
  41. s2 = 0xdc00 | (n & 0x3ff)
  42. return '\\u%04x\\u%04x' % (s1, s2)
  43. return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
  44. def decode_string(s):
  45. return ESCAPED.sub(lambda m: eval(u + '"' + m.group() + '"'), s)
  46. reswords = set("""\
  47. abstract else instanceof switch
  48. boolean enum int synchronized
  49. break export interface this
  50. byte extends long throw
  51. case false native throws
  52. catch final new transient
  53. char finally null true
  54. class float package try
  55. const for private typeof
  56. continue function protected var
  57. debugger goto public void
  58. default if return volatile
  59. delete implements short while
  60. do import static with
  61. double in super""".split())
  62. def dumps(obj, key=False):
  63. if key:
  64. if not isinstance(obj, str):
  65. obj = str(obj)
  66. if _nameonly_re.match(obj) and obj not in reswords:
  67. return obj # return it as a bare word
  68. else:
  69. return encode_string(obj)
  70. if obj is None:
  71. return 'null'
  72. elif obj is True or obj is False:
  73. return obj and 'true' or 'false'
  74. elif isinstance(obj, (int, float)):
  75. return str(obj)
  76. elif isinstance(obj, dict):
  77. return '{%s}' % ','.join('%s:%s' % (
  78. dumps(key, True),
  79. dumps(value)
  80. ) for key, value in obj.items())
  81. elif isinstance(obj, (tuple, list, set)):
  82. return '[%s]' % ','.join(dumps(x) for x in obj)
  83. elif isinstance(obj, str):
  84. return encode_string(obj)
  85. raise TypeError(type(obj))
  86. def dump(obj, f):
  87. f.write(dumps(obj))
  88. def loads(x):
  89. """Loader that can read the JS subset the indexer produces."""
  90. nothing = object()
  91. i = 0
  92. n = len(x)
  93. stack = []
  94. obj = nothing
  95. key = False
  96. keys = []
  97. while i < n:
  98. c = x[i]
  99. if c == '{':
  100. obj = {}
  101. stack.append(obj)
  102. key = True
  103. keys.append(nothing)
  104. i += 1
  105. elif c == '[':
  106. obj = []
  107. stack.append(obj)
  108. key = False
  109. keys.append(nothing)
  110. i += 1
  111. elif c in '}]':
  112. if key:
  113. if keys[-1] is not nothing:
  114. raise ValueError("unfinished dict")
  115. # empty dict
  116. key = False
  117. oldobj = stack.pop()
  118. keys.pop()
  119. if stack:
  120. obj = stack[-1]
  121. if isinstance(obj, dict):
  122. if keys[-1] is nothing:
  123. raise ValueError("invalid key object", oldobj)
  124. obj[keys[-1]] = oldobj
  125. else:
  126. obj.append(oldobj)
  127. else:
  128. break
  129. i += 1
  130. elif c == ',':
  131. if key:
  132. raise ValueError("multiple keys")
  133. if isinstance(obj, dict):
  134. key = True
  135. i += 1
  136. elif c == ':':
  137. if not isinstance(obj, dict):
  138. raise ValueError("colon in list")
  139. i += 1
  140. if not key:
  141. raise ValueError("multiple values")
  142. key = False
  143. else:
  144. m = _str_re.match(x, i)
  145. if m:
  146. y = decode_string(m.group()[1:-1])
  147. else:
  148. m = _int_re.match(x, i)
  149. if m:
  150. y = int(m.group())
  151. else:
  152. m = _name_re.match(x, i)
  153. if m:
  154. y = m.group()
  155. if y == 'true':
  156. y = True
  157. elif y == 'false':
  158. y = False
  159. elif y == 'null':
  160. y = None
  161. elif not key:
  162. raise ValueError("bareword as value")
  163. else:
  164. raise ValueError("read error at pos %d" % i)
  165. i = m.end()
  166. if isinstance(obj, dict):
  167. if key:
  168. keys[-1] = y
  169. else:
  170. obj[keys[-1]] = y
  171. key = False
  172. else:
  173. obj.append(y)
  174. if obj is nothing:
  175. raise ValueError("nothing loaded from string")
  176. return obj
  177. def load(f):
  178. return loads(f.read())