Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add defaults values to context dependent destinations #29

Merged
merged 2 commits into from
Jan 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions routemaster/config/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ def _load_context_next_states(
)
for idx, yaml_option in enumerate(yaml_next_states['destinations'])
],
default=yaml_next_states['default'],
)


Expand Down
5 changes: 3 additions & 2 deletions routemaster/config/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,19 @@ class ContextNextStates(NamedTuple):
"""Defined a choice based on a path in the given `label_context`."""
path: str
destinations: Iterable[ContextNextStatesOption]
default: str # noqa: E704 misidentified "multiple statements on one line"

def next_state_for_label(self, label_context: 'Context') -> str:
"""Returns next state based on context value at `self.path`."""
val = label_context.lookup(self.path.split('.'))
for destination in self.destinations:
if destination.value == val:
return destination.state
raise RuntimeError("Handle this gracefully.")
return self.default

def all_destinations(self) -> Iterable[str]:
"""Returns all possible destination states."""
return [x.state for x in self.destinations]
return [x.state for x in self.destinations] + [self.default]


class NoNextStates(NamedTuple):
Expand Down
2 changes: 2 additions & 0 deletions routemaster/config/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ properties:
type:
const: 'metadata'
path: *dotted_path_definition
default:
type: string
destinations:
type: array
minItems: 1
Expand Down
6 changes: 4 additions & 2 deletions routemaster/config/tests/test_loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ def test_realistic_config():
state='stage3',
value='2',
),
]
],
default='end',
),
exit_condition=ExitConditionProgram(
'foo.bar is defined',
Expand Down Expand Up @@ -271,7 +272,8 @@ def test_environment_variables_override_config_file_for_database_config():
state='stage3',
value='2',
),
]
],
default='end',
),
exit_condition=ExitConditionProgram(
'foo.bar is defined',
Expand Down
9 changes: 5 additions & 4 deletions routemaster/config/tests/test_next_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,25 @@ def test_context_next_states(make_context):
ContextNextStatesOption(state='1', value=True),
ContextNextStatesOption(state='2', value=False),
],
default='3',
)

context = make_context(label='label1', metadata={'foo': True})

assert next_states.all_destinations() == ['1', '2']
assert next_states.all_destinations() == ['1', '2', '3']
assert next_states.next_state_for_label(context) == '1'


def test_context_next_states_raises_for_no_valid_state(make_context):
def test_context_next_states_returns_default_if_no_match(make_context):
next_states = ContextNextStates(
path='metadata.foo',
destinations=[
ContextNextStatesOption(state='1', value=True),
ContextNextStatesOption(state='2', value=False),
],
default='3',
)

context = make_context(label='label1', metadata={'foo': 'bar'})

with pytest.raises(RuntimeError):
next_states.next_state_for_label(context)
assert next_states.next_state_for_label(context) == '3'
10 changes: 2 additions & 8 deletions routemaster/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@
next_states=ContextNextStates(
path='feeds.tests.should_do_alternate_action',
destinations=[
ContextNextStatesOption(
state='perform_action',
value=None,
),
ContextNextStatesOption(
state='perform_action',
value=False,
Expand All @@ -83,6 +79,7 @@
value=True,
),
],
default='perform_action',
),
exit_condition=ExitConditionProgram(
'metadata.should_progress = true',
Expand All @@ -99,10 +96,6 @@
next_states=ContextNextStates(
path='feeds.tests.should_loop',
destinations=[
ContextNextStatesOption(
state='end',
value=None,
),
ContextNextStatesOption(
state='end',
value=False,
Expand All @@ -112,6 +105,7 @@
value=True,
),
],
default='end',
),
),
Gate(
Expand Down
3 changes: 2 additions & 1 deletion routemaster/tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ def test_nonexistent_node_destination_invalid(app_config):
state='end',
value='2',
),
]
],
default='end',
),
exit_condition=ExitConditionProgram('false'),
),
Expand Down
1 change: 1 addition & 0 deletions test_data/realistic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ state_machines:
next:
type: context
path: foo.bar
default: end
destinations:
- state: stage3
value: '1'
Expand Down