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.
Related
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)
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.
I'm attempting to create an application to retrieve and analyse emails sent through gmail. I'm using an alteration on the tutorial found here;
http://www.voidynullness.net/blog/2013/07/25/gmail-email-with-python-via-imap/
readmail.py
EMAIL_ACCOUNT = "*****"
PASSWD = "*****"
def process_mailbox(M):
rv, data = M.search(None, "ALL")
resp, items = M.search(None, "ALL")
if rv != 'OK':
print("No messages found!")
return
for num in data[0].split():
rv, data, = M.fetch(num, '(RFC822)')
if rv != 'OK':
print("ERROR getting message", num)
return
msg = email.message_from_bytes(data[0][1])
hdr = email.header.make_header(email.header.decode_header(msg['Subject']))
if msg.is_multipart():
for part in msg.get_payload():
body = part.get_payload()
subject = str(hdr)
print('Message %s: %s' % (num, subject))
print('Body:', body)
M = imaplib.IMAP4_SSL('imap.gmail.com',993)
try:
rv, data = M.login(EMAIL_ACCOUNT, PASSWD)
except imaplib.IMAP4.error:
print ("LOGIN FAILED!!! ")
sys.exit(1)
print(rv, data)
rv, data = M.select("INBOX")
if rv == 'OK':
print("Processing mailbox...\n")
process_mailbox(M)
M.close()
else:
print("ERROR: Unable to open mailbox ", rv)
M.logout()
When I run this code through the command line the output is as expected, however when ran through a basic flask import the entire thing falls apart.
app.py
from flask import Flask, render_template, jsonify, request
from readmail import process_mailbox
import json
import imaplib
app = Flask(__name__)
#app.route('/')
def homepage():
return render_template('index.html')
#app.route('/test')
def test():
return json.dumps({'name': process_mailbox(imaplib.IMAP4_SSL('imap.gmail.com',993)).subject})
if __name__ == '__main__':
app.run(use_reloader=True, debug=True)
The error I receive is;
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\flask\app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Python34\lib\site-packages\flask\app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "C:\Python34\lib\site-packages\flask\app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Python34\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "C:\Python34\lib\site-packages\flask\app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python34\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python34\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python34\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "C:\Python34\lib\site-packages\flask\app.py", line 1612, in
full_dispatch_request
rv = self.dispatch_request()
File "C:\Python34\lib\site-packages\flask\app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\user\project\flask\venv\Project\app.py", line 13, in test
return json.dumps({'name':
process_mailbox(imaplib.IMAP4_SSL('imap.gmail.com',993)).subject})
File "C:\Users\user\project\flask\venv\Project\readmail.py", line 14, in process_mailbox
M.select('"[Gmail]/All Mail"')
File "C:\Python34\lib\imaplib.py", line 683, in select
typ, dat = self._simple_command(name, mailbox)
File "C:\Python34\lib\imaplib.py", line 1134, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "C:\Python34\lib\imaplib.py", line 882, in _command
', '.join(Commands[name])))imaplib.error: command SELECT illegal in state NONAUTH, only allowed in
states AUTH, SELECTED
I've made several attempts this past week to find out ways to fix this error so any help would be appreciated.
Firstly, looking at the end of the traceback, you've got imaplib.error: command SELECT illegal in state NONAUTH, only allowed in states AUTH, SELECTED - and going back to the two lines in the traceback for your code:
app.py, test ... return json.dumps({'name': process_mailbox(imaplib.IMAP4_SSL('imap.gmail.com',993)).subject})
readmail.py process_mailbox ... M.select('"[Gmail]/All Mail"')
I've trimmed some excess here, but in test, you are only connecting to the Gmail IMAP server, but not logging in. The following code is what your ffirst file does:
M = imaplib.IMAP4_SSL('imap.gmail.com',993)
try:
rv, data = M.login(EMAIL_ACCOUNT, PASSWD)
except imaplib.IMAP4.error:
print ("LOGIN FAILED!!! ")
sys.exit(1)
Also, process_mailbox will only return null, it changes the object you've passed directly.
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
I have been stumped and can't seem to figure out why I am receiving an AssertionError. I am currently working on a rest api using the flask_restful lib. I am querying by:
#staticmethod
def find_by_id(id, user_id):
f = File.query.filter_by(id=id).first() #Error is happening here
if f is not None:
if f.check_permission(user_id)>=4:
return f
print f.check_permission(user_id)
FileErrors.InsufficientFilePermission()
FileErrors.FileDoesNotExist()
The error message looks like this:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 271, in error_router
return original_handler(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 268, in error_router
return self.handle_error(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 271, in error_router
return original_handler(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1531, in handle_user_exception
assert exc_value is e
AssertionError
This is how my File model looks like:
class File(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer)
parts = db.Column(db.Integer)
size = db.Column(db.Integer)
name = db.Column(db.String(100))
def __init__ (self, file_info):
self.user_id = file_info['user_id']
self.parts = file_info['parts']
self.size = file_info['size']
self.name = file_info['name']
#staticmethod
def create(file_info):
return add_to_db(File(file_info))
#staticmethod
def delete(file_id, user_id):
pass
def check_permission(self,user_id):
permission = 0
print 'self.user_id {}'.format(self.user_id)
print 'user_id {}'.format(user_id)
if self.user_id == user_id:
return 7
fs = FileShare.find_by_file_and_user_id(self.id, user_id)
if fs is not None:
permission = fs.permission
return permission
#staticmethod
def find_by_id(id, user_id):
f = File.query.filter_by(id=id).first() #Error is happening here
if f is not None:
if f.check_permission(user_id)>=4:
return f
print f.check_permission(user_id)
FileErrors.InsufficientFilePermission()
FileErrors.FileDoesNotExist()
Any help would be appreciated. Thanks in advance.
Are you sure you want to have an assignment operator instead of comparison in your filter. Try replacing = with == and see if it solves your problem.
f = File.query.filter_by(id == id).first()
Hannu
Although I couldn't figure out why the error occurs, I know how as well as how to prevent it. It is created because the query doesn't pull the live data right after the commit. The way to prevent it is by using db.session.query(). So in my example I would change:
f = File.query.filter_by(id=id).first()
to
f = db.session.query(File).filter_by(id=id).first()
For some reason that works. Although I don't know why.
EDIT: It seems to have to do with the class not receiving updated session. For the time being I recommending using queries within session.