How can I set the remote_addr property in a flask test_request_context? This question: Get IP Address when testing flask application through nosetests (and other, similar questions) explains how to do it using the get/post/whatever test client calls, but I'm not using those (in this case). Instead, I get a test_request_context and then call a function, thereby allowing me to test the functions that are called by my view functions individually.
Edit: to clarify, my testing code looks something like this:
with app.test_request_context():
result=my_function_which_expects_to_be_called_from_a_request_context()
<check result however>
So at no point am I using a test client call.
Pass the same arguments to test_request_context as you would to client.get. Both set up the WSGI environment the same way internally.
with app.test_request_context(environ_base={'REMOTE_ADDR': '10.1.2.3'}):
Related
I have a function which calls several API's and updates the database upon being called. I want to schedule the function to run daily at specific time.
Already tried flask_apscheduler and APScheduler which gives this error:
This typically means that you attempted to use functionality that needed an active HTTP request. Consult the documentation on testing for information about how to avoid this problem.
Any leads on this will be helpful.
You should:
Post the code where you define your flask application.
Specify how you try to access the app.
How you're calling the APIs.
Whether those APIs are 3rd party or part of your blueprint.
However, this is probably a context issue. I have come across a similar one with SQLAlchemy before.
You will need to somehow get access to your app, either by using app_context or by importing current_app from Flask and accessing the config.
Assuming you imported the app where your function is used, try this:
with app.app_context():
# call your function here
Refer to this document for more information: Flask Documentation
Another approach you can try, is passing your app configurations through a config class object.
You can define the jobs you want to schedule and pass a reference to your function inside.
Check this example from flask-apscheduler repository on GitHub.
This question already has an answer here:
Testing code that requires a Flask app or request context
(1 answer)
Closed 3 years ago.
I'm attempting to write unit tests for a file that is included inside of a flask app (microservice to handle some RESTful endpoints). Some things I'm running into: All the documentation and questions I seem to find involve invoking the APIs themselves, this isn't proper I need to invoke the post function directly with a mocked fake request that I've setup as I need to test functionality.
I'm able to attempt to mock the request.json object however i'm always met with "RuntimeError: Working outside of request context".I've attempted to use test_request_context() but that leads to the same issue. Then I started diving deeper into Flask and attempting to us app.test_client() however this has it's own problems alongside of calling the endpoint directly and doesn't let me unit test my function properly, they start moving into the realm of being integration tests.
This is the function i'm attempting to test:
#api.route...
class HandleRoute(Resource):
#authentication #<-- I want to Mock True or False response
def post(self): #<-- I want to call directly
try:
if not request.json #<-- Value I want to mock, from flask.request
How should I be going about this? I'm trying to avoid app.test_client() and other Flask related things as again, the point of these unit tests is to check my code paths as a sanity check, not just what should happen.
You are correct in wanting to actually perform the request, and test the received response. This is the proper way and Flask already has a built-in client to make this easy.
The official documentation already includes an example of how to do this (Testing Flask Applications). If you want to have more control over the request being processed, then have a look at Manually push a context.
I believe you are looking for the following snippet (adapted from this answer):
with app.test_client() as client:
resp = client.post('/route', {'some_key': 'some_data'})
If you want to do away with flask.test_client() you can use python-requests to stay in the python world, or even use javascript based libraries like Chakram or Frisby
I am trying to learn to make a variable available across method through a decorator function in Flask.
I read Flask request context documentation and wrote the following code, which works as intended.
a.py
_request_ctx_stack.top.current_identity = payload.get('sub')
b.py
current_identity = getattr(_request_ctx_stack.top, 'current_identity', None)
However flask-jwt solves this problem by introducing an additional local proxy like this:
a.py
from werkzeug.local import LocalProxy
current_identity = LocalProxy(lambda: getattr(_request_ctx_stack.top, 'current_identity', None))
_request_ctx_stack.top.current_identity = payload.get('sub')
b.py
from a import current_identity
Why? I read werkzeug context locals documentation and doesn't Flask already implements Werkzeug context locals for request object?
Is there any advantage of introducing LocalProxy?
The LocalProxy wraps the manual code you wrote for getting the value. Instead of needing that manual code everywhere you want to access current_identity, you access it as a proxy and it does the manual code for you.
It's most useful in libraries, where users wouldn't be expected to know how current_identity is set up, and would import the proxy to access it. The same applies to Flask itself: you're not expected to know how the request is set up, or where exactly it's stored, only that you access it by importing request.
A proxy is useful for data that is set up during and local to each request. If you used a true global variable, it would not behave the way you expect when multiple requests are being handled. See Are global variables thread safe in flask? How do I share data between requests?
I have a Pyramid application which uses a number of customization on the request object, in particular, and I would like to be sure that my settings are correctly configured and that they are actually configured.
For example, I have the following (simplified for brevity):
config = Configurator()
config.add_request_method(lambda self: portal_object, name="portal", property=True)
config.set_default_permission('view')
config.add_request_method(auth.get_user, 'user', reify=True)
If these things are not set on the configuration, the application is not going to work, or going to be completely open.
The things I would be interested to test would be:
the portal property that I want to set on the request is the one I passed when configuring the application
by default, my views have a permission set (so unauthenticated users have a forbidden access)
my requests always have a user property, and this property is cached.
So far, I tried to produce a "real" Pyramid request, which involves copy/paste-ing code from pyramid.router (not cool :( ) and, although I haven't tried, I guess it would work if I was setting up something like WebTest but I would then test the whole stack, which I'm not so interested at the moment (the views, especially, are already tested separately.)
What are my possibilities to test my application's configuration, and (hopefully) only this?
How about moving the configuration setting part to a separate function and create a unit test against this functinon?
When setting up a Pyramid app and adding settings to the Configurator, I'm having issues understanding how to access information from request, like request.session and such. I'm completely new at using Pyramid and I've searched all over the place for information on this but found nothing.
What I want to do is access information in the request object when sending out exception emails on production. I can't access the request object, since it's not global in the __init__.py file when creating the app. This is what I've got now:
import logging
import logging.handlers
from logging import Formatter
config.include('pyramid_exclog')
logger = logging.getLogger()
gm = logging.handlers.SMTPHandler(('localhost', 25), 'email#email.com', ['email#email.com'], 'Error')
gm.setLevel(logging.ERROR)
logger.addHandler(gm)
This works fine, but I want to include information about the logged in user when sending out the exception emails, stored in session. How can I access that information from __init__.py?
Attempting to make request a global variable, or somehow store a pointer to "current" request globally (if that's what you're going to try with subscribing to NewRequest event) is not a terribly good idea - a Pyramid application can have more than one thread of execution, so more than one request can be active within a single process at the same time. So the approach may appear to work during development, when the application runs in a single thread mode and just one user accesses it, but produce really funny results when deployed to a production server.
Pyramid has pyramid.threadlocal.get_current_request() function which returns thread-local request variable, however, the docs state that:
This function should be used extremely sparingly, usually only in unit
testing code. it’s almost always usually a mistake to use
get_current_request outside a testing context because its usage makes
it possible to write code that can be neither easily tested nor
scripted.
which suggests that the whole approach is not "pyramidic" (same as pythonic, but for Pyramid :)
Possible other solutions include:
look at exlog.extra_info parameter which should include environ and params attributes of the request into the log message
registering exception views would allow completely custom processing of exceptions
Using WSGI middleware, such as WebError#error_catcher or Paste#error_catcher to send emails when an exception occurs
if you want to log not only exceptions but possibly other non-fatal information, maybe just writing a wrapper function would be enough:
if int(request.POST['donation_amount']) >= 1000000:
send_email("Wake up, we're rich!", authenticated_userid(request))