### Set up development environment on macOS using uv Source: https://github.com/dpranke/pyjson5/blob/main/README.md Shell commands for macOS development environment setup using `uv` and the `run` script. The commands install `uv`, clone the repository, move into its directory, and source the development environment activation command produced by `./run devenv`. ```shell $ brew install uv $ git clone https://github.com/dpranke/pyjson5 $ cd pyjson5 $ source $(./run devenv) # To activate a venv w/ all the needed dev tools. ``` -------------------------------- ### CLI usage examples for python -m json5 Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.tool.md Shows common command-line invocations: reading from stdin, using --as-json, inline input with --indent and --quote-style, --version, and an error case with --bogus. The last example shows the usage error message and the exit code check. ```bash $ echo '{foo:"bar"}' | python -m json5 { foo: "bar", } ``` ```bash $ echo '{foo:"bar"}' | python -m json5 --as-json { "foo": "bar" } ``` ```bash $ python -m json5 -c '{a: 1}' --indent 0 --quote-style always_single { a: 1, } ``` ```bash $ python -m json5 --version 0.17.3 ``` ```bash $ python -m json5 --bogus usage: json5 [options] [FILE] -h/--help for help error: unrecognized arguments: --bogus $ echo $? # 2 ``` -------------------------------- ### Host usage example Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.host.md Shows how to instantiate Host and use its print, write_text_file, and read_text_file methods. The print writes 'hello\n' to stdout and flushes; write_text_file writes UTF-8 content; read_text_file reads it back. ```python from json5.host import Host host = Host() host.print('hello') # writes "hello\n" to stdout, flushed host.write_text_file('/tmp/out.json5', '{a: 1}') print(host.read_text_file('/tmp/out.json5')) # {a: 1} ``` -------------------------------- ### json5.load usage example Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.parsing.md Demonstrates loading JSON5 from a StringIO and BytesIO, including rejecting duplicate keys with allow_duplicate_keys=False. The output shows the parsed dict and the ValueError message. ```python import io import json5 fp = io.StringIO('{hello: "world", nums: [1, 2, 3,]}') data = json5.load(fp) print(data) # {'hello': 'world', 'nums': [1, 2, 3]} # Reject duplicate keys; byte input with explicit encoding. try: json5.load(io.BytesIO(b'{a: 1, a: 2}'), allow_duplicate_keys=False) except ValueError as e: print(e) # Duplicate key "a" found in object ``` -------------------------------- ### json5.dumps usage examples Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.encoding.md Examples of using json5.dumps with various options: indent for pretty-printing, quote_keys and trailing_commas for JSON-compatible output, and error handling for non-serializable values. ```python import json5 print(json5.dumps({'foo': 'bar', 'baz': 'quux'}, indent=2)) # { # foo: "bar", # baz: "quux", # } # Identical to json.dumps output: print(json5.dumps({'a': 1, 'b': [1, 2]}, quote_keys=True, trailing_commas=False, allow_duplicate_keys=True)) # {"a": 1, "b": [1, 2]} # Error handling: non-serializable value. try: json5.dumps({1, 2}) except TypeError as e: print(e) # {1, 2} is not JSON5 serializable ``` -------------------------------- ### Parser.__init__(msg, fname, pos=0) Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.parser.md Constructs a Parser instance with the input text, a name for error messages, and an optional starting position. Sets up internal state for parsing. ```APIDOC ## Parser.__init__(msg, fname, pos=0) ### Description Constructs a Parser instance with the input text, a name for error messages, and an optional starting position. Sets up internal state for parsing. ### Method Constructor ### Signature ```python def __init__(self, msg, fname, pos=0): ``` ### Parameters - **msg** (str) - Required - The text to parse. - **fname** (str) - Required - A name used in error messages (e.g. the file name); `json5.parse()` passes `''`. - **pos** (int) - Optional - Zero-based offset into `msg` to begin parsing at. Default: `0`. ### Instance State Set at construction: `msg` (input text), `end` (`len(msg)`), `fname`, `val` (last matched value, `None` initially), `pos` (current position), `failed` (bool), `errpos` (farthest error position), and internal `_scopes` / `_cache` / `_global_vars`. ``` -------------------------------- ### json5.loads usage examples Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.parsing.md Examples of using json5.loads: basic parsing with single-quoted strings and comments, a custom parse_int hook for hex literals, and strict=False to allow raw newlines inside strings. ```python import json5 d = json5.loads('{foo: 1, comment: "// not a comment"}') # strings can be single-quoted print(d) # {'foo': 1, 'comment': '// not a comment'} # Custom integer hook + strict=False (allow raw newlines inside strings). # Note: parse_int is also called with base=16 for hex literals like 0xff. def hexor(s, base=10): return int(s, base) print(json5.loads('0xff', parse_int=hexor)) # 255 print(json5.loads('"two\nlines"', strict=False)) # 'two\nlines' ``` -------------------------------- ### json5.dump usage example Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.encoding.md Demonstrates writing JSON5 to an in-memory StringIO buffer and to a file. The first call uses indent=0 and shows the output includes a trailing comma. The second writes to 'config.json5' with sort_keys=True. ```python import io import json5 buf = io.StringIO() json5.dump({'foo': 1}, buf, indent=0) print(repr(buf.getvalue())) # '{\nfoo: 1,\n}' with open('config.json5', 'w') as fp: json5.dump({'app': 'demo', 'port': 8080}, fp, sort_keys=True) ``` -------------------------------- ### Run presubmit checks with ./run presubmit Source: https://github.com/dpranke/pyjson5/blob/main/README.md Run all checks and tests at once via the `run` script. `presubmit` runs format, checks, tests, coverage, build, and publish --check in sequence, though it does not run `regen` because `glop` might not be installed. ```shell $ ./run presubmit ``` -------------------------------- ### json5.parse usage example with repeated extraction and error handling Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.parsing.md Shows how to use json5.parse to extract multiple values from a single string using start and consume_trailing=False, and how errors are returned as a tuple instead of raised. The example prints [1, 2, 3, 4] for the first part and None, error message, and position for the second. ```python import json5 # Repeatedly extract values from one string (works with consume_trailing=False). s = '1 2 3 4' values = [] start = 0 while True: v, err, pos = json5.parse(s, start=start, consume_trailing=False) if v: values.append(v) start = pos if start == len(s) or s[start:].isspace(): break continue raise ValueError(err) print(values) # [1, 2, 3, 4] # Error handling: the failure is returned, not raised. v, err, pos = json5.parse('[ ,]') print(v, err, pos) # None :1 Unexpected "," at column 3 2 # (position is the 0-based farthest error offset; column in the # message is 1-based) ``` -------------------------------- ### json5.tool.main (CLI) Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/configuration.md Documentation for the command-line interface tool. ```APIDOC ## CLI Tool ### Description Command-line interface for parsing JSON5 input and outputting JSON. Supports various formatting options and exit codes. ### Method CLI ### Endpoint `json5.tool.main` ### Parameters #### Options - **-V, --version** (flag) - Default: off - Print library version, exit 0. - **-c STR** (value) - Default: — - Inline JSON5 to parse. - **--as-json** (flag) - Default: off - JSON output: `--quote-keys --no-trailing-commas --quote-style always_double`. - **--indent** (value) - Default: `4` - Indent amount; `'None'` disables; non-integer strings used literally. - **--quote-keys / --no-quote-keys** (flag pair) - Default: off (unquoted id keys) - Quote / don't quote object keys. - **--trailing-commas / --no-trailing-commas** (flag pair) - Default: on - Add / suppress trailing commas. - **--strict / --no-strict** (flag pair) - Default: on - Disallow / allow raw `\r`/`\n` in strings. - **--quote-style** (choice) - Default: `always_double` - One of `always_double` | `always_single` | `prefer_double` | `prefer_single`. - **FILE** (positional) - Default: `-` (stdin) - Input file path. ### Exit Codes - **0** - Success - **2** - Usage error - **1** - Uncaught parse `ValueError` (Python default) ``` -------------------------------- ### main(argv=None, host=None) -> int Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.tool.md The main entry point for the json5.tool module, used both by the `python -m json5` command and the `pyjson5` console script. ```APIDOC ## main(argv=None, host=None) -> int ### Description Entry point for the JSON5 command-line tool. Parses arguments, reads input, and pretty-prints JSON5 documents. Returns an exit code. ### Method Function call ### Endpoint `json5.tool.main` ### Parameters - **argv** (Optional[list]) - Optional - Argument list; `None` means `sys.argv[1:]`. - **host** (Optional[Host]) - Optional - A `json5.host.Host` (or compatible fake) for stdio/file access; `None` creates a real `Host()`. ### Return Value - **int** - Exit code. `0` on success (including `--version`). Argument errors terminate via `sys.exit(2)`. ### Usage Example ```python import json5.tool rc = json5.tool.main(argv=['-c', '{foo:"bar"}', '--indent', '2']) print(rc) # 0 ``` ``` -------------------------------- ### Custom JSON5Encoder subclass example Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.JSON5Encoder.md Shows how to override encode() to handle a custom Hex integer type, falling back to super().encode() for normal objects. The example prints the JSON5 output for a list containing a regular integer and a Hex value, producing [20, 0x14]. ```python import json5 from typing import Any, Set class Hex(int): def __repr__(self): return hex(self) class CustomEncoder(json5.JSON5Encoder): def encode(self, obj: Any, seen: Set, level: int, *, as_key: bool) -> str: if isinstance(obj, Hex): return repr(obj) return super().encode(obj, seen, level, as_key=as_key) print(json5.dumps([20, Hex(20)], cls=CustomEncoder)) # [20, 0x14] ``` -------------------------------- ### Using is_reserved_word Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.JSON5Encoder.md Example usage of is_reserved_word. 'new' returns True, so it must be quoted; 'newbie' returns False, so it can be unquoted. ```python enc = json5.JSON5Encoder() print(enc.is_reserved_word('new')) # True → key must be quoted: {"new": 1} print(enc.is_reserved_word('newbie')) # False → unquoted: {newbie: 1} ``` -------------------------------- ### Create and activate virtual environment with ./run devenv Source: https://github.com/dpranke/pyjson5/blob/main/README.md Shell commands to create a virtual environment using the `run` script and activate it. The first command invokes `./run devenv` which internally calls `uv sync`, and the second activates the environment directly, useful when wanting to run tools like `ruff` directly. ```shell $ ./run devenv # which really just calls `uv sync`. $ source .venv/bin/activate ``` -------------------------------- ### Host.join method Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.host.md Joins path components using os.path.join. ```python def join(self, *comps): ``` -------------------------------- ### main() function signature Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.tool.md The entry point for the json5.tool CLI. Accepts an optional argument list and an optional Host for stdio/file access. Returns an exit code: 0 on success, 2 on usage errors, and propagates ValueError on parse failures. ```python def main(argv=None, host=None): ``` -------------------------------- ### Use QuoteStyle.PREFER_DOUBLE with json5.dumps Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.encoding.md Shows how to pass quote_style=json5.QuoteStyle.PREFER_DOUBLE to json5.dumps. The example string contains two double quotes and no single quotes, so the encoder re-encodes it single-quoted to avoid escaping the double quotes. ```python import json5 s = 'a "b" "c" d' # two double quotes, no single quotes print(json5.dumps(s)) # "a \"b\" \"c\" d" print(json5.dumps(s, quote_style=json5.QuoteStyle.PREFER_DOUBLE)) # 'a "b" "c" d' (re-encoded single-quoted to avoid escaping the double quotes) ``` -------------------------------- ### Host constructor Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.host.md Initializes a Host instance, binding sys.stdin, sys.stdout, and sys.stderr to the corresponding attributes. ```python def __init__(self): ``` -------------------------------- ### Host.mkdtemp method Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.host.md Creates a temporary directory via tempfile.mkdtemp, passing through keyword arguments like prefix, suffix, and dir. ```python def mkdtemp(self, **kwargs): ``` -------------------------------- ### Raise TypeError for unserializable object in JSON5Encoder Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/errors.md Raised by JSON5Encoder.default (the default default_fn) when dump/dumps meet an unsupported value and no usable default hook is provided. Example: json5.dumps({1, 2}) → '{1, 2} is not JSON5 serializable'. ```python def _raise_type_error(obj) -> Any: raise TypeError(f'{obj!r} is not JSON5 serializable') ``` -------------------------------- ### Serialization options — dump, dumps, JSON5Encoder.__init__ Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/configuration.md Documentation for the serialization options of the pyjson5 library, covering the `dump`, `dumps`, and `JSON5Encoder.__init__` functions. Each entry lists the same set of keyword-only options with types, defaults, and descriptions. ```APIDOC ## dump(obj, fp, ...) ### Description Serializes a Python object to a JSON5-formatted stream, writing to a file-like object. Accepts the same keyword-only options as `dumps`. ### Method N/A (Python function) ### Endpoint N/A (Python function) ### Parameters #### Keyword Arguments - **skipkeys** (bool) - Optional - Default: `False` - Skip dict keys that cannot be encoded as keys (instead of raising `TypeError`). - **ensure_ascii** (bool) - Optional - Default: `True` - Escape non-ASCII as `\uXXXX` (surrogate pairs above `0xFFFF`). `\u2028`/`\u2029` always escaped. - **check_circular** (bool) - Optional - Default: `True` - Raise `ValueError('Circular reference detected.')` on cycles. - **allow_nan** (bool) - Optional - Default: `True` - Encode `Infinity`/`-Infinity`/`NaN`; `False` raises `ValueError`. - **cls** (Optional[Type['JSON5Encoder']]) - Optional - Default: `None` (`JSON5Encoder`) - Encoder subclass. (Unlike decoding, a non-`None` `cls` here is valid.) - **indent** (Optional[Union[int, str]]) - Optional - Default: `None` - `int > 0`: spaces per level; `int <= 0`: bare newlines; `str`: repeated per level; `None`: compact. Enables multi-line output → trailing commas per `trailing_commas`. - **separators** (Optional[Tuple[str, str]]) - Optional - Default: `None` - `(item_separator, kv_separator)`; default `(', ', ': ')` compact / `(',', ': ')` indented. - **default** (Optional[Callable[[Any], Any]]) - Optional - Default: `None` (raises `TypeError`) - Converts unencodable objects; must return a serializable value, not a pre-encoded string. - **sort_keys** (bool) - Optional - Default: `False` - Emit dict keys in `sorted()` order. - **quote_keys** (bool) - Optional - Default: `False` - Always quote object keys; `False` leaves identifier (non-reserved) keys unquoted. - **trailing_commas** (bool) - Optional - Default: `True` - Add trailing commas in multi-line objects/arrays. - **allow_duplicate_keys** (bool) - Optional - Default: `True` - `False` raises `ValueError(f'duplicate key {key!r}')` on repeated rendered keys. - **quote_style** (QuoteStyle) - Optional - Default: `QuoteStyle.ALWAYS_DOUBLE` - String quoting policy (see [types.md](types.md)). *Added v0.10.0.* ### Request Example N/A (Python function) ### Response #### Success Response N/A (Python function) #### Response Example N/A (Python function) ### Error Handling - Raises `TypeError` for unencodable keys (unless `skipkeys=True`). - Raises `ValueError('Circular reference detected.')` on cycles (unless `check_circular=False`). - Raises `ValueError` for `Infinity`/`-Infinity`/`NaN` when `allow_nan=False`. - Raises `ValueError(f'duplicate key {key!r}')` on repeated rendered keys when `allow_duplicate_keys=False`. - Raises `TypeError` for unencodable objects when `default` is not provided. ``` ```APIDOC ## dumps(obj, ...) ### Description Serializes a Python object to a JSON5-formatted string. Accepts the same keyword-only options as `dump`. ### Method N/A (Python function) ### Endpoint N/A (Python function) ### Parameters #### Keyword Arguments - **skipkeys** (bool) - Optional - Default: `False` - Skip dict keys that cannot be encoded as keys (instead of raising `TypeError`). - **ensure_ascii** (bool) - Optional - Default: `True` - Escape non-ASCII as `\uXXXX` (surrogate pairs above `0xFFFF`). `\u2028`/`\u2029` always escaped. - **check_circular** (bool) - Optional - Default: `True` - Raise `ValueError('Circular reference detected.')` on cycles. - **allow_nan** (bool) - Optional - Default: `True` - Encode `Infinity`/`-Infinity`/`NaN`; `False` raises `ValueError`. - **cls** (Optional[Type['JSON5Encoder']]) - Optional - Default: `None` (`JSON5Encoder`) - Encoder subclass. (Unlike decoding, a non-`None` `cls` here is valid.) - **indent** (Optional[Union[int, str]]) - Optional - Default: `None` - `int > 0`: spaces per level; `int <= 0`: bare newlines; `str`: repeated per level; `None`: compact. Enables multi-line output → trailing commas per `trailing_commas`. - **separators** (Optional[Tuple[str, str]]) - Optional - Default: `None` - `(item_separator, kv_separator)`; default `(', ', ': ')` compact / `(',', ': ')` indented. - **default** (Optional[Callable[[Any], Any]]) - Optional - Default: `None` (raises `TypeError`) - Converts unencodable objects; must return a serializable value, not a pre-encoded string. - **sort_keys** (bool) - Optional - Default: `False` - Emit dict keys in `sorted()` order. - **quote_keys** (bool) - Optional - Default: `False` - Always quote object keys; `False` leaves identifier (non-reserved) keys unquoted. - **trailing_commas** (bool) - Optional - Default: `True` - Add trailing commas in multi-line objects/arrays. - **allow_duplicate_keys** (bool) - Optional - Default: `True` - `False` raises `ValueError(f'duplicate key {key!r}')` on repeated rendered keys. - **quote_style** (QuoteStyle) - Optional - Default: `QuoteStyle.ALWAYS_DOUBLE` - String quoting policy (see [types.md](types.md)). *Added v0.10.0.* ### Request Example N/A (Python function) ### Response #### Success Response N/A (Python function) #### Response Example N/A (Python function) ### Error Handling - Raises `TypeError` for unencodable keys (unless `skipkeys=True`). - Raises `ValueError('Circular reference detected.')` on cycles (unless `check_circular=False`). - Raises `ValueError` for `Infinity`/`-Infinity`/`NaN` when `allow_nan=False`. - Raises `ValueError(f'duplicate key {key!r}')` on repeated rendered keys when `allow_duplicate_keys=False`. - Raises `TypeError` for unencodable objects when `default` is not provided. ``` ```APIDOC ## JSON5Encoder.__init__(...) ### Description Constructor for the `JSON5Encoder` class. Accepts the same keyword-only options as `dump` and `dumps`; extra `**kw` are discarded. ### Method N/A (Python constructor) ### Endpoint N/A (Python constructor) ### Parameters #### Keyword Arguments - **skipkeys** (bool) - Optional - Default: `False` - Skip dict keys that cannot be encoded as keys (instead of raising `TypeError`). - **ensure_ascii** (bool) - Optional - Default: `True` - Escape non-ASCII as `\uXXXX` (surrogate pairs above `0xFFFF`). `\u2028`/`\u2029` always escaped. - **check_circular** (bool) - Optional - Default: `True` - Raise `ValueError('Circular reference detected.')` on cycles. - **allow_nan** (bool) - Optional - Default: `True` - Encode `Infinity`/`-Infinity`/`NaN`; `False` raises `ValueError`. - **cls** (Optional[Type['JSON5Encoder']]) - Optional - Default: `None` (`JSON5Encoder`) - Encoder subclass. (Unlike decoding, a non-`None` `cls` here is valid.) - **indent** (Optional[Union[int, str]]) - Optional - Default: `None` - `int > 0`: spaces per level; `int <= 0`: bare newlines; `str`: repeated per level; `None`: compact. Enables multi-line output → trailing commas per `trailing_commas`. - **separators** (Optional[Tuple[str, str]]) - Optional - Default: `None` - `(item_separator, kv_separator)`; default `(', ', ': ')` compact / `(',', ': ')` indented. - **default** (Optional[Callable[[Any], Any]]) - Optional - Default: `None` (raises `TypeError`) - Converts unencodable objects; must return a serializable value, not a pre-encoded string. - **sort_keys** (bool) - Optional - Default: `False` - Emit dict keys in `sorted()` order. - **quote_keys** (bool) - Optional - Default: `False` - Always quote object keys; `False` leaves identifier (non-reserved) keys unquoted. - **trailing_commas** (bool) - Optional - Default: `True` - Add trailing commas in multi-line objects/arrays. - **allow_duplicate_keys** (bool) - Optional - Default: `True` - `False` raises `ValueError(f'duplicate key {key!r}')` on repeated rendered keys. - **quote_style** (QuoteStyle) - Optional - Default: `QuoteStyle.ALWAYS_DOUBLE` - String quoting policy (see [types.md](types.md)). *Added v0.10.0.* ### Request Example N/A (Python constructor) ### Response #### Success Response N/A (Python constructor) #### Response Example N/A (Python constructor) ### Error Handling - Raises `TypeError` for unencodable keys (unless `skipkeys=True`). - Raises `ValueError('Circular reference detected.')` on cycles (unless `check_circular=False`). - Raises `ValueError` for `Infinity`/`-Infinity`/`NaN` when `allow_nan=False`. - Raises `ValueError(f'duplicate key {key!r}')` on repeated rendered keys when `allow_duplicate_keys=False`. - Raises `TypeError` for unencodable objects when `default` is not provided. ``` -------------------------------- ### Parse JSON5 string with Parser and get raw AST Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.parser.md Instantiate Parser with a JSON5 string and source name, then call parse() with global_vars to enable strict mode and trailing consumption. The returned value is the raw AST (nested lists with tags like ['object', ...]) before conversion to Python objects; use json5.loads or json5.parse for Python values. ```python from json5.parser import Parser p = Parser('{a: 1}', '') val, err, pos = p.parse(global_vars={'_strict': True, '_consume_trailing': True}) # val == ['object', [['a', ['number', '1']]]] (raw AST, pre-conversion) ``` -------------------------------- ### Host.chdir method Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.host.md Changes the working directory by joining path components with os.path.join and calling os.chdir. Returns the result of os.chdir (None). ```python def chdir(self, *comps): ``` -------------------------------- ### Programmatic invocation of json5.tool.main Source: https://github.com/dpranke/pyjson5/blob/main/_autodocs/api-reference/json5.tool.md Shows how to call main() from Python with an inline JSON5 string and custom indent. Returns the exit code (0 on success) and prints the pretty-printed output to stdout. ```python import json5.tool # parse+pretty-print from an inline string, returning the exit code rc = json5.tool.main(argv=['-c', '{foo:"bar"}', '--indent', '2']) print(rc) # 0 (output is printed to stdout) ```