- 新增图像生成接口,支持试用、积分和自定义API Key模式 - 实现生成图片结果异步上传至MinIO存储,带重试机制 - 优化积分预扣除和异常退还逻辑,保障用户积分准确 - 添加获取生成历史记录接口,支持时间范围和分页 - 提供本地字典配置接口,支持模型、比例、提示模板和尺寸 - 实现图片批量上传接口,支持S3兼容对象存储 feat(admin): 增加管理员角色管理与权限分配接口 - 实现角色列表查询、角色创建、更新及删除功能 - 增加权限列表查询接口 - 实现用户角色分配接口,便于统一管理用户权限 - 增加系统字典增删查改接口,支持分类过滤和排序 - 权限控制全面覆盖管理接口,保证安全访问 feat(auth): 完善用户登录注册及权限相关接口与页面 - 实现手机号验证码发送及校验功能,保障注册安全 - 支持手机号注册、登录及退出接口,集成日志记录 - 增加修改密码功能,验证原密码后更新 - 提供动态导航菜单接口,基于权限展示不同菜单 - 实现管理界面路由及日志、角色、字典管理页面访问权限控制 - 添加系统日志查询接口,支持关键词和等级筛选 feat(app): 初始化Flask应用并配置蓝图与数据库 - 创建应用程序工厂,加载配置,初始化数据库和Redis客户端 - 注册认证、API及管理员蓝图,整合路由 - 根路由渲染主页模板 - 应用上下文中自动创建数据库表,保证运行环境准备完毕 feat(database): 提供数据库创建与迁移支持脚本 - 新增数据库创建脚本,支持自动检测是否已存在 - 添加数据库表初始化脚本,支持创建和删除所有表 - 实现RBAC权限初始化,包含基础权限和角色创建 - 新增字段手动修复脚本,添加用户API Key和积分字段 - 强制迁移脚本支持清理连接和修复表结构,初始化默认数据及角色分配 feat(config): 新增系统配置参数 - 配置数据库、Redis、Session和MinIO相关参数 - 添加AI接口地址及试用Key配置 - 集成阿里云短信服务配置及开发模式相关参数 feat(extensions): 初始化数据库、Redis和MinIO客户端 - 创建全局SQLAlchemy数据库实例和Redis客户端 - 配置基于boto3的MinIO兼容S3客户端 chore(logs): 添加示例系统日志文件 - 记录用户请求、验证码发送成功与失败的日志信息
257 lines
5.8 KiB
Python
257 lines
5.8 KiB
Python
"""Built-in template tests used with the ``is`` operator."""
|
|
|
|
import operator
|
|
import typing as t
|
|
from collections import abc
|
|
from numbers import Number
|
|
|
|
from .runtime import Undefined
|
|
from .utils import pass_environment
|
|
|
|
if t.TYPE_CHECKING:
|
|
from .environment import Environment
|
|
|
|
|
|
def test_odd(value: int) -> bool:
|
|
"""Return true if the variable is odd."""
|
|
return value % 2 == 1
|
|
|
|
|
|
def test_even(value: int) -> bool:
|
|
"""Return true if the variable is even."""
|
|
return value % 2 == 0
|
|
|
|
|
|
def test_divisibleby(value: int, num: int) -> bool:
|
|
"""Check if a variable is divisible by a number."""
|
|
return value % num == 0
|
|
|
|
|
|
def test_defined(value: t.Any) -> bool:
|
|
"""Return true if the variable is defined:
|
|
|
|
.. sourcecode:: jinja
|
|
|
|
{% if variable is defined %}
|
|
value of variable: {{ variable }}
|
|
{% else %}
|
|
variable is not defined
|
|
{% endif %}
|
|
|
|
See the :func:`default` filter for a simple way to set undefined
|
|
variables.
|
|
"""
|
|
return not isinstance(value, Undefined)
|
|
|
|
|
|
def test_undefined(value: t.Any) -> bool:
|
|
"""Like :func:`defined` but the other way round."""
|
|
return isinstance(value, Undefined)
|
|
|
|
|
|
@pass_environment
|
|
def test_filter(env: "Environment", value: str) -> bool:
|
|
"""Check if a filter exists by name. Useful if a filter may be
|
|
optionally available.
|
|
|
|
.. code-block:: jinja
|
|
|
|
{% if 'markdown' is filter %}
|
|
{{ value | markdown }}
|
|
{% else %}
|
|
{{ value }}
|
|
{% endif %}
|
|
|
|
.. versionadded:: 3.0
|
|
"""
|
|
return value in env.filters
|
|
|
|
|
|
@pass_environment
|
|
def test_test(env: "Environment", value: str) -> bool:
|
|
"""Check if a test exists by name. Useful if a test may be
|
|
optionally available.
|
|
|
|
.. code-block:: jinja
|
|
|
|
{% if 'loud' is test %}
|
|
{% if value is loud %}
|
|
{{ value|upper }}
|
|
{% else %}
|
|
{{ value|lower }}
|
|
{% endif %}
|
|
{% else %}
|
|
{{ value }}
|
|
{% endif %}
|
|
|
|
.. versionadded:: 3.0
|
|
"""
|
|
return value in env.tests
|
|
|
|
|
|
def test_none(value: t.Any) -> bool:
|
|
"""Return true if the variable is none."""
|
|
return value is None
|
|
|
|
|
|
def test_boolean(value: t.Any) -> bool:
|
|
"""Return true if the object is a boolean value.
|
|
|
|
.. versionadded:: 2.11
|
|
"""
|
|
return value is True or value is False
|
|
|
|
|
|
def test_false(value: t.Any) -> bool:
|
|
"""Return true if the object is False.
|
|
|
|
.. versionadded:: 2.11
|
|
"""
|
|
return value is False
|
|
|
|
|
|
def test_true(value: t.Any) -> bool:
|
|
"""Return true if the object is True.
|
|
|
|
.. versionadded:: 2.11
|
|
"""
|
|
return value is True
|
|
|
|
|
|
# NOTE: The existing 'number' test matches booleans and floats
|
|
def test_integer(value: t.Any) -> bool:
|
|
"""Return true if the object is an integer.
|
|
|
|
.. versionadded:: 2.11
|
|
"""
|
|
return isinstance(value, int) and value is not True and value is not False
|
|
|
|
|
|
# NOTE: The existing 'number' test matches booleans and integers
|
|
def test_float(value: t.Any) -> bool:
|
|
"""Return true if the object is a float.
|
|
|
|
.. versionadded:: 2.11
|
|
"""
|
|
return isinstance(value, float)
|
|
|
|
|
|
def test_lower(value: str) -> bool:
|
|
"""Return true if the variable is lowercased."""
|
|
return str(value).islower()
|
|
|
|
|
|
def test_upper(value: str) -> bool:
|
|
"""Return true if the variable is uppercased."""
|
|
return str(value).isupper()
|
|
|
|
|
|
def test_string(value: t.Any) -> bool:
|
|
"""Return true if the object is a string."""
|
|
return isinstance(value, str)
|
|
|
|
|
|
def test_mapping(value: t.Any) -> bool:
|
|
"""Return true if the object is a mapping (dict etc.).
|
|
|
|
.. versionadded:: 2.6
|
|
"""
|
|
return isinstance(value, abc.Mapping)
|
|
|
|
|
|
def test_number(value: t.Any) -> bool:
|
|
"""Return true if the variable is a number."""
|
|
return isinstance(value, Number)
|
|
|
|
|
|
def test_sequence(value: t.Any) -> bool:
|
|
"""Return true if the variable is a sequence. Sequences are variables
|
|
that are iterable.
|
|
"""
|
|
try:
|
|
len(value)
|
|
value.__getitem__ # noqa B018
|
|
except Exception:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def test_sameas(value: t.Any, other: t.Any) -> bool:
|
|
"""Check if an object points to the same memory address than another
|
|
object:
|
|
|
|
.. sourcecode:: jinja
|
|
|
|
{% if foo.attribute is sameas false %}
|
|
the foo attribute really is the `False` singleton
|
|
{% endif %}
|
|
"""
|
|
return value is other
|
|
|
|
|
|
def test_iterable(value: t.Any) -> bool:
|
|
"""Check if it's possible to iterate over an object."""
|
|
try:
|
|
iter(value)
|
|
except TypeError:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def test_escaped(value: t.Any) -> bool:
|
|
"""Check if the value is escaped."""
|
|
return hasattr(value, "__html__")
|
|
|
|
|
|
def test_in(value: t.Any, seq: t.Container[t.Any]) -> bool:
|
|
"""Check if value is in seq.
|
|
|
|
.. versionadded:: 2.10
|
|
"""
|
|
return value in seq
|
|
|
|
|
|
TESTS = {
|
|
"odd": test_odd,
|
|
"even": test_even,
|
|
"divisibleby": test_divisibleby,
|
|
"defined": test_defined,
|
|
"undefined": test_undefined,
|
|
"filter": test_filter,
|
|
"test": test_test,
|
|
"none": test_none,
|
|
"boolean": test_boolean,
|
|
"false": test_false,
|
|
"true": test_true,
|
|
"integer": test_integer,
|
|
"float": test_float,
|
|
"lower": test_lower,
|
|
"upper": test_upper,
|
|
"string": test_string,
|
|
"mapping": test_mapping,
|
|
"number": test_number,
|
|
"sequence": test_sequence,
|
|
"iterable": test_iterable,
|
|
"callable": callable,
|
|
"sameas": test_sameas,
|
|
"escaped": test_escaped,
|
|
"in": test_in,
|
|
"==": operator.eq,
|
|
"eq": operator.eq,
|
|
"equalto": operator.eq,
|
|
"!=": operator.ne,
|
|
"ne": operator.ne,
|
|
">": operator.gt,
|
|
"gt": operator.gt,
|
|
"greaterthan": operator.gt,
|
|
"ge": operator.ge,
|
|
">=": operator.ge,
|
|
"<": operator.lt,
|
|
"lt": operator.lt,
|
|
"lessthan": operator.lt,
|
|
"<=": operator.le,
|
|
"le": operator.le,
|
|
}
|