<commit_before>import datetime
from functools import partial

from requests.cookies import RequestsCookieJar, cookiejar_from_dict
from requests.structures import CaseInsensitiveDict
from urllib3.response import HTTPHeaderDict

from .. import get_placeholder_class
from ..models import CachedResponse
from .pipeline import Stage

try:
    from cattr import GenConverter
    from cattr.preconf import bson, json, msgpack, orjson, pyyaml, tomlkit, ujson

    def to_datetime(obj, cls) -> datetime:
        if isinstance(obj, str):
            obj = datetime.fromisoformat(obj)
        return obj

    def to_timedelta(obj, cls) -> datetime.timedelta:
        if isinstance(obj, (int, float)):
            obj = datetime.timedelta(seconds=obj)
        return obj

    class CattrsStage(Stage):
        def __init__(self, converter, *args, **kwargs):
            super().__init__(converter, *args, **kwargs)
            self.loads = partial(converter.structure, cl=CachedResponse)

    def init_converter(factory: GenConverter = None):
        """Make a converter to structure and unstructure some of the nested objects within a response,
        if cattrs is installed.
        """
        converter = factory(omit_if_default=True)

        # Convert datetimes to and from iso-formatted strings
        converter.register_unstructure_hook(datetime, lambda obj: obj.isoformat() if obj else None)
        converter.register_structure_hook(datetime, to_datetime)

        # Convert timedeltas to and from float values in seconds
        converter.register_unstructure_hook(
            datetime.timedelta, lambda obj: obj.total_seconds() if obj else None
        )
        converter.register_structure_hook(datetime.timedelta, to_timedelta)

        # Convert dict-like objects to and from plain dicts
        converter.register_unstructure_hook(RequestsCookieJar, lambda obj: dict(obj.items()))
        converter.register_structure_hook(RequestsCookieJar, lambda obj, cls: cookiejar_from_dict(obj))
        converter.register_unstructure_hook(CaseInsensitiveDict, dict)
        converter.register_structure_hook(CaseInsensitiveDict, lambda obj, cls: CaseInsensitiveDict(obj))
        converter.register_unstructure_hook(HTTPHeaderDict, dict)
        converter.register_structure_hook(HTTPHeaderDict, lambda obj, cls: HTTPHeaderDict(obj))

        converter.register_structure_hook(
            CachedResponse,
            lambda obj, cls: converter.structure(obj, CachedResponse),
        )
        converter = CattrsStage(converter, dumps='unstructure', loads='structure')<commit_msg>Fix inifinite loop of doom<commit_after>import datetime
from functools import partial
from typing import ForwardRef

from requests.cookies import RequestsCookieJar, cookiejar_from_dict
from requests.structures import CaseInsensitiveDict
from urllib3.response import HTTPHeaderDict

from .. import get_placeholder_class
from ..models import CachedResponse
from .pipeline import Stage

try:
    from cattr import GenConverter
    from cattr.preconf import bson, json, msgpack, orjson, pyyaml, tomlkit, ujson

    def to_datetime(obj, cls) -> datetime:
        if isinstance(obj, str):
            obj = datetime.fromisoformat(obj)
        return obj

    def to_timedelta(obj, cls) -> datetime.timedelta:
        if isinstance(obj, (int, float)):
            obj = datetime.timedelta(seconds=obj)
        return obj

    class CattrsStage(Stage):
        def __init__(self, converter, *args, **kwargs):
            super().__init__(converter, *args, **kwargs)
            self.loads = partial(converter.structure, cl=CachedResponse)

    def init_converter(factory: GenConverter = None):
        """Make a converter to structure and unstructure some of the nested objects within a response,
        if cattrs is installed.
        """
        converter = factory(omit_if_default=True)

        # Convert datetimes to and from iso-formatted strings
        converter.register_unstructure_hook(datetime, lambda obj: obj.isoformat() if obj else None)
        converter.register_structure_hook(datetime, to_datetime)

        # Convert timedeltas to and from float values in seconds
        converter.register_unstructure_hook(
            datetime.timedelta, lambda obj: obj.total_seconds() if obj else None
        )
        converter.register_structure_hook(datetime.timedelta, to_timedelta)

        # Convert dict-like objects to and from plain dicts
        converter.register_unstructure_hook(RequestsCookieJar, lambda obj: dict(obj.items()))
        converter.register_structure_hook(RequestsCookieJar, lambda obj, cls: cookiejar_from_dict(obj))
        converter.register_unstructure_hook(CaseInsensitiveDict, dict)
        converter.register_structure_hook(CaseInsensitiveDict, lambda obj, cls: CaseInsensitiveDict(obj))
        converter.register_unstructure_hook(HTTPHeaderDict, dict)
        converter.register_structure_hook(HTTPHeaderDict, lambda obj, cls: HTTPHeaderDict(obj))

        # Tell cattrs that a 'CachedResponse' forward ref is equivalent to the CachedResponse class
        converter.register_structure_hook(
            ForwardRef('CachedResponse'),
            lambda obj, cls: converter.structure(obj, CachedResponse),
        )
        converter = CattrsStage(converter, dumps='unstructure', loads='structure')
{'fraction_non_alphanumeric': 0.07431796801505174, 'fraction_numerical': 0.00037629350893697084, 'mean_word_length': 3.594641313742437, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, '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': '3089313', 'n_tokens_mistral': 1449, 'n_tokens_neox': 1431, 'n_words': 390}