Custom exceptions in python starlette - python-3.x

I am trying to raise the custom exception using the starlette framework in python. I have the API call which checks some condtions depends on the result, it should raise exception.
I have two files app.py and error.py
#app.py
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from error import EmptyParamError
async def homepage(request):
a=1
b=0
if a == 1:
raise EmptyParamError(400, "status_code")
return JSONResponse({'hello': 'world'})
routes = [
Route("/", endpoint=homepage)
]
app = Starlette(routes=routes,debug=True)`
#error.py ```
from starlette.responses import JSONResponse
class BaseError(Exception):
def __init__(self, status_code: int, detail: str = None) -> None:
if detail is None:
detail = "http.HTTPStatus(status_code).phrase"
self.status_code = status_code
self.detail = detail
async def not_found(self):
return JSONResponse(content=self.title, status_code=self.status_code)
class EmptyParamError(BaseError):
""" Error is raised when group name is not provided. """
status_code = 400
title = "Missing Group Name"
When the condition is true, i want to raise the exception but its not returning the jsonrespnse but its returning the stacktrace on the console.
Please let me know if anything is wrong here

adding try block resolved the issue
try:
if a==1:
raise InvalidUsage(100,"invalid this one")
if b == 0:
raise EmptyParamError("this is empty paramuvi")
except InvalidUsage as e:
return JSONResponse({'hello': str(e.message)})
except EmptyParamError as e:
return JSONResponse({'hello': str(e.message)})

Related

"delete_message" not working on sqs client under moto

I have a code like:
class SqsClientWrapper:
def __init__(self, sqs_client, queue_url):
self.sqs_client = sqs_client
self.queue_url = queue_url
def receive_message(self):
try:
while True:
response = self.sqs_client.receive_message(QueueUrl=self.queue_url, MaxNumberOfMessages=1)
if len(response.get("Messages", [])) > 0:
return response["Messages"][0]
except ClientError as e:
raise e
def delete_message(self, receipt_handle):
try:
response = self.sqs_client.delete_message(
QueueUrl=self.queue_url, ReceiptHandle=receipt_handle
)
except ClientError:
self.__logger.exception(
f"Could not delete the meessage from the - {self.__queue_url}."
)
raise
else:
return response
class Listener:
def listen(self, queue_url):
sqs_client = SqsClientWrapper(boto3.client("sqs"), queue_url)
while True:
try:
message = sqs_client.receive_message()
print(str(message))
sqs_client.delete_message(message["ReceiptHandle"])
except Exception as e:
continue
I'm trying to test the Listener using moto, I have the following test code:
logger = logging.getLogger()
class ListenerTest(unittest.TestCase):
def setUp(self) -> None:
self.executor = ThreadPoolExecutor()
self.futures = []
def tearDown(self) -> None:
for future in self.futures:
future.cancel()
self.executor.shutdown()
#mock_sqs
def test_simple(self):
sqs = boto3.resource("sqs")
queue = sqs.create_queue(QueueName="test-fake-queue")
queue_url = queue.url
listener = Listener()
self.futures.append(
self.executor.submit(listener.listen, queue_url)
)
sqs_client = boto3.client("sqs")
sqs_client.send_message(
QueueUrl=queue_url,
MessageBody=json.dumps({"id": "1234"}),
)
if __name__ == "__main__":
unittest.main()
When I run this, it seems to have received the message okay, but when deleting it from the queue it fails with the following error:
botocore.exceptions.ClientError: An error occurred (InvalidClientTokenId) when calling the DeleteMessage operation: The security token included in the request is invalid.
Anyone know what might be going on here? Thanks!

ERROR:root:Error in xyz There is no current event loop in thread 'Thread-7'

I am trying to achieve fire_and_forget functionality and here are the details.
Async decorater i am trying to use:
import asyncio
import time
def fire_and_forget(f):
def wrapped(*args, **kwargs):
return asyncio.get_event_loop().run_in_executor(None, f, *args, *kwargs)
return wrapped
My Async call using above decorator:
#fire_and_forget
def call_async(self, req, body, headers_params):
logger.info("Calling ASYNC")
try:
f = urllib.request.urlopen(req)
response = f.read()
f.close()
except Exception as e:
logger.exception("api exception %s" % e)
return None
# Parse and return the response
try:
res = self._parse_response(response)
except Exception as e:
logger.exception("Exception in parsing response of %s" % e)
res = None
logger.debug("clevertap response: {}".format(res))
My Flask app calling test_xyz which in turns fire the above fire and forget call_async:
from flask import Flask, jsonify, request
from call_xyz import test_xyz
app = Flask(__name__)
#app.route('/events_dm')
def events_dm():
session_id = request.args.get('sessionId', "11111111")
test_obj = test_xyz(session_id)
test_obj.track_test()
return jsonify({"success": True})
app.run(
host='0.0.0.0',
port=8091,
debug=True,
threaded=True
)
I am not able to understand where to set my event loop correctly so that i don't get the error: "Error in xyz There is no current event loop in thread 'Thread-7'" and my events get fired correctly.
Flask is not asyncio-compatible, so you shouldn't attempt to use asyncio within it.
Besides, you're not actually using asyncio's functionality, but run_in_executor which calls into concurrent.futures, i.e. uses threads under the hood. If that's what you need, you can create an executor directly and just submit your function to it. For example:
import concurrent.futures
_pool = concurrent.futures.ThreadPoolExecutor()
def fire_and_forget(f):
def wrapped(*args, **kwargs):
return _pool.submit(lambda: f(*args, **kwargs))
return wrapped
You must probably go through once asyncio usage and its main heart event loop understanding.
Similar issue which might help you to understand.
Here is the tutorial with some good explanation
Just give some flow for how use coroutine with normal Flask app here is the sample one.
import asyncio
import datetime
from flask import Flask, jsonify, request
app = Flask(__name__)
def print_now():
print(datetime.datetime.now())
async def keep_printing(name: str="") -> None:
print(name, end=" ")
print_now()
await asyncio.sleep(1.50)
async def main(num_times):
result = await asyncio.gather(
keep_printing("first"),
keep_printing("second"),
keep_printing("third"),
)
return result
def execute_statement():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(main(2))
loop.close()
#app.route('/events_dm')
def events_dm():
execute_statement()
return jsonify({"success": True})
app.run(
host='0.0.0.0',
port=8091,
debug=True,
threaded=True
)
Output when you hit /events_dm
first 2020-07-18 00:46:26.452921
second 2020-07-18 00:46:26.452921
third 2020-07-18 00:46:26.452921
127.0.0.1 - - [18/Jul/2020 00:46:27] "GET /events_dm HTTP/1.1" 200 -

Python3 <sqlite3.Row object at 0x10fcbb4b0> is not JSON serializable

Python3.7
I have the following GET endpoint to return the data in the database, but keeps getting
{
"code": 400,
"message": "Exception in _query: <sqlite3.Row object at 0x10fcbb4b0> is not JSON serializable"
}
Here is the code. I have been trying many different solutions but none of them works. Any thoughts?
Any way I can printout the sqlite3 data? When I do
print(entries)
I will return
as well. Any thoughts? Thank you!
# all the imports
import os
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, \
render_template, flash
from .response import Response
app = Flask(__name__) # create the application instance :)
app.config.from_object(__name__) # load config from this file , flaskr.py
import json
import requests
#app.route('/table_result', methods=['GET'])
def table_result():
try:
db = get_db()
cur = db.execute("SELECT name FROM mouse_tracking; ")
entries = cur.fetchall()
# return Response(200, json.dumps(entries)).payload()
return json.dumps(entries)
except sqlite3.Error as e:
return Response(400, "Database error: %s" % e).payload()
except Exception as e:
return Response(400, "Exception in _query: %s" % e).payload()
(i cant comment yet) did you use cursor?
def table():
try:
db = sqlite3.connect('db.db')
cursor = db.cursor()
cursor.execute("SELECT name FROM db")
entries = cursor.fetchall()
return jsonify(json.dumps(entries))
except Exception as e:
return Response(400, "Exception: %s" % e).payload()
you should use db.cursor() to execute commands on the database

Mock exception raised in function using Pytest

I have the following function and it is a generic function which will make API call based on the input hostname and data. It will construct http request to make API and will return the response. This function will throw four types of exception(invalid URL, timeout, auth error and status check). How can I Mcok and Test the exception raised in API call using pytest? Which will be the best method to test the exceptions raised from API call?
import ssl
import urllib
import urllib.request
import urllib.error
import xml
import xml.etree.ElementTree as ET
def call_api(hostname, data):
'''Function to make API call
'''
# Todo:
# Context to separate function?
# check response for status codes and return reponse.read() if success
# Else throw exception and catch it in calling function
error_codes = {
"1": "Unknown command",
"6": "Bad Xpath",
"7": "Object not present",
"8": "Object not unique"
}
url = "http://" + hostname + "/api"
encoded_data = urllib.parse.urlencode(data).encode('utf-8')
try:
response = urllib.request.urlopen(url, data=encoded_data,
timeout=10).read()
root = ET.fromstring(response)
if root.attrib.get('status') != "success":
Errorcode = root.attrib.get('code')
raise Exception(pan_error_codes.get(Errorcode, "UnknownError"),
response)
else:
return response
except urllib.error.HTTPError as e:
raise Exception(f"HttpError: {e.code} {e.reason} at {e.url}", None)
except urllib.error.URLError as e:
raise Exception(f"Urlerror: {e.reason}", None)
If i call this function
def create_key(hostname, username, password):
hostname = 'myhost ip'
data = {
'type': 'keygen',
'username': username,
'password': password
}
username = 'myuser'
password = 'password'
response = call_api(hostname, data)
return response
i will get a response like following
b"<response status = 'success'><result><key>mykey</key></result></response>"
You can mock error raising via side_effect parameter:
Alternatively side_effect can be an exception class or instance. In this case the exception will be raised when the mock is called.
In your case, this can be used like this (assuming call_api is defined in module foo):
import pytest
from unittest.mock import patch
def test_api():
with patch('foo.call_api', side_effect=Exception('mocked error')):
with pytest.raises(Exception) as excinfo:
create_key('localhost:8080', 'spam', 'eggs')
assert excinfo.value.message == 'mocked error'

'Connection' object is not callable while using sqlalchemy in python

I am getting
Connection' object is not callable
error while executing my python code in which I am using sqlalchemy package.
Code which is not working
import sys
import pymysql
import sqlalchemy.pool as pool
from init import db_config
DEBUG="True"
def _get_connection(**kwargs):
try:
return pymysql.Connection(**kwargs);
except pymysql.OperationalError as e:
if DEBUG=="True": print("Exception catched %s" %e.message)
return None
def connect_db(kwargs=db_config):
try:
conn = _get_connection(**kwargs)
if not conn == None:
mypool = pool.QueuePool(conn, max_overflow=1, pool_size=1)
print("====Type of pool", type(mypool))
local_conn = mypool.connect()
print("LocalConn object given: ", local_conn)
return local_conn
else:
print("conn is None")
except TypeError as e:
if DEBUG=="True": print("Exception catched during queue pooling:", e)
return None
def disconnect_db(dbh):
dbh.close()
def fetch_rows(query):
query = str(query)
if not query:
LOGGER
if DEBUG=="True": print("Input query is empty")
return None
rows=[]
local_conn = connect_db();
if not local_conn == None:
try:
print("fetch_rows.local_conn:", local_conn);
with local_conn.cursor() as cursor:
cursor.execute(query);
rows = cursor.fetchall();
except pymysql.OperationalError as e:
if DEBUG=="True": print("FetchRows excep:", e)
finally:
disconnect_db(local_conn)
else:
print("fetch_rows.local_conn is None");
return rows
Output:
Exception catched during queue pooling: 'Connection' object is not callable
fetch_rows.local_conn is None

Resources