Python-Socketio client not working in flask current_app context - flask

I am using python-socketio client to define events that will manipulate the database once triggered but i am getting the "Working outside app context" error.
#socketio.event
def my_event(data):
id = data["id"]
user = User.query.get(id)
print("Debug Text")
File "/home/allan/Documents/proj/Onsite/proj_backend/proj/websocket/routes.py", line 20, in complete_online_booking
user = User.query.get(id)
^^^^^^^^^^^^^^^^^^^^
File "/home/allan/Documents/proj/Onsite/proj_backend/venv/lib/python3.11/site-packages/flask_sqlalchemy/__init__.py", line 552, in __get__
return type.query_class(mapper, session=self.sa.session())
^^^^^^^^^^^^^^^^^
File "/home/allan/Documents/proj/Onsite/proj_backend/venv/lib/python3.11/site-packages/sqlalchemy/orm/scoping.py", line 47, in __call__
sess = self.registry()
^^^^^^^^^^^^^^^
File "/home/allan/Documents/proj/Onsite/proj_backend/venv/lib/python3.11/site-packages/sqlalchemy/util/_collections.py", line 1010, in __call__
return self.registry.setdefault(key, self.createfunc())
^^^^^^^^^^^^^^^^^
File "/home/allan/Documents/proj/Onsite/proj_backend/venv/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 4274, in __call__
return self.class_(**local_kw)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/allan/Documents/proj/Onsite/proj_backend/venv/lib/python3.11/site-packages/flask_sqlalchemy/__init__.py", line 174, in __init__
self.app = app = db.get_app()
^^^^^^^^^^^^
File "/home/allan/Documents/proj/Onsite/proj_backend/venv/lib/python3.11/site-packages/flask_sqlalchemy/__init__.py", line 1042, in get_app
raise RuntimeError(
RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/

Related

error serializaing GAE session with webapp2_extras

I am not new to App Engine, but am just getting started with the Python stack on it. I am using webapp2 and Cygwin with its own Python. I am trying to implement custom authentication, relying on sessions.. I am following numerous examples of enabling sessions using webapp2-extras module. I have the following relevant code:
import webapp2
from webapp2_extras import sessions
class BaseHandler(webapp2.RequestHandler):
def dispatch(self):
self.session_store = sessions.get_store(request=self.request)
try:
webapp2.RequestHandler.dispatch(self)
finally:
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def session(self):
return self.session_store.get_session(self.response, backend='datastore')
class CounterHandler(BaseHandler):
def get(self):
cnt_key = 'cnt'
if cnt_key in self.session:
cnt = int(self.session[cnt_key])
else:
cnt = 0
cnt += 1
self.session[cnt_key] = str(cnt)
self.response.headers['Content-Type'] = 'text/plain'
self.response.write("Hello, world!")
This fails with the following stack trace:
Traceback (most recent call last):
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/cygdrive/c/Documents and Settings/dev/My Documents/proj/easytime_gae/src/handlers.py", line 11, in dispatch
self.session_store.save_sessions(self.response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 420, in save_sessions
session.save_session(response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/appengine/sessions_ndb.py", line 117, in save_session
response, self.name, {'_sid': self.sid}, **self.session_args)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 423, in save_secure_cookie
value = self.serializer.serialize(name, value)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/securecookie.py", line 48, in serialize
signature = self._get_signature(name, value, timestamp)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/securecookie.py", line 103, in _get_signature
signature.update('|'.join(parts))
TypeError: sequence item 0: expected string, Response found
The error goes away if I disable the line that writes to the session object and leave reading from sessions intact:
# self.session[cnt_key] = str(cnt)
Any help would be much appreciated.
The first argument to get_session is the name, if you want to change from the default. You are passing a response object, which is wrong.
#webapp2.cached_property
def session(self):
return self.session_store.get_session(backend='datastore')

PyMySql + SQLAlchemy on Flask: create_all fails

I am starting a brand new project that involves Flask + SQLAlchemy with pymysql. Currently, creation of tables based on model fails with the following:
The lines in my code (main.py) leading up to the error are:
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://myapp:myapp#localhost/myapp'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
guid = db.Column(db.String(255), unique=True)
def __init__(self):
self.guid = str(uuid.uuid1())
db.create_all()
# Note: We don't need to call run() since our application is embedded within
# the App Engine WSGI application server.
#app.route('/')
def hello():
"""Return a friendly HTTP greeting."""
return 'Hello World!'
#app.errorhandler(404)
def page_not_found(e):
"""Return a custom 404 error."""
return 'Sorry, nothing at this URL.', 404
Traceback (most recent call last):
File "/Users/myuserid/Documents/Development/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 240, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/Users/myuserid/Documents/Development/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 299, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "/Users/myuserid/Documents/Development/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 85, in LoadObject
obj = __import__(path[0])
File "/Users/myuserid/Documents/Development/myapp-server/main.py", line 9, in <module>
db.create_all()
File "/Users/myuserid/Documents/Development/myapp-server/lib/flask_sqlalchemy/__init__.py", line 895, in create_all
self._execute_for_all_tables(app, bind, 'create_all')
File "/Users/myuserid/Documents/Development/myapp-server/lib/flask_sqlalchemy/__init__.py", line 887, in _execute_for_all_tables
op(bind=self.get_engine(app, bind), **extra)
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/sql/schema.py", line 3614, in create_all
tables=tables)
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/engine/base.py", line 1850, in _run_visitor
with self._optional_conn_ctx_manager(connection) as conn:
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/engine/base.py", line 1843, in _optional_conn_ctx_manager
with self.contextual_connect() as conn:
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/engine/base.py", line 2034, in contextual_connect
self._wrap_pool_connect(self.pool.connect, None),
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/engine/base.py", line 2069, in _wrap_pool_connect
return fn()
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/pool.py", line 376, in connect
return _ConnectionFairy._checkout(self)
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/pool.py", line 708, in _checkout
fairy = _ConnectionRecord.checkout(pool)
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/pool.py", line 480, in checkout
rec = pool._do_get()
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/pool.py", line 1049, in _do_get
self._dec_overflow()
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/util/langhelpers.py", line 60, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/pool.py", line 1046, in _do_get
return self._create_connection()
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/pool.py", line 323, in _create_connection
return _ConnectionRecord(self)
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/pool.py", line 449, in __init__
self.connection = self.__connect()
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/pool.py", line 602, in __connect
connection = self.__pool._invoke_creator(self)
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/engine/strategies.py", line 97, in connect
return dialect.connect(*cargs, **cparams)
File "/Users/myuserid/Documents/Development/myapp-server/lib/sqlalchemy/engine/default.py", line 377, in connect
return self.dbapi.connect(*cargs, **cparams)
File "/Users/myuserid/Documents/Development/myapp-server/lib/pymysql/__init__.py", line 88, in Connect
return Connection(*args, **kwargs)
File "/Users/myuserid/Documents/Development/myapp-server/lib/pymysql/connections.py", line 644, in __init__
self._connect()
File "/Users/myuserid/Documents/Development/myapp-server/lib/pymysql/connections.py", line 837, in _connect
self._get_server_information()
File "/Users/myuserid/Documents/Development/myapp-server/lib/pymysql/connections.py", line 1048, in _get_server_information
packet = self._read_packet()
File "/Users/myuserid/Documents/Development/myapp-server/lib/pymysql/connections.py", line 882, in _read_packet
packet_header = self._read_bytes(4)
File "/Users/myuserid/Documents/Development/myapp-server/lib/pymysql/connections.py", line 899, in _read_bytes
data = self._rfile.read(num_bytes)
File "/Users/myuserid/Documents/Development/myapp-server/lib/pymysql/_socketio.py", line 64, in readinto
n = e.args[0]
IndexError: tuple index out of range
INFO 2015-05-05 23:30:40,803 module.py:788] default: "GET / HTTP/1.1" 500 -

Attribute error for list of objects from collection?

We're using Flask-Restful for implementing an API. As database we use MongoDB and MongoEngine as ODM. To get MongoEngine to work with Restful, we followed this blog article. For getting the correct json-format we using the builtin marsheling-methods. This works perfectly for single objects (e.g. one item of a collection), but when marsheling a list of objects (e.g. all items of a collection), an AttributeError is raised (although we use the same syntax as for single objects). This is how our model and our views look like (I don't paste the routes, as they are in a separate file and work).
model:
class Task(db.Document):
name = db.StringField()
description_mini = db.StringField()
views:
parser = reqparse.RequestParser()
parser.add_argument('task_id', type=str)
task_format = {
"name": fields.String,
"description_mini": fields.String
}
class TasksView(Resource):
#marshal_with(task_format)
def get(self):
tasks = Task.objects().all()
return tasks, 200
class TaskDetailView(Resource):
#marshal_with(task_format)
def get(self):
args = parser.parse_args()
startup_id = args['task_id']
task = Task.objects(id=task_id).first()
return task, 200
full stacktrace:
AttributeError
Traceback (most recent call last)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 257, in error_router
return self.handle_error(e)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 257, in error_router
return self.handle_error(e)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 397, in wrapper
resp = resource(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask/views.py", line 84, in view
return self.dispatch_request(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 487, in dispatch_request
resp = meth(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 562, in wrapper
return marshal(data, self.fields), code, headers
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 533, in marshal
return OrderedDict(items)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 52, in __init__
self.__update(*args, **kwds)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_abcoll.py", line 547, in update
for key, value in other:
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 532, in <genexpr>
for k, v in fields.items())
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 104, in output
value = get_value(key if self.attribute is None else self.attribute, obj)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 37, in get_value
return _get_value_for_keys(key.split('.'), obj, default)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 42, in _get_value_for_keys
return _get_value_for_key(keys[0], obj, default)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 51, in _get_value_for_key
return obj[key]
File "/project/venv/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 152, in __getitem__
raise AttributeError
AttributeError
When you want to marshal a list you have to define the fields as a list as well.
I think this will work:
task_list_format = {
'tasks': fields.List(fields.Nested(task_format))
}
class TasksView(Resource):
#marshal_with(task_list_format)
def get(self):
tasks = Task.objects().all()
return { 'tasks': tasks }, 200
I believe it is not possible to return a plain list using the marshaling support in Flask-RESTful, it always expects a dictionary. For that reason I put the list under a "tasks" key.
I hope this helps.
From what I understand, the problem is that mongoengine's Queryset object lazily queries the database and that Flask-restful/restplus marshalling expects a list.
I could make it work with
task_format = {
"name": fields.String,
"description_mini": fields.String
}
class TasksView(Resource):
#marshal_with(task_format)
def get(self):
tasks = Task.objects().all()
return list(tasks)
try flask_restful.marshal_with_fields:
>>> from flask_restful import marshal_with_field, fields
>>> #marshal_with_field(fields.List(fields.Integer))
... def get():
... return ['1', 2, 3.0]
...
>>> get()
[1, 2, 3]

adding admin interface to existing pyramid app

I'm trying to add a nice admin interface to an existing Pyramid project. I created a test project using pcreate -s alchemy -s pyramid_fa fa_test and then copied all the extra files created into my project and altered them to be suitable.
Everything looks to be good and dandy until I try to add a formalchemy route:
config.formalchemy_model("/foo", package='bar',
model='bar.models.specific_models.Thingy',
**settings)
Then I get: ImportError: No module named forms
My question is: How do I fix this? Or what is the correct way to add an admin interface?
I've googled around a bunch to no avail...
Here's relevant code:
fainit.py:
from bar import models, faforms
import logging
def includeme(config):
config.include('pyramid_formalchemy')
config.include('bar.fainit')
config.include('fa.jquery')
config.include('pyramid_fanstatic')
model_view = 'fa.jquery.pyramid.ModelView'
session_factory = 'bar.models.access.DBSession'
## register session and model_view for later use
settings = {'package': 'bar',
'view': model_view,
'session_factory': session_factory,
}
config.registry.settings['bar.fa_config'] = settings
config.formalchemy_admin("/admin", models=models, forms=faforms,
**settings)
# Adding the package specific routes
config.include('shop.faroutes')
log.info('formalchemy_admin registered at /admin')
faroutes.py
from bar import models
import logging
log = logging.getLogger(__name__)
def includeme(config):
settings = config.registry.settings.get('shop.fa_settings}}', {})
config.formalchemy_model("/alerts", package='shop',
model='shop.models.super_models.Alert',
**settings)
log.info('shop.faroutes loaded')
And the traceback:
Starting subprocess with file monitor
Traceback (most recent call last):
File "../bin/pserve", line 9, in <module>
load_entry_point('pyramid==1.5a1', 'console_scripts', 'pserve')()
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/scripts/pserve.py", line 51, in main
return command.run()
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/scripts/pserve.py", line 316, in run
global_conf=vars)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/scripts/pserve.py", line 340, in loadapp
return loadapp(app_spec, name=name, relative_to=relative_to, **kw)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/PasteDeploy-1.5.0-py2.7.egg/paste/deploy/loadwsgi.py", line 247, in loadapp
return loadobj(APP, uri, name=name, **kw)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/PasteDeploy-1.5.0-py2.7.egg/paste/deploy/loadwsgi.py", line 272, in loadobj
return context.create()
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/PasteDeploy-1.5.0-py2.7.egg/paste/deploy/loadwsgi.py", line 710, in create
return self.object_type.invoke(self)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/PasteDeploy-1.5.0-py2.7.egg/paste/deploy/loadwsgi.py", line 146, in invoke
return fix_call(context.object, context.global_conf, **context.local_conf)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/PasteDeploy-1.5.0-py2.7.egg/paste/deploy/util.py", line 56, in fix_call
val = callable(*args, **kw)
File "/home/sheena/WORK/tv_guys_env/shop/shop/__init__.py", line 30, in main
includeme(config)
File "/home/sheena/WORK/tv_guys_env/shop/shop/fainit.py", line 8, in includeme
config.include('shop.fainit')
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/config/__init__.py", line 778, in include
c(configurator)
File "/home/sheena/WORK/tv_guys_env/shop/shop/fainit.py", line 24, in includeme
config.include('shop.faroutes')
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/config/__init__.py", line 778, in include
c(configurator)
File "/home/sheena/WORK/tv_guys_env/shop/shop/faroutes.py", line 12, in includeme
**settings)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/util.py", line 507, in wrapper
result = wrapped(self, *arg, **kw)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid_formalchemy-0.4.4-py2.7.egg/pyramid_formalchemy/__init__.py", line 58, in formalchemy_model
view=view, models=[model], model=model, **kwargs)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid_formalchemy-0.4.4-py2.7.egg/pyramid_formalchemy/__init__.py", line 85, in formalchemy_admin
forms = config.maybe_dotted('%s.forms' % package)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/config/__init__.py", line 848, in maybe_dotted
return self.name_resolver.maybe_resolve(dotted)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/path.py", line 316, in maybe_resolve
return self._resolve(dotted, package)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/path.py", line 323, in _resolve
return self._zope_dottedname_style(dotted, package)
File "/home/sheena/WORK/tv_guys_env/local/lib/python2.7/site-packages/pyramid-1.5a1-py2.7.egg/pyramid/path.py", line 372, in _zope_dottedname_style
__import__(used)
ImportError: No module named forms
It sounds like it's looking for you to create a forms module at shop.faroutes.forms.

RabbitMQ RPC call works in real life, but doesn't work in tests

I have Flask application and implemented RPC in it.
engine.py
import pickle
import pika
from databasyfacade.rpc import api
__author__ = 'Marboni'
def on_request(ch, method, props, body):
request = pickle.loads(body)
func = getattr(api, request['func'])
try:
result = func(*request['args'])
except Exception, e:
response = {
'status': 'ERROR',
'error': e
}
else:
response = {
'status': 'OK',
'result': result
}
ch.basic_publish(exchange='',
routing_key=props.reply_to,
properties=pika.BasicProperties(
correlation_id=props.correlation_id
),
body=pickle.dumps(response)
)
ch.basic_ack(delivery_tag=method.delivery_tag)
def init(host):
connection = pika.BlockingConnection(pika.ConnectionParameters(host))
channel = connection.channel()
channel.queue_declare(queue='facade_rpc')
channel.basic_qos(prefetch_count=1)
channel.basic_consume(on_request, queue='facade_rpc')
api.py
from databasyfacade.services import profiles_service
__author__ = 'Marboni'
def profile(user_id):
return profiles_service.profile(user_id)
When Flask application initializes, it runs method init(host).
Now I need to test how my application responses to RPC calls. So I wrote following RPC client:
client.py
import pickle
import uuid
import pika
__author__ = 'Marboni'
class RpcClient(object):
def __init__(self, host):
self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=host))
self.channel = self.connection.channel()
result = self.channel.queue_declare(exclusive=True)
self.callback_queue = result.method.queue
self.channel.basic_consume(self.on_response, no_ack=True, queue=self.callback_queue)
def on_response(self, ch, method, props, body):
if self.corr_id == props.correlation_id:
self.response = body
def call(self, func, *args):
request = {
'func': func,
'args': args
}
self.response = None
self.corr_id = str(uuid.uuid4())
self.channel.basic_publish(exchange='',
routing_key='facade_rpc',
properties=pika.BasicProperties(
reply_to = self.callback_queue,
correlation_id = self.corr_id,
),
body=pickle.dumps(request))
while self.response is None:
self.connection.process_data_events()
response = pickle.loads(self.response)
if response['status'] == 'ERROR':
e = response['error']
raise e
else:
return response['result']
Then I wrote test based on Flask-Testing framework. It initializes Flask application between each test method, so we can interact with it.
tests.py
from databasyfacade.rpc import RpcClient
from databasyfacade.testing import DatabasyTest, fixtures
from databasyfacade.testing.testdata import UserData, ProfileData
__author__ = 'Marboni'
class RpcTest(DatabasyTest):
#fixtures(UserData, ProfileData)
def test_profile(self, data):
rpc = RpcClient(self.app.config['RABBITMQ_HOST'])
profile = rpc.call('profile', ProfileData.hero.user_id)
self.assertIsNotNone(profile)
self.assertEqual(ProfileData.hero.email, profile.email)
This test hangs when makes call. It iterates infinitely here:
From client.py
while self.response is None:
self.connection.process_data_events()
It means that on_response() method on client never called.
If I interrupt my tests with CTRL-C, I will see following stacktrace:
Traceback (most recent call last):
File "../env/bin/nosetests", line 8, in <module>
load_entry_point('nose==1.3.0', 'console_scripts', 'nosetests')()
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/core.py", line 118, in __init__
**extra_args)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/main.py", line 95, in __init__
self.runTests()
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/core.py", line 197, in runTests
result = self.testRunner.run(self.test)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/core.py", line 61, in run
test(result)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 176, in __call__
return self.run(*arg, **kw)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 223, in run
test(orig)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/suite.py", line 65, in __call__
return self.run(*args, **kwds)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 74, in run
test(result)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 176, in __call__
return self.run(*arg, **kw)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 223, in run
test(orig)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 176, in __call__
return self.run(*arg, **kw)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 223, in run
test(orig)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 176, in __call__
return self.run(*arg, **kw)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 223, in run
test(orig)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 176, in __call__
return self.run(*arg, **kw)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 223, in run
test(orig)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 176, in __call__
return self.run(*arg, **kw)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/suite.py", line 223, in run
test(orig)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/case.py", line 45, in __call__
return self.run(*arg, **kwarg)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/case.py", line 133, in run
self.runTest(result)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/nose/case.py", line 151, in runTest
test(result)
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/flask_testing.py", line 72, in __call__
self._pre_setup()
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/flask_testing.py", line 80, in _pre_setup
self.app = self.create_app()
File "/Users/Marboni/Projects/Databasy/databasy-facade/databasyfacade/databasyfacade/testing/__init__.py", line 12, in create_app
return app.create_app()
File "/Users/Marboni/Projects/Databasy/databasy-facade/databasyfacade/databasyfacade/app.py", line 75, in create_app
init_rpc(app)
File "/Users/Marboni/Projects/Databasy/databasy-facade/databasyfacade/databasyfacade/app.py", line 63, in init_rpc
rpc.init(app.config['RABBITMQ_HOST'])
File "/Users/Marboni/Projects/Databasy/databasy-facade/databasyfacade/databasyfacade/rpc/engine.py", line 39, in init
channel.basic_consume(on_request, queue='facade_rpc')
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/pika/channel.py", line 220, in basic_consume
{'consumer_tag': consumer_tag})])
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/pika/adapters/blocking_connection.py", line 1104, in _rpc
self._wait_on_response(method_frame))
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/pika/adapters/blocking_connection.py", line 1124, in _send_method
self.connection.process_data_events()
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/pika/adapters/blocking_connection.py", line 215, in process_data_events
if self._handle_read():
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/pika/adapters/blocking_connection.py", line 327, in _handle_read
if self._read_poller.ready():
File "/Users/Marboni/Projects/Databasy/databasy-facade/env/lib/python2.7/site-packages/pika/adapters/blocking_connection.py", line 66, in ready
self.poll_timeout)
KeyboardInterrupt
I tried to run application and access it from separate script:
#!/usr/bin/env python
from databasyfacade.rpc.client import RpcClient
rpc = RpcClient('localhost')
profile = rpc.call('profile', 4L)
print profile.email
As you can see, code is the same as in test, but in this case it works.
What can be the cause of this issue? May be, it's because Flask-Testing runs both application and client in one process? How to check it / write correct test?
I found the cause, it's not related with MQ. Remove method accessed database using SQLAlchemy with scoped_session. Problem disappeared after I finalized session properly:
Session.remove()