<commit_before>class Dict(dict):
    """
    Dict is a subclass of dict, which allows you to get AND SET(!!)
    items in the dict using the attribute syntax!

    When you previously had to write:

    my_dict = {'a': {'b': {'c': [1, 2, 3]}}}

    you can now do the same simply by:

    my_Dict = Dict()
    my_Dict.a.b.c = [1, 2, 3]

    Or for instance, if you'd like to add some additional stuff,
    where you'd with the normal dict would write

    my_dict['a']['b']['d'] = [4, 5, 6],

    you may now do the AWESOME

    my_Dict.a.b.d = [4, 5, 6]

    instead. But hey, you can always use the same syntax as a regular dict,
    however, this will not raise TypeErrors or AtrributeErrors at any time
    while you try to get an item. A lot like a defaultdict.

    """
    def __init__(self, *args, **kwargs):
        """
        If we're initialized with a dict, make sure we turn all the
        subdicts into Dicts as well.

        """
        if (args and isinstance(args[0], dict)):
            for key, val in args[0].iteritems():
                self._set_both(key, val)

    def __setattr__(self, name, value):
        """
        setattr is called when the syntax a.b = 2 is used to set a value.

        """
        self._set_both(name, value)

    def _set_both(self, name, value):
        """
        This method does the 'heavy' lifting here. If value is an instance
        of dict, it will be turned into a Dict (Yay!). If name is a string,
        it can be set as a property. If name is not in the Dict already,
        we put it in :-)

        """
        if isinstance(value, dict):
            value = self.__class__(value)
        if isinstance(name, str):
            super(Dict, self).__setattr__(name, value)
        if name not in self:
            super(Dict, self).__setitem__(name, value)

    def __setitem__(self, name, value):
        """
        This is called when trying to set a value of the Dict using [].
        E.g. some_instance_of_Dict['b'] = val. If 'val

        """
        self._set_both(name, value)

    def __getattr__(self, name):
        """
        This is called when __getattribute__ can't find an attribute.
        So this only handles the cases of missing attributes. This
        is the defaultdict-like part.

        """
        self._set_both(name, {})
        return super(Dict, self).__getattribute__(name)

    def __getitem__(self, name):
        """
        This is called when the Dict is accessed by []. E.g.
        some_instance_of_Dict['a'];
        If the name is in the dict, we return it. Otherwise we set both
        the attr and item to a new instance of Dict.

        """
        if name in self:
            return super(Dict, self).__getitem__(name)
        else:
            self._set_both(name, {})
            return super(Dict, self).__getitem__(name)

    def __delattr__(self, name):
        """
        Is invoked when del some_instance_of_Dict.b is called.

        """
        self._delete(name)

    def __delitem__(self, name):
        """
        Is invoked when del some_instance_of_Dict[b] is called.

        """
        self._delete(name)

    def _delete(self, name):
        """
        Deletes both the attribute and item associated with 'name'

        """
        super(Dict, self).__delitem__(name)
        super(Dict, self).__delattr__(name)

    def prune(self):
        """
        Removes all empty Dicts inside the Dict.
        E.g
        >>> a = Dict()
        >>> a.b.c.d
        {}
        >>> a.a = 2
        >>> a
        {'a': 2, 'b': {'c': {'d': {}}}}
        >>> a.prune()
        >>> a
        {'a': 2}
        """
        for key, val in self.items():
            if not val:
                self._delete(key)
            elif isinstance(val, dict):
                val.prune()
                self._delete(key)
<commit_msg>Some small changes made to support py3.<commit_after>class Dict(dict):
    """
    Dict is a subclass of dict, which allows you to get AND SET(!!)
    items in the dict using the attribute syntax!

    When you previously had to write:

    my_dict = {'a': {'b': {'c': [1, 2, 3]}}}

    you can now do the same simply by:

    my_Dict = Dict()
    my_Dict.a.b.c = [1, 2, 3]

    Or for instance, if you'd like to add some additional stuff,
    where you'd with the normal dict would write

    my_dict['a']['b']['d'] = [4, 5, 6],

    you may now do the AWESOME

    my_Dict.a.b.d = [4, 5, 6]

    instead. But hey, you can always use the same syntax as a regular dict,
    however, this will not raise TypeErrors or AtrributeErrors at any time
    while you try to get an item. A lot like a defaultdict.

    """
    def __init__(self, *args, **kwargs):
        """
        If we're initialized with a dict, make sure we turn all the
        subdicts into Dicts as well.

        """
        if (args and isinstance(args[0], dict)):
            for key, val in args[0].items():
                self._set_both(key, val)

    def __setattr__(self, name, value):
        """
        setattr is called when the syntax a.b = 2 is used to set a value.

        """
        self._set_both(name, value)

    def _set_both(self, name, value):
        """
        This method does the 'heavy' lifting here. If value is an instance
        of dict, it will be turned into a Dict (Yay!). If name is a string,
        it can be set as a property. If name is not in the Dict already,
        we put it in :-)

        """
        if isinstance(value, dict):
            value = self.__class__(value)
        if isinstance(name, str):
            super(Dict, self).__setattr__(name, value)
        if name not in self:
            super(Dict, self).__setitem__(name, value)

    def __setitem__(self, name, value):
        """
        This is called when trying to set a value of the Dict using [].
        E.g. some_instance_of_Dict['b'] = val. If 'val

        """
        self._set_both(name, value)

    def __getattr__(self, name):
        """
        This is called when __getattribute__ can't find an attribute.
        So this only handles the cases of missing attributes. This
        is the defaultdict-like part.

        """
        self._set_both(name, {})
        return super(Dict, self).__getattribute__(name)

    def __getitem__(self, name):
        """
        This is called when the Dict is accessed by []. E.g.
        some_instance_of_Dict['a'];
        If the name is in the dict, we return it. Otherwise we set both
        the attr and item to a new instance of Dict.

        """
        if name in self:
            return super(Dict, self).__getitem__(name)
        else:
            self._set_both(name, {})
            return super(Dict, self).__getitem__(name)

    def __delattr__(self, name):
        """
        Is invoked when del some_instance_of_Dict.b is called.

        """
        self._delete(name)

    def __delitem__(self, name):
        """
        Is invoked when del some_instance_of_Dict[b] is called.

        """
        self._delete(name)

    def _delete(self, name):
        """
        Deletes both the attribute and item associated with 'name'

        """
        super(Dict, self).__delitem__(name)
        super(Dict, self).__delattr__(name)

    def prune(self):
        """
        Removes all empty Dicts inside the Dict.
        E.g
        >>> a = Dict()
        >>> a.b.c.d
        {}
        >>> a.a = 2
        >>> a
        {'a': 2, 'b': {'c': {'d': {}}}}
        >>> a.prune()
        >>> a
        {'a': 2}
        """
        for key, val in list(self.items()):
            if not val:
                self._delete(key)
            elif isinstance(val, dict):
                val.prune()
                self._delete(key)

{'fraction_non_alphanumeric': 0.11213140196585618, 'fraction_numerical': 0.004785307811691671, 'mean_word_length': 1.8451066961000735, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 39, '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': '872013', 'n_tokens_mistral': 2376, 'n_tokens_neox': 2269, 'n_words': 852}