<commit_before># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

import traceback

from mongoengine import ValidationError

from st2common.exceptions import db as db_exceptions
from st2common.exceptions import rbac as rbac_exceptions
from st2common.exceptions.apivalidation import ValueValidationException
from st2common import log as logging
from st2common.router import exc, Response, NotFoundException
from st2common.util.debugging import is_enabled as is_debugging_enabled
from st2common.util.jsonify import json_encode


LOG = logging.getLogger(__name__)


class ErrorHandlingMiddleware(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        try:
            try:
                return self.app(environ, start_response)
            except NotFoundException:
                raise exc.HTTPNotFound()
        except Exception as e:
            status = getattr(e, 'code', exc.HTTPInternalServerError.code)

            if hasattr(e, 'detail') and not getattr(e, 'comment'):
                setattr(e, 'comment', getattr(e, 'detail'))

            if hasattr(e, 'body') and isinstance(getattr(e, 'body', None), dict):
                body = getattr(e, 'body', None)
            else:
                body = {}

            if isinstance(e, exc.HTTPException):
                status_code = status
                message = str(e)
            elif isinstance(e, db_exceptions.StackStormDBObjectNotFoundError):
                status_code = exc.HTTPNotFound.code
                message = str(e)
            elif isinstance(e, db_exceptions.StackStormDBObjectConflictError):
                status_code = exc.HTTPConflict.code
                message = str(e)
                body['conflict-id'] = getattr(e, 'conflict_id', None)
            elif isinstance(e, rbac_exceptions.AccessDeniedError):
                status_code = exc.HTTPForbidden.code
                message = str(e)
            elif isinstance(e, (ValueValidationException, ValueError, ValidationError)):
                status_code = exc.HTTPBadRequest.code
                message = getattr(e, 'message', str(e))
            else:
                status_code = exc.HTTPInternalServerError.code
                message = 'Internal Server Error'

            # Log the error
            is_internal_server_error = status_code == exc.HTTPInternalServerError.code
            error_msg = getattr(e, 'comment', str(e))
            extra = {
                'exception_class': e.__class__.__name__,
                'exception_message': str(e),
                'exception_data': e.__dict__
            }

            if is_internal_server_error:
                LOG.exception('API call failed: %s', error_msg, extra=extra)
                LOG.exception(traceback.format_exc())
            else:
                LOG.debug('API call failed: %s', error_msg, extra=extra)

                if is_debugging_enabled():
                    LOG.debug(traceback.format_exc())

            body['faultstring'] = message

            response_body = json_encode(body)
            headers = {
                'Content-Type': 'application/json',
                'Content-Length': str(len(response_body))
            }

            resp = Response(response_body, status=status_code, headers=headers)

            return resp(environ, start_response)<commit_msg>Fix traceback duplication in ErrorHandlingMiddleware<commit_after># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

import traceback

from mongoengine import ValidationError

from st2common.exceptions import db as db_exceptions
from st2common.exceptions import rbac as rbac_exceptions
from st2common.exceptions.apivalidation import ValueValidationException
from st2common import log as logging
from st2common.router import exc, Response, NotFoundException
from st2common.util.debugging import is_enabled as is_debugging_enabled
from st2common.util.jsonify import json_encode


LOG = logging.getLogger(__name__)


class ErrorHandlingMiddleware(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        try:
            try:
                return self.app(environ, start_response)
            except NotFoundException:
                raise exc.HTTPNotFound()
        except Exception as e:
            status = getattr(e, 'code', exc.HTTPInternalServerError.code)

            if hasattr(e, 'detail') and not getattr(e, 'comment'):
                setattr(e, 'comment', getattr(e, 'detail'))

            if hasattr(e, 'body') and isinstance(getattr(e, 'body', None), dict):
                body = getattr(e, 'body', None)
            else:
                body = {}

            if isinstance(e, exc.HTTPException):
                status_code = status
                message = str(e)
            elif isinstance(e, db_exceptions.StackStormDBObjectNotFoundError):
                status_code = exc.HTTPNotFound.code
                message = str(e)
            elif isinstance(e, db_exceptions.StackStormDBObjectConflictError):
                status_code = exc.HTTPConflict.code
                message = str(e)
                body['conflict-id'] = getattr(e, 'conflict_id', None)
            elif isinstance(e, rbac_exceptions.AccessDeniedError):
                status_code = exc.HTTPForbidden.code
                message = str(e)
            elif isinstance(e, (ValueValidationException, ValueError, ValidationError)):
                status_code = exc.HTTPBadRequest.code
                message = getattr(e, 'message', str(e))
            else:
                status_code = exc.HTTPInternalServerError.code
                message = 'Internal Server Error'

            # Log the error
            is_internal_server_error = status_code == exc.HTTPInternalServerError.code
            error_msg = getattr(e, 'comment', str(e))
            extra = {
                'exception_class': e.__class__.__name__,
                'exception_message': str(e),
                'exception_data': e.__dict__
            }

            if is_internal_server_error:
                LOG.exception('API call failed: %s', error_msg, extra=extra)
            else:
                LOG.debug('API call failed: %s', error_msg, extra=extra)

                if is_debugging_enabled():
                    LOG.debug(traceback.format_exc())

            body['faultstring'] = message

            response_body = json_encode(body)
            headers = {
                'Content-Type': 'application/json',
                'Content-Length': str(len(response_body))
            }

            resp = Response(response_body, status=status_code, headers=headers)

            return resp(environ, start_response)
{'fraction_non_alphanumeric': 0.08082041264802832, 'fraction_numerical': 0.002685874740568917, 'mean_word_length': 2.3684210526315788, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '7582633', 'n_tokens_mistral': 2142, 'n_tokens_neox': 2057, 'n_words': 628}