Files
MoviePilot/docs/rules/07-naming-conventions.md

8.1 KiB
Raw Permalink Blame History

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 Prefer one lowercase responsibility noun; extend an existing owner before adding a sibling file torrent.py, package.py, resources.py
Multi-file capabilities Create a same-named package and use focused single-word child files; do not flatten related <capability>_<role>.py siblings transfer/workflow.py, transfer/execution.py
Module package directories snake_case/; package roots do not duplicate-export host implementations qbittorrent/, synologychat/, transfer/
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/

Production Module Creation Gate

新增或拆分生产模块时必须按以下顺序决策,代码评审与架构测试以此为准:

  1. 优先扩展当前职责 owner;只因文件变长或需要一个私有辅助类,不得新建平级模块。
  2. 一个能力需要第二个生产文件时,必须在同一次变更中改为同名目录包,禁止继续增加 <capability>_<role>.py 平级文件。
  3. 包内子文件使用准确、可独立说明职责的单个小写名词,如 dependencies/profile.py 与 dependencies/native.py;不得使用 native_dependencies.py、transfer_execution.py 这类重复能力名。
  4. 包根 __init__.py 只允许包说明和确有外部契约证据的公开门面,不得复制实现,也不得为宿主代码重复导出子模块符号;宿主必须直接导入 owner 子模块。
  5. 旧路径兼容只能在确认真实插件消费者后,通过 app/sdk/ 或 app/runtime/compat/ 做精确映射;不得为假设消费者保留旧源码、通配映射或双份导出。
  6. 新增文件前必须同步更新本规则对应的机器门禁;若现有门禁不能表达该命名约束,应在同一变更中补充 tests/test_architecture_dependencies.py。

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():
configuration.get("RssUrls") configuration.get(SystemConfigKey.RssUrls)
class subscribe_oper: class SubscribeOper:
transfer.py + transfer_execution.py transfer/workflow.py + transfer/execution.py
dependencies.py + native_dependencies.py dependencies/profile.py + dependencies/native.py
Package-root host re-exports for an old path Exact SDK/Compat mapping; host code imports the owning child module
MessageChannel.Telegram(新代码) NotificationChannel.Telegram
Notification(title=...)(新代码) Message(title=...)

Last Updated: 2026-08-29