<commit_before>import re
import types
from functools import partial


LITERAL_TYPE = types.StringTypes + (int, float, long, bool, )


class Spec(object):
    """
    This object, when overridden with an object that implements a file format
    specification, will perform validation on a given parsed version of the
    format input.

    SPEC Node Documentation:
    ========================

    expected_type:
        A type object whose type the object should match.
    required_nodes:
        A list of nodes that are required for the current node.
    required_nodes_when:
        A dict of node name/lambda pairs. If the lambda evaluates to True, a
        node whose name corresponds to the node name is required.
        The current node is passed as a parameter to the lambda as the only
        argument.
    disallowed_nodes:
        A list of nodes that explicitly are disallowed in the current node.
    allowed_once_nodes:
        A list of nodes that are allowed only once.
    allowed_nodes:
        A list of nodes that are allowed multiple times.
    unknown_node_level:
        The message type to return when an unknown node is encountered.
    child_nodes:
        A dict of node definitions for nodes that can exist within this node.
    max_length:
        For sequence values only. An integer describing the maximum length of
        the string.
    not_empty:
        A boolean value describing whether the string/list/dict can be empty.
    values:
        A list of possible values for the node. Only applies to lists and
        literal nodes.
    value_matches:
        If `values` is not set, the value must match this regex. Only applies
        to string nodes.
    process:
        A lambda function that returns a function to process the node. The
        lambda accepts one parameter (self) and should return a function that
        accepts two parameters (self, node).
    child_process:
        A lambda function (similar to `process` that returns a function to
        process a child node. The lambda accepts one parameter (self) and
        should return a function that accepts three parameters (self, node_name,
        node).
        If this is set, no further testing will take place on child nodes.
    """

    SPEC_NAME = "Specification"
    MORE_INFO = "You can find more info online."

    SPEC = None

    def __init__(self, data, err):
        self.data = self.parse(data)
        self.err = err

        self.error = partial(self._err_message, self.err.error)
        self.warning = partial(self._err_message, self.err.warning)
        self.notice = partial(self._err_message, self.err.notice)

        self.err_map = {"error": self.error,
                        "warning": self.warning,
                        "notice": self.notice}

        self.path = []

    def _err_message(self, func, *args, **kwargs):
        if self.path:
            kwargs['description'].append("Node: %s" % self._get_path())
        func(*args, **kwargs)

    def _message(self, type_, *args, **kwargs):
        kwargs[type_] = kwargs.pop("message")
        self.err_map[type_](*args, **kwargs)

    def validate(self):
        # Validate the root node.
        root_name, root_node = self.get_root_node(self.data)
        root_val_result = self.validate_root_node(root_node)
        if root_val_result == False:
            return

        # Iterate the tree and validate as we go.
        self.iterate(root_name, root_node, self.SPEC)

    def parse(self, data): pass
    def validate_root_node(self, node): pass
    def get_root_node(self, data):
        """
        We expect this function to return a tuple:<commit_msg>Fix tests for messages with single-line descriptions<commit_after>import re
import types
from functools import partial


LITERAL_TYPE = types.StringTypes + (int, float, long, bool, )


class Spec(object):
    """
    This object, when overridden with an object that implements a file format
    specification, will perform validation on a given parsed version of the
    format input.

    SPEC Node Documentation:
    ========================

    expected_type:
        A type object whose type the object should match.
    required_nodes:
        A list of nodes that are required for the current node.
    required_nodes_when:
        A dict of node name/lambda pairs. If the lambda evaluates to True, a
        node whose name corresponds to the node name is required.
        The current node is passed as a parameter to the lambda as the only
        argument.
    disallowed_nodes:
        A list of nodes that explicitly are disallowed in the current node.
    allowed_once_nodes:
        A list of nodes that are allowed only once.
    allowed_nodes:
        A list of nodes that are allowed multiple times.
    unknown_node_level:
        The message type to return when an unknown node is encountered.
    child_nodes:
        A dict of node definitions for nodes that can exist within this node.
    max_length:
        For sequence values only. An integer describing the maximum length of
        the string.
    not_empty:
        A boolean value describing whether the string/list/dict can be empty.
    values:
        A list of possible values for the node. Only applies to lists and
        literal nodes.
    value_matches:
        If `values` is not set, the value must match this regex. Only applies
        to string nodes.
    process:
        A lambda function that returns a function to process the node. The
        lambda accepts one parameter (self) and should return a function that
        accepts two parameters (self, node).
    child_process:
        A lambda function (similar to `process` that returns a function to
        process a child node. The lambda accepts one parameter (self) and
        should return a function that accepts three parameters (self, node_name,
        node).
        If this is set, no further testing will take place on child nodes.
    """

    SPEC_NAME = "Specification"
    MORE_INFO = "You can find more info online."

    SPEC = None

    def __init__(self, data, err):
        self.data = self.parse(data)
        self.err = err

        self.error = partial(self._err_message, self.err.error)
        self.warning = partial(self._err_message, self.err.warning)
        self.notice = partial(self._err_message, self.err.notice)

        self.err_map = {"error": self.error,
                        "warning": self.warning,
                        "notice": self.notice}

        self.path = []

    def _err_message(self, func, *args, **kwargs):
        if self.path:
            nodepath = "Node: %s" % self._get_path()
            if isinstance(kwargs["description"], list):
                kwargs["description"].append(nodepath)
            else:
                kwargs["description"] = [
                    kwargs["description"], nodepath]
        func(*args, **kwargs)

    def _message(self, type_, *args, **kwargs):
        kwargs[type_] = kwargs.pop("message")
        self.err_map[type_](*args, **kwargs)

    def validate(self):
        # Validate the root node.
        root_name, root_node = self.get_root_node(self.data)
        root_val_result = self.validate_root_node(root_node)
        if root_val_result == False:
            return

        # Iterate the tree and validate as we go.
        self.iterate(root_name, root_node, self.SPEC)

    def parse(self, data): pass
    def validate_root_node(self, node): pass
    def get_root_node(self, data):
        """
        We expect this function to return a tuple:
{'fraction_non_alphanumeric': 0.07524464427400158, 'fraction_numerical': 0.0, 'mean_word_length': 2.4221719457013573, 'pattern_counts': {'":': 6, '<': 3, '<?xml version=': 0, '>': 3, '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': '7032027', 'n_tokens_mistral': 1997, 'n_tokens_neox': 1944, 'n_words': 814}