Compare commits

..

No commits in common. "e6a2f6eac73f4b95c7c368476f3122ba97a7c97a" and "5c5d61ec03660b376d507bc504272a1be5349b49" have entirely different histories.

9 changed files with 16 additions and 99 deletions

View File

@ -1,16 +1,12 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional, Collection, Any from typing import Optional, Collection, Any
from abc import ABC, abstractmethod, abstractproperty from abc import abstractmethod
from enum import Enum
class DeviceLifecycleState:
pass # TODO(Homework #3)
class DeviceLifecycleState(Enum): class DevaceError(Exception):
INIT = 0
OPEN = 1
CLOSE = 2
class DeviceError(Exception):
pass pass
@ -37,7 +33,8 @@ class ActionDescriptor:
info: Optional[str] = None info: Optional[str] = None
class Device(ABC): class Device:
# TODO(Homework #3)
_state = DeviceLifecycleState.INIT _state = DeviceLifecycleState.INIT
@property @property
@ -47,11 +44,9 @@ class Device(ABC):
def close(self): def close(self):
self._state = DeviceLifecycleState.CLOSE self._state = DeviceLifecycleState.CLOSE
@abstractproperty
def trait_descriptors(self) -> Collection[TraitDescriptor]: def trait_descriptors(self) -> Collection[TraitDescriptor]:
pass pass
@abstractproperty
def action_descriptors(self) -> Collection[ActionDescriptor]: def action_descriptors(self) -> Collection[ActionDescriptor]:
pass pass
@ -84,4 +79,4 @@ class SynchronyDevice(Device):
@abstractmethod @abstractmethod
def invalidate(self, trait_name: str): def invalidate(self, trait_name: str):
"""Invalidate logical state of trait `trait_name`""" """Invalidate logical state of trait `trait_name`"""
pass pass

View File

@ -0,0 +1,8 @@
from turtle import Turtle
from controls.device import SynchronyDevice
class TurtleDevice(SynchronyDevice):
pass # TODO(Homework #3)

1
turtle/.gitignore vendored
View File

@ -1 +0,0 @@
test.ipynb

View File

@ -1,85 +0,0 @@
from turtle import Turtle
from typing import Optional, Collection, Any
from controls.device import SynchronyDevice
from controls.device import TraitDescriptor
from controls.device import ActionDescriptor
from controls.device import DeviceError
import inspect
class TurtleDevice(SynchronyDevice):
def open(self):
self.turtle = Turtle()
self.descriptors = dict(traits=dict(), actions=dict())
super().open()
def close(self):
self.turtle.clear()
super().close()
def trait_descriptors(self) -> Collection[TraitDescriptor]:
return self.get_descriptors()["traits"]
def action_descriptors(self) -> Collection[ActionDescriptor]:
return self.get_descriptors()["actions"]
def __getitem__(self, trait_name: str) -> Optional[Any]:
"""Return logical state of trait `trait_name`."""
return self.descriptors[trait_name]
def read_descriptors(self, arg):
self.descriptors = self.get_descriptors()
return self.descriptors
def read(self, trait_name: str) -> Any:
"""Read physical state of trait `trait_name` from device."""
self.read_descriptors()
return self.descriptors[trait_name]
def write(self, trait_name: str, value: Any) -> bool:
"""Turtle traits are not writable"""
# trait_desc = self.trait_descriptors.get(trait_name)
# if trait_desc.writable:
# return getattr(self.turtle, trait_name)(value)
super().write()
def execute(self, action_name: str, *args, **kwargs):
"""Execute action `action_name`, using `args` and `kwargs` as action argument."""
action = self.get_descriptors()["actions"].get(action_name)
if action:
return getattr(self.turtle, action_name)(*args, **kwargs)
super().execute()
def invalidate(self, trait_name: str):
"""Invalidate logical state of trait `trait_name`"""
if self.trait_descriptors.get(trait_name):
self.trait_descriptors[trait_name] = None
raise DeviceError()
def get_descriptors(self):
descriptors = dict(actions=dict(), traits=dict())
for k, v in self.turtle.__dict__.items():
if not k.startswith("_"):
descriptors["traits"][k] = TraitDescriptor(k,
inspect.getdoc(v),
readable=True,
writable=False)
for m_name, member in inspect.getmembers(Turtle):
if m_name.startswith("_"): continue
if m_name.lower() != m_name: continue
doc = inspect.getdoc(member)
if doc is None: continue
if not inspect.isfunction(member):
descriptors["traits"][m_name] = TraitDescriptor(m_name,
doc,
readable=True,
writable=False)
else:
sig = inspect.signature(member)
params_dict = dict(sig.parameters)
descriptors["actions"][m_name] = ActionDescriptor(m_name,
arguments=params_dict,
info=doc)
return descriptors