From 7071e6298553d5f85badc8f041d44b5167d7384c Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Mon, 22 Apr 2019 14:51:52 -0700 Subject: [PATCH] Extend Flask Blueprint class to allow skipping routes When adding a new API we want to use the old code for any routes that aren't being overridden. This modifies the Flask Blueprint class so that a skip_rules list can be passed to server.register_blueprint() --- src/pylorax/api/flask_blueprint.py | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/pylorax/api/flask_blueprint.py diff --git a/src/pylorax/api/flask_blueprint.py b/src/pylorax/api/flask_blueprint.py new file mode 100644 index 00000000..fee3bf05 --- /dev/null +++ b/src/pylorax/api/flask_blueprint.py @@ -0,0 +1,54 @@ +# +# Copyright (C) 2019 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +""" Flask Blueprints that support skipping routes + +When using Blueprints for API versioning you will usually want to fall back +to the previous version's rules for routes that have no new behavior. To do +this we add a 'skip_rule' list to the Blueprint's options dictionary. It lists +all of the routes that you do not want to register. + +For example: + from pylorax.api.v0 import v0 + from pylorax.api.v1 import v1 + + server.register_blueprint(v0, url_prefix="/api/v0/") + server.register_blueprint(v0, url_prefix="/api/v1/", skip_rules=["/blueprints/list"] + server.register_blueprint(v1, url_prefix="/api/v1/") + +This will register all of v0's routes under `/api/v0`, and all but `/blueprints/list` under /api/v1, +and then register v1's version of `/blueprints/list` under `/api/v1` + +""" +from flask import Blueprint +from flask.blueprints import BlueprintSetupState + +class BlueprintSetupStateSkip(BlueprintSetupState): + def __init__(self, blueprint, app, options, first_registration, skip_rules): + self._skip_rules = skip_rules + super(BlueprintSetupStateSkip, self).__init__(blueprint, app, options, first_registration) + + def add_url_rule(self, rule, endpoint=None, view_func=None, **options): + if rule not in self._skip_rules: + super(BlueprintSetupStateSkip, self).add_url_rule(rule, endpoint, view_func, **options) + +class BlueprintSkip(Blueprint): + def __init__(self, *args, **kwargs): + super(BlueprintSkip, self).__init__(*args, **kwargs) + + def make_setup_state(self, app, options, first_registration=False): + skip_rules = options.pop("skip_rules", []) + return BlueprintSetupStateSkip(self, app, options, first_registration, skip_rules)