aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/infini/core.py16
-rw-r--r--src/infini/exceptions.py4
-rw-r--r--src/infini/generator.py48
-rw-r--r--src/infini/loader.py26
-rw-r--r--src/infini/output.py6
-rw-r--r--src/infini/register.py30
-rw-r--r--src/infini/typing.py14
7 files changed, 115 insertions, 29 deletions
diff --git a/src/infini/core.py b/src/infini/core.py
index 08b81f15..7c84a15f 100644
--- a/src/infini/core.py
+++ b/src/infini/core.py
@@ -1,23 +1,23 @@
from infini.input import Input
from infini.interceptor import Interceptor
-from infini.generator import TextGenerator
+from infini.generator import Generator
from infini.handler import Handler
from infini.injector import Injector
from infini.output import Output
-from infini.typing import Any, Generator, Union
+from infini.typing import Any, Generator as GeneratorT, Union
from infini.exceptions import ValueError
class Core:
pre_interceptor: Interceptor
handler: Handler
- generator: TextGenerator
+ generator: Generator
interceptor: Interceptor
injector: Injector
def input(
self, input: Input
- ) -> Generator[Union[str, Output], Any, None]: # TODO 支持Workflow
+ ) -> GeneratorT[Union[str, Output], Any, None]:
for pre_intercepted_stream in self.pre_intercept(input):
if isinstance(pre_intercepted_stream, Output):
if not isinstance(pre_intercepted_stream, Output):
@@ -53,10 +53,12 @@ class Core:
if handled_stream.block:
return
- def pre_intercept(self, input: Input) -> Generator[Union[Input, Output], Any, None]:
+ def pre_intercept(
+ self, input: Input
+ ) -> GeneratorT[Union[Input, Output], Any, None]:
return self.pre_interceptor.input(input)
- def handle(self, input: Input) -> Generator[Output, Any, None]:
+ def handle(self, input: Input) -> GeneratorT[Output, Any, None]:
iterator = self.handler.input(input)
for output in iterator:
yield output
@@ -66,5 +68,5 @@ class Core:
def intercept(
self, output: Output, output_text: str
- ) -> Generator[Union[str, Output], Any, None]:
+ ) -> GeneratorT[Union[str, Output], Any, None]:
return self.interceptor.output(output, output_text)
diff --git a/src/infini/exceptions.py b/src/infini/exceptions.py
index 37386ce3..2e2b0197 100644
--- a/src/infini/exceptions.py
+++ b/src/infini/exceptions.py
@@ -10,5 +10,9 @@ class UnknownEvent(InfiniException):
"""文本事件不存在"""
+class UnknownEventType(InfiniException, TypeError):
+ """文本事件不存在"""
+
+
class ValueError(InfiniException, ValueError):
"""错误的数据"""
diff --git a/src/infini/generator.py b/src/infini/generator.py
index 5473dade..254f0cdd 100644
--- a/src/infini/generator.py
+++ b/src/infini/generator.py
@@ -1,20 +1,37 @@
from infini.output import Output
-from infini.typing import Dict, Callable, Union
-from infini.exceptions import UnknownEvent
+from infini.typing import Type, Dict, Callable, Union, Optional
+from infini.exceptions import UnknownEvent, UnknownEventType
from infini.injector import Injector
from jinja2 import Template
+import abc
-class TextGenerator: # TODO 兼容多类型事件
+
+class BaseGenerator(metaclass=abc.ABCMeta):
+ type: str
events: Dict[str, str]
global_variables: Dict[str, Union[str, Callable]]
+ @abc.abstractmethod
+ def output(self, output: Output, injector: Injector) -> str:
+ raise NotImplementedError
+
+ @abc.abstractmethod
+ def match(self, output: Output) -> Template:
+ raise NotImplementedError
+
+
+class TextGenerator(BaseGenerator):
+ type = "text"
+
def __init__(self) -> None:
self.events = {}
self.global_variables = {}
def output(self, output: Output, injector: Injector) -> str:
- assert output.type == "text", "文本生成器应当传入类型为 'text' 的 Output 实例"
+ assert (
+ output.type == self.type
+ ), f"文本生成器应当传入类型为 '{self.type}' 的 Output 实例"
variables = self.global_variables.copy()
variables.update(output.variables)
for name, variable in variables.items():
@@ -26,3 +43,26 @@ class TextGenerator: # TODO 兼容多类型事件
if context := self.events.get(output.name):
return Template(context)
raise UnknownEvent(f"事件不存在: {output.name}")
+
+
+class Generator:
+ generators: Dict[str, BaseGenerator]
+ events: Dict[str, str]
+ global_variables: Dict[str, Union[str, Callable]]
+
+ def __init__(self) -> None:
+ self.generators = {"text": TextGenerator()}
+
+ def output(self, output: Output, injector: Injector) -> str:
+ assert (
+ output.type != "workflow"
+ ), "生成器应当传入类型为非 'workflow' 的 Output 实例"
+ if not (generator := self.match(output)):
+ raise UnknownEventType(f"没有为事件类型 '{output.type}' 注册生成器")
+
+ generator.events = self.events
+ generator.global_variables = self.global_variables
+ return generator.output(output, injector)
+
+ def match(self, output: Output) -> Optional[BaseGenerator]:
+ return self.generators.get(output.type)
diff --git a/src/infini/loader.py b/src/infini/loader.py
index 061ed8b9..07ebe0a8 100644
--- a/src/infini/loader.py
+++ b/src/infini/loader.py
@@ -1,6 +1,6 @@
from importlib.util import spec_from_file_location
from infini.core import Core
-from infini.generator import TextGenerator
+from infini.generator import BaseGenerator, Generator, TextGenerator
from infini.handler import Handler
from infini.injector import Injector
from infini.interceptor import Interceptor
@@ -81,15 +81,17 @@ class InfiniLoader(importlib.abc.Loader):
exec(Path(self.filename).read_text("utf-8"), vars(module))
-def install():
- sys.meta_path.insert(0, InfiniMetaFinder())
+def _install():
+ if not sys.meta_path:
+ raise OSError("Var 'sys.meta_path' is empty, since Python is stop.")
+ if not isinstance(sys.meta_path[0], InfiniMetaFinder):
+ sys.meta_path.insert(0, InfiniMetaFinder())
-def uninstall():
+def _uninstall():
for meta_path in sys.meta_path:
if isinstance(meta_path, InfiniMetaFinder):
sys.meta_path.remove(meta_path)
- break
class Loader:
@@ -98,6 +100,7 @@ class Loader:
events: Dict[str, str]
global_variables: Dict[str, Union[str, Callable]]
interceptors: List[RouterType]
+ generators: Dict[str, BaseGenerator]
def __init__(self) -> None:
self.pre_interceptors = []
@@ -105,6 +108,7 @@ class Loader:
self.events = {}
self.global_variables = {}
self.interceptors = []
+ self.generators = {}
self.prepare()
def __enter__(self) -> "Loader":
@@ -124,7 +128,7 @@ class Loader:
return register_variables
def prepare(self) -> None:
- install()
+ _install()
def load(self, name: str) -> ModuleType:
self.prepare()
@@ -168,7 +172,7 @@ class Loader:
return list
def close(self):
- uninstall()
+ _uninstall()
def inject_core(self, core: Core):
pre_interceptor = Interceptor()
@@ -176,6 +180,7 @@ class Loader:
generator = TextGenerator()
interceptor = Interceptor()
injector = Injector()
+ generator = Generator()
self.inject_pre_interceptor(pre_interceptor)
self.inject_handler(handler)
@@ -221,12 +226,13 @@ class Loader:
self.inject_handler(handler)
return handler
- def inject_generator(self, generator: TextGenerator):
+ def inject_generator(self, generator: Generator):
generator.events = self.events
generator.global_variables = self.global_variables
+ generator.generators.update(self.generators)
- def into_generator(self) -> TextGenerator:
- generator = TextGenerator()
+ def into_generator(self) -> Generator:
+ generator = Generator()
self.inject_generator(generator)
return generator
diff --git a/src/infini/output.py b/src/infini/output.py
index 73aa5213..13f26d47 100644
--- a/src/infini/output.py
+++ b/src/infini/output.py
@@ -1,8 +1,8 @@
-from infini.typing import Literal, Dict, Any
+from infini.typing import Union, Literal, Dict, Any
class Output:
- type: Literal["null", "text", "workflow"]
+ type: Union[Literal["null", "text", "workflow"], str]
name: str
status: int
block: bool
@@ -11,7 +11,7 @@ class Output:
def __init__(
self,
- type: Literal["null", "text", "workflow"],
+ type: Union[Literal["null", "text", "workflow"], str],
name: str,
*,
status: int = 0,
diff --git a/src/infini/register.py b/src/infini/register.py
index 0586ae7e..0d85c3c0 100644
--- a/src/infini/register.py
+++ b/src/infini/register.py
@@ -1,7 +1,8 @@
+from infini.typing import List, Dict, Any, Callable, RouterType, Optional, Union, Type
from infini.input import Input
from infini.output import Output
from infini.router import Contains, Router
-from infini.typing import List, Dict, Any, Callable, RouterType, Optional, Union
+from infini.generator import BaseGenerator
from functools import wraps
@@ -11,6 +12,7 @@ class Register:
events: Dict[str, str]
global_variables: Dict[str, Union[str, Callable]]
interceptors: List[RouterType]
+ generators: Dict[str, BaseGenerator]
def __init__(self) -> None:
self.pre_interceptors = []
@@ -18,6 +20,7 @@ class Register:
self.events = {}
self.global_variables = {}
self.interceptors = []
+ self.generators = {}
def pre_interceptor(self, router: Union[Router, str], priority: int = 0):
def decorator(func):
@@ -54,9 +57,27 @@ class Register:
return decorator
def regist_textevent(self, name: str, text: str):
+ import warnings
+
+ warnings.warn(
+ "Infini will soon deprecated `regist_textevent`, "
+ "use `register_textevent` instead."
+ )
+ self.events[name] = text
+
+ def register_textevent(self, name: str, text: str):
self.events[name] = text
def regist_variable(self, name: str, data: Any):
+ import warnings
+
+ warnings.warn(
+ "Infini will soon deprecated `regist_variable`, "
+ "use `register_variable` instead."
+ )
+ self.global_variables[name] = data
+
+ def register_variable(self, name: str, data: Any):
self.global_variables[name] = data
def dynamic_variable(self, name: Optional[str] = None):
@@ -86,3 +107,10 @@ class Register:
return wrapper
return decorator
+
+ def register_generator(
+ self, generator: Union[BaseGenerator, Type[BaseGenerator]]
+ ) -> None:
+ if not isinstance(generator, BaseGenerator):
+ generator = generator()
+ self.generators[generator.type] = generator
diff --git a/src/infini/typing.py b/src/infini/typing.py
index 874e8753..14c219fc 100644
--- a/src/infini/typing.py
+++ b/src/infini/typing.py
@@ -1,7 +1,9 @@
from typing import (
+ TYPE_CHECKING,
Dict as Dict,
List as List,
Any as Any,
+ Type as Type,
Optional as Optional,
Generic as Generic,
Callable as Callable,
@@ -14,14 +16,18 @@ from typing import (
Union,
)
from types import ModuleType as ModuleType, GeneratorType as GeneratorType
-from . import router, input, output
+
+if TYPE_CHECKING:
+ from infini.router import Router
+ from infini.input import Input
+ from infini.output import Output
T = TypeVar("T")
-Stream = Union["input.Input[Any]", "output.Output"]
-OutputGenerator = Generator["output.Output", Any, None]
+Stream = Union["Input[Any]", "Output"]
+OutputGenerator = Generator["Output", Any, None]
class RouterType(TypedDict):
priority: int
- router: router.Router
+ router: "Router"
handler: Callable[..., Union[Stream, OutputGenerator]]