gllm-core-binary 0.4.4__py3-none-macosx_13_0_arm64.whl
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.
- gllm_core/__init__.py +1 -0
- gllm_core/__init__.pyi +0 -0
- gllm_core/adapters/__init__.py +5 -0
- gllm_core/adapters/__init__.pyi +3 -0
- gllm_core/adapters/tool/__init__.py +6 -0
- gllm_core/adapters/tool/__init__.pyi +4 -0
- gllm_core/adapters/tool/google_adk.py +91 -0
- gllm_core/adapters/tool/google_adk.pyi +23 -0
- gllm_core/adapters/tool/langchain.py +130 -0
- gllm_core/adapters/tool/langchain.pyi +31 -0
- gllm_core/constants.py +55 -0
- gllm_core/constants.pyi +36 -0
- gllm_core/event/__init__.py +6 -0
- gllm_core/event/__init__.pyi +4 -0
- gllm_core/event/event_emitter.py +211 -0
- gllm_core/event/event_emitter.pyi +155 -0
- gllm_core/event/handler/__init__.py +7 -0
- gllm_core/event/handler/__init__.pyi +5 -0
- gllm_core/event/handler/console_event_handler.py +48 -0
- gllm_core/event/handler/console_event_handler.pyi +32 -0
- gllm_core/event/handler/event_handler.py +89 -0
- gllm_core/event/handler/event_handler.pyi +51 -0
- gllm_core/event/handler/print_event_handler.py +130 -0
- gllm_core/event/handler/print_event_handler.pyi +33 -0
- gllm_core/event/handler/stream_event_handler.py +85 -0
- gllm_core/event/handler/stream_event_handler.pyi +62 -0
- gllm_core/event/hook/__init__.py +5 -0
- gllm_core/event/hook/__init__.pyi +3 -0
- gllm_core/event/hook/event_hook.py +30 -0
- gllm_core/event/hook/event_hook.pyi +18 -0
- gllm_core/event/hook/json_stringify_event_hook.py +32 -0
- gllm_core/event/hook/json_stringify_event_hook.pyi +16 -0
- gllm_core/event/messenger.py +133 -0
- gllm_core/event/messenger.pyi +66 -0
- gllm_core/schema/__init__.py +8 -0
- gllm_core/schema/__init__.pyi +6 -0
- gllm_core/schema/chunk.py +148 -0
- gllm_core/schema/chunk.pyi +66 -0
- gllm_core/schema/component.py +546 -0
- gllm_core/schema/component.pyi +205 -0
- gllm_core/schema/event.py +50 -0
- gllm_core/schema/event.pyi +33 -0
- gllm_core/schema/schema_generator.py +150 -0
- gllm_core/schema/schema_generator.pyi +35 -0
- gllm_core/schema/tool.py +418 -0
- gllm_core/schema/tool.pyi +198 -0
- gllm_core/utils/__init__.py +32 -0
- gllm_core/utils/__init__.pyi +13 -0
- gllm_core/utils/analyzer.py +256 -0
- gllm_core/utils/analyzer.pyi +123 -0
- gllm_core/utils/binary_handler_factory.py +99 -0
- gllm_core/utils/binary_handler_factory.pyi +62 -0
- gllm_core/utils/chunk_metadata_merger.py +102 -0
- gllm_core/utils/chunk_metadata_merger.pyi +41 -0
- gllm_core/utils/concurrency.py +184 -0
- gllm_core/utils/concurrency.pyi +94 -0
- gllm_core/utils/event_formatter.py +69 -0
- gllm_core/utils/event_formatter.pyi +30 -0
- gllm_core/utils/google_sheets.py +115 -0
- gllm_core/utils/google_sheets.pyi +18 -0
- gllm_core/utils/imports.py +91 -0
- gllm_core/utils/imports.pyi +42 -0
- gllm_core/utils/logger_manager.py +339 -0
- gllm_core/utils/logger_manager.pyi +176 -0
- gllm_core/utils/main_method_resolver.py +185 -0
- gllm_core/utils/main_method_resolver.pyi +54 -0
- gllm_core/utils/merger_method.py +130 -0
- gllm_core/utils/merger_method.pyi +49 -0
- gllm_core/utils/retry.py +258 -0
- gllm_core/utils/retry.pyi +41 -0
- gllm_core/utils/similarity.py +29 -0
- gllm_core/utils/similarity.pyi +10 -0
- gllm_core/utils/validation.py +26 -0
- gllm_core/utils/validation.pyi +12 -0
- gllm_core_binary-0.4.4.dist-info/METADATA +177 -0
- gllm_core_binary-0.4.4.dist-info/RECORD +78 -0
- gllm_core_binary-0.4.4.dist-info/WHEEL +5 -0
- gllm_core_binary-0.4.4.dist-info/top_level.txt +1 -0
gllm_core/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Provides fundamental components and utilities."""
|
gllm_core/__init__.pyi
ADDED
|
File without changes
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Google ADK tool adapter conversions.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Dimitrij Ray (dimitrij.ray@gdplabs.id)
|
|
5
|
+
|
|
6
|
+
References:
|
|
7
|
+
NONE
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
from typing import Any, Callable
|
|
12
|
+
|
|
13
|
+
from gllm_core.schema.tool import Tool
|
|
14
|
+
|
|
15
|
+
_DEFAULT_SCHEMA: dict[str, Any] = {"type": "object", "properties": {}}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _validate_and_extract_schema(parameters: Any) -> dict[str, Any]:
|
|
19
|
+
"""Validate and extract the input schema from Google ADK parameters.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
parameters (Any): The parameters from the Google ADK function declaration.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
dict[str, Any]: The validated input schema.
|
|
26
|
+
|
|
27
|
+
Raises:
|
|
28
|
+
TypeError: If the schema has invalid structure.
|
|
29
|
+
"""
|
|
30
|
+
if parameters is None:
|
|
31
|
+
return _DEFAULT_SCHEMA.copy()
|
|
32
|
+
|
|
33
|
+
if isinstance(parameters, dict):
|
|
34
|
+
if "properties" in parameters and not isinstance(parameters.get("properties"), dict):
|
|
35
|
+
raise TypeError("Google ADK function schema 'properties' must be a dictionary.")
|
|
36
|
+
return parameters
|
|
37
|
+
|
|
38
|
+
return dict(parameters) if hasattr(parameters, "__iter__") else _DEFAULT_SCHEMA.copy()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def from_google_function(function_declaration: Any, func: Callable | None = None) -> Tool:
|
|
42
|
+
"""Convert a Google ADK function declaration into the SDK Tool representation.
|
|
43
|
+
|
|
44
|
+
The Google ADK `FunctionDeclaration` provides access to:
|
|
45
|
+
1. `name`: The function name
|
|
46
|
+
2. `description`: The function description
|
|
47
|
+
3. `parameters`: A dict in JSON Schema format (OpenAPI 3.0 compatible)
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
function_declaration (Any): The Google ADK function declaration to convert.
|
|
51
|
+
func (Callable | None, optional): The implementation function for the tool. Defaults to None.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Tool: The converted SDK tool.
|
|
55
|
+
|
|
56
|
+
Raises:
|
|
57
|
+
ValueError: If the function declaration is None or has invalid fields.
|
|
58
|
+
AttributeError: If required attributes are missing.
|
|
59
|
+
TypeError: If field types are incorrect.
|
|
60
|
+
"""
|
|
61
|
+
if function_declaration is None:
|
|
62
|
+
raise ValueError("Google ADK function declaration cannot be None.")
|
|
63
|
+
|
|
64
|
+
for attr in ("name", "description"):
|
|
65
|
+
if not hasattr(function_declaration, attr):
|
|
66
|
+
raise AttributeError(f"Google ADK function declaration must have a {attr!r} attribute.")
|
|
67
|
+
|
|
68
|
+
name = function_declaration.name
|
|
69
|
+
description = function_declaration.description
|
|
70
|
+
|
|
71
|
+
if not isinstance(name, str) or not name:
|
|
72
|
+
raise ValueError("Google ADK function 'name' must be a non-empty string.")
|
|
73
|
+
|
|
74
|
+
if description is not None and not isinstance(description, str):
|
|
75
|
+
raise TypeError("Google ADK function 'description' must be a string when provided.")
|
|
76
|
+
|
|
77
|
+
if func is not None and not callable(func):
|
|
78
|
+
raise TypeError("Google ADK tool implementation must be callable when provided.")
|
|
79
|
+
|
|
80
|
+
parameters = getattr(function_declaration, "parameters", None)
|
|
81
|
+
input_schema = _validate_and_extract_schema(parameters)
|
|
82
|
+
|
|
83
|
+
is_async = asyncio.iscoroutinefunction(func) if func else False
|
|
84
|
+
|
|
85
|
+
return Tool(
|
|
86
|
+
name=name,
|
|
87
|
+
description=description,
|
|
88
|
+
input_schema=input_schema,
|
|
89
|
+
func=func,
|
|
90
|
+
is_async=is_async,
|
|
91
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from gllm_core.schema.tool import Tool as Tool
|
|
2
|
+
from typing import Any, Callable
|
|
3
|
+
|
|
4
|
+
def from_google_function(function_declaration: Any, func: Callable | None = None) -> Tool:
|
|
5
|
+
"""Convert a Google ADK function declaration into the SDK Tool representation.
|
|
6
|
+
|
|
7
|
+
The Google ADK `FunctionDeclaration` provides access to:
|
|
8
|
+
1. `name`: The function name
|
|
9
|
+
2. `description`: The function description
|
|
10
|
+
3. `parameters`: A dict in JSON Schema format (OpenAPI 3.0 compatible)
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
function_declaration (Any): The Google ADK function declaration to convert.
|
|
14
|
+
func (Callable | None, optional): The implementation function for the tool. Defaults to None.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
Tool: The converted SDK tool.
|
|
18
|
+
|
|
19
|
+
Raises:
|
|
20
|
+
ValueError: If the function declaration is None or has invalid fields.
|
|
21
|
+
AttributeError: If required attributes are missing.
|
|
22
|
+
TypeError: If field types are incorrect.
|
|
23
|
+
"""
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""LangChain tool adapter conversions.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Dimitrij Ray (dimitrij.ray@gdplabs.id)
|
|
5
|
+
|
|
6
|
+
References:
|
|
7
|
+
NONE
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
from typing import Any, Callable
|
|
12
|
+
|
|
13
|
+
from gllm_core.schema.tool import Tool
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LangChainToolKeys:
|
|
17
|
+
"""Constants for LangChain tool attribute keys."""
|
|
18
|
+
|
|
19
|
+
FUNC = "func"
|
|
20
|
+
COROUTINE = "coroutine"
|
|
21
|
+
RUN = "_run"
|
|
22
|
+
ARUN = "_arun"
|
|
23
|
+
NAME = "name"
|
|
24
|
+
DESCRIPTION = "description"
|
|
25
|
+
ARGS_SCHEMA = "args_schema"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
LANGCHAIN_FUNCTION_ATTRS = (
|
|
29
|
+
LangChainToolKeys.FUNC,
|
|
30
|
+
LangChainToolKeys.COROUTINE,
|
|
31
|
+
LangChainToolKeys.RUN,
|
|
32
|
+
LangChainToolKeys.ARUN,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _extract_attribute(tool: Any, attr_name: str) -> Any:
|
|
37
|
+
"""Extract an attribute from a LangChain tool.
|
|
38
|
+
|
|
39
|
+
A LangChain tool can be either a dictionary-like object or an object with attributes.
|
|
40
|
+
This function handles both cases:
|
|
41
|
+
1. If the tool has the attribute as an attribute, it returns the attribute value.
|
|
42
|
+
2. If the tool has the attribute as a key (is a dictionary-like object), it returns the key value.
|
|
43
|
+
3. Otherwise, it returns None.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
tool (Any): The LangChain tool to extract the attribute from.
|
|
47
|
+
attr_name (str): The attribute name to extract.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Any: The attribute value, or None if not found.
|
|
51
|
+
"""
|
|
52
|
+
if hasattr(tool, attr_name):
|
|
53
|
+
return getattr(tool, attr_name)
|
|
54
|
+
|
|
55
|
+
if hasattr(tool, "get"):
|
|
56
|
+
return tool.get(attr_name)
|
|
57
|
+
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _get_langchain_tool_func(tool: Any) -> Callable | None:
|
|
62
|
+
"""Gets the function from a LangChain tool.
|
|
63
|
+
|
|
64
|
+
This function extracts the appropriate callable from a LangChain tool, with the following priority:
|
|
65
|
+
1. func
|
|
66
|
+
2. coroutine
|
|
67
|
+
3. _run
|
|
68
|
+
4. _arun
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
tool (Any): The LangChain tool to extract the function from.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Callable | None: The extracted function, or None if no function is found.
|
|
75
|
+
"""
|
|
76
|
+
for func_key in LANGCHAIN_FUNCTION_ATTRS:
|
|
77
|
+
func = _extract_attribute(tool, func_key)
|
|
78
|
+
if callable(func):
|
|
79
|
+
return func
|
|
80
|
+
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _get_input_schema(tool: Any) -> dict[str, Any]:
|
|
85
|
+
"""Get input schema from a LangChain tool.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
tool (Any): The LangChain tool to get schema from.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
dict[str, Any]: The input schema, or default empty schema if none found.
|
|
92
|
+
"""
|
|
93
|
+
input_schema = _extract_attribute(tool, LangChainToolKeys.ARGS_SCHEMA)
|
|
94
|
+
|
|
95
|
+
return input_schema if input_schema is not None else {"type": "object", "properties": {}}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def from_langchain_tool(langchain_tool: Any) -> Tool:
|
|
99
|
+
"""Convert a LangChain tool into the SDK Tool representation.
|
|
100
|
+
|
|
101
|
+
This function handles both traditional LangChain tools created with the @tool decorator
|
|
102
|
+
and tools created by subclassing the LangChain Tool class.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
langchain_tool (Any): The LangChain tool to convert.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Tool: The converted SDK tool.
|
|
109
|
+
|
|
110
|
+
Raises:
|
|
111
|
+
ValueError: If the input is not a valid LangChain tool.
|
|
112
|
+
"""
|
|
113
|
+
name = _extract_attribute(langchain_tool, LangChainToolKeys.NAME)
|
|
114
|
+
if not name:
|
|
115
|
+
raise ValueError("LangChain tool must have a 'name' attribute or key.")
|
|
116
|
+
|
|
117
|
+
description = _extract_attribute(langchain_tool, LangChainToolKeys.DESCRIPTION)
|
|
118
|
+
if not description:
|
|
119
|
+
raise ValueError("LangChain tool must have a 'description' attribute or key.")
|
|
120
|
+
|
|
121
|
+
func = _get_langchain_tool_func(langchain_tool)
|
|
122
|
+
input_schema = _get_input_schema(langchain_tool)
|
|
123
|
+
|
|
124
|
+
return Tool(
|
|
125
|
+
name=name,
|
|
126
|
+
description=description,
|
|
127
|
+
input_schema=input_schema,
|
|
128
|
+
func=func,
|
|
129
|
+
is_async=asyncio.iscoroutinefunction(func) if func is not None else False,
|
|
130
|
+
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from gllm_core.schema.tool import Tool as Tool
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
class LangChainToolKeys:
|
|
6
|
+
"""Constants for LangChain tool attribute keys."""
|
|
7
|
+
FUNC: str
|
|
8
|
+
COROUTINE: str
|
|
9
|
+
RUN: str
|
|
10
|
+
ARUN: str
|
|
11
|
+
NAME: str
|
|
12
|
+
DESCRIPTION: str
|
|
13
|
+
ARGS_SCHEMA: str
|
|
14
|
+
|
|
15
|
+
LANGCHAIN_FUNCTION_ATTRS: Incomplete
|
|
16
|
+
|
|
17
|
+
def from_langchain_tool(langchain_tool: Any) -> Tool:
|
|
18
|
+
"""Convert a LangChain tool into the SDK Tool representation.
|
|
19
|
+
|
|
20
|
+
This function handles both traditional LangChain tools created with the @tool decorator
|
|
21
|
+
and tools created by subclassing the LangChain Tool class.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
langchain_tool (Any): The LangChain tool to convert.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Tool: The converted SDK tool.
|
|
28
|
+
|
|
29
|
+
Raises:
|
|
30
|
+
ValueError: If the input is not a valid LangChain tool.
|
|
31
|
+
"""
|
gllm_core/constants.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Contains constants used throughout the gllm_core package.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Henry Wicaksono (henry.wicaksono@gdplabs.id)
|
|
5
|
+
|
|
6
|
+
References:
|
|
7
|
+
NONE
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from enum import IntEnum, StrEnum
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class EventLevel(IntEnum):
|
|
14
|
+
"""Defines event levels for the event emitter module."""
|
|
15
|
+
|
|
16
|
+
TRACE = 0
|
|
17
|
+
DEBUG = 1
|
|
18
|
+
INFO = 2
|
|
19
|
+
WARN = 3
|
|
20
|
+
ERROR = 4
|
|
21
|
+
FATAL = 5
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class EventType(StrEnum):
|
|
25
|
+
"""Defines event types for the event emitter module."""
|
|
26
|
+
|
|
27
|
+
ACTIVITY = "activity"
|
|
28
|
+
CODE = "code"
|
|
29
|
+
REFERENCE = "reference"
|
|
30
|
+
RESPONSE = "response"
|
|
31
|
+
STATUS = "status"
|
|
32
|
+
THINKING = "thinking"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class EventTypeSuffix(StrEnum):
|
|
36
|
+
"""Defines suffixes for block based event types."""
|
|
37
|
+
|
|
38
|
+
START = "_start"
|
|
39
|
+
END = "_end"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class DefaultChunkMetadata:
|
|
43
|
+
"""Defines constants for default chunk metadata keys."""
|
|
44
|
+
|
|
45
|
+
CHUNK_ID = "chunk_id"
|
|
46
|
+
PREV_CHUNK_ID = "previous_chunk"
|
|
47
|
+
NEXT_CHUNK_ID = "next_chunk"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class LogMode(StrEnum):
|
|
51
|
+
"""Defines supported log modes for the SDK logging system."""
|
|
52
|
+
|
|
53
|
+
TEXT = "text"
|
|
54
|
+
SIMPLE = "simple"
|
|
55
|
+
JSON = "json"
|
gllm_core/constants.pyi
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from enum import IntEnum, StrEnum
|
|
2
|
+
|
|
3
|
+
class EventLevel(IntEnum):
|
|
4
|
+
"""Defines event levels for the event emitter module."""
|
|
5
|
+
TRACE = 0
|
|
6
|
+
DEBUG = 1
|
|
7
|
+
INFO = 2
|
|
8
|
+
WARN = 3
|
|
9
|
+
ERROR = 4
|
|
10
|
+
FATAL = 5
|
|
11
|
+
|
|
12
|
+
class EventType(StrEnum):
|
|
13
|
+
"""Defines event types for the event emitter module."""
|
|
14
|
+
ACTIVITY = 'activity'
|
|
15
|
+
CODE = 'code'
|
|
16
|
+
REFERENCE = 'reference'
|
|
17
|
+
RESPONSE = 'response'
|
|
18
|
+
STATUS = 'status'
|
|
19
|
+
THINKING = 'thinking'
|
|
20
|
+
|
|
21
|
+
class EventTypeSuffix(StrEnum):
|
|
22
|
+
"""Defines suffixes for block based event types."""
|
|
23
|
+
START = '_start'
|
|
24
|
+
END = '_end'
|
|
25
|
+
|
|
26
|
+
class DefaultChunkMetadata:
|
|
27
|
+
"""Defines constants for default chunk metadata keys."""
|
|
28
|
+
CHUNK_ID: str
|
|
29
|
+
PREV_CHUNK_ID: str
|
|
30
|
+
NEXT_CHUNK_ID: str
|
|
31
|
+
|
|
32
|
+
class LogMode(StrEnum):
|
|
33
|
+
"""Defines supported log modes for the SDK logging system."""
|
|
34
|
+
TEXT = 'text'
|
|
35
|
+
SIMPLE = 'simple'
|
|
36
|
+
JSON = 'json'
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"""Defines the event emitter module used throughout the Gen AI applications.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Henry Wicaksono (henry.wicaksono@gdplabs.id)
|
|
5
|
+
|
|
6
|
+
References:
|
|
7
|
+
NONE
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import AsyncGenerator
|
|
11
|
+
|
|
12
|
+
from gllm_core.constants import EventLevel
|
|
13
|
+
from gllm_core.event.handler import ConsoleEventHandler, PrintEventHandler, StreamEventHandler
|
|
14
|
+
from gllm_core.event.handler.event_handler import BaseEventHandler
|
|
15
|
+
from gllm_core.event.hook.event_hook import BaseEventHook
|
|
16
|
+
from gllm_core.schema import Event
|
|
17
|
+
from gllm_core.utils import validate_string_enum
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class EventEmitter:
|
|
21
|
+
"""Handles events emitting using event handlers with various levels and types.
|
|
22
|
+
|
|
23
|
+
The `EventEmitter` class is responsible for handling and emitting events using a list of event handlers.
|
|
24
|
+
Events are processed based on their severity level and type, with the option to disable specific handlers.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
handlers (list[BaseEventHandler]): A list of event handlers to process emitted events.
|
|
28
|
+
severity (int): The minimum severity level of events to be processed.
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
Basic usage:
|
|
32
|
+
```python
|
|
33
|
+
event_emitter = EventEmitter(handlers=[ConsoleEventHandler()])
|
|
34
|
+
await event_emitter.emit("Hello, world!")
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Emitting an event object:
|
|
38
|
+
```python
|
|
39
|
+
event_emitter = EventEmitter(handlers=[ConsoleEventHandler()])
|
|
40
|
+
event = Event(id="123", value="Hello, world!", level=EventLevel.INFO, type="object", metadata={})
|
|
41
|
+
await event_emitter.emit(event)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Using with hooks:
|
|
45
|
+
```python
|
|
46
|
+
event_emitter = EventEmitter(handlers=[ConsoleEventHandler()], hooks=[JSONStringifyEventHook()])
|
|
47
|
+
await event_emitter.emit("Hello, world!")
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Using with customized event level:
|
|
51
|
+
```python
|
|
52
|
+
event_emitter = EventEmitter(handlers=[ConsoleEventHandler()], event_level=EventLevel.DEBUG)
|
|
53
|
+
await event_emitter.emit("Hello, world!")
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Using with console handler:
|
|
57
|
+
```python
|
|
58
|
+
event_emitter = EventEmitter.with_console_handler()
|
|
59
|
+
await event_emitter.emit("Hello, world!")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Using with print handler:
|
|
63
|
+
```python
|
|
64
|
+
event_emitter = EventEmitter.with_print_handler()
|
|
65
|
+
await event_emitter.emit("Hello, world!")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Using with stream handler:
|
|
69
|
+
```python
|
|
70
|
+
async def function(event_emitter: EventEmitter):
|
|
71
|
+
await event_emitter.emit("Hello, world!")
|
|
72
|
+
|
|
73
|
+
event_emitter = EventEmitter.with_stream_handler()
|
|
74
|
+
asyncio.create_task(function(event_emitter))
|
|
75
|
+
async for event in event_emitter.stream():
|
|
76
|
+
print(event)
|
|
77
|
+
```
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __init__(
|
|
81
|
+
self,
|
|
82
|
+
handlers: list[BaseEventHandler],
|
|
83
|
+
event_level: EventLevel = EventLevel.INFO,
|
|
84
|
+
hooks: list[BaseEventHook] | None = None,
|
|
85
|
+
):
|
|
86
|
+
"""Initializes a new instance of the EventEmitter class.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
handlers (list[BaseEventHandler]): A list of event handlers to process emitted events.
|
|
90
|
+
event_level (EventLevel, optional): The minimum severity level of events to be processed.
|
|
91
|
+
Defaults to EventLevel.INFO.
|
|
92
|
+
hooks (list[BaseEventHook] | None, optional): A list of event hooks to be applied to the emitted events.
|
|
93
|
+
Defaults to None, in which case the event emitter will not apply any hooks.
|
|
94
|
+
|
|
95
|
+
Raises:
|
|
96
|
+
ValueError:
|
|
97
|
+
1. If the event handlers list is empty.
|
|
98
|
+
2. If an invalid event level is provided.
|
|
99
|
+
"""
|
|
100
|
+
if not handlers:
|
|
101
|
+
raise ValueError("The event handlers can not be empty.")
|
|
102
|
+
|
|
103
|
+
validate_string_enum(EventLevel, event_level)
|
|
104
|
+
|
|
105
|
+
self.handlers = handlers
|
|
106
|
+
self.severity = event_level
|
|
107
|
+
self.hooks = hooks or []
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def with_console_handler(
|
|
111
|
+
cls, event_level: EventLevel = EventLevel.INFO, hooks: list[BaseEventHook] | None = None
|
|
112
|
+
) -> "EventEmitter":
|
|
113
|
+
"""Creates a new instance of the EventEmitter class with a single ConsoleEventHandler.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
event_level (EventLevel, optional): The minimum severity level of events to be processed.
|
|
117
|
+
Defaults to EventLevel.INFO.
|
|
118
|
+
hooks (list[BaseEventHook] | None, optional): A list of event hooks to be applied to the emitted events.
|
|
119
|
+
Defaults to None, in which case the event emitter will not apply any hooks.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
EventEmitter: A new instance of the EventEmitter class with a single ConsoleEventHandler.
|
|
123
|
+
"""
|
|
124
|
+
return cls(handlers=[ConsoleEventHandler()], event_level=event_level, hooks=hooks)
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def with_print_handler(
|
|
128
|
+
cls, event_level: EventLevel = EventLevel.INFO, hooks: list[BaseEventHook] | None = None
|
|
129
|
+
) -> "EventEmitter":
|
|
130
|
+
"""Creates a new instance of the EventEmitter class with a single PrintEventHandler.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
event_level (EventLevel, optional): The minimum severity level of events to be processed.
|
|
134
|
+
Defaults to EventLevel.INFO.
|
|
135
|
+
hooks (list[BaseEventHook] | None, optional): A list of event hooks to be applied to the emitted events.
|
|
136
|
+
Defaults to None, in which case the event emitter will not apply any hooks.
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
EventEmitter: A new instance of the EventEmitter class with a single PrintEventHandler.
|
|
140
|
+
"""
|
|
141
|
+
return cls(handlers=[PrintEventHandler()], event_level=event_level, hooks=hooks)
|
|
142
|
+
|
|
143
|
+
@classmethod
|
|
144
|
+
def with_stream_handler(
|
|
145
|
+
cls, event_level: EventLevel = EventLevel.INFO, hooks: list[BaseEventHook] | None = None
|
|
146
|
+
) -> "EventEmitter":
|
|
147
|
+
"""Creates a new instance of the EventEmitter class with a single StreamEventHandler.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
event_level (EventLevel, optional): The minimum severity level of events to be processed.
|
|
151
|
+
Defaults to EventLevel.INFO.
|
|
152
|
+
hooks (list[BaseEventHook] | None, optional): A list of event hooks to be applied to the emitted events.
|
|
153
|
+
Defaults to None, in which case the event emitter will not apply any hooks.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
EventEmitter: A new instance of the EventEmitter class with a single StreamEventHandler.
|
|
157
|
+
"""
|
|
158
|
+
return cls(handlers=[StreamEventHandler()], event_level=event_level, hooks=hooks)
|
|
159
|
+
|
|
160
|
+
async def emit(self, event: Event, disabled_handlers: list[str] | None = None) -> None:
|
|
161
|
+
"""Emits an event using the configured event handlers.
|
|
162
|
+
|
|
163
|
+
Events are emitted by passing them to all handlers except those listed in disabled_handlers.
|
|
164
|
+
Events are only processed if their severity level meets or exceeds the EventEmitter's configured level.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
event (Event): The event to emit.
|
|
168
|
+
disabled_handlers (list[str] | None, optional): Names of handlers to skip for this event. Defaults to None.
|
|
169
|
+
|
|
170
|
+
Raises:
|
|
171
|
+
ValueError: If the provided event_level is not a valid EventLevel.
|
|
172
|
+
"""
|
|
173
|
+
if event.level < self.severity:
|
|
174
|
+
return
|
|
175
|
+
|
|
176
|
+
for hook in self.hooks:
|
|
177
|
+
event = await hook(event)
|
|
178
|
+
|
|
179
|
+
disabled_handlers = disabled_handlers or []
|
|
180
|
+
for handler in self.handlers:
|
|
181
|
+
if handler.name not in disabled_handlers:
|
|
182
|
+
await handler.emit(event)
|
|
183
|
+
|
|
184
|
+
async def close(self) -> None:
|
|
185
|
+
"""Closes all handlers in the handler list.
|
|
186
|
+
|
|
187
|
+
This method iterates through the list of handlers and calls the `close` method on each handler.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
None
|
|
191
|
+
"""
|
|
192
|
+
for handler in self.handlers:
|
|
193
|
+
await handler.close()
|
|
194
|
+
|
|
195
|
+
def stream(self) -> AsyncGenerator:
|
|
196
|
+
"""Streams events from the StreamEventHandler.
|
|
197
|
+
|
|
198
|
+
This method is a convenience method that calls the `stream` method on the StreamEventHandler.
|
|
199
|
+
To use this method, the event emitter must have exactly one StreamEventHandler.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
AsyncGenerator: An asynchronous generator yielding events from the StreamEventHandler.
|
|
203
|
+
"""
|
|
204
|
+
stream_handlers = [handler for handler in self.handlers if isinstance(handler, StreamEventHandler)]
|
|
205
|
+
|
|
206
|
+
if len(stream_handlers) != 1:
|
|
207
|
+
raise ValueError(
|
|
208
|
+
f"The event emitter must have exactly one stream handler. Found {len(stream_handlers)} instances."
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
return stream_handlers[0].stream()
|