<commit_before>#!/usr/bin/python
"""This module solves the challenge for Spotippos.
Example requests:
* http://pythonbox/garbanzo-api/provinces
* http://pythonbox/garbanzo-api/properties
* http://pythonbox/garbanzo-api/properties/2
* http://pythonbox/garbanzo-api/properties?ax=630&ay=680&bx=685&by=675

"""
import urllib
import json
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask
from flask import jsonify
from flask import abort
from flask import make_response
from flask import request

# Global variables
provinces_url   = "https://raw.githubusercontent.com/VivaReal/code-challenge/master/provinces.json"
provinces_resp  = urllib.urlopen(provinces_url)
provinces_json  = json.loads(provinces_resp.read())
properties_url  = "https://raw.githubusercontent.com/VivaReal/code-challenge/master/properties.json"
properties_resp = urllib.urlopen(properties_url)
properties_json = json.loads(properties_resp.read())

# FlaskApp
app = Flask(__name__)

# Global methods
@app.errorhandler(404)
def not_found(error):
    """Method to handle 404

    Just a helper to make a default response for 404 status code. 

    """
    return make_response(jsonify({'error': 'Not found'}, 404))

def findProperty(property_id):
    """Method to find a property inside the JSON of properties.

    Receives an integer to find the related property among the JSON properties.
          :param property_id: Integer representing the ID of the property.

    """
    if 'properties' in properties_json:
        for p in properties_json['properties']:
            if p.get('id') == property_id:
                ret = p
    return ret

def searchProperties(p_ax, p_ay, p_bx, p_by):
    """Method to find properties inside an area.

    Receives four integers that represents the upper-left and bottom-right of the are that need to be explored. Returns all properties inside that area.
          :param property_id: Integer representing the ID of the property.

    """
    ret = []

    if 'properties' in properties_json:
        for p in properties_json['properties']:
            # app.logger.info('p_ax=' + `p_ax` + '#p_ay=' + `p_ay` + '#p_bx=' + `p_bx` + '#p_by=' + `p_by` + '#p-long=' + `p['long']` + '#p-lat=' + `p['lat']`)
            if ((p_ax <= p['long']) and (p_ay >= p['lat'])) and ((p_bx >= p['long']) and (p_by <= p['lat'])):
                p['provinces'] = setProvince(p['long'], p['lat'])
                ret.append(p)

    return ret

def setNewPropertyID():
    """Generates a new ID for a created property.

    Iterate over the whole JSON to garantee that a new ID will be generated for the new Property.

    """
    ret = 0

    if 'properties' in properties_json:
        for p in properties_json['properties']:
            if p.get('id') > ret:
                ret = p.get('id')

    ret += 1
    return ret

def setProvince(p_x, p_y):
    """Defines the provice for a property.

    Based on its X/Y positions, defines the set of provinces the property belongs to.

    """
    province_list = ['Gode', 'Groola', 'Jaby', 'Nova', 'Ruja', 'Scavy']
    pvlist_len    = len(province_list)
    ret = []

    for idx in range(0, pvlist_len):
        pv = province_list[idx]

        if (p_x >= provinces_json[pv]['boundaries']['upperLeft']['x']) and (p_y <= provinces_json[pv]['boundaries']['upperLeft']['y']) and (p_x <= provinces_json[pv]['boundaries']['bottomRight']['x']) and (p_y >= provinces_json[pv]['boundaries']['bottomRight']['y']):
            ret.append(pv)

    return ret

def validateHouse(p_data):
    """Run the range business validation rules.

    Validates if a property has the right values for its attributes.

    """
    ret = False

    if (p_data['beds'] in range(1, 5)) and (p_data['baths'] in range(1, 4)) and (p_data['squareMeters'] in range(20, 240)) and (p_data['long'] in range(0, 1400)) and (p_data['lat'] in range(0, 1000)):
        ret = True

    return ret

# REST operations
@app.route('/garbanzo-api/provinces', methods=['GET'])
def get_provinces():
    """Return all the provinces."""
    return jsonify(provinces_json)

@app.route('/garbanzo-api/properties', methods=['GET', 'POST'])
def property():
    """Return and create properties."""
    if request.method == 'GET':
        app.logger.info('Entrou no GET')

        if len(properties_json) == 0:
            app.logger.info('Entrou como se nao houvesse dados pra mostrar')
            abort(404)

        if len(request.args) == 0:
            app.logger.info('Entrou no ZERO')
            return jsonify(properties_json)

        if len(request.args) == 4:
            app.logger.info('Entrou no QUATRO')
            qs_ax = request.args.get('ax')
            qs_ay = request.args.get('ay')
            qs_bx = request.args.get('bx')
            qs_by = request.args.get('by')

            if len(qs_ax) > 0 and len(qs_ay) > 0 and len(qs_bx) > 0 and len(qs_by) > 0:
                app.logger.info('Entrou no ESTRANHO')
                compl = ""
                lista = searchProperties(int(qs_ax), int(qs_ay), int(qs_bx), int(qs_by))
                ret = [ { 'foundProperties' : len(lista), 'properties' : lista } ]
                return jsonify(ret)
            else:
                abort(500)
        else:
            abort(500)

    if request.method == 'POST':
        data                  = request.data
        dataDict              = json.loads(data)
        dataDict['id']        = setNewPropertyID()
        dataDict['provinces'] = setProvince(dataDict['long'], dataDict['lat'])

        if validateHouse(dataDict) == False:
           abort(500);

        properties_json['properties'].append(dataDict)
        new_data = {'id': dataDict['id'], 'provinces' : dataDict['provinces']}
        return jsonify(new_data), 201, {'Content-Type': 'application/json', 'Location': '/garbanzo-api/properties/' + `dataDict['id']`}

@app.route('/garbanzo-api/properties/<int:property_id>', methods=['GET'])
def get_property_by_id(property_id):
    """Return a specific property."""
    property = findProperty(property_id)

    if len(property) == 0:
        abort(404)

    property['provinces'] = setProvince(property['long'], property['lat'])
    return jsonify(property)

# Start app
if __name__ == '__main__':
    formatter = logging.Formatter("[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s")
    handler   = RotatingFileHandler('/var/log/garbanzo.log', maxBytes=1073741824, backupCount=1)
    handler.setLevel(logging.DEBUG)
    handler.setFormatter(formatter)
    app.logger.addHandler(handler)
    app.run(host='0.0.0.0', port=80, debug=True)

<commit_msg>Attending PEP#8 (line ending standards).<commit_after>#!/usr/bin/python
"""This module solves the challenge for Spotippos.
Example requests:
* http://pythonbox/garbanzo-api/provinces
* http://pythonbox/garbanzo-api/properties
* http://pythonbox/garbanzo-api/properties/2
* http://pythonbox/garbanzo-api/properties?ax=630&ay=680&bx=685&by=675

"""
import urllib
import json
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask
from flask import jsonify
from flask import abort
from flask import make_response
from flask import request

# Global variables
base_url        = "https://raw.githubusercontent.com/VivaReal/code-challenge"
provinces_url   = base_url + "/master/provinces.json"
provinces_resp  = urllib.urlopen(provinces_url)
provinces_json  = json.loads(provinces_resp.read())
properties_url  = base_url + "/master/properties.json"
properties_resp = urllib.urlopen(properties_url)
properties_json = json.loads(properties_resp.read())

# FlaskApp
app = Flask(__name__)

# Global methods
@app.errorhandler(404)
def not_found(error):
    """Method to handle 404

    Just a helper to make a default response for 404 status code. 

    """
    return make_response(jsonify({'error': 'Not found'}, 404))

def findProperty(property_id):
    """Method to find a property inside the JSON of properties.

    Receives an integer to find the related property among the JSON
    properties.
          :param property_id: Integer representing the ID of the
                              property.

    """
    if 'properties' in properties_json:
        for p in properties_json['properties']:
            if p.get('id') == property_id:
                ret = p
    return ret

def searchProperties(p_ax, p_ay, p_bx, p_by):
    """Method to find properties inside an area.

    Receives four integers that represents the upper-left and
    bottom-right of the are that need to be explored. Returns all
    properties inside that area.
          :param property_id: Integer representing the ID of the
                              property.

    """
    ret = []

    if 'properties' in properties_json:
        for p in properties_json['properties']:
            if ((p_ax <= p['long'])
                    and (p_ay >= p['lat']))
                    and ((p_bx >= p['long'])
                    and (p_by <= p['lat'])):
                p['provinces'] = setProvince(p['long'], p['lat'])
                ret.append(p)

    return ret

def setNewPropertyID():
    """Generates a new ID for a created property.

    Iterate over the whole JSON to garantee that a new ID will be
    generated for the new Property.

    """
    ret = 0

    if 'properties' in properties_json:
        for p in properties_json['properties']:
            if p.get('id') > ret:
                ret = p.get('id')

    ret += 1
    return ret

def setProvince(p_x, p_y):
    """Defines the provice for a property.

    Based on its X/Y positions, defines the set of provinces the
    property belongs to.

    """
    province_list = ['Gode', 'Groola', 'Jaby', 'Nova', 'Ruja', 'Scavy']
    pvlist_len    = len(province_list)
    ret = []

    for idx in range(0, pvlist_len):
        pv = province_list[idx]

        if (p_x >= provinces_json[pv]['boundaries']['upperLeft']['x'])
            and (p_y <= provinces_json[pv]['boundaries']['upperLeft']['y'])
            and (p_x <= provinces_json[pv]['boundaries']['bottomRight']['x'])
            and (p_y >= provinces_json[pv]['boundaries']['bottomRight']['y']):
            ret.append(pv)

    return ret

def validateHouse(p_data):
    """Run the range business validation rules.

    Validates if a property has the right values for its attributes.

    """
    ret = False

    if (p_data['beds'] in range(1, 5))
            and (p_data['baths'] in range(1, 4))
            and (p_data['squareMeters'] in range(20, 240))
            and (p_data['long'] in range(0, 1400))
            and (p_data['lat'] in range(0, 1000)):
        ret = True

    return ret

# REST operations
@app.route('/garbanzo-api/provinces', methods=['GET'])
def get_provinces():
    """Return all the provinces."""
    return jsonify(provinces_json)

@app.route('/garbanzo-api/properties', methods=['GET', 'POST'])
def property():
    """Return and create properties."""
    if request.method == 'GET':
        app.logger.info('Entrou no GET')

        if len(properties_json) == 0:
            app.logger.info('Entrou como se nao houvesse dados pra mostrar')
            abort(404)

        if len(request.args) == 0:
            app.logger.info('Entrou no ZERO')
            return jsonify(properties_json)

        if len(request.args) == 4:
            app.logger.info('Entrou no QUATRO')
            qs_ax = request.args.get('ax')
            qs_ay = request.args.get('ay')
            qs_bx = request.args.get('bx')
            qs_by = request.args.get('by')

            if len(qs_ax) > 0 and len(qs_ay) > 0
                    and len(qs_bx) > 0 and len(qs_by) > 0:
                app.logger.info('Entrou no ESTRANHO')
                compl = ""
                lista = searchProperties(int(qs_ax), int(qs_ay),
                                         int(qs_bx), int(qs_by))
                ret = [ { 'foundProperties' : len(lista),
                          'properties' : lista } ]
                return jsonify(ret)
            else:
                abort(500)
        else:
            abort(500)

    if request.method == 'POST':
        data                  = request.data
        dataDict              = json.loads(data)
        dataDict['id']        = setNewPropertyID()
        dataDict['provinces'] = setProvince(dataDict['long'], dataDict['lat'])

        if validateHouse(dataDict) == False:
           abort(500);

        properties_json['properties'].append(dataDict)
        prop_id = dataDict['id']
        ret = {'id': prop_id, 'provinces' : dataDict['provinces']}
        return jsonify(ret),
                       201,
                       {'Content-Type': 'application/json',
                        'Location': '/garbanzo-api/properties/' + `prop_id`}

@app.route('/garbanzo-api/properties/<int:property_id>', methods=['GET'])
def get_property_by_id(property_id):
    """Return a specific property."""
    property = findProperty(property_id)

    if len(property) == 0:
        abort(404)

    property['provinces'] = setProvince(property['long'], property['lat'])
    return jsonify(property)

# Start app
if __name__ == '__main__':
    log_format  = "[%(asctime)s] {%(pathname)s"
    log_format += ":%(lineno)d} %(levelname)s - %(message)s"
    formatter   = logging.Formatter(log_format)
    handler     = RotatingFileHandler('/var/log/garbanzo.log',
                                      maxBytes=1073741824, backupCount=1)
    handler.setLevel(logging.DEBUG)
    handler.setFormatter(formatter)
    app.logger.addHandler(handler)
    app.run(host='0.0.0.0', port=80, debug=True)


{'fraction_non_alphanumeric': 0.13565063701303484, 'fraction_numerical': 0.013329405699977906, 'mean_word_length': 2.6982570806100217, 'pattern_counts': {'":': 1, '<': 13, '<?xml version=': 0, '>': 23, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5663233', 'n_tokens_mistral': 4426, 'n_tokens_neox': 4148, 'n_words': 1066}