Include recursive JSON type checks
This commit is contained in:
parent
a02f088c0b
commit
6dae1fb0f9
|
@ -1,5 +1,5 @@
|
|||
[bumpversion]
|
||||
current_version = 0.6.0.107
|
||||
current_version = 0.6.0.108
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\.(?P<build>\d+)
|
||||
serialize = {major}.{minor}.{patch}.{build}
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@ from src.rule import get_rule
|
|||
from src.util import DictDeserializable, explain_abstract, get_client
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from typing import Any, Mapping, Optional
|
||||
from typing import Any, Optional
|
||||
|
||||
from pymanifold.types import JSONDict
|
||||
|
||||
from src import Rule
|
||||
from src.consts import OutcomeType
|
||||
|
@ -98,7 +100,7 @@ class ManifoldRequest(DictDeserializable):
|
|||
if self.answers is None or len(self.answers) < 2 or any(len(x) < 1 for x in self.answers):
|
||||
raise ValueError("Invalid answers list")
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
def to_dict(self) -> JSONDict:
|
||||
state = deepcopy(self.__dict__)
|
||||
state['description'].pop('processed', None)
|
||||
return {
|
||||
|
@ -135,7 +137,7 @@ class CreationRequest:
|
|||
self.manifold.description["processed"] = True
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, obj: Mapping[str, Any]) -> 'CreationRequest':
|
||||
def from_dict(cls, obj: JSONDict) -> 'CreationRequest':
|
||||
"""Take a dictionary and return an instance of the associated class."""
|
||||
obj = dict(obj)
|
||||
manifold = ManifoldRequest.from_dict(obj.pop('manifold'))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
name = ManifoldMarketManager
|
||||
author = Olivia Appleton
|
||||
author_email = Liv@OliviaAppleton.com
|
||||
version = 0.6.0.107
|
||||
version = 0.6.0.108
|
||||
description = Tools and market management for manifold.markets
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown
|
||||
|
|
BIN
src.png
BIN
src.png
Binary file not shown.
Before Width: | Height: | Size: 674 KiB After Width: | Height: | Size: 630 KiB |
|
@ -1 +1 @@
|
|||
Subproject commit c59a0d3f1375b54e21c56cc99e55688d8401c89f
|
||||
Subproject commit 3159de40a59b04dab78fdfefa14a59e0615f3083
|
|
@ -178,7 +178,7 @@ register_converter("Rule", loads)
|
|||
register_adapter(market.Market, dumps)
|
||||
register_converter("Market", loads)
|
||||
|
||||
VERSION = "0.6.0.107"
|
||||
VERSION = "0.6.0.108"
|
||||
__version_info__ = tuple(int(x) for x in VERSION.split('.'))
|
||||
__all__ = [
|
||||
"__version_info__", "VERSION", "DoResolveRule", "ResolutionValueRule", "Rule", "Market", "get_client", "rule",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from pickle import loads, dumps
|
||||
from pickle import dumps, loads
|
||||
from typing import cast
|
||||
|
||||
from cryptography.fernet import Fernet
|
||||
|
|
|
@ -14,9 +14,12 @@ from ..util import round_sig_figs
|
|||
from . import ResolutionValueRule, get_rule
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from typing import Any, ClassVar, Mapping, Sequence
|
||||
from typing import Any, ClassVar, Sequence
|
||||
|
||||
from pymanifold.types import JSONDict
|
||||
|
||||
from ..market import Market
|
||||
from ..util import ModJSONDict
|
||||
|
||||
SENTINEL_STUB = "A programatic explanation was not provided"
|
||||
|
||||
|
@ -54,10 +57,11 @@ class UnaryRule(AbstractRule[T]):
|
|||
self.child.explain_specific(market, indent + 1, sig_figs)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, env: Mapping[str, Any]) -> 'UnaryRule[T]':
|
||||
def from_dict(cls, env: ModJSONDict) -> 'UnaryRule[T]':
|
||||
"""Take a dictionary and return an instance of the associated class."""
|
||||
env_copy = dict(env)
|
||||
type_, kwargs = env["child"]
|
||||
child: tuple[str, ModJSONDict] = env["child"] # type: ignore[assignment]
|
||||
type_, kwargs = child
|
||||
env_copy["child"] = get_rule(type_).from_dict(kwargs)
|
||||
return super().from_dict(env_copy)
|
||||
|
||||
|
@ -70,11 +74,12 @@ class BinaryRule(AbstractRule[T]):
|
|||
rule2: Rule[T]
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, env: Mapping[str, Any]) -> 'BinaryRule[T]':
|
||||
def from_dict(cls, env: ModJSONDict) -> 'BinaryRule[T]':
|
||||
"""Take a dictionary and return an instance of the associated class."""
|
||||
env_copy = dict(env)
|
||||
for name in ('rule1', 'rule2'):
|
||||
type_, kwargs = env[name]
|
||||
child: tuple[str, ModJSONDict] = env[name] # type: ignore[assignment]
|
||||
type_, kwargs = child
|
||||
env_copy[name] = get_rule(type_).from_dict(kwargs)
|
||||
return super().from_dict(env_copy)
|
||||
|
||||
|
@ -98,13 +103,14 @@ class VariadicRule(AbstractRule[T]):
|
|||
rules: list[Rule[T]] = Factory(list)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, env: Mapping[str, Any]) -> 'VariadicRule[T]':
|
||||
def from_dict(cls, env: ModJSONDict) -> 'VariadicRule[T]':
|
||||
"""Take a dictionary and return an instance of the associated class."""
|
||||
env_copy = dict(env)
|
||||
arr = env.get("rules", [])
|
||||
env_copy["rules"] = [None] * len(arr)
|
||||
arr: Sequence[tuple[str, ModJSONDict]] = env.get("rules", []) # type: ignore[assignment]
|
||||
rules: list[None | Rule[Any]] = [None] * len(arr)
|
||||
for idx, (type_, kwargs) in enumerate(arr):
|
||||
env_copy["rules"][idx] = get_rule(type_).from_dict(kwargs)
|
||||
rules[idx] = get_rule(type_).from_dict(kwargs)
|
||||
env_copy["rules"] = rules
|
||||
return super().from_dict(env_copy)
|
||||
|
||||
def _explain_abstract(self, indent: int = 0, **kwargs: Any) -> str:
|
||||
|
@ -129,7 +135,7 @@ class ResolveRandomSeed(ResolutionValueRule):
|
|||
method: str = 'random'
|
||||
rounds: int = 1
|
||||
args: Sequence[Any] = ()
|
||||
kwargs: dict[str, Any] = Factory(dict)
|
||||
kwargs: JSONDict = Factory(dict)
|
||||
|
||||
def _value(self, market: Market) -> Any:
|
||||
source = Random(self.seed)
|
||||
|
|
|
@ -17,6 +17,8 @@ from .abstract import BinaryRule, ResolveRandomSeed, UnaryRule, VariadicRule
|
|||
if TYPE_CHECKING: # pragma: no cover
|
||||
from typing import Any, ClassVar, DefaultDict, Literal, MutableSequence
|
||||
|
||||
from pymanifold.types import JSONDict, JSONType
|
||||
|
||||
from ..consts import FreeResponseResolution, MultipleChoiceResolution
|
||||
from ..market import Market
|
||||
|
||||
|
@ -252,14 +254,14 @@ class ResolveMultipleValues(ResolutionValueRule):
|
|||
return ret
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, env: Mapping[str, Any]) -> 'ResolveMultipleValues':
|
||||
def from_dict(cls, env: dict[str, JSONType | Rule]) -> 'ResolveMultipleValues':
|
||||
"""Take a dictionary and return an instance of the associated class."""
|
||||
env_copy: dict[str, Any] = dict(env)
|
||||
shares: MutableSequence[tuple[ResolutionValueRule | tuple[str, dict[str, Any]], float]] = env.get('shares', [])
|
||||
env_copy: JSONDict = dict(env)
|
||||
shares: MutableSequence[tuple[ResolutionValueRule | tuple[str, JSONDict], float]] = env.get('shares', [])
|
||||
new_shares = []
|
||||
for rule, weight in shares:
|
||||
try:
|
||||
type_, kwargs = cast(Tuple[str, Dict[str, Any]], rule)
|
||||
type_, kwargs = cast(Tuple[str, JSONDict], rule)
|
||||
new_rule = get_rule(type_).from_dict(kwargs)
|
||||
new_shares.append((new_rule, weight))
|
||||
except Exception:
|
||||
|
|
|
@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, cast
|
|||
|
||||
from attrs import define
|
||||
from pymanifold.lib import ManifoldClient
|
||||
from pymanifold.types import JSONDict
|
||||
|
||||
from ... import Rule
|
||||
|
||||
|
@ -31,7 +32,7 @@ class ManifoldUserRule(Rule[float]):
|
|||
|
||||
def _value(self, market: Market) -> float:
|
||||
user = ManifoldClient()._get_user_raw(self.user)
|
||||
return cast(float, user[self.attr][self.field])
|
||||
return cast(float, cast(JSONDict, user[self.attr])[self.field])
|
||||
|
||||
def _explain_abstract(self, indent: int = 0, **kwargs: Any) -> str:
|
||||
return f"{' ' * indent}- Resolves to the current {self.field} {self.attr_desc} user {self.user}.\n"
|
||||
|
|
|
@ -21,10 +21,12 @@ from pymanifold.utils.math import number_to_prob_cpmm1 # noqa: F401
|
|||
from .consts import EnvironmentVariable, Outcome
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from typing import Any, Callable, Collection, Iterable, Mapping, MutableSequence, Type, TypeVar
|
||||
from typing import Any, Callable, Collection, Iterable, Mapping, MutableSequence, Sequence, Type, TypeVar, Union
|
||||
|
||||
from . import Market, Rule
|
||||
|
||||
ModJSONType = Union[int, float, bool, str, None, Rule[Any], Sequence['ModJSONType'], Mapping[str, 'ModJSONType']]
|
||||
ModJSONDict = Mapping[str, ModJSONType]
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
|
@ -32,7 +34,7 @@ class DictDeserializable:
|
|||
"""A port of PyManifold's DictDeserializable that does not check against the signature."""
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type[T], env: dict[str, Any]) -> T:
|
||||
def from_dict(cls: Type[T], env: ModJSONDict) -> T:
|
||||
"""Take a dictionary and return an instance of the associated class."""
|
||||
return cls(**env)
|
||||
|
||||
|
|
Loading…
Reference in New Issue