<commit_before>import json
import warnings
from collections import defaultdict
from urllib import parse
from aenum import extend_enum

from waspy import exceptions
from waspy.parser import parsers
from .router import Methods
from http import HTTPStatus, cookies

extend_enum(HTTPStatus, 'INVALID_REQUEST', (430, 'Invalid Request',
                                            'Request was syntactically sound, '
                                            'but failed validation rules'))


class QueryParams:
    """
    A dictionary that stores multiple values per key.

    this has all the normal dictionary methods, and works as normal but does
    not override a key when `add` is used, and also has `getall`
    """
    __slots__ = ['mappings']

    @classmethod
    def from_string(cls, string):
        query_params = QueryParams()
        qs = parse.parse_qsl(string)
        for k, v in qs:
            query_params.add(k, v)

        return query_params

    def __init__(self):
        self.mappings = defaultdict(list)

    def get(self, name, default=None):
        return self.mappings.get(name, [default])[0]

    def getall(self, name, default=None):
        return self.mappings.get(name, default)

    def __getitem__(self, key):
        try:
            return self.mappings.__getitem__(key)[0]
        except IndexError:
            raise KeyError('Invalid Key: {key}'.format(key))

    def __setitem__(self, key, value):
        raise TypeError('MultiDict does not support item assignment. '
                        'Use .add(k, v) instead.')

    def add(self, name, value):
        self.mappings[name].append(value)

    def __str__(self):
        return parse.urlencode(self.mappings, doseq=True)


class Parseable:
    def __init__(self, *args, content_type=None, body=None, **kwargs):
        self._parser = None
        self.content_type = content_type
        self.app = None

        self.original_body = body
        self._body = None
        self._raw_body = None

    @property
    def parser(self):
        if not self._parser:
            if not self.content_type and self.app.default_content_type:
                self.content_type = self.app.default_content_type
            self._parser = parsers.get(self.content_type)
            if not self._parser:
                raise exceptions.UnsupportedMediaType(self.content_type)
        return self._parser

    @property
    def body(self) -> dict:
        """ Decoded Body """
        if self._body is None and self.original_body is not None:
            if isinstance(self.original_body, bytes):
                self._body = self.parser.decode(self.original_body)
            else:
                self._body = self.original_body
        return self._body

    @body.setter
    def body(self, value):
        if isinstance(value, bytes):<commit_msg>Throw away charset on the content type for now<commit_after>import json
import warnings
from collections import defaultdict
from urllib import parse
from aenum import extend_enum

from waspy import exceptions
from waspy.parser import parsers
from .router import Methods
from http import HTTPStatus, cookies

extend_enum(HTTPStatus, 'INVALID_REQUEST', (430, 'Invalid Request',
                                            'Request was syntactically sound, '
                                            'but failed validation rules'))


class QueryParams:
    """
    A dictionary that stores multiple values per key.

    this has all the normal dictionary methods, and works as normal but does
    not override a key when `add` is used, and also has `getall`
    """
    __slots__ = ['mappings']

    @classmethod
    def from_string(cls, string):
        query_params = QueryParams()
        qs = parse.parse_qsl(string)
        for k, v in qs:
            query_params.add(k, v)

        return query_params

    def __init__(self):
        self.mappings = defaultdict(list)

    def get(self, name, default=None):
        return self.mappings.get(name, [default])[0]

    def getall(self, name, default=None):
        return self.mappings.get(name, default)

    def __getitem__(self, key):
        try:
            return self.mappings.__getitem__(key)[0]
        except IndexError:
            raise KeyError('Invalid Key: {key}'.format(key))

    def __setitem__(self, key, value):
        raise TypeError('MultiDict does not support item assignment. '
                        'Use .add(k, v) instead.')

    def add(self, name, value):
        self.mappings[name].append(value)

    def __str__(self):
        return parse.urlencode(self.mappings, doseq=True)


class Parseable:
    def __init__(self, *args, content_type=None, body=None, **kwargs):
        self._parser = None
        self.app = None
        self.original_body = body
        self._body = None
        self._raw_body = None

        self.content_type = content_type

    @property
    def content_type(self):
        if self._content_type:
            return self._content_type
        if self.app:
            return self.app.default_content_type

    @content_type.setter
    def content_type(self, value):
        if value:
            # Throw away charset for now. We will have to figure this out later.
            self._content_type = value.split(';')[0]

    @property
    def parser(self):
        if not self._parser:
            self._parser = parsers.get(self.content_type)
            if not self._parser:
                raise exceptions.UnsupportedMediaType(self.content_type)
        return self._parser

    @property
    def body(self) -> dict:
        """ Decoded Body """
        if self._body is None and self.original_body is not None:
            if isinstance(self.original_body, bytes):
                self._body = self.parser.decode(self.original_body)
            else:
                self._body = self.original_body
        return self._body

    @body.setter
    def body(self, value):
        if isinstance(value, bytes):
{'fraction_non_alphanumeric': 0.08638040925863805, 'fraction_numerical': 0.0018450184501845018, 'mean_word_length': 2.2284786139685977, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4394854', 'n_tokens_mistral': 1660, 'n_tokens_neox': 1604, 'n_words': 490}