<commit_before>import asyncio
from asyncio.coroutines import iscoroutinefunction
from asyncio.futures import Future
from functools import partial
from time import time
from types import MethodType

from asyncpg.exceptions import UniqueViolationError, UndefinedColumnError
from trellio import request, get, put, post, delete, api
from trelliopg import get_db_adapter

from trelliolibs.utils.helpers import json_serializer
from .decorators import TrellioValidator
from .helpers import RecordHelper, uuid_serializer, json_response


class RecordNotFound(Exception):
    pass


class RequestKeyError(Exception):
    pass


def extract_request_params(request, filter_keys=()):
    params = dict()
    if request.get('limit') and request.get('limit') == 'ALL':
        params['limit'] = 'ALL'
        request.pop('limit')
    else:
        params['limit'] = int(request.pop('limit', 25))
    params['offset'] = int(request.pop('offset', 0))
    params['order_by'] = request.pop('order_by', 'created desc')

    if filter_keys:
        wrong_keys = [key for key in request.keys() if key not in filter_keys]
        if wrong_keys:
            raise RequestKeyError('{} request params not allowed. Allowed params - {}'.format(', '.join(wrong_keys),
                                                                                              ', '.join(filter_keys)))

    params['filter'] = dict()
    params['filter'].update(request)

    return params


class SignalMethodWrapper:
    """
    Wrapper object for a method to be called.
    """

    def __init__(self, instance, func, name):
        self.instance, self.func, self.name = instance, func, name
        assert instance is not None
        assert func is not None
        assert name is not None

    def __call__(self, *args, **kwargs):
        return self.instance._run_signals(self.name, self.func, *args, **kwargs)


class BaseSignal:
    registered_methods = []

    def __init__(self, signals: bool = True):
        if signals:
            self._enable_signals()

    def _enable_signals(self):
        for method in self.registered_methods:
            self.__setattr__('pre_{}'.format(method), [])
            self.__setattr__('post_{}'.format(method), [])
            func = getattr(self, method)
            if type(func) is MethodType:
                wrapper = SignalMethodWrapper(self, func, method)
                setattr(self, method, wrapper)

    def _run_signals(self, name, func, *args, **kwargs):
        pre_signals = getattr(self, 'pre_{}'.format(name))
        post_signals = getattr(self, 'post_{}'.format(name))

        self._run_coroutines(pre_signals, None, *args, **kwargs)
        if iscoroutinefunction(func):
            result = asyncio.ensure_future(func(*args, **kwargs))
            result.add_done_callback(partial(self._run_coroutines, post_signals, *args, **kwargs))
        else:
            result = func(*args, **kwargs)
            self._run_coroutines(post_signals, result, *args, **kwargs)

        return result

    def _run_coroutines(self, coroutines, result, *args, **kwargs):
        if type(result) is Future:
            result = result.result()
        for coro in coroutines:
            if iscoroutinefunction(coro):
                asyncio.ensure_future(coro(result, *args, **kwargs))
            else:
                coro(result, *args, **kwargs)


class CRUDModel(BaseSignal):<commit_msg>fixing signals<commit_after>import asyncio
from asyncio.coroutines import iscoroutinefunction
from asyncio.futures import Future
from functools import partial
from time import time
from types import MethodType

from asyncpg.exceptions import UniqueViolationError, UndefinedColumnError
from trellio import request, get, put, post, delete, api
from trelliopg import get_db_adapter

from trelliolibs.utils.helpers import json_serializer
from .decorators import TrellioValidator
from .helpers import RecordHelper, uuid_serializer, json_response


class RecordNotFound(Exception):
    pass


class RequestKeyError(Exception):
    pass


def extract_request_params(request, filter_keys=()):
    params = dict()
    if request.get('limit') and request.get('limit') == 'ALL':
        params['limit'] = 'ALL'
        request.pop('limit')
    else:
        params['limit'] = int(request.pop('limit', 25))
    params['offset'] = int(request.pop('offset', 0))
    params['order_by'] = request.pop('order_by', 'created desc')

    if filter_keys:
        wrong_keys = [key for key in request.keys() if key not in filter_keys]
        if wrong_keys:
            raise RequestKeyError('{} request params not allowed. Allowed params - {}'.format(', '.join(wrong_keys),
                                                                                              ', '.join(filter_keys)))

    params['filter'] = dict()
    params['filter'].update(request)

    return params


class SignalMethodWrapper:
    """
    Wrapper object for a method to be called.
    """

    def __init__(self, instance, func, name):
        self.instance, self.func, self.name = instance, func, name
        assert instance is not None
        assert func is not None
        assert name is not None

    def __call__(self, *args, **kwargs):
        return self.instance._run_signals(self.name, self.func, *args, **kwargs)


class BaseSignal:
    registered_methods = []

    def __init__(self, signals: bool = True):
        if signals:
            self._enable_signals()

    def _enable_signals(self):
        for method in self.registered_methods:
            self.__setattr__('pre_{}'.format(method), [])
            self.__setattr__('post_{}'.format(method), [])
            func = getattr(self, method)
            if type(func) is MethodType:
                wrapper = SignalMethodWrapper(self, func, method)
                setattr(self, method, wrapper)

    def _run_signals(self, name, func, *args, **kwargs):
        pre_signals = getattr(self, 'pre_{}'.format(name))
        post_signals = getattr(self, 'post_{}'.format(name))

        self._run_coroutines(pre_signals, None, *args, **kwargs)

        if iscoroutinefunction(func):
            result = asyncio.ensure_future(func(*args, **kwargs))
        else:
            result = func(*args, **kwargs)

        self._run_coroutines(post_signals, result, *args, **kwargs)
        return result

    def _run_coroutines(self, coroutines, result, *args, **kwargs):
        if type(result) is Future:
            result = result.result()
        for coro in coroutines:
            if iscoroutinefunction(coro):
                asyncio.ensure_future(coro(result, *args, **kwargs))
            else:
                coro(result, *args, **kwargs)


class CRUDModel(BaseSignal):
{'fraction_non_alphanumeric': 0.11063068435962427, 'fraction_numerical': 0.0008945877441479052, 'mean_word_length': 2.745393634840871, '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': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6480178', 'n_tokens_mistral': 1921, 'n_tokens_neox': 1873, 'n_words': 506}