<commit_before>"""
Main app entry point
<NAME>
"""

from flask import Flask, jsonify, request, abort

import data_engines
import security
import settings

app = Flask(__name__)
coders_engine = data_engines.CoderEngine()
languages_engine = data_engines.LanguageEngine()

@app.route('/')
def test() -> str:
    """
    Confirmation route to ensure app is working

    Returns:
        confirmation message if success else error will be raised
    """
    return 'It works!'


@app.route('/users', methods=['GET'])
@security.authenticate.requires_auth
def users() -> dict:
    """
    Get route for all users

    Returns:
        list of users if success else 404 response is sent
    """

    data = coders_engine.get_all()
    payload = []
    for user in data:
        current_users = {}
        for k, v in user.items():
            if k == '_id':
                continue
            current_users[k] = v
        payload.append(current_users)
    return jsonify(payload)


@app.route('/users', methods=['POST'])
@security.authenticate.requires_auth
def post_users() -> tuple:
    """
    Post route for adding user data

    Returns:
        Confirmation message if success else 400 bad request
    """

    try:
        r = request.get_json()
        data = {
            'username': r['username'],
            'languages': r['languages']
        }
    except ValueError:
        abort(400)

    if coders_engine.get_one(data['username']):
        abort(409)
    try:
        coders_engine.add_one(data)
    except ValueError:
        abort(500)

    for lang in data['languages']:
        if languages_engine.get_one(lang):
            doc = languages_engine.get_one(lang)
            if data['username'] not in doc['users']:
                doc['users'].append(data['username'])
                languages_engine.update_one(lang, doc)
            continue
        else:
            doc = {'name': lang, 'users': [data['username']]}
            languages_engine.add_one(doc)


    return 'Ok', 201


@app.route('/users/<user>', methods=['GET'])
@security.authenticate.requires_auth
def get_one_user(user: str) -> dict:
    """
    Get route for a single user

    Args:
        user: username to query for

    Returns:
        specified user data
    """

    data = coders_engine.get_one(user)
    payload = None
    try:
        payload = {k: v for k, v in data.items() if k != '_id'}
    except AttributeError:
        abort(404)
    return jsonify(payload)


@app.route('/users/<user>', methods=['DELETE'])
@security.authenticate.requires_auth
def delete_one_user(user: str) -> tuple:
    """
    Delete route to remove a user

    Args:
        user: username to search and delete

    Returns:
        status code for either success 204 or failure 400
    """
    if not coders_engine.get_one(user):
        abort(400)
    coders_engine.delete_one(user)

    # remove user from language collection
    for lang in languages_engine.get_all():
        if user in lang['users']:
            lang['users'].remove(user)
            lang.pop('_id', None)
            languages_engine.update_one(lang['name'], lang)
    return '', 204


@app.route('/users/<user>', methods=['PATCH'])
@security.authenticate.requires_auth
def edit_one_user(user: str) -> tuple:
    """
    Patch route to edit a user's data

    Args:
        user: user to search for and edit

    Returns:
        update message if success else 404 not found or 400 if bad data
    """
    new_data = request.get_json()

    if len(new_data) < 1:
        abort(400)
    try:
        coders_engine.update_one(user, new_data)
    except ValueError:
        abort(404)

    # sync data between user and language
    user = new_data['username']
    langs = new_data['languages']

    # add user to language collection for all his/her languages
    for lang in langs:
        current_doc = languages_engine.get_one(lang)
        if current_doc:
            if user not in current_doc['users']:
                current_doc['users'].append(user)
                current_doc.pop('_id', None)
                languages_engine.update_one(current_doc['name'], current_doc)
        else:
            continue

    # check language collection and remove user from languages not mentioned
    # anymore
    for doc in languages_engine.get_all():
        if user in doc['users'] and doc['name'] not in langs:
            doc['users'].remove(user)
            doc.pop('_id', None)
        languages_engine.update_one(doc['name'], doc)

    return '', 204



@app.route('/languages', methods=['GET'])
@security.authenticate.requires_auth
def get_languages() -> dict:
    """
    Get route for all languages

    Returns:
        json language data
    """

    data = languages_engine.get_all()
    payload = []

    for datum in data:
        current_data = {}
        for k, v in datum.items():
            if k == '_id':
                continue
            current_data[k] = v
        payload.append(current_data)
    return jsonify(payload)


@app.route('/languages', methods=['POST'])<commit_msg>added a fix to _id being immutable fixes #9<commit_after>"""
Main app entry point
<NAME>
"""

from flask import Flask, jsonify, request, abort

import data_engines
import security
import settings

app = Flask(__name__)
coders_engine = data_engines.CoderEngine()
languages_engine = data_engines.LanguageEngine()

@app.route('/')
def test() -> str:
    """
    Confirmation route to ensure app is working

    Returns:
        confirmation message if success else error will be raised
    """
    return 'It works!'


@app.route('/users', methods=['GET'])
@security.authenticate.requires_auth
def users() -> dict:
    """
    Get route for all users

    Returns:
        list of users if success else 404 response is sent
    """

    data = coders_engine.get_all()
    payload = []
    for user in data:
        current_users = {}
        for k, v in user.items():
            if k == '_id':
                continue
            current_users[k] = v
        payload.append(current_users)
    return jsonify(payload)


@app.route('/users', methods=['POST'])
@security.authenticate.requires_auth
def post_users() -> tuple:
    """
    Post route for adding user data

    Returns:
        Confirmation message if success else 400 bad request
    """

    try:
        r = request.get_json()
        data = {
            'username': r['username'],
            'languages': r['languages']
        }
    except ValueError:
        abort(400)

    if coders_engine.get_one(data['username']):
        abort(409)
    try:
        coders_engine.add_one(data)
    except ValueError:
        abort(500)

    for lang in data['languages']:
        doc = languages_engine.get_one(lang)
        doc.pop('_id', None)
        if doc:
            if data['username'] not in doc['users']:
                doc['users'].append(data['username'])
                languages_engine.update_one(lang, doc)
            continue
        else:
            doc = {'name': lang, 'users': [data['username']]}
            languages_engine.add_one(doc)

    return 'Ok', 201


@app.route('/users/<user>', methods=['GET'])
@security.authenticate.requires_auth
def get_one_user(user: str) -> dict:
    """
    Get route for a single user

    Args:
        user: username to query for

    Returns:
        specified user data
    """

    data = coders_engine.get_one(user)
    payload = None
    try:
        payload = {k: v for k, v in data.items() if k != '_id'}
    except AttributeError:
        abort(404)
    return jsonify(payload)


@app.route('/users/<user>', methods=['DELETE'])
@security.authenticate.requires_auth
def delete_one_user(user: str) -> tuple:
    """
    Delete route to remove a user

    Args:
        user: username to search and delete

    Returns:
        status code for either success 204 or failure 400
    """
    if not coders_engine.get_one(user):
        abort(400)
    coders_engine.delete_one(user)

    # remove user from language collection
    for lang in languages_engine.get_all():
        lang.pop('_id', None)
        if user in lang['users']:
            lang['users'].remove(user)
            languages_engine.update_one(lang['name'], lang)
    return '', 204


@app.route('/users/<user>', methods=['PATCH'])
@security.authenticate.requires_auth
def edit_one_user(user: str) -> tuple:
    """
    Patch route to edit a user's data

    Args:
        user: user to search for and edit

    Returns:
        update message if success else 404 not found or 400 if bad data
    """
    new_data = request.get_json()

    if len(new_data) < 1:
        abort(400)
    try:
        coders_engine.update_one(user, new_data)
    except ValueError:
        abort(404)

    # sync data between user and language
    user = new_data['username']
    langs = new_data['languages']

    # add user to language collection for all his/her languages
    for lang in langs:
        current_doc = languages_engine.get_one(lang)
        current_doc.pop('_id', None)
        if current_doc:
            if user not in current_doc['users']:
                current_doc['users'].append(user)
                languages_engine.update_one(current_doc['name'], current_doc)
        else:
            continue

    # check language collection and remove user from languages not mentioned
    # anymore
    for doc in languages_engine.get_all():
        doc.pop('_id', None)
        if user in doc['users'] and doc['name'] not in langs:
            doc['users'].remove(user)
        languages_engine.update_one(doc['name'], doc)

    return '', 204



@app.route('/languages', methods=['GET'])
@security.authenticate.requires_auth
def get_languages() -> dict:
    """
    Get route for all languages

    Returns:
        json language data
    """

    data = languages_engine.get_all()
    payload = []

    for datum in data:
        current_data = {}
        for k, v in datum.items():
            if k == '_id':
                continue
            current_data[k] = v
        payload.append(current_data)
    return jsonify(payload)


@app.route('/languages', methods=['POST'])
{'fraction_non_alphanumeric': 0.11439296651190359, 'fraction_numerical': 0.009779709572261187, 'mean_word_length': 2.3836898395721926, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 25, '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': '1800454', 'n_tokens_mistral': 3100, 'n_tokens_neox': 2940, 'n_words': 841}