kronosapiens.github.io - Understanding Contexts in Flask









Search Preview

Understanding Contexts in Flask

kronosapiens.github.io
For those of you following along, you’ll be happy to know that the database and model layers of the Paragon Measure web application are more-or-less built. W...
.io > kronosapiens.github.io

SEO audit: Content analysis

Language Error! No language localisation is found.
Title Understanding Contexts in Flask
Text / HTML ratio 42 %
Frame Excellent! The website does not use iFrame solutions.
Flash Excellent! The website does not have any flash contents.
Keywords cloud request application context ipdb> Flask def import = I’m test current_app app function view variables contexts object client access return
Keywords consistency
Keyword Content Title Description Headings
request 38
application 36
context 34
ipdb> 18
Flask 18
def 14
Headings
H1 H2 H3 H4 H5 H6
2 7 0 0 0 0
Images We found 0 images on this web page.

SEO Keywords (Single)

Keyword Occurrence Density
request 38 1.90 %
application 36 1.80 %
context 34 1.70 %
ipdb> 18 0.90 %
Flask 18 0.90 %
def 14 0.70 %
import 14 0.70 %
= 13 0.65 %
I’m 13 0.65 %
test 12 0.60 %
current_app 11 0.55 %
app 10 0.50 %
function 10 0.50 %
view 9 0.45 %
variables 8 0.40 %
contexts 7 0.35 %
object 7 0.35 %
client 6 0.30 %
access 6 0.30 %
return 6 0.30 %

SEO Keywords (Two Word)

Keyword Occurrence Density
the application 16 0.80 %
application context 15 0.75 %
the request 12 0.60 %
to the 10 0.50 %
request context 9 0.45 %
an application 7 0.35 %
is the 6 0.30 %
of the 6 0.30 %
in the 6 0.30 %
a request 6 0.30 %
the Flask 6 0.30 %
to be 6 0.30 %
on the 6 0.30 %
with the 5 0.25 %
that the 5 0.25 %
able to 5 0.25 %
need to 5 0.25 %
from flask 5 0.25 %
view function 5 0.25 %
What a 4 0.20 %

SEO Keywords (Three Word)

Keyword Occurrence Density Possible Spam
the application context 7 0.35 % No
an application context 5 0.25 % No
the request context 4 0.20 % No
the view functions 3 0.15 % No
setUp and tearDown 3 0.15 % No
it seems that 3 0.15 % No
application context the 3 0.15 % No
beautiful day for 3 0.15 % No
a beautiful day 3 0.15 % No
a request context 3 0.15 % No
What a beautiful 3 0.15 % No
the application object 3 0.15 % No
g and current_app 3 0.15 % No
from flask import 3 0.15 % No
there is no 3 0.15 % No
a view function 3 0.15 % No
import unittest from 3 0.15 % No
for collection in 2 0.10 % No
in dbsessiondbcollection_names Skip 2 0.10 % No
collection in dbsessiondbcollection_names 2 0.10 % No

SEO Keywords (Four Word)

Keyword Occurrence Density Possible Spam
a beautiful day for 3 0.15 % No
What a beautiful day 3 0.15 % No
'Hello What a beautiful 2 0.10 % No
setUpself appconfigfrom_object'webappconfigTesting' dbinit_appapp selfapp 2 0.10 % No
tearDownself for collection in 2 0.10 % No
def tearDownself for collection 2 0.10 % No
apptest_client def tearDownself for 2 0.10 % No
= apptest_client def tearDownself 2 0.10 % No
selfapp = apptest_client def 2 0.10 % No
that the application context 2 0.10 % No
seems that the application 2 0.10 % No
it seems that the 2 0.10 % No
dbinit_appapp selfapp = apptest_client 2 0.10 % No
appconfigfrom_object'webappconfigTesting' dbinit_appapp selfapp = 2 0.10 % No
def setUpself appconfigfrom_object'webappconfigTesting' dbinit_appapp 2 0.10 % No
collection in dbsessiondbcollection_names Skip 2 0.10 % No
TestIntegrationunittestTestCase def setUpself appconfigfrom_object'webappconfigTesting' 2 0.10 % No
class TestIntegrationunittestTestCase def setUpself 2 0.10 % No
an application context the 2 0.10 % No
webapp import app db 2 0.10 % No

Internal links in - kronosapiens.github.io

About
About
Strange Loops and Blockchains
Strange Loops and Blockchains
Trie, Merkle, Patricia: A Blockchain Story
Trie, Merkle, Patricia: A Blockchain Story
Reputation Systems: Promise and Peril
Reputation Systems: Promise and Peril
The Future of Housing, in Three Parts
The Future of Housing, in Three Parts
Proof of Work vs Proof of Stake: a Mirror of History
Proof of Work vs Proof of Stake: a Mirror of History
Introducing Talmud
Introducing Talmud
The Economics of Urban Farming
The Economics of Urban Farming
Time and Authority
Time and Authority
On Meaning in Games
On Meaning in Games
Objective Functions in Machine Learning
Objective Functions in Machine Learning
A Basic Computing Curriculum
A Basic Computing Curriculum
The Problem of Information II
The Problem of Information II
The Problem of Information
The Problem of Information
Elements of Modern Computing
Elements of Modern Computing
Blockchain as Talmud
Blockchain as Talmud
Understanding Variational Inference
Understanding Variational Inference
OpsWorks, Flask, and Chef
OpsWorks, Flask, and Chef
On Learning Some Math
On Learning Some Math
Understanding Unix Permissions
Understanding Unix Permissions
30 Feet from Michael Bloomberg
30 Feet from Michael Bloomberg
The Academy: A Machine Learning Framework
The Academy: A Machine Learning Framework
Setting up a queue service: Django, RabbitMQ, Celery on AWS
Setting up a queue service: Django, RabbitMQ, Celery on AWS
Versioning and Orthogonality in an API
Versioning and Orthogonality in an API
Designing to be Subclassed
Designing to be Subclassed
Understanding Contexts in Flask
Understanding Contexts in Flask
Setting up Unit Tests with Flask, SQLAlchemy, and Postgres
Setting up Unit Tests with Flask, SQLAlchemy, and Postgres
Understanding Package Imports in Python
Understanding Package Imports in Python
Setting up Virtual Environments in Python
Setting up Virtual Environments in Python
Creating superfunctions in Python
Creating superfunctions in Python
Some Recent Adventures
Some Recent Adventures
Sorting in pandas
Sorting in pandas
Mimicking DCI through Integration Tests
Mimicking DCI through Integration Tests
From Ruby to Python
From Ruby to Python
Self-Focus vs. Collaboration in a Programming School
Self-Focus vs. Collaboration in a Programming School
Designing Software to Influence Behavior
Designing Software to Influence Behavior
Maintaining Octopress themes as git submodules
Maintaining Octopress themes as git submodules
Setting up a test suite with FactoryGirl and Faker
Setting up a test suite with FactoryGirl and Faker
To Unit Test or not to Unit Test
To Unit Test or not to Unit Test
A Dynamic and Generally Efficient Front-End Filtering Algorithm
A Dynamic and Generally Efficient Front-End Filtering Algorithm
Trails & Ways: A Look at Rails Routing
Trails & Ways: A Look at Rails Routing
Getting Cozy with rspec_helper
Getting Cozy with rspec_helper
Exploring the ActiveRecord Metaphor
Exploring the ActiveRecord Metaphor
Civic Hacking as Inspiration
Civic Hacking as Inspiration
From Scheme to Ruby
From Scheme to Ruby
Setting up Auto-Indent in Sublime Text 2
Setting up Auto-Indent in Sublime Text 2
hello world
hello world
via RSS
Abacus

Kronosapiens.github.io Spined HTML


Understanding Contexts in Flask AbacusWell-nighUnderstanding Contexts in Flask Aug 14, 2014 For those of you pursuit along, you’ll be happy to know that the database and model layers of the Paragon Measure web using are more-or-less built. We can fire up an interpreter and create, destroy, and interact with our data in much the same way we would when everything was washed-up locally. This is good. Now my work is starting to pivot over to the API side of things – towers a RESTful interface for the front-end developers who are going to be towers the client-side interface.Stuffa Test-Driven kind of Developer, I need to establish a good framework for testing the API as I move forwards. This ways getting my throne virtually Flask’s siring of contexts.Surpassinggetting into the details, let’s establish the purpose of contexts. From Miguel Grinberg’s Flask WebMinutiae(p12): When Flask receives a request from a client, it needs to make a few objects misogynist to the view functions that will handle it. A good example of this is the request object, which encapsulates the HTTP request sent by the client. The obvious way in which Flask could requite a view function wangle to the request object is by sending it as an argument, but that would require every single view function in the using to have an uneaten argument. … To stave cluttering view functions with lots of arguments that may or may not be neded, Flask uses contexts to temporarily make unrepealable objects globally accessible. Alright, so it seems that contexts are used to tenancy the presence or sparsity of various global variables, so that you, the developer, can simply seem that the correct variables will be misogynist when you need them. Given that an using can be running in multiple threads and serving multiple clients at once, I seem that this kind of context management will prove very helpful in keeping things organized. First, let’s take a squint at the using context. TheUsingContext An excerpt from the Flask docs: One of the diamond ideas overdue Flask is that there are two variegated “states” in which lawmaking is executed. The using setup state in which the using implicitly is on the module level. It starts when the Flask object is instantiated, and it implicitly ends when the first request comes in. While the using is in this state a few assumptions are true: the programmer can modify the using object safely. no request handling happened so far you have to have a reference to the using object in order to modify it, there is no magic proxy that can requite you a reference to the using object you’re currently creating or modifying. In contrast, during request handling, a couple of other rules exist: while a request is active, the context local objects (flask.request and others) point to the current request. any lawmaking can get hold of these objects at any time. There is a third state which is sitting in between a little bit. Sometimes you are dealing with an using in a way that is similar to how you interact with applications during request handling just that there is no request active. Consider for instance that you’re sitting in an interactive Python shell and interacting with the application, or a writ line application. The using context is what powers the current_app context local. Ok, so looking at this, it seems that the using context, at least inasmuch as we’ll be interacting with it, is the state of the using without the first request has been made (and when large configuration changes are no longer possible), but surpassing a specific request has come in (at which point we should switch to the (more specific?) request context). Continuing with the docs, there are two ways to create an using context: Automatically, whenever a request context is pushed. Manually, by using the app_context() method. And within an using context, the function flask.current_app will return the current using object.* The g variable is moreover specified there. Not quite, apparently. current_app returns a proxy which *wraps virtually the current app (for some reason which seem to involve words like “threads”). To get the real, bona-fide app, undeniability current_app._get_current_object. Regarding the use of an using context, the docs have this to say (emphasis mine): The context is typically used to enshroud resources on there that need to be created on a per-request or usage case. For instance database connects are destined to go there. When storing things on the using context unique names should be chosen as this is a place that is shared between Flask applications and extensions. So it seems that the using context (specifically, the g variable) is the worldwide resource repository for everything which needs to interact to create this application. This moreover implies that your views connect to your database through this g variable. No g, no db, as they say. Now, let’s move on and take a squint at the request context. The Request Context While the using context contains g and current_app, the request context contains the request and session variables – the request-specific variables containing the information your view function will need to process it’s request, while still relying on the increasingly powerful tools made misogynist by g and current_app. As with the app context, a request context can be created: Automatically when the using recieves a request. Manually, by calling app.test_request_context('/route?param=value) You’ll note that, unlike the using context, the transmission megacosm accepts an treatise representing the request. Also, important: Another thing of note is that the request context will automatically moreover create an using context when it’s pushed and there is no using context for that using so far. This seems to make sense. Since using contexts aren’t instantiated by themselves during the running of a normal using (you create them in the shell, in tests, etc), the request context would just bring a new using context withal with it. Working with Contexts This is the thing that’s been giving me a bit of a struggle.Variegatedexamples will show the contexts stuff initialized and used in variegated ways, some with with statements, some without. I’ll go over the examples one-by-one and try to unpack what’s going on. From the Flask docs: from flask import Flask, current_app app = Flask(__name__) with app.app_context(): # within this block, current_app points to app. print current_app.name From a testing example in Flask Web Development: import unittest from app import create_app, db from app.models import User, Role matriculation FlaskClientTestCase(unittest.TestCase): def setUp(self): self.app = create_app('testing') self.app_context = self.app.app_context() self.app_context.push() db.create_all() Role.insert_roles() self.client = self.app.test_client(use_cookies=True) def tearDown(self): db.session.remove() db.drop_all() self.app_context.pop() def test_home_page(self): response = self.client.get(url_for('main.index)) self.assertTrue('Stranger' in response.get_data(as_text=True) Finally, a third syntax: with app.test_client() as client: resp = client.get('/foo') Here, we pass in app.test_client() in as client. Poking virtually the docs some more, I found this clarifying nugget: This context can be used in two ways. Either with the with statement or by calling the push() and pop() methods. Hallelujah! The warm light of wisdom shines upon my face. Well, mostly. I’m not 100% confident that I understand how the Flask context stack works, but I’m getting there. There’s probably some important functionality well-nigh embedding requests in each other that I’m just not quite ready for. Some day. But in seriousness, this is a very helpful clarification. Some settings (such as within a function) might undeniability for the with syntax. Others, such as in the shell or in the setUp() and tearDown() functions of a test suite, .push() and .pop() might be easier. As a counterexample, let’s squint at some of my pre-enlightenment code. From my integration test file, tests/test_integration.py: from flask import request import unittest from webapp import app, db matriculation TestIntegration(unittest.TestCase): def setUp(self): app.config.from_object('webapp.config.Testing') db.init_app(app) self.app = app.test_client() def tearDown(self): for hodgepodge in db.session.db.collection_names()[1:]: # Skip first db.session.db.drop_collection(collection) def test_root(self): rv = self.app.get('/') predicate 'Hello world!' in rv.data def test_params(self): with app.test_request_context('/?name=Daniel'): predicate request.path == '/' predicate request.args['name'] == 'Daniel' Amusingly, both of these tests passed, which made it nonflexible for me to understand why the increasingly elaborate setups discussed whilom are necessary. Here are the view functions that I was testing: @app.route('/') def root(): return 'Hello world! What a trappy day for research!' @app.route('/<name>') def name(name): return 'Hello {0}! What a trappy day for research!'.format(name) Things became well-spoken to me when I began trying to test increasingly involved views. These two views are scrutinizingly entirely self-contained – they never wangle g, or the database, or anything. Further, in my utter ignorance, I didn’t plane realize that test_params never unquestionably made it to the views. This became well-spoken to me when I tried this: @app.route('/<name>') def name(name): import ipdb; ipdb.set_trace() return 'Hello {0}! What a trappy day for research!'.format(name) And I never plane hit the binding. Truly, in the words of my favorite Roman Civ professor, the depths of my ignorance are vast and unplumbed. Well, at least I’m figuring it out. One thing I noticed is that I’m unquestionably using the request variable in my test_params function – note that I imported it at the top of the file, from flask. I didn’t import anything else, though – not g, or session, or current_app. So plane though these might be in existence within the test request context I’ve created, I can’t unquestionably wangle them. This is an important point, at least for neophytes like me: these variables are flask magic, so you need to unquestionably import them (and moreover be in the correct context) surpassing you can wangle them. They don’t just appear. This isn’t Rails. Ok, I think I may be getting tropical to stuff worldly-wise to test my using like a real grown-up. Ok, time to set a goal: to be worldly-wise to retrieve a model from my database. Let’s see if I can manage it. Let’s start off by defining a view function in webapp/views.py to exhibit a single research trial: @app.route('trials/<name>') def trial(name): trial = Trial.query.filter({'name': name}) # Mongo! if trial is None: return 'Trial not found!' return 'Trial found: {0}, {1}'.format(trial.name, trial.mongo_id) And writing a test. For brevity, I’m truncating the two tests I included earlier, but keeping the setUp() and tearDown() methods. from flask import request import unittest from webapp import app, db from webapp.models import Trial matriculation TestIntegration(unittest.TestCase): def setUp(self): app.config.from_object('webapp.config.Testing') db.init_app(app) self.app = app.test_client() def tearDown(self): for hodgepodge in db.session.db.collection_names()[1:]: # Skip first db.session.db.drop_collection(collection) def test_trial(self): Trial('Parkinsons').save() rv = self.app.get('/trials/Parkinsons') predicate 'Trial found: Parkinsons' in rv.data I run it… and it works. Well, that’s great. Turns out my janky setup is actually… ok? This is strange. I’m not popping or pushing or withing or anything. Well, might as well alimony exploring. I’ve formally imported g, current_app, request, and session from flask, so let’s see what those squint like: g: ipdb> g <flask.g of 'webapp'> ipdb> g.get <bound method _AppCtxGlobals.get of <flask.g of 'webapp'>> I tab-completed g. and got exactly one method, get. I’m not sure what values are currently set on g, considering it doesn’t respond to .keys(). What a mystery. current_app: ipdb> current_app <Flask 'webapp'> ipdb> type(current_app) <class 'werkzeug.local.LocalProxy'> ipdb> myapp = current_app._get_current_object() ipdb> myapp <Flask 'webapp'> ipdb> type(myapp) <class 'flask.app.Flask'>Well-nighwhat I expected. session: ipdb> session <SecureCookieSession {}> ipdb> session.modified False ipdb> session.items() [] Not much going on here just yet. request: ipdb> request <Request 'http://localhost/trials/Parkinsons' [GET]> ipdb> request.view_args {'name': u'Parkinsons'} ipdb> request.path u'/trials/Parkinsons' ipdb> request.url u'http://localhost/trials/Parkinsons' ipdb> request.headers EnvironHeaders([('Host', u'localhost'), ('Content-Length', u'0'), ('Content-Type', u'')])Well-nighright. Groovy. Those work. So why is my terrible test suite working? I’m distraught. Where have I entered the correct context? Miguel’s example from whilom is the same as mine, except he creates and pushes an app context surpassing creating his test client, while I don’t. Yet I’m worldly-wise to wangle the database just fine, and it seems like my contexts are stuff generated correctly. The mysteries of life. In any case, I’m quite pleased with the work we’ve washed-up today. I’ll alimony working on the app and I’ll update this post once I finally icon out where I’ve gone wrong. So far, things seem to be working. Update #1 Ok, I figured out at least one way that my testing setup differs from Miguel’s. I threw a tightness right without my predicate statement and tried to see what variables I could find: ipdb> flask.g <LocalProxy unbound> ipdb> flask.current_app <LocalProxy unbound> As I thought. I’m using the Flask test vendee for my request, which ways that while the request is made as it should be, and within the request (within the view functions, etc) all of the context variables exist, the minute the request finishes and the response is returned, those variables go away. I can make assertions only well-nigh the value of response. In Miguel’s version, on the other hand, since he pushes and pops the using context inside of setUp() and tearDown(), he has wangle to g and current_app from anywhere in his test, and can make assertions well-nigh them. Update #2 A bit increasingly strangeness. Flask gives you a helper function, url_for(), which takes the name of a view function as a string and returns either the relative or the wool URL for that function. Somewhat similar to the _path functions in Rails. I tried to switch my test suite yonder from hard-coded URLs and towards url_for(), but got the pursuit error: RuntimeError:Usingwas not worldly-wise to create a URL connector for request self-sustaining URL generation. You might be worldly-wise to fix this by setting the SERVER_NAME config variable. I pop on over to the Flask config docs, and see this, under the unravelment of the SERVER_NAME variable: Setting a SERVER_NAME moreover by default enables URL generation without a request context but with an using context. I set SERVER_NAME = 'http://localhost:5000/' in my config file, and lo, url_for() started to work. I’m still mulling over why this is the specimen – if Flask defaults to localhost when you start a minutiae server, why wouldn’t url_for() do the same? Why does it need to be given the server explicitly, but nothing else does? I suppose it could be an issue with a single using interacting with multiple servers, so Flask can’t really know what the URL should be for any given route prior to an very request stuff fired. Anyway, life’s mysteries. Update #2.1 Getting when into the office today, I kept working on the test suite. I was still getting bugs with url_for(), so I threw in a tightness and poked around: ipdb> url_for('trials') 'http://http://localhost:5000//trials' Hmm. Definitely increasingly http:// and a little increasingly / than there needs to be. It seems like SERVER_NAME should be set to something increasingly like localhost:5000. Let’s try. Works. Go bears. Comments Please enable JavaScript to view the comments powered by Disqus. Abacus Abacus kronovet@gmail.com kronosapiens kronosapiens I'm Daniel Kronovet, a data scientist living in Tel Aviv.