diff --git a/app/controllers/turk_hit.py b/app/controllers/turk_hit.py index 79463aa0b0e2806efb5cace7cb6f0a126e9b4326..69d6e0bd4e1f87ed5162f0f8a5460423d7d46b0f 100644 --- a/app/controllers/turk_hit.py +++ b/app/controllers/turk_hit.py @@ -3,13 +3,17 @@ import base64 import json import requests import mimetypes +from bpeng import ParseDimensions from flask import current_app from werkzeug.datastructures import MultiDict from werkzeug.exceptions import NotFound, BadRequest from .base import RestController -from ..lib.database import proc +from .unapproved_point import UnapprovedPointController +from .unapproved_window_door import UnapprovedWindowDoorController +from .unapproved_building_dimensions import UnapprovedBuildingDimensionsController +from ..lib.database import proc, db from ..lib.mech_turk import create_hit, approve_or_reject_hit,\ get_hit_status from ..lib.service import services @@ -17,8 +21,6 @@ from ..models.turk_hit import TurkHit from ..forms.turk_hit import TurkHitPostForm, TurkHitPutForm - - class TurkHitController(RestController): """A turk_hit controller.""" Model = TurkHit @@ -30,7 +32,7 @@ class TurkHitController(RestController): 4: 'Accepted', 5: 'Rejected', 6: 'Disposed', - 7: 'Expired' + 7: 'Expired', } # The above dictionary with the keys as values and the values as keys @@ -54,13 +56,17 @@ class TurkHitController(RestController): address (string): The address of the building for saving to box Returns: list: - dict: TurkHit object + dict: TurkHit object, with additional dimensions data if applicable """ address = filter_data.get('address') if not address: raise BadRequest("Please ensure there is an address in the url params") try: - hit_list = proc(self.Model, self.Model.PROCS['READ'], **{'building_id': id_}) + hit_list = proc( + self.Model, + self.Model.PROCS['READ'], + **{'building_id': id_}, + ) except Exception as err: raise ( @@ -71,11 +77,21 @@ class TurkHitController(RestController): if not hit_list: return [] + # Get the dimensions for all of the previous hits + for hit in hit_list[1:]: + dimen = self.get_dimensions_data(hit.db_id) + if (dimen['building_dimensions']): + hit.dimensions = dimen + cur_hit = hit_list[0] - # No need to check in with amazon if we've already reached one of those states + # Get the dimensions for the cur hit if they exist + dimensions = self.get_dimensions_data(cur_hit.db_id) + + # No need to check in with amazon if we've already reached these states status_string = self.STATUS_DICT_ID[cur_hit.status_id] if status_string in ["Accepted", "Rejected", "Disposed", "Expired"]: + cur_hit.dimensions = dimensions return hit_list # Get the new hit status from AWS @@ -84,7 +100,10 @@ class TurkHitController(RestController): # No changes if the status is the same if new_hit_status == status_string: + if (dimensions['building_dimensions']): + cur_hit.dimensions = dimensions return hit_list + # Download file here if result['file_url'] and not cur_hit.csv_document_key: response = requests.get(result['file_url']) @@ -97,37 +116,88 @@ class TurkHitController(RestController): response_message = 'This hit was automatically rejected because '\ 'the uploaded file was not in the correct file '\ 'format. The file must be of type .xlsx.' - put_body = {**cur_hit.get_dictionary(), - **{'approve': 0, 'response_message': response_message}} - self.put(cur_hit.db_id, put_body, None) + new_hit_status = self.reject_hit(cur_hit, response_message) cur_hit.response_message = response_message - new_hit_status = "Rejected" else: - file_name = "BuildingDimensions--{}--{}.xlsx".format(cur_hit.building_id, - cur_hit.amazon_hit_id) - folder_path = "/Buildings/{}_{}/Building_Dimensions".format(cur_hit.building_id, - address) - # Download the file - document = self.download_file(cur_hit.building_id, folder_path, - file_name, response.content) - # Get the key to update the model - cur_hit.csv_document_key = document['key'] + # Parse the excel file + try: + dimensions = self.parse_dimensions_data( + response.content, + cur_hit.db_id, + cur_hit.building_id, + ) + # Automatically Reject the HIT if it failed to parse + except Exception as e: + if current_app.config['DEBUG']: + print("Failed to parse the dimensions file, rejecting now") + response_message = 'This hit was automatically rejected because '\ + 'the uploaded file was not parseable. Did '\ + 'you try uploading the file to our testing site?' + new_hit_status = self.reject_hit(cur_hit, response_message) + cur_hit.response_message = response_message + else: + # Save new dimensions data to the database + UnapprovedWindowDoorController().post( + dimensions['windows_doors'], + None, + ) + UnapprovedPointController().post( + dimensions['points'], + None, + ) + UnapprovedBuildingDimensionsController().post( + dimensions['building_dimensions'], + None, + ) + + # Save the file to box + file_name = "BuildingDimensions--{}--{}.xlsx".format( + cur_hit.building_id, + cur_hit.amazon_hit_id, + ) + folder_path = "/Buildings/{}_{}/Building_Dimensions".format( + cur_hit.building_id, + address, + ) + document = self.download_file( + cur_hit.building_id, + folder_path, + file_name, + response.content, + ) + # Get the key to update the model + cur_hit.csv_document_key = document['key'] # Update the entry in the database new_hit_status_id = self.STATUS_DICT_TEXT[new_hit_status] cur_hit.status_id = new_hit_status_id try: - proc(self.Model, - self.Model.PROCS['UPDATE'], - **cur_hit.get_dictionary()) + proc( + self.Model, + self.Model.PROCS['UPDATE'], + **cur_hit.get_dictionary(), + ) except Exception as err: raise ( err if current_app.config['DEBUG'] else BadRequest('Error while executing db call') ) + if (dimensions['building_dimensions']): + cur_hit.dimensions = dimensions return hit_list + def reject_hit(self, hit, response_message): + put_body = { + **hit.get_dictionary(), + **{ + 'approve': 0, + 'response_message': response_message, + }, + } + self.put(hit.db_id, put_body, None) + return "Rejected" + def download_file(self, building_id, folder_path, file_name, byte_data): """ A function to download a file to box @@ -140,7 +210,7 @@ class TurkHitController(RestController): "data": "data:csv/plain;charset=utf-8;base64,{}".format(encoded_string_data), "building_id": str(building_id), "tags": '', - "name": file_name + "name": file_name, } # Call the generic method in the base class response = services.document.post('', '/document/', data=json.dumps(post_data)) @@ -153,6 +223,49 @@ class TurkHitController(RestController): document = response.json()['data'] return document + def parse_dimensions_data(self, contents, hit_id, building_id): + """ + A function to parse dimensions data from the completed mech turk hit + + Relies on a specific formatting of excel documents given to the worker + + """ + windows_doors, points, building_dimensions = ParseDimensions.parse(contents) + for point in points: + point['building_id'] = building_id + point['hit_id'] = hit_id + + for window_door in windows_doors: + window_door['building_id'] = building_id + window_door['hit_id'] = hit_id + + building_dimensions['building_id'] = building_id + building_dimensions['hit_id'] = hit_id + + return { + 'windows_doors': windows_doors, + 'points': points, + 'building_dimensions': building_dimensions, + } + + def get_dimensions_data(self, hit_id): + """ + Get the unapproved dimensions for a hit + """ + args = MultiDict([('hit_id[]', hit_id)]) + windows_doors = UnapprovedWindowDoorController().index(args) + points = UnapprovedPointController().index(args) + building_dimensions = UnapprovedBuildingDimensionsController().index(args) + + dimensions = {} + dimensions["windows_doors"] = [model.get_dictionary() + for model in windows_doors] + dimensions["points"] = [model.get_dictionary() + for model in points] + dimensions["building_dimensions"] = {} + if building_dimensions: + dimensions["building_dimensions"] = building_dimensions[0].get_dictionary() + return dimensions def post(self, data, filter_data): """ @@ -168,7 +281,6 @@ class TurkHitController(RestController): min_file_bytes (int) instructions_text (string) instructions_url (string) - worksheet_url (string) max_assignments (int) title (string) description (string) @@ -191,11 +303,16 @@ class TurkHitController(RestController): # Store the hit data in the database try: - hit_list = proc(self.Model, self.Model.PROCS['WRITE'], - **{'building_id': building_id, - 'amazon_hit_id': amazon_hit_id, - 'requester_name': requester_name, - 'status_id': self.STATUS_DICT_TEXT['Assignable']}) + hit_list = proc( + self.Model, + self.Model.PROCS['WRITE'], + **{ + 'building_id': building_id, + 'amazon_hit_id': amazon_hit_id, + 'requester_name': requester_name, + 'status_id': self.STATUS_DICT_TEXT['Assignable'], + } + ) except Exception as err: raise ( err if current_app.config['DEBUG'] else @@ -204,11 +321,8 @@ class TurkHitController(RestController): if not hit_list: raise NotFound("Hit was not found in the database") - return hit_list[0] - - def put(self, id_, data, filter_data): """ Update a TurkHit object @@ -226,12 +340,13 @@ class TurkHitController(RestController): if int(id_) != data["db_id"]: raise BadRequest("The URL id and the body db_id are not the same") - approve = data.pop("approve") - + approve = data["approve"] # Approve or reject the hit on the amazon mech turk side - if approve_or_reject_hit(data["amazon_hit_id"], - approve, - data["response_message"]): + if approve_or_reject_hit( + data["amazon_hit_id"], + approve, + data["response_message"], + ): # Update the hit data in the database try: approve_id = self.STATUS_DICT_TEXT['Accepted'] @@ -239,10 +354,17 @@ class TurkHitController(RestController): status_id = approve_id if approve else reject_id # The data - data['status_id'] = status_id - - hit_list = proc(self.Model, self.Model.PROCS['UPDATE'], - **data) + clean_model = self.Model() + form.populate_obj(clean_model) + clean_data = clean_model.get_dictionary() + clean_data.pop("approve") + clean_data['status_id'] = status_id + + hit_list = proc( + self.Model, + self.Model.PROCS['UPDATE'], + **clean_data, + ) except Exception as err: raise ( diff --git a/app/controllers/unapproved_building_dimensions.py b/app/controllers/unapproved_building_dimensions.py new file mode 100644 index 0000000000000000000000000000000000000000..25660479a6d1956314b34d4110b2eeeb3399a5f7 --- /dev/null +++ b/app/controllers/unapproved_building_dimensions.py @@ -0,0 +1,35 @@ +"""Controllers for managing top-level unapproved_building_dimensions.""" +from sqlalchemy import and_ +from werkzeug.exceptions import BadRequest +from flask import current_app + +from app.lib.database import db, proc +from app.controllers.base import RestController +from app.models.unapproved_building_dimensions import UnapprovedBuildingDimensions +from app.forms.unapproved_building_dimensions import UnapprovedBuildingDimensionsForm + + +class UnapprovedBuildingDimensionsController(RestController): + """The unapproved_building_dimensions controller.""" + Model = UnapprovedBuildingDimensions + filters = { + 'hit_id[]': \ + lambda d: UnapprovedBuildingDimensions.hit_id.in_(d.getlist('hit_id[]')) + } + + def get_form(self, filter_data): + """Return the unapproved_building_dimensions form.""" + return UnapprovedBuildingDimensionsForm + + def post(self, data, filter_data): + """Post a new model. + + """ + try: + model = super(UnapprovedBuildingDimensionsController, self).post(data, filter_data) + return model + except Exception as e: + raise ( + e if current_app.config["DEBUG"] else + BadRequest("Error while posting unapproved_building_dimensions data") + ) diff --git a/app/controllers/unapproved_point.py b/app/controllers/unapproved_point.py new file mode 100644 index 0000000000000000000000000000000000000000..042facfa023d4f7a8de8dd62b65c6f8fe1bfaa47 --- /dev/null +++ b/app/controllers/unapproved_point.py @@ -0,0 +1,39 @@ +"""Controllers for managing top-level unapproved_points.""" +from sqlalchemy import and_ +from werkzeug.exceptions import BadRequest +from flask import current_app + +from app.lib.database import db, proc +from app.controllers.base import RestController +from app.models.unapproved_point import UnapprovedPoint +from app.forms.unapproved_point import UnapprovedPointForm + + +class UnapprovedPointController(RestController): + """The unapproved_point controller.""" + Model = UnapprovedPoint + filters = { + 'hit_id[]': \ + lambda d: UnapprovedPoint.hit_id.in_(d.getlist('hit_id[]')) + } + + def get_form(self, filter_data): + """Return the unapproved_point form.""" + return UnapprovedPointForm + + def post(self, data, filter_data): + """Post a new model. + + """ + # Will want to loop through the inputted unapproved_points + try: + model_list = [] + for point in data: + model = super(UnapprovedPointController, self).post(point, filter_data) + model_list.append(model) + return model_list + except Exception as e: + raise ( + e if current_app.config["DEBUG"] else + BadRequest("Error while posting unapproved_point data") + ) diff --git a/app/controllers/unapproved_window_door.py b/app/controllers/unapproved_window_door.py new file mode 100644 index 0000000000000000000000000000000000000000..250810c9188ca98c134682edcd8f02d5f844c3c6 --- /dev/null +++ b/app/controllers/unapproved_window_door.py @@ -0,0 +1,39 @@ +"""Controllers for managing top-level unapproved_window_doors.""" +from sqlalchemy import and_ +from werkzeug.exceptions import BadRequest +from flask import current_app + +from app.lib.database import db, proc +from app.controllers.base import RestController +from app.models.unapproved_window_door import UnapprovedWindowDoor +from app.forms.unapproved_window_door import UnapprovedWindowDoorForm + + +class UnapprovedWindowDoorController(RestController): + """The unapproved_window_door controller.""" + Model = UnapprovedWindowDoor + filters = { + 'hit_id[]': \ + lambda d: UnapprovedWindowDoor.hit_id.in_(d.getlist('hit_id[]')) + } + + def get_form(self, filter_data): + """Return the unapproved_window_door form.""" + return UnapprovedWindowDoorForm + + def post(self, data, filter_data): + """Post a new model. + + """ + # Will want to loop through the inputted unapproved_window_doors + try: + model_list = [] + for item in data: + model = super(UnapprovedWindowDoorController, self).post(item, filter_data) + model_list.append(model) + return model_list + except Exception as e: + raise ( + e if current_app.config["DEBUG"] else + BadRequest("Error while posting unapproved_window_door data") + ) diff --git a/app/forms/turk_hit.py b/app/forms/turk_hit.py index b16d9b3a972572a3691b85c783eab8d9b980bec5..1699e9145be208ee4b6b9838cd19a98c33ce4f4b 100644 --- a/app/forms/turk_hit.py +++ b/app/forms/turk_hit.py @@ -36,6 +36,7 @@ class TurkHitPostForm(wtf.Form): reward = wtf.FloatField( validators=[wtf.validators.Required()]) + class TurkHitPutForm(wtf.Form): """ A form for validating turk hits.""" db_id = wtf.IntegerField( @@ -68,4 +69,3 @@ class TurkHitPutForm(wtf.Form): self.response_message.errors.append('If accept is 0 explanation must be nonempty') return False return True - diff --git a/app/forms/unapproved_building_dimensions.py b/app/forms/unapproved_building_dimensions.py new file mode 100644 index 0000000000000000000000000000000000000000..ef46a94f8fcbb43cd8aeeb8003dfb202f40f3827 --- /dev/null +++ b/app/forms/unapproved_building_dimensions.py @@ -0,0 +1,17 @@ +import wtforms as wtf + + +class UnapprovedBuildingDimensionsForm(wtf.Form): + """ A form for validating unapproved_building_dimensions requests.""" + + hit_id = wtf.IntegerField( + validators=[wtf.validators.Required()]) + perimeter = wtf.DecimalField() + area = wtf.DecimalField() + num_floors = wtf.IntegerField() + ground_elevation = wtf.IntegerField() + building_id = wtf.IntegerField() + north_adjacency = wtf.DecimalField() + south_adjacency = wtf.DecimalField() + west_adjacency = wtf.DecimalField() + east_adjacency = wtf.DecimalField() diff --git a/app/forms/unapproved_point.py b/app/forms/unapproved_point.py new file mode 100644 index 0000000000000000000000000000000000000000..c7fe2185632bc995d50ffd425891ed2fd11cbef5 --- /dev/null +++ b/app/forms/unapproved_point.py @@ -0,0 +1,14 @@ +import wtforms as wtf + + +class UnapprovedPointForm(wtf.Form): + """ A form for validating unapproved_point requests.""" + + hit_id = wtf.IntegerField( + validators=[wtf.validators.Required()]) + latitude = wtf.DecimalField() + longitude = wtf.DecimalField() + elevation = wtf.IntegerField() + corresponding_height = wtf.IntegerField() + feature = wtf.IntegerField() + building_id = wtf.IntegerField() diff --git a/app/forms/unapproved_window_door.py b/app/forms/unapproved_window_door.py new file mode 100644 index 0000000000000000000000000000000000000000..9864a613d7fb1e8c3ba5772b59bda896a7aba31f --- /dev/null +++ b/app/forms/unapproved_window_door.py @@ -0,0 +1,15 @@ +import wtforms as wtf + + +class UnapprovedWindowDoorForm(wtf.Form): + """ A form for validating unapproved_window_door requests.""" + + hit_id = wtf.IntegerField( + validators=[wtf.validators.Required()]) + height = wtf.DecimalField() + width = wtf.DecimalField() + quantity = wtf.IntegerField() + orientation = wtf.IntegerField() + direction = wtf.IntegerField() + feature = wtf.IntegerField() + building_id = wtf.IntegerField() diff --git a/app/models/turk_hit.py b/app/models/turk_hit.py index cd3cd2dc597cbe73aa69bc8eecb2fccf960b52e5..b993dcb6003312bdf8e17c3b90477c6d9502650b 100644 --- a/app/models/turk_hit.py +++ b/app/models/turk_hit.py @@ -12,6 +12,8 @@ class TurkHit(BaseModel): 'UPDATE': 'update_hit', } + def get_dictionary(self): + return self.__dict__ __table__ = ProcTable( 'TurkHit', @@ -26,11 +28,11 @@ class TurkHit(BaseModel): ProcColumn('response_message'), ) - def __init__(self, db_id, building_id, amazon_hit_id, status_id, - hit_date, requester_name, csv_document_key, - shapefile_document_key, response_message - ): - + def __init__( + self, db_id=None, building_id=None, amazon_hit_id=None, status_id=None, + hit_date=None, requester_name=None, csv_document_key=None, + shapefile_document_key=None, response_message=None, + ): self.db_id = db_id self.building_id = building_id self.amazon_hit_id = amazon_hit_id diff --git a/app/models/unapproved_building_dimensions.py b/app/models/unapproved_building_dimensions.py new file mode 100644 index 0000000000000000000000000000000000000000..e4a59c96ca37198e2a67f310cda994b33575bcf7 --- /dev/null +++ b/app/models/unapproved_building_dimensions.py @@ -0,0 +1,28 @@ +"""Models for dealing with an unapproved_building_dimensions.""" +from sqlalchemy.ext.declarative import declared_attr + +from ..lib.database import ProcColumn, ProcTable, db +from .base import Model + + +class UnapprovedBuildingDimensions(Model, db.Model): + + @declared_attr + def __tablename__(cls): + return "unapproved_building_dimensions" + + __table_args__ = {"schema": "mechanical_turk"} + + perimeter = db.Column(db.Float) + area = db.Column(db.Float) + num_floors = db.Column(db.Integer) + ground_elevation = db.Column(db.Integer) + hit_id = db.Column(db.Integer, nullable=False) + building_id = db.Column(db.Integer) + north_adjacency = db.Column(db.Float) + south_adjacency = db.Column(db.Float) + west_adjacency = db.Column(db.Float) + east_adjacency = db.Column(db.Float) + + def __str__(self): + return "unapproved_building_dimensions data for account {}".format(self.hit_id) diff --git a/app/models/unapproved_point.py b/app/models/unapproved_point.py new file mode 100644 index 0000000000000000000000000000000000000000..e44674d08300be77593a5ba03f89c0c3b30f35c9 --- /dev/null +++ b/app/models/unapproved_point.py @@ -0,0 +1,25 @@ +"""Models for dealing with an unapproved_point.""" +from sqlalchemy.ext.declarative import declared_attr + +from ..lib.database import ProcColumn, ProcTable, db +from .base import Model + + +class UnapprovedPoint(Model, db.Model): + + @declared_attr + def __tablename__(cls): + return "unapproved_point" + + __table_args__ = {"schema": "mechanical_turk"} + + latitude = db.Column(db.Float) + longitude = db.Column(db.Float) + elevation = db.Column(db.Integer) + corresponding_height = db.Column(db.Integer) + feature = db.Column(db.Integer) + hit_id = db.Column(db.Integer, nullable=False) + building_id = db.Column(db.Integer) + + def __str__(self): + return "unapproved_point data for account {}".format(self.hit_id) diff --git a/app/models/unapproved_window_door.py b/app/models/unapproved_window_door.py new file mode 100644 index 0000000000000000000000000000000000000000..a3e43440b1c1f88ed9e85474c531af97ea0d60f7 --- /dev/null +++ b/app/models/unapproved_window_door.py @@ -0,0 +1,26 @@ +"""Models for dealing with an unapproved_window_door.""" +from sqlalchemy.ext.declarative import declared_attr + +from ..lib.database import ProcColumn, ProcTable, db +from .base import Model + + +class UnapprovedWindowDoor(Model, db.Model): + + @declared_attr + def __tablename__(cls): + return "unapproved_window_door" + + __table_args__ = {"schema": "mechanical_turk"} + + height = db.Column(db.Float) + width = db.Column(db.Float) + quantity = db.Column(db.Integer) + orientation = db.Column(db.Integer) + direction = db.Column(db.Integer) + feature = db.Column(db.Integer) + hit_id = db.Column(db.Integer, nullable=False) + building_id = db.Column(db.Integer) + + def __str__(self): + return "unapproved_window_door data for account {}".format(self.hit_id) diff --git a/app/views/__init__.py b/app/views/__init__.py index 0248c90ba4bdbc8915d5711041fa1b76e044c978..3afb4b15076e9ab2cfe79a9ef2acee7bda871c3f 100644 --- a/app/views/__init__.py +++ b/app/views/__init__.py @@ -1,5 +1,9 @@ """Flask-classy views for the flask application.""" -from . import building, turk_hit +from . import (building, + turk_hit, + unapproved_point, + unapproved_window_door, + unapproved_building_dimensions) def register(app): @@ -10,3 +14,6 @@ def register(app): """ building.BuildingView.register(app) turk_hit.TurkHitView.register(app) + unapproved_point.UnapprovedPointView.register(app) + unapproved_window_door.UnapprovedWindowDoorView.register(app) + unapproved_building_dimensions.UnapprovedBuildingDimensionsView.register(app) diff --git a/app/views/base.py b/app/views/base.py index 452a5bb600ec4fcd871206c50618a331b69b4dc8..1a175c57e9aaae6e9b01a3da64eeecfb763279b4 100644 --- a/app/views/base.py +++ b/app/views/base.py @@ -15,7 +15,7 @@ class View(FlaskView): def json(self, obj, status=200): """A wrapper for Flask's jsonify().""" - response = jsonify(obj) + response = jsonify(data=obj) return response, status def parse(self, model): diff --git a/app/views/building.py b/app/views/building.py index 8e5615121eb73956ed6ade4e7b23d767ac912223..15fc763c9fefb9a8a564eddb4fa32c4a16911a2e 100644 --- a/app/views/building.py +++ b/app/views/building.py @@ -15,21 +15,19 @@ class BuildingView(RestView): """/ GET - Retrieve a list of resources.""" # TODO: Add data key back to self.json # return super(BuildingView, self).index(request.args) - return self.json({ - 'data': [ - self.parse(m) for m in self.get_controller().index(request.args) - ] - }) + return self.json( + [self.parse(m) for m in self.get_controller().index(request.args)] + ) def get(self, id_): """/{id} GET - Retrieve a resource by id.""" # TODO: Add data key back in self.json # return super(BuildingView, self).get(id_, request.args) - return self.json({ - 'data': self.parse( + return self.json( + self.parse( self.get_controller().get(id_, request.args) ) - }) + ) def post(self): raise MethodNotAllowed() diff --git a/app/views/turk_hit.py b/app/views/turk_hit.py index 0190a07c6d7c3dca6fea002362da178a6b58a694..f2e0f3a00d6c1cefd8c9e827aa7b3b07daeec457 100644 --- a/app/views/turk_hit.py +++ b/app/views/turk_hit.py @@ -26,11 +26,9 @@ class TurkHitView(RestView): if error.error_code == 'AWS.MechanicalTurk.HITDoesNotExist': raise NotFound(error.error_code) raise BadGateway(error.error_code) - return self.json({ - 'data': [ - self.parse(m) for m in response - ] - }) + return self.json( + [self.parse(m) for m in response] + ) def post(self): """/ POST - Create a hit given an id in the POST body""" @@ -41,9 +39,7 @@ class TurkHitView(RestView): except MTurkRequestError as error: raise BadGateway(error.error_code) - return self.json({ - 'data': self.parse(response) - }, 201) + return self.json(self.parse(response), 201) def put(self, id_): """ / PUT - Approve or decline a hit given a building_id. @@ -61,10 +57,7 @@ class TurkHitView(RestView): raise BadRequest(error.error_code) raise BadGateway(error.error_code) - return self.json({ - 'data': self.parse(response) - - }) + return self.json(self.parse(response)) def delete(self, id_): raise MethodNotAllowed() diff --git a/app/views/unapproved_building_dimensions.py b/app/views/unapproved_building_dimensions.py new file mode 100644 index 0000000000000000000000000000000000000000..2313281884afd234997ef644a494c878164686a1 --- /dev/null +++ b/app/views/unapproved_building_dimensions.py @@ -0,0 +1,18 @@ +"""Views for managing unapproved_building_dimensions data.""" +from werkzeug.exceptions import MethodNotAllowed +from flask import request + +from app.views.base import RestView +from app.controllers.unapproved_building_dimensions import UnapprovedBuildingDimensionsController + + +class UnapprovedBuildingDimensionsView(RestView): + """The unapproved_building_dimensions view.""" + def get_controller(self): + """Return an instance of the unapproved_building_dimensions controller.""" + return UnapprovedBuildingDimensionsController() + + def post(self): + """Post an unapproved_building_dimensions row""" + model = self.get_controller().post(self.request_json(), request.args) + return self.json(self.parse(model), 201) diff --git a/app/views/unapproved_point.py b/app/views/unapproved_point.py new file mode 100644 index 0000000000000000000000000000000000000000..6459a31ac334eb1ff218f42233f550538ed0c23a --- /dev/null +++ b/app/views/unapproved_point.py @@ -0,0 +1,21 @@ +"""Views for managing unapproved_point data.""" +from werkzeug.exceptions import MethodNotAllowed +from flask import request + +from app.views.base import RestView +from app.controllers.unapproved_point import UnapprovedPointController + + +class UnapprovedPointView(RestView): + """The unapproved_point view.""" + def get_controller(self): + """Return an instance of the unapproved_point controller.""" + return UnapprovedPointController() + + def post(self): + """Post a list of unapproved_point rows""" + result = self.get_controller().post(self.request_json(), request.args) + parsed_result = [] + for model in result: + parsed_result.append(self.parse(model)) + return self.json(parsed_result, 201) diff --git a/app/views/unapproved_window_door.py b/app/views/unapproved_window_door.py new file mode 100644 index 0000000000000000000000000000000000000000..1a257eb44ee9681f04376bdce6ff4c3ae331dd49 --- /dev/null +++ b/app/views/unapproved_window_door.py @@ -0,0 +1,21 @@ +"""Views for managing unapproved_window_door data.""" +from werkzeug.exceptions import MethodNotAllowed +from flask import request + +from app.views.base import RestView +from app.controllers.unapproved_window_door import UnapprovedWindowDoorController + + +class UnapprovedWindowDoorView(RestView): + """The unapproved_window_door view.""" + def get_controller(self): + """Return an instance of the unapproved_window_door controller.""" + return UnapprovedWindowDoorController() + + def post(self): + """Post a list of unapproved_window_door rows""" + result = self.get_controller().post(self.request_json(), request.args) + parsed_result = [] + for model in result: + parsed_result.append(self.parse(model)) + return self.json(parsed_result, 201) diff --git a/requirements.txt b/requirements.txt index ef551a0ff2710404a4eaec7fdf3e6bea710f5428..641a43c02bef88bb746800e58144a1c35b18fda2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ arrow==0.7.0 beautifulsoup4==4.4.1 blessed==1.9.5 +boto==2.45.0 botocore==1.3.28 cement==2.4.0 colorama==0.3.3 @@ -40,4 +41,5 @@ wcwidth==0.1.6 websocket-client==0.35.0 Werkzeug==0.11.4 WTForms==2.1 -boto==2.45.0 + +git+ssh://git@github.com/Blocp/bpeng.git