mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-30 04:27:40 +08:00
- notification 域:渠道能力(MessageChannel→NotificationChannel、ChannelCapability* 迁入 notification.py) - message 域:消息收发(Notification→Message、NotificationType→MessageType、CommingMessage→IncomingMessage、NotificationHistoryItem→MessageHistoryItem、NotificationClear*→MessageClear*) - Agent 工具契约:send_notification_message→send_message、notification_callback→message_callback - 源码不保留旧名物理别名,旧导入经 app/runtime/compat/manifest.py SYMBOL_ALIASES 惰性解析 - API 路径与持久化键冻结不变,前端零改动 - 新增兼容守护测试与 docs/rules/07 命名边界规范
6.3 KiB
6.3 KiB
07 — Naming Conventions
All new code must follow these conventions. Consistent naming is how the codebase communicates intent without comments.
Files
| Context | Convention | Examples |
|---|---|---|
| Python source files | snake_case.py |
download.py, qbittorrent.py, package.py |
| New files in canonical capability packages | Focused snake_case.py; prefer a package-owned noun and an existing owned domain file before adding one |
torrent.py, plugin_manager.py, package.py |
| Module package directories | snake_case/ |
qbittorrent/, synologychat/ |
| Test files | test_<domain>.py |
test_download_chain.py, test_subscribe_endpoint.py |
| Alembic migrations | Auto-generated by Alembic; do not rename | 20240101_add_column.py |
| Skill directories | <kebab-case>/ |
transfer-failed-retry/, moviepilot-cli/ |
Classes
| Context | Convention | Examples |
|---|---|---|
| Chain classes | <Domain>Chain |
DownloadChain, SearchChain, SubscribeChain |
| Module classes | <Backend>Module |
QbittorrentModule, EmbyModule, TelegramModule |
| Oper (data access) classes | <Model>Oper |
SubscribeOper, SystemConfigOper, TransferHistoryOper |
| Helper classes | <Domain>Helper |
TorrentHelper, DirectoryHelper, MessageHelper |
| Pydantic schema models | PascalCase, noun-focused |
MediaInfo, TorrentInfo, DownloadingTorrent |
| SQLAlchemy model classes | PascalCase, singular noun |
Subscribe, TransferHistory, SystemConfig |
| Enum classes | PascalCase |
MediaType, EventType, ModuleType |
| Manager classes | <Domain>Manager |
ModuleManager, PluginManager, EventManager |
| General classes | PascalCase |
MetaInfo, Context, ChainBase |
Functions and Methods
| Context | Convention | Examples |
|---|---|---|
| All functions and methods | snake_case |
get_subscribe, run_module, on_config_changed |
| Private methods | _snake_case (leading underscore) |
_submit_download_added_task, _parse_result |
| Event handler methods | on_<event_name> or descriptive |
on_transfer_complete, handle_config_changed |
| Module interface methods | Match _ModuleBase contract |
init_module, init_setting, get_name, get_type, test, stop |
| Oper methods | Verb + noun | get, add, update, delete, list |
Variables and Parameters
| Context | Convention | Examples |
|---|---|---|
| Local variables | snake_case |
torrent_info, media_type, download_dir |
| Instance attributes | snake_case |
self.download_history, self.config |
| Constants (module-level) | UPPER_SNAKE_CASE |
DEFAULT_EVENT_PRIORITY, MIN_EVENT_CONSUMER_THREADS |
| Private variables | _snake_case (leading underscore) |
_instance, _lock |
| Type variables | PascalCase with TypeVar |
T = TypeVar("T") |
Enums
| Context | Convention | Examples |
|---|---|---|
| Enum class name | PascalCase |
MediaType, TorrentStatus, EventType |
| Enum members | PascalCase (for complex enums) |
MediaType.MOVIE, EventType.TransferComplete |
| String enum values | Match the domain language | MediaType.MOVIE = '电影', TorrentStatus.TRANSFER = '可转移' |
SystemConfigKey values |
Match the config key as a string | SystemConfigKey.RssUrls = "RssUrls" |
Configuration and Settings
| Context | Convention | Examples |
|---|---|---|
Settings / ConfigModel fields |
UPPER_SNAKE_CASE |
API_TOKEN, LLM_MODEL, QB_HOST |
SystemConfigKey enum members |
PascalCase |
SystemConfigKey.RssUrls, SystemConfigKey.SubscribeFilter |
| Environment variable names | UPPER_SNAKE_CASE |
AI_AGENT_ENABLE, DB_TYPE |
API Endpoints and Routers
| Context | Convention | Examples |
|---|---|---|
| Endpoint function names | snake_case, verb-first |
get_subscribe_list, add_download, delete_history |
| URL path segments | kebab-case or snake_case matching existing patterns |
/api/v1/subscribe, /api/v1/transfer/history |
| Router tags | Match the resource domain name | "subscribe", "download", "media" |
Message / Notification Domain Boundary
message 与 notification 是两个不同的语义域,新增或修改相关代码时必须按职责选名,不得混用:
| 语义域 | 职责 | 规范命名示例 |
|---|---|---|
notification |
通知渠道能力:渠道枚举、渠道配置、渠道发现、渠道管理、渠道能力描述 | NotificationChannel, NotificationConf, NotificationHelper, NotificationChain, NotificationAction, ChannelCapabilityManager, ModuleType.Notification, channel_manage |
message |
各渠道发送或接收的消息:消息体、消息类型、消息链、消息历史、消息队列 | Message, MessageType, IncomingMessage, MessageChain, MessageHistoryItem, MessageOper, post_message, message_parser |
| 规则 | 说明 |
|---|---|
| 渠道本身用 notification | 渠道是能力提供方,如 NotificationChannel 枚举、NotificationConf 渠道配置 |
| 消息内容与收发用 message | 消息是被传输的内容,如发送体 Message、接收体 IncomingMessage、分类 MessageType |
| 渠道 × 消息的交叉概念按主导方判断 | 按渠道控制消息开关的 NotificationSwitch 属渠道能力;消息历史清理 MessageClearScope 属消息 |
| 历史旧名不在源码保留 | Notification、MessageChannel、NotificationType、CommingMessage 等旧名仅登记在 app/runtime/compat/manifest.py 的 SYMBOL_ALIASES,新代码一律使用规范名 |
| 持久化值与外部协议冻结 | 枚举值、SystemConfigKey 配置值、DB 表名、API 路径、外部平台字段(如 Jellyfin 的 NotificationType)不随命名统一变更 |
Anti-Patterns
| Wrong | Correct |
|---|---|
class downloadchain: |
class DownloadChain: |
class QBModule: |
class QbittorrentModule: |
def GetSubscribe(): |
def get_subscribe(): |
TORRENT_info = ... |
torrent_info = ... |
def handleConfigChanged(): |
def on_config_changed(): or def handle_config_changed(): |
SystemConfigOper().get("RssUrls") |
SystemConfigOper().get(SystemConfigKey.RssUrls) |
class subscribe_oper: |
class SubscribeOper: |
MessageChannel.Telegram(新代码) |
NotificationChannel.Telegram |
Notification(title=...)(新代码) |
Message(title=...) |
Last Updated: 2026-08-16