muninn-cli 0.1.1__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 (42) hide show
  1. muninn_cli-0.1.1/.agent/api.md +193 -0
  2. muninn_cli-0.1.1/.agent/plan.md +124 -0
  3. muninn_cli-0.1.1/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  4. muninn_cli-0.1.1/.github/ISSUE_TEMPLATE/feature_request.md +26 -0
  5. muninn_cli-0.1.1/.github/workflows/ci.yml +57 -0
  6. muninn_cli-0.1.1/.github/workflows/publish.yml +31 -0
  7. muninn_cli-0.1.1/.gitignore +218 -0
  8. muninn_cli-0.1.1/.python-version +1 -0
  9. muninn_cli-0.1.1/.vscode/settings.json +5 -0
  10. muninn_cli-0.1.1/LICENSE +21 -0
  11. muninn_cli-0.1.1/PKG-INFO +196 -0
  12. muninn_cli-0.1.1/README.md +176 -0
  13. muninn_cli-0.1.1/README_zh.md +174 -0
  14. muninn_cli-0.1.1/example/chemistry/elements.json +38 -0
  15. muninn_cli-0.1.1/example/chemistry/manifest.json +7 -0
  16. muninn_cli-0.1.1/example/chemistry/plugin.py +53 -0
  17. muninn_cli-0.1.1/example/flashcard/manifest.json +7 -0
  18. muninn_cli-0.1.1/example/flashcard/plugin.py +5 -0
  19. muninn_cli-0.1.1/example/flashcard/words.csv +11 -0
  20. muninn_cli-0.1.1/main.py +6 -0
  21. muninn_cli-0.1.1/pyproject.toml +45 -0
  22. muninn_cli-0.1.1/scripts/bump_version.py +109 -0
  23. muninn_cli-0.1.1/src/__init__.py +0 -0
  24. muninn_cli-0.1.1/src/cli/__init__.py +0 -0
  25. muninn_cli-0.1.1/src/cli/manager.py +161 -0
  26. muninn_cli-0.1.1/src/cli/runner.py +121 -0
  27. muninn_cli-0.1.1/src/core/__init__.py +0 -0
  28. muninn_cli-0.1.1/src/core/base_plugin.py +32 -0
  29. muninn_cli-0.1.1/src/core/helpers.py +205 -0
  30. muninn_cli-0.1.1/src/core/scheduler.py +44 -0
  31. muninn_cli-0.1.1/src/core/state.py +62 -0
  32. muninn_cli-0.1.1/src/main.py +91 -0
  33. muninn_cli-0.1.1/src/ui.py +47 -0
  34. muninn_cli-0.1.1/tests/__init__.py +0 -0
  35. muninn_cli-0.1.1/tests/cli/__init__.py +0 -0
  36. muninn_cli-0.1.1/tests/cli/test_manager.py +182 -0
  37. muninn_cli-0.1.1/tests/conftest.py +92 -0
  38. muninn_cli-0.1.1/tests/core/__init__.py +0 -0
  39. muninn_cli-0.1.1/tests/core/test_helpers.py +280 -0
  40. muninn_cli-0.1.1/tests/core/test_scheduler.py +60 -0
  41. muninn_cli-0.1.1/tests/core/test_state.py +74 -0
  42. muninn_cli-0.1.1/uv.lock +108 -0
@@ -0,0 +1,193 @@
1
+ # Muninn API 扩展规划 - 面向插件开发者的辅助层
2
+
3
+ ## 背景:当前问题
4
+
5
+ 以 `example/chemistry/plugin.py` 为例,开发者目前需要:
6
+
7
+ 1. 手动维护一个 `self.problems` 字典,每个 "方向" 都需要完整填写 `type`, `element`, `statement`, `expected` 字段
8
+ 2. 在 `check_answer` 中用 `if q_type == ...` 分支处理不同题型的判题逻辑
9
+ 3. 自己实现所有容错匹配(忽略大小写、空格、输入顺序等)
10
+ 4. 即使是最简单的正反面闪卡,也要实现全部 5 个抽象方法
11
+
12
+ ---
13
+
14
+ ## 目标:降低插件开发者的心智负担
15
+
16
+ Muninn 的 `src/core/` 层新增一组 **辅助工具 (Helpers)**,让开发者专注于"数据"和"语义",而不是"胶水代码"。
17
+
18
+ ---
19
+
20
+ ## 1. `QuestionType` —— 可复用的题型单元
21
+
22
+ ### 设计思路
23
+
24
+ 把"一种问答方向"抽象成一个独立的 `QuestionType` 对象。它封装了三件事:
25
+
26
+ - 如何**渲染**题目(给定数据项,生成题目文本)
27
+ - 如何**渲染**预期答案(给定数据项,生成标准答案文本)
28
+ - 如何**判断**用户输入是否正确(使用内置的 Matcher,详见第 2 节)
29
+
30
+ ```python
31
+ # 插件开发者的代码
32
+ from core.helpers import QuestionType, Matchers
33
+
34
+ # 把一种"问答方向"声明为一行
35
+ q_num_to_element = QuestionType(
36
+ label="看序号背元素",
37
+ statement=lambda el: f"原子序数: {el['num']}",
38
+ answer=lambda el: f"{el['name']} {el['sym']}",
39
+ matcher=Matchers.chinese_symbol_pair("name", "sym"), # 内置容错匹配
40
+ )
41
+ ```
42
+
43
+ ### 注册到插件
44
+
45
+ ```python
46
+ class Plugin(BaseRecitePlugin):
47
+ QUESTION_TYPES = [
48
+ QuestionType(
49
+ label="看序号背元素",
50
+ statement=lambda el: f"原子序数: {el['num']}",
51
+ answer=lambda el: f"{el['name']} {el['sym']}",
52
+ matcher=Matchers.chinese_symbol_pair("name", "sym"),
53
+ ),
54
+ QuestionType(
55
+ label="看元素背序号",
56
+ statement=lambda el: f"元素: {el['name']} ({el['sym']})",
57
+ answer=lambda el: str(el["num"]),
58
+ matcher=Matchers.exact_integer("num"),
59
+ ),
60
+ ]
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 2. `Matchers` —— 内置容错匹配器
66
+
67
+ 常见的输入容错逻辑不应该由每个插件重复实现。Muninn 提供一组开箱即用的 Matcher 工厂函数:
68
+
69
+ | Matcher | 说明 | 示例 |
70
+ | ------------------------------------------ | ------------------------------------------------ | ------------------------- |
71
+ | `Matchers.exact(key)` | 精确匹配某字段(去除首尾空格) | 完全相同的字符串 |
72
+ | `Matchers.exact_integer(key)` | 只提取数字后精确匹配 | `" 17 "` / `"#17"` → `17` |
73
+ | `Matchers.case_insensitive(key)` | 忽略大小写匹配 | 英文单词背诵 |
74
+ | `Matchers.chinese_symbol_pair(key1, key2)` | 匹配"中文+符号"或"符号+中文"任意顺序,忽略空格 | `氢H` / `H氢` / `氢 H` |
75
+ | `Matchers.any_order(*keys)` | 多个字段任意顺序输入,忽略分隔符 | 周期+族 `4 IVB` / `IVB4` |
76
+ | `Matchers.custom(fn)` | 传入自定义函数 `(data_item, user_input) -> bool` | 完全自由扩展 |
77
+
78
+ ---
79
+
80
+ ## 3. `DataPlugin` —— 面向"实体+多题型"场景的高阶基类
81
+
82
+ ### 设计思路
83
+
84
+ 当一组 `QuestionType` 需要应用到一批数据上("每条数据 × 每种题型 = 一道题"),这个模式极其常见。`DataPlugin` 是 `BaseRecitePlugin` 的子类,它自动完成 ID 生成、问题注册和方法路由,开发者只需提供:
85
+
86
+ 1. 数据加载逻辑 `load_records()` → 返回记录列表
87
+ 2. 题型列表 `QUESTION_TYPES`
88
+ 3. 可选的过滤器 `filter(record, q_type)` → 某条数据是否参与某种题型
89
+
90
+ ### 改写后的 chemistry plugin(从 87 行缩减到 ~40 行)
91
+
92
+ ```python
93
+ import os
94
+ import json
95
+ from core.helpers import DataPlugin, QuestionType, Matchers
96
+
97
+
98
+ class Plugin(DataPlugin):
99
+ QUESTION_TYPES = [
100
+ QuestionType(
101
+ label="看序号背元素",
102
+ statement=lambda el: f"原子序数: {el['num']}",
103
+ answer=lambda el: f"{el['name']} {el['sym']}",
104
+ matcher=Matchers.chinese_symbol_pair("name", "sym"),
105
+ ),
106
+ QuestionType(
107
+ label="看元素背序号",
108
+ statement=lambda el: f"元素: {el['name']} ({el['sym']})",
109
+ answer=lambda el: str(el["num"]),
110
+ matcher=Matchers.exact_integer("num"),
111
+ ),
112
+ QuestionType(
113
+ label="看位置背元素",
114
+ statement=lambda el: f"位置: 第{el['period']}周期 {el['group']}族",
115
+ answer=lambda el: f"{el['name']} {el['sym']}",
116
+ matcher=Matchers.chinese_symbol_pair("name", "sym"),
117
+ ),
118
+ QuestionType(
119
+ label="看元素背位置",
120
+ statement=lambda el: f"元素: {el['name']} ({el['sym']})",
121
+ answer=lambda el: f"{el['period']} {el['group']}",
122
+ matcher=Matchers.any_order("period", "group"),
123
+ ),
124
+ ]
125
+
126
+ def load_records(self) -> list:
127
+ with open(
128
+ os.path.join(self.workspace_dir, "elements.json"), encoding="utf-8"
129
+ ) as f:
130
+ return json.load(f)
131
+
132
+ def filter(self, record: dict, q_type: QuestionType) -> bool:
133
+ """过滤掉 0 族元素的位置类题目"""
134
+ if q_type.label in ("看位置背元素", "看元素背位置"):
135
+ return record["group"] != "0"
136
+ return True
137
+
138
+ def get_expand_info(self, problem_id: str) -> str:
139
+ el, _ = self._resolve(problem_id)
140
+ return f"{el['eng']} ({el['sym']}, {el['name']}) - 第{el['period']}周期 {el['group']}族"
141
+ ```
142
+
143
+ ---
144
+
145
+ ## 4. `FlashcardPlugin` —— 最简单的闪卡场景
146
+
147
+ 对于纯粹的"正面→背面"记忆(如 GRE 单词、古诗词),提供一个更高阶的 `FlashcardPlugin`,实现 0 样板代码的目标:
148
+
149
+ ```python
150
+ # flashcard 格式 CSV / JSON:每条数据有 front, back 两个字段即可
151
+ class Plugin(FlashcardPlugin):
152
+ DATA_FILE = "words.csv"
153
+
154
+ # FlashcardPlugin 自动实现 load_records, get_all_problem_ids,
155
+ # render_statement, check_answer, get_expected_display
156
+ # 开发者完全不需要写任何一行额外代码(除非需要定制)
157
+ ```
158
+
159
+ ---
160
+
161
+ ## 5. 实现计划
162
+
163
+ ### Phase 1:`Matchers` + `QuestionType`
164
+
165
+ - 在 `src/core/helpers.py` 中实现 `Matchers` 工具类和 `QuestionType` 数据类
166
+ - 无需修改 `BaseRecitePlugin`,完全向后兼容
167
+
168
+ ### Phase 2:`DataPlugin`
169
+
170
+ - 在 `src/core/helpers.py` 中实现 `DataPlugin(BaseRecitePlugin)` 子类
171
+ - 将 `example/chemistry/plugin.py` 改写为 `DataPlugin` 版本作为验证
172
+
173
+ ### Phase 3:`FlashcardPlugin`
174
+
175
+ - 支持从 CSV/JSON 自动加载 `front/back` 格式数据
176
+ - 提供一个示例闪卡包(如 GRE 单词)验证
177
+
178
+ ---
179
+
180
+ ## 附:改动涉及文件
181
+
182
+ ```text
183
+ src/
184
+ └── core/
185
+ ├── base_plugin.py # 不变
186
+ ├── helpers.py # ✅ 新增:QuestionType, Matchers, DataPlugin, FlashcardPlugin
187
+ ├── scheduler.py # 不变
188
+ └── state.py # 不变
189
+
190
+ example/
191
+ ├── chemistry/plugin.py # ✅ 改写为 DataPlugin 版本(用于验证)
192
+ └── flashcard/ # ✅ 新增:FlashcardPlugin 示例包
193
+ ```
@@ -0,0 +1,124 @@
1
+ # Muninn - 架构设计与项目规划
2
+
3
+ ## 1. 核心设计理念:宿主与插件架构
4
+
5
+ 本项目旨在将“背诵软件”解耦为一个 **“宿主容器 (Host)”** 和若干 **“背诵包插件 (Plugins)”**。
6
+
7
+ - **宿主 (CLI Framework)**:负责题目的调度算法(如按权重出题)、界面渲染、用户输入捕获、题库包的管理(导入/导出)以及进度的持久化存储。
8
+ - **插件 (Recite Pack)**:负责定义具体的题目逻辑,包含静态数据(如元素周期表、古诗文内容)和出题/判题的 Python 脚本。
9
+
10
+ 这种架构能让用户自由开发、导入和导出第三方题库包,极大地提高了可扩展性。
11
+
12
+ ---
13
+
14
+ ## 2. “背诵包”的规范定义 (Package Specification)
15
+
16
+ 一个标准的背诵包在物理上是一个独立的文件夹,分发时可打包为 `.zip`,结构如下:
17
+
18
+ ```text
19
+ chemistry/
20
+ ├── manifest.json # 包的元数据 (包名、包ID、作者、版本、描述、当前版本哈希)
21
+ ├── data.csv # 静态数据 (也可以是 json, yaml, sqlite 或媒体资源)
22
+ └── plugin.py # 核心逻辑脚本 (必须实现 CLI 规定的标准接口)
23
+ ```
24
+
25
+ ---
26
+
27
+ ## 3. 标准化 API 契约 (Plugin API Contract)
28
+
29
+ 所有导入的 `plugin.py` 必须提供一个继承自 `BaseRecitePlugin` 的主类。CLI 会在初始化时将专用的工作区路径 (`workspace_dir`) 传给该插件,插件需从该路径加载自己的静态数据。
30
+
31
+ ```python
32
+ class BaseRecitePlugin:
33
+ def __init__(self, workspace_dir: str):
34
+ """
35
+ 初始化插件
36
+ :param workspace_dir: CLI 分配给该包的私有静态数据目录
37
+ """
38
+ self.workspace_dir = workspace_dir
39
+ self.load_data()
40
+
41
+ def load_data(self):
42
+ """加载 workspace_dir 中的静态数据,由子类实现"""
43
+ pass
44
+
45
+ def get_all_problem_ids(self) -> list[str]:
46
+ """返回题库中所有题目的唯一 ID,供 CLI 调度器建立索引和存档进度"""
47
+ raise NotImplementedError
48
+
49
+ def render_statement(self, problem_id: str) -> str:
50
+ """根据题目 ID 返回要在终端显示的问题文本"""
51
+ raise NotImplementedError
52
+
53
+ def check_answer(self, problem_id: str, user_input: str) -> bool:
54
+ """回调函数:判断用户输入是否正确"""
55
+ raise NotImplementedError
56
+
57
+ def get_expected_display(self, problem_id: str) -> str:
58
+ """回答错误时,展示给用户的标准答案"""
59
+ raise NotImplementedError
60
+
61
+ def get_expand_info(self, problem_id: str) -> str:
62
+ """回答正确时,展示给用户的拓展/提示信息 (可选)"""
63
+ return ""
64
+ ```
65
+
66
+ ---
67
+
68
+ ## 4. CLI 宿主的四大职责 (CLI Core Responsibilities)
69
+
70
+ 1. **包管理器 (Package Manager)**
71
+ - `new`: 在当前工作目录生成一个标准的背诵包插件模板(包含 `manifest.json`, 示例 `plugin.py` 和数据文件),方便用户快速开始自己的开发。
72
+ - `import`: 接收一个本地的文件夹路径或 `.zip` 压缩包,将其拷贝/解压至 `~/.muninn/packs/<pack_id>/`,并校验完整性。如果本地已经有该包的旧版本,应该覆盖为新版本。
73
+ - `loader`: 使用 `importlib` 动态加载包内的 `plugin.py`。
74
+ 2. **状态与存储管理器 (State Manager)**
75
+ - **进度隔离**:进度的存储(答对次数、耗时)绝对不能放在包的 `workspace_dir` 中,以防止导出时泄露私人数据。
76
+ - 所有进度集中存放在 `~/.muninn/states/<pack_id>.db`。
77
+ 3. **全局调度算法 (Global Scheduler)**
78
+ - 提取自当前的智能权重逻辑。接管出题顺序,在内存中维护优先队列。
79
+ 4. **统一终端 UI (Terminal UI)**
80
+ - 负责 ANSI 颜色输出、清屏操作、数据统计的 banner 显示及捕捉用户输入。
81
+
82
+ ---
83
+
84
+ ## 5. 工作流示例 (Workflow)
85
+
86
+ 当用户运行命令 `muninn run my_chemistry_pack` 时:
87
+
88
+ 1. **CLI 启动**:定位到 `~/.muninn/packs/my_chemistry_pack/`。
89
+ 2. **实例化插件**:初始化插件并传入 `workspace_dir`,插件完成数据加载。
90
+ 3. **初始化调度**:CLI 调用 `get_all_problem_ids()`,并从 State Manager 读取每个题目的权重,压入堆中。
91
+ 4. **游戏循环**:
92
+ - 调度器弹出一道题的 ID。
93
+ - CLI 调用 `render_statement(ID)` 打印题目。
94
+ - CLI 截获用户输入 `user_input`。
95
+ - CLI 将其传给插件:`check_answer(ID, user_input)`。
96
+ - 得到 True/False 后,CLI 更新权重并保存状态,打印拓展信息或标准答案。
97
+ - 循环往复。
98
+
99
+ ---
100
+
101
+ ## 6. 项目系统目录架构
102
+
103
+ ```text
104
+ muninn/ # 源码库目录
105
+ ├── src/ # 核心源码
106
+ │ ├── core/
107
+ │ │ ├── base_plugin.py # 插件基类 API 契约
108
+ │ │ ├── scheduler.py # 权重与出题队列调度算法
109
+ │ │ └── state.py # 学习进度持久化管理
110
+ │ ├── cli/
111
+ │ │ ├── manager.py # New/Import 包管理模块
112
+ │ │ └── runner.py # 核心游戏循环 (整合 UI, Plugin, Scheduler)
113
+ │ └── ui.py # 终端渲染与颜色控制
114
+ └── pyproject.toml # 使用 uv 管理依赖,打包配置,注册全局命令 'muninn'
115
+
116
+ ~/.muninn/ # App Data 目录 (程序运行时在用户系统生成)
117
+ ├── packs/ # 统一存放通过 import 导入的第三方题库包
118
+ │ └── chemistry/ # 具体的包目录 (被当作 workspace_dir)
119
+ │ ├── manifest.json
120
+ │ ├── data.csv
121
+ │ └── plugin.py
122
+ └── states/ # 进度隔离存储
123
+ └── chemistry.db # 记录该题库中所有题目的熟练度和学习数据
124
+ ```
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: "\U0001F41E Bug Report"
3
+ about: "报告一个问题 / Report a bug"
4
+ labels: ["bug"]
5
+ assignees: ["a1fredbao"]
6
+ ---
7
+
8
+ ## 🐛 问题描述 / Bug Description
9
+
10
+ <!-- 简要描述你遇到的问题 / Briefly describe the bug -->
11
+
12
+ ## 📋 复现步骤 / Steps to Reproduce
13
+
14
+ 1.
15
+ 2.
16
+ 3.
17
+
18
+ ## 🤔 期望行为 / Expected Behavior
19
+
20
+ <!-- 描述你期望看到的正确行为 / What did you expect to happen? -->
21
+
22
+ ## 😱 实际行为 / Actual Behavior
23
+
24
+ <!-- 描述实际发生了什么 / What actually happened? -->
25
+
26
+ ## 🖥️ 环境信息 / Environment
27
+
28
+ - **OS**:
29
+ - **Python version**: <!-- `python --version` -->
30
+ - **Muninn version**: <!-- `muninn --version` or `pip show muninn` -->
31
+ - **Pack ID** (if applicable):
32
+
33
+ ## 📎 错误日志 / Error Log
34
+
35
+ ```text
36
+ 粘贴错误信息 / Paste error output here
37
+ ```
38
+
39
+ ## 📝 补充信息 / Additional Context
40
+
41
+ <!-- 其他你认为相关的信息 / Any other context about the problem -->
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: "\U0001F680 Feature Request"
3
+ about: "建议一个新功能 / Suggest a new feature or improvement"
4
+ labels: ["enhancement"]
5
+ assignees: ["a1fredbao"]
6
+ ---
7
+
8
+ ## 🚀 功能描述 / Feature Description
9
+
10
+ <!-- 简要描述你希望增加的功能 / Briefly describe the feature you'd like -->
11
+
12
+ ## 💡 动机与背景 / Motivation & Context
13
+
14
+ <!-- 为什么需要这个功能?它解决了什么问题? / Why is this feature needed? What problem does it solve? -->
15
+
16
+ ## 🎯 建议方案 / Proposed Solution
17
+
18
+ <!-- 如果你有实现思路,请描述 / If you have ideas on how to implement this, describe them -->
19
+
20
+ ## 🔄 替代方案 / Alternatives Considered
21
+
22
+ <!-- 你是否考虑过其他解决方案? / Have you considered any alternative solutions? -->
23
+
24
+ ## 📝 补充信息 / Additional Context
25
+
26
+ <!-- 截图、草图、参考链接等 / Screenshots, mockups, reference links, etc. -->
@@ -0,0 +1,57 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: ["**"]
6
+ pull_request:
7
+ branches: ["**"]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout code
15
+ uses: actions/checkout@v7
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v9.0.0
19
+ with:
20
+ version: "latest"
21
+
22
+ - name: Set up Python
23
+ run: uv python install
24
+
25
+ - name: Install dependencies
26
+ run: uv sync
27
+
28
+ - name: Run Ruff (linter)
29
+ run: uv run ruff check src/
30
+
31
+ - name: Run Ruff (formatter check)
32
+ run: uv run ruff format --check src/
33
+
34
+ test:
35
+ name: Test (${{ matrix.os }})
36
+ runs-on: ${{ matrix.os }}
37
+ needs: lint
38
+ strategy:
39
+ matrix:
40
+ os: [ubuntu-latest, macos-latest, windows-latest]
41
+ steps:
42
+ - name: Checkout code
43
+ uses: actions/checkout@v7
44
+
45
+ - name: Install uv
46
+ uses: astral-sh/setup-uv@v9.0.0
47
+ with:
48
+ version: "latest"
49
+
50
+ - name: Set up Python
51
+ run: uv python install
52
+
53
+ - name: Install dependencies
54
+ run: uv sync
55
+
56
+ - name: Run tests
57
+ run: uv run pytest tests/ -v
@@ -0,0 +1,31 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ name: Build and Publish
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write
14
+
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v7
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v9.0.0
21
+ with:
22
+ version: "latest"
23
+
24
+ - name: Set up Python
25
+ run: uv python install
26
+
27
+ - name: Build package
28
+ run: uv build
29
+
30
+ - name: Publish to PyPI
31
+ run: uv publish
@@ -0,0 +1,218 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,5 @@
1
+ {
2
+ "cSpell.words": [
3
+ "muninn"
4
+ ]
5
+ }