view configmix/json.py @ 428:090a25f36a3d

FIX: Allow jailed configurations to use correctly use base configurations that use a different "default" marker object. Jailed configurations assumed that their "default" marker object is identical to the "default" marker object in the unjailed base configuration. This is not always true, especially if "_JailedConfiguration.rebind()" is used. Removed the explicit "default" keyword argument and passed the complete keywords argument dictionary to the base instead. This triggers correct default handling in the base.
author Franz Glasner <f.glasner@feldmann-mg.com>
date Thu, 09 Dec 2021 13:02:17 +0100
parents eed16a1ec8f3
children f454889e41fa
line wrap: on
line source

# -*- coding: utf-8 -*-
# :-
# :Copyright: (c) 2018-2020, Franz Glasner. All rights reserved.
# :License:   BSD-3-Clause. See LICENSE.txt for details.
# :-
"""Read JSON-style configuration files.

"""

from __future__ import division, absolute_import, print_function


__all__ = ["load"]


import io
import json.decoder
try:
    from collections import OrderedDict as DictImpl
except ImportError:
    try:
        from ordereddict import OrderedDict as DictImpl
    except ImportError:
        DictImpl = dict

from .compat import u2fs


#
# Determine whether the JSONDecoder has the "object_pairs_hook"
# parameter once
#
try:
    json.decoder.JSONDecoder(object_pairs_hook=DictImpl)
except TypeError:
    _with_object_pairs_hook = False
else:
    _with_object_pairs_hook = True


def load(filename, encoding="utf-8"):
    """Load a single JSON file with name `filename` and encoding `encoding`.

    """
    with io.open(u2fs(filename), mode="rt", encoding=encoding) as jsfp:
        #
        # The scanner (not to be changed yet) does only recognize decimal
        # integers yet.
        #
        kwds = {
            "parse_int": lambda s: int(s, 0),
            "strict": False
        }
        if _with_object_pairs_hook:
            kwds["object_pairs_hook"] = DictImpl
        decoder = json.decoder.JSONDecoder(**kwds)
        data = decoder.decode(jsfp.read())
        if not isinstance(data, DictImpl):
            raise TypeError("JSON root must be an object (i.e. dict)")
        return data