fill in remaining docstrings
diff --git a/json5/__init__.py b/json5/__init__.py index 0e8f774..b1bf412 100644 --- a/json5/__init__.py +++ b/json5/__init__.py
@@ -12,15 +12,69 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""A pure Python implementation of the JSON5 configuration language.""" +"""A pure Python implementation of the JSON5 configuration language. + +`JSON5 <https://www.json5.org>`_ extends the +`JSON <http://www.json.org>`_ data interchange format to make it more +usable as a configuration language: + +* JavaScript-style comments (both single and multi-line) are legal. + +* Object keys may be unquoted if they are legal ECMAScript identifiers + +* Objects and arrays may end with trailing commas. + +* Strings can be single-quoted, and multi-line string literals are allowed. + +There are a few other more minor extensions to JSON; see the above pages +for the full details. + +This project implements a reader and writer implementation for Python; +mirroring the +`standard JSON package <https://docs.python.org/library/json.html>`_'s +API. + +Python values are mapped to JSON5 values as follows: + +Python JSON5 +------ ----- +None null +True true +False false +float('inf') Infinity +float('nan') NaN +float('-inf') -Infinity +int/float Number +list array +dict object + +The ``tool`` module implements a command-line tool that can be used to +convert between and reformat JSON and JSON5. + + $ echo '{"foo": "bar"}' | python -m json5.tool + {foo: "bar"} + $ echo '{"foo": "bar"}' | python -m json5.tool --compact + {foo:"bar"} + $ echo '[1, 2]' | python -m json5.tool --indent=2 --trailing-commas + [ + 1, + 2, + ] + $ echo '{foo: "bar"}' | python -m json5.tool --json + {"foo": "bar"} + $ + +""" from . import tool -from .lib import load, loads, dump, dumps +from .lib import Decoder, Encoder, dump, dumps, load, loads, dump, dumps from .version import VERSION __all__ = [ 'VERSION', + 'Decoder', + 'Encoder', 'dump', 'dumps', 'load',
diff --git a/json5/lib.py b/json5/lib.py index 652fc51..cc0994c 100644 --- a/json5/lib.py +++ b/json5/lib.py
@@ -25,24 +25,66 @@ from .parser import Parser -def load(fp, **kwargs): +def load(fp, cls=None, encoding='utf-8', object_hook=None, parse_float=None, + parse_int=None, parse_constant=None, object_pairs_hook=None): """Deserialize ``fp`` (a ``.read()``-supporting file-like object - containing a JSON document) to a Python object.""" - return loads(fp.read()) + containing a JSON document) to a Python object. + + For help on the keyword args, see the docstring for json5.loads().""" + + return loads(fp.read(), cls=cls, encoding=encoding, + object_hook=object_hook, parse_float=parse_float, + parse_int=parse_int, parse_constant=parse_constant, + object_pairs_hook=object_pairs_hook) -def loads(s, **kwargs): +def loads(s, cls=None, encoding='utf-8', object_hook=None, parse_float=None, + parse_int=None, parse_constant=None, object_pairs_hook=None): """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a - JSON5 document) to a Python object.""" - cls = kwargs.pop('cls', Decoder) - return cls(**kwargs).decode(s) + JSON5 document) to a Python object. + + If ``cls`` is specified, it will be used to encode the object instead + of the standard Decoder class. + + In Python2, ``encoding`` determines the encoding used to used to + interpret an object of type ``str``; if the object is a unicode + string, the encoding is ignored. In Python3, the same applies if the + object is a byte string and not a string. + + If ``object_hook`` is not none, it will be used to convert an dict + into a custom Python value. + + If ``parse_float`` is not none, it will be used to convert the + string representation of a floating-point number into a custom + Python value. + + If ``parse_int`` is not none, it will be used to convert the string + representation of an integer number into a custom Python value. + + If ``parse_constant`` is not none, it will be used to convert the + string representation of a Nan, -Infinity, and Infinity JSON5 + values into Python values. + + If ``object_pairs_hook`` is not none, it will be used to convert an + object into a custom Python value; it is passed a list of key-value + pairs. If object_pairs_hook and object_hook are both passed, + object_pairs_hook takes precedence. + """ + cls = cls or Decoder + return cls(encoding=encoding, object_hook=object_hook, + parse_float=parse_float, parse_int=parse_int, + parse_constant=parse_constant, + object_pairs_hook=object_pairs_hook).decode(s) class Decoder(object): + """Simple JSON5 <http://json5.org> decoder.""" - def __init__(self, encoding=None, object_hook=None, parse_float=None, + def __init__(self, encoding='utf-8', object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None): - self.encoding = encoding or 'utf-8' + 'For help on the keyword args, see the docstring for json5.loads().' + + self.encoding = encoding self.parse_float = parse_float or float self.parse_int = parse_int or self._default_parse_int self.parse_constant = parse_constant or self._default_parse_constant @@ -55,6 +97,7 @@ self.object_pairs_hook = dict def decode(self, s): + 'Returns the string decoded into a Python object.' if _is_python2: decodable_type = type('') else: @@ -100,16 +143,94 @@ raise Exception('unknown ast node: ' + repr(ast_node)) -def dump(obj, fp, **kwargs): + +def dump(obj, fp, cls=None, skipkeys=False, ensure_ascii=True, + check_circular=True, allow_nan=True, indent=None, separators=None, + encoding='utf-8', default=None, sort_keys=False, + compact=False, as_json=False, trailing_commas=False): """Serialize ``obj`` to a JSON5-formatted stream to ``fp`` (a ``.write()``- - supporting file-like object).""" - fp.write(dumps(obj, **kwargs)) + supporting file-like object). + + For help on the keyword args, see the docstring for json5.dumps.""" + + fp.write(dumps(obj, cls=cls, skipkeys=skipkeys, ensure_ascii=ensure_ascii, + check_circular=check_circular, allow_nan=allow_nan, + indent=indent, separators=separators, encoding=encoding, + default=default, sort_keys=sort_keys, compact=compact, + as_json=as_json, trailing_commas=trailing_commas)) -def dumps(obj, **kwargs): - """Serialize ``obj`` to a JSON5-formatted string.""" - cls = kwargs.pop('cls', Encoder) - return cls(**kwargs).encode(obj) +def dumps(obj, cls=None, skipkeys=False, ensure_ascii=True, + check_circular=True, allow_nan=True, indent=None, separators=None, + encoding='utf-8', default=None, sort_keys=False, + compact=False, as_json=False, trailing_commas=False): + """Returns ``obj`` serialized as a JSON5-formatted string. + + If ``cls`` is specified, it will be used to encode the object instead + of the standard Encoder class. + + ``skipkeys``, if true, will tell the encoder to skip any keys in a + dict that are not of type str, int, float, or None; if false (the + default), a TypeError will be raised instead. + + If ``ensure_ascii`` is true (the default), all non-ASCII characters + in the output are encoded as \\uXXXX sequences instead; if false, the + string will be rendered into unicode instead. + + If ``check_circular`` is true (the default), if the encoder tries to + encode an object that contains circular references, a ValueError will + be raised; if it is false, the encoder will be slightly faster, but + unpredictable things will happen if an object contains cycles. + + If ``allow_nan`` is true (the default), floating point values of NaN, + -Infinity, and +Infinity are allowed, otherwise a ValueError is + raised. + + If ``indent`` is None (the default), the encoding will contain no + newlines or indentation; if indent is zero, the encoding will contain + newlines but not be indented and if indent is greater than zero, each + line will be indented by that many spaces as appropriate. + + If ``separators`` is non-None, it must be a tuple of two strings, the + first of which is used to separate items in objects and lists, and the + second of which is used to separate a key from its value in an object. + If it is None, the default value of (', ', ': ') will be used (unless + compact=True is passed, see below). + + In Python2, ``encoding`` determines the encoding used to used to + interpret an object of type ``str``; if the object is a unicode string, + the encoding is ignored. In Python3, the same applies if the object is + a byte string instead of a string. + + If ``default`` is non-None, it will be invoked whenever the object is + of a non-standard type; it must return an equivalent standard + representation. + + If ``sort_keys`` is true; an object will be encoded with its keys and + values in lexicographic order; if false, the keys may show up in an + arbitrary order. + + If ``compact`` is true, the object will be rendered in the most + compact way possible; this is the same as passing + separators=(',',':'), indent=None, as_json=False, and + trailing_commas=False. However, if any of those arguments are also + passed, they will override the compact value. This field is an + extension to the standard JSON API. + + If ``as_json`` is true, the object will be encoded as JSON, not + JSON5. This is an extension to the standard JSON API. + + If ``trailing_commas`` is true, then objects and lists will be + encoded with a comma on the end. For example, you'd get [1,2,] + instead of [1,2]. This is an extension to the standard JSON API. + """ + + cls = cls or Encoder + return cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, + check_circular=check_circular, allow_nan=allow_nan, + indent=indent, separators=separators, encoding=encoding, + default=default, sort_keys=sort_keys, compact=compact, + as_json=as_json, trailing_commas=trailing_commas).encode(obj) squote = "'" @@ -118,6 +239,7 @@ class Encoder(object): + """Simple JSON5 <http://json5.org> encoder.""" def __init__(self, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, @@ -125,6 +247,8 @@ encoding='utf-8', default=None, sort_keys=False, compact=False, as_json=False, trailing_commas=False): + 'For help on the keyword args, see the docstring for json5.dumps().' + self.skipkeys = skipkeys self.ensure_ascii = ensure_ascii self.check_circular = check_circular @@ -158,6 +282,8 @@ self._indent_level = 0 def encode(self, obj): + """Return the obj serialized into a string.""" + t = type(obj) if obj is True: return 'true'
diff --git a/json5/tool.py b/json5/tool.py index 576fc00..16be394 100644 --- a/json5/tool.py +++ b/json5/tool.py
@@ -14,11 +14,20 @@ """Command-line tool to validate and pretty-print JSON5. -Usage:: +Usage: - $ echo '{foo:"bar"}' | python -m json5.tool + $ echo '{"foo": "bar"}' | python -m json5.tool {foo: "bar"} + $ echo '{"foo": "bar"}' | python -m json5.tool --compact + {foo:"bar"} + $ echo '{"foo": "bar"}' | python -m json5.tool --indent=2 --trailing-commas + { + foo: "bar", + } + $ echo '{foo: "bar"}' | python -m json5.tool --json + {"foo": "bar"} $ + """ import os