Skip to content

Instantly share code, notes, and snippets.

@gustavz
Last active December 8, 2022 11:43
Show Gist options
  • Save gustavz/f1c615e95f0874c80a66d2f367b2007e to your computer and use it in GitHub Desktop.
Save gustavz/f1c615e95f0874c80a66d2f367b2007e to your computer and use it in GitHub Desktop.

Revisions

  1. Gustav von Zitzewitz renamed this gist Dec 8, 2022. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. Gustav von Zitzewitz revised this gist Dec 8, 2022. 1 changed file with 0 additions and 6 deletions.
    6 changes: 0 additions & 6 deletions gistfile1.py
    Original file line number Diff line number Diff line change
    @@ -71,12 +71,6 @@ def __setattr__(self, name, value):
    @property
    def _keys(self):
    return {k.name:k for k in self._converter.keys}

    def _validate(self, data):
    keys = set(data.keys())
    if not keys.issubset(self._fields):
    wrong_keys = keys - self._fields
    raise ValueError(f'invalid parameters: {wrong_keys}')

    @classmethod
    def from_dict(cls, data):
  3. Gustav von Zitzewitz revised this gist Dec 8, 2022. 1 changed file with 11 additions and 4 deletions.
    15 changes: 11 additions & 4 deletions gistfile1.py
    Original file line number Diff line number Diff line change
    @@ -56,10 +56,11 @@ def __init__(self, **kwargs):

    def _set_init_kwargs(self, kwargs):
    for key, value in kwargs.items():
    # We only log attributes defined in _converter
    # and we don't log default values
    if key in self._keys and value != self._keys[key].default:
    reason = self._logger.generate_reason('initial user input')
    if key in self._keys:
    reason = 'initial user input'
    if value == self._keys[key].default:
    reason = 'default value'
    reason = self._logger.generate_reason(reason)
    value = value, reason
    setattr(self, key, value)

    @@ -70,6 +71,12 @@ def __setattr__(self, name, value):
    @property
    def _keys(self):
    return {k.name:k for k in self._converter.keys}

    def _validate(self, data):
    keys = set(data.keys())
    if not keys.issubset(self._fields):
    wrong_keys = keys - self._fields
    raise ValueError(f'invalid parameters: {wrong_keys}')

    @classmethod
    def from_dict(cls, data):
  4. Gustav von Zitzewitz renamed this gist Dec 8, 2022. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  5. Gustav von Zitzewitz created this gist Dec 8, 2022.
    90 changes: 90 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    import trafaret as t

    class DecisionLog:
    def __init__(self, reason_key=''):
    self.init()
    self._reason_key = reason_key
    self._len_reason_key = len(reason_key)

    def init(self):
    self.logs = []

    def log(self, text):
    self.logs.append(text)

    def _read_reason_from_value(self, value):
    reason = None
    if(
    isinstance(value, tuple)
    and len(value) == 2
    and isinstance(value[1], str)
    and len(value[1]) > self._len_reason_key
    and value[1][:self._len_reason_key] == self._reason_key
    ):
    reason = value[1][self._len_reason_key:]
    value = value[0]
    return value, reason

    def _generate_setattr_text(self, name, value, reason):
    text = f'Setting {name} to {value}'
    if reason: text += f' because {reason}'
    return text

    def log_setattr_with_reason(self, name, value):
    value, reason = self._read_reason_from_value(value)
    text = self._generate_setattr_text(name, value, reason)
    self.log(text)
    return value

    def generate_reason(self, value):
    return self._reason_key + value

    def to_string(self):
    for log in self.logs:
    print(log)
    return '\n'.join(self.logs)


    class BaseDataWithDecisionLog:
    _converter = t.Dict()
    _logger = DecisionLog(reason_key='r:')

    def __init__(self, **kwargs):
    self._logger.init()
    kwargs = self._converter.check_and_return(kwargs)
    self._set_init_kwargs(kwargs)

    def _set_init_kwargs(self, kwargs):
    for key, value in kwargs.items():
    # We only log attributes defined in _converter
    # and we don't log default values
    if key in self._keys and value != self._keys[key].default:
    reason = self._logger.generate_reason('initial user input')
    value = value, reason
    setattr(self, key, value)

    def __setattr__(self, name, value):
    value = self._logger.log_setattr_with_reason(name, value)
    super().__setattr__(name, value)

    @property
    def _keys(self):
    return {k.name:k for k in self._converter.keys}

    @classmethod
    def from_dict(cls, data):
    return cls(**data)

    def to_dict(self):
    return {k:getattr(self, k) for k in self._keys}

    def get_log(self):
    return self._logger.to_string()

    class MyDataClass(BaseDataWithDecisionLog):
    _converter = t.Dict({
    t.Key('var1', optional=True, default=None): t.Or(t.Int, t.Null),
    t.Key('var2', optional=True, default=None): t.Or(t.Int, t.Null),
    t.Key('var3', optional=True, default=None): t.Or(t.Int, t.Null),
    t.Key('var4', optional=True, default=None): t.Or(t.Int, t.Null),
    })