Skip to content

Commit

Permalink
Merge pull request #6 from melvinkcx/multiple_ot_middleware
Browse files Browse the repository at this point in the history
Fixed multiple oneshot middleware not run issue
  • Loading branch information
melvinkcx authored Feb 20, 2020
2 parents 0401eab + b0e4138 commit d36f214
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
9 changes: 5 additions & 4 deletions graphql_utilities/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ def resolve(self, next, root, info, *args, **kwargs):
@wraps(resolve_func)
def wrapper(self, next, root, info, *args, **kwargs):
has_context = info.context is not None
decorator_name = "__{}_run__".format(self.__class__.__name__)

if has_context:
if isinstance(info.context, dict) and not info.context.get("__middleware_ran", False):
info.context["__middleware_ran"] = True
if isinstance(info.context, dict) and not info.context.get(decorator_name, False):
info.context[decorator_name] = True
return resolve_func(self, next, root, info, *args, **kwargs)
elif not isinstance(info.context, dict) and not getattr(info.context, "__middleware_ran", False):
elif not isinstance(info.context, dict) and not getattr(info.context, decorator_name, False):
# Graphene: it could be a Context or WSGIRequest object
setattr(info.context, "__middleware_ran", True)
setattr(info.context, decorator_name, True)
return resolve_func(self, next, root, info, *args, **kwargs)

# No context, run_only_once will not work
Expand Down
22 changes: 22 additions & 0 deletions tests/test_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,28 @@ def resolve(self, next_, *args, **kwargs):
context_value=_get_fake_wsgi_request_obj()) for _ in (0, 1)]
assert len(runs) == 2, "middleware should run twice for 2 requests"

def test_multiple_one_shot_middleware():
runs = []

class OneShotMiddleware:
@run_only_once
def resolve(self, next_, *args, **kwargs):
runs.append("OneShotMiddleware")
return next_(*args, **kwargs)

class AnotherOneShotMiddleware:
@run_only_once
def resolve(self, next_, *args, **kwargs):
runs.append("AnotherOneShotMiddleware")
return next_(*args, **kwargs)

middleware = (OneShotMiddleware(), AnotherOneShotMiddleware())
execute(schema=schema, document=parse(query), middleware=middleware,
context_value={})
assert len(runs) == 2, "both middleware should have run"
assert "OneShotMiddleware" in runs
assert "AnotherOneShotMiddleware" in runs

def _get_fake_wsgi_request_obj():
return WSGIRequest({
'REQUEST_METHOD': 'POST',
Expand Down

0 comments on commit d36f214

Please # to comment.