bear-utils 0.0.1__py3-none-any.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.
- bear_utils/__init__.py +51 -0
- bear_utils/__main__.py +14 -0
- bear_utils/_internal/__init__.py +0 -0
- bear_utils/_internal/_version.py +1 -0
- bear_utils/_internal/cli.py +119 -0
- bear_utils/_internal/debug.py +174 -0
- bear_utils/ai/__init__.py +30 -0
- bear_utils/ai/ai_helpers/__init__.py +136 -0
- bear_utils/ai/ai_helpers/_common.py +19 -0
- bear_utils/ai/ai_helpers/_config.py +24 -0
- bear_utils/ai/ai_helpers/_parsers.py +194 -0
- bear_utils/ai/ai_helpers/_types.py +15 -0
- bear_utils/cache/__init__.py +131 -0
- bear_utils/cli/__init__.py +22 -0
- bear_utils/cli/_args.py +12 -0
- bear_utils/cli/_get_version.py +207 -0
- bear_utils/cli/commands.py +105 -0
- bear_utils/cli/prompt_helpers.py +186 -0
- bear_utils/cli/shell/__init__.py +1 -0
- bear_utils/cli/shell/_base_command.py +81 -0
- bear_utils/cli/shell/_base_shell.py +430 -0
- bear_utils/cli/shell/_common.py +19 -0
- bear_utils/cli/typer_bridge.py +90 -0
- bear_utils/config/__init__.py +13 -0
- bear_utils/config/config_manager.py +229 -0
- bear_utils/config/dir_manager.py +69 -0
- bear_utils/config/settings_manager.py +179 -0
- bear_utils/constants/__init__.py +90 -0
- bear_utils/constants/_exceptions.py +8 -0
- bear_utils/constants/_exit_code.py +60 -0
- bear_utils/constants/_http_status_code.py +37 -0
- bear_utils/constants/_lazy_typing.py +15 -0
- bear_utils/constants/_meta.py +196 -0
- bear_utils/constants/date_related.py +25 -0
- bear_utils/constants/time_related.py +24 -0
- bear_utils/database/__init__.py +8 -0
- bear_utils/database/_db_manager.py +98 -0
- bear_utils/events/__init__.py +18 -0
- bear_utils/events/events_class.py +52 -0
- bear_utils/events/events_module.py +74 -0
- bear_utils/extras/__init__.py +28 -0
- bear_utils/extras/_async_helpers.py +67 -0
- bear_utils/extras/_tools.py +185 -0
- bear_utils/extras/_zapper.py +399 -0
- bear_utils/extras/platform_utils.py +57 -0
- bear_utils/extras/responses/__init__.py +5 -0
- bear_utils/extras/responses/function_response.py +451 -0
- bear_utils/extras/wrappers/__init__.py +1 -0
- bear_utils/extras/wrappers/add_methods.py +100 -0
- bear_utils/extras/wrappers/string_io.py +46 -0
- bear_utils/files/__init__.py +6 -0
- bear_utils/files/file_handlers/__init__.py +5 -0
- bear_utils/files/file_handlers/_base_file_handler.py +107 -0
- bear_utils/files/file_handlers/file_handler_factory.py +280 -0
- bear_utils/files/file_handlers/json_file_handler.py +71 -0
- bear_utils/files/file_handlers/log_file_handler.py +40 -0
- bear_utils/files/file_handlers/toml_file_handler.py +76 -0
- bear_utils/files/file_handlers/txt_file_handler.py +76 -0
- bear_utils/files/file_handlers/yaml_file_handler.py +64 -0
- bear_utils/files/ignore_parser.py +293 -0
- bear_utils/graphics/__init__.py +6 -0
- bear_utils/graphics/bear_gradient.py +145 -0
- bear_utils/graphics/font/__init__.py +13 -0
- bear_utils/graphics/font/_raw_block_letters.py +463 -0
- bear_utils/graphics/font/_theme.py +31 -0
- bear_utils/graphics/font/_utils.py +220 -0
- bear_utils/graphics/font/block_font.py +192 -0
- bear_utils/graphics/font/glitch_font.py +63 -0
- bear_utils/graphics/image_helpers.py +45 -0
- bear_utils/gui/__init__.py +8 -0
- bear_utils/gui/gui_tools/__init__.py +10 -0
- bear_utils/gui/gui_tools/_settings.py +36 -0
- bear_utils/gui/gui_tools/_types.py +12 -0
- bear_utils/gui/gui_tools/qt_app.py +150 -0
- bear_utils/gui/gui_tools/qt_color_picker.py +130 -0
- bear_utils/gui/gui_tools/qt_file_handler.py +130 -0
- bear_utils/gui/gui_tools/qt_input_dialog.py +303 -0
- bear_utils/logger_manager/__init__.py +109 -0
- bear_utils/logger_manager/_common.py +63 -0
- bear_utils/logger_manager/_console_junk.py +135 -0
- bear_utils/logger_manager/_log_level.py +50 -0
- bear_utils/logger_manager/_styles.py +95 -0
- bear_utils/logger_manager/logger_protocol.py +42 -0
- bear_utils/logger_manager/loggers/__init__.py +1 -0
- bear_utils/logger_manager/loggers/_console.py +223 -0
- bear_utils/logger_manager/loggers/_level_sin.py +61 -0
- bear_utils/logger_manager/loggers/_logger.py +19 -0
- bear_utils/logger_manager/loggers/base_logger.py +244 -0
- bear_utils/logger_manager/loggers/base_logger.pyi +51 -0
- bear_utils/logger_manager/loggers/basic_logger/__init__.py +5 -0
- bear_utils/logger_manager/loggers/basic_logger/logger.py +80 -0
- bear_utils/logger_manager/loggers/basic_logger/logger.pyi +19 -0
- bear_utils/logger_manager/loggers/buffer_logger.py +57 -0
- bear_utils/logger_manager/loggers/console_logger.py +278 -0
- bear_utils/logger_manager/loggers/console_logger.pyi +50 -0
- bear_utils/logger_manager/loggers/fastapi_logger.py +333 -0
- bear_utils/logger_manager/loggers/file_logger.py +151 -0
- bear_utils/logger_manager/loggers/simple_logger.py +98 -0
- bear_utils/logger_manager/loggers/sub_logger.py +105 -0
- bear_utils/logger_manager/loggers/sub_logger.pyi +23 -0
- bear_utils/monitoring/__init__.py +13 -0
- bear_utils/monitoring/_common.py +28 -0
- bear_utils/monitoring/host_monitor.py +346 -0
- bear_utils/time/__init__.py +59 -0
- bear_utils-0.0.1.dist-info/METADATA +305 -0
- bear_utils-0.0.1.dist-info/RECORD +107 -0
- bear_utils-0.0.1.dist-info/WHEEL +4 -0
bear_utils/__init__.py
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
"""A module for Bear Utils, providing various utilities and tools."""
|
2
|
+
|
3
|
+
from bear_utils.cache import CacheWrapper, cache, cache_factory
|
4
|
+
from bear_utils.config.settings_manager import SettingsManager, get_settings_manager
|
5
|
+
from bear_utils.constants import DEVNULL, STDERR, STDOUT, ExitCode, HTTPStatusCode
|
6
|
+
from bear_utils.database import DatabaseManager
|
7
|
+
from bear_utils.events import Events
|
8
|
+
from bear_utils.extras.responses import FunctionResponse
|
9
|
+
from bear_utils.files.file_handlers.file_handler_factory import FileHandlerFactory
|
10
|
+
from bear_utils.logger_manager import BaseLogger, BufferLogger, ConsoleLogger, FileLogger, LoggingClient, LoggingServer
|
11
|
+
from bear_utils.logger_manager._common import VERBOSE_CONSOLE_FORMAT
|
12
|
+
from bear_utils.logger_manager._styles import VERBOSE
|
13
|
+
from bear_utils.time import (
|
14
|
+
DATE_FORMAT,
|
15
|
+
DATE_TIME_FORMAT,
|
16
|
+
EpochTimestamp,
|
17
|
+
TimeTools,
|
18
|
+
convert_to_milliseconds,
|
19
|
+
seconds_to_time,
|
20
|
+
)
|
21
|
+
|
22
|
+
__all__ = [
|
23
|
+
"DATE_FORMAT",
|
24
|
+
"DATE_TIME_FORMAT",
|
25
|
+
"DEVNULL",
|
26
|
+
"STDERR",
|
27
|
+
"STDOUT",
|
28
|
+
"VERBOSE",
|
29
|
+
"VERBOSE_CONSOLE_FORMAT",
|
30
|
+
"BaseLogger",
|
31
|
+
"BufferLogger",
|
32
|
+
"CacheWrapper",
|
33
|
+
"ConsoleLogger",
|
34
|
+
"DatabaseManager",
|
35
|
+
"EpochTimestamp",
|
36
|
+
"Events",
|
37
|
+
"ExitCode",
|
38
|
+
"FileHandlerFactory",
|
39
|
+
"FileLogger",
|
40
|
+
"FunctionResponse",
|
41
|
+
"HTTPStatusCode",
|
42
|
+
"LoggingClient",
|
43
|
+
"LoggingServer",
|
44
|
+
"SettingsManager",
|
45
|
+
"TimeTools",
|
46
|
+
"cache",
|
47
|
+
"cache_factory",
|
48
|
+
"convert_to_milliseconds",
|
49
|
+
"get_settings_manager",
|
50
|
+
"seconds_to_time",
|
51
|
+
]
|
bear_utils/__main__.py
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
"""Entry-point module, in case you use `python -m bear_utils`.
|
2
|
+
|
3
|
+
Why does this file exist, and why `__main__`? For more info, read:
|
4
|
+
|
5
|
+
- https://www.python.org/dev/peps/pep-0338/
|
6
|
+
- https://docs.python.org/3/using/cmdline.html#cmdoption-m
|
7
|
+
"""
|
8
|
+
|
9
|
+
import sys
|
10
|
+
|
11
|
+
from bear_utils._internal.cli import main
|
12
|
+
|
13
|
+
if __name__ == "__main__":
|
14
|
+
sys.exit(main(sys.argv[1:]))
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
version = "0.0.1"
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Why does this file exist, and why not put this in `__main__`?
|
2
|
+
#
|
3
|
+
# You might be tempted to import things from `__main__` later,
|
4
|
+
# but that will cause problems: the code will get executed twice:
|
5
|
+
#
|
6
|
+
# - When you run `python -m bear_utils` python will execute
|
7
|
+
# `__main__.py` as a script. That means there won't be any
|
8
|
+
# `bear_utils.__main__` in `sys.modules`.
|
9
|
+
# - When you import `__main__` it will get executed again (as a module) because
|
10
|
+
# there's no `bear_utils.__main__` in `sys.modules`.
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
from argparse import Action, ArgumentParser, Namespace
|
14
|
+
import sys
|
15
|
+
from typing import Any
|
16
|
+
|
17
|
+
from bear_utils._internal import debug
|
18
|
+
from bear_utils._internal._version import version as _version
|
19
|
+
from bear_utils.cli._get_version import VALID_BUMP_TYPES, cli_bump
|
20
|
+
from bear_utils.constants import STDERR, ExitCode
|
21
|
+
|
22
|
+
|
23
|
+
class _DebugInfo(Action):
|
24
|
+
def __init__(self, nargs: int | str | None = 0, **kwargs: Any) -> None:
|
25
|
+
super().__init__(nargs=nargs, **kwargs)
|
26
|
+
|
27
|
+
def __call__(self, *_: Any, **__: Any) -> None:
|
28
|
+
debug._print_debug_info()
|
29
|
+
sys.exit(ExitCode.SUCCESS)
|
30
|
+
|
31
|
+
|
32
|
+
class _About(Action):
|
33
|
+
def __init__(self, nargs: int | str | None = 0, **kwargs: Any) -> None:
|
34
|
+
super().__init__(nargs=nargs, **kwargs)
|
35
|
+
|
36
|
+
def __call__(self, *_: Any, **__: Any) -> None:
|
37
|
+
print(debug._get_package_info())
|
38
|
+
sys.exit(ExitCode.SUCCESS)
|
39
|
+
|
40
|
+
|
41
|
+
class _Version(Action):
|
42
|
+
def __init__(self, nargs: int | str | None = 0, **kwargs: Any) -> None:
|
43
|
+
super().__init__(nargs=nargs, **kwargs)
|
44
|
+
|
45
|
+
def __call__(self, *_: Any, **__: Any) -> None:
|
46
|
+
version: str = f"{debug._get_name()} v{_version}"
|
47
|
+
print(version)
|
48
|
+
sys.exit(ExitCode.SUCCESS)
|
49
|
+
|
50
|
+
|
51
|
+
def get_version() -> ExitCode:
|
52
|
+
"""CLI command to get the version of the package."""
|
53
|
+
print(_version)
|
54
|
+
return ExitCode.SUCCESS
|
55
|
+
|
56
|
+
|
57
|
+
def bump_version(args: list[str] | None = None) -> ExitCode:
|
58
|
+
"""CLI command to bump the version of the package."""
|
59
|
+
parser = ArgumentParser(description="Bump the version of the package.")
|
60
|
+
parser.add_argument(
|
61
|
+
"bump_type",
|
62
|
+
type=str,
|
63
|
+
choices=VALID_BUMP_TYPES,
|
64
|
+
help=f"Type of version bump: {', '.join(VALID_BUMP_TYPES)}",
|
65
|
+
)
|
66
|
+
_args: Namespace = parser.parse_args(args or sys.argv[1:])
|
67
|
+
return cli_bump([_args.bump_type, debug.__PACKAGE_NAME__, _version])
|
68
|
+
|
69
|
+
|
70
|
+
def get_parser() -> ArgumentParser:
|
71
|
+
name = debug._get_name()
|
72
|
+
parser = ArgumentParser(description=name.capitalize(), prog=name, exit_on_error=False)
|
73
|
+
parser.add_argument("-V", "--version", action=_Version, help="Print the version of the package")
|
74
|
+
subparser = parser.add_subparsers(dest="command", required=False, help="Available commands")
|
75
|
+
subparser.add_parser("get-version", help="Get the current version of the package")
|
76
|
+
bump = subparser.add_parser("bump-version", help="Bump the version of the package")
|
77
|
+
bump.add_argument("bump_type", type=str, choices=VALID_BUMP_TYPES, help="major, minor, or patch")
|
78
|
+
parser.add_argument("--about", action=_About, help="Print information about the package")
|
79
|
+
parser.add_argument("--debug_info", action=_DebugInfo, help="Print debug information")
|
80
|
+
return parser
|
81
|
+
|
82
|
+
|
83
|
+
def main(args: list[str] | None = None) -> ExitCode:
|
84
|
+
"""Main entry point for the CLI.
|
85
|
+
|
86
|
+
This function is called when the CLI is executed. It can be used to
|
87
|
+
initialize the CLI, parse arguments, and execute commands.
|
88
|
+
|
89
|
+
Args:
|
90
|
+
args (list[str] | None): A list of command-line arguments. If None, uses sys.argv[1:].
|
91
|
+
|
92
|
+
Returns:
|
93
|
+
int: Exit code of the CLI execution. 0 for success, non-zero for failure.
|
94
|
+
"""
|
95
|
+
if args is None:
|
96
|
+
args = sys.argv[1:]
|
97
|
+
try:
|
98
|
+
parser: ArgumentParser = get_parser()
|
99
|
+
opts: Namespace = parser.parse_args(args)
|
100
|
+
command: str | None = opts.command
|
101
|
+
if command is None:
|
102
|
+
parser.print_help()
|
103
|
+
return ExitCode.SUCCESS
|
104
|
+
if command == "get-version":
|
105
|
+
return get_version()
|
106
|
+
if command == "bump-version":
|
107
|
+
if not hasattr(opts, "bump_type"):
|
108
|
+
print("Error: 'bump-version' command requires a 'bump_type' argument.", STDERR)
|
109
|
+
return ExitCode.FAILURE
|
110
|
+
bump_type: str = opts.bump_type
|
111
|
+
return bump_version([bump_type])
|
112
|
+
except Exception as e:
|
113
|
+
print(f"Error initializing CLI: {e}", STDERR)
|
114
|
+
return ExitCode.FAILURE
|
115
|
+
return ExitCode.SUCCESS
|
116
|
+
|
117
|
+
|
118
|
+
if __name__ == "__main__":
|
119
|
+
main()
|
@@ -0,0 +1,174 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from dataclasses import dataclass, field
|
4
|
+
import importlib.metadata
|
5
|
+
from importlib.metadata import PackageNotFoundError, metadata, version
|
6
|
+
import os
|
7
|
+
import platform
|
8
|
+
import sys
|
9
|
+
|
10
|
+
from bear_utils._internal._version import version as _version
|
11
|
+
from bear_utils.cli._get_version import Version
|
12
|
+
|
13
|
+
__PACKAGE_NAME__ = "bear-utils"
|
14
|
+
|
15
|
+
|
16
|
+
@dataclass
|
17
|
+
class _Package:
|
18
|
+
"""Dataclass to store package information."""
|
19
|
+
|
20
|
+
name: str = __PACKAGE_NAME__
|
21
|
+
"""Package name."""
|
22
|
+
version: str = _version
|
23
|
+
"""Package version."""
|
24
|
+
_version: Version = field(default_factory=lambda: Version.from_string(_version))
|
25
|
+
description: str = "No description available."
|
26
|
+
"""Package description."""
|
27
|
+
|
28
|
+
def __post_init__(self) -> None:
|
29
|
+
"""Post-initialization to ensure version is a string."""
|
30
|
+
if not isinstance(self.version, str) or "0.0.0" in self.version:
|
31
|
+
self.version = version(self.name) if self.name else "0.0.0"
|
32
|
+
if not self.description:
|
33
|
+
try:
|
34
|
+
self.description = metadata(self.name)["Summary"]
|
35
|
+
except PackageNotFoundError:
|
36
|
+
self.description = "No description available."
|
37
|
+
|
38
|
+
def __str__(self) -> str:
|
39
|
+
"""String representation of the package information."""
|
40
|
+
return f"{self.name} v{self.version}: {self.description}"
|
41
|
+
|
42
|
+
|
43
|
+
@dataclass
|
44
|
+
class _Variable:
|
45
|
+
"""Dataclass describing an environment variable."""
|
46
|
+
|
47
|
+
name: str
|
48
|
+
"""Variable name."""
|
49
|
+
value: str
|
50
|
+
"""Variable value."""
|
51
|
+
|
52
|
+
|
53
|
+
@dataclass
|
54
|
+
class _Environment:
|
55
|
+
"""Dataclass to store environment information."""
|
56
|
+
|
57
|
+
interpreter_name: str
|
58
|
+
"""Python interpreter name."""
|
59
|
+
interpreter_version: str
|
60
|
+
"""Python interpreter version."""
|
61
|
+
interpreter_path: str
|
62
|
+
"""Path to Python executable."""
|
63
|
+
platform: str
|
64
|
+
"""Operating System."""
|
65
|
+
packages: list[_Package]
|
66
|
+
"""Installed packages."""
|
67
|
+
variables: list[_Variable]
|
68
|
+
"""Environment variables."""
|
69
|
+
|
70
|
+
|
71
|
+
def _interpreter_name_version() -> tuple[str, str]:
|
72
|
+
if hasattr(sys, "implementation"):
|
73
|
+
impl = sys.implementation.version
|
74
|
+
version = f"{impl.major}.{impl.minor}.{impl.micro}"
|
75
|
+
kind = impl.releaselevel
|
76
|
+
if kind != "final":
|
77
|
+
version += kind[0] + str(impl.serial)
|
78
|
+
return sys.implementation.name, version
|
79
|
+
return "", "0.0.0"
|
80
|
+
|
81
|
+
|
82
|
+
def _get_package_info(dist: str = __PACKAGE_NAME__) -> _Package:
|
83
|
+
try:
|
84
|
+
return _Package(
|
85
|
+
name=dist,
|
86
|
+
version=_version or version(dist),
|
87
|
+
description=metadata(dist)["Summary"],
|
88
|
+
)
|
89
|
+
except PackageNotFoundError:
|
90
|
+
return _Package(name=dist)
|
91
|
+
|
92
|
+
|
93
|
+
def _get_name(dist: str = __PACKAGE_NAME__) -> str:
|
94
|
+
"""Get name of the given distribution.
|
95
|
+
|
96
|
+
Parameters:
|
97
|
+
dist: A distribution name.
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
A package name.
|
101
|
+
"""
|
102
|
+
return _get_package_info(dist).name
|
103
|
+
|
104
|
+
|
105
|
+
def _get_version(dist: str = __PACKAGE_NAME__) -> str:
|
106
|
+
"""Get version of the given distribution.
|
107
|
+
|
108
|
+
Parameters:
|
109
|
+
dist: A distribution name.
|
110
|
+
|
111
|
+
Returns:
|
112
|
+
A version number.
|
113
|
+
"""
|
114
|
+
return _get_package_info(dist).version
|
115
|
+
|
116
|
+
|
117
|
+
def _get_description(dist: str = __PACKAGE_NAME__) -> str:
|
118
|
+
"""Get description of the given distribution.
|
119
|
+
|
120
|
+
Parameters:
|
121
|
+
dist: A distribution name.
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
A description string.
|
125
|
+
"""
|
126
|
+
return _get_package_info(dist).description
|
127
|
+
|
128
|
+
|
129
|
+
def _get_debug_info() -> _Environment:
|
130
|
+
"""Get debug/environment information.
|
131
|
+
|
132
|
+
Returns:
|
133
|
+
Environment information.
|
134
|
+
"""
|
135
|
+
py_name, py_version = _interpreter_name_version()
|
136
|
+
packages: list[str] = [__PACKAGE_NAME__]
|
137
|
+
variables: list[str] = [
|
138
|
+
"PYTHONPATH",
|
139
|
+
*[var for var in os.environ if var.startswith(__PACKAGE_NAME__.replace("-", "_"))],
|
140
|
+
]
|
141
|
+
return _Environment(
|
142
|
+
interpreter_name=py_name,
|
143
|
+
interpreter_version=py_version,
|
144
|
+
interpreter_path=sys.executable,
|
145
|
+
platform=platform.platform(),
|
146
|
+
variables=[_Variable(var, val) for var in variables if (val := os.getenv(var))],
|
147
|
+
packages=[_Package(pkg, _get_version(pkg)) for pkg in packages],
|
148
|
+
)
|
149
|
+
|
150
|
+
|
151
|
+
def get_installed_packages() -> list[_Package]:
|
152
|
+
"""Get all installed packages in current environment"""
|
153
|
+
packages = []
|
154
|
+
for dist in importlib.metadata.distributions():
|
155
|
+
packages.append({"name": dist.metadata["Name"], "version": dist.version})
|
156
|
+
return packages
|
157
|
+
|
158
|
+
|
159
|
+
def _print_debug_info() -> None:
|
160
|
+
"""Print debug/environment information."""
|
161
|
+
info: _Environment = _get_debug_info()
|
162
|
+
print(f"- __System__: {info.platform}")
|
163
|
+
print(f"- __Python__: {info.interpreter_name} {info.interpreter_version} ({info.interpreter_path})")
|
164
|
+
print("- __Environment variables__:")
|
165
|
+
for var in info.variables:
|
166
|
+
print(f" - `{var.name}`: `{var.value}`")
|
167
|
+
print("- __Installed packages__:")
|
168
|
+
for pkg in info.packages:
|
169
|
+
print(f" - `{pkg.name}` v{pkg.version}")
|
170
|
+
|
171
|
+
|
172
|
+
if __name__ == "__main__":
|
173
|
+
# _print_debug_info()
|
174
|
+
print(_get_package_info())
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"""AI Helpers Module for Bear Utils."""
|
2
|
+
|
3
|
+
from .ai_helpers._common import (
|
4
|
+
GPT_4_1,
|
5
|
+
GPT_4_1_MINI,
|
6
|
+
GPT_4_1_NANO,
|
7
|
+
PRODUCTION_MODE,
|
8
|
+
TESTING_MODE,
|
9
|
+
AIModel,
|
10
|
+
EnvironmentMode,
|
11
|
+
)
|
12
|
+
from .ai_helpers._config import AIEndpointConfig
|
13
|
+
from .ai_helpers._parsers import CommandResponseParser, PassthroughResponseParser, ResponseParser, TypedResponseParser
|
14
|
+
from .ai_helpers._types import ResponseParser as BaseResponseParser
|
15
|
+
|
16
|
+
__all__ = [
|
17
|
+
"GPT_4_1",
|
18
|
+
"GPT_4_1_MINI",
|
19
|
+
"GPT_4_1_NANO",
|
20
|
+
"PRODUCTION_MODE",
|
21
|
+
"TESTING_MODE",
|
22
|
+
"AIEndpointConfig",
|
23
|
+
"AIModel",
|
24
|
+
"BaseResponseParser",
|
25
|
+
"CommandResponseParser",
|
26
|
+
"EnvironmentMode",
|
27
|
+
"PassthroughResponseParser",
|
28
|
+
"ResponseParser",
|
29
|
+
"TypedResponseParser",
|
30
|
+
]
|
@@ -0,0 +1,136 @@
|
|
1
|
+
"""This module provides helper functions to create AI endpoints with various response parsing strategies."""
|
2
|
+
|
3
|
+
from collections.abc import Callable
|
4
|
+
from typing import Any, cast
|
5
|
+
|
6
|
+
from rich.markdown import Markdown
|
7
|
+
|
8
|
+
from bear_utils.logger_manager import BaseLogger
|
9
|
+
|
10
|
+
from ._common import GPT_4_1_NANO, PRODUCTION_MODE, TESTING_MODE, AIModel, EnvironmentMode
|
11
|
+
from ._config import AIEndpointConfig
|
12
|
+
from ._parsers import JSONResponseParser, ModularAIEndpoint, PassthroughResponseParser, TypedResponseParser
|
13
|
+
|
14
|
+
|
15
|
+
def create_typed_endpoint[T_Response](
|
16
|
+
response_type: type[T_Response],
|
17
|
+
project_name: str,
|
18
|
+
prompt: str,
|
19
|
+
testing_url: str,
|
20
|
+
production_url: str,
|
21
|
+
logger: BaseLogger,
|
22
|
+
transformers: dict[str, Callable] | None = None,
|
23
|
+
environment: EnvironmentMode = PRODUCTION_MODE,
|
24
|
+
chat_model: AIModel = GPT_4_1_NANO,
|
25
|
+
**kwargs,
|
26
|
+
) -> ModularAIEndpoint[T_Response]:
|
27
|
+
"""Create an endpoint with strict TypedDict response typing."""
|
28
|
+
config = AIEndpointConfig(
|
29
|
+
project_name=project_name,
|
30
|
+
prompt=prompt,
|
31
|
+
testing_url=testing_url,
|
32
|
+
production_url=production_url,
|
33
|
+
environment=environment,
|
34
|
+
chat_model=chat_model,
|
35
|
+
**kwargs,
|
36
|
+
)
|
37
|
+
parser: TypedResponseParser[type[T_Response]] = TypedResponseParser(
|
38
|
+
default_response=response_type,
|
39
|
+
response_transformers=transformers,
|
40
|
+
)
|
41
|
+
return cast("ModularAIEndpoint[T_Response]", ModularAIEndpoint(config, logger, parser))
|
42
|
+
|
43
|
+
|
44
|
+
def create_command_endpoint[T_Response](
|
45
|
+
default_response: T_Response,
|
46
|
+
project_name: str,
|
47
|
+
prompt: str,
|
48
|
+
testing_url: str,
|
49
|
+
production_url: str,
|
50
|
+
logger: BaseLogger,
|
51
|
+
environment: EnvironmentMode = EnvironmentMode.PRODUCTION,
|
52
|
+
chat_model: AIModel = GPT_4_1_NANO,
|
53
|
+
**kwargs,
|
54
|
+
) -> ModularAIEndpoint[T_Response]:
|
55
|
+
"""Create an endpoint that returns a command response with Markdown formatting."""
|
56
|
+
config = AIEndpointConfig(
|
57
|
+
project_name=project_name,
|
58
|
+
prompt=prompt,
|
59
|
+
testing_url=testing_url,
|
60
|
+
production_url=production_url,
|
61
|
+
environment=environment,
|
62
|
+
chat_model=chat_model,
|
63
|
+
**kwargs,
|
64
|
+
)
|
65
|
+
|
66
|
+
parser: TypedResponseParser[T_Response] = TypedResponseParser(
|
67
|
+
default_response=default_response,
|
68
|
+
response_transformers={"response": lambda x: Markdown(str(x))},
|
69
|
+
)
|
70
|
+
return ModularAIEndpoint(config=config, logger=logger, response_parser=parser)
|
71
|
+
|
72
|
+
|
73
|
+
def create_flexible_endpoint(
|
74
|
+
project_name: str,
|
75
|
+
prompt: str,
|
76
|
+
testing_url: str,
|
77
|
+
production_url: str,
|
78
|
+
logger: BaseLogger,
|
79
|
+
required_fields: list | None = None,
|
80
|
+
transformers: dict[str, Callable] | None = None,
|
81
|
+
append_json: bool = True,
|
82
|
+
environment: EnvironmentMode = PRODUCTION_MODE,
|
83
|
+
chat_model: AIModel = GPT_4_1_NANO,
|
84
|
+
**kwargs,
|
85
|
+
) -> ModularAIEndpoint[dict[str, Any]]:
|
86
|
+
"""Create an endpoint with flexible JSON parsing."""
|
87
|
+
config = AIEndpointConfig(
|
88
|
+
project_name=project_name,
|
89
|
+
prompt=prompt,
|
90
|
+
testing_url=testing_url,
|
91
|
+
production_url=production_url,
|
92
|
+
append_json_suffix=append_json,
|
93
|
+
environment=environment,
|
94
|
+
chat_model=chat_model,
|
95
|
+
**kwargs,
|
96
|
+
)
|
97
|
+
parser = JSONResponseParser(required_fields=required_fields, response_transformers=transformers)
|
98
|
+
return ModularAIEndpoint(config=config, logger=logger, response_parser=parser)
|
99
|
+
|
100
|
+
|
101
|
+
def create_simple_endpoint(
|
102
|
+
project_name: str,
|
103
|
+
prompt: str,
|
104
|
+
testing_url: str,
|
105
|
+
production_url: str,
|
106
|
+
logger: BaseLogger,
|
107
|
+
environment: EnvironmentMode = PRODUCTION_MODE,
|
108
|
+
chat_model: AIModel = GPT_4_1_NANO,
|
109
|
+
**kwargs,
|
110
|
+
) -> ModularAIEndpoint[dict[str, Any]]:
|
111
|
+
"""Create an endpoint that returns raw output without JSON parsing."""
|
112
|
+
config = AIEndpointConfig(
|
113
|
+
project_name=project_name,
|
114
|
+
prompt=prompt,
|
115
|
+
testing_url=testing_url,
|
116
|
+
production_url=production_url,
|
117
|
+
append_json_suffix=False,
|
118
|
+
environment=environment,
|
119
|
+
chat_model=chat_model,
|
120
|
+
**kwargs,
|
121
|
+
)
|
122
|
+
parser = PassthroughResponseParser()
|
123
|
+
return ModularAIEndpoint(config, logger, parser)
|
124
|
+
|
125
|
+
|
126
|
+
__all__: list[str] = [
|
127
|
+
"PRODUCTION_MODE",
|
128
|
+
"TESTING_MODE",
|
129
|
+
"AIEndpointConfig",
|
130
|
+
"EnvironmentMode",
|
131
|
+
"ModularAIEndpoint",
|
132
|
+
"create_command_endpoint",
|
133
|
+
"create_flexible_endpoint",
|
134
|
+
"create_simple_endpoint",
|
135
|
+
"create_typed_endpoint",
|
136
|
+
]
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from enum import Enum, StrEnum
|
2
|
+
|
3
|
+
|
4
|
+
class EnvironmentMode(Enum):
|
5
|
+
TESTING = "testing"
|
6
|
+
PRODUCTION = "production"
|
7
|
+
|
8
|
+
|
9
|
+
class AIModel(StrEnum):
|
10
|
+
GPT_4_1_NANO = "gpt-4.1-nano"
|
11
|
+
GPT_4_1_MINI = "gpt-4.1-mini"
|
12
|
+
GPT_4_1 = "gpt-4.1"
|
13
|
+
|
14
|
+
|
15
|
+
GPT_4_1_NANO = AIModel.GPT_4_1_NANO
|
16
|
+
GPT_4_1_MINI = AIModel.GPT_4_1_MINI
|
17
|
+
GPT_4_1 = AIModel.GPT_4_1
|
18
|
+
TESTING_MODE = EnvironmentMode.TESTING
|
19
|
+
PRODUCTION_MODE = EnvironmentMode.PRODUCTION
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
|
3
|
+
from ._common import GPT_4_1_NANO, PRODUCTION_MODE, AIModel, EnvironmentMode
|
4
|
+
|
5
|
+
|
6
|
+
@dataclass
|
7
|
+
class AIEndpointConfig:
|
8
|
+
"""Configuration for AI endpoint communication."""
|
9
|
+
|
10
|
+
project_name: str
|
11
|
+
bearer_token: str
|
12
|
+
prompt: str
|
13
|
+
testing_url: str
|
14
|
+
production_url: str
|
15
|
+
connection_timeout: int = 20
|
16
|
+
append_json_suffix: bool = True
|
17
|
+
json_suffix: str = " \nEnsure to output your response as json as specified in the prompt"
|
18
|
+
chat_model: AIModel | str = GPT_4_1_NANO
|
19
|
+
environment: EnvironmentMode = PRODUCTION_MODE
|
20
|
+
|
21
|
+
@property
|
22
|
+
def url(self) -> str:
|
23
|
+
"""Get the appropriate URL based on environment."""
|
24
|
+
return self.testing_url if self.environment == EnvironmentMode.TESTING else self.production_url
|