<commit_before>import re
import copy
import pprint

import jsonschema

from jsonschema.exceptions import ValidationError


class Validator(object):
    core_schema = {
        'type': 'object',
        'properties': {
            'paradigm': {
                'type': 'string',
            },
            'method': {
                'type': 'string',
            },
        },
        'additionalProperties': False,
    }

    def request(self, *args):
        self.validate('request', *args)

    def response(self, *args):
        self.validate('response', *args)

    def validate(self, kind, request, paradigms):
        paradigm_name, method_key = self.get_method(request)

        paradigm = paradigms.get(paradigm_name)

        if paradigm is None:
            raise ValidationError(
                "Paradigm '{0}' not known. Choices are: {1}".format(
                    paradigm_name,
                    self._csl(paradigms)
                )
            )

        validator = paradigm.validator
        method_name = '{0}_{1}'.format(method_key, kind)
        method = getattr(validator, method_name, None)

        if method is None:
            raise ValidationError(
                "Method '{0}()' not found in '{1}'. Choices are: {2}".format(
                    method_name,
                    paradigm_name,
                    self._csl(validator.get_known_methods())
                )
            )

        # Since we are going to modify the schema, we need to make a deep copy
        # of it so that future requests are not contaminated by what we do now.
        # TODO: Split into function and add deeper tests.
        schema = copy.deepcopy(self.core_schema)
        schema['properties'].update(method())

        jsonschema.validate(request, schema)

    def get_method(self, data):
        # TODO: Make this method actually return the method, with the
        # validation from the above.
        error = None

        if 'paradigm' not in data:
            error = 'paradigm'
        elif 'method' not in data:
            error = 'method'

        if error:
            msg = ''''{0}' field missing in:\n{1}'''
            raise ValidationError(msg.format(error, pprint.pformat(data)))

        return data['paradigm'], data['method']

    def get_known_methods(self):
        """
        Get known validation methods by finding all methods ending in _request
        or _response.

        """

        ret = []
        for key in dir(self):
            item = getattr(self, key)
            if re.search(r'_(request|response)$', key) and callable(item):
                ret.append(key)
        return ret

    def _csl(self, iterable):
        """
        Make a list quoted and comma separated

        """

        return ", ".join("'{0}'".format(x) for x in iterable)
<commit_msg>Move schema decoration to own function<commit_after>import re
import copy
import pprint

import jsonschema

from jsonschema.exceptions import ValidationError


class Validator(object):
    core_schema = {
        'type': 'object',
        'properties': {
            'paradigm': {
                'type': 'string',
            },
            'method': {
                'type': 'string',
            },
        },
        'additionalProperties': False,
    }

    def request(self, *args):
        self.validate('request', *args)

    def response(self, *args):
        self.validate('response', *args)

    def validate(self, kind, request, paradigms):
        paradigm_name, method_key = self.get_method(request)

        paradigm = paradigms.get(paradigm_name)

        if paradigm is None:
            raise ValidationError(
                "Paradigm '{0}' not known. Choices are: {1}".format(
                    paradigm_name,
                    self._csl(paradigms)
                )
            )

        validator = paradigm.validator
        method_name = '{0}_{1}'.format(method_key, kind)
        method = getattr(validator, method_name, None)

        if method is None:
            raise ValidationError(
                "Method '{0}()' not found in '{1}'. Choices are: {2}".format(
                    method_name,
                    paradigm_name,
                    self._csl(validator.get_known_methods())
                )
            )

        schema = self.decorate_schema(method())
        jsonschema.validate(request, schema)

    def get_method(self, data):
        # TODO: Make this method actually return the method, with the
        # validation from the above.
        error = None

        if 'paradigm' not in data:
            error = 'paradigm'
        elif 'method' not in data:
            error = 'method'

        if error:
            msg = ''''{0}' field missing in:\n{1}'''
            raise ValidationError(msg.format(error, pprint.pformat(data)))

        return data['paradigm'], data['method']

    def get_known_methods(self):
        """
        Get known validation methods by finding all methods ending in _request
        or _response.

        """

        ret = []
        for key in dir(self):
            item = getattr(self, key)
            if re.search(r'_(request|response)$', key) and callable(item):
                ret.append(key)
        return ret

    def _csl(self, iterable):
        """
        Make a list quoted and comma separated

        """

        return ", ".join("'{0}'".format(x) for x in iterable)

    def decorate_schema(self, schema):
        # TODO: Fine grained unit tests
        # Since we are going to modify the schema, we need to make a deep copy
        # of it so that future requests are not contaminated by what we do now.
        decorated = copy.deepcopy(self.core_schema)
        decorated['properties'].update(schema)

        return decorated

{'fraction_non_alphanumeric': 0.1049618320610687, 'fraction_numerical': 0.0034698126301179735, 'mean_word_length': 1.785024154589372, 'pattern_counts': {'":': 0, '<': 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': '2930509', 'n_tokens_mistral': 1643, 'n_tokens_neox': 1553, 'n_words': 455}