<commit_before>from flask import current_app as app, abort
from eve.utils import config, debug_error_message, ParsedRequest
from werkzeug.exceptions import BadRequestKeyError


def versioned_id_field(resource_settings):
    """ Shorthand to add two commonly added versioning parameters.

    .. versionadded: 0.4
    """
    return resource_settings['id_field'] + app.config['VERSION_ID_SUFFIX']


def resolve_document_version(document, resource, method, latest_doc=None):
    """ Version number logic for all methods.

    :param document: the document in question.
    :param resource: the resource of the request/document.
    :param method: method coorsponding to the request.
    :param latest_doc: the most recent version of the document.

    .. versionadded:: 0.4
    """
    resource_def = app.config['DOMAIN'][resource]
    version = app.config['VERSION']
    latest_version = app.config['LATEST_VERSION']

    if resource_def['versioning'] is True:
        # especially on collection endpoints, we don't to encure an extra
        # lookup if we are already pulling the latest version
        if method == 'GET' and latest_doc is None:
            if version not in document:
                # well it should be... the api designer must have turned on
                # versioning after data was already in the collection or the
                # collection has been modified without respecting versioning
                document[version] = 1  # the first saved version will be 2
            document[latest_version] = document[version]

        # include latest_doc if the request is for an older version so that we
        # can set the latest_version field in the response
        if method == 'GET' and latest_doc is not None:
            if version not in latest_doc:
                # well it should be... the api designer must have turned on
                # versioning after data was already in the collection or the
                # collection has been modified without respecting versioning
                document[version] = 1  # the first saved version will be 2
                document[latest_version] = document[version]
            else:
                document[latest_version] = latest_doc[version]
                if version not in document:
                    # this version was put in the database before versioning
                    # was turned on or outside of Eve
                    document[version] = 1

        if method == 'POST':
            # this one is easy! it is a new document
            document[version] = 1

        if method == 'PUT' or method == 'PATCH' or \
                (method == 'DELETE' and resource_def['soft_delete'] is True):
            if not latest_doc:
                abort(500, description=debug_error_message(
                    'I need the latest document here!'
                ))
            if version in latest_doc:
                # all is right in the world :)
                document[version] = latest_doc[version] + 1
            else:
                # if versioning was just turned on, then we will start
                # versioning now. if the db was modified outside of Eve or
                # versioning was turned of for a while, version numbers will
                # not be consistent! you have been warned
                document[version] = 1


def late_versioning_catch(document, resource):
    """ Insert versioning copy of document for the previous version of a
    document if it is missing. Intended for PUT and PATCH.

    :param resource: the resource of the request/document.
    :param ids: a list of id number coorsponding to the documents parameter.
    :param document: the documents be written by POST, PUT, or PATCH.

    .. versionadded:: 0.4
    """
    resource_def = app.config['DOMAIN'][resource]
    version = app.config['VERSION']

    if resource_def['versioning'] is True:
        # TODO: Could directly check that there are no shadow copies for this
        # document. If there are shadow copies but the version field is in the
        # stored document, then something is wrong. (Modified outside of Eve?)

        if version not in document:
            # The API maintainer must of turned on versioning after the
            # document was added to the database, so let's add this old version
            # to the shadow collection now as if it was a new document.
            resolve_document_version(document, resource, 'POST')
            insert_versioning_documents(resource, document)


def insert_versioning_documents(resource, documents):
    """ Insert versioning copy of document. Intended for POST, PUT, and PATCH.

    :param resource: the resource of the request/document.
    :param documents: the documents be written by POST, PUT, or PATCH.

    .. versionadded:: 0.4
    """
    resource_def = app.config['DOMAIN'][resource]
    _id = resource_def['id_field']

    # push back versioned items if applicable
    # note: MongoDB doesn't have transactions! if the server dies, no
    # history will be saved.
    if resource_def['versioning'] is True:
        # force input as lists
        if not isinstance(documents, list):
            documents = [documents]

        # build vesioning documents
        version = app.config['VERSION']
        versioned_documents = []
        for index, document in enumerate(documents):
            ver_doc = {}

            # push normal fields
            fields = versioned_fields(resource_def)
            for field in document:
                if field in fields:
                    ver_doc[field] = document[field]

            # push special fields
            ver_doc[versioned_id_field(resource_def)] = document[_id]
            ver_doc[version] = document[version]

            # add document to the stack
            versioned_documents.append(ver_doc)

        # bulk insert
        source = resource_def['datasource']['source']
        versionable_resource_name = source + app.config['VERSIONS']
        app.data.insert(versionable_resource_name, versioned_documents)


def versioned_fields(resource_def):
    """ Returns a list of versioned fields for a resource.

    :param resource_def: a resource definition.

    .. versionchanged:: 0.6
       Added DELETED as versioned field for soft delete (#335)

    .. versionchanged:: 0.5
       ETAG is now a versioned field (#369).

    .. versionadded:: 0.4
    """<commit_msg>Fix to push auth_field onto versioned documents<commit_after>from flask import current_app as app, abort
from eve.utils import config, debug_error_message, ParsedRequest
from werkzeug.exceptions import BadRequestKeyError


def versioned_id_field(resource_settings):
    """ Shorthand to add two commonly added versioning parameters.

    .. versionadded: 0.4
    """
    return resource_settings['id_field'] + app.config['VERSION_ID_SUFFIX']


def resolve_document_version(document, resource, method, latest_doc=None):
    """ Version number logic for all methods.

    :param document: the document in question.
    :param resource: the resource of the request/document.
    :param method: method coorsponding to the request.
    :param latest_doc: the most recent version of the document.

    .. versionadded:: 0.4
    """
    resource_def = app.config['DOMAIN'][resource]
    version = app.config['VERSION']
    latest_version = app.config['LATEST_VERSION']

    if resource_def['versioning'] is True:
        # especially on collection endpoints, we don't to encure an extra
        # lookup if we are already pulling the latest version
        if method == 'GET' and latest_doc is None:
            if version not in document:
                # well it should be... the api designer must have turned on
                # versioning after data was already in the collection or the
                # collection has been modified without respecting versioning
                document[version] = 1  # the first saved version will be 2
            document[latest_version] = document[version]

        # include latest_doc if the request is for an older version so that we
        # can set the latest_version field in the response
        if method == 'GET' and latest_doc is not None:
            if version not in latest_doc:
                # well it should be... the api designer must have turned on
                # versioning after data was already in the collection or the
                # collection has been modified without respecting versioning
                document[version] = 1  # the first saved version will be 2
                document[latest_version] = document[version]
            else:
                document[latest_version] = latest_doc[version]
                if version not in document:
                    # this version was put in the database before versioning
                    # was turned on or outside of Eve
                    document[version] = 1

        if method == 'POST':
            # this one is easy! it is a new document
            document[version] = 1

        if method == 'PUT' or method == 'PATCH' or \
                (method == 'DELETE' and resource_def['soft_delete'] is True):
            if not latest_doc:
                abort(500, description=debug_error_message(
                    'I need the latest document here!'
                ))
            if version in latest_doc:
                # all is right in the world :)
                document[version] = latest_doc[version] + 1
            else:
                # if versioning was just turned on, then we will start
                # versioning now. if the db was modified outside of Eve or
                # versioning was turned of for a while, version numbers will
                # not be consistent! you have been warned
                document[version] = 1


def late_versioning_catch(document, resource):
    """ Insert versioning copy of document for the previous version of a
    document if it is missing. Intended for PUT and PATCH.

    :param resource: the resource of the request/document.
    :param ids: a list of id number coorsponding to the documents parameter.
    :param document: the documents be written by POST, PUT, or PATCH.

    .. versionadded:: 0.4
    """
    resource_def = app.config['DOMAIN'][resource]
    version = app.config['VERSION']

    if resource_def['versioning'] is True:
        # TODO: Could directly check that there are no shadow copies for this
        # document. If there are shadow copies but the version field is in the
        # stored document, then something is wrong. (Modified outside of Eve?)

        if version not in document:
            # The API maintainer must of turned on versioning after the
            # document was added to the database, so let's add this old version
            # to the shadow collection now as if it was a new document.
            resolve_document_version(document, resource, 'POST')
            insert_versioning_documents(resource, document)


def insert_versioning_documents(resource, documents):
    """ Insert versioning copy of document. Intended for POST, PUT, and PATCH.

    :param resource: the resource of the request/document.
    :param documents: the documents be written by POST, PUT, or PATCH.

    .. versionadded:: 0.4
    """
    resource_def = app.config['DOMAIN'][resource]
    _id = resource_def['id_field']

    # push back versioned items if applicable
    # note: MongoDB doesn't have transactions! if the server dies, no
    # history will be saved.
    if resource_def['versioning'] is True:
        # force input as lists
        if not isinstance(documents, list):
            documents = [documents]

        # if 'user-restricted resource access' is enabled and there's
        # an Auth request active, inject the username into the document
        auth = resource_def['authentication']
        auth_field = resource_def['auth_field']
        if auth and auth_field:
            request_auth_value = auth.get_request_auth_value()

        # build vesioning documents
        version = app.config['VERSION']
        versioned_documents = []
        for index, document in enumerate(documents):
            ver_doc = {}

            # push normal fields
            fields = versioned_fields(resource_def)
            for field in document:
                if field in fields:
                    ver_doc[field] = document[field]

            # push special fields
            ver_doc[versioned_id_field(resource_def)] = document[_id]
            ver_doc[version] = document[version]

            # push auth_field
            if request_auth_value:
                ver_doc[auth_field] = request_auth_value

            # add document to the stack
            versioned_documents.append(ver_doc)

        # bulk insert
        source = resource_def['datasource']['source']
        versionable_resource_name = source + app.config['VERSIONS']
        app.data.insert(versionable_resource_name, versioned_documents)


def versioned_fields(resource_def):
    """ Returns a list of versioned fields for a resource.

    :param resource_def: a resource definition.

    .. versionchanged:: 0.6
       Added DELETED as versioned field for soft delete (#335)

    .. versionchanged:: 0.5
       ETAG is now a versioned field (#369).

    .. versionadded:: 0.4
    """
{'fraction_non_alphanumeric': 0.06937673441836045, 'fraction_numerical': 0.004650116252906323, 'mean_word_length': 2.3152660367976132, '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': '7083912', 'n_tokens_mistral': 3430, 'n_tokens_neox': 3233, 'n_words': 1334}