refactor(config): 日常读写改由 Daily 承担(声明层 + 接线) - #52
Open
LevelDownRefine wants to merge 27 commits into
Open
LevelDownRefine wants to merge 27 commits into
LevelDownRefine wants to merge 27 commits into
Conversation
safe_update / get_field / _scalar_kind 从 set_config.py 搬到 src/utils/utils_dict.py, 好让配置规则层(daily.Daily)也能用而不与 set_config 循环导入。函数体逐字节不变, 唯一差异是日志前缀随模块名([set_config] → [safe_update] / [get_field]),消息正文不变。
把「一个日常」从 7 个脚本子类的手写落点表里抽成对象:daily.Daily 解析自己的声明节点得出 落点(task_field / task_map / option_fields / options / 静态二级枚举),并出读写规则—— 只出规则、不碰盘(fields / write / read / read_enabled / set_enabled / section / section_exists 一律吃 dict 吐 dict/值),文件 I/O 仍归 ScriptConfig。声明表达不了的三类各一个子类: NoopDaily(绝区零/崩铁)、AnomalyDaily + AnomalyHunterDaily(异环两日常各一段 + 第二份文件 里的开关)、MaaDaily(TaskQueue / StagePlan)。 本步不接线(无生产调用方),配套 tests/test_daily.py 拿现有实现当独立裁判做差分验证: 落点逐字段对比现有落点读取器,写入/反读/开关逐组合(7 脚本 90 个组合)对比现有公开入口, 且都在同一份种子上跑、比全量 config。这组差分测试是临时脚手架,接线后由 golden 基线接管。
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ScriptConfig 不再手写落点,改为:_daily_cls / _daily_types / _daily_type / _build_dailies / _dispatch_daily 按声明构造日常对象;set_daily_task / set_daily_enabled / _read_daily_enabled / _read_daily_tasks 四个入口全部退化成「读盘 → 交给日常 → 有改动才落盘」(文件 I/O 仍只在这一层)。 删掉 7 个子类的手写落点表与覆写:_task_key / _task_map / _update_task / _read_daily_task / set_daily_task(绝区零/崩铁 log、原神/终末地 预归一)/ NTE 的段与 Routine Items 读写 / set_daily_enabled / _read_daily_enabled,以及 _daily_section_dict / _routine_item / _write_routine_enabled / _daily_physical_name。task_config.get_daily_configs 从「落点 dict」 改为「该脚本的日常声明列表」,get_daily_config(单数)随之删除。 顺带两处收益: - _read_daily_tasks 一次读盘(主 config 与开关文件各一次,分发给各日常):异环反读 4→2 次读盘, 单日常脚本 2→1; - get_daily_options(菜单)直接取 Daily.options,与写入侧同源对象。 行为等价由 golden 基线(tests/golden/daily_baseline.json,本步未改动)守住:菜单内容、每个 (日常, 一级项, 二级项) 的落盘结果、反读记录三段逐项一致。tests/test_daily.py 收敛为 Daily 自身的语义;原差分验证的裁判(_update_task 等)随本步删除,故其差分部分一并收敛。
一个日常一个类(日常数 = 类数 = 实例数):共同部分(取自己那段 + 第二份文件的开关读写) 提到 SegmentedDaily,AnomalyDaily / AnomalyHunterDaily 各只留类名与说明 —— 相比接线时那版, 不再有 87 行逐字重复,且每个日常有自己命名的类作为将来分歧的落点。绑定写回脚本级 _daily_types(按日常展示名,与声明主键一致)。 _daily_types 非空时加一致性断言:必须与声明里的日常一一对应(多一个少一个都报错)—— 既是「有多少个日常就有多少个类」这条不变量的可执行形式,也堵住了表外日常静默落到 基类 Daily(把副本写进顶层 config、不报错)的隐患。
LevelDownRefine
force-pushed
the
refactor/daily-object
branch
from
September 13, 2026 14:43
9519719 to
98f1c8f
Compare
一个机制代替两个:每个脚本都填「日常展示名 → 实现类」(单日常脚本也就是一行), 日常数 = 类数。随之删掉 _daily_cls 与它的回落分支,_build_dailies 的一致性断言变成 无条件 —— 声明里多一个日常而没配类时直接报错(原先会静默回落到基类 Daily)。 菜单(get_daily_options)反向调整:它只用声明 + 基类 Daily 解析,不经 _daily_types —— 菜单只需要声明(有哪些日常、各有那些选项),声明里新增日常时照常显示;落点才需要类 (要按该日常的读写机制来)。这样「加日常」仍只是改声明,界面立刻能显示,而写入不会 悄悄写错位置。
7 个脚本都已各自声明,基类那个空表默认只会让人以为「可以不给」——漏声明时会静默拿空表, 报出来的是「与声明的日常不一致」,读着像数据问题而不是漏声明。改成裸注解(无默认值), 并在 _build_dailies 里显式校验:漏声明直接说「未声明 _daily_types」。新增 1 例用例钉住。
每个日常一个实现类、身份(展示名)由类自带:daily_display_name。于是 config 里不再重复 写名字 —— _daily_types 从「名 → 类」的表改成类的元组,名字只由类给;_build_dailies 按类 身份与声明一一对应(类缺身份、身份重复、与声明对不上,三者都 assert)。 6 个单日常脚本也各建一个类(WutheringWavesDaily / GenshinDaily / EndfieldDaily / ZenlessZoneZeroDaily / StarRailDaily / ArknightsDaily,各三行:docstring + 身份),异环两个 (AnomalyDaily / AnomalyHunterDaily,各继承 SegmentedDaily)。这些类紧挨各自 config 定义; daily.py 只留机制类(Daily / NoopDaily / SegmentedDaily / MaaDaily)。
get_weekly_map 输出物化声明节点(不再产 {name, tasks} 旧形状);
顺带修 _materialize_daily 日常级 source 组缺 values 的 KeyError。
update/read 改收整份 config;NoopDaily 覆写 update 恒无改动, 类型检查消失;set_daily_task 退化为读盘→update→有改动才落盘。
_daily_types 元组改单个 _daily_type(默认 Daily);8 个身份子类删除; daily_display_name 类属性删除,名字只来自声明;形状解析归各机制类。
Daily 构造接管所属 ScriptConfig(路径/display_name/_load/_save); update/read/set_enabled 各自完成读盘→改内存→有改动才落盘的闭环。
_daily_type/_daily_flat_type 按两层/单层选类,跨日常混用合法; 单层带 key 的解析/反读归 AnomalyHunterDaily;_dailies_cache 改名 _dailies_data。
声明标注机制类(DAILY_CLASSES 注册表查表),config 子类零日常配置; 物化时剥离 class;utils_config 测试改单变量环境还原,避开本机超长变量。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
日常配置重构 P4:把「一个日常」抽成
Daily对象,并把读写接到它上面。13 文件 / +1390 −1191(净减约 600 行)/ 7 commit。行为等价由 P3 的 golden 基线守住 —— 关键证据是:
tests/golden/daily_baseline.json本步一行未改,而 golden 测试仍绿(菜单内容、每个 (日常, 一级项, 二级项) 的落盘结果、反读记录三段逐项一致)。设计:
Daily只出规则、不碰盘从 7 个脚本子类的手写落点表里抽出「一个日常」:
Dailyname/physical_name/options/task_field/task_map/option_fields(+_sequence_values/_sequence_required/_single_field);出读写规则fields/write/read/read_enabled/set_enabled/section/section_exists—— 一律「吃 dict 吐 dict/值」,不认识ScriptConfigNoopDailySegmentedDailyMaaDailyTaskQueue/StagePlan+ 借槽改写每个日常一个类,身份写在类上(
daily_display_name)。7 个脚本共 8 个日常类,类定义紧挨各自 config:于是 config 里的绑定不再重复写名字 ——
_daily_types是类的元组((AnomalyDaily, AnomalyHunterDaily)),名字只由类给;_build_dailies按类身份与声明一一对应:类缺daily_display_name/身份重复/与声明对不上,三者都 assert。这就是「日常数 = 类数 = 实例数」的可执行形式。daily.py只留机制类(Daily/NoopDaily/SegmentedDaily/MaaDaily),各脚本的日常类在set_config.py里各自 config 旁边。菜单只用声明:
get_daily_options用声明 + 基类Daily解析,不经_daily_types。菜单只需要"有哪些日常、各有那些选项"(声明就够),落点才需要类(要按该日常的读写机制来)。所以「加一个日常」仍是改声明即可在界面出现;写入若没配类则当场报错,而不是悄悄写错位置。文件 I/O(路径、两份文件、
_verify_saved)全部留在ScriptConfig(唯一碰盘的一层)——所以daily.py → set_config不存在(也不需要TYPE_CHECKING绕环)。commit
refactor(config): 抽出字段工具到 utils_dict——safe_update/get_field/_scalar_kind搬到src/utils/utils_dict.py。理由是硬的:Daily要用,而daily.py → set_config会成环。纯搬:机器验证「main 原文切片 vs 新模块体,前缀归一后逐字节相同」= True,唯一差异是日志前缀随模块名,消息正文不变。refactor(config): 加 Daily 规则对象(声明层)——src/config/daily.py。此 commit 单独看是「新增模块」,等价性由下面那组差分测试证明。refactor(config): 日常读写改由 Daily 承担(接线)——ScriptConfig的_build_dailies/_dispatch_daily/_daily_types;四个入口(set_daily_task/set_daily_enabled/_read_daily_enabled/_read_daily_tasks)退化成「读盘 → 交给日常 → 有改动才落盘」;删掉 7 个子类全部手写落点表与覆写(_task_key/_task_map/_update_task/_read_daily_task/set_daily_task/ NTE 的段与 Routine Items 读写 /_daily_section_dict/_routine_item/_write_routine_enabled/_daily_physical_name)。task_config.get_daily_configs从「落点 dict」改为「该脚本的日常声明列表」,单数的get_daily_config随之删除 —— 这顺带解掉了上一步留下的命名问题:现在「单数=一份声明 / 复数=该脚本全部声明」是同一件事的两个数。refactor(config): 异环两个日常各一个类,共同实现留在 SegmentedDaily—— review 提出「每个日常应该有自己的类」。原状是两个类各写一遍(AST 去 docstring 后逐字相同,差 0 行),所以按「一个日常一个类 + 共同实现只留一份」重排:共同部分(取自己那段 + 第二份文件的开关读写)提到SegmentedDaily,两个日常类各只留自己的身份。refactor(config): _daily_types 覆盖每个脚本,删掉 _daily_cls—— 之前是「特例脚本填_daily_types、普通脚本填_daily_cls(3 个脚本连这行都没写、吃基类默认Daily)」两套写法。现在一个机制:每个脚本都填表、每个日常一个类;_daily_cls及其回落分支删除,一致性断言随之变成无条件。refactor(config): _daily_types 去掉基类默认值—— 7 个脚本都已各自声明,基类那个空表默认只会让人以为「可以不给」(漏声明时拿空表,报出来的是「与声明的日常不一致」,读着像数据问题)。改成裸注解(无默认值)+_build_dailies显式校验,漏声明直接报「未声明_daily_types」。refactor(config): 日常的身份写在类上,每个日常一个类—— review 指出「区分日常应该靠类,类有自己的属性」:于是_daily_types从「名 → 类」的表改成类的元组(config 不再重复写名字),身份由类自带的daily_display_name给出;6 个单日常脚本也各建一个类,daily.py只留机制类。两处顺带收益:
_read_daily_tasks一次读盘(主 config 与开关文件各一次,再分发给各日常):异环反读 4→2 次读盘、单日常脚本 2→1;自证
行为等价(golden 未改仍绿)之外,接线前另有一组差分验证:拿现有实现当独立裁判 —— 落点对比现有落点读取器;写入对比
cfg.set_daily_task(用公开入口而非_update_task,因为子类会预归一:原神把「二级 or 一级」当一级传);反读/开关对比_read_daily_task/_read_daily_enabled/set_daily_enabled(含「无变化即不落盘」的判定)。范围 7 脚本 × 90 个组合、两边跑同一份种子、比全量 config。变异验证:对daily.py做 4 处定向变异(落点解析 / 写入 / 反读 / 开关)→ 四组测试各组独立报红(failures=4/1/1/1),还原即 OK。该差分部分的裁判(
_update_task等)就是本步删掉的东西,故它随本步收敛为Daily自身的语义测试;端到端等价改由 golden 永久接管(PR 正文预先声明,不是事后找补)。测试方法数 −23 / +28:删掉的是「落点手写表」与那组差分用例(其裁判已不存在),新增的是
Daily的单元用例与「_daily_types必须覆盖声明」那条不变量的用例(含逐脚本断言「日常数 = 类数」)。一处 API 收紧(唯一的行为变化,请留意)
set_daily_task(daily_display_name, task_name, sequence)现在要求task_name是一级项、sequence是二级项。旧实现里 原神/终末地 的子类会把「二级名当一级传」预归一(target = sequence or task_name),新实现没有了这层兜底 —— 因为Daily.options/option_fields是层级数据,必须按菜单层级传。已核实不影响用户可见路径:仓库里没有
--task/--sequenceCLI 参数(cli.py只传weekly_start),GUI 从菜单下行本就直接给 (一级项, 二级项)。受影响的只有tests/test_endfield_config_safety.py里那两处旧写法(本步已按新 API 改)。本步不做(下一步 = P5 菜单链)
src/config/set_config.md的日常段(连同gui/README.md/service/README.md/CONVENTIONS.md里的相关句)现在描述的还是已被删除的 API(_update_task/_daily_tasks/_task_key/_daily_physical_name/ 落点读取器),18 处引用失效。文档重写之所以再往后挪一步:P5 要动的正是这份文档描述的 API(
daily_config.get_daily_map()的形状、get_daily_options的有无)。先写文档 = 写两遍。所以顺序是 本 PR 合入 → P5(菜单链收成一层)→ 文档。如果你更希望文档同 PR 一起进,我立刻补上,只是本 PR 会变大。