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

History in context #26

Merged
merged 7 commits into from
Jan 16, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 2 additions & 7 deletions routemaster/config/tests/test_next_states.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import datetime

import pytest
import dateutil

from routemaster.config import (
NoNextStates,
Expand All @@ -11,8 +8,6 @@
)
from routemaster.context import Context

UTC_NOW = datetime.datetime.now(dateutil.tz.tzutc())


def test_constant_next_state():
next_states = ConstantNextState(state='foo')
Expand All @@ -36,7 +31,7 @@ def test_context_next_states():
],
)

context = Context('label1', {'foo': True}, UTC_NOW, None, [])
context = Context(label='label1', metadata={'foo': True})

assert next_states.all_destinations() == ['1', '2']
assert next_states.next_state_for_label(context) == '1'
Expand All @@ -51,7 +46,7 @@ def test_context_next_states_raises_for_no_valid_state():
],
)

context = Context('label1', {'foo': 'bar'}, UTC_NOW, None, [])
context = Context(label='label1', metadata={'foo': 'bar'})

with pytest.raises(RuntimeError):
next_states.next_state_for_label(context)
15 changes: 10 additions & 5 deletions routemaster/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import datetime
from typing import Any, Dict, Iterable, Sequence

import dateutil.tz

from routemaster.feeds import Feed
from routemaster.utils import get_path

Expand All @@ -11,14 +13,17 @@ class Context(object):

def __init__(
self,
*,
label: str,
metadata: Dict[str, Any],
now: datetime.datetime,
feeds: Dict[str, Feed],
accessed_variables: Iterable[str],
metadata: Dict[str, Any] = {},
now: datetime.datetime = None,
feeds: Dict[str, Feed] = {},
accessed_variables: Iterable[str] = [],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that having these mutable defaults is a good idea (maybe add flake8-mutable?).

Perhaps a better way to solve this would be a helper used in tests which handles the non-interesting defaults?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've fixed these with a test factory method that has the defaults (but not as mutable args).

) -> None:
"""Create an execution context."""
if now.tzinfo is None:
if now is None:
now = datetime.datetime.now(dateutil.tz.tzutc())
elif now.tzinfo is None:
raise ValueError(
"Cannot evaluate exit conditions with naive datetimes",
)
Expand Down
19 changes: 8 additions & 11 deletions routemaster/exit_conditions/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,14 @@
}



@pytest.mark.parametrize("program, expected, variables", PROGRAMS)
def test_evaluate(program, expected, variables):
program = ExitConditionProgram(program)
context = Context(
'label1',
VARIABLES,
NOW,
{},
program.accessed_variables(),
label='label1',
metadata=VARIABLES,
now=NOW,
accessed_variables=program.accessed_variables(),
)
assert program.run(context) == expected

Expand Down Expand Up @@ -143,11 +141,10 @@ def test_errors(source, error):
with pytest.raises(ValueError) as compile_error:
program = ExitConditionProgram(source)
context = Context(
'label1',
VARIABLES,
NOW,
{},
program.accessed_variables(),
label='label1',
metadata=VARIABLES,
now=NOW,
accessed_variables=program.accessed_variables(),
)
program.run(context)

Expand Down
20 changes: 10 additions & 10 deletions routemaster/state_machine/tests/test_state_machine_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ def test_context_for_label_in_gate_created_with_correct_variables(app_config):

utils.context_for_label(label, metadata, state_machine, state)
mock_constructor.assert_called_once_with(
label.name,
metadata,
dt,
{'tests': Feed('http://localhost/tests', 'test_machine')},
[
label=label.name,
metadata=metadata,
now=dt,
feeds={'tests': Feed('http://localhost/tests', 'test_machine')},
accessed_variables=[
'metadata.should_progress',
'feeds.tests.should_do_alternate_action',
],
Expand All @@ -105,9 +105,9 @@ def test_context_for_label_in_action_created_with_correct_variables(app_config):

utils.context_for_label(label, metadata, state_machine, state)
mock_constructor.assert_called_once_with(
label.name,
metadata,
dt,
{'tests': Feed('http://localhost/tests', 'test_machine')},
['feeds.tests.should_loop'],
label=label.name,
metadata=metadata,
now=dt,
feeds={'tests': Feed('http://localhost/tests', 'test_machine')},
accessed_variables=['feeds.tests.should_loop'],
)
10 changes: 5 additions & 5 deletions routemaster/state_machine/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ def context_for_label(
accessed_variables.append(state.next_states.path)

return Context(
label.name,
metadata,
datetime.datetime.now(dateutil.tz.tzutc()),
feeds,
accessed_variables,
label=label.name,
metadata=metadata,
now=datetime.datetime.now(dateutil.tz.tzutc()),
feeds=feeds,
accessed_variables=accessed_variables,
)
61 changes: 22 additions & 39 deletions routemaster/tests/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,39 @@

import mock
import pytest
import dateutil
import httpretty

from routemaster.feeds import Feed
from routemaster.context import Context

UTC_NOW = datetime.datetime.now(dateutil.tz.tzutc())


def test_context_does_not_accept_naive_datetimes():
with pytest.raises(ValueError):
Context('label1', {}, datetime.datetime.utcnow(), None, [])
Context(label='label1', now=datetime.datetime.utcnow())


def test_finds_path_in_context():
context = Context(
'label1',
{'foo': {'bar': 'baz'}},
UTC_NOW,
{},
['metadata.foo.bar'],
label='label1',
metadata={'foo': {'bar': 'baz'}},
accessed_variables=['metadata.foo.bar'],
)
assert context.lookup(['metadata', 'foo', 'bar']) == 'baz'


def test_returns_none_for_unknown_prefix():
context = Context(
'label1',
{'foo': {'bar': 'baz'}},
UTC_NOW,
{},
['unknown.foo.bar'],
label='label1',
accessed_variables=['unknown.foo.bar'],
)
assert context.lookup(['unknown', 'foo', 'bar']) is None


def test_returns_none_for_unknown_metadata_variable():
context = Context(
'label1',
{'foo': {'bar': 'baz'}},
UTC_NOW,
{},
['metadata.unknown'],
label='label1',
metadata={'foo': {'bar': 'baz'}},
accessed_variables=['metadata.unknown'],
)
assert context.lookup(['metadata', 'unknown']) is None

Expand All @@ -60,11 +50,9 @@ def test_accesses_variable_in_feed():

feed = Feed('http://example.com/<label>', 'test_machine')
context = Context(
'label1',
{},
UTC_NOW,
{'example': feed},
['feeds.example.foo'],
label='label1',
feeds={'example': feed},
accessed_variables=['feeds.example.foo'],
)
result = context.lookup(('feeds', 'example', 'foo'))
assert result == 'bar'
Expand All @@ -84,11 +72,10 @@ def test_only_loads_feed_once():

feed = Feed('http://example.com/<label>', 'test_machine')
context = Context(
'label1',
{},
UTC_NOW,
{'example': feed},
['feeds.example.foo', 'feeds.example.baz'],
label='label1',
metadata={},
feeds={'example': feed},
accessed_variables=['feeds.example.foo', 'feeds.example.baz'],
)

context.lookup(('feeds', 'example', 'foo'))
Expand All @@ -99,21 +86,17 @@ def test_only_loads_feed_once():

def test_non_existent_feed_is_none():
context = Context(
'label1',
{},
UTC_NOW,
{},
['feeds.foo.bar'],
label='label1',
feeds={},
accessed_variables=['feeds.foo.bar'],
)
assert context.lookup(['feeds', 'foo', 'bar']) is None


def test_accessing_prefix_directly_does_not_error():
context = Context(
'label1',
{},
UTC_NOW,
{},
['metadata'],
label='label1',
metadata={},
accessed_variables=['metadata'],
)
assert context.lookup(['metadata']) == {}