prediction-market-agent-tooling 0.64.2.dev604__py3-none-any.whl → 0.64.3__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.
@@ -2,11 +2,12 @@ import builtins
2
2
  import logging
3
3
  import sys
4
4
  import typing as t
5
- import warnings
6
5
  from enum import Enum
7
6
 
7
+ import typer.main
8
8
  from loguru import logger
9
9
  from pydantic_settings import BaseSettings, SettingsConfigDict
10
+ from pythonjsonlogger import jsonlogger
10
11
 
11
12
 
12
13
  class LogFormat(str, Enum):
@@ -31,17 +32,35 @@ class LogConfig(BaseSettings):
31
32
  LOG_LEVEL: LogLevel = LogLevel.DEBUG
32
33
 
33
34
 
34
- class NoNewLineStreamHandler(logging.StreamHandler): # type: ignore # StreamHandler is not typed in the standard library.
35
- def format(self, record: logging.LogRecord) -> str:
36
- return super().format(record).replace("\n", " ")
37
-
35
+ class _CustomJsonFormatter(jsonlogger.JsonFormatter):
36
+ def add_fields(
37
+ self,
38
+ log_record: dict[str, t.Any],
39
+ record: logging.LogRecord,
40
+ message_dict: dict[str, t.Any],
41
+ ) -> None:
42
+ super().add_fields(log_record, record, message_dict)
43
+ # Include "level" and "severity" with the same value as "levelname" to be friendly with log aggregators.
44
+ if log_record.get("levelname"):
45
+ log_record["level"] = log_record["levelname"]
46
+ log_record["severity"] = log_record["levelname"]
47
+
48
+ @staticmethod
49
+ def get_handler() -> logging.StreamHandler: # type: ignore # Seems correct, but mypy doesn't like it.
50
+ logHandler = logging.StreamHandler()
51
+ formatter = _CustomJsonFormatter("%(asctime)s %(levelname)s %(message)s")
52
+ logHandler.setFormatter(formatter)
53
+ return logHandler
54
+
55
+
56
+ def _handle_exception(
57
+ exc_type: type[BaseException], exc_value: BaseException, exc_traceback: t.Any
58
+ ) -> None:
59
+ if issubclass(exc_type, KeyboardInterrupt):
60
+ sys.__excepthook__(exc_type, exc_value, exc_traceback)
61
+ return
38
62
 
39
- GCP_LOG_LOGURU_FORMAT = (
40
- "{level:<.1}{time:MMDD HH:mm:ss} {process} {name}:{line}] {message}"
41
- )
42
- GCP_LOG_LOGGING_FORMAT, GCP_LOG_FORMAT_LOGGING_DATEFMT = (
43
- "%(levelname).1s%(asctime)s %(process)d %(name)s:%(lineno)d] %(message)s"
44
- ), "%m%d %H:%M:%S"
63
+ logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
45
64
 
46
65
 
47
66
  def patch_logger() -> None:
@@ -57,49 +76,44 @@ def patch_logger() -> None:
57
76
  config = LogConfig()
58
77
 
59
78
  if config.LOG_FORMAT == LogFormat.GCP:
60
- format_loguru = GCP_LOG_LOGURU_FORMAT
61
- format_logging = GCP_LOG_LOGGING_FORMAT
62
- datefmt_logging = GCP_LOG_FORMAT_LOGGING_DATEFMT
63
- print_logging = print_using_loguru_info
64
- handlers: list[logging.Handler] | None = [NoNewLineStreamHandler()]
79
+ handler = _CustomJsonFormatter.get_handler()
80
+ print_logging = print_using_logger_info
81
+ sys.excepthook = _handle_exception
82
+ typer.main.except_hook = _handle_exception # type: ignore # Monkey patching, it's messy but it works.
65
83
 
66
84
  elif config.LOG_FORMAT == LogFormat.DEFAULT:
67
- format_loguru, format_logging, datefmt_logging = None, None, None
85
+ handler = None
68
86
  print_logging = None
69
- handlers = None
70
87
 
71
88
  else:
72
89
  raise ValueError(f"Unknown log format: {config.LOG_FORMAT}")
73
90
 
74
91
  # Change built-in logging.
75
- if format_logging is not None:
92
+ if handler is not None:
76
93
  logging.basicConfig(
77
94
  level=config.LOG_LEVEL.value,
78
- format=format_logging,
79
- datefmt=datefmt_logging,
80
- handlers=handlers,
95
+ handlers=[handler],
81
96
  )
82
-
83
97
  # Configure all existing loggers
84
98
  for logger_name in logging.root.manager.loggerDict:
85
99
  existing_logger = logging.getLogger(logger_name)
86
100
  existing_logger.setLevel(config.LOG_LEVEL.value)
87
- if handlers is not None:
88
- existing_logger.handlers = handlers
101
+ # Remove existing handlers
102
+ if existing_logger.hasHandlers():
103
+ existing_logger.handlers.clear()
104
+ # And add ours only
105
+ existing_logger.addHandler(handler)
89
106
  existing_logger.propagate = False
90
107
 
91
108
  # Change loguru.
92
- if format_loguru is not None:
109
+ if handler is not None:
93
110
  logger.remove()
94
111
  logger.add(
95
- sys.stdout,
96
- format=format_loguru,
112
+ handler,
97
113
  level=config.LOG_LEVEL.value,
98
- colorize=True,
114
+ colorize=False,
99
115
  )
100
116
 
101
- # Change warning formatting to a simpler one (no source code in a new line).
102
- warnings.formatwarning = simple_warning_format
103
117
  # Use logging module for warnings.
104
118
  logging.captureWarnings(True)
105
119
 
@@ -110,23 +124,13 @@ def patch_logger() -> None:
110
124
  logger.info(f"Patched logger for {config.LOG_FORMAT.value} format.")
111
125
 
112
126
 
113
- def print_using_loguru_info(
127
+ def print_using_logger_info(
114
128
  *values: object,
115
129
  sep: str = " ",
116
130
  end: str = "\n",
117
131
  **kwargs: t.Any,
118
132
  ) -> None:
119
- message = sep.join(map(str, values)) + end
120
- message = message.strip().replace(
121
- "\n", "\\n"
122
- ) # Escape new lines, because otherwise logs will be broken.
123
- logger.info(message)
124
-
125
-
126
- def simple_warning_format(message, category, filename, lineno, line=None): # type: ignore[no-untyped-def] # Not typed in the standard library neither.
127
- return f"{category.__name__}: {message}".strip().replace(
128
- "\n", "\\n"
129
- ) # Escape new lines, because otherwise logs will be broken.
133
+ logger.info(sep.join(map(str, values)) + end)
130
134
 
131
135
 
132
136
  patch_logger()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.64.2.dev604
3
+ Version: 0.64.3
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.13
@@ -46,6 +46,7 @@ Requires-Dist: pydantic-settings (>=2.4.0,<3.0.0)
46
46
  Requires-Dist: pymongo (>=4.8.0,<5.0.0)
47
47
  Requires-Dist: pytest-postgresql (>=6.1.1,<7.0.0)
48
48
  Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
49
+ Requires-Dist: python-json-logger (>=3.3.0,<4.0.0)
49
50
  Requires-Dist: safe-cli (>=1.0.0,<2.0.0)
50
51
  Requires-Dist: safe-eth-py (>=6.0.0b41,<7.0.0)
51
52
  Requires-Dist: scikit-learn (>=1.3.1,<2.0.0)
@@ -35,7 +35,7 @@ prediction_market_agent_tooling/gtypes.py,sha256=bUIZfZIGvIi3aiZNu5rVE9kRevw8sfM
35
35
  prediction_market_agent_tooling/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  prediction_market_agent_tooling/jobs/jobs_models.py,sha256=8vYafsK1cqMWQtjBoq9rruroF84xAVD00vBTMWH6QMg,2166
37
37
  prediction_market_agent_tooling/jobs/omen/omen_jobs.py,sha256=Pf6QxPXGyie-2l_wZUjaGPTjZTlpv50_JhP40mULBaU,5048
38
- prediction_market_agent_tooling/loggers.py,sha256=MvCkQSJL2_0yErNatqr81sJlc4aOgPzDp9VNrIhKUcc,4140
38
+ prediction_market_agent_tooling/loggers.py,sha256=R56BCTlJ7GZMNHgAtF1QLe0hrRzchcO2NdbKr-v0Q7g,4217
39
39
  prediction_market_agent_tooling/markets/agent_market.py,sha256=1NomilM0GCXcRq_1N_cr2AbSK5ONTowFeRbrhc7V5zE,14929
40
40
  prediction_market_agent_tooling/markets/base_subgraph_handler.py,sha256=7RaYO_4qAmQ6ZGM8oPK2-CkiJfKmV9MxM-rJlduaecU,1971
41
41
  prediction_market_agent_tooling/markets/blockchain_utils.py,sha256=qm21scopQ6dfewkoqQF6lWLDGg2BblsKUdC9aG93Hmc,2249
@@ -124,8 +124,8 @@ prediction_market_agent_tooling/tools/tokens/usd.py,sha256=yuW8iPPtcpP4eLH2nORMD
124
124
  prediction_market_agent_tooling/tools/transaction_cache.py,sha256=K5YKNL2_tR10Iw2TD9fuP-CTGpBbZtNdgbd0B_R7pjg,1814
125
125
  prediction_market_agent_tooling/tools/utils.py,sha256=AC2a68jwASMWuQi-w8twl8b_M52YwrEJ81abmuEaqMY,6661
126
126
  prediction_market_agent_tooling/tools/web3_utils.py,sha256=zRq-eeBGWt8uUGN9G_WfjmJ0eVvO8aWE9S0Pz_Y6AOA,12342
127
- prediction_market_agent_tooling-0.64.2.dev604.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
128
- prediction_market_agent_tooling-0.64.2.dev604.dist-info/METADATA,sha256=38NbTGoeHosQDE-geyMz6TINHrmiaueopsL_J1-ZU2g,8697
129
- prediction_market_agent_tooling-0.64.2.dev604.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
130
- prediction_market_agent_tooling-0.64.2.dev604.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
131
- prediction_market_agent_tooling-0.64.2.dev604.dist-info/RECORD,,
127
+ prediction_market_agent_tooling-0.64.3.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
128
+ prediction_market_agent_tooling-0.64.3.dist-info/METADATA,sha256=9P0UQvjvMuCYrhNQeeqiq8fFLm-QFmoqXWKfXO9i6Us,8741
129
+ prediction_market_agent_tooling-0.64.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
130
+ prediction_market_agent_tooling-0.64.3.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
131
+ prediction_market_agent_tooling-0.64.3.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any