ai_v/venv/Lib/site-packages/werkzeug/datastructures/cache_control.py
24024 af7c11d7f9 feat(api): 实现图像生成及后台同步功能
- 新增图像生成接口,支持试用、积分和自定义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): 添加示例系统日志文件

- 记录用户请求、验证码发送成功与失败的日志信息
2026-01-12 00:53:31 +08:00

274 lines
9.5 KiB
Python

from __future__ import annotations
import collections.abc as cabc
import typing as t
from inspect import cleandoc
from .mixins import ImmutableDictMixin
from .structures import CallbackDict
def cache_control_property(
key: str, empty: t.Any, type: type[t.Any] | None, *, doc: str | None = None
) -> t.Any:
"""Return a new property object for a cache header. Useful if you
want to add support for a cache extension in a subclass.
:param key: The attribute name present in the parsed cache-control header dict.
:param empty: The value to use if the key is present without a value.
:param type: The type to convert the string value to instead of a string. If
conversion raises a ``ValueError``, the returned value is ``None``.
:param doc: The docstring for the property. If not given, it is generated
based on the other params.
.. versionchanged:: 3.1
Added the ``doc`` param.
.. versionchanged:: 2.0
Renamed from ``cache_property``.
"""
if doc is None:
parts = [f"The ``{key}`` attribute."]
if type is bool:
parts.append("A ``bool``, either present or not.")
else:
if type is None:
parts.append("A ``str``,")
else:
parts.append(f"A ``{type.__name__}``,")
if empty is not None:
parts.append(f"``{empty!r}`` if present with no value,")
parts.append("or ``None`` if not present.")
doc = " ".join(parts)
return property(
lambda x: x._get_cache_value(key, empty, type),
lambda x, v: x._set_cache_value(key, v, type),
lambda x: x._del_cache_value(key),
doc=cleandoc(doc),
)
class _CacheControl(CallbackDict[str, t.Optional[str]]):
"""Subclass of a dict that stores values for a Cache-Control header. It
has accessors for all the cache-control directives specified in RFC 2616.
The class does not differentiate between request and response directives.
Because the cache-control directives in the HTTP header use dashes the
python descriptors use underscores for that.
To get a header of the :class:`CacheControl` object again you can convert
the object into a string or call the :meth:`to_header` method. If you plan
to subclass it and add your own items have a look at the sourcecode for
that class.
.. versionchanged:: 3.1
Dict values are always ``str | None``. Setting properties will
convert the value to a string. Setting a non-bool property to
``False`` is equivalent to setting it to ``None``. Getting typed
properties will return ``None`` if conversion raises
``ValueError``, rather than the string.
.. versionchanged:: 2.1
Setting int properties such as ``max_age`` will convert the
value to an int.
.. versionchanged:: 0.4
Setting ``no_cache`` or ``private`` to ``True`` will set the
implicit value ``"*"``.
"""
no_store: bool = cache_control_property("no-store", None, bool)
max_age: int | None = cache_control_property("max-age", None, int)
no_transform: bool = cache_control_property("no-transform", None, bool)
stale_if_error: int | None = cache_control_property("stale-if-error", None, int)
def __init__(
self,
values: cabc.Mapping[str, t.Any] | cabc.Iterable[tuple[str, t.Any]] | None = (),
on_update: cabc.Callable[[_CacheControl], None] | None = None,
):
super().__init__(values, on_update)
self.provided = values is not None
def _get_cache_value(
self, key: str, empty: t.Any, type: type[t.Any] | None
) -> t.Any:
"""Used internally by the accessor properties."""
if type is bool:
return key in self
if key not in self:
return None
if (value := self[key]) is None:
return empty
if type is not None:
try:
value = type(value)
except ValueError:
return None
return value
def _set_cache_value(
self, key: str, value: t.Any, type: type[t.Any] | None
) -> None:
"""Used internally by the accessor properties."""
if type is bool:
if value:
self[key] = None
else:
self.pop(key, None)
elif value is None or value is False:
self.pop(key, None)
elif value is True:
self[key] = None
else:
if type is not None:
value = type(value)
self[key] = str(value)
def _del_cache_value(self, key: str) -> None:
"""Used internally by the accessor properties."""
if key in self:
del self[key]
def to_header(self) -> str:
"""Convert the stored values into a cache control header."""
return http.dump_header(self)
def __str__(self) -> str:
return self.to_header()
def __repr__(self) -> str:
kv_str = " ".join(f"{k}={v!r}" for k, v in sorted(self.items()))
return f"<{type(self).__name__} {kv_str}>"
cache_property = staticmethod(cache_control_property)
class RequestCacheControl(ImmutableDictMixin[str, t.Optional[str]], _CacheControl): # type: ignore[misc]
"""A cache control for requests. This is immutable and gives access
to all the request-relevant cache control headers.
To get a header of the :class:`RequestCacheControl` object again you can
convert the object into a string or call the :meth:`to_header` method. If
you plan to subclass it and add your own items have a look at the sourcecode
for that class.
.. versionchanged:: 3.1
Dict values are always ``str | None``. Setting properties will
convert the value to a string. Setting a non-bool property to
``False`` is equivalent to setting it to ``None``. Getting typed
properties will return ``None`` if conversion raises
``ValueError``, rather than the string.
.. versionchanged:: 3.1
``max_age`` is ``None`` if present without a value, rather
than ``-1``.
.. versionchanged:: 3.1
``no_cache`` is a boolean, it is ``True`` instead of ``"*"``
when present.
.. versionchanged:: 3.1
``max_stale`` is ``True`` if present without a value, rather
than ``"*"``.
.. versionchanged:: 3.1
``no_transform`` is a boolean. Previously it was mistakenly
always ``None``.
.. versionchanged:: 3.1
``min_fresh`` is ``None`` if present without a value, rather
than ``"*"``.
.. versionchanged:: 2.1
Setting int properties such as ``max_age`` will convert the
value to an int.
.. versionadded:: 0.5
Response-only properties are not present on this request class.
"""
no_cache: bool = cache_control_property("no-cache", None, bool)
max_stale: int | t.Literal[True] | None = cache_control_property(
"max-stale",
True,
int,
)
min_fresh: int | None = cache_control_property("min-fresh", None, int)
only_if_cached: bool = cache_control_property("only-if-cached", None, bool)
class ResponseCacheControl(_CacheControl):
"""A cache control for responses. Unlike :class:`RequestCacheControl`
this is mutable and gives access to response-relevant cache control
headers.
To get a header of the :class:`ResponseCacheControl` object again you can
convert the object into a string or call the :meth:`to_header` method. If
you plan to subclass it and add your own items have a look at the sourcecode
for that class.
.. versionchanged:: 3.1
Dict values are always ``str | None``. Setting properties will
convert the value to a string. Setting a non-bool property to
``False`` is equivalent to setting it to ``None``. Getting typed
properties will return ``None`` if conversion raises
``ValueError``, rather than the string.
.. versionchanged:: 3.1
``no_cache`` is ``True`` if present without a value, rather than
``"*"``.
.. versionchanged:: 3.1
``private`` is ``True`` if present without a value, rather than
``"*"``.
.. versionchanged:: 3.1
``no_transform`` is a boolean. Previously it was mistakenly
always ``None``.
.. versionchanged:: 3.1
Added the ``must_understand``, ``stale_while_revalidate``, and
``stale_if_error`` properties.
.. versionchanged:: 2.1.1
``s_maxage`` converts the value to an int.
.. versionchanged:: 2.1
Setting int properties such as ``max_age`` will convert the
value to an int.
.. versionadded:: 0.5
Request-only properties are not present on this response class.
"""
no_cache: str | t.Literal[True] | None = cache_control_property(
"no-cache", True, None
)
public: bool = cache_control_property("public", None, bool)
private: str | t.Literal[True] | None = cache_control_property(
"private", True, None
)
must_revalidate: bool = cache_control_property("must-revalidate", None, bool)
proxy_revalidate: bool = cache_control_property("proxy-revalidate", None, bool)
s_maxage: int | None = cache_control_property("s-maxage", None, int)
immutable: bool = cache_control_property("immutable", None, bool)
must_understand: bool = cache_control_property("must-understand", None, bool)
stale_while_revalidate: int | None = cache_control_property(
"stale-while-revalidate", None, int
)
# circular dependencies
from .. import http # noqa: E402