<commit_before># This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Handler for the /lab URLs."""

from urlparse import urlunparse

import datetime
import bson

import handlers.base
import handlers.common
import handlers.response as hresponse
import models
import models.lab as mlab
import models.token as mtoken
import utils.validator as validator
import utils.db


# pylint: disable=too-many-public-methods
class LabHandler(handlers.base.BaseHandler):
    """Handle all traffic through the /lab URLs."""

    def __init__(self, application, request, **kwargs):
        super(LabHandler, self).__init__(application, request, **kwargs)

    @property
    def collection(self):
        return self.db[models.LAB_COLLECTION]

    @staticmethod
    def _valid_keys(method):
        return handlers.common.LAB_VALID_KEYS.get(method, None)

    @staticmethod
    def _token_validation_func():
        return handlers.common.valid_token_th

    def _post(self, *args, **kwargs):
        response = hresponse.HandlerResponse(201)

        json_obj = kwargs["json_obj"]

        valid_contact, reason = validator.is_valid_lab_contact_data(json_obj)
        if valid_contact:
            lab_id = kwargs.get("id", None)
            status_code, reason, result, headers = self._create_or_update(
                json_obj, lab_id)

            response.status_code = status_code
            response.result = result
            if reason:
                if kwargs["reason"]:
                    reason += "\n" + kwargs["reason"]
                response.reason = reason
            if headers:
                response.headers = headers
        else:
            response.status_code = 400
            if reason:
                if kwargs["reason"]:
                    reason += "\n" + kwargs["reason"]
                response.reason = reason

        return response

    def _create_or_update(self, json_obj, lab_id):
        """Create or update a new lab object.

        If the request comes in with a specified lab name, it will be treated
        as an update request.

        :param json_obj: The JSON data as sent in the request.
        :type json_obj: dict
        :param lab_id: The ID part of the request.
        :type lab_id: str
        :return A tuple with: status code, reason, result and headers.
        """
        status_code = None
        reason = None
        result = None
        headers = None
        old_lab = None
        name = json_obj.get(models.NAME_KEY)

        if lab_id:
            try:
                old_lab = utils.db.find_one(
                    self.collection,
                    [bson.objectid.ObjectId(lab_id)]
                )
            except bson.errors.InvalidId, ex:
                self.log.exception(ex)
                self.log.error("Wrong ID value '%s' passed as doc ID", lab_id)
                reason = "Wrong ID value provided"
        else:
            old_lab = utils.db.find_one(
                self.collection, [name], field=models.NAME_KEY
            )

        if all([lab_id, old_lab]):
            self.log.info(
                "Updating lab with ID '%s' from IP address %s",
                old_lab.get(models.ID_KEY), self.request.remote_ip
            )
            status_code, reason, result, headers = self._update_lab(
                json_obj, old_lab
            )
        elif all([lab_id, not old_lab]):
            status_code = 404
            reason = "Lab with name '%s' not found" % lab_id
        elif all([not old_lab, not lab_id]):
            self.log.info("Creating new lab object")
            status_code, reason, result, headers = self._create_new_lab(
                json_obj)
        else:
            status_code = 400
            if not reason:
                reason = (
                    "Lab with name '%s' already exists: did you mean to "
                    "update it?" % name
                )

        return status_code, reason, result, headers

    def _update_lab(self, json_obj, old_lab):
        """Update an existing lab object.

        :param json_obj: The JSON object with the lab data.
        :type json_obj: dict
        :param old_lab: The JSON object of the lab from the db.
        :type old_lab: dict
        :return A tuple with: status code, reason, result and headers.
        """
        status_code = None
        reason = None
        result = None
        headers = None

        # Locally used to store the contact information from the new lab object.
        new_contact = None

        old_lab = mlab.LabDocument.from_json(old_lab)
        new_lab = mlab.LabDocument.from_json(json_obj)

        if new_lab.name:
            if old_lab.name != new_lab.name:
                old_lab._name = new_lab.name

        if new_lab.contact:<commit_msg>Add comment.<commit_after># This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Handler for the /lab URLs."""

from urlparse import urlunparse

import datetime
import bson

import handlers.base
import handlers.common
import handlers.response as hresponse
import models
import models.lab as mlab
import models.token as mtoken
import utils.validator as validator
import utils.db


# pylint: disable=too-many-public-methods
class LabHandler(handlers.base.BaseHandler):
    """Handle all traffic through the /lab URLs."""

    def __init__(self, application, request, **kwargs):
        super(LabHandler, self).__init__(application, request, **kwargs)

    @property
    def collection(self):
        return self.db[models.LAB_COLLECTION]

    @staticmethod
    def _valid_keys(method):
        return handlers.common.LAB_VALID_KEYS.get(method, None)

    @staticmethod
    def _token_validation_func():
        return handlers.common.valid_token_th

    def _post(self, *args, **kwargs):
        response = hresponse.HandlerResponse(201)

        json_obj = kwargs["json_obj"]

        valid_contact, reason = validator.is_valid_lab_contact_data(json_obj)
        if valid_contact:
            lab_id = kwargs.get("id", None)
            status_code, reason, result, headers = self._create_or_update(
                json_obj, lab_id)

            response.status_code = status_code
            response.result = result
            if reason:
                if kwargs["reason"]:
                    reason += "\n" + kwargs["reason"]
                response.reason = reason
            if headers:
                response.headers = headers
        else:
            response.status_code = 400
            if reason:
                if kwargs["reason"]:
                    reason += "\n" + kwargs["reason"]
                response.reason = reason

        return response

    def _create_or_update(self, json_obj, lab_id):
        """Create or update a new lab object.

        If the request comes in with a specified lab name, it will be treated
        as an update request.

        :param json_obj: The JSON data as sent in the request.
        :type json_obj: dict
        :param lab_id: The ID part of the request.
        :type lab_id: str
        :return A tuple with: status code, reason, result and headers.
        """
        status_code = None
        reason = None
        result = None
        headers = None
        old_lab = None
        name = json_obj.get(models.NAME_KEY)

        if lab_id:
            try:
                old_lab = utils.db.find_one(
                    self.collection,
                    [bson.objectid.ObjectId(lab_id)]
                )
            except bson.errors.InvalidId, ex:
                self.log.exception(ex)
                self.log.error("Wrong ID value '%s' passed as doc ID", lab_id)
                reason = "Wrong ID value provided"
        else:
            old_lab = utils.db.find_one(
                self.collection, [name], field=models.NAME_KEY
            )

        if all([lab_id, old_lab]):
            self.log.info(
                "Updating lab with ID '%s' from IP address %s",
                old_lab.get(models.ID_KEY), self.request.remote_ip
            )
            status_code, reason, result, headers = self._update_lab(
                json_obj, old_lab
            )
        elif all([lab_id, not old_lab]):
            status_code = 404
            reason = "Lab with name '%s' not found" % lab_id
        elif all([not old_lab, not lab_id]):
            self.log.info("Creating new lab object")
            status_code, reason, result, headers = self._create_new_lab(
                json_obj)
        else:
            status_code = 400
            if not reason:
                reason = (
                    "Lab with name '%s' already exists: did you mean to "
                    "update it?" % name
                )

        return status_code, reason, result, headers

    def _update_lab(self, json_obj, old_lab):
        """Update an existing lab object.

        :param json_obj: The JSON object with the lab data.
        :type json_obj: dict
        :param old_lab: The JSON object of the lab from the db.
        :type old_lab: dict
        :return A tuple with: status code, reason, result and headers.
        """
        status_code = None
        reason = None
        result = None
        headers = None

        # Locally used to store the contact information from the new lab object.
        new_contact = None

        old_lab = mlab.LabDocument.from_json(old_lab)
        new_lab = mlab.LabDocument.from_json(json_obj)

        if new_lab.name:
            if old_lab.name != new_lab.name:
                # The is no setter for the name field in the Lab model.
                old_lab._name = new_lab.name

        if new_lab.contact:
{'fraction_non_alphanumeric': 0.07886726316760446, 'fraction_numerical': 0.002398302739599668, 'mean_word_length': 1.9614859328052445, 'pattern_counts': {'":': 0, '<': 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': '4396970', 'n_tokens_mistral': 3014, 'n_tokens_neox': 2880, 'n_words': 996}