<commit_before>"""Setting manager for Porcupine."""

import codecs
import collections
import configparser
import glob
import json
import logging
import os
import pkgutil
import re
import tkinter.font as tkfont

log = logging.getLogger(__name__)


class _Config:
    """A {'section:name': value} dictionary-like object.

    Unlike plain dictionaries, these objects support things like
    callbacks that run when a value is changed.

    >>> c = _Config({})
    >>> c.load({'test': {'a': 1, 'b': 2}}, {'test': {'a': 3}})
    >>> dict(c) == {'test:a': 3, 'test:b': 2}
    True
    >>> c['test:b']     # default setting
    2
    >>> c['test:a']     # user setting that overrides a default setting
    3
    >>> c.dump()        # settings that are different from defaults
    {'test': {'a': 3}}
    >>>
    """

    def __init__(self, name, validators=None):
        if validators is None:
            validators = {}
        self.log = logging.getLogger(name)
        self._validators = validators
        self._callbacks = collections.defaultdict(list)
        self._default_values = None
        self._original_values = None

    def _flatten_dict(self, dictionary):
        result = {}
        for key1, sub in dictionary.items():
            for key2, value in sub.items():
                result[key1 + ':' + key2] = value
        return result

    def _unflatten_dict(self, dictionary):
        result = {}
        for key, value in dictionary.items():
            key1, key2 = key.split(':')
            try:
                result[key1][key2] = value
            except KeyError:
                result[key1] = {key2: value}
        return result

    def load(self, defaults, user_settings):
        """Set settings from two dict-like objects."""
        self._values = self._flatten_dict(defaults)
        self._default_values = self._values.copy()<commit_msg>at least a little bit nicer error messages<commit_after>"""Setting manager for Porcupine."""

import codecs
import collections
import configparser
import glob
import json
import logging
import os
import pkgutil
import re
import tkinter.font as tkfont

log = logging.getLogger(__name__)


class _Config:
    """A {'section:name': value} dictionary-like object.

    Unlike plain dictionaries, these objects support things like
    callbacks that run when a value is changed.

    >>> c = _Config({})
    >>> c.load({'test': {'a': 1, 'b': 2}}, {'test': {'a': 3}})
    >>> dict(c) == {'test:a': 3, 'test:b': 2}
    True
    >>> c['test:b']     # default setting
    2
    >>> c['test:a']     # user setting that overrides a default setting
    3
    >>> c.dump()        # settings that are different from defaults
    {'test': {'a': 3}}
    >>>
    """

    def __init__(self, name, validators=None):
        if validators is None:
            validators = {}
        self.log = logging.getLogger(name)
        self._validators = validators
        self._callbacks = collections.defaultdict(list)
        self._default_values = None
        self._original_values = None
        self._values = None

    def _flatten_dict(self, dictionary):
        result = {}
        for key1, sub in dictionary.items():
            for key2, value in sub.items():
                result[key1 + ':' + key2] = value
        return result

    def _unflatten_dict(self, dictionary):
        result = {}
        for key, value in dictionary.items():
            key1, key2 = key.split(':')
            try:
                result[key1][key2] = value
            except KeyError:
                result[key1] = {key2: value}
        return result

    def load(self, defaults, user_settings):
        """Set settings from two dict-like objects."""
        self._values = self._flatten_dict(defaults)
        self._default_values = self._values.copy()
{'fraction_non_alphanumeric': 0.12430866473531736, 'fraction_numerical': 0.00948116934421912, 'mean_word_length': 2.3790035587188614, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5178139', 'n_tokens_mistral': 1108, 'n_tokens_neox': 1070, 'n_words': 336}