-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #141 from ababic/feature/context-modifiers
Improve support for forms and other complex Python/Django constructs (v2)
- Loading branch information
Showing
7 changed files
with
374 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
import inspect | ||
from typing import Callable | ||
|
||
|
||
def accepts_kwarg(func: Callable, kwarg: str) -> bool: | ||
""" | ||
Returns a boolean indicating whether the callable ``func`` has | ||
a signature that accepts the keyword argument ``kwarg``. | ||
""" | ||
signature = inspect.signature(func) | ||
try: | ||
signature.bind_partial(**{kwarg: None}) | ||
return True | ||
except TypeError: | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from collections import defaultdict | ||
from operator import attrgetter | ||
from typing import Callable | ||
|
||
from django.core.exceptions import ImproperlyConfigured | ||
|
||
from .cm_utils import accepts_kwarg | ||
|
||
GENERIC_CM_KEY = "__generic__" | ||
ORDER_ATTR_NAME = "__cm_order" | ||
|
||
__all__ = [ | ||
"ContextModifierRegistry", | ||
"register_context_modifier" | ||
] | ||
|
||
|
||
class ContextModifierRegistry(defaultdict): | ||
def __init__(self): | ||
super().__init__(list) | ||
|
||
def register(self, func: Callable, template: str = None, order: int = 0) -> None: | ||
""" | ||
Adds a context modifier to the registry. | ||
""" | ||
if not callable(func): | ||
raise ImproperlyConfigured( | ||
f"Context modifiers must be callables. {func} is a {type(func).__name__}." | ||
) | ||
if not accepts_kwarg(func, "context"): | ||
raise ImproperlyConfigured( | ||
f"Context modifiers must accept a 'context' keyword argument. {func} does not." | ||
) | ||
if not accepts_kwarg(func, "request"): | ||
raise ImproperlyConfigured( | ||
f"Context modifiers must accept a 'request' keyword argument. {func} does not." | ||
) | ||
|
||
key = template or GENERIC_CM_KEY | ||
if func not in self[key]: | ||
setattr(func, ORDER_ATTR_NAME, order) | ||
self[key].append(func) | ||
self[key].sort(key=attrgetter(ORDER_ATTR_NAME)) | ||
|
||
return func | ||
|
||
def register_decorator(self, func: Callable = None, **kwargs): | ||
if func is None: | ||
return lambda func: self.register(func, **kwargs) | ||
return self.register(func, **kwargs) | ||
|
||
def get_for_template(self, template: str): | ||
modifiers = self[GENERIC_CM_KEY] + self[template] | ||
return sorted(modifiers, key=attrgetter(ORDER_ATTR_NAME)) | ||
|
||
|
||
registry = ContextModifierRegistry() | ||
register_context_modifier = registry.register_decorator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.