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