unittest on flask_restful app does not work - stuck on flask server running - unit-testing

My tools: Python 3.5.0, flask 1.0.2, mac osx
My problem:
I have a very simple RESTful app with two endpoints that are working. I wrote two very simple unit tests, via unittest, and they are not proceeding for a reason that I'm not sure of right now. The tests succeed if I do the following:
If I run the server separately, say on http://127.0.0.1:8015/, (and not setUp() anything)
And run the tests such that they call requests.get(http://127.0.0.1:8015/employee/3)
the tests run just fine and they pass
The tests just hang if I run the tests with the setUp(self) definition below:
Serving Flask app "testing" (lazy loading)
Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
Debug mode: off
Running on http://127.0.0.1:8015/ (Press CTRL+C to quit)
And here is the pertinent code
def setUp(self):
self.app = Flask("testing")
self.app.testing = True
self.client = self.app.test_client()
self.EmployeeId = 4
with self.app.app_context():
db_connect = create_engine('sqlite:///some.db')
self.api = Api(self.app)
self.api.add_resource(server.Car, '/car/<employee_id>') # Route_4
app.run(port=8015, debug=False)
def test_api_can_get_employee_by_id(self):
res = requests.get(url = 'http://127.0.0.1:8015/car/{}'.format(self.EmployeeId))
data = res.json()
self.assertEqual(res.status_code, 200)
self.assertIn('mazda', data["data"][0]['make_model'])
I've looked online and found no resource that really covers my question. The set up of the server works during the testing but the unit tests are not executed. How would you recommend troubleshooting this? I'm open to all suggestions including changing the approach. Thank you!

For those of you stumbling here after Googling "Unit tests stuck on Running on with Flask":
It's possible that your code always starts the Flask server, regardless of how your module was loaded. If that's the case, even the unit tests will start the server, which will indefinitively listens for connections as expected.
Eg, this will get stuck:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return "Hello World!"
app.run()
Instead, you'll need to start the Flask server only if your module is the main program:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run()
More info on the "name == 'main'" block here.
Regarding the original question, this answer does not solves it. To do something like that you would need to start the Flask server, but in a non-blocking way such as another thread or process. There's many ways to do this and without any additional info, the question is just too vague to answer as is.

Related

Flask - converting python execution to flask run

I developed my first flask application that is currently running and everything work fine. The application is loaded using "python application.py" or using gUnicorn. There is no fancy fancy folder structure everything is in the same folder, with exception of the static\ and templates\
Folder Structure:
- application\hello.py
- application\static\
- application\templates\
To Run:
- python hello.py
#hello.py
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', load_dotenv=True, debug=True, threaded=True)
Now that looking to add more functionalities to the application noticed most tutorials uses "flask run" to launch the instead. There are two different tutorials I am following one using blueprints and the other one is the microblog tutorial both using similar folder structure:
- application\run.py
- application\app\main.py
- application\app\static\
- application\app\templates\
To run:
- export Flask_APP=run.py
- flask run
The application will continue to grow and I want to follow best practices.
Question 1:
How do I enable the following parameters when using "flask run"??:
if __name__ == '__main__':
app.run(host='0.0.0.0', load_dotenv=True, debug=True, threaded=True)
Question 2:
Is there any pro/cons configuring the app to run using flask run vs python app.py????? There was another post with this title but context was unrelated.
When can I read more about this??
Threaded mode is enabled by default. You don't have to pass it in. Source
For debug mode, use export FLASK_DEBUG=1. Source
For load_dotenv use export FLASK_SKIP_DOTENV=0 Source
For specifying port use export FLASK_RUN_PORT=8000. Source
To bind the app to 0.0.0.0, set SERVER_NAME config like app.config['SERVER_NAME']. Source
Also see:
http://flask.pocoo.org/docs/1.0/cli/#setting-command-options

How to fix internal server error in Flask application using elastic beanstalk and aws

When I run my flask application locally, I can connect to MySQL RDS just fine. However, when I try to deploy the app using Elastic Beanstalk, I get a "500 Internal Server Error".
I do not know if this helps or not, but when I use a local sqlite file, my application works as intended both when ran locally and when deployed with Elastic Beanstalk.
I did try and work along with this page, but I did not notice any difference when I included the environment properties. https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-rds.html#python-rds-create
Here is my __init__.py file. I just comment out whichever database URI I do not wish to use when testing.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
application = Flask(__name__)
application.config['SECRET_KEY'] = 'c4633b5a978d282104dbc44c32c9486'
application.config['SQLALCHEMY_DATABASE_URI'] =
'mysql+pymysql://<username>:<password>#garbagero.cuz5hqf0nh5m.us-east-
2.rds.amazonaws.com/ebdb'
#application.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(application)
bcrypt = Bcrypt(application)
login_manager = LoginManager(application)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
from garbageRO import routes
EDIT: I finally figured out that I accidentally left 1 package out of my requirements.txt file. I thought I had already double checked this before posting but apparently I did not.
I do recommend that you debug your application using the verbose mode of Flask and SQLAlchemy, so you can better know whats going on, with this level or detail i can only suggest something to check like the permissions/IAM on AWS, to check if your ElasticBeanstalk can really access the RDS, im assuming the ELB/applcation use a set of credentials, and you tested locally with another credentials, right?
About the "verbose mode", try setting the SQLALCHEMY_ECHO to True: http://flask-sqlalchemy.pocoo.org/2.3/config/
There's also this option ive not tested: https://github.com/pallets/flask-sqlalchemy/pull/208/files?short_path=fd40cf2
And on the Flask app you can set debug to True also.
Another option, is to debug if you can connect on the RDS directly with a client on the machine/container, or a least if a telnet is working.

Where to put logging setup code in a flask app?

I'm writing my first Flask application. The application itself runs fine. I just have a newbie question about logging in production mode.
The basic structure:
app/
app/templates/
app/static
config.py
flask/... <- virtual env with flask + extensions
run.py
The application is started by run.py script:
#!flask/bin/python
import os.path
import sys
appdir = os.path.dirname(os.path.abspath(__file__))
if appdir not in sys.path:
sys.path.insert(1, appdir)
from app import app as application
if __name__ == '__main__':
application.run(debug=True)
and is started either directly or from an Apache 2.4 web server. I have these lines in the apache config:
WSGIPythonHome /usr/local/opt/app1/flask
WSGIScriptAlias /app1 /usr/local/opt/app1/run.py
In the former case, the debug=True is all I need for the development.
I'd like to have some logging also for the latter case, i.e. when running under Apache on a production server. Following is a recommendation from the Flask docs:
if not app.debug:
import logging
from themodule import TheHandlerYouWant
file_handler = TheHandlerYouWant(...)
file_handler.setLevel(logging.WARNING)
app.logger.addHandler(file_handler)
It needs some customization, but that's what I want - instructions for the case when app.debug flag is not set. Similar recommendation was given also here:
How do I write Flask's excellent debug log message to a file in production?
Please help: where do I have to put this code?
UPDATE: based on the comments by davidism and the first answer I've got I think the app in the current simple form is not suitable for what I was asking for. I will modify it to use different sets of configuration data as recommended here: http://flask.pocoo.org/docs/0.10/config/#development-production . If my application were larger, I would follow the pech0rin's answer.
UPDATE2: I think the key here is that the environment variables should control how the application is to be configured.
I have had a lot of success with setting up my logging configurations inside a create_app function. This uses the application factory pattern. This allows you to pass in some arguments or a configuration class. The application is then specifically created using your parameters.
This allows you initialize the application, setup logging, and do whatever else you want to do, before the application is sent back to be run.
For example:
def create_app(dev=False):
app = Flask(__name__)
if dev:
app.config['DEBUG'] = True
else:
...
app.logger.addHandler(file_handler)
return app
This has worked very well for me in production environments. YMMV

Viewing a Flask app in the Cloud9 Test Browser

I'm creating a web app based on Miguel Grinberg's Flasky app (from his book Flask Web Development).
When running manage.py runserver in the Cloud9 IDE, the command line tells me that it is running at http://127.0.0.1:5000/. However, when I type this IP address into the Cloud9 test browser, I see nothing. https://[workspace]-[username].c9users.io (with or without :5000) doesn't work either.
Here's my manage.py code:
from app import create_app
from flask.ext.script import Manager, Shell
app = create_app('default')
manager = Manager(app)
if __name__ == '__main__':
manager.run()
This video https://www.youtube.com/watch?v=MI8YIRDeGzU by Chris Lynch outlines the flask configuration settings you need for the Cloud9 browser at around the 7 minute mark. In order to start server hit the green run button near the top of the page to the right of the preview button.
#Insert the line below to to run on Cloud9
app.run(host=os.getenv('IP', '0.0.0.0'), port=int(os.getenv('PORT', 8080)))
#end insert, place above __name__ == __main__
if __name__ == '__main__':
app.run()
app.debug(True)

django project with twisted and run as "Daemon"

Last two day I'm trying to find a way to run a working django project under twisted. After detailed searching I found several methods to configure it. But most of them are deal with how to run the app via command line not as a daemon.I want to run the django project as daemon.
I tried following links to implement this,
Twisted: Creating a ThreadPool and then daemonizing leads to uninformative hangs
http://www.robgolding.com/blog/2011/02/05/django-on-twistd-web-wsgi-issue-workaround/
But this also not working for me.By this method TCP server is not even listen to the given port.
Please help me to figure it out.
UPDATE
I'm sorry for the missing informations.Here is my objectives.
I'm beginner in twisted world, so first I'm trying to get my working django project configured under twisted,currently its working well on django testing server or apache via mod_wsgi.
To configure it with twisted I used the biding code given below, that code is a combination of two sample's found in the links that I given in the first post.
So in-order to integrate django app with twisted I used the following code, file name: "server.py".
import sys
import os
from twisted.application import internet, service
from twisted.web import server, resource, wsgi, static
from twisted.python import threadpool
from twisted.internet import reactor
from django.conf import settings
import twresource # This file hold implementation of "Class Root".
class ThreadPoolService(service.Service):
def __init__(self, pool):
self.pool = pool
def startService(self):
service.Service.startService(self)
self.pool.start()
def stopService(self):
service.Service.stopService(self)
self.pool.stop()
class Root(resource.Resource):
def __init__(self, wsgi_resource):
resource.Resource.__init__(self)
self.wsgi_resource = wsgi_resource
def getChild(self, path, request):
path0 = request.prepath.pop(0)
request.postpath.insert(0, path0)
return self.wsgi_resource
PORT = 8080
# Environment setup for your Django project files:
#insert it to first so our project will get first priority.
sys.path.insert(0,"django_project")
sys.path.insert(0,".")
os.environ['DJANGO_SETTINGS_MODULE'] = 'django_project.settings'
from django.core.handlers.wsgi import WSGIHandler
def wsgi_resource():
pool = threadpool.ThreadPool()
pool.start()
# Allow Ctrl-C to get you out cleanly:
reactor.addSystemEventTrigger('after', 'shutdown', pool.stop)
wsgi_resource = wsgi.WSGIResource(reactor, pool, WSGIHandler())
return wsgi_resource
# Twisted Application Framework setup:
application = service.Application('twisted-django')
# WSGI container for Django, combine it with twisted.web.Resource:
# XXX this is the only 'ugly' part: see the 'getChild' method in twresource.Root
wsgi_root = wsgi_resource()
root = Root(wsgi_root)
#multi = service.MultiService()
#pool = threadpool.ThreadPool()
#tps = ThreadPoolService(pool)
#tps.setServiceParent(multi)
#resource = wsgi.WSGIResource(reactor, tps.pool, WSGIHandler())
#root = twresource.Root(resource)
#Admin Site media files
#staticrsrc = static.File(os.path.join(os.path.abspath("."), "/usr/haridas/eclipse_workplace/skgargpms/django/contrib/admin/media/"))
#root.putChild("admin/media", staticrsrc)
# Serve it up:
main_site = server.Site(root)
#internet.TCPServer(PORT, main_site).setServiceParent(multi)
internet.TCPServer(PORT, main_site).setServiceParent(application)
#EOF.
Using above code It worked well from command line using "twisted -ny server.py", but when we run it as daemon "twisted -y server.py" it will hang, but the app is listening to the port 8080. I can access it using telnet.
I found some fixes for this hanging issue from stackoverflow itself. It helped me to use the code sections given below, which is commented in the above server.py file.
multi = service.MultiService()
pool = threadpool.ThreadPool()
tps = ThreadPoolService(pool)
tps.setServiceParent(multi)
resource = wsgi.WSGIResource(reactor, tps.pool, WSGIHandler())
root = twresource.Root(resource)
and :-
internet.TCPServer(PORT, main_site).setServiceParent(multi)
instead of using the:-
wsgi_root = wsgi_resource()
root = Root(wsgi_root)
and :-
internet.TCPServer(PORT, main_site).setServiceParent(application)
The modified method also didn't helped me to avoid the hanging issue.Is any body out there who successfully run the django apps under twisted daemon mode?.
I maid any mistakes while combining these codes?, Currently I'm only started to learn the twisted architectures in detail. Please help me to solve this problem
Thanks and Regards,
Haridas N.
Note:- Im looking for the Twisted Application configuration (TAC) file, which integrate django app with twisted and run with out any problem in the daemon mode also.
Thank you,
Haridas N.
twistd is the Twisted Daemonizer. Anything you run with twistd will be easy to daemonize. All you have to do is not pass the --nodaemon option.
As far as why your code is "not working", you need to provide more details about what you did, what you expected to happen, and how what actually happened differed from your expectations. Otherwise, only a magician can answer your question.
Since you said the TCP port doesn't even get set up, the only guess I can think of is that you're trying to listen on a privileged port (such as 80) without having permissions to do so (ie, you're not root and you're not using authbind or something similar).