mopr 0.0.67__tar.gz → 0.0.69.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. {mopr-0.0.67 → mopr-0.0.69.dev0}/AGENTS.md +37 -0
  2. {mopr-0.0.67 → mopr-0.0.69.dev0}/BUILDING.md +2 -2
  3. {mopr-0.0.67 → mopr-0.0.69.dev0}/CHANGELOG.md +239 -1
  4. {mopr-0.0.67 → mopr-0.0.69.dev0}/CONTRIBUTING.md +8 -2
  5. {mopr-0.0.67/mopr.egg-info → mopr-0.0.69.dev0}/PKG-INFO +20 -5
  6. {mopr-0.0.67 → mopr-0.0.69.dev0}/README.md +19 -4
  7. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/__init__.py +5 -1
  8. mopr-0.0.69.dev0/base/mmap.md +150 -0
  9. mopr-0.0.69.dev0/base/mmap.py +252 -0
  10. mopr-0.0.69.dev0/base/mmap_test.py +230 -0
  11. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/state_store.py +19 -34
  12. mopr-0.0.69.dev0/encoding/README.md +142 -0
  13. mopr-0.0.69.dev0/encoding/__init__.py +27 -0
  14. mopr-0.0.69.dev0/encoding/charsets.py +55 -0
  15. {mopr-0.0.67 → mopr-0.0.69.dev0}/encoding/csv.md +7 -7
  16. {mopr-0.0.67 → mopr-0.0.69.dev0}/encoding/json.md +4 -4
  17. {mopr-0.0.67 → mopr-0.0.69.dev0}/encoding/yaml.md +11 -11
  18. {mopr-0.0.67 → mopr-0.0.69.dev0/mopr.egg-info}/PKG-INFO +20 -5
  19. {mopr-0.0.67 → mopr-0.0.69.dev0}/mopr.egg-info/SOURCES.txt +26 -0
  20. mopr-0.0.69.dev0/mopr.egg-info/scm_file_list.json +188 -0
  21. mopr-0.0.69.dev0/mopr.egg-info/scm_version.json +8 -0
  22. {mopr-0.0.67 → mopr-0.0.69.dev0}/pyproject.toml +5 -0
  23. {mopr-0.0.67 → mopr-0.0.69.dev0}/python/_version.py +3 -3
  24. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/once.md +2 -2
  25. mopr-0.0.69.dev0/security/README.md +4 -0
  26. mopr-0.0.69.dev0/security/__init__.py +19 -0
  27. mopr-0.0.69.dev0/security/audit/README.md +1 -0
  28. mopr-0.0.69.dev0/security/auth/README.md +252 -0
  29. mopr-0.0.69.dev0/security/auth/__init__.py +72 -0
  30. mopr-0.0.69.dev0/security/auth/authorize.py +64 -0
  31. mopr-0.0.69.dev0/security/auth/catalog.py +195 -0
  32. mopr-0.0.69.dev0/security/auth/credential.py +137 -0
  33. mopr-0.0.69.dev0/security/auth/credential_test.py +159 -0
  34. mopr-0.0.69.dev0/security/auth/errors.py +48 -0
  35. mopr-0.0.69.dev0/security/auth/model.py +265 -0
  36. mopr-0.0.69.dev0/security/auth/principal.py +121 -0
  37. mopr-0.0.69.dev0/security/auth/rbac_test.py +340 -0
  38. mopr-0.0.69.dev0/security/auth/session.py +196 -0
  39. mopr-0.0.69.dev0/security/auth/session_test.py +222 -0
  40. mopr-0.0.69.dev0/security/auth/spi.py +114 -0
  41. mopr-0.0.69.dev0/security/auth/token.py +141 -0
  42. mopr-0.0.69.dev0/security/auth/token_test.py +115 -0
  43. mopr-0.0.69.dev0/security/compliance/README.md +1 -0
  44. mopr-0.0.69.dev0/spec/api.md +24 -0
  45. mopr-0.0.69.dev0/spec/behavior.md +24 -0
  46. {mopr-0.0.67 → mopr-0.0.69.dev0}/storage/storage.md +2 -2
  47. mopr-0.0.67/encoding/__init__.py +0 -21
  48. mopr-0.0.67/mopr.egg-info/scm_file_list.json +0 -122
  49. mopr-0.0.67/mopr.egg-info/scm_version.json +0 -8
  50. {mopr-0.0.67 → mopr-0.0.69.dev0}/.clang-format +0 -0
  51. {mopr-0.0.67 → mopr-0.0.69.dev0}/.clang-tidy +0 -0
  52. {mopr-0.0.67 → mopr-0.0.69.dev0}/.clangd +0 -0
  53. {mopr-0.0.67 → mopr-0.0.69.dev0}/.editorconfig +0 -0
  54. {mopr-0.0.67 → mopr-0.0.69.dev0}/.gitattributes +0 -0
  55. {mopr-0.0.67 → mopr-0.0.69.dev0}/.githooks/commit-msg +0 -0
  56. {mopr-0.0.67 → mopr-0.0.69.dev0}/.gitignore +0 -0
  57. {mopr-0.0.67 → mopr-0.0.69.dev0}/.vscode-default/settings.json +0 -0
  58. {mopr-0.0.67 → mopr-0.0.69.dev0}/.vscode-default/tasks.json +0 -0
  59. {mopr-0.0.67 → mopr-0.0.69.dev0}/.vscode-macos/settings.json +0 -0
  60. {mopr-0.0.67 → mopr-0.0.69.dev0}/.vscode-macos/tasks.json +0 -0
  61. {mopr-0.0.67 → mopr-0.0.69.dev0}/.vscode-windows/launch.json +0 -0
  62. {mopr-0.0.67 → mopr-0.0.69.dev0}/.vscode-windows/settings.json +0 -0
  63. {mopr-0.0.67 → mopr-0.0.69.dev0}/.vscode-windows/tasks.json +0 -0
  64. {mopr-0.0.67 → mopr-0.0.69.dev0}/LICENSE +0 -0
  65. {mopr-0.0.67 → mopr-0.0.69.dev0}/MANIFEST.in +0 -0
  66. {mopr-0.0.67 → mopr-0.0.69.dev0}/THIRD_PARTY_NOTICES.md +0 -0
  67. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/cron.md +0 -0
  68. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/cron.py +0 -0
  69. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/dataclass_utils.py +0 -0
  70. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/environment.py +0 -0
  71. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/filesystem.py +0 -0
  72. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/region.md +0 -0
  73. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/region.py +0 -0
  74. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/strings.md +0 -0
  75. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/strings.py +0 -0
  76. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/time.py +0 -0
  77. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/timestamp.md +0 -0
  78. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/timestamp.py +0 -0
  79. {mopr-0.0.67 → mopr-0.0.69.dev0}/base/types.py +0 -0
  80. {mopr-0.0.67 → mopr-0.0.69.dev0}/benchmark/README.md +0 -0
  81. {mopr-0.0.67 → mopr-0.0.69.dev0}/benchmark/macro/README.md +0 -0
  82. {mopr-0.0.67 → mopr-0.0.69.dev0}/benchmark/regression/README.md +0 -0
  83. {mopr-0.0.67 → mopr-0.0.69.dev0}/benchmark/stability/README.md +0 -0
  84. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/__init__.py +0 -0
  85. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/FileStateStore.java +0 -0
  86. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/Generator.java +0 -0
  87. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/HLC.java +0 -0
  88. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/Id.java +0 -0
  89. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/Option.java +0 -0
  90. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/PersistentState.java +0 -0
  91. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/README.md +0 -0
  92. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/StateStore.java +0 -0
  93. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/__init__.py +0 -0
  94. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/generator.py +0 -0
  95. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/hlc.py +0 -0
  96. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/id.py +0 -0
  97. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/option.py +0 -0
  98. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/queue.py +0 -0
  99. {mopr-0.0.67 → mopr-0.0.69.dev0}/distributed/id/tests.py +0 -0
  100. {mopr-0.0.67 → mopr-0.0.69.dev0}/encoding/csv.py +0 -0
  101. {mopr-0.0.67 → mopr-0.0.69.dev0}/encoding/yaml.py +0 -0
  102. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/__init__.py +0 -0
  103. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/exchange/README.md +0 -0
  104. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/exchange/__init__.py +0 -0
  105. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/exchange/data/ISO10383_MIC.csv +0 -0
  106. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/exchange/data/mic_codes.txt +0 -0
  107. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/exchange/exchange.py +0 -0
  108. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/README.md +0 -0
  109. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/__init__.py +0 -0
  110. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/allratestoday.py +0 -0
  111. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/bcd.py +0 -0
  112. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/bog.py +0 -0
  113. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/cfets.py +0 -0
  114. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/data/cfets_cny_1994_2005.csv +0 -0
  115. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/exchange_rate_api.py +0 -0
  116. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/fed.py +0 -0
  117. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/forex.py +0 -0
  118. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/hkma.py +0 -0
  119. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/official_source.py +0 -0
  120. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/xof.py +0 -0
  121. {mopr-0.0.67 → mopr-0.0.69.dev0}/finance/forex/yahoo.py +0 -0
  122. {mopr-0.0.67 → mopr-0.0.69.dev0}/log/__init__.py +0 -0
  123. {mopr-0.0.67 → mopr-0.0.69.dev0}/log/core.py +0 -0
  124. {mopr-0.0.67 → mopr-0.0.69.dev0}/machine/__init__.py +0 -0
  125. {mopr-0.0.67 → mopr-0.0.69.dev0}/machine/id.py +0 -0
  126. {mopr-0.0.67 → mopr-0.0.69.dev0}/mopr.egg-info/dependency_links.txt +0 -0
  127. {mopr-0.0.67 → mopr-0.0.69.dev0}/mopr.egg-info/entry_points.txt +0 -0
  128. {mopr-0.0.67 → mopr-0.0.69.dev0}/mopr.egg-info/requires.txt +0 -0
  129. {mopr-0.0.67 → mopr-0.0.69.dev0}/mopr.egg-info/top_level.txt +0 -0
  130. {mopr-0.0.67 → mopr-0.0.69.dev0}/python/__init__.py +0 -0
  131. {mopr-0.0.67 → mopr-0.0.69.dev0}/quant1x.png +0 -0
  132. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/__init__.py +0 -0
  133. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/once.py +0 -0
  134. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/once_test.py +0 -0
  135. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/ringbuffer.md +0 -0
  136. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/ringbuffer.py +0 -0
  137. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/ringbuffer_test.py +0 -0
  138. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/scheduler.md +0 -0
  139. {mopr-0.0.67 → mopr-0.0.69.dev0}/runtime/scheduler.py +0 -0
  140. {mopr-0.0.67 → mopr-0.0.69.dev0}/setup.cfg +0 -0
  141. {mopr-0.0.67 → mopr-0.0.69.dev0}/storage/__init__.py +0 -0
  142. {mopr-0.0.67 → mopr-0.0.69.dev0}/storage/storage.py +0 -0
  143. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/__init__.py +0 -0
  144. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/__main__.py +0 -0
  145. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/__init__.py +0 -0
  146. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/__main__.py +0 -0
  147. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/cli.py +0 -0
  148. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/handlers/__init__.py +0 -0
  149. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/handlers/cpp.py +0 -0
  150. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/handlers/go.py +0 -0
  151. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/handlers/java.py +0 -0
  152. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/handlers/python.py +0 -0
  153. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/handlers/rust.py +0 -0
  154. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/notices.py +0 -0
  155. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/report.py +0 -0
  156. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_audit/todo.py +0 -0
  157. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/__init__.py +0 -0
  158. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/__main__.py +0 -0
  159. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/cli.py +0 -0
  160. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/core.py +0 -0
  161. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/handlers/__init__.py +0 -0
  162. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/handlers/base.py +0 -0
  163. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/handlers/cpp.py +0 -0
  164. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/handlers/go.py +0 -0
  165. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/handlers/java.py +0 -0
  166. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/handlers/python.py +0 -0
  167. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/handlers/rust.py +0 -0
  168. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/license_header/project_meta.py +0 -0
  169. {mopr-0.0.67 → mopr-0.0.69.dev0}/tools/run_module.py +0 -0
@@ -32,6 +32,21 @@ mopr 同一语义的多语言实现遵循固定的**角色与演进顺序**,
32
32
  - 跨语言差异处理先从 Python(spec)侧定案,再推广至 C++(生产)与 Rust/Go(扩展);若 Python 缺少某能力而其他语言已有,应先补 Python spec。
33
33
  - 语言最低版本表(上文)与 README.md「语言与版本要求」不因角色调整而改变。
34
34
 
35
+ ## 文件命名与物理命名空间约定
36
+
37
+ 同一功能拆分为多个源文件时,文件名统一采用「**功能名前缀 + 下划线 + 角色/平台名**」,用前缀在目录内构成**物理层面的命名空间**:
38
+
39
+ - **前缀即命名空间**:同族文件按前缀自然聚拢,按前缀即可检索到该功能的全部实现:
40
+ - `base/strings_camel.go` / `strings_snake.go` / `strings_kebab.go` / `strings_helper.go`;
41
+ - `distributed/id/state_lock_unix.go` / `state_lock_windows.go` / `state_lock_shared.go` / `state_lock_other.go`;
42
+ - `base/mmap/mmap_posix.go` / `mmap_windows.go` / `mmap_unsupported.go`;
43
+ - `benchmark/micro/ringbuffer_mpmc_probe.cpp` / `ringbuffer_sched_cost_probe.cpp` / `ringbuffer_single_thread_ablation.cpp`。
44
+ - **两级正交**:前缀承载功能维度,后缀承载语言与角色维度——语言后缀沿用各语言惯例(`.py` / `.h` / `.cpp` / `.rs` / `.go` / `.md`),角色后缀用于平台分支(`_posix` / `_windows` / `_unsupported`)与测试(`_test`);同一功能的跨语言实现因此同名不同后缀、同处一目录。
45
+ - **适用边界**:前缀只用于同一功能的文件分组,不为无关文件强加公共前缀;功能名已唯一的文件直接以功能名命名(`region.go` / `cron.rs` / `crc32.h`),不画蛇添足。
46
+ - **同目录优先,不按语言分目录**:语言工具链要求「目录即成包」时(Go 的 `package`、Java 的包路径),在**该功能目录内**加同名二级目录与其它语言对齐(`base/mmap/mmap.go` ↔ `base/mmap.py`);**不得**在仓库根按语言拆分语言级目录,把同一功能的各语言实现物理隔离——同目录并列才能形成「看到 `mmap.py` 顺手去看 `mmap.h` / `mmap.rs` / `mmap/mmap.go`」的对照与主动学习。
47
+ - 与「仓库根即实现根」配合:目录承载模块级命名空间,文件名前缀承载模块内的功能级命名空间,二者共同决定 C++ 命名空间与各语言模块路径(见下文与 [CONTRIBUTING.md](CONTRIBUTING.md)「目录与多语言布局约定」)。
48
+ - 设计意图(同目录对照的收益、按语言分目录为何是反例、对 AI 的友好之处)见 [docs/directory-layout-rationale.md](docs/directory-layout-rationale.md)。
49
+
35
50
  ## Python 包形态与导入约定
36
51
 
37
52
  - mopr 的 Python 代码经 `pyproject.toml` package-dir 注册为 `mopr.*` 子包:`python/` → `mopr`(包入口,导出 `__version__`),`base/` → `mopr.base`,`log/` → `mopr.log`,`machine/` → `mopr.machine`,`runtime/` → `mopr.runtime`,`distributed/` → `mopr.distributed`,`tools/` → `mopr.tools`。仓库根目录无 `__init__.py`,源码形态下 `mopr` 是 PEP 420 隐式命名空间包。
@@ -47,6 +62,28 @@ mopr 同一语义的多语言实现遵循固定的**角色与演进顺序**,
47
62
  - `.cpp`、`tests/`、`benchmark/` 等不随安装分发的文件可用仓库根相对路径(构建期由 `$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>` 提供 include 根)。
48
63
  - 使用方包含安装后的头文件写 `<mopr/<模块>/<头文件>.h>`(如 `<mopr/runtime/once.h>`)。
49
64
 
65
+ ## C++ 命名空间与头文件宏约定
66
+
67
+ - **命名空间**:以项目名 `mopr` 为根,**仓库根路径下的子目录为第二级**,多级目录依次下探:
68
+ - `base/timestamp.h` → `mopr::base`;`storage/storage.h` → `mopr::storage`;
69
+ - `distributed/id/hlc.h` → `mopr::distributed::id`;`encoding/csv.h` → `mopr::encoding`。
70
+ - 同一模块内可按文件/职责再设下一级子命名空间(如 `base/strings.h` → `mopr::base::strings`;`encoding/csv.h` → `mopr::encoding::csv`;`encoding/json.h` → `mopr::encoding::json`,含 `mopr::encoding::json_detail` / `mopr::encoding::safe_json` / `mopr::encoding::unsafe_json`;`encoding/yaml.h` → `mopr::encoding::yaml` / `mopr::encoding::safe_yaml`)。
71
+ - **禁止**使用未挂 `mopr` 根的顶层命名空间(如 `namespace encoding`、`namespace runtime`)。第三方库自身的顶层命名空间(如 csv-parser 的 `csv`、yaml-cpp 的 `YAML`)不得作为本项目的命名空间根,与本项目命名空间冲突时一律以全局限定形式书写(`::csv::`)。
72
+ - **头文件宏(`#ifndef` 守卫)**:`MOPR_{大写的目录名}_{文件名}_H`,目录层级用下划线连接,文件名取去扩展名的主体:
73
+ - `encoding/csv.h` → `MOPR_ENCODING_CSV_H`;`encoding/charsets.h` → `MOPR_ENCODING_CHARSETS_H`;
74
+ - `distributed/id/hlc.h` → `MOPR_DISTRIBUTED_ID_HLC_H`;`base/strings.h` → `MOPR_BASE_STRINGS_H`。
75
+ - 守卫宏与 `#pragma once` 并存;`#endif` 行以注释回写宏名(如 `#endif // MOPR_ENCODING_CSV_H`)。
76
+ - 新增公共头文件一律遵循上述规则。既有不合规处按模块逐个收敛(`runtime::*` → `mopr::runtime::*`、`base/filesystem.h` 的 `filesystem` → `mopr::base::filesystem`、`base/except.h` 的 `quant1x` → `mopr::base`、`base/mmap.h` 的全局 `file_mmap` / `mmap_open` / `mmap_flush` / `mmap_close` → `mopr::base` 内的 `MmapHandle` / `mmap_open` / `mmap_flush` / `mmap_close`),不做一次性大范围改名。
77
+ - **公开符号命名跨语言一致**(同一语义在各语言同名,便于跨语言对照与回溯):
78
+ - **公开函数名一致**:Python 与 C++ 使用同一函数名(如 Python `mmap_open` ↔ C++ `mmap_open`),不因语言差异改名;Rust / Go 沿用本语言惯例的,须在模块文档的 API 对照表中给出对应关系。
79
+ - **函数名带模块前缀时不套同名命名空间**:函数名已含模块前缀(如 `mmap_`)时,C++ 侧不再套一层同名命名空间——`mmap_open` 直接位于 `mopr::base`,而非 `mopr::base::mmap::mmap_open`(同风格参考 `base/region.h` 的 `region_currency` / `region_timezone`)。
80
+ - **公开结构体 typedef 统一 `mopr_` 前缀**:结构体标签与 typedef 用同名风格,如 `typedef struct mopr_xxx mopr_xxx_t;`;但跨语言共享的**句柄类型除外**——句柄跨语言同名,C++ 侧直接定义 `struct MmapHandle`(与 Python / Rust / Go 的 `MmapHandle` 一字不差),不套 `mopr_xxx_t` 风格。
81
+ - **句柄类型不得命名 `File`**:句柄承载的是映射而不是文件(文件句柄只是其内部成员之一),`File` 会与 `os.File` / 文件流混淆;跨语言统一用 `MmapHandle`(C++ 为 `struct MmapHandle`)。
82
+ - **句柄操作遵循语言惯例**:Python / Rust / Go 用句柄方法(`flush` / `close`、`Flush` / `Close`),C++ 句柄是 POD,用同名自由函数(`mmap_flush` / `mmap_close`)与之一一对应。
83
+ - **同一语义可同时提供「公开 API + RAII 类」两层**:第一层为跨平台公开 API(如 `mmap_open` / `mmap_flush` / `mmap_close` + 句柄),资源由调用方显式管理;第二层为跨语言同名的 RAII 类(如 `MappedMemory`:`MappedMemory.open` 打开,析构 / `Drop` / `with` / `defer` 自动释放)。两层共用同一实现、语义必须一致,区别仅在释放时机;模块文档须给出两层对照表(示例见 `base/mmap.md`「1. 分层与命名」)。
84
+ - **RAII 类名不得与模块名重复**:类名不叫 `mmap` / `Mmap`(与模块名、包名重复,且易被误读为句柄),统一用其语义名(如 `MappedMemory`),并跨语言同名;句柄另用 `XxxHandle`(如 `MmapHandle`,四语言同名,C++ 亦为 `struct MmapHandle`)。
85
+ - 已知遗留(需按模块逐一评估,勿批量替换):`base/common.h` 的全局 typedef 与常量(`i8` / `u8` / … 为标量别名、非结构体 typedef,不适用 `mopr_` 前缀约定),`base/format.h` 的全局探测模板与 `std::vector` 的 `operator<<`(依赖 ADL / 非限定查找,移入命名空间会导致使用方找不到),`tests/` 下 `*_test_types` 等测试辅助命名空间。
86
+
50
87
  ## git 提交规范
51
88
 
52
89
  ### 1. 提交信息规范(含上级仓库约定)
@@ -625,7 +625,7 @@ go build ./...
625
625
  go test ./...
626
626
  ```
627
627
 
628
- 现有包:`base/cache`(内存映射缓存)、`base/mem`(页与大小换算)、`runtime`(环形缓冲)、`distributed/id`(分布式 ID,含 `state_lock_windows.go` 等平台分文件)。也可按目录定向运行:
628
+ 现有包:`base/cache`(泛型内存映射缓存)、`base/mem`(页与大小换算)、`base/mmap`(文件内存映射)、`runtime`(环形缓冲)、`distributed/id`(分布式 ID,含 `state_lock_windows.go` 等平台分文件)。也可按目录定向运行:
629
629
 
630
630
  ```powershell
631
631
  go test ./runtime/... ./distributed/id/...
@@ -637,7 +637,7 @@ Go 侧唯一运行时第三方依赖为 `golang.org/x/sys` v0.47.0(声明于 `
637
637
 
638
638
  ### 5.4 平台分文件与许可证头
639
639
 
640
- `base/cache` 的 mmap 与 `distributed/id` 的 state_lock 均按平台拆分实现:`mmap_windows.go` / `mmap_posix.go` / `mmap_unsupported.go`、`state_lock_windows.go` / `state_lock_unix.go` / `state_lock_other.go`。平台分文件必须保留 `//go:build` 构建约束:许可证头位于其前(均为行注释,Go 允许 build constraint 被行注释与空行前置),批量写入版权/许可证头时不得删除 build tag;`mapFile`、`processAlive` 等平台符号由 build tag 决定唯一编译。平台分文件改动不得引入低于 Go 1.27.0 的特性。当前验证环境(Windows + `go1.27.0`)下 `go build ./...` 与 `go test ./...` 全绿(`base/cache`、`base/mem`、`distributed/id`、`runtime` 四个包)。
640
+ `base/mmap` 的映射实现与 `distributed/id` 的 state_lock 均按平台拆分实现:`mmap_windows.go` / `mmap_posix.go` / `mmap_unsupported.go`、`state_lock_windows.go` / `state_lock_unix.go` / `state_lock_other.go`。平台分文件必须保留 `//go:build` 构建约束:许可证头位于其前(均为行注释,Go 允许 build constraint 被行注释与空行前置),批量写入版权/许可证头时不得删除 build tag;`Map`、`processAlive` 等平台符号由 build tag 决定唯一编译。平台分文件改动不得引入低于 Go 1.27.0 的特性。当前验证环境(Windows + `go1.27.0`)下 `go build ./...` 与 `go test ./...` 全绿(`base/cache`、`base/mem`、`base/mmap`、`distributed/id`、`runtime` 五个包)。
641
641
 
642
642
  ## 6. 第三方声明与许可证归档
643
643
 
@@ -3,6 +3,243 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  ## [Unreleased]
5
5
 
6
+ ## [0.0.68] - 2026-09-12
7
+ ### Changed
8
+ - fix[web]: 调整键盘信息采集的web代码路径到tests
9
+ - fix[python]: 补充版权信息
10
+ - feat[multi]:新增 website/oa 内置 OA 办公协同系统
11
+ - 后端:Python 3.12+ 标准库 HTTP 服务 + SQLite 单文件库,覆盖公告通知、申请单、多级审批、任务待办、流程定义与系统管理(用户 / 部门 / 角色权限 / 操作日志),鉴权与菜单口径统一由 oa/rbac.py 权限点目录驱动
12
+ - 前端:Vue 3 + Vue Router + Vite 源码位于 frontend/,产物输出到 Vite 默认目录 frontend/dist
13
+ - 静态托管根目录由 oa/config.py 的 WEB_DIR 与 vite.config.js 的输出目录共同决定,两处绑定、改名须同改;产物缺失时 40400 提示直接给出构建命令
14
+ - 产物不入库:frontend/dist 由仓库根 .gitignore 的 dist/ 规则忽略,首次运行须先在 frontend/ 执行 npm run build
15
+ - 文档:README 补齐目录结构、快速开始、接口约定、权限模型与开发约定,并写明产物目录的后端绑定关系
16
+ - 验证:cd website/oa && python3 tests/smoke_test.py
17
+ - fix[multi]:修正新建流程弹窗业务类型与审批人类型下拉为空
18
+ - 根因:FlowFormDialog.vue 中 bizTypes / approverTypes 被定义为普通箭头函数,模板用 v-for 直接迭代该函数;Vue 的 renderList 对函数走对象分支,遍历其自身可枚举属性(函数无此属性)结果为 0 项,下拉不显示任何选项
19
+ - 改动:两者改为 computed(() => optionList(...)),模板保持不变,与视图层既有的 v-for="option in <computed>" 写法统一,并补 computed 导入
20
+ - 影响范围:顺带修复同一缺陷导致的「审批人类型」下拉为空
21
+ - 接口与数据侧无改动:/api/meta 的 biz_types / approver_types 字典与登录时装载的 state.dicts 本身正常,无需调整
22
+ - 验证:cd website/oa/frontend && npm run build 构建通过,产物已刷新;界面效果需浏览器刷新后确认
23
+ - feat[python]:新增合同审批与财务反向处理业务类型及样例流程
24
+ - 业务类型白名单 BIZ_TYPES(oa/services/approval.py)新增 contract 合同审批、reversal 财务冲正、red_reversal 红字冲销、adjustment 账务调整,并在注释中固化命名口径:合同审批指签前审批(对应内控「合同订立」,盖章另走 seal);财务冲正指资金/清算层对某笔交易反向记账;红字冲销指会计凭证层对已入账凭证做负数分录更正(俗称红冲);账务调整指人工发起、需审批留痕的账务更正单据;三者口径互不等价,不做合并
25
+ - 样例流程:seed.py 的 _FLOWS 补入上述四条流程定义(含各自表单字段与审批链路),财务复核统一取 role:finance,红字冲销与账务调整末步回到 applicant 确认;seed 内示例公告文案同步补「合同审批」
26
+ - 表结构注释:schema.sql 中 flow_defs.biz_type 的枚举注释补齐新取值;biz_type 为 TEXT 且无 CHECK 约束,老库无需迁移
27
+ - 前端零改动:业务类型选项全部经 /api/meta 的 biz_types 下发,前端无硬编码 code 列表,流程定义与申请单的下拉自动带出新类型
28
+ - 文档:README 新增「业务类型与样例流程」章节(业务类型口径表、审批人来源、首次初始化灌入的样例流程清单),并在「数据库」小节说明 seed 以 meta.seeded 为哨兵只执行一次、既有库不会补入新增样例流程
29
+ - 兼容性:既有库不会新增样例流程,需重置库或在「流程定义」页手工新建;业务类型来自代码、不依赖灌库,升级即生效
30
+ - 验证:cd website/oa && python3 tests/smoke_test.py(通过 39 项,失败 0 项)
31
+ - feat[python]:内置样例流程改为启动时按缺失回填并记录删除墓碑
32
+ - schema.sql:flow_defs 增加 is_seed 列,标注内置样例流程
33
+ - db.py:SCHEMA_VERSION 升至 2,_migrate 补 v2 分支(ALTER TABLE 加列),替换原先的空循环占位
34
+ - seed.py:新增 sync_flows(每次启动按缺失回填;已存在与被停用的流程不动,同编码历史行补标 is_seed)、mark_flow_removed 与 _removed_flow_codes(meta.seed_flows_removed 删除墓碑);抽出 _insert_flow 供首次灌入与启动回填共用
35
+ - server.py:create_server 在 database.initialize 之后接上 seed.sync_flows
36
+ - services/approval.py:delete_flow 删除样例流程时同事务写墓碑,审计事件补 detail.sample
37
+ - README.md:更新升级行为(样例流程升级即补齐)、结构版本与迁移约定、服务层对 seed 的例外依赖
38
+ - 验证:python3 tests/smoke_test.py 通过 39 项、失败 0 项;另在真实库的只读备份副本上实测三个用例——结构 v1 的库启动即迁移(schema_version 2、8 条流程补标 is_seed)、缺 4 条样例流程的老库启动后回填至 8 条、接口删除 purchase 写墓碑后重启不回填(同批裸删的 seal 被正常回填)
39
+ - feat[multi]:流程定义页新增内置样例流程的恢复入口
40
+ - 后端把删除墓碑从「只写」变为可读可恢复:`seed._write_removed` 抽出整表回写,
41
+ 新增 `seed.removed_flows`(墓碑中登记且库中缺失的内置样例流程)与
42
+ `seed.restore_flows`(按内置定义重建并摘除命中编码,`conn` 可复用调用方事务)
43
+ - `seed._flow_brief` 返回内置定义副本,步骤与表单字段逐项浅拷贝,避免上层补展示字段
44
+ 时污染模块级 `_FLOWS`
45
+ - 服务层新增 `approval.list_removed_flows`(补齐 `biz_type_label`/`approver_type_label`/
46
+ `is_seed`,与 `/api/flows` 行形状一致)与 `approval.restore_flows`(校验 codes 落在
47
+ 可恢复清单内,无可恢复项 409、编码非法 400,写 `flow:restore` 审计)
48
+ - 新增 `GET /api/flows/removed`(`flow:view`)与 `POST /api/flows/restore`
49
+ (`flow:create`,请求体 `codes` 缺省即恢复全部),路由排在 `{id}` 之前
50
+ - 前端流程定义页把墓碑中的样例流程渲染为灰行(状态「已删除」、名称旁「可恢复」),
51
+ 行尾「恢复」按内置定义重建,多条时页头出现「恢复内置样例流程(N)」一次恢复全部;
52
+ 删除内置样例流程的确认文案改为提示可找回
53
+ - 语义一致性:恢复即「按内置定义新建」,与手工新建同编码流程等价,故复用 `flow:create`
54
+ 而不新增权限点(权限点只在首次初始化时灌入,新增权限码对既有库不生效);恢复后编码
55
+ 从墓碑摘除,交由 `sync_flows` 常规接管,此后再次删除会重新登记墓碑;自建流程删除既
56
+ 不入墓碑也不可恢复
57
+ - 涉及语言与文件范围:Python(`oa/seed.py`、`oa/services/approval.py`、`oa/api.py`、
58
+ `tests/smoke_test.py`)+ 前端 JS/Vue(`frontend/src/api.js`、`frontend/src/views/FlowsView.vue`)
59
+ + `README.md`
60
+ - 验证:`cd website/oa && python3 tests/smoke_test.py` 通过 51 项、失败 0 项(新增第 5 节
61
+ 覆盖 样例流程带 is_seed → 删除 → 进可恢复清单且列表消失 → 按编码恢复 → 步骤与出厂
62
+ 定义一致且 is_seed 仍为 1 → 墓碑摘除 → 再恢复得 409 → 自建流程删除不进清单 →
63
+ 普通员工恢复得 403);`cd frontend && npm run build` 通过
64
+ - feat[docs]: 新增安全与合规模块
65
+ - feat[python]:新增 security/auth 通用安全模块
66
+ - 按 security/auth/README.md 的 spec 落地实现,模块只依赖标准库,与存储、传输解耦:
67
+ credential(口令哈希与策略校验)、token(令牌生成与签名编解码)、
68
+ session(会话与登录节流/锁定)、model / principal(主体与数据范围)、
69
+ catalog / authorize(权限点目录与鉴权)、errors,以及 spi(接入方实现的存储与目录接口)
70
+ - 对外只暴露 SPI 接口,由宿主提供 IdentityStore / SessionStore / LoginAttemptStore 等实现,
71
+ 便于 OA、MES 等不同接入层复用同一套安全语义
72
+ - pyproject.toml:packages 与 package-dir 新增 mopr.security、mopr.security.auth
73
+ - 验证:python -m security.auth.credential_test / rbac_test / session_test / token_test 全部 OK
74
+ (须用 -m 方式运行:security/auth/token.py 会遮蔽同名标准库模块)
75
+ - feat[python]:OA 认证授权接入 security/auth 通用模块
76
+ - website/oa/oa/security.py、rbac.py 由自带实现改为对 mopr.security.auth 的薄封装:
77
+ 保留原有函数签名与返回结构,把口令哈希、令牌随机数、权限判定与数据范围计算下沉到通用模块
78
+ - 新增分流语义:库内口令摘要损坏(无法解析 / 算法不符 / 迭代次数非正 / base64 损坏)时,
79
+ 不再计入失败次数、不触发锁定,也不当作「用户输错口令」,而是明示
80
+ 「账号口令数据异常,请联系系统管理员重置口令」,并分别记 login_rejected / change_password_rejected 审计;
81
+ 普通失败仍统一提示「账号或口令错误」,不泄露账号是否存在
82
+ - 改密路径同一分流但返回 400 而非 401:前端对 401 会强制清会话跳登录页,
83
+ 而此刻会话是有效的,用户需要停在改密弹窗里看到原因;失败时库内摘要不会被改写
84
+ - 测试:security_test.py 28 项、smoke_test.py 60 项全部通过;冒烟第 7 节新增
85
+ 「摘要损坏前可正常登录 / 登录 401 / 不计失败次数 / 改密 400 / 摘要未被改写 / 两条审计留痕」
86
+ - 文档:website/oa/README.md 登录安全与冒烟覆盖说明同步
87
+ - feat[python]:新增 encoding/charsets 字符集转码的 Python 实现并导出至包入口
88
+ - 变更概述:新增 encoding/charsets.py,作为 UTF-8 与 GBK(GB18030) 双向转码的 Python spec 实现;encoding/__init__.py 同步导出
89
+ - 文件范围:encoding/charsets.py(新增)、encoding/__init__.py(包入口导出 utf8_to_gbk / gbk_to_utf8 并更新模块说明)
90
+ - 语义一致性:码表选用 GB18030,与 C++ 侧 iconv 的 GB18030//IGNORE 对齐;非法/不完整多字节序列按 //IGNORE 语义丢弃、两个方向均不抛异常;转换前在首个 NUL 处截断,均与 encoding/charsets.cpp 的 truncate_at_null 行为一致;Python str 为 Unicode、GBK 侧以 bytes 承载,与 C++ std::string 原始字节串语义等价
91
+ - 验证:python -c "from mopr.encoding import utf8_to_gbk, gbk_to_utf8",'中文' 往返转换结果一致
92
+ - refactor[c++]:统一 encoding 命名空间为 mopr::encoding 并落定命名空间与头文件宏规则
93
+ - 变更概述:encoding 模块的 C++ 命名空间由未挂根的 encoding::*(csv/json/yaml)收敛到 mopr::encoding::*,调用方 storage 同步改造;同时在文档中固化 C++ 命名空间与头文件 #ifndef 宏规则
94
+ - 命名空间映射:charsets.h/charsets.cpp → mopr::encoding;csv.h → mopr::encoding::csv;json.h/json.cpp → mopr::encoding::json(含 json_detail / safe_json / unsafe_json 子命名空间);yaml.h → mopr::encoding::yaml(含 safe_yaml)
95
+ - 头文件守卫宏:encoding/charsets.h 的 MOPR_ENCODING_ICONV_H 按 MOPR_{大写的目录名}_{文件名}_H 规则改为 MOPR_ENCODING_CHARSETS_H
96
+ - 文件范围:encoding/{csv.h,json.h,json.cpp,yaml.h,charsets.h,charsets.cpp}、调用方 storage/storage.h、测试 tests/encoding/{charsets,csv,json,yaml}_test.cpp、文档 AGENTS.md(新增「C++ 命名空间与头文件宏约定」)、CONTRIBUTING.md、encoding/README.md、encoding/{csv,json,yaml}.md、storage/storage.md
97
+ - 语义一致性:仅命名空间、头文件守卫宏与文档调整,函数签名、序列化行为及与 Python(spec) / Go 侧契约不变
98
+ - 遗留:顶层 runtime、base/filesystem.h 的顶层 filesystem、base/except.h 的 quant1x 尚未收敛,已在 AGENTS.md 记为后续逐模块处理
99
+ - 验证:cmake --build --preset release-dynamic --target mopr_tests 编译通过;mopr_tests.exe --gtest_filter=*Charsets*:*Csv*:*Json*:*Yaml* 4 个测试套件 28 个用例全部通过
100
+ - refactor[c++]:统一 base/mmap.h 命名空间为 mopr::base::mmap
101
+ - base/mmap.h:file_mmap / mmap_t / mmap_open / mmap_flush / mmap_close 全部纳入 mopr::base::mmap;
102
+ windows.h 的引入仍留在全局作用域(HANDLE 等平台类型不能落进本项目命名空间)
103
+ - base/mmap.cpp:Windows 与 POSIX 两分支由单个 mopr::base::mmap 块包裹;POSIX 的 sys/mman.h 等
104
+ 系统头从 #else 分支上提到文件顶部——置于命名空间内会把 ::mmap 等系统声明误建到本项目命名空间,
105
+ 平台分支代码体零改动
106
+ - distributed/id/state_store.h:前向声明由全局 struct file_mmap / typedef mmap_t 改为
107
+ namespace mopr::base::mmap { struct file_mmap; },成员改用 mopr::base::mmap::file_mmap *,
108
+ 继续只暴露不完整类型,不向使用方泄漏 mmap.h 与 windows.h
109
+ - distributed/id/state_store.cpp:8 处 mmap_* 调用改为 mopr::base::mmap:: 全限定形式,与同文件
110
+ 既有 mopr::base::getenv 风格一致,未引入 using 声明
111
+ - 语义不变:共享映射的跨语言(Spec: Python → Go/Rust)文件格式、平台对齐修正与 flush 时机均未改动
112
+ - 验证:cmake --build --preset release-dynamic 通过;
113
+ build/release-dynamic/tests/Release/mopr_tests.exe 94 用例 93 通过、1 跳过
114
+ (CronTest.DstGapSkipsInsteadOfStalling:本地时区无夏令时的既有条件跳过)
115
+ - refactor[c++,go]:抽出 Go 版 base/mmap 包并同步 C++ mmap 头注释
116
+ - 变更概述:把原先内嵌在 base/cache 的 Go 内存映射实现抽成独立包 base/mmap(与 C++
117
+ base/mmap.h 的目录/命名布局对齐),base/cache 退化为该映射包的使用方。
118
+ - 涉及语言与文件范围:
119
+ - go:新增 base/mmap/{mmap.go, mmap_posix.go, mmap_windows.go, mmap_unsupported.go,
120
+ mmap_test.go};删除 base/cache/{mmap_file.go, mmap_posix.go, mmap_windows.go,
121
+ mmap_unsupported.go, mmap_file_test.go};base/cache/cache.go 改用 mmap.MemObject 与
122
+ mmap.Map;distributed/id/state_store.go 改用 *mmap.File 与 mmap.Open;BUILDING.md 同步
123
+ Go 包清单(增至五个包)与平台分文件段落(base/cache → base/mmap、mapFile → Map)。
124
+ - c++:base/mmap.h 仅更新头部注释中的 Go 对应路径(base/cache/mmap_file.go →
125
+ base/mmap/mmap.go),无代码改动。
126
+ - 导出名按 Go 惯例去重:MappedFile / OpenMappedFile / mapFile → mmap.File / mmap.Open /
127
+ mmap.Map;MemObject 由 cache 迁至 mmap(描述映射操作,随映射功能归位)。
128
+ - 语义一致性:映射实现逐行搬运,未改逻辑——size 校验(非正数、超 MaxInt/MaxUint32)、父目录
129
+ 按需创建、定长 Truncate、Flush 刷脏页与文件元数据、Close 幂等(先 Flush 再 Unmap 再关文件,
130
+ 首个错误优先返回);平台分文件保留 //go:build 约束且许可证头仍位于其前。
131
+ - 验证:
132
+ - gofmt -l base/cache base/mmap distributed/id 无输出;
133
+ - go build ./... 与 go vet ./... 通过;
134
+ - go test ./... 全绿(base/cache 5.0s、base/mmap 0.39s、distributed/id 0.51s、runtime、base、
135
+ encoding/base64);
136
+ - 交叉平台分支核对:GOOS=linux go build/vet ./base/mmap/... ./base/cache/... ./distributed/id/...
137
+ 通过(POSIX 分支),GOOS=js GOARCH=wasm go build ./base/mmap/... 通过(unsupported 分支)。
138
+ - refactor[c++]:统一 runtime 命名空间为 mopr::runtime
139
+ - runtime/once.h:顶层 namespace runtime 收敛为 mopr::runtime,收尾注释同步回写
140
+ - runtime/ringbuffer.h:namespace runtime::ringbuffer → mopr::runtime::ringbuffer,detail 与
141
+ queue 两处代码块及收尾注释一并回写;头文件宏 MOPR_RUNTIME_RINGBUFFER_H 不变,文件内
142
+ 「与 Rust runtime::Queue 语义一致」等指代他语言的描述保持原样
143
+ - runtime/scheduler.h:顶层 namespace runtime 收敛为 mopr::runtime,并把原先分处两个 namespace
144
+ 块的 task_id/JobType 枚举与 AsyncScheduler 类合并到同一块内;JobInfo 成员随之去限定
145
+ (runtime::task_id → task_id、runtime::JobType → JobType)
146
+ - runtime/scheduler.cpp:add_job 返回类型与 7 处成员函数形参的 ID 类型改为 task_id /
147
+ mopr::runtime::task_id,4 处 JobType 使用去限定(文件自身处于 mopr::runtime 内,按资质查找可见)
148
+ - 调用点同步限定:tests/runtime/once_test.cpp、tests/runtime/scheduler_test.cpp(含
149
+ info->type == mopr::runtime::JobType::Cron 断言)、benchmark/micro/ringbuffer_mpmc_probe.cpp /
150
+ ringbuffer_single_thread_ablation.cpp / vyukov_bench.cpp(using namespace
151
+ mopr::runtime::ringbuffer)、distributed/id/queue.h(内嵌成员类型与注释)
152
+ - 文档与构建脚本:runtime/once.md 的 API 对照表与用法示例由 runtime::RollingOnce 改为
153
+ mopr::runtime::RollingOnce;CMakeLists.txt 说明注释中的 runtime::ringbuffer::queue<T> 同步
154
+ - 语义一致性:纯命名空间与限定名收敛,无逻辑、接口、头文件宏改动;公共头文件之间仍用相对路径
155
+ 互引,头文件宏命名规则不变
156
+ - 验证:cmake --build --preset release-dynamic 成功(exit 0);
157
+ build/release-dynamic/tests/Release/mopr_tests.exe 94 用例 93 通过、1 跳过
158
+ (CronTest.DstGapSkipsInsteadOfStalling:本地时区无夏令时的既有条件跳过),
159
+ 12 个 SchedulerTest 用例全绿
160
+ - 范围说明:encoding/csv.h、encoding/csv.md 的 filesystem 限定名改动随 base/filesystem 批次提交
161
+ (csv 调用点依赖 filesystem 头命名空间收敛),不在本次提交内
162
+ - refactor[c++]:统一 base/filesystem 命名空间为 mopr::base::filesystem
163
+ - base/filesystem.h:顶层 namespace filesystem 收敛为 mopr::base::filesystem,收尾注释同步回写;
164
+ 头文件宏 MOPR_BASE_FILESYSTEM_H 与全部函数签名、默认参数不变
165
+ - base/filesystem.cpp:同名收敛(定义与收尾注释),文件内 namespace fs = std::filesystem 别名、
166
+ 各平台分支(home/executable/写文件等)实现逻辑逐行未改
167
+ - encoding/csv.h:写出端口径的调用点由 filesystem::check_filepath 改为
168
+ mopr::base::filesystem::check_filepath——原写法依赖顶层 filesystem 命名空间的可见性,
169
+ 收敛后必须显式全限定
170
+ - encoding/csv.md:写入端行为说明中的同名调用点同步更新
171
+ - 语义一致性:纯命名空间与限定名收敛,无逻辑、接口、头文件宏改动;std::filesystem 的使用方式
172
+ 与调用点(含 distributed/id/state_store.cpp 等 std::filesystem 用法)保持原样
173
+ - 验证:cmake --build --preset release-dynamic 成功(exit 0);
174
+ build/release-dynamic/tests/Release/mopr_tests.exe 94 用例 93 通过、1 跳过
175
+ (CronTest.DstGapSkipsInsteadOfStalling:本地时区无夏令时的既有条件跳过),
176
+ OnceTest 16 个、SchedulerTest 12 个用例全绿
177
+ - refactor[c++]:统一 base/except 命名空间为 mopr::base
178
+ - base/except.h:BaseException 由全局命名空间移入 mopr::base;原 quant1x 命名空间内的 error
179
+ 与 make_error_code 并入 mopr::base,收尾注释同步回写
180
+ - THROW_EXCEPTION 宏改为全限定展开(throw mopr::base::BaseException(msg, __FILE__, __LINE__)),
181
+ 使任意命名空间下的调用点无需逐个补限定名
182
+ - 影响范围:仓库内唯一包含点为 base/time.cpp(其 THROW_EXCEPTION 调用当前处于注释状态),
183
+ 全仓无其他 BaseException 引用或捕获点,调用方无需同步改动
184
+ - 语义一致性:仅命名空间归属与宏限定名变化;异常类定义(what()、file/line 成员与构造函数)、
185
+ error 继承 std::error_code 的接口与实现均逐行未改
186
+ - 遗留:storage/storage.h 头部 TODO 提到的 quant1x::data::meta::Instrument 属未移植的旧模块,
187
+ 不在本次收敛范围
188
+ - 验证:cmake --build --preset release-dynamic 成功(exit 0);
189
+ build/release-dynamic/tests/Release/mopr_tests.exe 94 用例 93 通过、1 跳过
190
+ (CronTest.DstGapSkipsInsteadOfStalling:本地时区无夏令时的既有条件跳过)
191
+ - docs[c++]:记录命名空间按模块收敛结果与已知遗留清单
192
+ - AGENTS.md:把「既有不合规处随对应模块重构逐步收敛」改为已落地的四类对照写法
193
+ (runtime::* → mopr::runtime::*、base/filesystem.h 的 filesystem → mopr::base::filesystem、
194
+ base/except.h 的 quant1x → mopr::base、base/mmap.h 的全局 file_mmap / mmap_open / mmap_flush /
195
+ mmap_close → mopr::base::mmap),并保留「不做一次性大范围改名」的约束
196
+ - 新增「已知遗留」条目:base/common.h 的全局 typedef 与常量、base/format.h 的全局探测模板与
197
+ std::vector 的 operator<<(依赖 ADL/非限定查找,移入命名空间会导致使用方找不到)、tests/ 下
198
+ *_test_types 等测试辅助命名空间,须按模块逐一评估,勿批量替换
199
+ - 规范与现状对齐:该规则涉及的四个模块收敛已分别落地(base/mmap、runtime、base/filesystem、
200
+ base/except 四个批次),本次仅补记结论,不含代码改动
201
+ - 验证:纯文档改动,不触及编译;同批次的 C++ 全量构建与测试已通过
202
+ (cmake --build --preset release-dynamic、mopr_tests.exe 94 用例 93 通过、1 跳过)
203
+ - refactor[python,c++]:统一 mmap 公开函数名并收敛 C++ 命名空间与句柄类型
204
+ - Python:base/mmap.py 的 open_file 更名为 mmap_open,与 C++ 公开函数名完全一致;mopr.base 包导出与 __all__ 同步更名
205
+ - C++:base/mmap.h 与 base/mmap.cpp 由 namespace mopr::base::mmap 收敛为 namespace mopr::base,函数名保留 mmap_ 前缀(mmap_open / mmap_flush / mmap_close),不再套一层同名命名空间
206
+ - C++:公开句柄类型 file_mmap / mmap_t 更名并统一 mopr_ 前缀,为 struct mopr_mmap 加 typedef struct mopr_mmap mopr_mmap_t;distributed/id/state_store.h 的前向声明与成员类型同步
207
+ - 调用点:distributed/id/state_store.cpp、distributed/id/state_store.py、base/mmap_test.py 全部切换到新符号名
208
+ - 语义一致性:Python(spec)与 C++(生产)的打开、刷盘、释放语义不变,仅调整符号命名与命名空间层级;刷盘与释放仍分别对应句柄方法 File.flush / File.close 与自由函数 mmap_flush / mmap_close,一一对应
209
+ - 规范沉淀:AGENTS.md 新增「公开符号命名跨语言一致」四条约定(函数名跨语言一致、带模块前缀不套同名命名空间、公开结构体 typedef 统一 mopr_ 前缀、句柄操作按语言惯例);base/mmap.md 增加命名约定小节并同步清单、API 对照表与使用方表
210
+ - 验证:cmake --build --preset release-dynamic(exit 0);build/release-dynamic/tests/Release/mopr_tests.exe 94 用例 93 通过 1 跳过;python -m unittest mopr.base.mmap_test mopr.distributed.id.tests 26 用例 OK;python -m mopr.tools.license_header --check 4 个改动文件通过
211
+ - feat[python,c++,rust,go]:新增跨平台 mmap 基建并统一跨语言句柄命名
212
+ - 变更概述:落地两层 mmap API——第一层为跨平台公开 API(mmap_open / mmap_flush / mmap_close + 句柄 MmapHandle,资源由调用方显式管理),第二层为跨语言同名的 RAII 类 MappedMemory(析构 / Drop / with / defer 自动释放);支持定长共享映射的 offset / length、按需创建父目录、文件短于请求长度时扩展(长于请求长度不截断,非破坏性)。
213
+ - 句柄命名跨语言统一为 MmapHandle:Python / Go 原先的 File 改名(File 名称过于通用,与 os.File / 文件流混淆);C++ 由 struct mopr_mmap + typedef mopr_mmap_t 改为 struct MmapHandle 并删除 mopr_mmap_t 别名;Rust 随新增模块一并为 MmapHandle。Go 低层平台映射接口 MemObject 改名 Mapping,与第二层 MappedMemory、入口 Map 不再撞名。
214
+ - 文件范围:base/mmap.py、base/mmap.h、base/mmap.cpp、base/mmap.rs(新增)、base/mmap/mmap.go 与 mmap_posix.go / mmap_windows.go / mmap_unsupported.go、base/mmap.md、AGENTS.md 命名约定;使用方 distributed/id/state_store.py / .h / .cpp / .rs / .go、base/cache/cache.go、base/__init__.py、base/mod.rs;测试 base/mmap_test.py、base/mmap.rs 内联测试、base/mmap/mmap_test.go、tests/base/mmap_test.cpp(新增并接入 tests/CMakeLists.txt)。Rust 侧顺带做 rustfmt 风格统一(base/cron.rs、base/timestamp.rs、base/region.rs 的 BOM 清理、格式与导入排序)。
215
+ - 语义一致性:四语言第一层语义一致(打开即定长共享映射、flush 幂等刷盘、close 幂等释放且句柄置空 / 归零),第二层仅释放时机不同、共用同一实现;C++ 句柄为 POD 配同名自由函数,其余语言用句柄方法一一对应,两层 API 对照表见 base/mmap.md。
216
+ - 验证:cargo test(lib 与 doctests 全通过);python -m unittest mopr.base.mmap_test(18 passed);go test ./...(全部 ok);cmake --build --preset release-dynamic --target mopr_tests 后运行 mopr_tests.exe(106 用例 105 passed + 1 skipped)。
217
+ - docs[multi]:统一目录与命名约定并补齐 spec 占位、沉淀布局设计意图
218
+ - 目录布局:README「项目结构」改为「仓库根即实现根」,删除 `src/core` 与 `src/platform`
219
+ 两级,功能模块目录平铺在仓库根,同一功能的多语言实现同目录、同名不同后缀
220
+ - 命名约定:AGENTS.md 新增「文件命名与物理命名空间约定」小节(前缀即命名空间、
221
+ 两级正交、适用边界、同目录优先不按语言分目录)
222
+ - 规范条款:CONTRIBUTING.md §2 将原「语言边界冲突可下沉语言专属子目录做物理隔离」
223
+ 改为「语言边界适配(不按语言分目录)」——工具链要求目录即成包时,在该功能目录内
224
+ 加同名二级目录与其它语言对齐,禁止在仓库根按语言拆分目录
225
+ - spec 占位:新增 spec/api.md(接口契约)与 spec/behavior.md(行为语义),对齐
226
+ README「项目结构」与 CONTRIBUTING「Spec 驱动与基准验证工作流」的约定,均标注待起草
227
+ - 设计意图:新增 docs/directory-layout-rationale.md,记录约定收益、层级由语言工具链
228
+ 决定、按语言分目录的反例、对 AI 友好的四点与三条不变式;README / CONTRIBUTING /
229
+ AGENTS 各留一处指针
230
+ - 语义一致性:布局与命名约定在 README / CONTRIBUTING / AGENTS / spec 四处表述一致,
231
+ 未涉及代码与构建产物,无版本号与发布信息
232
+ - 验证:人工核对四处表述与交叉链接一致,docs 内引用根文档统一用 ../ 相对链接
233
+ - chore[python]:发布脚本改为自动检测并安装发布依赖
234
+ - publish.ps1 / publish.bat / publish.sh 统一依赖处理流程:先升级 pip 本身(失败回退 --user,再失败仅告警继续,不阻断发布),再按需安装 build、twine
235
+ - 用 importlib.util.find_spec 探测模块是否可用,缺失时用 pip 安装(全局失败回退 --user),装完复检,仍缺失才明确报错
236
+ - pip 自身缺失时先用 python -m ensurepip --upgrade 自举
237
+ - 上传统一改为 python -m twine upload,避免 PATH 中的 twine 指向其它解释器;publish.ps1 与 publish.sh 改为上传已解析出的 sdist 与 wheel 产物
238
+ - publish.ps1 修正 Remove-ReleaseResidualDirs 在项目名尚未解析时触发 StrictMode 报错的问题
239
+ - 三个脚本的头部注释与帮助文本同步说明依赖处理行为
240
+ - 验证:publish.ps1 PowerShell 语法解析通过,实跑 Update-Pip(pip 26.1.1 升级至 26.2.1)与依赖探测、安装失败回退路径;publish.sh 的 bash -n 通过,并以真实 bash 抽取依赖 helper 验证模块存在性探测与安装失败退出码;publish.bat 保持 CRLF 行尾
241
+ - release version 0.0.68
242
+
6
243
  ## [0.0.67] - 2026-09-11
7
244
  ### Changed
8
245
  - fix[c++]:修正 encoding 测试因 boost::pfr 反射类型无外部链接导致的编译失败
@@ -1688,7 +1925,8 @@ All notable changes to this project will be documented in this file.
1688
1925
  - release version 0.0.1
1689
1926
 
1690
1927
 
1691
- [Unreleased]: https://gitee.com/quant1x/mopr/compare/v0.0.67...HEAD
1928
+ [Unreleased]: https://gitee.com/quant1x/mopr/compare/v0.0.68...HEAD
1929
+ [0.0.68]: https://gitee.com/quant1x/mopr/compare/v0.0.67...v0.0.68
1692
1930
  [0.0.67]: https://gitee.com/quant1x/mopr/compare/v0.0.66...v0.0.67
1693
1931
  [0.0.66]: https://gitee.com/quant1x/mopr/compare/v0.0.65...v0.0.66
1694
1932
  [0.0.65]: https://gitee.com/quant1x/mopr/compare/v0.0.64...v0.0.65
@@ -30,9 +30,13 @@ MOPR(Monorepo Optimal Portable Runtime,单仓最优可移植运行时)是*
30
30
  └── (后续引入的其它语言,如 main.go / main.py,同样平铺在此目录)
31
31
  ```
32
32
 
33
+ - **仓库根即实现根(不设 `src/` 层)**:功能模块目录直接平铺在仓库根,作为各语言共同的模块根,模块路径取自同一目录相对路径,保证同一功能在各语言的模块语义相同。
34
+ - **与 Go 的 package 对齐**:Go 的包边界以目录划分,功能模块目录因此与 Go 的 `package` 一一对应(`distributed/id` 即 `package id`);C++ 命名空间第二级(`distributed/id/hlc.h` → `mopr::distributed::id`)、Python 子模块路径、Rust `mod` 路径均取自同一目录路径。
35
+ - **同功能多文件以统一前缀构成物理命名空间**:一个功能拆成多个源文件时,统一以「功能名_」为前缀命名——`strings_camel.go` / `strings_snake.go`、`state_lock_unix.go` / `state_lock_windows.go`、`mmap_posix.go` / `mmap_windows.go` / `mmap_unsupported.go`、`ringbuffer_mpmc_probe.cpp` / `ringbuffer_sched_cost_probe.cpp`;前缀承载功能维度,后缀承载语言与角色维度(`.py` / `.h` / `.cpp` / `.rs` / `.go`、`_posix` / `_windows` / `_test`),使同族文件在目录中自然聚拢、可按前缀检索;功能名已唯一时直接以功能名命名,不强行加前缀。完整约定见 [AGENTS.md](AGENTS.md)「文件命名与物理命名空间约定」。
36
+ - **语言边界适配(不按语言分目录)**:语言工具链要求「目录即成包」时(Go 的 `package`、Java 的包路径),在**该功能目录内**加同名二级目录承载该语言实现,与其它语言保持同名对齐——`base/mmap/mmap.go` 与 `base/mmap.py` 同为 mmap。层级由语言工具链决定、服务于跨语言对齐,**不得**在仓库根按语言拆分语言级目录,把同一功能的各语言实现物理隔离;同目录并列才能形成「看到 `mmap.py` 顺手去看 `mmap.h` / `mmap.rs` / `mmap/mmap.go`」的对照与主动学习。
33
37
  - **语义对齐**:各语言实现的函数签名、命名前缀保持一致,降低跨语言阅读与二次开发成本。
34
- - **语言边界冲突**:若某语言的包/模块边界不允许与其它语言共处一目录(如 Go 的包边界以目录划分),可将该语言实现下沉到语言专属子目录做物理隔离,对外调用语义与命名前缀不变。
35
- - **结构总览**:仓库布局(`spec/`、`src/`、`benchmark/`、`docs/`)见 [README.md](README.md#项目结构)。
38
+ - **结构总览**:仓库布局(`spec/`、功能模块目录、`benchmark/`、`tests/`、`docs/`、`tools/`)见 [README.md](README.md#项目结构)。
39
+ - **设计意图**:上述条款为何如此、同目录并列的收益与反例,见 [docs/directory-layout-rationale.md](docs/directory-layout-rationale.md)。
36
40
 
37
41
  ## 3. 命名与数据契约
38
42
 
@@ -49,6 +53,8 @@ MOPR(Monorepo Optimal Portable Runtime,单仓最优可移植运行时)是*
49
53
 
50
54
  - **边界态**:跨实现落地的数据格式与字段命名属于 Spec 契约,以 `spec/` 为准,禁止各语言实现各自定义一套;字段命名统一小写蛇形。语言命名与契约不一致处(如 Go 结构体标签),通过语言特性映射到契约字段。
51
55
 
56
+ - **C++ 命名空间与头文件宏**:命名空间以项目名 `mopr` 为根、仓库根路径下的子目录为第二级(`distributed/id/hlc.h` → `mopr::distributed::id`,`encoding/csv.h` → `mopr::encoding::csv`);头文件 `#ifndef` 守卫宏为 `MOPR_{大写的目录名}_{文件名}_H`(如 `MOPR_ENCODING_CSV_H`),并与 `#pragma once` 并存。完整规则见 [AGENTS.md](AGENTS.md)「C++ 命名空间与头文件宏约定」。
57
+
52
58
  ## 4. 文档与 AI 协同规范
53
59
 
54
60
  Spec 与模块 `.md` 文档是跨语言实现的**真理之源(Source of Truth)**:业务定义、行为契约、边界与异常处理须在文档中一次性写明,并保持与代码同步。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mopr
3
- Version: 0.0.67
3
+ Version: 0.0.69.dev0
4
4
  Summary: Monorepo Optimal Portable Runtime
5
5
  Author: Quant1X
6
6
  Author-email: Quant1X <wangfengxy@sina.cn>
@@ -87,17 +87,32 @@ mopr/
87
87
  ├── spec/ # 规范定义
88
88
  │ ├── api.md # 接口契约
89
89
  │ └── behavior.md # 行为语义
90
- ├── src/ # MOPR 实现
91
- │ ├── core/ # 平台无关核心
92
- │ └── platform/ # 平台相关极致优化
90
+ ├── base/ # 基础组件:cache / mem / mmap / cron / timestamp ...
91
+ ├── runtime/ # 运行时:ringbuffer / scheduler / once ...
92
+ ├── distributed/ # 分布式:id(HLC / 生成器 / 状态存储)
93
+ ├── encoding/ # 编码:csv / charsets / json / base64 / barcode ...
94
+ ├── storage/ # 存储抽象
95
+ ├── security/ # 安全:auth / audit / compliance
96
+ ├── machine/ # 机器标识
97
+ ├── log/ # 日志
98
+ ├── finance/ # 金融:forex / exchange
93
99
  ├── benchmark/ # 基准测试套件
94
100
  │ ├── micro/ # 微基准:吞吐、延迟、内存
95
101
  │ ├── macro/ # 场景基准:端到端性能
96
102
  │ ├── stability/ # 稳定性:长时间运行、压力、边界
97
103
  │ └── regression/ # 性能回归检测
98
- └── docs/ # 设计决策记录
104
+ ├── tests/ # 跨语言测试用例
105
+ ├── docs/ # 设计决策记录
106
+ └── tools/ # 辅助工具(许可审计、许可证头)
99
107
  ```
100
108
 
109
+ **仓库根即实现根**:不设 `src/` 层,功能模块目录直接平铺在仓库根,同一功能的多语言实现共处同一目录、同名不同后缀(如 `base/mmap.py` / `base/mmap.h` / `base/mmap.rs` / `base/mmap/mmap.go`;各语言入口 `main.cpp` / `main.rs` 同样平铺在根)。
110
+
111
+ - **与 Go 的 package 对齐**:Go 的包边界以目录划分,功能模块目录因此与 Go 的 `package` 一一对应(`distributed/id` 即 `package id`);C++ 命名空间第二级(`distributed/id/hlc.h` → `mopr::distributed::id`)、Python 子模块路径、Rust `mod` 路径均取自同一目录路径,保证同一功能在各语言的模块语义相同。
112
+ - **平台无关核心与平台极致优化就地组织**:核心语义落在各模块的公共实现中,平台相关优化留在同一模块内,按文件名后缀(`_posix` / `_windows` / `_unsupported`)或条件编译区分,不另设 `core/` / `platform/` 目录。
113
+
114
+ 这些约定只服务一件事:**让同一语义在各语言占据同一位置**——看到 `mmap.py`,顺手就能看到 `mmap.h` / `mmap.rs` / `mmap/mmap.go`,跨语言对照不必先找路径。完整论证(层级为何由语言工具链决定、按语言分目录为何是反例、对 AI 的友好之处)见 [docs/directory-layout-rationale.md](docs/directory-layout-rationale.md)。
115
+
101
116
  ## 语言与版本要求
102
117
 
103
118
  MOPR 是单仓多语言库(monolibrary),同一份规范下将来会有多种语言实现。各语言的版本基线由本项目独立维护,不要求与同系列 `quant1x` 仓库同步:
@@ -67,17 +67,32 @@ mopr/
67
67
  ├── spec/ # 规范定义
68
68
  │ ├── api.md # 接口契约
69
69
  │ └── behavior.md # 行为语义
70
- ├── src/ # MOPR 实现
71
- │ ├── core/ # 平台无关核心
72
- │ └── platform/ # 平台相关极致优化
70
+ ├── base/ # 基础组件:cache / mem / mmap / cron / timestamp ...
71
+ ├── runtime/ # 运行时:ringbuffer / scheduler / once ...
72
+ ├── distributed/ # 分布式:id(HLC / 生成器 / 状态存储)
73
+ ├── encoding/ # 编码:csv / charsets / json / base64 / barcode ...
74
+ ├── storage/ # 存储抽象
75
+ ├── security/ # 安全:auth / audit / compliance
76
+ ├── machine/ # 机器标识
77
+ ├── log/ # 日志
78
+ ├── finance/ # 金融:forex / exchange
73
79
  ├── benchmark/ # 基准测试套件
74
80
  │ ├── micro/ # 微基准:吞吐、延迟、内存
75
81
  │ ├── macro/ # 场景基准:端到端性能
76
82
  │ ├── stability/ # 稳定性:长时间运行、压力、边界
77
83
  │ └── regression/ # 性能回归检测
78
- └── docs/ # 设计决策记录
84
+ ├── tests/ # 跨语言测试用例
85
+ ├── docs/ # 设计决策记录
86
+ └── tools/ # 辅助工具(许可审计、许可证头)
79
87
  ```
80
88
 
89
+ **仓库根即实现根**:不设 `src/` 层,功能模块目录直接平铺在仓库根,同一功能的多语言实现共处同一目录、同名不同后缀(如 `base/mmap.py` / `base/mmap.h` / `base/mmap.rs` / `base/mmap/mmap.go`;各语言入口 `main.cpp` / `main.rs` 同样平铺在根)。
90
+
91
+ - **与 Go 的 package 对齐**:Go 的包边界以目录划分,功能模块目录因此与 Go 的 `package` 一一对应(`distributed/id` 即 `package id`);C++ 命名空间第二级(`distributed/id/hlc.h` → `mopr::distributed::id`)、Python 子模块路径、Rust `mod` 路径均取自同一目录路径,保证同一功能在各语言的模块语义相同。
92
+ - **平台无关核心与平台极致优化就地组织**:核心语义落在各模块的公共实现中,平台相关优化留在同一模块内,按文件名后缀(`_posix` / `_windows` / `_unsupported`)或条件编译区分,不另设 `core/` / `platform/` 目录。
93
+
94
+ 这些约定只服务一件事:**让同一语义在各语言占据同一位置**——看到 `mmap.py`,顺手就能看到 `mmap.h` / `mmap.rs` / `mmap/mmap.go`,跨语言对照不必先找路径。完整论证(层级为何由语言工具链决定、按语言分目录为何是反例、对 AI 的友好之处)见 [docs/directory-layout-rationale.md](docs/directory-layout-rationale.md)。
95
+
81
96
  ## 语言与版本要求
82
97
 
83
98
  MOPR 是单仓多语言库(monolibrary),同一份规范下将来会有多种语言实现。各语言的版本基线由本项目独立维护,不要求与同系列 `quant1x` 仓库同步:
@@ -11,7 +11,7 @@ base 各单文件模块的公共函数与类型经 __init__ 直接导出, 业务
11
11
  """
12
12
 
13
13
  # 模块对象保留为包属性; environment 依赖 filesystem, 故 filesystem 在前
14
- from . import cron, dataclass_utils, environment, filesystem, region, strings, time, timestamp
14
+ from . import cron, dataclass_utils, environment, filesystem, mmap, region, strings, time, timestamp
15
15
 
16
16
  # cron
17
17
  from .cron import CronExpr, make_cron, resolve_timezone
@@ -21,6 +21,8 @@ from .dataclass_utils import get_field_names
21
21
  from .filesystem import expand_user, homedir, mkdirs, touch, update_file_mtime
22
22
  # environment
23
23
  from .environment import app_entry, env, getuser, read_dotenv
24
+ # mmap (MappedMemory / MmapHandle 名称过于通用, 连同两层 API 一并保留在 mopr.base.mmap 内)
25
+ from .mmap import MmapError, mmap_open
24
26
  # time
25
27
  from .time import from_rfc1123, get_quarter_by_date, get_timezone_offset_standard, to_rfc1123
26
28
  # timestamp
@@ -41,6 +43,8 @@ __all__ = [
41
43
  "expand_user", "homedir", "mkdirs", "touch", "update_file_mtime",
42
44
  # environment
43
45
  "app_entry", "env", "getuser", "read_dotenv",
46
+ # mmap
47
+ "MmapError", "mmap_open",
44
48
  # time
45
49
  "from_rfc1123", "get_quarter_by_date", "get_timezone_offset_standard", "to_rfc1123",
46
50
  # timestamp