<commit_before>from functools import wraps
import inspect
import json

from flask import Response, current_app, request
from werkzeug.wrappers import Response as ResponseBase

__all__ = ('ReturnableResponse', 'Prism', 'ResponseMapper')

class ReturnableResponse(Response):
    STATUS_OK = 200
    DEFAULT_MIMETYPE = 'text/json'

    PRISM_VERSION_ATTRIBUTE = 'prism_version'
    PRISM_MIMETYPE_ATTRIBUTE = 'prism_mimetype'

    def __init__(self, objects, status=STATUS_OK, as_list=False, mimetype=None):
        super(ReturnableResponse, self).__init__()
        if isinstance(objects, list):
            self.data_objects = objects
        else:
            self.data_objects = [objects]

        self.as_list = as_list

        # Get mimetype from representations
        mimetype_model_rep = self.get_mimetype_representation()
        if mimetype_model_rep != None:
            self.mimetype = mimetype_model_rep

        # If mimetype is defined in this response then override
        if mimetype != None:
            self.mimetype = mimetype

        self.response = self.build_response()
        self.status = str(status)
        self.mimetype = ReturnableResponse.DEFAULT_MIMETYPE if mimetype_model_rep == None else self.mimetype

    def get_mimetype_representation(self):

        for o in self.data_objects:
            func = self.get_representation_builder(o)

            if hasattr(func, ReturnableResponse.PRISM_MIMETYPE_ATTRIBUTE):
                return getattr(func, ReturnableResponse.PRISM_MIMETYPE_ATTRIBUTE)

        return None

    def get_representation_builder(self, object):
        # Get class name of object
        class_name = object.__class__.__name__

        # Determine if a blueprint is being used
        if request.blueprint != None:
            # Get BP from current app
            bp = current_app.blueprints[request.blueprint]

            # Get prism_version from BP if applicable
            version = getattr(bp, ReturnableResponse.PRISM_VERSION_ATTRIBUTE) \
                if hasattr(bp, ReturnableResponse.PRISM_VERSION_ATTRIBUTE) else None
        else:
            version = None

        # Get representation
        func = current_app.ext_prism.lookup_mappings(class_name, version=version)

        if func is None:
            raise Exception('Issue retrieving stored function reference for PRISM mapping on %s object. '
                            'Does this object have an api_response/is the right version defined?' % class_name)

        return func

    def get_representation_dict(self, object):
        # Get response from builder
        resp = self.get_representation_builder(object)(object)

        # Look for has_ methods and evaluate
        def evaluate_level(items):
            # TODO:// Convert and combine, this if statement is poor.
            if isinstance(items, dict):
                for k, v in items.items():
                    if isinstance(v, (dict, list)):
                        # If a dict or a list pass through eval_level again for further processing
                        evaluate_level(v)
                    elif isinstance(v, ResponseEvaluator.Killer):
                        # If killer object, pop this key (I doubt this will ever be hit, but just for safety)
                        items.pop(k, 0)
                    elif isinstance(v, ResponseEvaluator):
                        # If a response evaluator, evaluate
                        new_val = v.evaluate_for_response(object)

                        # If new_val is a Killer, pop this key and continue
                        if isinstance(new_val, ResponseEvaluator.Killer):
                            items.pop(k, 0)
                            continue

                        # If new_val is a list or dict, pass through eval_level again for further processing
                        if isinstance(new_val, (dict, list)):
                            evaluate_level(new_val)

                        items[k] = new_val

            elif isinstance(items, list):
                #TODO: At this point the only things left to do is handle the class name issue, if it's a list and not a dict (below)
                for i, v in enumerate(items):
                    if isinstance(v, (dict, list)):
                        # If a dict or list pass through eval_level again for further processing
                        evaluate_level(v)
                    elif isinstance(v, ResponseEvaluator.Killer):
                        # If a killer object, remove this item from the list
                        items.remove(v)
                    elif isinstance(v, ResponseEvaluator):
                        # If it's a response evaluator, evaluate it
                        new_val = v.evaluate_for_response(object)

                        # If new_val is a Killer, remove this value and continue
                        if isinstance(new_val, ResponseEvaluator.Killer):
                            items.remove(v)
                            continue

                        # If new_val is a list or dict, pass through eval_level again for further processing
                        if isinstance(new_val, (dict, list)):
                            evaluate_level(new_val)

                        items[i] = new_val

            return items

        final = evaluate_level(resp)

        return final

    def build_response(self):
        return_objects = {} if not self.as_list or self.data_objects.__len__() > 1 else []

        if self.data_objects.__len__() > 1:

            pass
        elif self.data_objects.__len__() == 1:
            r = self.get_representation_dict(self.data_objects[0])
            return_objects = r

        return json.dumps(return_objects)


class Prism(object):
    def __init__(self, app=None):
        self.app = app
        self.mapper = ResponseMapper()

        if app is not None:<commit_msg>Fix for multiple objects through returnable response<commit_after>from functools import wraps
import inspect
import json

from flask import Response, current_app, request
from werkzeug.wrappers import Response as ResponseBase

__all__ = ('ReturnableResponse', 'Prism', 'ResponseMapper')

class ReturnableResponse(Response):
    STATUS_OK = 200
    DEFAULT_MIMETYPE = 'text/json'

    PRISM_VERSION_ATTRIBUTE = 'prism_version'
    PRISM_MIMETYPE_ATTRIBUTE = 'prism_mimetype'

    def __init__(self, objects, status=STATUS_OK, as_list=False, mimetype=None):
        super(ReturnableResponse, self).__init__()
        if isinstance(objects, list):
            self.data_objects = objects
        else:
            self.data_objects = [objects]

        self.as_list = as_list

        # Get mimetype from representations
        mimetype_model_rep = self.get_mimetype_representation()
        if mimetype_model_rep != None:
            self.mimetype = mimetype_model_rep

        # If mimetype is defined in this response then override
        if mimetype != None:
            self.mimetype = mimetype

        self.response = self.build_response()
        self.status = str(status)
        self.mimetype = ReturnableResponse.DEFAULT_MIMETYPE if mimetype_model_rep == None else self.mimetype

    def get_mimetype_representation(self):

        for o in self.data_objects:
            func = self.get_representation_builder(o)

            if hasattr(func, ReturnableResponse.PRISM_MIMETYPE_ATTRIBUTE):
                return getattr(func, ReturnableResponse.PRISM_MIMETYPE_ATTRIBUTE)

        return None

    def get_representation_builder(self, object):
        # Get class name of object
        class_name = object.__class__.__name__

        # Determine if a blueprint is being used
        if request.blueprint != None:
            # Get BP from current app
            bp = current_app.blueprints[request.blueprint]

            # Get prism_version from BP if applicable
            version = getattr(bp, ReturnableResponse.PRISM_VERSION_ATTRIBUTE) \
                if hasattr(bp, ReturnableResponse.PRISM_VERSION_ATTRIBUTE) else None
        else:
            version = None

        # Get representation
        func = current_app.ext_prism.lookup_mappings(class_name, version=version)

        if func is None:
            raise Exception('Issue retrieving stored function reference for PRISM mapping on %s object. '
                            'Does this object have an api_response/is the right version defined?' % class_name)

        return func

    def get_representation_dict(self, object):
        # Get response from builder
        resp = self.get_representation_builder(object)(object)

        # Look for has_ methods and evaluate
        def evaluate_level(items):
            # TODO:// Convert and combine, this if statement is poor.
            if isinstance(items, dict):
                for k, v in items.items():
                    if isinstance(v, (dict, list)):
                        # If a dict or a list pass through eval_level again for further processing
                        evaluate_level(v)
                    elif isinstance(v, ResponseEvaluator.Killer):
                        # If killer object, pop this key (I doubt this will ever be hit, but just for safety)
                        items.pop(k, 0)
                    elif isinstance(v, ResponseEvaluator):
                        # If a response evaluator, evaluate
                        new_val = v.evaluate_for_response(object)

                        # If new_val is a Killer, pop this key and continue
                        if isinstance(new_val, ResponseEvaluator.Killer):
                            items.pop(k, 0)
                            continue

                        # If new_val is a list or dict, pass through eval_level again for further processing
                        if isinstance(new_val, (dict, list)):
                            evaluate_level(new_val)

                        items[k] = new_val

            elif isinstance(items, list):
                #TODO: At this point the only things left to do is handle the class name issue, if it's a list and not a dict (below)
                for i, v in enumerate(items):
                    if isinstance(v, (dict, list)):
                        # If a dict or list pass through eval_level again for further processing
                        evaluate_level(v)
                    elif isinstance(v, ResponseEvaluator.Killer):
                        # If a killer object, remove this item from the list
                        items.remove(v)
                    elif isinstance(v, ResponseEvaluator):
                        # If it's a response evaluator, evaluate it
                        new_val = v.evaluate_for_response(object)

                        # If new_val is a Killer, remove this value and continue
                        if isinstance(new_val, ResponseEvaluator.Killer):
                            items.remove(v)
                            continue

                        # If new_val is a list or dict, pass through eval_level again for further processing
                        if isinstance(new_val, (dict, list)):
                            evaluate_level(new_val)

                        items[i] = new_val

            return items

        final = evaluate_level(resp)

        return final

    def build_response(self):
        return_objects = {} if not self.as_list and self.data_objects.__len__() > 1 else []

        if self.data_objects.__len__() > 1:
            for o in self.data_objects:
                return_objects.append(self.get_representation_dict(o))

        elif self.data_objects.__len__() == 1:
            r = self.get_representation_dict(self.data_objects[0])
            return_objects = r

        return json.dumps(return_objects)


class Prism(object):
    def __init__(self, app=None):
        self.app = app
        self.mapper = ResponseMapper()

        if app is not None:
{'fraction_non_alphanumeric': 0.06355861143719604, 'fraction_numerical': 0.0015093073956062384, 'mean_word_length': 1.824964471814306, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1918307', 'n_tokens_mistral': 3130, 'n_tokens_neox': 2925, 'n_words': 925}