diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 784cf69d..3ff02078 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,4 +11,4 @@ repos: rev: 7.0.0 hooks: - id: flake8 - + additional_dependencies: [flake8-pyproject] diff --git a/benchmarks/component_rendering.py b/benchmarks/component_rendering.py index cdd5c009..98b48828 100644 --- a/benchmarks/component_rendering.py +++ b/benchmarks/component_rendering.py @@ -4,10 +4,7 @@ from django.template import Context, Template from django.test import override_settings from django_components import component -from django_components.middleware import ( - CSS_DEPENDENCY_PLACEHOLDER, - JS_DEPENDENCY_PLACEHOLDER, -) +from django_components.middleware import CSS_DEPENDENCY_PLACEHOLDER, JS_DEPENDENCY_PLACEHOLDER from tests.django_test_setup import * # NOQA from tests.testutils import Django30CompatibleSimpleTestCase as SimpleTestCase from tests.testutils import create_and_process_template_response @@ -75,9 +72,7 @@ class RenderBenchmarks(SimpleTestCase): component.registry.clear() component.registry.register("test_component", SlottedComponent) component.registry.register("inner_component", SimpleComponent) - component.registry.register( - "breadcrumb_component", BreadcrumbComponent - ) + component.registry.register("breadcrumb_component", BreadcrumbComponent) @staticmethod def timed_loop(func, iterations=1000): @@ -91,22 +86,28 @@ class RenderBenchmarks(SimpleTestCase): def test_render_time_for_small_component(self): template = Template( - "{% load component_tags %}{% component_block 'test_component' %}" - "{% slot \"header\" %}{% component_block 'inner_component' variable='foo' %}{% endslot %}{% endcomponent_block %}" - "{% endcomponent_block %}", - name="root", + """ + {% load component_tags %} + {% component_block 'test_component' %} + {% slot "header" %} + {% component_block 'inner_component' variable='foo' %}{% endcomponent_block %} + {% endslot %} + {% endcomponent_block %} + """ ) - print( - f"{self.timed_loop(lambda: template.render(Context({})))} ms per iteration" - ) + print(f"{self.timed_loop(lambda: template.render(Context({})))} ms per iteration") def test_middleware_time_with_dependency_for_small_page(self): template = Template( - "{% load component_tags %}{% component_dependencies %}" - "{% component_block 'test_component' %}{% slot \"header\" %}" - "{% component_block 'inner_component' variable='foo' %}{% endslot %}{% endcomponent_block %}{% endcomponent_block %}", - name="root", + """ + {% load component_tags %}{% component_dependencies %} + {% component_block 'test_component' %} + {% slot "header" %} + {% component_block 'inner_component' variable='foo' %}{% endcomponent_block %} + {% endslot %} + {% endcomponent_block %} + """ ) # Sanity tests response_content = create_and_process_template_response(template) @@ -116,15 +117,9 @@ class RenderBenchmarks(SimpleTestCase): self.assertIn("script.js", response_content) without_middleware = self.timed_loop( - lambda: create_and_process_template_response( - template, use_middleware=False - ) - ) - with_middleware = self.timed_loop( - lambda: create_and_process_template_response( - template, use_middleware=True - ) + lambda: create_and_process_template_response(template, use_middleware=False) ) + with_middleware = self.timed_loop(lambda: create_and_process_template_response(template, use_middleware=True)) print("Small page middleware test") self.report_results(with_middleware, without_middleware) @@ -140,14 +135,10 @@ class RenderBenchmarks(SimpleTestCase): self.assertIn("test.js", response_content) without_middleware = self.timed_loop( - lambda: create_and_process_template_response( - template, {}, use_middleware=False - ) + lambda: create_and_process_template_response(template, {}, use_middleware=False) ) with_middleware = self.timed_loop( - lambda: create_and_process_template_response( - template, {}, use_middleware=True - ) + lambda: create_and_process_template_response(template, {}, use_middleware=True) ) print("Large page middleware test") @@ -156,15 +147,9 @@ class RenderBenchmarks(SimpleTestCase): @staticmethod def report_results(with_middleware, without_middleware): print(f"Middleware active\t\t{with_middleware:.3f} ms per iteration") - print( - f"Middleware inactive\t{without_middleware:.3f} ms per iteration" - ) + print(f"Middleware inactive\t{without_middleware:.3f} ms per iteration") time_difference = with_middleware - without_middleware if without_middleware > with_middleware: - print( - f"Decrease of {-100 * time_difference / with_middleware:.2f}%" - ) + print(f"Decrease of {-100 * time_difference / with_middleware:.2f}%") else: - print( - f"Increase of {100 * time_difference / without_middleware:.2f}%" - ) + print(f"Increase of {100 * time_difference / without_middleware:.2f}%") diff --git a/django_components/app_settings.py b/django_components/app_settings.py index 30daeab9..d4550e98 100644 --- a/django_components/app_settings.py +++ b/django_components/app_settings.py @@ -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() diff --git a/django_components/component.py b/django_components/component.py index 0bbf905d..2aa0ff1f 100644 --- a/django_components/component.py +++ b/django_components/component.py @@ -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) diff --git a/django_components/component_registry.py b/django_components/component_registry.py index eb983276..209592d7 100644 --- a/django_components/component_registry.py +++ b/django_components/component_registry.py @@ -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): diff --git a/django_components/management/commands/startcomponent.py b/django_components/management/commands/startcomponent.py index 746c5e9c..6054ebbd 100644 --- a/django_components/management/commands/startcomponent.py +++ b/django_components/management/commands/startcomponent.py @@ -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"""
value=1;calls=1
', rendered - ) + self.assertEqual(rendered, 'value=1;calls=1
', rendered) def test_one_context_call_with_simple_component_and_arg(self): template = Template( @@ -354,31 +302,21 @@ class ContextCalledOnceTests(SimpleTestCase): ) rendered = template.render(Context()).strip() - self.assertEqual( - rendered, 'value=3;calls=1
', rendered - ) + self.assertEqual(rendered, 'value=3;calls=1
', rendered) def test_one_context_call_with_component_block(self): - template = Template( - "{% load component_tags %}" - "{% component_block 'incrementer' %}{% endcomponent_block %}" - ) + template = Template("{% load component_tags %}" "{% component_block 'incrementer' %}{% endcomponent_block %}") rendered = template.render(Context()).strip() - self.assertEqual( - rendered, 'value=1;calls=1
', rendered - ) + self.assertEqual(rendered, 'value=1;calls=1
', rendered) def test_one_context_call_with_component_block_and_arg(self): template = Template( - "{% load component_tags %}" - "{% component_block 'incrementer' value='3' %}{% endcomponent_block %}" + "{% load component_tags %}" "{% component_block 'incrementer' value='3' %}{% endcomponent_block %}" ) rendered = template.render(Context()).strip() - self.assertEqual( - rendered, 'value=4;calls=1
', rendered - ) + self.assertEqual(rendered, 'value=4;calls=1
', rendered) def test_one_context_call_with_slot(self): template = Template( @@ -415,9 +353,7 @@ class ComponentsCanAccessOuterContext(SimpleTestCase): "{% load component_tags %}{% component_dependencies %}" "{% component_block 'simple_component' %}{% endcomponent_block %}" ) - rendered = template.render( - Context({"variable": "outer_value"}) - ).strip() + rendered = template.render(Context({"variable": "outer_value"})).strip() self.assertIn("outer_value", rendered, rendered) @@ -427,9 +363,7 @@ class IsolatedContextTests(SimpleTestCase): "{% load component_tags %}{% component_dependencies %}" "{% component_block 'simple_component' variable only %}{% endcomponent_block %}" ) - rendered = template.render( - Context({"variable": "outer_value"}) - ).strip() + rendered = template.render(Context({"variable": "outer_value"})).strip() self.assertIn("outer_value", rendered, rendered) def test_simple_component_cannot_use_outer_context(self): @@ -437,9 +371,7 @@ class IsolatedContextTests(SimpleTestCase): "{% load component_tags %}{% component_dependencies %}" "{% component_block 'simple_component' only %}{% endcomponent_block %}" ) - rendered = template.render( - Context({"variable": "outer_value"}) - ).strip() + rendered = template.render(Context({"variable": "outer_value"})).strip() self.assertNotIn("outer_value", rendered, rendered) @@ -504,9 +436,7 @@ class OuterContextPropertyTests(SimpleTestCase): "{% load component_tags %}{% component_dependencies %}" "{% component_block 'outer_context_component' only %}{% endcomponent_block %}" ) - rendered = template.render( - Context({"variable": "outer_value"}) - ).strip() + rendered = template.render(Context({"variable": "outer_value"})).strip() self.assertIn("outer_value", rendered, rendered) def test_outer_context_property_with_component_block(self): @@ -514,7 +444,5 @@ class OuterContextPropertyTests(SimpleTestCase): "{% load component_tags %}{% component_dependencies %}" "{% component_block 'outer_context_component' only %}{% endcomponent_block %}" ) - rendered = template.render( - Context({"variable": "outer_value"}) - ).strip() + rendered = template.render(Context({"variable": "outer_value"})).strip() self.assertIn("outer_value", rendered, rendered) diff --git a/tests/test_dependency_rendering.py b/tests/test_dependency_rendering.py index ecae89e3..83c8514c 100644 --- a/tests/test_dependency_rendering.py +++ b/tests/test_dependency_rendering.py @@ -52,9 +52,7 @@ class ComponentMediaRenderingTests(SimpleTestCase): def test_no_dependencies_when_no_components_used(self): component.registry.register(name="test", component=SimpleComponent) - template = Template( - "{% load component_tags %}{% component_dependencies %}" - ) + template = Template("{% load component_tags %}{% component_dependencies %}") rendered = create_and_process_template_response(template) self.assertInHTML('