为Flask提供功能标志
项目描述
flask-pancake
为Flask提供功能标志
这个库受到了django-waffle的极大启发。
安装
flask-pancake
依赖于 Redis 和 flask-redis Python包。
$ python -m pip install flask-pancake
Successfully installed flask-pancake
from flask import Flask
from flask_pancake import FlaskPancake, Switch
from flask_redis import FlaskRedis
app = Flask(__name__)
app.secret_key = "s3cr!t"
pancake = FlaskPancake(app)
redis = FlaskRedis(app)
SWITCH_FEATURE = Switch("FEATURE", default=False)
@app.route("/")
def index():
if SWITCH_FEATURE.is_active():
return "Hello World!", 200
else:
return "Not found", 404
或者,如果您使用 create_app()
方法配置您的Flask应用,请使用 pancake.init_app()
from flask import Flask
from flask_pancake import FlaskPancake
pancake = FlaskPancake()
def create_app() -> Flask:
app = Flask(__name__)
app.secret_key = "s3cr!t"
pancake.init_app(app)
return app
使用
flask-pancake
提供了三种类型的标志
-
开关
,它们可以是全局激活或关闭。这些开关的常见用途是在整个系统中启用或禁用功能。例如,在依赖第三方服务的情况下,当该服务不可用时,使用全局开关禁用功能。 -
标志
与开关类似,但可以针对单个组进行覆盖。要使用标志
,需要定义至少一个返回组唯一ID或None
的函数。组可以是您希望用户分组的任何内容:用户ID(这将允许按用户启用/禁用功能)、用户的属性,如“is_superuser”或“is_staff”,或您能想到的任何其他内容。将按顺序尝试组。第一个匹配的将被使用。这意味着,更具体的函数应该首先定义,不具体的函数最后定义。
from flask import request from flask_pancake import FlaskPancake def get_group_user(): # If the `request` object has a `user` attribute and the `user` object # has a `uid` attribute, return that. return getattr(getattr(request, "user", None), "uid", None) def get_group_superuser(): # If the `request` object has a `user` attribute and the `user` object # has an `is_superuser` attribute, return "y" if that is boolean `True` # or "n" if it isn't. return getattr(getattr(request, "user", None), "is_superuser", None) and "y" or "n" # Alternatively, instead of using `get_group_superuser()` one can use a # slightly more verbose class-based approach which has the added benefit # of adding additional value to the flask-pancake overview API view (see # below). class IsSuperuser(GroupFunc): def __call__(self) -> str: return getattr(getattr(request, "user", None), "is_superuser", None) and "y" or "n" def get_candidate_ids(self) -> List[str]: return ["yes", "no"] pancake = FlaskPancake( group_funcs={"user": get_group_user, "superuser": get_group_superuser} # alternatively if using the class-based approach: # group_funcs={"user": get_group_user, "superuser": IsSuperuser} ) # Or, if importing a function from somewhere isn't possible, a string based # approach can be used. # Separate the the fully qualified module path from the function with a `:` pancake = FlaskPancake( group_funcs={ "user", "my.app.account.utils:get_group_user", "superuser", "my.app.account.utils:get_group_superuser", # alternatively if using the class-based approach: "superuser", "my.app.account.utils:IsSuperuser", } )
在示例中,每次检查
标志
时,FlaskPancake 都会按以下顺序检查是否设置了值- 标志是为当前用户禁用/启用吗?
- 如果不是,标志是为超级用户/非超级用户禁用/启用吗?
- 如果没有,默认情况下标志是禁用/启用吗?
-
示例
具有全局“比例”0 - 100%。在请求中对示例进行第一次检查时,将检查这些范围内的随机值。如果它低于或等于设定的值,则是激活的,如果它更大,则是非激活的。由于随机性,示例将它们的状态存储在请求上下文中(Flask的
g
上下文对象)。此外,为了在请求之间为用户提供一致的行为,请求中使用的示例的值存储在用户的浏览器中的cookie中。然后在下一个请求中再次加载,从而在请求之间提供稳定的行为。这意味着,尽管涉及随机性,但此行为实际上是安全的
def foo(): if MY_SAMPLE.is_active(): # do something pass ... if MY_SAMPLE.is_active(): # do more pass
可以使用clear()
方法清除所有三种类型功能标志的持久状态。
类似地,可以使用disable()
和enable()
方法更改Flag
和Switch
的持久状态。Sample
可以使用它们的set(value: float)
方法进行更新。
当使用Flag
时,有clear_group(group_id)
和clear_all_group(group_id)
方法,用于清除当前组或所有用户的状态。同样,还有disable_group(group_id)
和enable_group(group_id)
用于设置当前用户所属组的组状态。
Web API
flask-pancake
提供了一个API端点,该端点在蓝图中的/overview
路由下显示所有可用的Flag
、Sample
和Switch
及其对应的状态。它还提供了一个JSON API,用于在/status
路由下获取当前用户的所有功能标志的状态。可以通过注册Flask蓝图来启用这些API。
from flask import Flask
from flask_pancake import FlaskPancake, blueprint
app = Flask(__name__)
app.secret_key = "s3cr!t"
pancake = FlaskPancake(app)
app.register_blueprint(blueprint, url_prefix="/pancakes")
警告:此API没有进行任何形式的保护!您应使用Flask的Blueprint.before_request()
功能为/overview
端点添加一些身份验证。请参阅complex_app.py
以获取示例。
注意:/status
API端点是供前端应用程序使用的,用于加载所有Flag
、Sample
和Switch
的状态,并在前端中轻松使用。如果不想通过/status
端点暴露某些功能标志,则将功能标志分为两个FlaskPancake
扩展实例,并且仅允许访问为前端功能标志服务的/status
端点。
如上所述,Sample
在请求之间将它们的状态存储在cookie中。默认情况下,cookie名称为扩展的名称,但可以在创建FlaskPancake()
扩展时使用cookie_name
参数显式设置。对于cookie选项也是如此:默认情况下,cookie将使用HttpOnly
和SameSite=Lax
属性进行设置。cookie选项通过传递到Werkzeug的set_cookie()
方法
from flask import Flask
from flask_pancake import FlaskPancake
app = Flask(__name__)
app.secret_key = "s3cr!t"
pancake = FlaskPancake(
app,
name="feature-flags",
cookie_name="ff",
cookie_options={"httponly": True, "samesite": "Lax", "secure": True},
)
命令行界面
flask-pancake
提供了一个CLI,它可以与Flask自己的CLI集成。您可以使用flask run
以开发模式启动应用程序的方式调用flask pancake
。以下是一些示例
$ flask pancake
Usage: flask pancake [OPTIONS] COMMAND [ARGS]...
Commands to manage flask-pancake flags, samples, and switches.
Options:
--help Show this message and exit.
Commands:
flags
samples
switches
$ flask pancake flags list
DO_SOMETHING_ELSE: Yes (default: Yes)
FOO_CAN_DO: No (default: No)
$ flask pancake flags enable FOO_CAN_DO
Flag 'FOO_CAN_DO' enabled.
$ flask pancake flags list
DO_SOMETHING_ELSE: Yes (default: Yes)
FOO_CAN_DO: Yes (default: No)
项目详情
下载文件
下载适用于您平台的应用程序。如果您不确定选择哪个,请了解更多关于安装包的信息。
源分发
构建分发版
flask-pancake-0.5.2.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | a045b1e867e8b64708821cdf7eae8b24995a9e2b5461527eb4bd3cf271999f50 |
|
MD5 | 9585dc27ef638a2e0273911ae441b0ad |
|
BLAKE2b-256 | b4868e8fecaf433b5c7596dd5dafcf0463a5bb2afaa7ebcb84a5e68396ec010c |
flask_pancake-0.5.2-py3-none-any.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e4401ab59965c0cee26717209f92ff968129475c5fc653667acd04bd996057dd |
|
MD5 | 8ed532f72365ce3f23bddc476d64f36a |
|
BLAKE2b-256 | b3f048bb2201c029f1c73994b5115bd82a74560c2e17454e052d938ccc1fef85 |