Skip to content

Commit

Permalink
Add update_current_context to ContextMixin
Browse files Browse the repository at this point in the history
 - `update_current_context` allows changing of a context without
   entering a `with` block.
 - Corrects `Context.__init__` to copy the dictionary it is passed, not
   doing so caused some bugs when introducing `update_current_context`.
  • Loading branch information
mundya committed Mar 21, 2015
1 parent b8425d3 commit 38a58e1
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
10 changes: 9 additions & 1 deletion rig/utils/contexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ def get_new_context(self, **kwargs):
"""Create a new context with the given keyword arguments."""
return Context(kwargs, self.__context_stack)

def update_current_context(self, **context_args):
"""Update the current context to contain new arguments."""
self.__context_stack[-1].update(context_args)

def get_context_arguments(self):
"""Return a dictionary containing the current context arguments."""
cargs = {}
Expand Down Expand Up @@ -161,9 +165,13 @@ def __init__(self, context_arguments, stack=None):
Context stack to which this context will append itself when
entered.
"""
self.context_arguments = context_arguments
self.context_arguments = dict(context_arguments)
self.stack = stack

def update(self, updates):
"""Update the arguments contained within this context."""
self.context_arguments.update(updates)

def __enter__(self):
# Add this context object to the stack
self.stack.append(self)
Expand Down
37 changes: 37 additions & 0 deletions rig/utils/tests/test_contexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,43 @@ def test_contextmixin_required_passed(object_to_test, arg1, arg2):
(123, "Hello", 4, tuple(), {})


@pytest.mark.parametrize("arg1", [1, None, 5])
@pytest.mark.parametrize("arg2", [1, None, 5])
def test_contextmixin_update_current_context(object_to_test, arg1, arg2):
# Create the object
obj = object_to_test()

# Missing arguments currently
with pytest.raises(TypeError) as excinfo:
obj.method_a(1)
assert "arg1" in str(excinfo.value)
assert "method_a" in str(excinfo.value)

# Update the current context
obj.update_current_context(arg1=arg1, bob=3)

assert obj.method_a(1) == (1, arg1, 30)
assert obj.method_a(1, arg2=50) == (1, arg1, 50)

# And again
obj.update_current_context(arg2=arg2)
assert (obj.method_b("World", "Hello") ==
("World", arg1, arg2, ("Hello", ), {}))
assert (obj.method_b(123, arg1="Hello", arg2=4) ==
(123, "Hello", 4, tuple(), {}))

# Within a context
t_arg1 = 11111
with obj.get_new_context(arg1=t_arg1):
assert obj.method_a(1) == (1, t_arg1, arg2)

obj.update_current_context(arg1=arg1)
assert obj.method_a(1) == (1, arg1, arg2)

# And outside of that context
assert obj.method_a(1) == (1, arg1, arg2)


@pytest.mark.parametrize("arg1", [1, None, 5])
def test_contextmixin_required_not_passed_context(object_to_test, arg1):
# Create the object
Expand Down

0 comments on commit 38a58e1

Please sign in to comment.