├── localtunnel ├── __init__.py ├── cli.py ├── core.py ├── http.py └── packages │ ├── __init__.py │ └── omnijson │ ├── __init__.py │ ├── core.py │ └── packages │ ├── __init__.py │ └── simplejson │ ├── __init__.py │ ├── decoder.py │ ├── encoder.py │ ├── ordered_dict.py │ └── scanner.py ├── localtunnel_r └── reqs.txt /localtunnel/__init__.py: -------------------------------------------------------------------------------- 1 | from core import * -------------------------------------------------------------------------------- /localtunnel/cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | localtunnel.cli 4 | ~~~~~~~~~~~~~~~ 5 | 6 | This module provides the command-line interface for Localtunnel. 7 | """ 8 | 9 | import sys 10 | 11 | import clint 12 | from clint.utils import expand_path 13 | 14 | from . import http 15 | 16 | USAGE = ''' 17 | Usage: localtunnel [options] 18 | -k, --key FILE upload a public key for authentication 19 | -h, --help show this help 20 | '''.lstrip() 21 | 22 | 23 | def display_usage(): 24 | print USAGE 25 | 26 | def display_port_error(): 27 | print 'Invalid port number.' 28 | 29 | 30 | def main(): 31 | """Main localtunnel dispatch.""" 32 | 33 | if ('-h', '--help') in clint.args: 34 | display_usage() 35 | sys.exit() 36 | 37 | elif ('-k', '--key') in clint.args: 38 | 39 | if len(clint.args.files) != 1: 40 | print 'Please specify a specific public key file.' 41 | 42 | maybe_key = expand_path('~/.ssh/*.pub').pop(0) 43 | print 'Best guess: {0}\n'.format(maybe_key) 44 | sys.exit(1) 45 | 46 | keyfile = clint.args.files.pop(0) 47 | 48 | with open(keyfile, 'rb') as f: 49 | http.register_key(f.read()) 50 | 51 | print 'Key successfully registered.' 52 | sys.exit() 53 | 54 | elif not len(clint.args.not_flags): 55 | display_usage() 56 | sys.exit(1) 57 | 58 | port = clint.args.not_flags.pop(0) 59 | 60 | try: 61 | int(port) 62 | except ValueError: 63 | display_port_error() 64 | sys.exit(1) 65 | 66 | if __name__ == '__main__': 67 | main() -------------------------------------------------------------------------------- /localtunnel/core.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | -------------------------------------------------------------------------------- /localtunnel/http.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | localtunnel.http 5 | ~~~~~~~~~~~~~~~~ 6 | 7 | This module provides 8 | """ 9 | 10 | import requests 11 | 12 | from .packages.omnijson import loads as from_json 13 | from .packages.omnijson import JSONError 14 | 15 | 16 | LOCALTUNNEL_API = 'http://open.localtunnel.com/' 17 | 18 | 19 | def register_key(pub_key): 20 | """Publishes a public key to the localtunnel service.""" 21 | 22 | r = requests.post(LOCALTUNNEL_API, data={'key': pub_key}) 23 | r.raise_for_status() 24 | 25 | 26 | def register_tunnel(): 27 | """Requests a new connection to the localtunnel service.""" 28 | r = requests.get(LOCALTUNNEL_API) 29 | 30 | try: 31 | return from_json(r.content) 32 | except JSONError, why: 33 | raise why 34 | 35 | -------------------------------------------------------------------------------- /localtunnel/packages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz-archive/python-localtunnel/86496bc30c19b60acf3f4ba26aaa74217360135a/localtunnel/packages/__init__.py -------------------------------------------------------------------------------- /localtunnel/packages/omnijson/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from __future__ import absolute_import 4 | 5 | from .core import loads, dumps, JSONError 6 | 7 | 8 | __all__ = ('loads', 'dumps', 'JSONError') 9 | 10 | 11 | __version__ = '0.1.2' 12 | __author__ = 'Kenneth Reitz' 13 | __license__ = 'MIT' 14 | -------------------------------------------------------------------------------- /localtunnel/packages/omnijson/core.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | omijson.core 5 | ~~~~~~~~~~~~ 6 | 7 | This module provides the core omnijson functionality. 8 | 9 | """ 10 | 11 | import sys 12 | 13 | engine = None 14 | _engine = None 15 | 16 | 17 | options = [ 18 | ['ujson', 'loads', 'dumps', (ValueError,)], 19 | ['yajl', 'loads', 'dumps', (TypeError, ValueError)], 20 | ['jsonlib2', 'read', 'write', (ValueError,)], 21 | ['jsonlib', 'read', 'write', (ValueError,)], 22 | ['simplejson', 'loads', 'dumps', (TypeError, ValueError)], 23 | ['json', 'loads', 'dumps', (TypeError, ValueError)], 24 | ['simplejson_from_packages', 'loads', 'dumps', (ValueError,)], 25 | ] 26 | 27 | 28 | def _import(engine): 29 | try: 30 | if '_from_' in engine: 31 | engine, package = engine.split('_from_') 32 | m = __import__(package, globals(), locals(), [engine], -1) 33 | return getattr(m, engine) 34 | 35 | return __import__(engine) 36 | 37 | except ImportError: 38 | return False 39 | 40 | 41 | def loads(s, **kwargs): 42 | """Loads JSON object.""" 43 | 44 | try: 45 | return _engine[0](s) 46 | 47 | except: 48 | # crazy 2/3 exception hack 49 | # http://www.voidspace.org.uk/python/weblog/arch_d7_2010_03_20.shtml 50 | 51 | ExceptionClass, why = sys.exc_info()[:2] 52 | 53 | if any([(issubclass(ExceptionClass, e)) for e in _engine[2]]): 54 | raise JSONError(why) 55 | else: 56 | raise why 57 | 58 | 59 | def dumps(o, **kwargs): 60 | """Dumps JSON object.""" 61 | 62 | try: 63 | return _engine[1](o) 64 | 65 | except: 66 | ExceptionClass, why = sys.exc_info()[:2] 67 | 68 | if any([(issubclass(ExceptionClass, e)) for e in _engine[2]]): 69 | raise JSONError(why) 70 | else: 71 | raise why 72 | 73 | 74 | class JSONError(ValueError): 75 | """JSON Failed.""" 76 | 77 | 78 | # ------ 79 | # Magic! 80 | # ------ 81 | 82 | 83 | for e in options: 84 | 85 | __engine = _import(e[0]) 86 | 87 | if __engine: 88 | engine, _engine = e[0], e[1:4] 89 | 90 | for i in (0, 1): 91 | _engine[i] = getattr(__engine, _engine[i]) 92 | 93 | break 94 | -------------------------------------------------------------------------------- /localtunnel/packages/omnijson/packages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz-archive/python-localtunnel/86496bc30c19b60acf3f4ba26aaa74217360135a/localtunnel/packages/omnijson/packages/__init__.py -------------------------------------------------------------------------------- /localtunnel/packages/omnijson/packages/simplejson/__init__.py: -------------------------------------------------------------------------------- 1 | r"""JSON (JavaScript Object Notation) is a subset of 2 | JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data 3 | interchange format. 4 | 5 | :mod:`simplejson` exposes an API familiar to users of the standard library 6 | :mod:`marshal` and :mod:`pickle` modules. It is the externally maintained 7 | version of the :mod:`json` library contained in Python 2.6, but maintains 8 | compatibility with Python 2.4 and Python 2.5 and (currently) has 9 | significant performance advantages, even without using the optional C 10 | extension for speedups. 11 | 12 | Encoding basic Python object hierarchies:: 13 | 14 | >>> import simplejson as json 15 | >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) 16 | '["foo", {"bar": ["baz", null, 1.0, 2]}]' 17 | >>> print json.dumps("\"foo\bar") 18 | "\"foo\bar" 19 | >>> print json.dumps(u'\u1234') 20 | "\u1234" 21 | >>> print json.dumps('\\') 22 | "\\" 23 | >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True) 24 | {"a": 0, "b": 0, "c": 0} 25 | >>> from StringIO import StringIO 26 | >>> io = StringIO() 27 | >>> json.dump(['streaming API'], io) 28 | >>> io.getvalue() 29 | '["streaming API"]' 30 | 31 | Compact encoding:: 32 | 33 | >>> import simplejson as json 34 | >>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':')) 35 | '[1,2,3,{"4":5,"6":7}]' 36 | 37 | Pretty printing:: 38 | 39 | >>> import simplejson as json 40 | >>> s = json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=' ') 41 | >>> print '\n'.join([l.rstrip() for l in s.splitlines()]) 42 | { 43 | "4": 5, 44 | "6": 7 45 | } 46 | 47 | Decoding JSON:: 48 | 49 | >>> import simplejson as json 50 | >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}] 51 | >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj 52 | True 53 | >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar' 54 | True 55 | >>> from StringIO import StringIO 56 | >>> io = StringIO('["streaming API"]') 57 | >>> json.load(io)[0] == 'streaming API' 58 | True 59 | 60 | Specializing JSON object decoding:: 61 | 62 | >>> import simplejson as json 63 | >>> def as_complex(dct): 64 | ... if '__complex__' in dct: 65 | ... return complex(dct['real'], dct['imag']) 66 | ... return dct 67 | ... 68 | >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}', 69 | ... object_hook=as_complex) 70 | (1+2j) 71 | >>> from decimal import Decimal 72 | >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1') 73 | True 74 | 75 | Specializing JSON object encoding:: 76 | 77 | >>> import simplejson as json 78 | >>> def encode_complex(obj): 79 | ... if isinstance(obj, complex): 80 | ... return [obj.real, obj.imag] 81 | ... raise TypeError(repr(o) + " is not JSON serializable") 82 | ... 83 | >>> json.dumps(2 + 1j, default=encode_complex) 84 | '[2.0, 1.0]' 85 | >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j) 86 | '[2.0, 1.0]' 87 | >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j)) 88 | '[2.0, 1.0]' 89 | 90 | 91 | Using simplejson.tool from the shell to validate and pretty-print:: 92 | 93 | $ echo '{"json":"obj"}' | python -m simplejson.tool 94 | { 95 | "json": "obj" 96 | } 97 | $ echo '{ 1.2:3.4}' | python -m simplejson.tool 98 | Expecting property name: line 1 column 2 (char 2) 99 | """ 100 | __version__ = '2.1.6' 101 | __all__ = [ 102 | 'dump', 'dumps', 'load', 'loads', 103 | 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', 104 | 'OrderedDict', 105 | ] 106 | 107 | __author__ = 'Bob Ippolito ' 108 | 109 | from decimal import Decimal 110 | 111 | from decoder import JSONDecoder, JSONDecodeError 112 | from encoder import JSONEncoder 113 | def _import_OrderedDict(): 114 | import collections 115 | try: 116 | return collections.OrderedDict 117 | except AttributeError: 118 | import ordered_dict 119 | return ordered_dict.OrderedDict 120 | OrderedDict = _import_OrderedDict() 121 | 122 | def _import_c_make_encoder(): 123 | try: 124 | from simplejson._speedups import make_encoder 125 | return make_encoder 126 | except ImportError: 127 | return None 128 | 129 | _default_encoder = JSONEncoder( 130 | skipkeys=False, 131 | ensure_ascii=True, 132 | check_circular=True, 133 | allow_nan=True, 134 | indent=None, 135 | separators=None, 136 | encoding='utf-8', 137 | default=None, 138 | use_decimal=False, 139 | ) 140 | 141 | def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, 142 | allow_nan=True, cls=None, indent=None, separators=None, 143 | encoding='utf-8', default=None, use_decimal=False, **kw): 144 | """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a 145 | ``.write()``-supporting file-like object). 146 | 147 | If ``skipkeys`` is true then ``dict`` keys that are not basic types 148 | (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) 149 | will be skipped instead of raising a ``TypeError``. 150 | 151 | If ``ensure_ascii`` is false, then the some chunks written to ``fp`` 152 | may be ``unicode`` instances, subject to normal Python ``str`` to 153 | ``unicode`` coercion rules. Unless ``fp.write()`` explicitly 154 | understands ``unicode`` (as in ``codecs.getwriter()``) this is likely 155 | to cause an error. 156 | 157 | If ``check_circular`` is false, then the circular reference check 158 | for container types will be skipped and a circular reference will 159 | result in an ``OverflowError`` (or worse). 160 | 161 | If ``allow_nan`` is false, then it will be a ``ValueError`` to 162 | serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) 163 | in strict compliance of the JSON specification, instead of using the 164 | JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). 165 | 166 | If *indent* is a string, then JSON array elements and object members 167 | will be pretty-printed with a newline followed by that string repeated 168 | for each level of nesting. ``None`` (the default) selects the most compact 169 | representation without any newlines. For backwards compatibility with 170 | versions of simplejson earlier than 2.1.0, an integer is also accepted 171 | and is converted to a string with that many spaces. 172 | 173 | If ``separators`` is an ``(item_separator, dict_separator)`` tuple 174 | then it will be used instead of the default ``(', ', ': ')`` separators. 175 | ``(',', ':')`` is the most compact JSON representation. 176 | 177 | ``encoding`` is the character encoding for str instances, default is UTF-8. 178 | 179 | ``default(obj)`` is a function that should return a serializable version 180 | of obj or raise TypeError. The default simply raises TypeError. 181 | 182 | If *use_decimal* is true (default: ``False``) then decimal.Decimal 183 | will be natively serialized to JSON with full precision. 184 | 185 | To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the 186 | ``.default()`` method to serialize additional types), specify it with 187 | the ``cls`` kwarg. 188 | 189 | """ 190 | # cached encoder 191 | if (not skipkeys and ensure_ascii and 192 | check_circular and allow_nan and 193 | cls is None and indent is None and separators is None and 194 | encoding == 'utf-8' and default is None and not use_decimal 195 | and not kw): 196 | iterable = _default_encoder.iterencode(obj) 197 | else: 198 | if cls is None: 199 | cls = JSONEncoder 200 | iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, 201 | check_circular=check_circular, allow_nan=allow_nan, indent=indent, 202 | separators=separators, encoding=encoding, 203 | default=default, use_decimal=use_decimal, **kw).iterencode(obj) 204 | # could accelerate with writelines in some versions of Python, at 205 | # a debuggability cost 206 | for chunk in iterable: 207 | fp.write(chunk) 208 | 209 | 210 | def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, 211 | allow_nan=True, cls=None, indent=None, separators=None, 212 | encoding='utf-8', default=None, use_decimal=False, **kw): 213 | """Serialize ``obj`` to a JSON formatted ``str``. 214 | 215 | If ``skipkeys`` is false then ``dict`` keys that are not basic types 216 | (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) 217 | will be skipped instead of raising a ``TypeError``. 218 | 219 | If ``ensure_ascii`` is false, then the return value will be a 220 | ``unicode`` instance subject to normal Python ``str`` to ``unicode`` 221 | coercion rules instead of being escaped to an ASCII ``str``. 222 | 223 | If ``check_circular`` is false, then the circular reference check 224 | for container types will be skipped and a circular reference will 225 | result in an ``OverflowError`` (or worse). 226 | 227 | If ``allow_nan`` is false, then it will be a ``ValueError`` to 228 | serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in 229 | strict compliance of the JSON specification, instead of using the 230 | JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). 231 | 232 | If ``indent`` is a string, then JSON array elements and object members 233 | will be pretty-printed with a newline followed by that string repeated 234 | for each level of nesting. ``None`` (the default) selects the most compact 235 | representation without any newlines. For backwards compatibility with 236 | versions of simplejson earlier than 2.1.0, an integer is also accepted 237 | and is converted to a string with that many spaces. 238 | 239 | If ``separators`` is an ``(item_separator, dict_separator)`` tuple 240 | then it will be used instead of the default ``(', ', ': ')`` separators. 241 | ``(',', ':')`` is the most compact JSON representation. 242 | 243 | ``encoding`` is the character encoding for str instances, default is UTF-8. 244 | 245 | ``default(obj)`` is a function that should return a serializable version 246 | of obj or raise TypeError. The default simply raises TypeError. 247 | 248 | If *use_decimal* is true (default: ``False``) then decimal.Decimal 249 | will be natively serialized to JSON with full precision. 250 | 251 | To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the 252 | ``.default()`` method to serialize additional types), specify it with 253 | the ``cls`` kwarg. 254 | 255 | """ 256 | # cached encoder 257 | if (not skipkeys and ensure_ascii and 258 | check_circular and allow_nan and 259 | cls is None and indent is None and separators is None and 260 | encoding == 'utf-8' and default is None and not use_decimal 261 | and not kw): 262 | return _default_encoder.encode(obj) 263 | if cls is None: 264 | cls = JSONEncoder 265 | return cls( 266 | skipkeys=skipkeys, ensure_ascii=ensure_ascii, 267 | check_circular=check_circular, allow_nan=allow_nan, indent=indent, 268 | separators=separators, encoding=encoding, default=default, 269 | use_decimal=use_decimal, **kw).encode(obj) 270 | 271 | 272 | _default_decoder = JSONDecoder(encoding=None, object_hook=None, 273 | object_pairs_hook=None) 274 | 275 | 276 | def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None, 277 | parse_int=None, parse_constant=None, object_pairs_hook=None, 278 | use_decimal=False, **kw): 279 | """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing 280 | a JSON document) to a Python object. 281 | 282 | *encoding* determines the encoding used to interpret any 283 | :class:`str` objects decoded by this instance (``'utf-8'`` by 284 | default). It has no effect when decoding :class:`unicode` objects. 285 | 286 | Note that currently only encodings that are a superset of ASCII work, 287 | strings of other encodings should be passed in as :class:`unicode`. 288 | 289 | *object_hook*, if specified, will be called with the result of every 290 | JSON object decoded and its return value will be used in place of the 291 | given :class:`dict`. This can be used to provide custom 292 | deserializations (e.g. to support JSON-RPC class hinting). 293 | 294 | *object_pairs_hook* is an optional function that will be called with 295 | the result of any object literal decode with an ordered list of pairs. 296 | The return value of *object_pairs_hook* will be used instead of the 297 | :class:`dict`. This feature can be used to implement custom decoders 298 | that rely on the order that the key and value pairs are decoded (for 299 | example, :func:`collections.OrderedDict` will remember the order of 300 | insertion). If *object_hook* is also defined, the *object_pairs_hook* 301 | takes priority. 302 | 303 | *parse_float*, if specified, will be called with the string of every 304 | JSON float to be decoded. By default, this is equivalent to 305 | ``float(num_str)``. This can be used to use another datatype or parser 306 | for JSON floats (e.g. :class:`decimal.Decimal`). 307 | 308 | *parse_int*, if specified, will be called with the string of every 309 | JSON int to be decoded. By default, this is equivalent to 310 | ``int(num_str)``. This can be used to use another datatype or parser 311 | for JSON integers (e.g. :class:`float`). 312 | 313 | *parse_constant*, if specified, will be called with one of the 314 | following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This 315 | can be used to raise an exception if invalid JSON numbers are 316 | encountered. 317 | 318 | If *use_decimal* is true (default: ``False``) then it implies 319 | parse_float=decimal.Decimal for parity with ``dump``. 320 | 321 | To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` 322 | kwarg. 323 | 324 | """ 325 | return loads(fp.read(), 326 | encoding=encoding, cls=cls, object_hook=object_hook, 327 | parse_float=parse_float, parse_int=parse_int, 328 | parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, 329 | use_decimal=use_decimal, **kw) 330 | 331 | 332 | def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, 333 | parse_int=None, parse_constant=None, object_pairs_hook=None, 334 | use_decimal=False, **kw): 335 | """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON 336 | document) to a Python object. 337 | 338 | *encoding* determines the encoding used to interpret any 339 | :class:`str` objects decoded by this instance (``'utf-8'`` by 340 | default). It has no effect when decoding :class:`unicode` objects. 341 | 342 | Note that currently only encodings that are a superset of ASCII work, 343 | strings of other encodings should be passed in as :class:`unicode`. 344 | 345 | *object_hook*, if specified, will be called with the result of every 346 | JSON object decoded and its return value will be used in place of the 347 | given :class:`dict`. This can be used to provide custom 348 | deserializations (e.g. to support JSON-RPC class hinting). 349 | 350 | *object_pairs_hook* is an optional function that will be called with 351 | the result of any object literal decode with an ordered list of pairs. 352 | The return value of *object_pairs_hook* will be used instead of the 353 | :class:`dict`. This feature can be used to implement custom decoders 354 | that rely on the order that the key and value pairs are decoded (for 355 | example, :func:`collections.OrderedDict` will remember the order of 356 | insertion). If *object_hook* is also defined, the *object_pairs_hook* 357 | takes priority. 358 | 359 | *parse_float*, if specified, will be called with the string of every 360 | JSON float to be decoded. By default, this is equivalent to 361 | ``float(num_str)``. This can be used to use another datatype or parser 362 | for JSON floats (e.g. :class:`decimal.Decimal`). 363 | 364 | *parse_int*, if specified, will be called with the string of every 365 | JSON int to be decoded. By default, this is equivalent to 366 | ``int(num_str)``. This can be used to use another datatype or parser 367 | for JSON integers (e.g. :class:`float`). 368 | 369 | *parse_constant*, if specified, will be called with one of the 370 | following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This 371 | can be used to raise an exception if invalid JSON numbers are 372 | encountered. 373 | 374 | If *use_decimal* is true (default: ``False``) then it implies 375 | parse_float=decimal.Decimal for parity with ``dump``. 376 | 377 | To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` 378 | kwarg. 379 | 380 | """ 381 | if (cls is None and encoding is None and object_hook is None and 382 | parse_int is None and parse_float is None and 383 | parse_constant is None and object_pairs_hook is None 384 | and not use_decimal and not kw): 385 | return _default_decoder.decode(s) 386 | if cls is None: 387 | cls = JSONDecoder 388 | if object_hook is not None: 389 | kw['object_hook'] = object_hook 390 | if object_pairs_hook is not None: 391 | kw['object_pairs_hook'] = object_pairs_hook 392 | if parse_float is not None: 393 | kw['parse_float'] = parse_float 394 | if parse_int is not None: 395 | kw['parse_int'] = parse_int 396 | if parse_constant is not None: 397 | kw['parse_constant'] = parse_constant 398 | if use_decimal: 399 | if parse_float is not None: 400 | raise TypeError("use_decimal=True implies parse_float=Decimal") 401 | kw['parse_float'] = Decimal 402 | return cls(encoding=encoding, **kw).decode(s) 403 | 404 | 405 | def _toggle_speedups(enabled): 406 | import simplejson.decoder as dec 407 | import simplejson.encoder as enc 408 | import simplejson.scanner as scan 409 | c_make_encoder = _import_c_make_encoder() 410 | if enabled: 411 | dec.scanstring = dec.c_scanstring or dec.py_scanstring 412 | enc.c_make_encoder = c_make_encoder 413 | enc.encode_basestring_ascii = (enc.c_encode_basestring_ascii or 414 | enc.py_encode_basestring_ascii) 415 | scan.make_scanner = scan.c_make_scanner or scan.py_make_scanner 416 | else: 417 | dec.scanstring = dec.py_scanstring 418 | enc.c_make_encoder = None 419 | enc.encode_basestring_ascii = enc.py_encode_basestring_ascii 420 | scan.make_scanner = scan.py_make_scanner 421 | dec.make_scanner = scan.make_scanner 422 | global _default_decoder 423 | _default_decoder = JSONDecoder( 424 | encoding=None, 425 | object_hook=None, 426 | object_pairs_hook=None, 427 | ) 428 | global _default_encoder 429 | _default_encoder = JSONEncoder( 430 | skipkeys=False, 431 | ensure_ascii=True, 432 | check_circular=True, 433 | allow_nan=True, 434 | indent=None, 435 | separators=None, 436 | encoding='utf-8', 437 | default=None, 438 | ) 439 | -------------------------------------------------------------------------------- /localtunnel/packages/omnijson/packages/simplejson/decoder.py: -------------------------------------------------------------------------------- 1 | """Implementation of JSONDecoder 2 | """ 3 | import re 4 | import sys 5 | import struct 6 | 7 | from .scanner import make_scanner 8 | def _import_c_scanstring(): 9 | try: 10 | from simplejson._speedups import scanstring 11 | return scanstring 12 | except ImportError: 13 | return None 14 | c_scanstring = _import_c_scanstring() 15 | 16 | __all__ = ['JSONDecoder'] 17 | 18 | FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL 19 | 20 | def _floatconstants(): 21 | _BYTES = '7FF80000000000007FF0000000000000'.decode('hex') 22 | # The struct module in Python 2.4 would get frexp() out of range here 23 | # when an endian is specified in the format string. Fixed in Python 2.5+ 24 | if sys.byteorder != 'big': 25 | _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1] 26 | nan, inf = struct.unpack('dd', _BYTES) 27 | return nan, inf, -inf 28 | 29 | NaN, PosInf, NegInf = _floatconstants() 30 | 31 | 32 | class JSONDecodeError(ValueError): 33 | """Subclass of ValueError with the following additional properties: 34 | 35 | msg: The unformatted error message 36 | doc: The JSON document being parsed 37 | pos: The start index of doc where parsing failed 38 | end: The end index of doc where parsing failed (may be None) 39 | lineno: The line corresponding to pos 40 | colno: The column corresponding to pos 41 | endlineno: The line corresponding to end (may be None) 42 | endcolno: The column corresponding to end (may be None) 43 | 44 | """ 45 | def __init__(self, msg, doc, pos, end=None): 46 | ValueError.__init__(self, errmsg(msg, doc, pos, end=end)) 47 | self.msg = msg 48 | self.doc = doc 49 | self.pos = pos 50 | self.end = end 51 | self.lineno, self.colno = linecol(doc, pos) 52 | if end is not None: 53 | self.endlineno, self.endcolno = linecol(doc, end) 54 | else: 55 | self.endlineno, self.endcolno = None, None 56 | 57 | 58 | def linecol(doc, pos): 59 | lineno = doc.count('\n', 0, pos) + 1 60 | if lineno == 1: 61 | colno = pos 62 | else: 63 | colno = pos - doc.rindex('\n', 0, pos) 64 | return lineno, colno 65 | 66 | 67 | def errmsg(msg, doc, pos, end=None): 68 | # Note that this function is called from _speedups 69 | lineno, colno = linecol(doc, pos) 70 | if end is None: 71 | #fmt = '{0}: line {1} column {2} (char {3})' 72 | #return fmt.format(msg, lineno, colno, pos) 73 | fmt = '%s: line %d column %d (char %d)' 74 | return fmt % (msg, lineno, colno, pos) 75 | endlineno, endcolno = linecol(doc, end) 76 | #fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})' 77 | #return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end) 78 | fmt = '%s: line %d column %d - line %d column %d (char %d - %d)' 79 | return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end) 80 | 81 | 82 | _CONSTANTS = { 83 | '-Infinity': NegInf, 84 | 'Infinity': PosInf, 85 | 'NaN': NaN, 86 | } 87 | 88 | STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) 89 | BACKSLASH = { 90 | '"': u'"', '\\': u'\\', '/': u'/', 91 | 'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t', 92 | } 93 | 94 | DEFAULT_ENCODING = "utf-8" 95 | 96 | def py_scanstring(s, end, encoding=None, strict=True, 97 | _b=BACKSLASH, _m=STRINGCHUNK.match): 98 | """Scan the string s for a JSON string. End is the index of the 99 | character in s after the quote that started the JSON string. 100 | Unescapes all valid JSON string escape sequences and raises ValueError 101 | on attempt to decode an invalid string. If strict is False then literal 102 | control characters are allowed in the string. 103 | 104 | Returns a tuple of the decoded string and the index of the character in s 105 | after the end quote.""" 106 | if encoding is None: 107 | encoding = DEFAULT_ENCODING 108 | chunks = [] 109 | _append = chunks.append 110 | begin = end - 1 111 | while 1: 112 | chunk = _m(s, end) 113 | if chunk is None: 114 | raise JSONDecodeError( 115 | "Unterminated string starting at", s, begin) 116 | end = chunk.end() 117 | content, terminator = chunk.groups() 118 | # Content is contains zero or more unescaped string characters 119 | if content: 120 | if not isinstance(content, unicode): 121 | content = unicode(content, encoding) 122 | _append(content) 123 | # Terminator is the end of string, a literal control character, 124 | # or a backslash denoting that an escape sequence follows 125 | if terminator == '"': 126 | break 127 | elif terminator != '\\': 128 | if strict: 129 | msg = "Invalid control character %r at" % (terminator,) 130 | #msg = "Invalid control character {0!r} at".format(terminator) 131 | raise JSONDecodeError(msg, s, end) 132 | else: 133 | _append(terminator) 134 | continue 135 | try: 136 | esc = s[end] 137 | except IndexError: 138 | raise JSONDecodeError( 139 | "Unterminated string starting at", s, begin) 140 | # If not a unicode escape sequence, must be in the lookup table 141 | if esc != 'u': 142 | try: 143 | char = _b[esc] 144 | except KeyError: 145 | msg = "Invalid \\escape: " + repr(esc) 146 | raise JSONDecodeError(msg, s, end) 147 | end += 1 148 | else: 149 | # Unicode escape sequence 150 | esc = s[end + 1:end + 5] 151 | next_end = end + 5 152 | if len(esc) != 4: 153 | msg = "Invalid \\uXXXX escape" 154 | raise JSONDecodeError(msg, s, end) 155 | uni = int(esc, 16) 156 | # Check for surrogate pair on UCS-4 systems 157 | if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535: 158 | msg = "Invalid \\uXXXX\\uXXXX surrogate pair" 159 | if not s[end + 5:end + 7] == '\\u': 160 | raise JSONDecodeError(msg, s, end) 161 | esc2 = s[end + 7:end + 11] 162 | if len(esc2) != 4: 163 | raise JSONDecodeError(msg, s, end) 164 | uni2 = int(esc2, 16) 165 | uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) 166 | next_end += 6 167 | char = unichr(uni) 168 | end = next_end 169 | # Append the unescaped character 170 | _append(char) 171 | return u''.join(chunks), end 172 | 173 | 174 | # Use speedup if available 175 | scanstring = c_scanstring or py_scanstring 176 | 177 | WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS) 178 | WHITESPACE_STR = ' \t\n\r' 179 | 180 | def JSONObject((s, end), encoding, strict, scan_once, object_hook, 181 | object_pairs_hook, memo=None, 182 | _w=WHITESPACE.match, _ws=WHITESPACE_STR): 183 | # Backwards compatibility 184 | if memo is None: 185 | memo = {} 186 | memo_get = memo.setdefault 187 | pairs = [] 188 | # Use a slice to prevent IndexError from being raised, the following 189 | # check will raise a more specific ValueError if the string is empty 190 | nextchar = s[end:end + 1] 191 | # Normally we expect nextchar == '"' 192 | if nextchar != '"': 193 | if nextchar in _ws: 194 | end = _w(s, end).end() 195 | nextchar = s[end:end + 1] 196 | # Trivial empty object 197 | if nextchar == '}': 198 | if object_pairs_hook is not None: 199 | result = object_pairs_hook(pairs) 200 | return result, end + 1 201 | pairs = {} 202 | if object_hook is not None: 203 | pairs = object_hook(pairs) 204 | return pairs, end + 1 205 | elif nextchar != '"': 206 | raise JSONDecodeError("Expecting property name", s, end) 207 | end += 1 208 | while True: 209 | key, end = scanstring(s, end, encoding, strict) 210 | key = memo_get(key, key) 211 | 212 | # To skip some function call overhead we optimize the fast paths where 213 | # the JSON key separator is ": " or just ":". 214 | if s[end:end + 1] != ':': 215 | end = _w(s, end).end() 216 | if s[end:end + 1] != ':': 217 | raise JSONDecodeError("Expecting : delimiter", s, end) 218 | 219 | end += 1 220 | 221 | try: 222 | if s[end] in _ws: 223 | end += 1 224 | if s[end] in _ws: 225 | end = _w(s, end + 1).end() 226 | except IndexError: 227 | pass 228 | 229 | try: 230 | value, end = scan_once(s, end) 231 | except StopIteration: 232 | raise JSONDecodeError("Expecting object", s, end) 233 | pairs.append((key, value)) 234 | 235 | try: 236 | nextchar = s[end] 237 | if nextchar in _ws: 238 | end = _w(s, end + 1).end() 239 | nextchar = s[end] 240 | except IndexError: 241 | nextchar = '' 242 | end += 1 243 | 244 | if nextchar == '}': 245 | break 246 | elif nextchar != ',': 247 | raise JSONDecodeError("Expecting , delimiter", s, end - 1) 248 | 249 | try: 250 | nextchar = s[end] 251 | if nextchar in _ws: 252 | end += 1 253 | nextchar = s[end] 254 | if nextchar in _ws: 255 | end = _w(s, end + 1).end() 256 | nextchar = s[end] 257 | except IndexError: 258 | nextchar = '' 259 | 260 | end += 1 261 | if nextchar != '"': 262 | raise JSONDecodeError("Expecting property name", s, end - 1) 263 | 264 | if object_pairs_hook is not None: 265 | result = object_pairs_hook(pairs) 266 | return result, end 267 | pairs = dict(pairs) 268 | if object_hook is not None: 269 | pairs = object_hook(pairs) 270 | return pairs, end 271 | 272 | def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): 273 | values = [] 274 | nextchar = s[end:end + 1] 275 | if nextchar in _ws: 276 | end = _w(s, end + 1).end() 277 | nextchar = s[end:end + 1] 278 | # Look-ahead for trivial empty array 279 | if nextchar == ']': 280 | return values, end + 1 281 | _append = values.append 282 | while True: 283 | try: 284 | value, end = scan_once(s, end) 285 | except StopIteration: 286 | raise JSONDecodeError("Expecting object", s, end) 287 | _append(value) 288 | nextchar = s[end:end + 1] 289 | if nextchar in _ws: 290 | end = _w(s, end + 1).end() 291 | nextchar = s[end:end + 1] 292 | end += 1 293 | if nextchar == ']': 294 | break 295 | elif nextchar != ',': 296 | raise JSONDecodeError("Expecting , delimiter", s, end) 297 | 298 | try: 299 | if s[end] in _ws: 300 | end += 1 301 | if s[end] in _ws: 302 | end = _w(s, end + 1).end() 303 | except IndexError: 304 | pass 305 | 306 | return values, end 307 | 308 | class JSONDecoder(object): 309 | """Simple JSON decoder 310 | 311 | Performs the following translations in decoding by default: 312 | 313 | +---------------+-------------------+ 314 | | JSON | Python | 315 | +===============+===================+ 316 | | object | dict | 317 | +---------------+-------------------+ 318 | | array | list | 319 | +---------------+-------------------+ 320 | | string | unicode | 321 | +---------------+-------------------+ 322 | | number (int) | int, long | 323 | +---------------+-------------------+ 324 | | number (real) | float | 325 | +---------------+-------------------+ 326 | | true | True | 327 | +---------------+-------------------+ 328 | | false | False | 329 | +---------------+-------------------+ 330 | | null | None | 331 | +---------------+-------------------+ 332 | 333 | It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as 334 | their corresponding ``float`` values, which is outside the JSON spec. 335 | 336 | """ 337 | 338 | def __init__(self, encoding=None, object_hook=None, parse_float=None, 339 | parse_int=None, parse_constant=None, strict=True, 340 | object_pairs_hook=None): 341 | """ 342 | *encoding* determines the encoding used to interpret any 343 | :class:`str` objects decoded by this instance (``'utf-8'`` by 344 | default). It has no effect when decoding :class:`unicode` objects. 345 | 346 | Note that currently only encodings that are a superset of ASCII work, 347 | strings of other encodings should be passed in as :class:`unicode`. 348 | 349 | *object_hook*, if specified, will be called with the result of every 350 | JSON object decoded and its return value will be used in place of the 351 | given :class:`dict`. This can be used to provide custom 352 | deserializations (e.g. to support JSON-RPC class hinting). 353 | 354 | *object_pairs_hook* is an optional function that will be called with 355 | the result of any object literal decode with an ordered list of pairs. 356 | The return value of *object_pairs_hook* will be used instead of the 357 | :class:`dict`. This feature can be used to implement custom decoders 358 | that rely on the order that the key and value pairs are decoded (for 359 | example, :func:`collections.OrderedDict` will remember the order of 360 | insertion). If *object_hook* is also defined, the *object_pairs_hook* 361 | takes priority. 362 | 363 | *parse_float*, if specified, will be called with the string of every 364 | JSON float to be decoded. By default, this is equivalent to 365 | ``float(num_str)``. This can be used to use another datatype or parser 366 | for JSON floats (e.g. :class:`decimal.Decimal`). 367 | 368 | *parse_int*, if specified, will be called with the string of every 369 | JSON int to be decoded. By default, this is equivalent to 370 | ``int(num_str)``. This can be used to use another datatype or parser 371 | for JSON integers (e.g. :class:`float`). 372 | 373 | *parse_constant*, if specified, will be called with one of the 374 | following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This 375 | can be used to raise an exception if invalid JSON numbers are 376 | encountered. 377 | 378 | *strict* controls the parser's behavior when it encounters an 379 | invalid control character in a string. The default setting of 380 | ``True`` means that unescaped control characters are parse errors, if 381 | ``False`` then control characters will be allowed in strings. 382 | 383 | """ 384 | self.encoding = encoding 385 | self.object_hook = object_hook 386 | self.object_pairs_hook = object_pairs_hook 387 | self.parse_float = parse_float or float 388 | self.parse_int = parse_int or int 389 | self.parse_constant = parse_constant or _CONSTANTS.__getitem__ 390 | self.strict = strict 391 | self.parse_object = JSONObject 392 | self.parse_array = JSONArray 393 | self.parse_string = scanstring 394 | self.memo = {} 395 | self.scan_once = make_scanner(self) 396 | 397 | def decode(self, s, _w=WHITESPACE.match): 398 | """Return the Python representation of ``s`` (a ``str`` or ``unicode`` 399 | instance containing a JSON document) 400 | 401 | """ 402 | obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 403 | end = _w(s, end).end() 404 | if end != len(s): 405 | raise JSONDecodeError("Extra data", s, end, len(s)) 406 | return obj 407 | 408 | def raw_decode(self, s, idx=0): 409 | """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` 410 | beginning with a JSON document) and return a 2-tuple of the Python 411 | representation and the index in ``s`` where the document ended. 412 | 413 | This can be used to decode a JSON document from a string that may 414 | have extraneous data at the end. 415 | 416 | """ 417 | try: 418 | obj, end = self.scan_once(s, idx) 419 | except StopIteration: 420 | raise JSONDecodeError("No JSON object could be decoded", s, idx) 421 | return obj, end 422 | -------------------------------------------------------------------------------- /localtunnel/packages/omnijson/packages/simplejson/encoder.py: -------------------------------------------------------------------------------- 1 | """Implementation of JSONEncoder 2 | """ 3 | import re 4 | from decimal import Decimal 5 | 6 | def _import_speedups(): 7 | try: 8 | from simplejson import _speedups 9 | return _speedups.encode_basestring_ascii, _speedups.make_encoder 10 | except ImportError: 11 | return None, None 12 | c_encode_basestring_ascii, c_make_encoder = _import_speedups() 13 | 14 | from .decoder import PosInf 15 | 16 | ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]') 17 | ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') 18 | HAS_UTF8 = re.compile(r'[\x80-\xff]') 19 | ESCAPE_DCT = { 20 | '\\': '\\\\', 21 | '"': '\\"', 22 | '\b': '\\b', 23 | '\f': '\\f', 24 | '\n': '\\n', 25 | '\r': '\\r', 26 | '\t': '\\t', 27 | } 28 | for i in range(0x20): 29 | #ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) 30 | ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) 31 | 32 | FLOAT_REPR = repr 33 | 34 | def encode_basestring(s): 35 | """Return a JSON representation of a Python string 36 | 37 | """ 38 | if isinstance(s, str) and HAS_UTF8.search(s) is not None: 39 | s = s.decode('utf-8') 40 | def replace(match): 41 | return ESCAPE_DCT[match.group(0)] 42 | return u'"' + ESCAPE.sub(replace, s) + u'"' 43 | 44 | 45 | def py_encode_basestring_ascii(s): 46 | """Return an ASCII-only JSON representation of a Python string 47 | 48 | """ 49 | if isinstance(s, str) and HAS_UTF8.search(s) is not None: 50 | s = s.decode('utf-8') 51 | def replace(match): 52 | s = match.group(0) 53 | try: 54 | return ESCAPE_DCT[s] 55 | except KeyError: 56 | n = ord(s) 57 | if n < 0x10000: 58 | #return '\\u{0:04x}'.format(n) 59 | return '\\u%04x' % (n,) 60 | else: 61 | # surrogate pair 62 | n -= 0x10000 63 | s1 = 0xd800 | ((n >> 10) & 0x3ff) 64 | s2 = 0xdc00 | (n & 0x3ff) 65 | #return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) 66 | return '\\u%04x\\u%04x' % (s1, s2) 67 | return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' 68 | 69 | 70 | encode_basestring_ascii = ( 71 | c_encode_basestring_ascii or py_encode_basestring_ascii) 72 | 73 | class JSONEncoder(object): 74 | """Extensible JSON encoder for Python data structures. 75 | 76 | Supports the following objects and types by default: 77 | 78 | +-------------------+---------------+ 79 | | Python | JSON | 80 | +===================+===============+ 81 | | dict | object | 82 | +-------------------+---------------+ 83 | | list, tuple | array | 84 | +-------------------+---------------+ 85 | | str, unicode | string | 86 | +-------------------+---------------+ 87 | | int, long, float | number | 88 | +-------------------+---------------+ 89 | | True | true | 90 | +-------------------+---------------+ 91 | | False | false | 92 | +-------------------+---------------+ 93 | | None | null | 94 | +-------------------+---------------+ 95 | 96 | To extend this to recognize other objects, subclass and implement a 97 | ``.default()`` method with another method that returns a serializable 98 | object for ``o`` if possible, otherwise it should call the superclass 99 | implementation (to raise ``TypeError``). 100 | 101 | """ 102 | item_separator = ', ' 103 | key_separator = ': ' 104 | def __init__(self, skipkeys=False, ensure_ascii=True, 105 | check_circular=True, allow_nan=True, sort_keys=False, 106 | indent=None, separators=None, encoding='utf-8', default=None, 107 | use_decimal=False): 108 | """Constructor for JSONEncoder, with sensible defaults. 109 | 110 | If skipkeys is false, then it is a TypeError to attempt 111 | encoding of keys that are not str, int, long, float or None. If 112 | skipkeys is True, such items are simply skipped. 113 | 114 | If ensure_ascii is true, the output is guaranteed to be str 115 | objects with all incoming unicode characters escaped. If 116 | ensure_ascii is false, the output will be unicode object. 117 | 118 | If check_circular is true, then lists, dicts, and custom encoded 119 | objects will be checked for circular references during encoding to 120 | prevent an infinite recursion (which would cause an OverflowError). 121 | Otherwise, no such check takes place. 122 | 123 | If allow_nan is true, then NaN, Infinity, and -Infinity will be 124 | encoded as such. This behavior is not JSON specification compliant, 125 | but is consistent with most JavaScript based encoders and decoders. 126 | Otherwise, it will be a ValueError to encode such floats. 127 | 128 | If sort_keys is true, then the output of dictionaries will be 129 | sorted by key; this is useful for regression tests to ensure 130 | that JSON serializations can be compared on a day-to-day basis. 131 | 132 | If indent is a string, then JSON array elements and object members 133 | will be pretty-printed with a newline followed by that string repeated 134 | for each level of nesting. ``None`` (the default) selects the most compact 135 | representation without any newlines. For backwards compatibility with 136 | versions of simplejson earlier than 2.1.0, an integer is also accepted 137 | and is converted to a string with that many spaces. 138 | 139 | If specified, separators should be a (item_separator, key_separator) 140 | tuple. The default is (', ', ': '). To get the most compact JSON 141 | representation you should specify (',', ':') to eliminate whitespace. 142 | 143 | If specified, default is a function that gets called for objects 144 | that can't otherwise be serialized. It should return a JSON encodable 145 | version of the object or raise a ``TypeError``. 146 | 147 | If encoding is not None, then all input strings will be 148 | transformed into unicode using that encoding prior to JSON-encoding. 149 | The default is UTF-8. 150 | 151 | If use_decimal is true (not the default), ``decimal.Decimal`` will 152 | be supported directly by the encoder. For the inverse, decode JSON 153 | with ``parse_float=decimal.Decimal``. 154 | 155 | """ 156 | 157 | self.skipkeys = skipkeys 158 | self.ensure_ascii = ensure_ascii 159 | self.check_circular = check_circular 160 | self.allow_nan = allow_nan 161 | self.sort_keys = sort_keys 162 | self.use_decimal = use_decimal 163 | if isinstance(indent, (int, long)): 164 | indent = ' ' * indent 165 | self.indent = indent 166 | if separators is not None: 167 | self.item_separator, self.key_separator = separators 168 | elif indent is not None: 169 | self.item_separator = ',' 170 | if default is not None: 171 | self.default = default 172 | self.encoding = encoding 173 | 174 | def default(self, o): 175 | """Implement this method in a subclass such that it returns 176 | a serializable object for ``o``, or calls the base implementation 177 | (to raise a ``TypeError``). 178 | 179 | For example, to support arbitrary iterators, you could 180 | implement default like this:: 181 | 182 | def default(self, o): 183 | try: 184 | iterable = iter(o) 185 | except TypeError: 186 | pass 187 | else: 188 | return list(iterable) 189 | return JSONEncoder.default(self, o) 190 | 191 | """ 192 | raise TypeError(repr(o) + " is not JSON serializable") 193 | 194 | def encode(self, o): 195 | """Return a JSON string representation of a Python data structure. 196 | 197 | >>> from simplejson import JSONEncoder 198 | >>> JSONEncoder().encode({"foo": ["bar", "baz"]}) 199 | '{"foo": ["bar", "baz"]}' 200 | 201 | """ 202 | # This is for extremely simple cases and benchmarks. 203 | if isinstance(o, basestring): 204 | if isinstance(o, str): 205 | _encoding = self.encoding 206 | if (_encoding is not None 207 | and not (_encoding == 'utf-8')): 208 | o = o.decode(_encoding) 209 | if self.ensure_ascii: 210 | return encode_basestring_ascii(o) 211 | else: 212 | return encode_basestring(o) 213 | # This doesn't pass the iterator directly to ''.join() because the 214 | # exceptions aren't as detailed. The list call should be roughly 215 | # equivalent to the PySequence_Fast that ''.join() would do. 216 | chunks = self.iterencode(o, _one_shot=True) 217 | if not isinstance(chunks, (list, tuple)): 218 | chunks = list(chunks) 219 | if self.ensure_ascii: 220 | return ''.join(chunks) 221 | else: 222 | return u''.join(chunks) 223 | 224 | def iterencode(self, o, _one_shot=False): 225 | """Encode the given object and yield each string 226 | representation as available. 227 | 228 | For example:: 229 | 230 | for chunk in JSONEncoder().iterencode(bigobject): 231 | mysocket.write(chunk) 232 | 233 | """ 234 | if self.check_circular: 235 | markers = {} 236 | else: 237 | markers = None 238 | if self.ensure_ascii: 239 | _encoder = encode_basestring_ascii 240 | else: 241 | _encoder = encode_basestring 242 | if self.encoding != 'utf-8': 243 | def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): 244 | if isinstance(o, str): 245 | o = o.decode(_encoding) 246 | return _orig_encoder(o) 247 | 248 | def floatstr(o, allow_nan=self.allow_nan, 249 | _repr=FLOAT_REPR, _inf=PosInf, _neginf=-PosInf): 250 | # Check for specials. Note that this type of test is processor 251 | # and/or platform-specific, so do tests which don't depend on 252 | # the internals. 253 | 254 | if o != o: 255 | text = 'NaN' 256 | elif o == _inf: 257 | text = 'Infinity' 258 | elif o == _neginf: 259 | text = '-Infinity' 260 | else: 261 | return _repr(o) 262 | 263 | if not allow_nan: 264 | raise ValueError( 265 | "Out of range float values are not JSON compliant: " + 266 | repr(o)) 267 | 268 | return text 269 | 270 | 271 | key_memo = {} 272 | if (_one_shot and c_make_encoder is not None 273 | and self.indent is None): 274 | _iterencode = c_make_encoder( 275 | markers, self.default, _encoder, self.indent, 276 | self.key_separator, self.item_separator, self.sort_keys, 277 | self.skipkeys, self.allow_nan, key_memo, self.use_decimal) 278 | else: 279 | _iterencode = _make_iterencode( 280 | markers, self.default, _encoder, self.indent, floatstr, 281 | self.key_separator, self.item_separator, self.sort_keys, 282 | self.skipkeys, _one_shot, self.use_decimal) 283 | try: 284 | return _iterencode(o, 0) 285 | finally: 286 | key_memo.clear() 287 | 288 | 289 | class JSONEncoderForHTML(JSONEncoder): 290 | """An encoder that produces JSON safe to embed in HTML. 291 | 292 | To embed JSON content in, say, a script tag on a web page, the 293 | characters &, < and > should be escaped. They cannot be escaped 294 | with the usual entities (e.g. &) because they are not expanded 295 | within