<commit_before># No shebang line, this module is meant to be imported
#
# Copyright 2013 <NAME>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Resource
--------

Base resources which can be used to build top leve
documents, pages, or other types of data for the web.
"""

from json import loads
from httplib import (
    responses, INTERNAL_SERVER_ERROR, NOT_FOUND, BAD_REQUEST,
    UNSUPPORTED_MEDIA_TYPE, METHOD_NOT_ALLOWED)

try:
    from itertools import ifilter as filter_
except ImportError:
    filter_ = filter

from twisted.web.server import NOT_DONE_YET
from twisted.web.resource import Resource as _Resource

from pyfarm.core.enums import STRING_TYPES
from pyfarm.agent.http.core import template
from pyfarm.agent.utility import dumps


class Resource(_Resource):
    """
    basic subclass of :class:`._Resource` for passing requests to
    specific methods
    """
    TEMPLATE = NotImplemented
    CONTENT_TYPES = set(["text/html", "application/json"])
    LOAD_DATA_FOR_METHODS = set(["POST", "PUT"])

    def __init__(self):
        _Resource.__init__(self)
        assert isinstance(self.CONTENT_TYPES, set)

    @property
    def template(self):
        """
        Loads the template provided but the partial path in ``TEMPLATE`` on
        the class.
        """
        if self.TEMPLATE is NotImplemented:
            raise NotImplementedError("You must set `TEMPLATE` first")
        return template.load(self.TEMPLATE)

    @property
    def methods(self):
        """A set containing all the methods this resource implements."""
        methods = set()
        for method in ("get", "post", "put", "delete", "head"):
            for attribute_name in (method, "render_%s" % method.upper()):
                attribute = getattr(self, attribute_name, None)
                if attribute is not None:
                    methods.add(method)
        return methods

    def content_types(self, request, default=None):
        """Returns the content type(s) present in the request"""
        headers = request.requestHeaders.getRawHeaders("content-type")
        if isinstance(default, STRING_TYPES):
            default = [default]
        elif default is None:
            default = []
        return set(headers) if headers is not None else set(default)

    def putChild(self, path, child):
        """
        Overrides the builtin putChild() so we can return the results for
        each call and use them externally
        """
        _Resource.putChild(self, path, child)
        return child

    def error(self, request, code, message):
        """
        Writes the proper out an error response message depending on the
        content type in the request
        """
        content_types = self.content_types(request, default="text/html")

        if "text/html" in content_types:
            request.setResponseCode(code)
            html_error = template.load("error.html")
            deferred = html_error.render(
                code=code, code_msg=responses[code], message=message)
            deferred.addCallback(request.write).addCallback(
                lambda _: request.finish())

        elif "application/json" in content_types:
            request.setResponseCode(code)
            request.write(dumps(error=message))
            request.finish()

        else:
            request.setResponseCode(INTERNAL_SERVER_ERROR)
            request.write(
                dumps(
                    error="Can only handle text/html or application/json here"))
            request.finish()

    def render(self, request):
        # I this is a leaf, meaning the end of the uri branch, then
        # make sure the uri ends with '/'.  Proper REST-like services
        # differentiate between /foo and /foo/ but twisted generally does
        # not care so we enforce it ourselves.
        if self.isLeaf and not request.uri.endswith("/"):
            self.error(request, NOT_FOUND, "%s does not exist" % request.uri)
            return NOT_DONE_YET

        # make sure that the requested content type is supported
        content_type = self.content_types(request, default="text/html")
        if not self.CONTENT_TYPES & content_type:
            self.error(
                request, UNSUPPORTED_MEDIA_TYPE,
                "%s is not a support content type for this url" % content_type)
            return NOT_DONE_YET

        # Try to find the method this web request is making by first trying
        # our usual convention then the 'standard' convention.
        request_methods = (request.method.lower(), "render_%s" % request.method)
        for method_name in request_methods:
            if hasattr(self, method_name):
                kwargs = {"request": request}

                # unpack the incoming data for the request
                if "application/json" in content_type \
                        and request.method in self.LOAD_DATA_FOR_METHODS:
                    try:
                        data = loads(request.content.read())
                    except ValueError as e:
                        self.error(
                            request, BAD_REQUEST,
                            "Failed to decode json data: %r" % e)
                        return NOT_DONE_YET
                    else:
                        kwargs.update(data=data)

                return getattr(self, method_name)(**kwargs)

        # If we could not find function to call for the given method
        # produce a warning.
        else:
            supported_methods = self.methods
            if not supported_methods:
                message = "%r does not support any methods" % request.uri
            else:
                message = "%r only supports the %s method(s)" % (
                    request.uri,<commit_msg>check for empty data<commit_after># No shebang line, this module is meant to be imported
#
# Copyright 2013 <NAME>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Resource
--------

Base resources which can be used to build top leve
documents, pages, or other types of data for the web.
"""

from json import loads
from httplib import (
    responses, INTERNAL_SERVER_ERROR, NOT_FOUND, BAD_REQUEST,
    UNSUPPORTED_MEDIA_TYPE, METHOD_NOT_ALLOWED)

try:
    from itertools import ifilter as filter_
except ImportError:
    filter_ = filter

from twisted.web.server import NOT_DONE_YET
from twisted.web.resource import Resource as _Resource

from pyfarm.core.enums import STRING_TYPES
from pyfarm.agent.http.core import template
from pyfarm.agent.utility import dumps


class Resource(_Resource):
    """
    basic subclass of :class:`._Resource` for passing requests to
    specific methods
    """
    TEMPLATE = NotImplemented
    CONTENT_TYPES = set(["text/html", "application/json"])
    LOAD_DATA_FOR_METHODS = set(["POST", "PUT"])

    def __init__(self):
        _Resource.__init__(self)
        assert isinstance(self.CONTENT_TYPES, set)

    @property
    def template(self):
        """
        Loads the template provided but the partial path in ``TEMPLATE`` on
        the class.
        """
        if self.TEMPLATE is NotImplemented:
            raise NotImplementedError("You must set `TEMPLATE` first")
        return template.load(self.TEMPLATE)

    @property
    def methods(self):
        """A set containing all the methods this resource implements."""
        methods = set()
        for method in ("get", "post", "put", "delete", "head"):
            for attribute_name in (method, "render_%s" % method.upper()):
                attribute = getattr(self, attribute_name, None)
                if attribute is not None:
                    methods.add(method)
        return methods

    def content_types(self, request, default=None):
        """Returns the content type(s) present in the request"""
        headers = request.requestHeaders.getRawHeaders("content-type")
        if isinstance(default, STRING_TYPES):
            default = [default]
        elif default is None:
            default = []
        return set(headers) if headers is not None else set(default)

    def putChild(self, path, child):
        """
        Overrides the builtin putChild() so we can return the results for
        each call and use them externally
        """
        _Resource.putChild(self, path, child)
        return child

    def error(self, request, code, message):
        """
        Writes the proper out an error response message depending on the
        content type in the request
        """
        content_types = self.content_types(request, default="text/html")

        if "text/html" in content_types:
            request.setResponseCode(code)
            html_error = template.load("error.html")
            deferred = html_error.render(
                code=code, code_msg=responses[code], message=message)
            deferred.addCallback(request.write).addCallback(
                lambda _: request.finish())

        elif "application/json" in content_types:
            request.setResponseCode(code)
            request.write(dumps(error=message))
            request.finish()

        else:
            request.setResponseCode(INTERNAL_SERVER_ERROR)
            request.write(
                dumps(
                    error="Can only handle text/html or application/json here"))
            request.finish()

    def render(self, request):
        # I this is a leaf, meaning the end of the uri branch, then
        # make sure the uri ends with '/'.  Proper REST-like services
        # differentiate between /foo and /foo/ but twisted generally does
        # not care so we enforce it ourselves.
        if self.isLeaf and not request.uri.endswith("/"):
            self.error(request, NOT_FOUND, "%s does not exist" % request.uri)
            return NOT_DONE_YET

        # make sure that the requested content type is supported
        content_type = self.content_types(request, default="text/html")
        if not self.CONTENT_TYPES & content_type:
            self.error(
                request, UNSUPPORTED_MEDIA_TYPE,
                "%s is not a support content type for this url" % content_type)
            return NOT_DONE_YET

        # Try to find the method this web request is making by first trying
        # our usual convention then the 'standard' convention.
        request_methods = (request.method.lower(), "render_%s" % request.method)
        for method_name in request_methods:
            if hasattr(self, method_name):
                kwargs = {"request": request}

                # Unpack the incoming data for the request
                if "application/json" in content_type \
                        and request.method in self.LOAD_DATA_FOR_METHODS:
                    request_content = request.content.read()

                    # Check to see if we have any incoming data at all
                    if not request_content.strip():
                        self.error(request, BAD_REQUEST, "No data provided")
                        return NOT_DONE_YET

                    # Either load the data or handle the error, don't call
                    # the method unless we're successful.
                    try:
                        data = loads(request_content)

                    except ValueError as e:
                        self.error(
                            request, BAD_REQUEST,
                            "Failed to decode json data: %r" % e)
                        return NOT_DONE_YET

                    else:
                        kwargs.update(data=data)

                return getattr(self, method_name)(**kwargs)

        # If we could not find function to call for the given method
        # produce a warning.
        else:
            supported_methods = self.methods
            if not supported_methods:
                message = "%r does not support any methods" % request.uri
            else:
                message = "%r only supports the %s method(s)" % (
                    request.uri,
{'fraction_non_alphanumeric': 0.07942989214175655, 'fraction_numerical': 0.0012326656394453005, 'mean_word_length': 2.121182976677086, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '3849129', 'n_tokens_mistral': 3386, 'n_tokens_neox': 3277, 'n_words': 1176}