mantisdk 0.1.0__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.
Potentially problematic release.
This version of mantisdk might be problematic. Click here for more details.
- mantisdk/__init__.py +22 -0
- mantisdk/adapter/__init__.py +15 -0
- mantisdk/adapter/base.py +94 -0
- mantisdk/adapter/messages.py +270 -0
- mantisdk/adapter/triplet.py +1028 -0
- mantisdk/algorithm/__init__.py +39 -0
- mantisdk/algorithm/apo/__init__.py +5 -0
- mantisdk/algorithm/apo/apo.py +889 -0
- mantisdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
- mantisdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
- mantisdk/algorithm/base.py +162 -0
- mantisdk/algorithm/decorator.py +264 -0
- mantisdk/algorithm/fast.py +250 -0
- mantisdk/algorithm/gepa/__init__.py +59 -0
- mantisdk/algorithm/gepa/adapter.py +459 -0
- mantisdk/algorithm/gepa/gepa.py +364 -0
- mantisdk/algorithm/gepa/lib/__init__.py +18 -0
- mantisdk/algorithm/gepa/lib/adapters/README.md +12 -0
- mantisdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +266 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +705 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
- mantisdk/algorithm/gepa/lib/api.py +375 -0
- mantisdk/algorithm/gepa/lib/core/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/core/adapter.py +180 -0
- mantisdk/algorithm/gepa/lib/core/data_loader.py +74 -0
- mantisdk/algorithm/gepa/lib/core/engine.py +356 -0
- mantisdk/algorithm/gepa/lib/core/result.py +233 -0
- mantisdk/algorithm/gepa/lib/core/state.py +636 -0
- mantisdk/algorithm/gepa/lib/examples/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/examples/aime.py +24 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
- mantisdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
- mantisdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
- mantisdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
- mantisdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +455 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +824 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
- mantisdk/algorithm/gepa/lib/gepa_utils.py +117 -0
- mantisdk/algorithm/gepa/lib/logging/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
- mantisdk/algorithm/gepa/lib/logging/logger.py +75 -0
- mantisdk/algorithm/gepa/lib/logging/utils.py +103 -0
- mantisdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/proposer/base.py +31 -0
- mantisdk/algorithm/gepa/lib/proposer/merge.py +357 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
- mantisdk/algorithm/gepa/lib/py.typed +0 -0
- mantisdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
- mantisdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
- mantisdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
- mantisdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
- mantisdk/algorithm/gepa/lib/strategies/instruction_proposal.py +127 -0
- mantisdk/algorithm/gepa/lib/utils/__init__.py +10 -0
- mantisdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
- mantisdk/algorithm/gepa/tracing.py +105 -0
- mantisdk/algorithm/utils.py +177 -0
- mantisdk/algorithm/verl/__init__.py +5 -0
- mantisdk/algorithm/verl/interface.py +202 -0
- mantisdk/cli/__init__.py +56 -0
- mantisdk/cli/prometheus.py +115 -0
- mantisdk/cli/store.py +131 -0
- mantisdk/cli/vllm.py +29 -0
- mantisdk/client.py +408 -0
- mantisdk/config.py +348 -0
- mantisdk/emitter/__init__.py +43 -0
- mantisdk/emitter/annotation.py +370 -0
- mantisdk/emitter/exception.py +54 -0
- mantisdk/emitter/message.py +61 -0
- mantisdk/emitter/object.py +117 -0
- mantisdk/emitter/reward.py +320 -0
- mantisdk/env_var.py +156 -0
- mantisdk/execution/__init__.py +15 -0
- mantisdk/execution/base.py +64 -0
- mantisdk/execution/client_server.py +443 -0
- mantisdk/execution/events.py +69 -0
- mantisdk/execution/inter_process.py +16 -0
- mantisdk/execution/shared_memory.py +282 -0
- mantisdk/instrumentation/__init__.py +119 -0
- mantisdk/instrumentation/agentops.py +314 -0
- mantisdk/instrumentation/agentops_langchain.py +45 -0
- mantisdk/instrumentation/litellm.py +83 -0
- mantisdk/instrumentation/vllm.py +81 -0
- mantisdk/instrumentation/weave.py +500 -0
- mantisdk/litagent/__init__.py +11 -0
- mantisdk/litagent/decorator.py +536 -0
- mantisdk/litagent/litagent.py +252 -0
- mantisdk/llm_proxy.py +1890 -0
- mantisdk/logging.py +370 -0
- mantisdk/reward.py +7 -0
- mantisdk/runner/__init__.py +11 -0
- mantisdk/runner/agent.py +845 -0
- mantisdk/runner/base.py +182 -0
- mantisdk/runner/legacy.py +309 -0
- mantisdk/semconv.py +170 -0
- mantisdk/server.py +401 -0
- mantisdk/store/__init__.py +23 -0
- mantisdk/store/base.py +897 -0
- mantisdk/store/client_server.py +2092 -0
- mantisdk/store/collection/__init__.py +30 -0
- mantisdk/store/collection/base.py +587 -0
- mantisdk/store/collection/memory.py +970 -0
- mantisdk/store/collection/mongo.py +1412 -0
- mantisdk/store/collection_based.py +1823 -0
- mantisdk/store/insight.py +648 -0
- mantisdk/store/listener.py +58 -0
- mantisdk/store/memory.py +396 -0
- mantisdk/store/mongo.py +165 -0
- mantisdk/store/sqlite.py +3 -0
- mantisdk/store/threading.py +357 -0
- mantisdk/store/utils.py +142 -0
- mantisdk/tracer/__init__.py +16 -0
- mantisdk/tracer/agentops.py +242 -0
- mantisdk/tracer/base.py +287 -0
- mantisdk/tracer/dummy.py +106 -0
- mantisdk/tracer/otel.py +555 -0
- mantisdk/tracer/weave.py +677 -0
- mantisdk/trainer/__init__.py +6 -0
- mantisdk/trainer/init_utils.py +263 -0
- mantisdk/trainer/legacy.py +367 -0
- mantisdk/trainer/registry.py +12 -0
- mantisdk/trainer/trainer.py +618 -0
- mantisdk/types/__init__.py +6 -0
- mantisdk/types/core.py +553 -0
- mantisdk/types/resources.py +204 -0
- mantisdk/types/tracer.py +515 -0
- mantisdk/types/tracing.py +218 -0
- mantisdk/utils/__init__.py +1 -0
- mantisdk/utils/id.py +18 -0
- mantisdk/utils/metrics.py +1025 -0
- mantisdk/utils/otel.py +578 -0
- mantisdk/utils/otlp.py +536 -0
- mantisdk/utils/server_launcher.py +1045 -0
- mantisdk/utils/system_snapshot.py +81 -0
- mantisdk/verl/__init__.py +8 -0
- mantisdk/verl/__main__.py +6 -0
- mantisdk/verl/async_server.py +46 -0
- mantisdk/verl/config.yaml +27 -0
- mantisdk/verl/daemon.py +1154 -0
- mantisdk/verl/dataset.py +44 -0
- mantisdk/verl/entrypoint.py +248 -0
- mantisdk/verl/trainer.py +549 -0
- mantisdk-0.1.0.dist-info/METADATA +119 -0
- mantisdk-0.1.0.dist-info/RECORD +190 -0
- mantisdk-0.1.0.dist-info/WHEEL +4 -0
- mantisdk-0.1.0.dist-info/entry_points.txt +2 -0
- mantisdk-0.1.0.dist-info/licenses/LICENSE +19 -0
mantisdk/logging.py
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
import platform
|
|
8
|
+
import sys
|
|
9
|
+
import warnings
|
|
10
|
+
from logging.config import dictConfig
|
|
11
|
+
from typing import Any, Dict, Optional
|
|
12
|
+
|
|
13
|
+
from rich.console import Console
|
|
14
|
+
|
|
15
|
+
__all__ = ["setup", "configure_logger", "setup_module"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def configure_logger(level: int = logging.INFO, name: str = "mantisdk") -> logging.Logger:
|
|
19
|
+
"""Create or reset a namespaced logger with a consistent console format.
|
|
20
|
+
|
|
21
|
+
This helper clears any previously attached handlers before binding a single
|
|
22
|
+
`StreamHandler` that writes to standard output. The resulting logger does
|
|
23
|
+
not propagate to the root logger, preventing duplicate log emission when
|
|
24
|
+
applications compose multiple logging configurations.
|
|
25
|
+
|
|
26
|
+
!!! danger
|
|
27
|
+
|
|
28
|
+
This function is deprecated in favor of [`setup_logging`][mantisdk.setup_logging].
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
level: Logging level applied both to the logger and the installed
|
|
32
|
+
handler. Defaults to `logging.INFO`.
|
|
33
|
+
name: Dotted path for the logger instance. Defaults to
|
|
34
|
+
`"mantisdk"`.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Configured logger instance ready for immediate use.
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
```python
|
|
41
|
+
from mantisdk import configure_logger
|
|
42
|
+
|
|
43
|
+
logger = configure_logger(level=logging.INFO)
|
|
44
|
+
logger.info("mantisdk is ready!")
|
|
45
|
+
```
|
|
46
|
+
"""
|
|
47
|
+
warnings.warn("This function is deprecated in favor of `setup_logging`.", DeprecationWarning, stacklevel=2)
|
|
48
|
+
|
|
49
|
+
return setup_module(level=level, name=name, console=True, color=True, propagate=False)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
DEFAULT_FORMAT = "%(asctime)s [%(levelname)s] (Process-%(process)d %(name)s) %(message)s"
|
|
53
|
+
DATE_FORMAT = "%H:%M:%S"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _to_level_value(lvl: int | str) -> int:
|
|
57
|
+
if isinstance(lvl, int):
|
|
58
|
+
return lvl
|
|
59
|
+
val = getattr(logging, str(lvl).upper(), None)
|
|
60
|
+
if val is None:
|
|
61
|
+
raise ValueError(f"Invalid log level: {lvl}")
|
|
62
|
+
return val
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _ensure_file_handler(
|
|
66
|
+
logger: logging.Logger,
|
|
67
|
+
filename: str,
|
|
68
|
+
*,
|
|
69
|
+
level: int,
|
|
70
|
+
formatter: Optional[logging.Formatter],
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Attach a FileHandler to `logger` for `filename` if it doesn't already exist."""
|
|
73
|
+
abspath = os.path.abspath(filename)
|
|
74
|
+
|
|
75
|
+
# Avoid duplicates
|
|
76
|
+
for h in logger.handlers:
|
|
77
|
+
if isinstance(h, logging.FileHandler) and getattr(h, "baseFilename", None) == abspath:
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
# Ensure directory exists
|
|
81
|
+
dirname = os.path.dirname(abspath)
|
|
82
|
+
if dirname:
|
|
83
|
+
os.makedirs(dirname, exist_ok=True)
|
|
84
|
+
|
|
85
|
+
fh = logging.FileHandler(abspath, encoding="utf-8")
|
|
86
|
+
fh.setLevel(level)
|
|
87
|
+
if formatter is not None:
|
|
88
|
+
fh.setFormatter(formatter)
|
|
89
|
+
else:
|
|
90
|
+
fh.setFormatter(logging.Formatter(DEFAULT_FORMAT, DATE_FORMAT))
|
|
91
|
+
|
|
92
|
+
logger.addHandler(fh)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def setup(
|
|
96
|
+
level: int | str = "INFO",
|
|
97
|
+
*,
|
|
98
|
+
console: bool = True,
|
|
99
|
+
color: bool | Dict[str, Any] = True,
|
|
100
|
+
propagate: bool = False,
|
|
101
|
+
disable_existing_loggers: bool = False,
|
|
102
|
+
capture_warnings: bool = False,
|
|
103
|
+
submodule_levels: Optional[dict[str, int | str]] = None,
|
|
104
|
+
extra_handlers: Optional[list[logging.Handler]] = None,
|
|
105
|
+
formatter: Optional[logging.Formatter] = None,
|
|
106
|
+
apply_to: Optional[list[str]] = None,
|
|
107
|
+
files: Optional[str | dict[str, str]] = None,
|
|
108
|
+
) -> None:
|
|
109
|
+
"""Configures logging for the `mantisdk` logger hierarchy.
|
|
110
|
+
|
|
111
|
+
This function provides a one-stop setup utility for configuring the
|
|
112
|
+
`mantisdk` root logger and optionally its submodules or external
|
|
113
|
+
loggers. It supports console logging, colored rich output, per-submodule
|
|
114
|
+
log levels, and optional handler/formatter injection.
|
|
115
|
+
|
|
116
|
+
The setup is intentionally isolated: it does not modify the global root
|
|
117
|
+
logger or loggers belonging to other libraries unless explicitly directed
|
|
118
|
+
via `apply_to`.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
level:
|
|
122
|
+
Logging level for the base `mantisdk` logger. Accepts either
|
|
123
|
+
an integer (e.g., `logging.DEBUG`) or a string level name
|
|
124
|
+
(e.g., `"INFO"`). Defaults to `"INFO"`.
|
|
125
|
+
console:
|
|
126
|
+
Whether to attach a console handler to the logger. Defaults to
|
|
127
|
+
`True`.
|
|
128
|
+
color:
|
|
129
|
+
Enables rich-formatted output using `RichHandler` when `True`
|
|
130
|
+
or a configuration dict. If `False`, a plain text formatter is
|
|
131
|
+
used instead. Defaults to `True`.
|
|
132
|
+
propagate:
|
|
133
|
+
Whether `mantisdk` logs should propagate to ancestor
|
|
134
|
+
loggers. Defaults to `False`.
|
|
135
|
+
disable_existing_loggers:
|
|
136
|
+
Passed to `logging.config.dictConfig`. If `True`, disables all
|
|
137
|
+
existing configured loggers before applying this configuration.
|
|
138
|
+
Defaults to `False`.
|
|
139
|
+
capture_warnings:
|
|
140
|
+
If `True`, redirects Python `warnings` emitted via the `warnings`
|
|
141
|
+
module into the logging system. Defaults to `False`.
|
|
142
|
+
submodule_levels:
|
|
143
|
+
Mapping of submodule logger names to logging levels. If a specified
|
|
144
|
+
submodule level is more verbose than the base level, a warning is emitted.
|
|
145
|
+
extra_handlers:
|
|
146
|
+
A list of user-provided handlers to attach to the `mantisdk` logger.
|
|
147
|
+
Handlers are added idempotently; duplicates are not reattached.
|
|
148
|
+
formatter:
|
|
149
|
+
A formatter to apply to any handler under `mantisdk` that does not
|
|
150
|
+
already have one assigned. Useful for customizing output without overwriting
|
|
151
|
+
formatters on custom handlers.
|
|
152
|
+
apply_to:
|
|
153
|
+
A list of additional logger names to configure identically to
|
|
154
|
+
`mantisdk` base logger. Their handlers are replaced with copies of the base
|
|
155
|
+
handlers, and propagation is disabled to avoid duplicate log emission.
|
|
156
|
+
files:
|
|
157
|
+
If a string, attach a FileHandler to the base `mantisdk` logger.
|
|
158
|
+
If a dict, for each `(logger_name, filename)` pair, attach a FileHandler
|
|
159
|
+
directly to that logger.
|
|
160
|
+
Each file handler should use the logger's effective level at creation.
|
|
161
|
+
|
|
162
|
+
Notes:
|
|
163
|
+
* On Windows, this function forces UTF-8 mode in the console to prevent
|
|
164
|
+
issues with rich output or special characters.
|
|
165
|
+
* Submodule loggers can generate records below the handler's emission
|
|
166
|
+
threshold. Whether such records appear depends on both the logger's
|
|
167
|
+
level and the handler's level.
|
|
168
|
+
* `apply_to` loggers inherit the same handlers but do not propagate
|
|
169
|
+
upward, yielding isolated, consistent behavior.
|
|
170
|
+
|
|
171
|
+
Examples:
|
|
172
|
+
Basic setup:
|
|
173
|
+
|
|
174
|
+
>>> setup()
|
|
175
|
+
|
|
176
|
+
Enabling debug mode with no color:
|
|
177
|
+
|
|
178
|
+
>>> setup(level="DEBUG", color=False)
|
|
179
|
+
|
|
180
|
+
Overriding specific submodule levels:
|
|
181
|
+
|
|
182
|
+
>>> setup(submodule_levels={"mantisdk.io": "DEBUG"})
|
|
183
|
+
|
|
184
|
+
Attaching an additional file handler:
|
|
185
|
+
|
|
186
|
+
>>> fh = logging.FileHandler("app.log")
|
|
187
|
+
>>> setup(extra_handlers=[fh])
|
|
188
|
+
"""
|
|
189
|
+
# Ensure UTF-8 encoding on Windows consoles
|
|
190
|
+
# Note: This change does not fully represent support for execution under the windows system.
|
|
191
|
+
# It only fixes console printing issues caused by special characters.
|
|
192
|
+
# TODO: More comprehensive Windows support may be needed in the future.
|
|
193
|
+
if platform.system() == "Windows":
|
|
194
|
+
os.environ["PYTHONUTF8"] = "1"
|
|
195
|
+
|
|
196
|
+
base_logger = setup_module(
|
|
197
|
+
level,
|
|
198
|
+
name="mantisdk",
|
|
199
|
+
console=console,
|
|
200
|
+
color=color,
|
|
201
|
+
propagate=propagate,
|
|
202
|
+
disable_existing_loggers=disable_existing_loggers,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
base_level_value = base_logger.level
|
|
206
|
+
|
|
207
|
+
# Apply user-provided formatter (only to handlers without one,
|
|
208
|
+
# so we don't clobber custom extra_handlers)
|
|
209
|
+
if formatter is not None:
|
|
210
|
+
for h in base_logger.handlers:
|
|
211
|
+
if h.formatter is None:
|
|
212
|
+
h.setFormatter(formatter)
|
|
213
|
+
|
|
214
|
+
# Attach user-provided handler(s) if any, idempotently
|
|
215
|
+
if extra_handlers:
|
|
216
|
+
for h in extra_handlers:
|
|
217
|
+
if h not in base_logger.handlers:
|
|
218
|
+
base_logger.addHandler(h)
|
|
219
|
+
|
|
220
|
+
# Per-submodule levels
|
|
221
|
+
if submodule_levels:
|
|
222
|
+
for name, lvl in submodule_levels.items():
|
|
223
|
+
sub_level = _to_level_value(lvl)
|
|
224
|
+
|
|
225
|
+
# Emit a warning if submodule level is lower (more verbose) than the global/base level
|
|
226
|
+
if sub_level < base_level_value:
|
|
227
|
+
base_logger.warning(
|
|
228
|
+
"Submodule logger '%s' level %s (%s) is more verbose than base "
|
|
229
|
+
"logger level %s (%s). Records below the base level may still be "
|
|
230
|
+
"filtered out by handlers depending on their own levels.",
|
|
231
|
+
name,
|
|
232
|
+
lvl,
|
|
233
|
+
sub_level,
|
|
234
|
+
logging.getLevelName(base_level_value),
|
|
235
|
+
base_level_value,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# The logger will *create* records down to the logger's level, but a handler
|
|
239
|
+
# with a higher level will still drop anything below its own threshold.
|
|
240
|
+
# Effective emission is gated by both: record.level >= logger.level AND handler.level.
|
|
241
|
+
logging.getLogger(name).setLevel(lvl)
|
|
242
|
+
|
|
243
|
+
# Attach file handlers if requested
|
|
244
|
+
if files is not None:
|
|
245
|
+
if isinstance(files, str):
|
|
246
|
+
# Single file for the entire `mantisdk` hierarchy.
|
|
247
|
+
_ensure_file_handler(
|
|
248
|
+
logger=base_logger,
|
|
249
|
+
filename=files,
|
|
250
|
+
level=base_level_value,
|
|
251
|
+
formatter=formatter,
|
|
252
|
+
)
|
|
253
|
+
else:
|
|
254
|
+
# Per-logger files
|
|
255
|
+
for logger_name, filename in files.items():
|
|
256
|
+
lg = logging.getLogger(logger_name)
|
|
257
|
+
# Use the logger's *effective* level at creation time
|
|
258
|
+
effective_level = lg.getEffectiveLevel()
|
|
259
|
+
_ensure_file_handler(
|
|
260
|
+
logger=lg,
|
|
261
|
+
filename=filename,
|
|
262
|
+
level=effective_level,
|
|
263
|
+
formatter=formatter,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# Optionally apply the same handler setup to other loggers outside this module
|
|
267
|
+
if apply_to:
|
|
268
|
+
for name in apply_to:
|
|
269
|
+
lg = logging.getLogger(name)
|
|
270
|
+
# This removes any existing handlers so we don't duplicate output
|
|
271
|
+
# and ensures these loggers share exactly the same handlers as base_logger.
|
|
272
|
+
lg.handlers.clear()
|
|
273
|
+
for h in base_logger.handlers:
|
|
274
|
+
lg.addHandler(h)
|
|
275
|
+
lg.setLevel(base_logger.level)
|
|
276
|
+
# We've attached handlers directly to these loggers; if propagate
|
|
277
|
+
# stayed True, records would bubble up to ancestor loggers and could be
|
|
278
|
+
# emitted twice (here and on the parent/root). Setting False isolates them.
|
|
279
|
+
lg.propagate = False
|
|
280
|
+
|
|
281
|
+
# Optionally capture warnings
|
|
282
|
+
if capture_warnings:
|
|
283
|
+
logging.captureWarnings(True)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def setup_module(
|
|
287
|
+
level: int | str = "INFO",
|
|
288
|
+
*,
|
|
289
|
+
name: str = "mantisdk",
|
|
290
|
+
console: bool = True,
|
|
291
|
+
color: bool | Dict[str, Any] = True,
|
|
292
|
+
propagate: bool = False,
|
|
293
|
+
disable_existing_loggers: bool = False,
|
|
294
|
+
) -> logging.Logger:
|
|
295
|
+
"""Initializes and returns the base logger for `mantisdk`.
|
|
296
|
+
|
|
297
|
+
This function constructs and applies a `dictConfig` configuration for the
|
|
298
|
+
logger hierarchy rooted at `name`. It supports either rich console
|
|
299
|
+
formatting (via `RichHandler`) or plain text formatting, based on the
|
|
300
|
+
`color` argument.
|
|
301
|
+
|
|
302
|
+
Unlike [`setup_logging`][mantisdk.setup_logging], this function configures only a single logger namespace
|
|
303
|
+
and does not attach extra handlers or submodule levels. It is primarily used
|
|
304
|
+
internally by [`setup_logging`][mantisdk.setup_logging] but is also suitable for direct integration in
|
|
305
|
+
custom logging workflows.
|
|
306
|
+
"""
|
|
307
|
+
root_cfg: Dict[str, Any] = {
|
|
308
|
+
"version": 1,
|
|
309
|
+
"disable_existing_loggers": disable_existing_loggers,
|
|
310
|
+
"loggers": {
|
|
311
|
+
name: {
|
|
312
|
+
"handlers": [],
|
|
313
|
+
"level": level,
|
|
314
|
+
"propagate": propagate,
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
"handlers": {},
|
|
318
|
+
"formatters": {},
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
# Choose formatter / handler definition
|
|
322
|
+
if color is not False and console:
|
|
323
|
+
# Console must be true to display colored outputs
|
|
324
|
+
if isinstance(color, dict):
|
|
325
|
+
rich_handler_config = color
|
|
326
|
+
else:
|
|
327
|
+
rich_handler_config: Dict[str, Any] = {
|
|
328
|
+
"rich_tracebacks": False,
|
|
329
|
+
"markup": False,
|
|
330
|
+
"show_time": True,
|
|
331
|
+
"show_path": True,
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if not _has_width():
|
|
335
|
+
# e.g., in a CI environment.
|
|
336
|
+
rich_handler_config["console"] = Console(width=200)
|
|
337
|
+
|
|
338
|
+
root_cfg["handlers"]["console"] = {
|
|
339
|
+
"class": "rich.logging.RichHandler",
|
|
340
|
+
"level": level,
|
|
341
|
+
**rich_handler_config,
|
|
342
|
+
}
|
|
343
|
+
# RichHandler manages its own style; keep formatter None
|
|
344
|
+
else:
|
|
345
|
+
fmt_name = "plain"
|
|
346
|
+
root_cfg["formatters"][fmt_name] = {
|
|
347
|
+
"format": DEFAULT_FORMAT,
|
|
348
|
+
"datefmt": DATE_FORMAT,
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if console:
|
|
352
|
+
root_cfg["handlers"]["console"] = {
|
|
353
|
+
"class": "logging.StreamHandler",
|
|
354
|
+
"level": level,
|
|
355
|
+
"formatter": fmt_name,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
# Attach selected handlers to mantisdk
|
|
359
|
+
handler_names = list(root_cfg["handlers"].keys())
|
|
360
|
+
root_cfg["loggers"][name]["handlers"] = handler_names
|
|
361
|
+
|
|
362
|
+
# Apply dictConfig (this resets the logger handlers)
|
|
363
|
+
dictConfig(root_cfg)
|
|
364
|
+
|
|
365
|
+
return logging.getLogger(name)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def _has_width() -> bool:
|
|
369
|
+
"""Automatically determine whether the terminal has a width."""
|
|
370
|
+
return sys.stdout.isatty()
|
mantisdk/reward.py
ADDED