mirror of
https://github.com/django-components/django-components.git
synced 2025-08-03 22:08:17 +00:00
Reformat lines that became too long. And enforce 119 line length.
This commit is contained in:
parent
ef6a082238
commit
48fe8171b4
25 changed files with 314 additions and 733 deletions
|
@ -26,9 +26,7 @@ class AppSettings:
|
|||
|
||||
@property
|
||||
def CONTEXT_BEHAVIOR(self):
|
||||
raw_value = self.settings.setdefault(
|
||||
"context_behavior", ContextBehavior.GLOBAL.value
|
||||
)
|
||||
raw_value = self.settings.setdefault("context_behavior", ContextBehavior.GLOBAL.value)
|
||||
return self._validate_context_behavior(raw_value)
|
||||
|
||||
def _validate_context_behavior(self, raw_value):
|
||||
|
@ -36,9 +34,7 @@ class AppSettings:
|
|||
return ContextBehavior(raw_value)
|
||||
except ValueError:
|
||||
valid_values = [behavior.value for behavior in ContextBehavior]
|
||||
raise ValueError(
|
||||
f"Invalid context behavior: {raw_value}. Valid options are {valid_values}"
|
||||
)
|
||||
raise ValueError(f"Invalid context behavior: {raw_value}. Valid options are {valid_values}")
|
||||
|
||||
|
||||
app_settings = AppSettings()
|
||||
|
|
|
@ -80,9 +80,7 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
|||
self,
|
||||
registered_name: Optional[str] = None,
|
||||
outer_context: Optional[Context] = None,
|
||||
fill_content: Union[
|
||||
DefaultFillContent, Iterable[NamedFillContent]
|
||||
] = (),
|
||||
fill_content: Union[DefaultFillContent, Iterable[NamedFillContent]] = (),
|
||||
):
|
||||
self.registered_name: Optional[str] = registered_name
|
||||
self.outer_context: Context = outer_context or Context()
|
||||
|
@ -152,14 +150,10 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
|||
if slots_data:
|
||||
self._fill_slots(slots_data, escape_slots_content)
|
||||
|
||||
updated_filled_slots_context: FilledSlotsContext = (
|
||||
self._process_template_and_update_filled_slot_context(
|
||||
context, template
|
||||
)
|
||||
updated_filled_slots_context: FilledSlotsContext = self._process_template_and_update_filled_slot_context(
|
||||
context, template
|
||||
)
|
||||
with context.update(
|
||||
{FILLED_SLOTS_CONTENT_CONTEXT_KEY: updated_filled_slots_context}
|
||||
):
|
||||
with context.update({FILLED_SLOTS_CONTENT_CONTEXT_KEY: updated_filled_slots_context}):
|
||||
return template.render(context)
|
||||
|
||||
def render_to_response(
|
||||
|
@ -201,19 +195,14 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
|||
named_fills_content = {}
|
||||
else:
|
||||
default_fill_content = None
|
||||
named_fills_content = {
|
||||
name: (nodelist, alias)
|
||||
for name, nodelist, alias in self.fill_content
|
||||
}
|
||||
named_fills_content = {name: (nodelist, alias) for name, nodelist, alias in self.fill_content}
|
||||
|
||||
# If value is `None`, then slot is unfilled.
|
||||
slot_name2fill_content: Dict[SlotName, Optional[FillContent]] = {}
|
||||
default_slot_encountered: bool = False
|
||||
required_slot_names: Set[str] = set()
|
||||
|
||||
for node in template.nodelist.get_nodes_by_type(
|
||||
(SlotNode, IfSlotFilledConditionBranchNode) # type: ignore
|
||||
):
|
||||
for node in template.nodelist.get_nodes_by_type((SlotNode, IfSlotFilledConditionBranchNode)): # type: ignore
|
||||
if isinstance(node, SlotNode):
|
||||
# Give slot node knowledge of its parent template.
|
||||
node.template = template
|
||||
|
@ -225,9 +214,7 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
|||
f"To fix, check template '{template.name}' "
|
||||
f"of component '{self.registered_name}'."
|
||||
)
|
||||
content_data: Optional[FillContent] = (
|
||||
None # `None` -> unfilled
|
||||
)
|
||||
content_data: Optional[FillContent] = None # `None` -> unfilled
|
||||
if node.is_required:
|
||||
required_slot_names.add(node.name)
|
||||
if node.is_default:
|
||||
|
@ -245,9 +232,7 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
|||
elif isinstance(node, IfSlotFilledConditionBranchNode):
|
||||
node.template = template
|
||||
else:
|
||||
raise RuntimeError(
|
||||
f"Node of {type(node).__name__} does not require linking."
|
||||
)
|
||||
raise RuntimeError(f"Node of {type(node).__name__} does not require linking.")
|
||||
|
||||
# Check: Only component templates that include a 'default' slot
|
||||
# can be invoked with implicit filling.
|
||||
|
@ -258,12 +243,8 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
|||
f"even though none of its slots is marked as 'default'."
|
||||
)
|
||||
|
||||
unfilled_slots: Set[str] = set(
|
||||
k for k, v in slot_name2fill_content.items() if v is None
|
||||
)
|
||||
unmatched_fills: Set[str] = (
|
||||
named_fills_content.keys() - slot_name2fill_content.keys()
|
||||
)
|
||||
unfilled_slots: Set[str] = set(k for k, v in slot_name2fill_content.items() if v is None)
|
||||
unmatched_fills: Set[str] = named_fills_content.keys() - slot_name2fill_content.keys()
|
||||
|
||||
# Check that 'required' slots are filled.
|
||||
for slot_name in unfilled_slots:
|
||||
|
@ -286,9 +267,7 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
|||
# Higher values make matching stricter. This is probably preferable, as it
|
||||
# reduces false positives.
|
||||
for fill_name in unmatched_fills:
|
||||
fuzzy_slot_name_matches = difflib.get_close_matches(
|
||||
fill_name, unfilled_slots, n=1, cutoff=0.7
|
||||
)
|
||||
fuzzy_slot_name_matches = difflib.get_close_matches(fill_name, unfilled_slots, n=1, cutoff=0.7)
|
||||
msg = (
|
||||
f"Component '{self.registered_name}' passed fill "
|
||||
f"that refers to undefined slot: '{fill_name}'."
|
||||
|
@ -305,9 +284,7 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
|||
if content_data # Slots whose content is None (i.e. unfilled) are dropped.
|
||||
}
|
||||
try:
|
||||
prev_context: FilledSlotsContext = context[
|
||||
FILLED_SLOTS_CONTENT_CONTEXT_KEY
|
||||
]
|
||||
prev_context: FilledSlotsContext = context[FILLED_SLOTS_CONTENT_CONTEXT_KEY]
|
||||
return prev_context.new_child(filled_slots_map)
|
||||
except KeyError:
|
||||
return ChainMap(filled_slots_map)
|
||||
|
|
|
@ -12,13 +12,8 @@ class ComponentRegistry(object):
|
|||
|
||||
def register(self, name=None, component=None):
|
||||
existing_component = self._registry.get(name)
|
||||
if (
|
||||
existing_component
|
||||
and existing_component.class_hash != component.class_hash
|
||||
):
|
||||
raise AlreadyRegistered(
|
||||
'The component "%s" has already been registered' % name
|
||||
)
|
||||
if existing_component and existing_component.class_hash != component.class_hash:
|
||||
raise AlreadyRegistered('The component "%s" has already been registered' % name)
|
||||
self._registry[name] = component
|
||||
|
||||
def unregister(self, name):
|
||||
|
|
|
@ -9,9 +9,7 @@ class Command(BaseCommand):
|
|||
help = "Creates a new component"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"name", type=str, help="The name of the component to create"
|
||||
)
|
||||
parser.add_argument("name", type=str, help="The name of the component to create")
|
||||
parser.add_argument(
|
||||
"--path",
|
||||
type=str,
|
||||
|
@ -71,9 +69,7 @@ class Command(BaseCommand):
|
|||
elif base_dir:
|
||||
component_path = os.path.join(base_dir, "components", name)
|
||||
else:
|
||||
raise CommandError(
|
||||
"You must specify a path or set BASE_DIR in your django settings"
|
||||
)
|
||||
raise CommandError("You must specify a path or set BASE_DIR in your django settings")
|
||||
|
||||
if os.path.exists(component_path):
|
||||
if force:
|
||||
|
@ -84,11 +80,7 @@ class Command(BaseCommand):
|
|||
)
|
||||
)
|
||||
else:
|
||||
self.stdout.write(
|
||||
self.style.WARNING(
|
||||
f'The component "{name}" already exists. Overwriting...'
|
||||
)
|
||||
)
|
||||
self.stdout.write(self.style.WARNING(f'The component "{name}" already exists. Overwriting...'))
|
||||
else:
|
||||
raise CommandError(
|
||||
f'The component "{name}" already exists at {component_path}. Use --force to overwrite.'
|
||||
|
@ -107,9 +99,7 @@ class Command(BaseCommand):
|
|||
)
|
||||
f.write(script_content.strip())
|
||||
|
||||
with open(
|
||||
os.path.join(component_path, css_filename), "w"
|
||||
) as f:
|
||||
with open(os.path.join(component_path, css_filename), "w") as f:
|
||||
style_content = dedent(
|
||||
f"""
|
||||
.component-{name} {{
|
||||
|
@ -119,9 +109,7 @@ class Command(BaseCommand):
|
|||
)
|
||||
f.write(style_content.strip())
|
||||
|
||||
with open(
|
||||
os.path.join(component_path, template_filename), "w"
|
||||
) as f:
|
||||
with open(os.path.join(component_path, template_filename), "w") as f:
|
||||
template_content = dedent(
|
||||
f"""
|
||||
<div class="component-{name}">
|
||||
|
@ -133,9 +121,7 @@ class Command(BaseCommand):
|
|||
)
|
||||
f.write(template_content.strip())
|
||||
|
||||
with open(
|
||||
os.path.join(component_path, f"{name}.py"), "w"
|
||||
) as f:
|
||||
with open(os.path.join(component_path, f"{name}.py"), "w") as f:
|
||||
py_content = dedent(
|
||||
f"""
|
||||
from django_components import component
|
||||
|
@ -157,16 +143,8 @@ class Command(BaseCommand):
|
|||
f.write(py_content.strip())
|
||||
|
||||
if verbose:
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f"Successfully created {name} component at {component_path}"
|
||||
)
|
||||
)
|
||||
self.stdout.write(self.style.SUCCESS(f"Successfully created {name} component at {component_path}"))
|
||||
else:
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f"Successfully created {name} component"
|
||||
)
|
||||
)
|
||||
self.stdout.write(self.style.SUCCESS(f"Successfully created {name} component"))
|
||||
else:
|
||||
raise CommandError("You must specify a component name")
|
||||
|
|
|
@ -11,9 +11,7 @@ CSS_DEPENDENCY_PLACEHOLDER = '<link name="CSS_PLACEHOLDER">'
|
|||
JS_DEPENDENCY_PLACEHOLDER = '<script name="JS_PLACEHOLDER"></script>'
|
||||
|
||||
SCRIPT_TAG_REGEX = re.compile("<script")
|
||||
COMPONENT_COMMENT_REGEX = re.compile(
|
||||
rb"<!-- _RENDERED (?P<name>[\w\-/]+?) -->"
|
||||
)
|
||||
COMPONENT_COMMENT_REGEX = re.compile(rb"<!-- _RENDERED (?P<name>[\w\-/]+?) -->")
|
||||
PLACEHOLDER_REGEX = re.compile(
|
||||
rb"<!-- _RENDERED (?P<name>[\w\-/]+?) -->"
|
||||
rb'|<link name="CSS_PLACEHOLDER">'
|
||||
|
@ -32,9 +30,7 @@ class ComponentDependencyMiddleware:
|
|||
def __call__(self, request):
|
||||
response = self.get_response(request)
|
||||
if (
|
||||
getattr(settings, "COMPONENTS", {}).get(
|
||||
"RENDER_DEPENDENCIES", False
|
||||
)
|
||||
getattr(settings, "COMPONENTS", {}).get("RENDER_DEPENDENCIES", False)
|
||||
and not isinstance(response, StreamingHttpResponse)
|
||||
and response.get("Content-Type", "").startswith("text/html")
|
||||
):
|
||||
|
@ -43,23 +39,12 @@ class ComponentDependencyMiddleware:
|
|||
|
||||
|
||||
def process_response_content(content):
|
||||
component_names_seen = {
|
||||
match.group("name")
|
||||
for match in COMPONENT_COMMENT_REGEX.finditer(content)
|
||||
}
|
||||
all_components = [
|
||||
registry.get(name.decode("utf-8"))("") for name in component_names_seen
|
||||
]
|
||||
component_names_seen = {match.group("name") for match in COMPONENT_COMMENT_REGEX.finditer(content)}
|
||||
all_components = [registry.get(name.decode("utf-8"))("") for name in component_names_seen]
|
||||
all_media = join_media(all_components)
|
||||
js_dependencies = b"".join(
|
||||
media.encode("utf-8") for media in all_media.render_js()
|
||||
)
|
||||
css_dependencies = b"".join(
|
||||
media.encode("utf-8") for media in all_media.render_css()
|
||||
)
|
||||
return PLACEHOLDER_REGEX.sub(
|
||||
DependencyReplacer(css_dependencies, js_dependencies), content
|
||||
)
|
||||
js_dependencies = b"".join(media.encode("utf-8") for media in all_media.render_js())
|
||||
css_dependencies = b"".join(media.encode("utf-8") for media in all_media.render_css())
|
||||
return PLACEHOLDER_REGEX.sub(DependencyReplacer(css_dependencies, js_dependencies), content)
|
||||
|
||||
|
||||
def add_module_attribute_to_scripts(scripts):
|
||||
|
|
|
@ -12,9 +12,7 @@ class SaferStaticFilesConfig(StaticFilesConfig):
|
|||
by the static file server.
|
||||
"""
|
||||
|
||||
default = (
|
||||
True # Ensure that _this_ app is registered, as opposed to parent cls.
|
||||
)
|
||||
default = True # Ensure that _this_ app is registered, as opposed to parent cls.
|
||||
ignore_patterns = StaticFilesConfig.ignore_patterns + [
|
||||
"*.py",
|
||||
"*.html",
|
||||
|
|
|
@ -9,13 +9,7 @@ else:
|
|||
import django.template
|
||||
from django.conf import settings
|
||||
from django.template import Context, Template
|
||||
from django.template.base import (
|
||||
FilterExpression,
|
||||
Node,
|
||||
NodeList,
|
||||
TextNode,
|
||||
TokenType,
|
||||
)
|
||||
from django.template.base import FilterExpression, Node, NodeList, TextNode, TokenType
|
||||
from django.template.defaulttags import CommentNode
|
||||
from django.template.exceptions import TemplateSyntaxError
|
||||
from django.template.library import parse_bits
|
||||
|
@ -24,10 +18,7 @@ from django.utils.safestring import mark_safe
|
|||
from django_components.app_settings import app_settings
|
||||
from django_components.component_registry import ComponentRegistry
|
||||
from django_components.component_registry import registry as component_registry
|
||||
from django_components.middleware import (
|
||||
CSS_DEPENDENCY_PLACEHOLDER,
|
||||
JS_DEPENDENCY_PLACEHOLDER,
|
||||
)
|
||||
from django_components.middleware import CSS_DEPENDENCY_PLACEHOLDER, JS_DEPENDENCY_PLACEHOLDER
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from django_components.component import Component
|
||||
|
@ -88,16 +79,8 @@ def component_dependencies_tag(preload=""):
|
|||
if is_dependency_middleware_active():
|
||||
preloaded_dependencies = []
|
||||
for component in get_components_from_preload_str(preload):
|
||||
preloaded_dependencies.append(
|
||||
RENDERED_COMMENT_TEMPLATE.format(
|
||||
name=component.registered_name
|
||||
)
|
||||
)
|
||||
return mark_safe(
|
||||
"\n".join(preloaded_dependencies)
|
||||
+ CSS_DEPENDENCY_PLACEHOLDER
|
||||
+ JS_DEPENDENCY_PLACEHOLDER
|
||||
)
|
||||
preloaded_dependencies.append(RENDERED_COMMENT_TEMPLATE.format(name=component.registered_name))
|
||||
return mark_safe("\n".join(preloaded_dependencies) + CSS_DEPENDENCY_PLACEHOLDER + JS_DEPENDENCY_PLACEHOLDER)
|
||||
else:
|
||||
rendered_dependencies = []
|
||||
for component in get_components_from_registry(component_registry):
|
||||
|
@ -113,14 +96,8 @@ def component_css_dependencies_tag(preload=""):
|
|||
if is_dependency_middleware_active():
|
||||
preloaded_dependencies = []
|
||||
for component in get_components_from_preload_str(preload):
|
||||
preloaded_dependencies.append(
|
||||
RENDERED_COMMENT_TEMPLATE.format(
|
||||
name=component.registered_name
|
||||
)
|
||||
)
|
||||
return mark_safe(
|
||||
"\n".join(preloaded_dependencies) + CSS_DEPENDENCY_PLACEHOLDER
|
||||
)
|
||||
preloaded_dependencies.append(RENDERED_COMMENT_TEMPLATE.format(name=component.registered_name))
|
||||
return mark_safe("\n".join(preloaded_dependencies) + CSS_DEPENDENCY_PLACEHOLDER)
|
||||
else:
|
||||
rendered_dependencies = []
|
||||
for component in get_components_from_registry(component_registry):
|
||||
|
@ -136,14 +113,8 @@ def component_js_dependencies_tag(preload=""):
|
|||
if is_dependency_middleware_active():
|
||||
preloaded_dependencies = []
|
||||
for component in get_components_from_preload_str(preload):
|
||||
preloaded_dependencies.append(
|
||||
RENDERED_COMMENT_TEMPLATE.format(
|
||||
name=component.registered_name
|
||||
)
|
||||
)
|
||||
return mark_safe(
|
||||
"\n".join(preloaded_dependencies) + JS_DEPENDENCY_PLACEHOLDER
|
||||
)
|
||||
preloaded_dependencies.append(RENDERED_COMMENT_TEMPLATE.format(name=component.registered_name))
|
||||
return mark_safe("\n".join(preloaded_dependencies) + JS_DEPENDENCY_PLACEHOLDER)
|
||||
else:
|
||||
rendered_dependencies = []
|
||||
for component in get_components_from_registry(component_registry):
|
||||
|
@ -151,6 +122,7 @@ def component_js_dependencies_tag(preload=""):
|
|||
|
||||
return mark_safe("\n".join(rendered_dependencies))
|
||||
|
||||
|
||||
class UserSlotVar:
|
||||
"""
|
||||
Extensible mechanism for offering 'fill' blocks in template access to properties
|
||||
|
@ -216,24 +188,17 @@ class SlotNode(Node, TemplateAwareNodeMixin):
|
|||
|
||||
def render(self, context):
|
||||
try:
|
||||
filled_slots_map: FilledSlotsContext = context[
|
||||
FILLED_SLOTS_CONTENT_CONTEXT_KEY
|
||||
]
|
||||
filled_slots_map: FilledSlotsContext = context[FILLED_SLOTS_CONTENT_CONTEXT_KEY]
|
||||
except KeyError:
|
||||
raise TemplateSyntaxError(
|
||||
f"Attempted to render SlotNode '{self.name}' outside a parent component."
|
||||
)
|
||||
raise TemplateSyntaxError(f"Attempted to render SlotNode '{self.name}' outside a parent component.")
|
||||
|
||||
extra_context = {}
|
||||
try:
|
||||
slot_fill_content: Optional[FillContent] = filled_slots_map[
|
||||
(self.name, self.template)
|
||||
]
|
||||
slot_fill_content: Optional[FillContent] = filled_slots_map[(self.name, self.template)]
|
||||
except KeyError:
|
||||
if self.is_required:
|
||||
raise TemplateSyntaxError(
|
||||
f"Slot '{self.name}' is marked as 'required' (i.e. non-optional), "
|
||||
f"yet no fill is provided. "
|
||||
f"Slot '{self.name}' is marked as 'required' (i.e. non-optional), " f"yet no fill is provided. "
|
||||
)
|
||||
nodelist = self.nodelist
|
||||
else:
|
||||
|
@ -257,9 +222,7 @@ def do_slot(parser, token):
|
|||
if 1 <= len(args) <= 3:
|
||||
slot_name, *options = args
|
||||
if not is_wrapped_in_quotes(slot_name):
|
||||
raise TemplateSyntaxError(
|
||||
f"'{bits[0]}' name must be a string 'literal'."
|
||||
)
|
||||
raise TemplateSyntaxError(f"'{bits[0]}' name must be a string 'literal'.")
|
||||
slot_name = strip_quotes(slot_name)
|
||||
modifiers_count = len(options)
|
||||
if SLOT_REQUIRED_OPTION_KEYWORD in options:
|
||||
|
@ -273,9 +236,7 @@ def do_slot(parser, token):
|
|||
SLOT_REQUIRED_OPTION_KEYWORD,
|
||||
SLOT_DEFAULT_OPTION_KEYWORD,
|
||||
]
|
||||
raise TemplateSyntaxError(
|
||||
f"Invalid options passed to 'slot' tag. Valid choices: {keywords}."
|
||||
)
|
||||
raise TemplateSyntaxError(f"Invalid options passed to 'slot' tag. Valid choices: {keywords}.")
|
||||
else:
|
||||
raise TemplateSyntaxError(
|
||||
"'slot' tag does not match pattern "
|
||||
|
@ -354,14 +315,10 @@ def do_fill(parser, token):
|
|||
elif len(args) == 3:
|
||||
tgt_slot_name, as_keyword, alias = args
|
||||
if as_keyword.lower() != "as":
|
||||
raise TemplateSyntaxError(
|
||||
f"{tag} tag args do not conform to pattern '<target slot> as <alias>'"
|
||||
)
|
||||
raise TemplateSyntaxError(f"{tag} tag args do not conform to pattern '<target slot> as <alias>'")
|
||||
alias_fexp = FilterExpression(alias, parser)
|
||||
else:
|
||||
raise TemplateSyntaxError(
|
||||
f"'{tag}' tag takes either 1 or 3 arguments: Received {len(args)}."
|
||||
)
|
||||
raise TemplateSyntaxError(f"'{tag}' tag takes either 1 or 3 arguments: Received {len(args)}.")
|
||||
nodelist = parser.parse(parse_until=["endfill"])
|
||||
parser.delete_first_token()
|
||||
|
||||
|
@ -397,27 +354,18 @@ class ComponentNode(Node):
|
|||
def __repr__(self):
|
||||
return "<ComponentNode: %s. Contents: %r>" % (
|
||||
self.name_fexp,
|
||||
getattr(
|
||||
self, "nodelist", None
|
||||
), # 'nodelist' attribute only assigned later.
|
||||
getattr(self, "nodelist", None), # 'nodelist' attribute only assigned later.
|
||||
)
|
||||
|
||||
def render(self, context: Context):
|
||||
resolved_component_name = self.name_fexp.resolve(context)
|
||||
component_cls: Type[Component] = component_registry.get(
|
||||
resolved_component_name
|
||||
)
|
||||
component_cls: Type[Component] = component_registry.get(resolved_component_name)
|
||||
|
||||
# Resolve FilterExpressions and Variables that were passed as args to the
|
||||
# component, then call component's context method
|
||||
# to get values to insert into the context
|
||||
resolved_context_args = [
|
||||
safe_resolve(arg, context) for arg in self.context_args
|
||||
]
|
||||
resolved_context_kwargs = {
|
||||
key: safe_resolve(kwarg, context)
|
||||
for key, kwarg in self.context_kwargs.items()
|
||||
}
|
||||
resolved_context_args = [safe_resolve(arg, context) for arg in self.context_args]
|
||||
resolved_context_kwargs = {key: safe_resolve(kwarg, context) for key, kwarg in self.context_kwargs.items()}
|
||||
|
||||
if isinstance(self.fill_nodes, ImplicitFillNode):
|
||||
fill_content = self.fill_nodes.nodelist
|
||||
|
@ -437,9 +385,7 @@ class ComponentNode(Node):
|
|||
)
|
||||
else:
|
||||
resolved_alias: None = None
|
||||
fill_content.append(
|
||||
(resolved_name, fill_node.nodelist, resolved_alias)
|
||||
)
|
||||
fill_content.append((resolved_name, fill_node.nodelist, resolved_alias))
|
||||
|
||||
component: Component = component_cls(
|
||||
registered_name=resolved_component_name,
|
||||
|
@ -447,9 +393,7 @@ class ComponentNode(Node):
|
|||
fill_content=fill_content,
|
||||
)
|
||||
|
||||
component_context: dict = component.get_context_data(
|
||||
*resolved_context_args, **resolved_context_kwargs
|
||||
)
|
||||
component_context: dict = component.get_context_data(*resolved_context_args, **resolved_context_kwargs)
|
||||
|
||||
if self.isolated_context:
|
||||
context = context.new()
|
||||
|
@ -457,10 +401,7 @@ class ComponentNode(Node):
|
|||
rendered_component = component.render(context)
|
||||
|
||||
if is_dependency_middleware_active():
|
||||
return (
|
||||
RENDERED_COMMENT_TEMPLATE.format(name=resolved_component_name)
|
||||
+ rendered_component
|
||||
)
|
||||
return RENDERED_COMMENT_TEMPLATE.format(name=resolved_component_name) + rendered_component
|
||||
else:
|
||||
return rendered_component
|
||||
|
||||
|
@ -482,9 +423,7 @@ def do_component_block(parser, token):
|
|||
|
||||
bits = token.split_contents()
|
||||
bits, isolated_context = check_for_isolated_context_keyword(bits)
|
||||
component_name, context_args, context_kwargs = parse_component_with_args(
|
||||
parser, bits, "component_block"
|
||||
)
|
||||
component_name, context_args, context_kwargs = parse_component_with_args(parser, bits, "component_block")
|
||||
body: NodeList = parser.parse(parse_until=["endcomponent_block"])
|
||||
parser.delete_first_token()
|
||||
fill_nodes = ()
|
||||
|
@ -575,10 +514,7 @@ def is_whitespace_token(token):
|
|||
|
||||
|
||||
def is_block_tag_token(token, name):
|
||||
return (
|
||||
token.token_type == TokenType.BLOCK
|
||||
and token.split_contents()[0] == name
|
||||
)
|
||||
return token.token_type == TokenType.BLOCK and token.split_contents()[0] == name
|
||||
|
||||
|
||||
@register.tag(name="if_filled")
|
||||
|
@ -610,9 +546,7 @@ def do_if_filled_block(parser, token):
|
|||
slot_name, is_positive = parse_if_filled_bits(bits)
|
||||
nodelist = parser.parse(("elif_filled", "else_filled", "endif_filled"))
|
||||
branches: List[_IfSlotFilledBranchNode] = [
|
||||
IfSlotFilledConditionBranchNode(
|
||||
slot_name=slot_name, nodelist=nodelist, is_positive=is_positive
|
||||
)
|
||||
IfSlotFilledConditionBranchNode(slot_name=slot_name, nodelist=nodelist, is_positive=is_positive)
|
||||
]
|
||||
|
||||
token = parser.next_token()
|
||||
|
@ -621,13 +555,9 @@ def do_if_filled_block(parser, token):
|
|||
while token.contents.startswith("elif_filled"):
|
||||
bits = token.split_contents()
|
||||
slot_name, is_positive = parse_if_filled_bits(bits)
|
||||
nodelist: NodeList = parser.parse(
|
||||
("elif_filled", "else_filled", "endif_filled")
|
||||
)
|
||||
nodelist: NodeList = parser.parse(("elif_filled", "else_filled", "endif_filled"))
|
||||
branches.append(
|
||||
IfSlotFilledConditionBranchNode(
|
||||
slot_name=slot_name, nodelist=nodelist, is_positive=is_positive
|
||||
)
|
||||
IfSlotFilledConditionBranchNode(slot_name=slot_name, nodelist=nodelist, is_positive=is_positive)
|
||||
)
|
||||
|
||||
token = parser.next_token()
|
||||
|
@ -656,9 +586,7 @@ def parse_if_filled_bits(
|
|||
tag, args = bits[0], bits[1:]
|
||||
if tag in ("else_filled", "endif_filled"):
|
||||
if len(args) != 0:
|
||||
raise TemplateSyntaxError(
|
||||
f"Tag '{tag}' takes no arguments. Received '{' '.join(args)}'"
|
||||
)
|
||||
raise TemplateSyntaxError(f"Tag '{tag}' takes no arguments. Received '{' '.join(args)}'")
|
||||
else:
|
||||
return None, None
|
||||
if len(args) == 1:
|
||||
|
@ -669,13 +597,10 @@ def parse_if_filled_bits(
|
|||
is_positive = bool_from_string(args[1])
|
||||
else:
|
||||
raise TemplateSyntaxError(
|
||||
f"{bits[0]} tag arguments '{' '.join(args)}' do not match pattern "
|
||||
f"'<slotname> (<is_positive>)'"
|
||||
f"{bits[0]} tag arguments '{' '.join(args)}' do not match pattern " f"'<slotname> (<is_positive>)'"
|
||||
)
|
||||
if not is_wrapped_in_quotes(slot_name):
|
||||
raise TemplateSyntaxError(
|
||||
f"First argument of '{bits[0]}' must be a quoted string 'literal'."
|
||||
)
|
||||
raise TemplateSyntaxError(f"First argument of '{bits[0]}' must be a quoted string 'literal'.")
|
||||
slot_name = strip_quotes(slot_name)
|
||||
return slot_name, is_positive
|
||||
|
||||
|
@ -691,9 +616,7 @@ class _IfSlotFilledBranchNode(Node):
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
class IfSlotFilledConditionBranchNode(
|
||||
_IfSlotFilledBranchNode, TemplateAwareNodeMixin
|
||||
):
|
||||
class IfSlotFilledConditionBranchNode(_IfSlotFilledBranchNode, TemplateAwareNodeMixin):
|
||||
def __init__(
|
||||
self,
|
||||
slot_name: str,
|
||||
|
@ -706,9 +629,7 @@ class IfSlotFilledConditionBranchNode(
|
|||
|
||||
def evaluate(self, context) -> bool:
|
||||
try:
|
||||
filled_slots: FilledSlotsContext = context[
|
||||
FILLED_SLOTS_CONTENT_CONTEXT_KEY
|
||||
]
|
||||
filled_slots: FilledSlotsContext = context[FILLED_SLOTS_CONTENT_CONTEXT_KEY]
|
||||
except KeyError:
|
||||
raise TemplateSyntaxError(
|
||||
f"Attempted to render {type(self).__name__} outside a Component rendering context."
|
||||
|
@ -777,9 +698,7 @@ def parse_component_with_args(parser, bits, tag_name):
|
|||
)
|
||||
|
||||
if tag_name != tag_args[0].token:
|
||||
raise RuntimeError(
|
||||
f"Internal error: Expected tag_name to be {tag_name}, but it was {tag_args[0].token}"
|
||||
)
|
||||
raise RuntimeError(f"Internal error: Expected tag_name to be {tag_name}, but it was {tag_args[0].token}")
|
||||
if len(tag_args) > 1:
|
||||
# At least one position arg, so take the first as the component name
|
||||
component_name = tag_args[1].token
|
||||
|
@ -791,9 +710,7 @@ def parse_component_with_args(parser, bits, tag_name):
|
|||
context_args = []
|
||||
context_kwargs = tag_kwargs
|
||||
except IndexError:
|
||||
raise TemplateSyntaxError(
|
||||
f"Call the '{tag_name}' tag with a component name as the first parameter"
|
||||
)
|
||||
raise TemplateSyntaxError(f"Call the '{tag_name}' tag with a component name as the first parameter")
|
||||
|
||||
return component_name, context_args, context_kwargs
|
||||
|
||||
|
@ -801,11 +718,7 @@ def parse_component_with_args(parser, bits, tag_name):
|
|||
def safe_resolve(context_item, context):
|
||||
"""Resolve FilterExpressions and Variables in context if possible. Return other items unchanged."""
|
||||
|
||||
return (
|
||||
context_item.resolve(context)
|
||||
if hasattr(context_item, "resolve")
|
||||
else context_item
|
||||
)
|
||||
return context_item.resolve(context) if hasattr(context_item, "resolve") else context_item
|
||||
|
||||
|
||||
def is_wrapped_in_quotes(s):
|
||||
|
@ -813,9 +726,7 @@ def is_wrapped_in_quotes(s):
|
|||
|
||||
|
||||
def is_dependency_middleware_active():
|
||||
return getattr(settings, "COMPONENTS", {}).get(
|
||||
"RENDER_DEPENDENCIES", False
|
||||
)
|
||||
return getattr(settings, "COMPONENTS", {}).get("RENDER_DEPENDENCIES", False)
|
||||
|
||||
|
||||
def norm_and_validate_name(name: str, tag: str, context: Optional[str] = None):
|
||||
|
@ -826,10 +737,7 @@ def norm_and_validate_name(name: str, tag: str, context: Optional[str] = None):
|
|||
name = strip_quotes(name)
|
||||
if not name.isidentifier():
|
||||
context = f" in '{context}'" if context else ""
|
||||
raise TemplateSyntaxError(
|
||||
f"{tag} name '{name}'{context} "
|
||||
"is not a valid Python identifier."
|
||||
)
|
||||
raise TemplateSyntaxError(f"{tag} name '{name}'{context} " "is not a valid Python identifier.")
|
||||
return name
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue