<commit_before>from aiohttp.web_reqrep import FileField
import csv
from io import StringIO
import logging
from pymongo.errors import AutoReconnect
import re
from uuid import uuid4

from nyuki.api import Response, resource, content_type
from nyuki.workflow.tasks import FACTORY_SCHEMAS


log = logging.getLogger(__name__)


@resource('/workflow/rules', versions=['v1'])
class ApiFactoryRules:

    async def get(self, request):
        return Response(list(FACTORY_SCHEMAS.keys()))


def new_regex(title, pattern, regex_id=None):
    return {
        'id': regex_id or str(uuid4()),
        'title': title,
        'pattern': pattern
    }


@resource('/workflow/regexes', versions=['v1'])
class ApiFactoryRegexes:

    async def get(self, request):
        """
        Return the list of all regexes
        """
        try:
            regexes = await self.nyuki.storage.regexes.get_all()
        except AutoReconnect:
            return Response(status=503)
        return Response(regexes)

    async def put(self, request):
        """
        Insert a new regex
        """
        request = await request.json()

        try:
            regex = new_regex(request['title'], request['pattern'])
        except KeyError as exc:
            return Response(status=400, body={
                'error': 'missing parameter {}'.format(exc)
            })

        try:
            await self.nyuki.storage.regexes.insert(regex)
        except AutoReconnect:
            return Response(status=503)
        return Response(regex)

    async def delete(self, request):
        """
        Delete all regexes and return the list
        """
        try:
            rules = await self.nyuki.storage.regexes.get_all()
        except AutoReconnect:
            return Response(status=503)
        await self.nyuki.storage.regexes.delete()
        return Response(rules)


@resource('/workflow/regexes/{regex_id}', versions=['v1'])
class ApiFactoryRegex:

    async def get(self, request, regex_id):
        """
        Return the regex for id `regex_id`
        """
        try:
            regex = await self.nyuki.storage.regexes.get(regex_id)
        except AutoReconnect:
            return Response(status=503)
        if not regex:
            return Response(status=404)
        return Response(regex)

    async def patch(self, request, regex_id):
        """
        Modify an existing regex
        """
        try:
            regex = await self.nyuki.storage.regexes.get(regex_id)
        except AutoReconnect:
            return Response(status=503)
        if not regex:
            return Response(status=404)

        request = await request.json()
        regex = new_regex(
            request.get('title', regex['title']),
            request.get('pattern', regex['pattern']),
            regex_id=regex_id
        )
        await self.nyuki.storage.regexes.insert(regex)
        return Response(regex)

    async def delete(self, request, regex_id):
        """
        Delete the regex with id `regex_id`
        """
        try:<commit_msg>Ensuring stored regexes can be compiled<commit_after>from aiohttp.web_reqrep import FileField
import csv
from io import StringIO
import logging
from pymongo.errors import AutoReconnect
import re
from re import error as re_error
from uuid import uuid4

from nyuki.api import Response, resource, content_type
from nyuki.workflow.tasks import FACTORY_SCHEMAS


log = logging.getLogger(__name__)


@resource('/workflow/rules', versions=['v1'])
class ApiFactoryRules:

    async def get(self, request):
        return Response(list(FACTORY_SCHEMAS.keys()))


def new_regex(title, pattern, regex_id=None):
    re.compile(pattern)
    return {
        'id': regex_id or str(uuid4()),
        'title': title,
        'pattern': pattern
    }


@resource('/workflow/regexes', versions=['v1'])
class ApiFactoryRegexes:

    async def get(self, request):
        """
        Return the list of all regexes
        """
        try:
            regexes = await self.nyuki.storage.regexes.get_all()
        except AutoReconnect:
            return Response(status=503)
        return Response(regexes)

    async def put(self, request):
        """
        Insert a new regex
        """
        request = await request.json()

        try:
            regex = new_regex(request['title'], request['pattern'])
        except KeyError as exc:
            return Response(status=400, body={
                'error': 'missing parameter {}'.format(exc)
            })
        except re_error as exc:
            return Response(status=400, body={
                'error': 'invalid regular expression {}'.format(exc),
                'error_code': 'invalid_regex'
            })

        try:
            await self.nyuki.storage.regexes.insert(regex)
        except AutoReconnect:
            return Response(status=503)
        return Response(regex)

    async def delete(self, request):
        """
        Delete all regexes and return the list
        """
        try:
            rules = await self.nyuki.storage.regexes.get_all()
        except AutoReconnect:
            return Response(status=503)
        await self.nyuki.storage.regexes.delete()
        return Response(rules)


@resource('/workflow/regexes/{regex_id}', versions=['v1'])
class ApiFactoryRegex:

    async def get(self, request, regex_id):
        """
        Return the regex for id `regex_id`
        """
        try:
            regex = await self.nyuki.storage.regexes.get(regex_id)
        except AutoReconnect:
            return Response(status=503)
        if not regex:
            return Response(status=404)
        return Response(regex)

    async def patch(self, request, regex_id):
        """
        Modify an existing regex
        """
        try:
            regex = await self.nyuki.storage.regexes.get(regex_id)
        except AutoReconnect:
            return Response(status=503)
        if not regex:
            return Response(status=404)

        request = await request.json()
        try:
            regex = new_regex(
                request.get('title', regex['title']),
                request.get('pattern', regex['pattern']),
                regex_id=regex_id
            )
        except re_error as exc:
            return Response(status=400, body={
                'error': 'invalid regular expression {}'.format(exc),
                'error_code': 'invalid_regex'
            })
        await self.nyuki.storage.regexes.insert(regex)
        return Response(regex)

    async def delete(self, request, regex_id):
        """
        Delete the regex with id `regex_id`
        """
        try:
{'fraction_non_alphanumeric': 0.10258724428399518, 'fraction_numerical': 0.009626955475330927, 'mean_word_length': 2.1230624706434944, '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': '640597', 'n_tokens_mistral': 1871, 'n_tokens_neox': 1811, 'n_words': 474}