Skip to content
This repository has been archived by the owner on Mar 28, 2019. It is now read-only.

Commit

Permalink
* Allow listening to context var updates via Env.context_var_updated …
Browse files Browse the repository at this point in the history
…hook

* RuntimeContext.context_entered and RuntimeContext.context_exited event handlers now get context_vars instead of rather pointless runtime_context reference

* Bump version: 1.0.0 → 1.1.0
  • Loading branch information
jbasko committed Jan 14, 2018
1 parent 9ab2bb6 commit 485576b
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.0.0
current_version = 1.1.0
commit = true
tag = false

Expand Down
2 changes: 1 addition & 1 deletion runtime_context/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '1.0.0'
__version__ = '1.1.0'

from .env2 import runtime_context_env
from .runtime_context import RuntimeContext
Expand Down
21 changes: 21 additions & 0 deletions runtime_context/env2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
@runtime_context_env is a decorator for your custom Env class which may want to have its attributes overridden by
context variables.
"""
from hookery import HookRegistry

from .runtime_context import RuntimeContext


Expand All @@ -11,10 +13,20 @@ class EnvBase:
'set',
'runtime_context',
'is_context_var',
'_hooks',
'context_var_updated',
'_handle_runtime_context_entered',
'_handle_runtime_context_exited',
)

runtime_context = None # type: RuntimeContext

def __init__(self):
self._hooks = HookRegistry()
self.context_var_updated = self._hooks.register_event('context_var_updated')
self.runtime_context.context_entered(self._handle_runtime_context_entered)
self.runtime_context.context_exited(self._handle_runtime_context_exited)

def is_context_var(self, name):
"""
Context variable is something that can be customised per context.
Expand Down Expand Up @@ -44,6 +56,7 @@ def __setattr__(self, name, value):
object.__setattr__(self, name, value)
elif self.is_context_var(name):
self.runtime_context.set(name, value)
self.context_var_updated.trigger(name=name)
else:
object.__setattr__(self, name, value)

Expand All @@ -57,6 +70,14 @@ def set(self, name, value):
raise AttributeError(name)
setattr(self, name, value)

def _handle_runtime_context_entered(self, context_vars):
for k in context_vars.keys():
self.context_var_updated.trigger(name=k)

def _handle_runtime_context_exited(self, context_vars):
for k in context_vars.keys():
self.context_var_updated.trigger(name=k)


def runtime_context_env(env_cls):
return type(env_cls.__name__, (env_cls, EnvBase), {
Expand Down
7 changes: 4 additions & 3 deletions runtime_context/runtime_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ def __init__(self, runtime_context, **context_vars):

def __enter__(self):
self.runtime_context._stack.append(self.context_vars)
self.runtime_context.context_entered.trigger(context=self.runtime_context)
self.runtime_context.context_entered.trigger(context_vars=self.context_vars)
return self.runtime_context

def __exit__(self, exc_type, exc_val, exc_tb):
self.runtime_context._stack.pop()
self.runtime_context.context_exited.trigger(context=self.runtime_context)
popped = self.runtime_context._stack.pop()
assert popped is self.context_vars
self.runtime_context.context_exited.trigger(context_vars=self.context_vars)


class RuntimeContext:
Expand Down
41 changes: 41 additions & 0 deletions tests/test_env2.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class App:
y = 1

def __init__(self):
super().__init__()
self.z = 2

app = App()
Expand Down Expand Up @@ -92,3 +93,43 @@ def __init__(self):

assert app.get('x') == 0
assert app.get('y') == 1


def test_change_hooks():
@runtime_context_env
class App:
config_file = 'config.json'
x = None

def __init__(self):
super().__init__()
self.times_reloaded = 0

def reload_config(self):
self.times_reloaded += 1

app = App()

@app.context_var_updated
def reload_local_config(name):
if name == 'config_file':
app.reload_config()

with app():
with app(x=1):
assert app.times_reloaded == 0
with app(config_file='config.yaml'):
assert app.times_reloaded == 1

assert app.times_reloaded == 2

assert app.times_reloaded == 2

app.config_file = 'config.txt'
assert app.times_reloaded == 3

with app():
assert app.times_reloaded == 3
assert app.times_reloaded == 3

assert app.times_reloaded == 4
8 changes: 0 additions & 8 deletions tests/test_runtime_context.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import pytest


def test_rc_fixture(rc):
import runtime_context

assert isinstance(rc, runtime_context.RuntimeContext)
assert len(rc._stack) == 1
assert rc._stack[-1] == {}


def test_rc_basics(rc):
"""
Basics are:
Expand Down

0 comments on commit 485576b

Please sign in to comment.