Skip to content

Commit

Permalink
feat: teach Part to skip exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
kalekundert committed Oct 3, 2022
1 parent 4a99f25 commit 4eca860
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 3 deletions.
20 changes: 17 additions & 3 deletions byoc/getters.py
Expand Up @@ -145,7 +145,7 @@ def bind(self, obj, param):

class Part(Getter):

def __init__(self, whole, index=noop, **kwargs):
def __init__(self, whole, index=noop, skip=(), **kwargs):
super().__init__(**kwargs)

# Strictly speaking, the user should provide the same "whole" getter
Expand Down Expand Up @@ -176,6 +176,7 @@ def __init__(self, whole, index=noop, **kwargs):

self.whole = whole
self.index = index
self.skip = skip

def __reprargs__(self):
if self.index is noop:
Expand Down Expand Up @@ -380,8 +381,21 @@ def _iter_values(self, log):
f"reusing value from parameter {name!r}: {values!r}"
)

value = lookup(values, self.parent.index)
yield value, meta, dynamic
try:
value = lookup(values, self.parent.index)
except self.parent.skip as err:
log += lambda err=err: (
f"called: {self.parent.index!r}\nraised {err.__class__.__name__}: {err}"
if callable(self.parent.index) else
f"did not find {self.parent.index!r} in {values!r}\nraised {err.__class__.__name__}: {err}"
)
else:
log += lambda: (
f"called: {self.parent.index!r}\nreturned: {value!r}"
if callable(self.parent.index) else
f"found {self.parent.index!r}: {value!r}"
)
yield value, meta, dynamic

def cleanup(self, log):
if not self.update_peers:
Expand Down
87 changes: 87 additions & 0 deletions tests/test_getters.nt
Expand Up @@ -1049,9 +1049,50 @@ test_getter_iter_values:
log:
- queried DummyConfig\(\):
- found 'x': 'a,b'
- found 0: 'a'

- getting 'x2' parameter for <DummyObj object at .*>
- reusing value from parameter 'x1': \['a', 'b'\]
- found 1: 'b'
-
id: part-skip
obj:
> class DummyConfig(Config):
> def load(self):
> yield DictLayer({'x': 'a,b'})
>
> key = Key(DummyConfig, 'x', cast=lambda x: x.split(','))
> parts = [
> Part(key, index=0),
> Part(key, index=2, skip=IndexError),
> ]
>
> class DummyObj:
> __config__ = [DummyConfig]
> x1 = byoc.param(parts[0])
> x2 = byoc.param(parts[1])
param: x1
getter:
> parts[0]
expected:
values: ['a']
meta:
-
type: LayerMeta
layer.values: {'x': 'a,b'}
dynamic:
- False
log:
- queried DummyConfig\(\):
- found 'x': 'a,b'
- found 0: 'a'

- getting 'x2' parameter for <DummyObj object at .*>
- reusing value from parameter 'x1': \['a', 'b'\]
-
> did not find 2 in \['a', 'b'\]
> raised IndexError: list index out of range
- did you mean to provide a default\?

test_getter_kwargs_err:
-
Expand Down Expand Up @@ -1390,5 +1431,51 @@ test_part:
x2: 'b'
n_calls:
f: 1
-
id: skip-first
funcs:
f: lambda x: x.split(',')
obj:
> class DummyConfig(byoc.Config):
> def load(self):
> yield byoc.DictLayer({'x': 'a,b'})
>
> class DummyObj:
> __config__ = [DummyConfig]
> x1 = byoc.param(
> Part(Key(DummyConfig, 'x', cast=f), index=2, skip=IndexError),
> default=None,
> )
> x2 = byoc.param(
> Part(x1, index=1),
> )
expected:
x1: None
x2: 'b'
n_calls:
f: 1
-
id: skip-second
funcs:
f: lambda x: x.split(',')
obj:
> class DummyConfig(byoc.Config):
> def load(self):
> yield byoc.DictLayer({'x': 'a,b'})
>
> class DummyObj:
> __config__ = [DummyConfig]
> x1 = byoc.param(
> Part(Key(DummyConfig, 'x', cast=f), index=0),
> )
> x2 = byoc.param(
> Part(x1, index=2, skip=IndexError),
> default=None,
> )
expected:
x1: 'a'
x2: None
n_calls:
f: 1


0 comments on commit 4eca860

Please sign in to comment.