from turtle import Turtle from controls.device import ( SynchronyDevice, TraitDescriptor, ActionDescriptor, NoSuchTrait, NoSuchAction, ) from typing import Collection, Optional, Any import inspect class TurtleDevice(SynchronyDevice): def __init__(self) -> None: super().__init__() self.open() def open(self) -> None: self.turtle = Turtle() def close(self) -> None: del self.turtle self.close() def execute(self, action_name: str, *args, **kwargs) -> None: actions = self.action_descriptors for action in actions: if action.name == action_name: # NOTE: судя по заданию, должен быть такой assert, # но почему-то у меня inspect плохо спарсил типы именно для Turtle # везде empty_time, хотя судя по доке в модуле typos проставлены # при чем тестировал на pd.DataFrame, там все прекрасно парсит # for argument in kwargs: # action_tmp_argument_type = action.arguments[argument] # given_method_tmp_argument = type(kwargs[argument]) # assert ( # action_tmp_argument_type == given_method_tmp_argument # ), f"Переданный аргумент должен быть типа {action_tmp_argument_type}, вы передали {given_method_tmp_argument}" getattr(self.turtle, action_name)(*args, **kwargs) return raise NoSuchAction def read(self, trait_name: str) -> Any: return Turtle().__getattribute__(trait_name) def write(self, trait_name: str, value: Any) -> bool: traits = self.trait_descriptors for trait in traits: if trait.name == trait_name: attribute_type = type(self.turtle.__getattribute__(trait_name)) assert ( type(value) == attribute_type ), f"Wrong value type. Type should be {attribute_type}, but you pass {type(value)}" self.turtle.__setattr__(trait_name, value) return True raise NoSuchTrait def invalidate(self, trait_name: str) -> None: self.write(trait_name=trait_name, value=Turtle().__getattribute__(trait_name)) return def __getitem__(self, trait_name: str) -> Optional[Any]: traits = self.trait_descriptors for trait in traits: if trait.name == trait_name: return self.turtle.__getattribute__(trait_name) raise NoSuchTrait @property def trait_descriptors(self) -> Collection[TraitDescriptor]: return [ TraitDescriptor(name=attr, info=getattr(self.turtle, attr).__doc__) for attr in dir(self.turtle) if attr[0] != "_" and attr[-1] != "_" and not callable(getattr(self.turtle, attr)) ] @property def action_descriptors(self) -> Collection[ActionDescriptor]: methods = [ attr for attr in dir(self.turtle) if attr[0] != "_" and attr[-1] != "_" and callable(getattr(self.turtle, attr)) ] result = [] for method_name in methods: method = getattr(self.turtle, method_name) parameters = inspect.signature(method).parameters arg_types = {} for arg_name, arg in parameters.items(): arg_types[arg_name] = parameters[arg_name].annotation result.append( ActionDescriptor( name=method_name, info=method.__doc__, arguments=arg_types ) ) return result