prediction-market-agent-tooling 0.56.2.dev145__py3-none-any.whl → 0.56.2.dev147__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.
@@ -1,13 +1,16 @@
1
1
  import builtins
2
2
  import logging
3
+ import sys
3
4
  import typing as t
4
5
  import warnings
5
6
  from enum import Enum
6
7
 
8
+ from loguru import logger
7
9
  from pydantic_settings import BaseSettings, SettingsConfigDict
8
10
 
9
11
 
10
12
  class LogFormat(str, Enum):
13
+ DEFAULT = "default"
11
14
  GCP = "gcp"
12
15
 
13
16
 
@@ -24,8 +27,8 @@ class LogConfig(BaseSettings):
24
27
  env_file=".env", env_file_encoding="utf-8", extra="ignore"
25
28
  )
26
29
 
27
- LOG_FORMAT: LogFormat = LogFormat.GCP
28
- LOG_LEVEL: LogLevel = LogLevel.INFO
30
+ LOG_FORMAT: LogFormat = LogFormat.DEFAULT
31
+ LOG_LEVEL: LogLevel = LogLevel.DEBUG
29
32
 
30
33
 
31
34
  class NoNewLineStreamHandler(logging.StreamHandler): # type: ignore # StreamHandler is not typed in the standard library.
@@ -33,15 +36,18 @@ class NoNewLineStreamHandler(logging.StreamHandler): # type: ignore # StreamHan
33
36
  return super().format(record).replace("\n", " ")
34
37
 
35
38
 
39
+ GCP_LOG_LOGURU_FORMAT = (
40
+ "{level:<.1}{time:MMDD HH:mm:ss} {process} {name}:{line}] {message}"
41
+ )
36
42
  GCP_LOG_LOGGING_FORMAT, GCP_LOG_FORMAT_LOGGING_DATEFMT = (
37
- "%(levelname).1s%(asctime)s %(process)d %(name)s:%(pathname)s:%(funcName)s:%(lineno)d] %(message)s"
43
+ "%(levelname).1s%(asctime)s %(process)d %(name)s:%(lineno)d] %(message)s"
38
44
  ), "%m%d %H:%M:%S"
39
45
 
40
46
 
41
47
  def patch_logger() -> None:
42
48
  """
43
49
  Function to patch loggers according to the deployed environment.
44
- Patches Python's default logger, warnings library and also monkey-patch print function as many libraries just use it.
50
+ Patches Loguru's logger, Python's default logger, warnings library and also monkey-patch print function as many libraries just use it.
45
51
  """
46
52
  if not getattr(logger, "_patched", False):
47
53
  logger._patched = True # type: ignore[attr-defined] # Hacky way to store a flag on the logger object, to not patch it multiple times.
@@ -51,34 +57,52 @@ def patch_logger() -> None:
51
57
  config = LogConfig()
52
58
 
53
59
  if config.LOG_FORMAT == LogFormat.GCP:
60
+ format_loguru = GCP_LOG_LOGURU_FORMAT
54
61
  format_logging = GCP_LOG_LOGGING_FORMAT
55
62
  datefmt_logging = GCP_LOG_FORMAT_LOGGING_DATEFMT
56
- print_logging = print_using_logger
63
+ print_logging = print_using_loguru_info
57
64
  handlers = [NoNewLineStreamHandler()]
58
65
 
66
+ elif config.LOG_FORMAT == LogFormat.DEFAULT:
67
+ format_loguru, format_logging, datefmt_logging = None, None, None
68
+ print_logging = None
69
+ handlers = None
70
+
59
71
  else:
60
72
  raise ValueError(f"Unknown log format: {config.LOG_FORMAT}")
61
73
 
62
74
  # Change built-in logging.
63
- logging.basicConfig(
64
- level=config.LOG_LEVEL.value,
65
- format=format_logging,
66
- datefmt=datefmt_logging,
67
- handlers=handlers,
68
- )
75
+ if format_logging is not None:
76
+ logging.basicConfig(
77
+ level=config.LOG_LEVEL.value,
78
+ format=format_logging,
79
+ datefmt=datefmt_logging,
80
+ handlers=handlers,
81
+ )
82
+
83
+ # Change loguru.
84
+ if format_loguru is not None:
85
+ logger.remove()
86
+ logger.add(
87
+ sys.stdout,
88
+ format=format_loguru,
89
+ level=config.LOG_LEVEL.value,
90
+ colorize=True,
91
+ )
69
92
 
70
93
  # Change warning formatting to a simpler one (no source code in a new line).
71
94
  warnings.formatwarning = simple_warning_format
72
95
  # Use logging module for warnings.
73
96
  logging.captureWarnings(True)
74
97
 
75
- # Use logger for prints.
76
- builtins.print = print_logging # type: ignore[assignment] # Monkey patching, it's messy but it works.
98
+ # Use loguru for prints.
99
+ if print_logging is not None:
100
+ builtins.print = print_logging # type: ignore[assignment] # Monkey patching, it's messy but it works.
77
101
 
78
102
  logger.info(f"Patched logger for {config.LOG_FORMAT.value} format.")
79
103
 
80
104
 
81
- def print_using_logger(
105
+ def print_using_loguru_info(
82
106
  *values: object,
83
107
  sep: str = " ",
84
108
  end: str = "\n",
@@ -97,6 +121,4 @@ def simple_warning_format(message, category, filename, lineno, line=None): # ty
97
121
  ) # Escape new lines, because otherwise logs will be broken.
98
122
 
99
123
 
100
- logger = logging.getLogger("prediction-market-agent-tooling")
101
-
102
124
  patch_logger()
@@ -22,7 +22,6 @@ from sqlmodel import Field, Session, SQLModel, create_engine, desc, select
22
22
  from prediction_market_agent_tooling.config import APIKeys
23
23
  from prediction_market_agent_tooling.loggers import logger
24
24
  from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC
25
- from prediction_market_agent_tooling.tools.pickle_utils import InitialiseNonPickable
26
25
  from prediction_market_agent_tooling.tools.utils import utcnow
27
26
 
28
27
  FunctionT = TypeVar("FunctionT", bound=Callable[..., Any])
@@ -91,17 +90,6 @@ def db_cache(
91
90
  return decorator
92
91
 
93
92
  api_keys = api_keys if api_keys is not None else APIKeys()
94
- wrapped_engine = InitialiseNonPickable(
95
- lambda: create_engine(
96
- api_keys.sqlalchemy_db_url.get_secret_value(),
97
- # Use custom json serializer and deserializer, because otherwise, for example `datetime` serialization would fail.
98
- json_serializer=json_serializer,
99
- json_deserializer=json_deserializer,
100
- )
101
- )
102
-
103
- if api_keys.ENABLE_CACHE:
104
- SQLModel.metadata.create_all(wrapped_engine.get_value())
105
93
 
106
94
  @wraps(func)
107
95
  def wrapper(*args: Any, **kwargs: Any) -> Any:
@@ -109,7 +97,14 @@ def db_cache(
109
97
  if not api_keys.ENABLE_CACHE:
110
98
  return func(*args, **kwargs)
111
99
 
112
- engine = wrapped_engine.get_value()
100
+ engine = create_engine(
101
+ api_keys.sqlalchemy_db_url.get_secret_value(),
102
+ # Use custom json serializer and deserializer, because otherwise, for example `datetime` serialization would fail.
103
+ json_serializer=json_serializer,
104
+ json_deserializer=json_deserializer,
105
+ pool_size=1,
106
+ )
107
+ SQLModel.metadata.create_all(engine)
113
108
 
114
109
  # Convert *args and **kwargs to a single dictionary, where we have names for arguments passed as args as well.
115
110
  signature = inspect.signature(func)
@@ -25,9 +25,12 @@ class RelevantNewsCacheModel(SQLModel, table=True):
25
25
  class RelevantNewsResponseCache:
26
26
  def __init__(self, sqlalchemy_db_url: str | None = None):
27
27
  self.engine = create_engine(
28
- sqlalchemy_db_url
29
- if sqlalchemy_db_url
30
- else APIKeys().sqlalchemy_db_url.get_secret_value()
28
+ (
29
+ sqlalchemy_db_url
30
+ if sqlalchemy_db_url
31
+ else APIKeys().sqlalchemy_db_url.get_secret_value()
32
+ ),
33
+ pool_size=1,
31
34
  )
32
35
  self._initialize_db()
33
36
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.56.2.dev145
3
+ Version: 0.56.2.dev147
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -26,6 +26,7 @@ Requires-Dist: langchain (>=0.2.6,<0.3.0) ; extra == "langchain"
26
26
  Requires-Dist: langchain-community (>=0.0.19)
27
27
  Requires-Dist: langchain-openai (>=0.1.0,<0.2.0) ; extra == "langchain"
28
28
  Requires-Dist: langfuse (>=2.42.0,<3.0.0)
29
+ Requires-Dist: loguru (>=0.7.2,<0.8.0)
29
30
  Requires-Dist: loky (>=3.4.1,<4.0.0)
30
31
  Requires-Dist: numpy (>=1.26.4,<2.0.0)
31
32
  Requires-Dist: openai (>=1.0.0,<2.0.0) ; extra == "openai"
@@ -29,7 +29,7 @@ prediction_market_agent_tooling/gtypes.py,sha256=tqp03PyY0Yhievl4XELfwAn0xOoecaT
29
29
  prediction_market_agent_tooling/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
30
  prediction_market_agent_tooling/jobs/jobs_models.py,sha256=GOtsNm7URhzZM5fPY64r8m8Gz-sSsUhG1qmDoC7wGL8,2231
31
31
  prediction_market_agent_tooling/jobs/omen/omen_jobs.py,sha256=N0_jGDyXQeVXXlYg4oA_pOfqIjscHsLQbr0pBwFGoRo,5178
32
- prediction_market_agent_tooling/loggers.py,sha256=i_CMm31EPvM734YDMSmgn0MI4NYS2kHp_FDaL1h-Z5M,3089
32
+ prediction_market_agent_tooling/loggers.py,sha256=Am6HHXRNO545BO3l7Ue9Wb2TkYE1OK8KKhGbI3XypVU,3751
33
33
  prediction_market_agent_tooling/markets/agent_market.py,sha256=W2ME57-CSAhrt8qm8-b5r7yLq-Sk7R_BZMaApvjhrUE,12901
34
34
  prediction_market_agent_tooling/markets/base_subgraph_handler.py,sha256=IxDTwX4tej9j5olNkXcLIE0RCF1Nh2icZQUT2ERMmZo,1937
35
35
  prediction_market_agent_tooling/markets/categorize.py,sha256=jsoHWvZk9pU6n17oWSCcCxNNYVwlb_NXsZxKRI7vmsk,1301
@@ -71,7 +71,7 @@ prediction_market_agent_tooling/tools/betting_strategies/market_moving.py,sha256
71
71
  prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py,sha256=-FUSuQQgjcWSSnoFxnlAyTeilY6raJABJVM2QKkFqAY,438
72
72
  prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py,sha256=THMXwFlskvzbjnX_OiYtDSzI8XVFyULWfP2525_9UGc,429
73
73
  prediction_market_agent_tooling/tools/betting_strategies/utils.py,sha256=kpIb-ci67Vc1Yqqaa-_S4OUkbhWSIYog4_Iwp69HU_k,97
74
- prediction_market_agent_tooling/tools/caches/db_cache.py,sha256=x3v-ZnMpnSzmdwnzubh9oQ7ebExONXjWSFqY48CYQwc,12847
74
+ prediction_market_agent_tooling/tools/caches/db_cache.py,sha256=88mRRyPRSOECvl70hbUCUVv7ii6dwFGY8CKSbxIcLIU,12643
75
75
  prediction_market_agent_tooling/tools/caches/inmemory_cache.py,sha256=tGHHd9HCiE_hCCtPtloHZQdDfBuiow9YsqJNYi2Tx_0,499
76
76
  prediction_market_agent_tooling/tools/contract.py,sha256=s3yo8IbXTcvAJcPfLM0_NbgaEsWwLsPmyVnOgyjq_xI,20919
77
77
  prediction_market_agent_tooling/tools/costs.py,sha256=EaAJ7v9laD4VEV3d8B44M4u3_oEO_H16jRVCdoZ93Uw,954
@@ -89,10 +89,9 @@ prediction_market_agent_tooling/tools/langfuse_.py,sha256=jI_4ROxqo41CCnWGS1vN_A
89
89
  prediction_market_agent_tooling/tools/langfuse_client_utils.py,sha256=B0PhAQyviFnVbtOCYMxYmcCn66cu9nbqAOIAZcdgiRI,5771
90
90
  prediction_market_agent_tooling/tools/omen/reality_accuracy.py,sha256=M1SF7iSW1gVlQSTskdVFTn09uPLST23YeipVIWj54io,2236
91
91
  prediction_market_agent_tooling/tools/parallelism.py,sha256=6Gou0hbjtMZrYvxjTDFUDZuxmE2nqZVbb6hkg1hF82A,1022
92
- prediction_market_agent_tooling/tools/pickle_utils.py,sha256=PUNRJGdURUnLlzbZoSCiOrikRbEC596hi--Z3q8Wt84,1144
93
92
  prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py,sha256=95l84aztFaxcRLLcRQ46yKJbIlOEuDAbIGLouyliDzA,1316
94
93
  prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py,sha256=CddJem7tk15NAudJDwmuL8znTycbR-YI8kTNtd3LzG8,5474
95
- prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py,sha256=2yxtBIDyMT_6CsTpZyuIv_2dy2B9WgEOaTT1fSloBu0,3223
94
+ prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py,sha256=Dcde74ZwoZuohhJ8gIO5GQkdAz1YrAKlvrM8CNgRqWw,3289
96
95
  prediction_market_agent_tooling/tools/safe.py,sha256=9vxGGLvSPnfy-sxUFDpBTe8omqpGXP7MzvGPp6bRxrU,5197
97
96
  prediction_market_agent_tooling/tools/singleton.py,sha256=CiIELUiI-OeS7U7eeHEt0rnVhtQGzwoUdAgn_7u_GBM,729
98
97
  prediction_market_agent_tooling/tools/streamlit_user_login.py,sha256=NXEqfjT9Lc9QtliwSGRASIz1opjQ7Btme43H4qJbzgE,3010
@@ -100,8 +99,8 @@ prediction_market_agent_tooling/tools/tavily/tavily_models.py,sha256=5ldQs1pZe6u
100
99
  prediction_market_agent_tooling/tools/tavily/tavily_search.py,sha256=Kw2mXNkMTYTEe1MBSTqhQmLoeXtgb6CkmHlcAJvhtqE,3809
101
100
  prediction_market_agent_tooling/tools/utils.py,sha256=1VvunbTmzGzpIlRukFhArreFNxJPbsg4lLtQNk0r2bY,7185
102
101
  prediction_market_agent_tooling/tools/web3_utils.py,sha256=44W8siSLNQxeib98bbwAe7V5C609NHNlUuxwuWIRDiY,11838
103
- prediction_market_agent_tooling-0.56.2.dev145.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
104
- prediction_market_agent_tooling-0.56.2.dev145.dist-info/METADATA,sha256=QluPksTg71v0W8QNWlGRF-x_hkfT9waaCli9BBvGeIo,8074
105
- prediction_market_agent_tooling-0.56.2.dev145.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
106
- prediction_market_agent_tooling-0.56.2.dev145.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
107
- prediction_market_agent_tooling-0.56.2.dev145.dist-info/RECORD,,
102
+ prediction_market_agent_tooling-0.56.2.dev147.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
103
+ prediction_market_agent_tooling-0.56.2.dev147.dist-info/METADATA,sha256=e63eTQImJF9KPbpiPIfEUOm8Buj5cf42OuxFX6vD2E4,8113
104
+ prediction_market_agent_tooling-0.56.2.dev147.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
105
+ prediction_market_agent_tooling-0.56.2.dev147.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
106
+ prediction_market_agent_tooling-0.56.2.dev147.dist-info/RECORD,,
@@ -1,31 +0,0 @@
1
- import typing as t
2
-
3
- InitialisedValue = t.TypeVar("InitialisedValue")
4
-
5
-
6
- class InitialiseNonPickable(t.Generic[InitialisedValue]):
7
- """
8
- Use this class to wrap values that you want to be shared within a thread,
9
- but they are re-initialised for a new processes.
10
-
11
- Initialiser for the value still needs to be pickable.
12
- """
13
-
14
- def __init__(self, initialiser: t.Callable[[], InitialisedValue]) -> None:
15
- self.value: InitialisedValue | None = None
16
- self.initialiser = initialiser
17
-
18
- def __getstate__(self) -> dict[str, t.Any]:
19
- # During pickling, always return `value` as just None, which is pickable and this class will re-initialise it in `get_value` when called.
20
- return {"value": None, "initialiser": self.initialiser}
21
-
22
- def __setstate__(self, d: dict[str, t.Any]) -> None:
23
- self.value = d["value"]
24
- self.initialiser = d["initialiser"]
25
-
26
- def get_value(self) -> InitialisedValue:
27
- """Use this function to get the wrapped value, which will be initialised if necessary."""
28
- if self.value is None:
29
- self.value = self.initialiser()
30
-
31
- return self.value