The API Reference
This part of the documentation covers wask’s Python interfaces.
Adapters
These classes are for adapting webapp2 code to run on flask.
- class wask.adapters.WaskApp[source]
Adapter for writting code that expects access to the active webapp2.WSGIApplication instance and makes it work with flask.current_app.
flask.current_app is a proxy to the application handling the current request. It is only available during requests.
- See the following documentation for more details:
https://flask.palletsprojects.com/en/1.1.x/api/#flask.current_app https://flask.palletsprojects.com/en/1.1.x/appcontext/
- class wask.adapters.WaskMethodView(*args, **kwargs)[source]
Adapter for writing webapp2 request handlers that work with flask.
- Methods not implemented:
error: Not used anywhere in mainapp. url_for: Not used anywhere in mainapp.
Differences between flask and webapp2 that influence how this class is implemented and how it should be used:
Flask: - By default, the allowed methods for a request where the handler is an instance
- of MethodView is determined as follows:
Any HTTP method functions (e.g. get, post, etc.) defined for a MethodView subclass.
If no method functions are defined, “GET” is included by default.
“HEAD” is automatically added if get is present. MethodView calls get if request.method == “HEAD” and there’s no head method.
“OPTIONS” is added and handled by flask automatically.
The above rules mean allowed methods will always include “OPTIONS”, and will always include “HEAD” if the handler has a get method.
If a request method is not in the allowed methods, flask won’t dispatch the request to the handler and automatically responds with a 405 status code and populates the “Allow” HTTP header with the allowed methods.
- For reference, see:
https://flask.palletsprojects.com/en/1.1.x/quickstart/#http-methods
Webapp2: - By default, webapp2 allows all HTTP methods (except for “PATCH”), and thus
dispatches requests with (almost) any HTTP method to a handler.
It’s up to the handler to call the right function to handle the request method (e.g. with getattr(self, method_name)) or respond with a 405 status code if it can’t handle the request method.
RequestHandler sets the “Allow” header on 405 responses to the list of HTTP method functions implemented by the class (e.g. get, post, etc.).
Webapp2 doesn’t automatically handle “OPTIONS” or “HEAD”.
To make flask’s request routing and dispatching work more like webapp2, the following must be done: - Disable automatic handling of “OPTIONS” for any subclass of WaskMethodView by setting
provide_automatic_options = False
Use wask.adapters.add_route to register a route with the application that has automatic support for the “HEAD” method disabled.
As a result, wask.adapters.add_route should always be used to register a route with the app that uses an instance of WaskMethodView as the route’s handler. E.g.
add_route(app, “/”, view_func=Handler.as_view(“endpoint-name”))
- class wask.adapters.WaskResponse(*args, **kwargs)[source]
For allowing you to write webapp2 code that works with flask.
- Methods not implemented:
- body: This is only used once in mainapp and seems like an improper
use of webapp2.Response
- status_message: Used for setting the text portion of the status
e.g. The “OK” in “200 OK”. This is also only used once and is likely unnecessary
- headers:
The header member variable is actually a different class in webapp2 than it is in flask. Both implement complex custom classes to handle headers.
Luckily they appear to have exactly the same interface, so we have not made any changes here to attempt to adapt them.
- In mainapp we only use self.response.header in the following ways:
Setting a header directly as if the header was a dictionary
using the header.add(key, value) method
using the header.add_header(key, value) method, which appears to be functionally the same as header.add(key, value)
- out:
In webapp1 (yes 1), you would access the write function through ` self.response.out.write, in webapp2 they changed it to self.response.write however they maintained the out property for backwards compatibility.
Because we have the old pattern all over the place in our code we have to support it as well.
Datastructures
These datastructures are used throughout wask. Based on werkzeug’s datastructures and adapting them to fit webapp2 style interfaces.
- class wask.datastructures.WaskCombinedMultiDict(dicts=None)[source]
In webapp2 they use webob.multidict.NestedMultiDic, which operates almost identically to werkzeug.datastructures.CombinedMultiDict.
The only difference is that in NestedMultiDic.items() by default it returns duplicate values, whereas in CombinedMultiDict.items() by default it doesn’t
- e.g. for GET /?foo=bar&foo=baz
webob.multidict.NestedMultiDic.items() returns [(“foo”, “bar”), (“foo”, “baz”)] werkzeug.datastructures.CombinedMultiDict.items() returns [(“foo”, “bar”)]
- class wask.datastructures.WaskImmutableMultiDict(mapping=None)[source]
In webapp2 they use webob.multidict.GetDict, which operates almost identically to werkzeug.datastructures.ImmutableMultiDict.
The only difference is that in GetDict.items() by default it returns duplicate values, whereas in ImmutableMultiDict.items() by default it doesn’t
- e.g. for GET /?foo=bar&foo=baz
webob.multidict.GetDict.items() returns [(“foo”, “bar”), (“foo”, “baz”)] werkzeug.datastructures.ImmutableMultiDict.items() returns [(“foo”, “bar”)]
Routing
These tools are for adapting webapp2 routing to run on flask. A lot of it is temporary scaffolding for migrating mainapp.
- wask.routing.uri_for(name, *args, **kwargs)[source]
Adapts webapp2.uri_for to flask.url_for
Documentation references: - webapp2: https://github.com/GoogleCloudPlatform/webapp2/blob/2.5.2/docs/guide/routing.rst#building-uris - flask: https://flask.palletsprojects.com/en/1.1.x/api/#flask.url_for
Differences from webapp2: - Query params are not sorted (Python 3 only) - If _scheme is not None and _full (_external in flask) is not True, ValueError is raised - _request argument is not supported, it will be ignored
- Return type:
str
- wask.routing.add_webapp2_routes_to_flask_app(app, route_config)[source]
Takes a webapp2 routing configuration and adds the same URLs to a flask app, while skipping any with matching endpoint names.
This should be done after you add all the migrated routes from webapp2.
The endpoint for each of these endpoints will return 501 Not Implemented.
These endpoints should never be called directly.
- Return type:
None
- Justification:
During the migration process we will need to have every routable URI from webapp2 available in Flask.
All that matters is that we are able to build the URIs from flasks url_for and webapp2s uri_for at the same time.
Once the migration is complete this file can be removed
- See:
https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations https://webapp2.readthedocs.io/en/latest/guide/routing.html#the-url-template
- Differences between webapp2 and flask routes:
webapp2 routes can have regular expressions, flask routes cannot
webapp2 routes can have unnamed templates, flask routes cannot Since we don’t have unnamed templates in mainapp, we are not supporting them
- class wask.routing.WaskRedirectRoute(path, name, redirect_to='', redirect_to_name='', **kwargs)[source]
Provides similar functionality as webapp2.RedirectRoute
Differences: - webapp2.RedirectRoute allows both redirect_to and redirect_to_name to be absent
whereas WaskRedirectRoute requires one or the other. Like webapp2.RedirectRoute, WaskRedirectRoute does not allow both at the same time.