- 新增图像生成接口,支持试用、积分和自定义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): 添加示例系统日志文件 - 记录用户请求、验证码发送成功与失败的日志信息
221 lines
7.9 KiB
Python
221 lines
7.9 KiB
Python
# event/api.py
|
|
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
|
# <see AUTHORS file>
|
|
#
|
|
# This module is part of SQLAlchemy and is released under
|
|
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
|
|
|
"""Public API functions for the event system."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
from typing import Callable
|
|
|
|
from .base import _registrars
|
|
from .registry import _ET
|
|
from .registry import _EventKey
|
|
from .registry import _ListenerFnType
|
|
from .. import exc
|
|
from .. import util
|
|
|
|
|
|
CANCEL = util.symbol("CANCEL")
|
|
NO_RETVAL = util.symbol("NO_RETVAL")
|
|
|
|
|
|
def _event_key(
|
|
target: _ET, identifier: str, fn: _ListenerFnType
|
|
) -> _EventKey[_ET]:
|
|
for evt_cls in _registrars[identifier]:
|
|
tgt = evt_cls._accept_with(target, identifier)
|
|
if tgt is not None:
|
|
return _EventKey(target, identifier, fn, tgt)
|
|
else:
|
|
raise exc.InvalidRequestError(
|
|
"No such event '%s' for target '%s'" % (identifier, target)
|
|
)
|
|
|
|
|
|
def listen(
|
|
target: Any, identifier: str, fn: Callable[..., Any], *args: Any, **kw: Any
|
|
) -> None:
|
|
"""Register a listener function for the given target.
|
|
|
|
The :func:`.listen` function is part of the primary interface for the
|
|
SQLAlchemy event system, documented at :ref:`event_toplevel`.
|
|
|
|
e.g.::
|
|
|
|
from sqlalchemy import event
|
|
from sqlalchemy.schema import UniqueConstraint
|
|
|
|
|
|
def unique_constraint_name(const, table):
|
|
const.name = "uq_%s_%s" % (table.name, list(const.columns)[0].name)
|
|
|
|
|
|
event.listen(
|
|
UniqueConstraint, "after_parent_attach", unique_constraint_name
|
|
)
|
|
|
|
:param bool insert: The default behavior for event handlers is to append
|
|
the decorated user defined function to an internal list of registered
|
|
event listeners upon discovery. If a user registers a function with
|
|
``insert=True``, SQLAlchemy will insert (prepend) the function to the
|
|
internal list upon discovery. This feature is not typically used or
|
|
recommended by the SQLAlchemy maintainers, but is provided to ensure
|
|
certain user defined functions can run before others, such as when
|
|
:ref:`Changing the sql_mode in MySQL <mysql_sql_mode>`.
|
|
|
|
:param bool named: When using named argument passing, the names listed in
|
|
the function argument specification will be used as keys in the
|
|
dictionary.
|
|
See :ref:`event_named_argument_styles`.
|
|
|
|
:param bool once: Private/Internal API usage. Deprecated. This parameter
|
|
would provide that an event function would run only once per given
|
|
target. It does not however imply automatic de-registration of the
|
|
listener function; associating an arbitrarily high number of listeners
|
|
without explicitly removing them will cause memory to grow unbounded even
|
|
if ``once=True`` is specified.
|
|
|
|
:param bool propagate: The ``propagate`` kwarg is available when working
|
|
with ORM instrumentation and mapping events.
|
|
See :class:`_ormevent.MapperEvents` and
|
|
:meth:`_ormevent.MapperEvents.before_mapper_configured` for examples.
|
|
|
|
:param bool retval: This flag applies only to specific event listeners,
|
|
each of which includes documentation explaining when it should be used.
|
|
By default, no listener ever requires a return value.
|
|
However, some listeners do support special behaviors for return values,
|
|
and include in their documentation that the ``retval=True`` flag is
|
|
necessary for a return value to be processed.
|
|
|
|
Event listener suites that make use of :paramref:`_event.listen.retval`
|
|
include :class:`_events.ConnectionEvents` and
|
|
:class:`_ormevent.AttributeEvents`.
|
|
|
|
.. note::
|
|
|
|
The :func:`.listen` function cannot be called at the same time
|
|
that the target event is being run. This has implications
|
|
for thread safety, and also means an event cannot be added
|
|
from inside the listener function for itself. The list of
|
|
events to be run are present inside of a mutable collection
|
|
that can't be changed during iteration.
|
|
|
|
Event registration and removal is not intended to be a "high
|
|
velocity" operation; it is a configurational operation. For
|
|
systems that need to quickly associate and deassociate with
|
|
events at high scale, use a mutable structure that is handled
|
|
from inside of a single listener.
|
|
|
|
.. seealso::
|
|
|
|
:func:`.listens_for`
|
|
|
|
:func:`.remove`
|
|
|
|
"""
|
|
|
|
_event_key(target, identifier, fn).listen(*args, **kw)
|
|
|
|
|
|
def listens_for(
|
|
target: Any, identifier: str, *args: Any, **kw: Any
|
|
) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
|
|
"""Decorate a function as a listener for the given target + identifier.
|
|
|
|
The :func:`.listens_for` decorator is part of the primary interface for the
|
|
SQLAlchemy event system, documented at :ref:`event_toplevel`.
|
|
|
|
This function generally shares the same kwargs as :func:`.listen`.
|
|
|
|
e.g.::
|
|
|
|
from sqlalchemy import event
|
|
from sqlalchemy.schema import UniqueConstraint
|
|
|
|
|
|
@event.listens_for(UniqueConstraint, "after_parent_attach")
|
|
def unique_constraint_name(const, table):
|
|
const.name = "uq_%s_%s" % (table.name, list(const.columns)[0].name)
|
|
|
|
A given function can also be invoked for only the first invocation
|
|
of the event using the ``once`` argument::
|
|
|
|
@event.listens_for(Mapper, "before_configure", once=True)
|
|
def on_config():
|
|
do_config()
|
|
|
|
.. warning:: The ``once`` argument does not imply automatic de-registration
|
|
of the listener function after it has been invoked a first time; a
|
|
listener entry will remain associated with the target object.
|
|
Associating an arbitrarily high number of listeners without explicitly
|
|
removing them will cause memory to grow unbounded even if ``once=True``
|
|
is specified.
|
|
|
|
.. seealso::
|
|
|
|
:func:`.listen` - general description of event listening
|
|
|
|
"""
|
|
|
|
def decorate(fn: Callable[..., Any]) -> Callable[..., Any]:
|
|
listen(target, identifier, fn, *args, **kw)
|
|
return fn
|
|
|
|
return decorate
|
|
|
|
|
|
def remove(target: Any, identifier: str, fn: Callable[..., Any]) -> None:
|
|
"""Remove an event listener.
|
|
|
|
The arguments here should match exactly those which were sent to
|
|
:func:`.listen`; all the event registration which proceeded as a result
|
|
of this call will be reverted by calling :func:`.remove` with the same
|
|
arguments.
|
|
|
|
e.g.::
|
|
|
|
# if a function was registered like this...
|
|
@event.listens_for(SomeMappedClass, "before_insert", propagate=True)
|
|
def my_listener_function(*arg):
|
|
pass
|
|
|
|
|
|
# ... it's removed like this
|
|
event.remove(SomeMappedClass, "before_insert", my_listener_function)
|
|
|
|
Above, the listener function associated with ``SomeMappedClass`` was also
|
|
propagated to subclasses of ``SomeMappedClass``; the :func:`.remove`
|
|
function will revert all of these operations.
|
|
|
|
.. note::
|
|
|
|
The :func:`.remove` function cannot be called at the same time
|
|
that the target event is being run. This has implications
|
|
for thread safety, and also means an event cannot be removed
|
|
from inside the listener function for itself. The list of
|
|
events to be run are present inside of a mutable collection
|
|
that can't be changed during iteration.
|
|
|
|
Event registration and removal is not intended to be a "high
|
|
velocity" operation; it is a configurational operation. For
|
|
systems that need to quickly associate and deassociate with
|
|
events at high scale, use a mutable structure that is handled
|
|
from inside of a single listener.
|
|
|
|
.. seealso::
|
|
|
|
:func:`.listen`
|
|
|
|
"""
|
|
_event_key(target, identifier, fn).remove()
|
|
|
|
|
|
def contains(target: Any, identifier: str, fn: Callable[..., Any]) -> bool:
|
|
"""Return True if the given target/ident/fn is set up to listen."""
|
|
|
|
return _event_key(target, identifier, fn).contains()
|