Skip to content

Commit

Permalink
Issue 196 (#200)
Browse files Browse the repository at this point in the history
* When coded values are passed to the repeated list def they now get caught via an instance check within the list field handlers. Added tests for coded defaults

* Allows for multiple semantics for defining defaults of lists of repeated classes. If no config values are passed or defaults are coded it will fall back on the base classes defaults and instantiate a list of length equal to the number of class instances specified in the default constructor. Added tests.

* linted
  • Loading branch information
ncilfone committed Jan 3, 2022
1 parent e9ddc98 commit d8eee88
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 5 deletions.
21 changes: 20 additions & 1 deletion spock/backend/field_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,26 @@ def handle_optional_attribute_value(
super().handle_optional_attribute_value(attr_space, builder_space)
if attr_space.field is not None:
list_item_spock_class = attr_space.field
builder_space.spock_space[list_item_spock_class.__name__] = attr_space.field
# Here we need to catch the possibility of repeated lists via coded defaults
if _is_spock_instance(attr_space.attribute.metadata["type"].__args__[0]):
spock_cls = attr_space.attribute.metadata["type"].__args__[0]
# Fall back to configs if present
if spock_cls.__name__ in builder_space.arguments:
attr_space.field = self._process_list(spock_cls, builder_space)
# Here we need to attempt to instantiate any class references that still exist
try:
attr_space.field = [
val() if type(val) is type else val for val in attr_space.field
]
except Exception as e:
raise SpockInstantiationError(
f"Spock class `{spock_cls.__name__}` could not be instantiated -- attrs message: {e}"
)
builder_space.spock_space[spock_cls.__name__] = attr_space.field
else:
builder_space.spock_space[
list_item_spock_class.__name__
] = attr_space.field

@staticmethod
def _process_list(spock_cls, builder_space: BuilderSpace):
Expand Down
2 changes: 1 addition & 1 deletion spock/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def _post_process_config_paths(payload):
"""
Transform path string into path object
"""
if "config" in payload:
if (payload is not None) and "config" in payload:
payload["config"] = [Path(c) for c in payload["config"]]

return payload
Expand Down
16 changes: 13 additions & 3 deletions tests/base/attr_configs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ class NestedListStuff:
two: str


@spock
class NestedListStuffDef:
one: int
two: str


class ClassChoice(Enum):
class_nested_stuff = NestedStuff
class_nested_list_stuff = NestedListStuff
Expand Down Expand Up @@ -235,8 +241,12 @@ class TypeDefaultConfig:
nested_def: NestedStuff = NestedStuff
# Nested configuration with no config
nested_no_conf_def: NestedStuffDefault = NestedStuffDefault()
# Nested list configuration
nested_list_def: List[NestedListStuff] = NestedListStuff
# Nested list configuration -- defaults to config values
nested_list_def: List[NestedListStuff] = [NestedListStuff]
# Nested list configuration -- defaults to coded values
nested_list_def_2: List[NestedListStuffDef] = [
NestedListStuffDef(one=100, two="two"), NestedListStuffDef(one=300, two="four")
]
# Class Enum
class_enum_def: ClassChoice = NestedStuff
# Double Nested class ref
Expand Down Expand Up @@ -282,7 +292,7 @@ class TypeDefaultOptConfig:
# Nested configuration
nested_opt_def: Optional[NestedStuff] = NestedStuff
# Nested list configuration
nested_list_opt_def: Optional[List[NestedListStuff]] = NestedListStuff
nested_list_opt_def: Optional[List[NestedListStuff]] = [NestedListStuff]
# Class Enum
class_enum_opt_def: Optional[ClassChoice] = NestedStuff

Expand Down
4 changes: 4 additions & 0 deletions tests/base/base_asserts_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ def test_all_defaults(self, arg_builder):
assert arg_builder.TypeDefaultConfig.nested_list_def[0].two == "hello"
assert arg_builder.TypeDefaultConfig.nested_list_def[1].one == 20
assert arg_builder.TypeDefaultConfig.nested_list_def[1].two == "bye"
assert arg_builder.TypeDefaultConfig.nested_list_def_2[0].one == 100
assert arg_builder.TypeDefaultConfig.nested_list_def_2[0].two == "two"
assert arg_builder.TypeDefaultConfig.nested_list_def_2[1].one == 300
assert arg_builder.TypeDefaultConfig.nested_list_def_2[1].two == "four"
assert arg_builder.TypeDefaultConfig.class_enum_def.one == 11
assert arg_builder.TypeDefaultConfig.class_enum_def.two == "ciao"
assert (
Expand Down
3 changes: 3 additions & 0 deletions tests/base/test_loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def arg_builder(monkeypatch):
TypeConfig,
NestedStuff,
NestedListStuff,
NestedListStuffDef,
NestedStuffDefault,
TypeDefaultConfig,
TypeDefaultOptConfig,
Expand Down Expand Up @@ -103,6 +104,7 @@ def arg_builder(monkeypatch):
TypeConfig,
NestedStuff,
NestedListStuff,
NestedListStuffDef,
NestedStuffDefault,
TypeOptConfig,
TypeDefaultConfig,
Expand Down Expand Up @@ -149,6 +151,7 @@ def arg_builder(monkeypatch):
TypeConfig,
NestedStuff,
NestedListStuff,
NestedListStuffDef,
NestedStuffDefault,
TypeOptConfig,
TypeDefaultConfig,
Expand Down
19 changes: 19 additions & 0 deletions tests/base/test_type_specific.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,22 @@ def test_enum_class_missing(self, monkeypatch):
SecondDoubleNestedConfig,
desc="Test Builder"
)


@spock
class RepeatedDefsFailConfig:
# Nested list configuration
nested_list_def: List[NestedListStuff] = [NestedListStuff]


class TestMissingRepeatedDefs:
def test_repeated_defs_fail(self, monkeypatch):
with monkeypatch.context() as m:
m.setattr(
sys,
"argv",
[""],
)
with pytest.raises(SpockInstantiationError):
config = ConfigArgBuilder(RepeatedDefsFailConfig, NestedListStuff, desc="Test Builder")
config.generate()

0 comments on commit d8eee88

Please sign in to comment.