circular import

This commit is contained in:
əlemi 2022-04-19 02:14:46 +02:00
parent 7b7c46e184
commit 3b9880ad6b
No known key found for this signature in database
GPG key ID: BBCBFE5D7244634E
3 changed files with 71 additions and 70 deletions

69
src/treepuncher/addon.py Normal file
View file

@ -0,0 +1,69 @@
import json
from typing import Any, Dict, List, Set, get_type_hints, get_args, get_origin
from dataclasses import dataclass, MISSING, fields
def parse_with_hint(val:str, hint:Any) -> Any:
if hint is bool:
if val.lower() in ['1', 'true', 't', 'on', 'enabled']:
return True
return False
if hint is list or get_origin(hint) is list:
if get_args(hint):
return [ parse_with_hint(x, get_args(hint)[0]) for x in val.split() ]
return val.split()
if hint is set or get_origin(hint) is set:
if get_args(hint):
return set( parse_with_hint(x, get_args(hint)[0]) for x in val.split() )
return set(val.split())
if hint is dict or get_origin(hint) is dict:
return json.loads(val)
return (get_origin(hint) or hint)(val) # try to instantiate directly
class ConfigObject:
def __getitem__(self, key: str) -> Any:
return getattr(self, key)
class Addon:
name: str
config: ConfigObject
_client: 'Treepuncher'
@dataclass(frozen=True)
class Options(ConfigObject):
pass
@property
def client(self) -> 'Treepuncher':
return self._client
def __init__(self, client: 'Treepuncher', *args, **kwargs):
self._client = client
self.name = type(self).__name__
cfg = self._client.config
opts: Dict[str, Any] = {}
cfg_clazz = get_type_hints(type(self))['config']
if cfg_clazz is not ConfigObject:
for field in fields(cfg_clazz):
default = field.default if field.default is not MISSING \
else field.default_factory() if field.default_factory is not MISSING \
else MISSING
if cfg.has_option(self.name, field.name):
opts[field.name] = parse_with_hint(self._client.config[self.name].get(field.name), field.type)
elif default is MISSING:
repr_type = field.type.__name__ if isinstance(field.type, type) else str(field.type) # TODO fix for 3.8 I think?
raise ValueError(
f"Missing required value '{field.name}' of type '{repr_type}' in section '{self.name}'"
)
else: # not really necessary since it's a dataclass but whatever
opts[field.name] = default
self.config = self.Options(**opts)
self.register()
def register(self):
pass
async def initialize(self):
pass
async def cleanup(self):
pass

View file

@ -1,6 +1,6 @@
from typing import Callable, List
from treepuncher import Addon
from .addon import Addon
class Notifier(Addon): # TODO this should be an Addon too!
_report_functions : List[Callable]

View file

@ -17,77 +17,9 @@ from aiocraft.mc.auth import AuthInterface, AuthException, MojangAuthenticator,
from .storage import Storage, SystemState
from .notifier import Notifier
from .addon import Addon
from .game import GameState, GameChat, GameInventory, GameTablist, GameWorld
REMOVE_COLOR_FORMATS = re.compile(r"§[0-9a-z]")
def parse_with_hint(val:str, hint:Any) -> Any:
if hint is bool:
if val.lower() in ['1', 'true', 't', 'on', 'enabled']:
return True
return False
if hint is list or get_origin(hint) is list:
if get_args(hint):
return [ parse_with_hint(x, get_args(hint)[0]) for x in val.split() ]
return val.split()
if hint is set or get_origin(hint) is set:
if get_args(hint):
return set( parse_with_hint(x, get_args(hint)[0]) for x in val.split() )
return set(val.split())
if hint is dict or get_origin(hint) is dict:
return json.loads(val)
return (get_origin(hint) or hint)(val) # try to instantiate directly
class ConfigObject:
def __getitem__(self, key: str) -> Any:
return getattr(self, key)
class Addon:
name: str
config: ConfigObject
_client: 'Treepuncher'
@dataclass(frozen=True)
class Options(ConfigObject):
pass
@property
def client(self) -> 'Treepuncher':
return self._client
def __init__(self, client: 'Treepuncher', *args, **kwargs):
self._client = client
self.name = type(self).__name__
cfg = self._client.config
opts: Dict[str, Any] = {}
cfg_clazz = get_type_hints(type(self))['config']
if cfg_clazz is not ConfigObject:
for field in fields(cfg_clazz):
default = field.default if field.default is not MISSING \
else field.default_factory() if field.default_factory is not MISSING \
else MISSING
if cfg.has_option(self.name, field.name):
opts[field.name] = parse_with_hint(self._client.config[self.name].get(field.name), field.type)
elif default is MISSING:
repr_type = field.type.__name__ if isinstance(field.type, type) else str(field.type) # TODO fix for 3.8 I think?
raise ValueError(
f"Missing required value '{field.name}' of type '{repr_type}' in section '{self.name}'"
)
else: # not really necessary since it's a dataclass but whatever
opts[field.name] = default
self.config = self.Options(**opts)
self.register()
def register(self):
pass
async def initialize(self):
pass
async def cleanup(self):
pass
class MissingParameterError(Exception):
pass