Fix crash on unrecognized channel-trigger-dict fields

pull/357/head
nyanpasu64 2019-03-14 02:41:27 -07:00
rodzic 0dc8f8bbca
commit c0b68bfd33
2 zmienionych plików z 19 dodań i 5 usunięć

Wyświetl plik

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Optional, Union, Dict, Any
import attr
from ruamel.yaml.comments import CommentedMap
from corrscope.config import DumpableAttrs, Alias, CorrError
from corrscope.config import DumpableAttrs, Alias, CorrError, evolve_compat
from corrscope.triggers import MainTriggerConfig
from corrscope.util import coalesce
from corrscope.wave import Wave, Flatten
@ -88,12 +88,15 @@ class Channel:
# Create a Trigger object.
if isinstance(cfg.trigger, MainTriggerConfig):
tcfg = cfg.trigger
elif isinstance(
cfg.trigger, (CommentedMap, dict)
): # CommentedMap may/not be subclass of dict.
tcfg = attr.evolve(corr_cfg.trigger, **cfg.trigger)
tcfg = evolve_compat(corr_cfg.trigger, **cfg.trigger)
elif cfg.trigger is None:
tcfg = corr_cfg.trigger
else:
raise CorrError(
f"invalid per-channel trigger {cfg.trigger}, type={type(cfg.trigger)}, "

Wyświetl plik

@ -23,6 +23,7 @@ __all__ = [
"yaml",
"copy_config",
"DumpableAttrs",
"evolve_compat",
"KeywordAttrs",
"with_units",
"get_units",
@ -190,10 +191,14 @@ class DumpableAttrs:
# SafeConstructor.construct_yaml_object() uses __setstate__ to load objects.
def __setstate__(self, state: Dict[str, Any]) -> None:
self.__dict__ = self.new_from_state(state).__dict__
# If called via instance, cls == type(self).
@classmethod
def new_from_state(cls: Type[T], state: Dict[str, Any]) -> T:
""" Redirect `Alias(key)=value` to `key=value`.
Then call the dataclass constructor (to validate parameters). """
cls = type(self)
cls_name = cls.__name__
fields = attr.fields_dict(cls)
@ -225,8 +230,14 @@ class DumpableAttrs:
new_state[key] = value
del state
obj = cls(**new_state)
self.__dict__ = obj.__dict__
return cls(**new_state)
def evolve_compat(obj: DumpableAttrs, **changes):
"""Evolve an object, based on user-specified dict,
while ignoring unrecognized keywords."""
# In dictionaries, later values will always override earlier ones
return obj.new_from_state({**obj.__dict__, **changes})
class KeywordAttrs(DumpableAttrs):