From 573bf22b2bb18c9250fcf3d4b77cac8c85b6bb88 Mon Sep 17 00:00:00 2001 From: david-ajax Date: Thu, 1 Jan 2026 06:36:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=B9=E8=BF=9B=E7=B2=92=E5=AD=90?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/heurams/interface/__init__.py | 2 +- src/heurams/interface/__main__.py | 2 +- src/heurams/interface/screens/about.py | 3 +- src/heurams/interface/screens/dashboard.py | 5 +- src/heurams/interface/screens/intelinote.py | 2 + .../interface/screens/memointegrity.py | 2 + .../screens/{memorizor.py => memoqueue.py} | 3 +- src/heurams/interface/screens/precache.py | 3 +- src/heurams/interface/screens/preparation.py | 5 +- src/heurams/interface/screens/radio.py | 2 + src/heurams/interface/screens/register.py | 0 .../screens/{nucreator.py => repocreator.py} | 3 +- src/heurams/interface/screens/synctool.py | 3 +- src/heurams/interface/screens/type43.py | 0 src/heurams/kernel/particles/atom.py | 75 ++----------------- src/heurams/kernel/particles/electron.py | 10 +-- src/heurams/kernel/particles/nucleon.py | 36 ++++----- src/heurams/kernel/repomgr/repo.py | 2 +- src/heurams/utils/evalizor.py | 49 ++++++------ 19 files changed, 74 insertions(+), 133 deletions(-) create mode 100644 src/heurams/interface/screens/memointegrity.py rename src/heurams/interface/screens/{memorizor.py => memoqueue.py} (99%) create mode 100644 src/heurams/interface/screens/radio.py delete mode 100644 src/heurams/interface/screens/register.py rename src/heurams/interface/screens/{nucreator.py => repocreator.py} (99%) delete mode 100644 src/heurams/interface/screens/type43.py diff --git a/src/heurams/interface/__init__.py b/src/heurams/interface/__init__.py index 8205e2e..a203359 100644 --- a/src/heurams/interface/__init__.py +++ b/src/heurams/interface/__init__.py @@ -6,7 +6,7 @@ from heurams.services.logger import get_logger from .screens.about import AboutScreen from .screens.dashboard import DashboardScreen -from .screens.nucreator import NucleonCreatorScreen +from .screens.repocreator import NucleonCreatorScreen from .screens.precache import PrecachingScreen from .screens.synctool import SyncScreen diff --git a/src/heurams/interface/__main__.py b/src/heurams/interface/__main__.py index a6dae83..8285937 100644 --- a/src/heurams/interface/__main__.py +++ b/src/heurams/interface/__main__.py @@ -7,7 +7,7 @@ from heurams.services.logger import get_logger from .screens.about import AboutScreen from .screens.dashboard import DashboardScreen -from .screens.nucreator import NucleonCreatorScreen +from .screens.repocreator import NucleonCreatorScreen from .screens.precache import PrecachingScreen logger = get_logger(__name__) diff --git a/src/heurams/interface/screens/about.py b/src/heurams/interface/screens/about.py index 915da4c..bd8697a 100644 --- a/src/heurams/interface/screens/about.py +++ b/src/heurams/interface/screens/about.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +"""关于界面 +""" from textual.app import ComposeResult from textual.containers import ScrollableContainer from textual.screen import Screen diff --git a/src/heurams/interface/screens/dashboard.py b/src/heurams/interface/screens/dashboard.py index daea1c0..f3be5c9 100644 --- a/src/heurams/interface/screens/dashboard.py +++ b/src/heurams/interface/screens/dashboard.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +"""仪表盘界面 +""" import pathlib from textual.app import ComposeResult @@ -187,7 +188,7 @@ class DashboardScreen(Screen): button_id = event.button.id if button_id == "new_nucleon_button": - from .nucreator import NucleonCreatorScreen + from .repocreator import NucleonCreatorScreen new_screen = NucleonCreatorScreen() self.app.push_screen(new_screen) diff --git a/src/heurams/interface/screens/intelinote.py b/src/heurams/interface/screens/intelinote.py index e69de29..a667d9c 100644 --- a/src/heurams/interface/screens/intelinote.py +++ b/src/heurams/interface/screens/intelinote.py @@ -0,0 +1,2 @@ +"""笔记界面 +""" \ No newline at end of file diff --git a/src/heurams/interface/screens/memointegrity.py b/src/heurams/interface/screens/memointegrity.py new file mode 100644 index 0000000..3049c4c --- /dev/null +++ b/src/heurams/interface/screens/memointegrity.py @@ -0,0 +1,2 @@ +"""整体式记忆工作界面 +""" \ No newline at end of file diff --git a/src/heurams/interface/screens/memorizor.py b/src/heurams/interface/screens/memoqueue.py similarity index 99% rename from src/heurams/interface/screens/memorizor.py rename to src/heurams/interface/screens/memoqueue.py index 53bb5cf..9bc9149 100644 --- a/src/heurams/interface/screens/memorizor.py +++ b/src/heurams/interface/screens/memoqueue.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +"""队列式记忆工作界面 +""" from enum import Enum, auto from textual.app import ComposeResult diff --git a/src/heurams/interface/screens/precache.py b/src/heurams/interface/screens/precache.py index 4c03bf2..3b24958 100644 --- a/src/heurams/interface/screens/precache.py +++ b/src/heurams/interface/screens/precache.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +"""缓存工具界面 +""" import pathlib from textual.app import ComposeResult diff --git a/src/heurams/interface/screens/preparation.py b/src/heurams/interface/screens/preparation.py index 37de55f..1647807 100644 --- a/src/heurams/interface/screens/preparation.py +++ b/src/heurams/interface/screens/preparation.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +"""记忆准备界面 +""" from textual.app import ComposeResult from textual.containers import ScrollableContainer from textual.reactive import reactive @@ -130,7 +131,7 @@ class PreparationScreen(Screen): if left_new >= 0: atoms_to_provide.append(i) logger.debug(f"ATP: {atoms_to_provide}") - from .memorizor import MemScreen + from .memoqueue import MemScreen memscreen = MemScreen(atoms_to_provide) self.app.push_screen(memscreen) diff --git a/src/heurams/interface/screens/radio.py b/src/heurams/interface/screens/radio.py new file mode 100644 index 0000000..3ccc1dd --- /dev/null +++ b/src/heurams/interface/screens/radio.py @@ -0,0 +1,2 @@ +""""前进电台" 界面 +""" \ No newline at end of file diff --git a/src/heurams/interface/screens/register.py b/src/heurams/interface/screens/register.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/heurams/interface/screens/nucreator.py b/src/heurams/interface/screens/repocreator.py similarity index 99% rename from src/heurams/interface/screens/nucreator.py rename to src/heurams/interface/screens/repocreator.py index 735dda6..ff36b35 100644 --- a/src/heurams/interface/screens/nucreator.py +++ b/src/heurams/interface/screens/repocreator.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +"""仓库创建向导界面 +""" from pathlib import Path import toml diff --git a/src/heurams/interface/screens/synctool.py b/src/heurams/interface/screens/synctool.py index 3d1eebe..4e2c337 100644 --- a/src/heurams/interface/screens/synctool.py +++ b/src/heurams/interface/screens/synctool.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +"""同步工具界面 +""" import pathlib import time diff --git a/src/heurams/interface/screens/type43.py b/src/heurams/interface/screens/type43.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/heurams/kernel/particles/atom.py b/src/heurams/kernel/particles/atom.py index 68ce358..eae9f54 100644 --- a/src/heurams/kernel/particles/atom.py +++ b/src/heurams/kernel/particles/atom.py @@ -3,7 +3,6 @@ import pathlib import typing from typing import TypedDict -import bidict import toml from heurams.context import config_var @@ -20,13 +19,11 @@ class AtomRegister_runtime(TypedDict): min_rate: int # 最低评分 new_activation: bool # 新激活 - class AtomRegister(TypedDict): nucleon: Nucleon electron: Electron runtime: AtomRegister_runtime - class Atom: """ 统一处理一系列对象的所有信息与持久化: @@ -50,61 +47,12 @@ class Atom: "orbital": orbital_obj, "runtime": dict(), } + self.init_runtime() if self.registry["electron"].is_activated() == 0: self.registry["runtime"]["new_activation"] = True def init_runtime(self): self.registry['runtime'] = AtomRegister_runtime(**self.default_runtime) - - def do_eval(self): - """ - 执行并以结果替换当前单元的所有 eval 语句 - TODO: 带有限制的 eval, 异步/多线程执行避免堵塞 - """ - # eval 环境设置 - def eval_with_env(s: str): - default = config_var.get()["puzzles"] - nucleon = self.registry["nucleon"] - payload = nucleon # 兼容历史遗留问题 - metadata = nucleon # 兼容历史遗留问题 - eval_value = eval(s) - if isinstance(eval_value, (int, float)): - ret = str(eval_value) - else: - ret = eval_value - logger.debug( - "eval 执行成功: '%s' -> '%s'", - s, - str(ret)[:50] + "..." if len(ret) > 50 else ret, - ) - return ret - - def traverse(data, modifier): - if isinstance(data, dict): - for key, value in data.items(): - data[key] = traverse(value, modifier) - return data - elif isinstance(data, list): - for i, item in enumerate(data): - data[i] = traverse(item, modifier) - return data - elif isinstance(data, tuple): - return tuple(traverse(item, modifier) for item in data) - else: - if isinstance(data, str): - if data.startswith("eval:"): - logger.debug("发现 eval 表达式: '%s'", data[5:]) - return modifier(data[5:]) - return data - - try: - traverse(self.registry["nucleon"].payload, eval_with_env) - traverse(self.registry["nucleon"].metadata, eval_with_env) - traverse(self.registry["orbital"], eval_with_env) - except Exception as e: - ret = f"此 eval 实例发生错误: {e}" - logger.warning(ret) - logger.debug("EVAL 完成") def minimize(self, rating): """效果等同于 self.registry['runtime']['min_rate'] = min(rating, self.registry['runtime']['min_rate']) @@ -143,22 +91,9 @@ class Atom: logger.debug("禁止总评分") def __getitem__(self, key): - logger.debug("Atom.__getitem__: key='%s'", key) - if key in self.registry: - value = self.registry[key] - logger.debug("返回 value type: %s", type(value).__name__) - return value - logger.error("不支持的键: '%s'", key) - raise KeyError(f"不支持的键: {key}") + return self.registry[key] def __setitem__(self, key, value): - logger.debug( - "Atom.__setitem__: key='%s', value type: %s", key, type(value).__name__ - ) - if key in self.registry: - self.registry[key] = value - logger.debug("键 '%s' 已设置", key) - else: - logger.error("不支持的键: '%s'", key) - raise KeyError(f"不支持的键: {key}") - + if key == "ident": + raise AttributeError("应为只读") + self.registry[key] = value \ No newline at end of file diff --git a/src/heurams/kernel/particles/electron.py b/src/heurams/kernel/particles/electron.py index b6de929..3e0b352 100644 --- a/src/heurams/kernel/particles/electron.py +++ b/src/heurams/kernel/particles/electron.py @@ -7,13 +7,6 @@ import heurams.kernel.algorithms as algolib from copy import deepcopy logger = get_logger(__name__) -class QueryType(TypedDict): - is_due: bool - is_activated: bool - rating: int - nextdate: int - lastdate: int - class Electron: """电子: 单算法支持的记忆数据包装""" @@ -30,9 +23,8 @@ class Electron: self.algodata = algodata self.ident = ident self.algo: algolib.BaseAlgorithm = algorithms[algo_name] - self.query = dict() - if self.algo.check_integrity(self.algodata): + if not self.algo.check_integrity(self.algodata): self.algodata[self.algo.algo_name] = deepcopy(self.algo.defaults) def activate(self): diff --git a/src/heurams/kernel/particles/nucleon.py b/src/heurams/kernel/particles/nucleon.py index 463020e..b836742 100644 --- a/src/heurams/kernel/particles/nucleon.py +++ b/src/heurams/kernel/particles/nucleon.py @@ -1,38 +1,36 @@ from heurams.services.logger import get_logger - +from copy import deepcopy +from heurams.utils.evalizor import Evalizer logger = get_logger(__name__) class Nucleon: - """原子核: 带有运行时隔离的半只读材料元数据容器 + """原子核: 带有运行时隔离的模板化只读材料元数据容器 """ def __init__(self, ident, payload, common): self.ident = ident - self.payload = payload - self.common = common - self.rtlayer = dict() # 运行时层 + env = { + "payload": payload + } + self.evalizer = Evalizer(environment=env) + self.data = self.evalizer(deepcopy((payload | common))) def __getitem__(self, key): if key == "ident": return self.ident - merged = self.rtlayer | self.payload | self.common - return merged[key] + return self.data[key] def __setitem__(self, key, value): - if key == "ident": - raise AttributeError("ident 应为只读") - else: - self.rtlayer[key] = value - + raise AttributeError("应为只读") + def __delitem__(self, key): - raise AttributeError("Nucleon 包含的数据被设计为无法删除") + raise AttributeError("应为只读") def __iter__(self): - merged = self.rtlayer | self.payload | self.common - return iter(merged) + return iter(self.data) def __contains__(self, key): - return key in (self.rtlayer | self.payload | self.common) + return key in (self.data) def get(self, key, default=None): if key in self: @@ -40,12 +38,10 @@ class Nucleon: return default def __len__(self): - return len(self.rtlayer | self.payload | self.common) + return len(self.data) def __repr__(self): - return f"""RUNTIME:{repr(self.rtlayer)} - PAYLOAD:{repr(self.payload)} - COMMON:{repr(self.common)}""" + return repr(self.data) @staticmethod def create_on_nucleonic_data(nucleonic_data: tuple): diff --git a/src/heurams/kernel/repomgr/repo.py b/src/heurams/kernel/repomgr/repo.py index 5750db5..e7e1e67 100644 --- a/src/heurams/kernel/repomgr/repo.py +++ b/src/heurams/kernel/repomgr/repo.py @@ -43,7 +43,7 @@ class Repo(): self.generate_particles_data() def generate_particles_data(self): - self.nucleonic_data_lict = Lict(list(map(self._attach(self.typedef), self.payload))) + self.nucleonic_data_lict = Lict(initlist=list(map(self._attach(self.typedef), self.payload))) self.electronic_data_lict = self.algodata @staticmethod diff --git a/src/heurams/utils/evalizor.py b/src/heurams/utils/evalizor.py index 65176b5..0638cd0 100644 --- a/src/heurams/utils/evalizor.py +++ b/src/heurams/utils/evalizor.py @@ -1,28 +1,33 @@ - -from typing import Any - - class Evalizer(): + """几乎无副作用的模板系统 + + 接受环境信息并创建一个模板解析工具, 工具传入参数支持list, dict及其嵌套 + 副作用问题: 仅存在于 eval 函数 + """ + # TODO: 弃用风险极高的 eval + # 理论上已经限制了全局函数 但eval仍有风险 + # TODO: 异步/多线程执行避免堵塞 def __init__(self, environment: dict) -> None: self.env = environment - def __call__(self, *args: Any, **kwds: Any) -> Any: - - -def do_eval(self): - """ - 执行并以结果替换当前单元的所有 eval 语句 - TODO: 带有限制的 eval, 异步/多线程执行避免堵塞 - """ - - # eval 环境设置 - def eval_with_env(s: str): - default = config_var.get()["puzzles"] - payload = self.registry["nucleon"].payload - metadata = self.registry["nucleon"].metadata - eval_value = eval(s) - if isinstance(eval_value, (int, float)): - ret = str(eval_value) + def __call__(self, anyobj): + return self.travel(anyobj) + + def travel(self, anyobj): + if isinstance(anyobj, list): + return list(map(self.travel, anyobj)) + elif isinstance(anyobj, dict): + return dict(map(self.travel, anyobj.items())) + elif isinstance(anyobj, str): + if anyobj.startswith("eval:"): + return self.eval_with_env(anyobj[5:]) + else: + return anyobj else: - ret = eval_value + return anyobj + + def eval_with_env(self, s: str): + ret = eval(s, {}, self.env) + if not isinstance(ret, str): + ret = str(ret) return ret \ No newline at end of file