# -*- coding: utf-8 -*-
"""
flask_via.routers.default
-------------------------
A set of flask specific router classes to be used when defining routes.
Example
-------
.. sourcecode:: python
from flask.ext.via.routes.flask import Basic, Pluggable
from yourapp.views import BarView, foo_view
routes = [
Basic('/foo', 'foo', foo_view),
Pluggable('/bar', BarView, 'bar'),
]
"""
import warnings
from flask import Blueprint as FlaskBlueprint
from flask_via import RoutesImporter
from flask_via.routers import BaseRouter
[docs]class Functional(BaseRouter):
""" A basic Flask router, used for the most basic form of flask routes,
namely functionally based views which would normally use the ``@route``
decorator.
.. versionadded:: 2014.05.19
Example
-------
.. sourcecode:: python
from flask.ext.via.routes import default
from yourapp.views import foo_view, bar_view
routes = [
default.Functional('/foo', 'foo', foo_view),
default.Functional('/bar', 'bar', bar_view),
]
"""
[docs] def __init__(self, url, func, endpoint=None):
""" Basic router constructor, stores passed arguments on the
instance.
Arguments
---------
url : str
The url to use for the route
func : function
The view function to connect the route with
Keyword Arguments
-----------------
endpoint : str, optional
Optional endpoint string, by default flask will use the
view function name as the endpoint name, use this argument
to change the endpoint name.
"""
self.url = url
self.func = func
self.endpoint = endpoint
[docs] def add_to_app(self, app, **kwargs):
""" Adds the url route to the flask application object.mro
.. versionchanged:: 2014.05.08
* ``url_prefix`` can now be prefixed if present in kwargs
.. versionchanged:: 2014.05.19
* ``endpoint`` can now be prefixed if present in kwargs
Arguments
---------
app : flask.app.Flask
Flask application instance
\*\*kwargs
Arbitrary keyword arguments passed in to ``init_app``
"""
url = self.url
endpoint = self.endpoint
#: If this route was included a url preifx may have been passed
#: to the route
if 'url_prefix' in kwargs:
url = kwargs['url_prefix'] + url
#: If this route was included a endpoint prefix may have been passed
#: to the route
if 'endpoint' in kwargs:
if endpoint is None:
endpoint = self.func.__name__
endpoint = kwargs['endpoint'] + endpoint
try:
app.add_url_rule(url, endpoint, self.func)
except AssertionError:
# TODO: Log / Warn
pass
[docs]class Basic(Functional):
""" This is deprecated and will be removed in the next release. Please use
:class:`.Functional`.
.. versionadded:: 2014.05.06
.. deprecated:: 2014.05.19
"""
[docs] def __init__(self, *args, **kwargs):
""" Issues ``DeprecationWarning`` as this is deprecated and will be
removed in a later version.
"""
warnings.simplefilter('always', DeprecationWarning)
warnings.warn(
'Basic router will be removed in a future version, please switch '
'to the Functional router.',
DeprecationWarning)
super(Basic, self).__init__(*args, **kwargs)
[docs]class Pluggable(BaseRouter):
""" Pluggable View router class, allows Flask pluggable view routes to be
added to the flask application.
.. versionadded:: 2014.05.06
Example
-------
.. sourcecode:: python
from flask.ext.via.routers import flask
from flask.views import MethodView
class FooView(MethodView):
def get(self):
return 'foo view'
class BarView(MethodView):
def get(self):
return 'bar view'
routes = [
flask.Pluggable('/', FooView, 'foo')
flask.Pluggable('/', BarView, 'bar')
]
"""
[docs] def __init__(self, url, view, endpoint, **kwargs):
""" Pluggable router constructor, stores passed arguments on instance.
.. versionchanged:: 2014.05.19
* Added ``view`` argument
* Added ``endpoint`` argument
Arguments
---------
url : str
The url to use for the route
view : class
The Flask pluggable view class, for example:
* :class:`flask.views.View`
* :class:`flask.views.MethodView`
endpoint : str
The Flask endpoint name for the view, this is required for Flask
pluggable views.
\*\*kwargs :
Arbitrary keyword arguments for ``add_url_rule``
"""
self.url = url
self.view = view
self.endpoint = endpoint
self.kwargs = kwargs
[docs] def add_to_app(self, app, **kwargs):
""" Adds the url route to the flask application object.
.. versionchanged:: 2014.05.19
Updated ``add_url_rule`` to support endpoint prefixing and support
new way of defining Pluggable views
Arguments
---------
app : flask.app.Flask
Flask application instance
\*\*kwargs
Arbitrary keyword arguments passed in to ``init_app``
"""
url = self.url
endpoint = self.endpoint
#: If this route was included a url preifx may have been passed
#: to the route
if 'url_prefix' in kwargs:
url = kwargs['url_prefix'] + url
#: If this route was included a endpoint prefix may have been passed
#: to the route
if 'endpoint' in kwargs:
endpoint = kwargs['endpoint'] + endpoint
try:
app.add_url_rule(
url,
view_func=self.view.as_view(endpoint),
**self.kwargs)
except AssertionError:
# TODO: Log / Warn
pass
[docs]class Blueprint(BaseRouter, RoutesImporter):
""" Registers a flask blueprint and registers routes to that blueprint,
similar to :py:class:`flask_via.routers.Include`.
.. versionadded:: 2014.05.06
Example
-------
**Auto creates Blueprint instance***
.. sourcecode:: python
from flask.ext.via.routers import default
routes = [
default.Blueprint('foo', 'flask_via.examples.blueprints.foo')
]
**Pass existing Blueprint instance***
.. sourcecode:: python
from flask import Blueprint
from flask.ext.via.routers import default
blueprint = Blueprint('foo', __name__)
routes = [
default.Blueprint(blueprint)
]
"""
[docs] def __init__(
self,
name_or_instance,
module=None,
routes_module_name='routes',
routes_name=None,
static_folder=None,
static_url_path=None,
template_folder=None,
url_prefix=None,
subdomain=None,
url_defaults=None):
""" Constructor for blueprint router.
.. versionchanged:: 2014.05.19
* Replaced ``name`` with ``name_or_instance`` argument which allows
the router to take an already instantiated blueprint instance.
* ``module`` argument optional when instance is passed as the
first argument
* ``routes_name`` keyword argument default value set to ``None``
Arguments
---------
name : str, flask.blueprints.Blueprint
Blueprint name or a Blueprint class instance
Keyword Arguments
-----------------
module : str
Python dotted path to the blueprint module
routes_module_name : str, optional
The module ``Flask-Via`` will look for within the blueprint module
which contains the routes, defaults to ``routes``
routes_name : str, optional
Name of the variable holding the routes in the module, defaults to
``None``
static_folder : str, optional
Path to static files for blueprint, defaults to ``None``
static_url_path : str, optional
URL path for blueprint static files, defaults to ``None``
template_folder : str, optional
Templates folder name, defaults to ``None``
url_prefix : str, optional
URL prefix for routes served within the blueprint, defaults
to ``None``
subdomain : str, optional
Sub domain for blueprint, defaults to ``None``
url_defaults : function, optional
Callback function for URL defaults for this blueprint.
It's called with the endpoint and values and should update
the values passed in place, defaults to ``None``.
"""
if isinstance(name_or_instance, FlaskBlueprint):
self.instance = name_or_instance
self.endpoint = self.instance.name
self.module = self.instance.import_name
else:
self.endpoint = name_or_instance
self.module = module
self.routes_module_name = routes_module_name
self.routes_name = routes_name
self.static_folder = static_folder
self.static_url_path = static_url_path
self.template_folder = template_folder
self.url_prefix = url_prefix
self.subdomain = subdomain
self.url_defaults = url_defaults
@property
[docs] def routes_module(self):
""" Generates the routes module path, this is built from
``self.module`` and ``self.routes_module_name``.
Returns
-------
str
Python dotted path to the routes module containing routes.
"""
return '{0}.{1}'.format(self.module, self.routes_module_name)
[docs] def blueprint(self, **kwargs):
""" Returns a Flask Blueprint instance, either one provided or created
here.
.. versionchanged:: 2014.05.19
* Renamed method from ``create_blueprint`` to ``blueprint``
* If ``instance`` attribute exists, use this is as the blueprint
else create the blueprint.
* Support for endpoint prefixing
Returns
-------
flask.blueprints.Blueprint
An instantiated Flask Blueprint instance
"""
try:
blueprint = self.instance
except AttributeError:
#: If this route was included a url preifx may have been passed
#: to the route
if 'url_prefix' in kwargs:
url_prefix = self.url_prefix or ''
self.url_prefix = kwargs['url_prefix'] + url_prefix
#: If this route was included a endpoint prefix may have been
#: passed to the route
if 'endpoint' in kwargs:
endpoint = self.endpoint or ''
self.endpoint = kwargs['endpoint'] + endpoint
blueprint = FlaskBlueprint(
self.endpoint,
self.module,
static_folder=self.static_folder,
static_url_path=self.static_url_path,
template_folder=self.template_folder,
url_prefix=self.url_prefix,
subdomain=self.subdomain,
url_defaults=self.url_defaults)
return blueprint
[docs] def add_to_app(self, app, **kwargs):
""" Creates a Flask blueprint and registers routes with that blueprint,
this means any routes defined will be added to the blueprint rather
than the application.
Arguments
---------
app : flask.app.Flask
Flask application instance
\*\*kwargs
Arbitrary keyword arguments passed in to ``init_app``
"""
# Register blueproiint
blueprint = self.blueprint(**kwargs)
# Routes name can be configured by setting VIA_ROUTES_NAME
if not self.routes_name:
self.routes_name = app.config.get('VIA_ROUTES_NAME', 'routes')
# Get the routes
routes = self.include(self.routes_module, self.routes_name)
# Load the routes
self.load(blueprint, routes, **kwargs)
# Register the blueprint with the application
app.register_blueprint(blueprint)