<commit_before>import math
from operator import attrgetter
from flask import jsonify, request, Response
from up.headliner import Application
from up.headliner.http import webapp
import json
import random

ERR_NO_QUERY = '{"err":"no query object provided"}'
ERR_INVALID_QUERY = '{"err":"invalid query"}'
MAX_RESPONSE_SIZE = 100

@webapp.route("/nytimes/mostpopular.json", methods=["GET"])
def index():
    """
    Return a listing of available interests
    """
    app = Application.instance()
    categories = app.article_store.get_category_counts("nytimes_mostpopular")
    for category, score in categories.iteritems():
        categories[category] = int(score)
    return jsonify(d=categories)

@webapp.route("/nytimes/mostpopular/personalize", methods=["POST"])
def personalize():
    """
    Return results based on user query
    Request Content-Type must be set to application/json
    The payload must be a json ascii string.

    e.g. {"Arts":0.9,"Autos":0.9}
    """
    limit = request.args.get("limit", 20)
    try:
        limit = int(limit)
    except ValueError:
        return Response(response=ERR_INVALID_QUERY, status=400)

    if limit < 0:
        return Response(response=ERR_INVALID_QUERY, status=400)
    elif limit > MAX_RESPONSE_SIZE:
        limit = MAX_RESPONSE_SIZE

    query = request.get_json()
    if query is None:
        return Response(response=ERR_NO_QUERY, status=400)
    elif type(query) != dict:
        return Response(response=ERR_INVALID_QUERY, status=400)

    numbers = {}
    weight_total = 0.0
    for category, weight in query.iteritems():
        if type(weight) not in (float, int) or weight < 0 or weight > 1:
            return Response(response=ERR_INVALID_QUERY, status=400)
        # weight_total should always be float
        weight_total += weight
    for category, weight in query.iteritems():
        numbers[category] = int(math.ceil(weight/weight_total*limit))

    # collect all recommendations for each category
    app = Application.instance()
    recommendations = []
    for category in numbers:
        recommendations.extend(app.article_store.fetch("nytimes_mostpopular", category, numbers[category]))

    # randomize and deduplicate recommendations. store results in articles array
    random.shuffle(recommendations);
    articles = []
    url_set = set()
    for article in recommendations:
        if article["url"] not in url_set:
            articles.append(article)
            url_set.add(article["url"])

    return jsonify(d=articles,num_articles=len(articles))

@webapp.route("/nytimes/mostpopular/<interest_name>.json", methods=["GET"])
def fetch_interest(interest_name):
    """
    Returns articles belonging to the provided interest name
    """
    limit = request.args.get("limit", 20)
    try:<commit_msg>Closes #9: Inforce articles limit<commit_after>import math
from operator import attrgetter
from flask import jsonify, request, Response
from up.headliner import Application
from up.headliner.http import webapp
import json
import random

ERR_NO_QUERY = '{"err":"no query object provided"}'
ERR_INVALID_QUERY = '{"err":"invalid query"}'
MAX_RESPONSE_SIZE = 100

@webapp.route("/nytimes/mostpopular.json", methods=["GET"])
def index():
    """
    Return a listing of available interests
    """
    app = Application.instance()
    categories = app.article_store.get_category_counts("nytimes_mostpopular")
    for category, score in categories.iteritems():
        categories[category] = int(score)
    return jsonify(d=categories)

@webapp.route("/nytimes/mostpopular/personalize", methods=["POST"])
def personalize():
    """
    Return results based on user query
    Request Content-Type must be set to application/json
    The payload must be a json ascii string.

    e.g. {"Arts":0.9,"Autos":0.9}
    """
    limit = request.args.get("limit", 20)
    try:
        limit = int(limit)
    except ValueError:
        return Response(response=ERR_INVALID_QUERY, status=400)

    if limit < 0:
        return Response(response=ERR_INVALID_QUERY, status=400)
    elif limit > MAX_RESPONSE_SIZE:
        limit = MAX_RESPONSE_SIZE

    query = request.get_json()
    if query is None:
        return Response(response=ERR_NO_QUERY, status=400)
    elif type(query) != dict:
        return Response(response=ERR_INVALID_QUERY, status=400)

    numbers = {}
    weight_total = 0.0
    for category, weight in query.iteritems():
        if type(weight) not in (float, int) or weight < 0 or weight > 1:
            return Response(response=ERR_INVALID_QUERY, status=400)
        # weight_total should always be float
        weight_total += weight
    for category, weight in query.iteritems():
        numbers[category] = int(math.ceil(weight/weight_total*limit))

    # collect all recommendations for each category
    app = Application.instance()
    recommendations = []
    for category in numbers:
        recommendations.extend(app.article_store.fetch("nytimes_mostpopular", category, numbers[category]))

    # randomize and deduplicate recommendations. store results in articles array
    random.shuffle(recommendations);
    articles = []
    url_set = set()
    for article in recommendations:
        if article["url"] not in url_set:
            articles.append(article)
            url_set.add(article["url"])
        # inforce articles limit
        if len(articles) >= limit:
            break

    return jsonify(d=articles,num_articles=len(articles))

@webapp.route("/nytimes/mostpopular/<interest_name>.json", methods=["GET"])
def fetch_interest(interest_name):
    """
    Returns articles belonging to the provided interest name
    """
    limit = request.args.get("limit", 20)
    try:
{'fraction_non_alphanumeric': 0.10635310635310635, 'fraction_numerical': 0.011056511056511056, 'mean_word_length': 3.537420382165605, 'pattern_counts': {'":': 8, '<': 9, '<?xml version=': 0, '>': 10, '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': '2871642', 'n_tokens_mistral': 1694, 'n_tokens_neox': 1628, 'n_words': 442}