Flask AssertionError While Trying to "POST" - python

I am brand new to python as of about 3 days ago and I need to build a prototype python server for an iOS work project. I followed a tutorial for the initial build.
When I perform a "POST" request, I get an error. Here is my full code, followed by the error I'm receiving in the Terminal when a "POST" request is submitted.
PS. also fairly new to stack overflow so I'm sorry if I'm asking this question incorrectly
import flask
from flask import Flask, request, jsonify
from flask_uploads import UploadSet, IMAGES, configure_uploads
from flask import make_response
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
import turicreate as tc
import sys
from queue import Queue
import os
import uuid
import logging
from flask import send_from_directory
import threading
from marshmallow import fields
from marshmallow import post_load
app = Flask(__name__)
if __name__ == "__main__":
# Only for debugging while developing
app.run(host='0.0.0.0', debug=True)
#configure logging
logging.basicConfig( level=logging.DEBUG,
format='[%(levelname)s] - %(threadName)-10s : %(message)s')
#configure images destination folder
app.config['UPLOADED_IMAGES_DEST'] = './images'
images = UploadSet('images', IMAGES)
configure_uploads(app, images)
#configure sqlite database
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'facerecognition.sqlite')
db = SQLAlchemy(app)
ma = Marshmallow(app)
#model/users is a many to many relationship, that means there's a third #table containing user id and model id
users_models = db.Table('users_models',
db.Column("user_id", db.Integer, db.ForeignKey('user.id')),
db.Column("model_id", db.Integer, db.ForeignKey('model.version'))
)
# model table
class Model(db.Model):
version = db.Column(db.Integer, primary_key=True)
url = db.Column(db.String(100))
users = db.relationship('User', secondary=users_models)
# user table
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(300))
position = db.Column(db.String(300))
def __init__(self, name, position):
self.name = name
self.position = position
#user schema
class UserSchema(ma.Schema):
class Meta:
fields = ('id', 'name', 'position')
#model schema
class ModelSchema(ma.Schema):
version = fields.Int()
url = fields.Method("add_host_to_url")
users = ma.Nested(UserSchema, many=True)
# this is necessary because we need to append the current host to the model url
def add_host_to_url(self, obj):
return request.host_url + obj.url
#initialize everything
user_schema = UserSchema()
users_schema = UserSchema(many=True)
model_schema = ModelSchema()
models_schema = ModelSchema(many=True)
db.create_all()
#error handlers
#app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'not found'}), 404)
#app.errorhandler(400)
def not_found(error):
return make_response(jsonify({'error': 'bad request'}), 400)
#register user
#app.route("/testImages/face-recognition/api/v1.0/user/register", methods=['POST'])
def register_user():
if not request.form or not 'name' in request.form:
return make_response(jsonify({'status': 'failed', 'error': 'bad request', 'message:' : 'Name is required'}), 400)
else:
name = request.form['name']
position = request.form.get('position')
if position is None:
position = ""
newuser = User(name, position)
db.session.add(newuser)
db.session.commit()
if 'photos' in request.files:
uploaded_images = request.files.getlist('photos')
save_images_to_folder(uploaded_images, newuser)
return jsonify({'status' : 'success', 'user' : user_schema.dump(newuser).data })
#function to save images to image directory
def save_images_to_folder(images_to_save, user):
for a_file in images_to_save:
# save images to images folder using user id as a subfolder name
images.save(a_file, str(user.id), str(uuid.uuid4()) + '.')
# get the last trained model
model = Model.query.order_by(Model.version.desc()).first()
if model is not None:
# increment the version
queue.put(model.version + 1)
else:
# create first version
queue.put(1)
#app.route("/testImages/face-recognition/api/v1.0/model/info" , methods=['GET'])
def get_model_info():
models_schema.context['request'] = request
model = Model.query.order_by(Model.version.desc()).first()
if model is None:
return make_response(jsonify({'status': 'failed', 'error': 'model is not ready'}), 400)
else:
return jsonify({'status' : 'success', 'model' : model_schema.dump(model).data})
#serve models
#app.route('/models/')
def download(filename):
return send_from_directory('models', filename, as_attachment=True)
def train_model():
while True:
#get the next version
version = queue.get()
logging.debug('loading images')
data = tc.image_analysis.load_images('images', with_path=True)
# From the path-name, create a label column
data['label'] = data['path'].apply(lambda path: path.split('/')[-2])
# use the model version to construct a filename
filename = 'Faces_v' + str(version)
mlmodel_filename = filename + '.mlmodel'
models_folder = 'models/'
# Save the data for future use
data.save(models_folder + filename + '.sframe')
result_data = tc.SFrame( models_folder + filename +'.sframe')
train_data = result_data.random_split(0.8)
#the next line starts the training process
model = tc.image_classifier.create(train_data, target='label', model='resnet-50', verbose=True)
db.session.commit()
logging.debug('saving model')
model.save( models_folder + filename + '.model')
logging.debug('saving coremlmodel')
model.export_coreml(models_folder + mlmodel_filename)
# save model data in database
modelData = Model()
modelData.url = models_folder + mlmodel_filename
classes = model.classes
for userId in classes:
user = User.query.get(userId)
if user is not None:
modelData.users.append(user)
db.session.add(modelData)
db.session.commit()
logging.debug('done creating model')
# mark this task as done
queue.task_done()
#configure queue for training models
queue = Queue(maxsize=0)
thread = threading.Thread(target=train_model, name='TrainingDaemon')
thread.setDaemon(False)
thread.start()```
Here is the Error I get In the Terminal
[DEBUG] - TrainingDaemon : loading images
127.0.0.1 - - [03/Jan/2020 11:52:39] "POST /testImages/face-recognition/api/v1.0/user/register HTTP/1.1" 500 -
[INFO] - Thread-3 : 127.0.0.1 - - [03/Jan/2020 11:52:39] "POST /testImages/face-recognition/api/v1.0/user/register HTTP/1.1" 500 -
Traceback (most recent call last):
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 2463, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 2449, in wsgi_app
response = self.handle_exception(e)
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1866, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/me/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/me/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/me/Desktop/GorillaFace/app.py", line 103, in register_user
save_images_to_folder(uploaded_images, newuser)
File "/Users/me/Desktop/GorillaFace/app.py", line 121, in save_images_to_folder
#app.route("/testImages/face-recognition/api/v1.0/model/info" , methods=['GET'])
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 1314, in decorator
self.add_url_rule(rule, endpoint, f, **options)
File "/Users/me/venv/lib/python3.7/site-packages/flask/app.py", line 90, in wrapper_func
"A setup function was called after the "
AssertionError: A setup function was called after the first request was handled. This usually indicates a bug in the application where a module was not imported and decorators or other functionality was called too late.
To fix this make sure to import all your view modules, database models and everything related at a central place before the application starts serving requests.
Exception in thread TrainingDaemon:
Traceback (most recent call last):
File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "/Users/me/Desktop/GorillaFace/app.py", line 159, in train_model
model = tc.image_classifier.create(train_data, target='label', model='resnet-50', verbose=True)
File "/Users/me/venv/lib/python3.7/site-packages/turicreate/toolkits/image_classifier/image_classifier.py", line 225, in create
raise TypeError('"dataset" must be of type SFrame.')
TypeError: "dataset" must be of type SFrame.
What I've tried:
Like I said I'm still new to python so I don't know much about troubleshooting python code. The assertion error seems to be saying something was not imported correctly, so I re-installed, flask-uploads,Flask-SQLAlchemy,flask-marshmallow, marshmallow-sqlalchemy. I also made sure all the imports looked like it did in the tutorial.
Anyone have any ideas as to what I need to do to not get this error? what this code should do is allow me to post a name, position, and photos to the server which will then train a ML model to recognize the new photos.

Error shows in which line it has problem
model = tc.image_classifier.create(...)
and it has problem with
"dataset" must be of type SFrame.
so use at least print() and print(type(..)) to check variablse which you use in this line and see if you use SFrame.

Related

Locust with Python: No Locust Stats are showing on UI

I am new to Locust (and Python) and am trying to load test an API. My Locust UI shows no stats whatsoever - no users hatched, no API calls, etc. I need help figuring out how to get them to show up on the UI so I can get the stats.
Here is my locust.py file:
from locust import HttpUser, SequentialTaskSet, task, constant
import finops_service.locust_files.finops_fx_load_testing as load_test
class FXTransaction(SequentialTaskSet):
def __init__(self, parent):
super().__init__(parent)
self.comp_data = dict()
self.rate_lock_response = dict()
self.transaction_response = dict()
self.fx_providerID = '57638f08-e938-48d7-accf-325b6728a9ee'
self.headers = {"Content-Type": "application/json"}
def on_start(self):
load_test.login(self),
#task
def get_company_data(self):
# Get company data
self.comp_data = load_test.get_company_data(self)
print("Company is: ", self.comp_data['company'])
print("Vendor is: ", self.comp_data['vendor'])
print("Payment Method is: ", self.comp_data['payment_method'])
print("Funding Method is: ", self.comp_data['funding_method'])
# #task
# def rate_lock(self):
print("Starting rate lock")
load_test.rate_lock(self)
print("This is the returned rate lock response:")
print(self.rate_lock_response)
# #task
# def approve_transaction(self):
# print("Starting transaction")
# load_test.approve_transaction(self)
# print("This is the returned transaction response:")
# print(self.transaction_response)
class MyUser(HttpUser):
wait_time = constant(1)
# weight = 1
host = "http://localhost:8080/PaymentService/base/"
tasks = [FXTransaction]
And here are my functions:
import json
import random
import uuid
from utils import json_util as json_util
enter code here
def login(self):
try:
with self.client.post(
"security/login",
headers={'Content-Type': 'application/json',
'Authorization': 'BASIC 0ee89b88-5c4b-4922-b1f9-c1584ab26e7e:12345'},
name=login,
timeout=55.6,
catch_response=True) as response:
if response.status_code != 200:
response.failure("Login failed")
else:
response.success()
print("Login succeeded")
self.headers.update({'if-Match': "{}".format(response.headers["ETag"])})
except ConnectionRefusedError:
print("The test could not connect to {}".format("http://localhost:8080/PaymentService/security/login"))
raise
def get_company_data(self):
comp_index = random.randrange(0, 9)
print("Random company data index is: ", comp_index)
try:
body = json.load(open("finops_service/locust_files/load_testing_data.json", 'r'))
comp_data = body['fx']['multipleCompanies_10']['company_data'][comp_index]
except ConnectionRefusedError:
print("The test could not connect to {}".format("http://localhost:8080/PaymentService/security/login"))
raise
return comp_data
def rate_lock(self):
body = json_util.get_json_object(
"/finops_service/locust_files/rate_lock_load_testing.json",
'fx'.lower(),
'valid_multiple_20'.lower()
)
body["debtorCompanyProfileId"] = self.comp_data['company']
i = 0
# there are 20 rate locks so need to update each request
while i < 20:
body["rateRequestPayments"][i]["creditorProfileId"] = self.comp_data['vendor']
body["rateRequestPayments"][i]["debtorProfileId"] = self.comp_data['company']
body["rateRequestPayments"][i]["paymentMethodId"] = self.comp_data['payment_method']
random_float_no = round(random.uniform(1.11, 999.99), 2)
body['rateRequestPayments'][i]['amount'] = random_float_no
i += 1
try:
print("RIGHT BEFORE RATE LOCK CALL")
with self.client.post("services/transaction/fx/rate/lock",
data=json.dumps(body),
headers=self.headers,
name="rate lock",
timeout=55.6,
catch_response=True) as response:
if "GENERIC_FAILURE" in response.text:
response.failure("FAIL")
print("Rate lock call failed")
else:
response.success()
print("rate lock succeeded")
print("Rate lock response is:.........", response)
print("Rate lock response TEXT is:.........", response.text)
self.rate_lock_response = response.text
except ConnectionRefusedError:
print("The test could not connect to {}".format(
"http://localhost:8080/PaymentService/services/transaction/fx/rate/lock"))
raise
When I run this, I can see that the self.client.post("services/transaction/fx/rate/lock"... is happening and either succeeding or failing. However, in the Locust UI, I show 0 users hatched (console shows I hatched 5) and 0 tasks shown.
I get this error each time I run which it looks related to my stats not showing up but I don't know why it is happening:
Traceback (most recent call last):
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/gevent/pywsgi.py", line 999, in handle_one_response
self.run_application()
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/gevent/pywsgi.py", line 945, in run_application
self.result = self.application(self.environ, self.start_response)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/locust/web.py", line 319, in wrapper
return view_func(*args, **kwargs)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/locust/util/cache.py", line 21, in wrapper
cache["result"] = func(*args, **kwargs)
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/site-packages/locust/web.py", line 208, in request_stats
"safe_name": escape(s.name, quote=False),
File "/Users/michellegautier/.pyenv/versions/3.7.4/lib/python3.7/html/__init__.py", line 19, in escape
s = s.replace("&", "&") # Must be done first!
AttributeError: 'function' object has no attribute 'replace'
2021-03-18T16:44:29Z {'REMOTE_ADDR': '::1', 'REMOTE_PORT': '49242', 'HTTP_HOST': 'localhost:8089', (hidden keys: 25)} failed with AttributeError
Can someone please help me figure out how to make my stats show up?
Thank you!!!!
The stats not showing up in Locust is because of that Exception you posted. If you resolve that and get to where your code runs without issues, you should see stats in the Locust UI.
There are a number of issues with your code.
I'm not sure if it's just an issue with pasting your code into SO, but your on_start() and get_company_data() functions (and the #task decorator) need to be indented so they're part of FXTransaction.
Also, trying to use self.client in login() or get_company_data() isn't going to work because they aren't part of a class so there's no such thing as self. You'd probably want to change self in that function to just client and then pass in self.client when you call it from the on_start() function.
But what's possibly your main issue is here:
with self.client.post(
"security/login",
headers={'Content-Type': 'application/json',
'Authorization': 'BASIC 0ee89b88-5c4b-4922-b1f9-c1584ab26e7e:12345'},
name=login,
…
name here is the name of the endpoint (URL) you're hitting. This is supposed to be a string but you're giving it your function login. So when the Locust code tries to do some thing with your name value that it wants to do, expecting it to be a string, it's going to fail because it's trying to do those on a function instead. That's what AttributeError: 'function' object has no attribute 'replace' means.
I think if you fix all of those things, Locust should work.

How would I be able to connect to SQLAlchemy python to a server.py file

What I want to do is have a file called server.py that has the SQLAlchemy database in it and a web server file called webServer.py that has all the redirecting and button click events in it. I don't know how to connect the two. The database works when the server.py code in inside the webServer.py file, I have all the imports, just in case anyone needs the code, here it is:
webServer.py
from flask import Flask, render_template
from flask import redirect, url_for, request, session
from server import *
web_server = Flask(__name__)
web_server.secret_key = "SecretKey"
""" ROUTING """
#web_server.route("/")
#web_server.route("/home")
def index():
return render_template("index.html")
#web_server.route("/sign-in", methods=["POST", "GET"])
def signIn():
if request.method == "POST":
uip = request.form["UIP"]
pip = request.form["PIP"]
# START PF DATABASE TESTING
isAcct = checkForAccount(uip)
if isAcct:
isCorrect = checkUser(uip, pip)
if isCorrect:
print("CORRECT")
return redirect(url_for("index"))
else:
print("FALSE")
return render_template("signIn.html", incorrectPass="Wrong username or password.")
else:
createAccount(uip, pip)
return render_template("signIn.html")
# END OF DATABASE TESTING
else:
return render_template("signIn.html")
#web_server.route("/run<data>")
def run(data):
check = checkUser()
if check:
print(data)
return "none"
""" ERROR HANDLING """
#web_server.errorhandler(404)
def error404(error):
return render_template("error.html", EC="Error! Page Not Found!"), 404
#web_server.errorhandler(500)
def error500(error):
return render_template("error.html", EC="Error! Internal Server Issue!"), 500
print("Server Loaded..")
if __name__ == "__main__":
db.create_all()
# server.run(host="192.168.1.80", port="3000") #For running on IP address
web_server.run(port="3000")
server.py
from webServer import web_server
from flask_sqlalchemy import SQLAlchemy
web_server.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///dataBase.sqlite3"
web_server.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(web_server)
class dataBase(db.Model):
#_id = db.Column(db.Integer, primary_key=True)
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(100), nullable=False)
def __init__(self, username, password):
self.username = username
self.password = password
def checkUser(username, password):
usernameQuery = dataBase.query.filter_by(username=username).first()
correctUser = usernameQuery.username
correctPass = usernameQuery.password
if username == correctUser and password == correctPass:
return True
else:
return False
def checkForAccount(uip):
found_user = dataBase.query.filter_by(username=uip).first()
return found_user
def createAccount(uip, pip):
accountStartupData = dataBase(uip, pip)
db.session.add(accountStartupData)
db.session.commit()
And here is the error:
[2020-05-18 17:59:48,172] ERROR in app: Exception on /sign-in [POST]
Traceback (most recent call last): File
"C:\Users\callu\Documents\Javo\venv\lib\site-packages\sqlalchemy\util_collections.py",
line 1020, in call
return self.registry[key] KeyError: 15864
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File
"C:\Users\callu\Documents\Javo\venv\lib\site-packages\flask\app.py",
line 2447, in wsgi_app
response = self.full_dispatch_request() File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\flask\app.py",
line 1952, in full_dispatch_request
rv = self.handle_user_exception(e) File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\flask\app.py",
line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb) File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\flask_compat.py",
line 39, in reraise
raise value File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\flask\app.py",
line 1950, in full_dispatch_request
rv = self.dispatch_request() File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\flask\app.py",
line 1936, in dispatch_request
return self.view_functionsrule.endpoint File "C:/Users/callu/Documents/Javo/webServer.py", line 25, in signIn
isAcct = checkForAccount(uip) File "C:\Users\callu\Documents\Javo\server.py", line 30, in checkForAccount
found_user = dataBase.query.filter_by(username=uip).first() File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\flask_sqlalchemy__init__.py",
line 519, in get
return type.query_class(mapper, session=self.sa.session()) File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\sqlalchemy\orm\scoping.py",
line 78, in call
return self.registry() File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\sqlalchemy\util_collections.py",
line 1022, in call
return self.registry.setdefault(key, self.createfunc()) File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\sqlalchemy\orm\session.py",
line 3286, in call
return self.class_(**local_kw) File "C:\Users\callu\Documents\Javo\venv\lib\site-packages\flask_sqlalchemy__init__.py",
line 137, in init
track_modifications = app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] KeyError: 'SQLALCHEMY_TRACK_MODIFICATIONS'

Python Mockito configuration for running test cases

I am writing unit tests for a Flask app using unittest and using mockito to mock the services which require the server to be up and running.
However I am unable to figure out how to mock the server. I am getting some error.
Here are the code snippets:
node.py
#app.route('/transaction', methods = ["POST"])
def transaction():
req = request.get_json()
print("\nreq")
i = bitcoin.addTransaction(req)
if req['purpose'] != 'redeem':
users = getColumn(sheet_u,0)
index = users.index(req['recipient'])
user = getRow(sheet_u,index)
hasPoints = int(user[labels_u.index("POINTS")])
hasPoints += req['amount']
setCell(sheet_u, index, labels_u.index("POINTS"), hasPoints)
wb.save("db.xlsx")
else:
users = getColumn(sheet_u,0)
index = users.index(req['sender'])
user = getRow(sheet_u,index)
hasPoints = int(user[labels_u.index("POINTS")])
hasPoints -= req['amount']
setCell(sheet_u, index, labels_u.index("POINTS"), hasPoints)
wb.save("db.xlsx")
r = requests.get(url = bitcoin.currentNodeUrl+"/save")
return jsonify({"note":"New transaction will be added to block "+str(i)})
#app.route('/transaction/broadcast', methods = ["POST"])
def transactionBroadcast():
check = True
failure = ""
req = request.get_json()
# Hiding some methods that change the value of check flag
if check:
newTransaction = bitcoin.createNewTransaction(req['amount'],req['sender'],req['recipient'],req['purpose'],time.time())
bitcoin.addTransaction(newTransaction)
promises = []
for node in bitcoin.networkNodes:
response = ""
try:
r = requests.post(url=node+"/transaction",json=newTransaction) #this line throws error
response = r.text #program control doesn't come here
print(newTransaction)
print("\n")
print(response)
except requests.exceptions.ConnectionError:
response = "{\"note\":\"The node is unavailable. It will sync itself later on.\"}"
if 'note' in json.loads(response):
promises.append(json.loads(response))
if len(promises) == len(bitcoin.networkNodes):
r = requests.get(url = bitcoin.currentNodeUrl+"/save")
return jsonify({"note":"Transaction broadcasted successfully"})
else:
return jsonify({"fail":"Invalid transaction. "+failure})
if __name__ == '__main__':
bitcoin = Blockchain(sys.argv[1])
app.run(port=sys.argv[1])
test_t2.py
from node import app
from flask import json
import unittest
import node
import requests
from mockito import when, mock, unstub
class TestSearch(unittest.TestCase):
print("inside TEST class")
def test_transactionBroadcast(self):
node.bitcoin = node.Blockchain('5000')
response = mock({"note": "New transaction will be added to block 5"})
when(requests).post('http://localhost:5001/transaction', strict = False ).thenReturn(response)
data1 = {
"sender" : "ph1000005",
"recipient" : "TIAA",
"amount" : 1,
"purpose" : "redeem"
}
response = app.test_client().post(
'/transaction/broadcast',
json = data1,
content_type='application/json',
)
print("running TransactionBroadcast test")
print(response)
self.assertEqual(response.get_json(), {
# 'fail': "Invalid transaction. This user doesn't exist. Check userid again."
"note": "Transaction broadcasted successfully"
})
unstub()
if __name__ == '__main__':
unittest.main()
error log
C:\POC>coverage run test_t2.py
inside TEST class
[2018-12-12 19:58:22,181] ERROR in app: Exception on /transaction/broadcast [POST]
Traceback (most recent call last):
File "c:\program files\python36\lib\site-packages\flask\app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "c:\program files\python36\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "c:\program files\python36\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "c:\program files\python36\lib\site-packages\flask\_compat.py", line 35, in reraise
raise value
File "c:\program files\python36\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "c:\program files\python36\lib\site-packages\flask\app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\POC\node.py", line 230, in transactionBroadcast
r = requests.post(url=node+"/transaction",json=newTransaction)
File "c:\program files\python36\lib\site-packages\mockito\mocking.py", line 89, in new_mocked_method
self, method_name, *args, **kwargs)
File "c:\program files\python36\lib\site-packages\mockito\mocking.py", line 44, in remembered_invocation_builder
return invoc(*args, **kwargs)
File "c:\program files\python36\lib\site-packages\mockito\invocation.py", line 103, in __call__
""" % (self, "\n ".join(str(invoc) for invoc in stubbed_invocations)))
mockito.invocation.InvocationError:
You called
post(url='http://localhost:5001/transaction', json={'amount': 1, 'purpose': 'redeem', 'recipient': 'TIAA', 'sender': 'ph1000005', 'timestamp': 1544624902.1440911, 'transactionId': 'd919ffb4080f47e890957f3f3edc97a1'}),
which is not expected. Stubbed invocations are:
post('http://localhost:5001/transaction', strict=False)
(Set strict to False to bypass this check.)
running TransactionBroadcast test
<Response streamed [500 INTERNAL SERVER ERROR]>
F
======================================================================
FAIL: test_transactionBroadcast (__main__.TestSearch)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_t2.py", line 49, in test_transactionBroadcast
"note": "Transaction broadcasted successfully"
AssertionError: None != {'note': 'Transaction broadcasted successfully'}
----------------------------------------------------------------------
Ran 1 test in 0.682s
FAILED (failures=1)
Now, I'm not sure what am I doing wrong. there is an internal route call to /transaction in the route /transaction/broadcast which is failing.
Since this is a unit testing, it doesn't require the server to be up and running. and the route is calling localhost
Any ideas on how to deal with it?
Basically, the stub error message tells you that your stubbing signature
when(requests).post('http://localhost:5001/transaction', strict = False ).thenReturn(response)
is wrong.
Note 1: when using strict it must go into when like so: when(requests, strict=False). But not being strict is usually not what you want.
Instead you fix your stubbing, e.g.:
when(requests).post(url='http://localhost:5001/transaction', ...).thenReturn(response)
# or for python2
from mockito import kwargs
when(requests).post(url='http://localhost:5001/transaction', **kwargs).thenReturn(response)

Unserializable value

I'm currently stuck with a serialization problem. The data seems ok in Nameko but not in Flask because an error occurred. I tried to serialise and unserialize, but it didn't work.
Here is an example of data from a MongoDB database :
{u'building': u'urk', u'idcapteur': 8, u'room': u'tyu', u'idpiece': 1, u'uri': u'urk/tyu/luminosity/yota1', u'idMesure': 458945, u'subId': u'yota1', u'datemesure2': datetime.datetime(2017, 6, 16, 12, 48, 19, 179000), u'datemesure': datetime.datetime(2017, 6, 16, 12, 48, 19, 179000), u'device': u'luminosity', u'_id': ObjectId('7825ahy'), u'data': {u'date': u'2017-06-16T14:48:19.179435', u'payload': {u'subID': u'yota1', u'input': 50, u'value_units': u'lux', u'value': 500, u'unitID': u'inside'}, u'uri': u'urk/tyu/luminosity/yota1'}, u'mesurevaleur': [{u'idlibv': 5, u'valeur': 500.0}]}
Here is my Nameko program :
# -*-coding:utf-8 -*
# neocampus.py
import json
from database import startMongoDbConnection, getRawDataCollection, mongoDbQuery
from nameko.rpc import rpc
#from database.py import startMongoDbConnection, getRawDataCollection, mongoDbQuery
mdbConnection = ''
mdbCollection = ''
# Send a request to the microservices system. It will call other microservices
class MsRequest:
name="msRequest"
# TODO
#rpc
def msRequest(self, value):
# Connect to MongoDB database and collection, if not already done
global mdbConnection, mdbCollection, queryResult
if mdbConnection == '':
mdbConnection = startMongoDbConnection()
if mdbCollection == '':
mdbCollection = getRawDataCollection(mdbConnection)
# Check the requested microservice
someData = GetData()
jsonData = someData.getData(value)
# It prints the proper data
for document in jsonData:
print(document)
print("FINISHED !!!")
# Don't forget : closeMongoDbConnection()
return jsonData
# Get data depending on sensor type
class GetData:
name="getData"
def getData(self, sensorType):
global mdbCollection
queryResult = mongoDbQuery(mdbCollection, "device", "$eq", sensorType)
return queryResult
# From database.py
def mongoDbQuery(someCollection, key, choice, value):
# Use MongoDB query dependeing on choices in parameters
docs = someCollection.find({key:{choice:value}}).limit(10)
#for document in docs:
#print(document)
return docs
# Start a MongoDB connection
def startMongoDbConnection():
connected = connectToMongoDb("mongodb")
return connected
# Start a MongoDB connection
def startMongoDbConnection():
connected = connectToMongoDb("mongodb")
return connected
# Choose the first collection available (for raw data)
def getRawDataCollection(connection):
currentCollection = chooseCollection(connection, mongollection)
return currentCollection
And now, my Flask program :
#app.route('/', methods=['GET', 'POST'])
def getData():
with ClusterRpcProxy(CONFIG) as rpc:
myData = rpc.msRequest.msRequest("luminosity")
#for document in myData:
#print myData
return flask.jsonify(**myData)
Finally, the error output :
ERROR in app: Exception on / [GET]
Traceback (most recent call last):
File "/home/oyo/.local/lib/python2.7/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/oyo/.local/lib/python2.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/oyo/.local/lib/python2.7/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/oyo/.local/lib/python2.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/oyo/.local/lib/python2.7/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/oyo/flask_sandfox/sandfox.py", line 16, in getData
myData = rpc.msRequest.msRequest("luminosity")
File "/home/oyo/.local/lib/python2.7/site-packages/nameko/rpc.py", line 369, in __call__
return reply.result()
File "/home/oyo/.local/lib/python2.7/site-packages/nameko/rpc.py", line 327, in result
raise deserialize(error)
RemoteError: UnserializableValueError Unserializable value: `<pymongo.cursor.Cursor object at 0x7f3274612e50>`
With a print, data is correctly displayed in the terminal. But not in Flask, I get an error 500. I thought that with JSON data and Jsonify (found here, in this site), I could display something. But it's not the cas.
Any help, advice or hint would be gladly appreciated. Thank you.
For people who'll have this exact problem, it took me 5 days to find it. I was sure it was in JSON, because, when I copied/pasted the result, it was ok. In fact, it was in BSON (I didn't even know this format). So, just add this at the beginning of your file :
from bson.json_util import dumps
Then, add this :
# limit for the example
retrievedocs = someCollection.find({* something *}}, {'_id': 0}).limit(10)
docs = dumps(retrievedocs)
Then, the serialization between Nameko and Flask will work.

Cannot pass the form data to a method in order to validate form

I'm trying to create a custom validator for one field in the AddSongForm. I used the inline validator and it uses two methods from my Songs class. When I try running the code, I get the following trace back:
form = AddSongForm()
[2017-05-16 13:44:11,547] ERROR in app: Exception on /addsong [POST]
Traceback (most recent call last):
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python36-32\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Python36-32\lib\site-packages\flask_login\utils.py", line 228, in decorated_view
return func(*args, **kwargs)
File "C:/Users/Pellissari/Desktop/files/projects/Musical 9gag/view.py", line 40, in addsong
if form.validate_on_submit():
File "C:\Python36-32\lib\site-packages\flask_wtf\form.py", line 101, in validate_on_submit
return self.is_submitted() and self.validate()
File "C:\Python36-32\lib\site-packages\wtforms\form.py", line 310, in validate
return super(Form, self).validate(extra)
File "C:\Python36-32\lib\site-packages\wtforms\form.py", line 152, in validate
if not field.validate(self, extra):
File "C:\Python36-32\lib\site-packages\wtforms\fields\core.py", line 204, in validate
stop_validation = self._run_validation_chain(form, chain)
File "C:\Python36-32\lib\site-packages\wtforms\fields\core.py", line 224, in _run_validation_chain
validator(form, self)
File "C:\Users\Pellissari\Desktop\files\projects\app\forms.py", line 20, in validate_song_link
if Songs.get_provider(url) in valid_providers:
TypeError: get_provider() missing 1 required positional argument: 'url'
127.0.0.1 - - [16/May/2017 13:44:11] "POST /addsong HTTP/1.1" 500 -
This is my form class
class AddSongForm(Form):
song_title = StringField('song_title', validators=[DataRequired()])
song_artist = StringField('song_artist', validators=[DataRequired()])
song_genre = StringField('song_genre')
song_link = StringField('song_link', validators=[DataRequired()])
def validate_song_link(form, song_link):
valid_providers = ['youtube.com', 'www.youtube.com', 'soundcloud.com', 'www.soundcloud.com']
url = song_link.data
if Songs.get_provider(url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True
else:
print("couldn't get your content")
return False
else:
print("unsupported provider")
return False
And here is the class I used the methods
class Songs(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
title = db.Column(db.String(50))
artist = db.Column(db.String(30))
genre = db.Column(db.String(40))
author = db.Column(db.String(40))
timestamp = db.Column(db.DateTime)
likes_num = db.Column(db.Integer)
song_link = db.Column(db.String(120))
def get_provider(self, url):
return urllib.parse.urlsplit(url)[1]
def get_embed_code(self, url):
code = None
vars = {'url': url, 'format': 'json', 'iframe': 'true', 'maxwidth': '450', 'show_comments': 'false'}
provider = self.get_provider(url)
endpoint = "http://"+provider+"/oembed?"
source = endpoint+urllib.parse.urlencode(vars)
try:
request = urlopen(source)
code = json.load(request)['html']
return code
except:
print("impossible to get your content. Check the link")
return False
I'm quite new with Python and this is my first time writing OO code, so I have no idea what could be happening here. Besides the problem, I would be happy if you also could give me some feedback on the code and if there are room to improve in some sense.
I'm not convinced these should be methods on Songs. They don't refer to anything to do with the Song class.
However if you want to keep them as methods, but still want to call them from the class, they need to be classmethods, not instance methods.
#classmethod
def get_provider(cls, url):
return urllib.parse.urlsplit(url)[1]
#classmethod
def get_embed_code(cls, url):
...
provider = cls.get_provider(url)
First of all correct the indentation for the method validate_song_link. It should be like this:
def validate_song_link(form, song_link):
valid_providers = ['youtube.com', 'www.youtube.com', 'soundcloud.com', 'www.soundcloud.com']
url = song_link.data
if Songs.get_provider(url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True
else:
print("couldn't get your content")
return False
else:
print("unsupported provider")
return False
To solve your problem you can try to change the get_provider method to a class method like this:
#classmethod
def get_provider(cls, url):
return urllib.parse.urlsplit(url)[1]
And then you can call this way:
songs = Songs()
if Songs.get_provider(songs, url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True

Categories

Resources