From 36e29745768140f4642487ce7272203aec7248bf Mon Sep 17 00:00:00 2001 From: Brandon Shar <6599653+BrandonShar@users.noreply.github.com> Date: Sat, 4 Jan 2025 14:39:35 -0500 Subject: [PATCH] V2: Deprecate lazy add optional (#59) * have actions run on PRs * deprecate lazy and add optional --- .github/workflows/pytest.yml | 10 +++++++++- .gitignore | 5 ++++- README.md | 10 +++++----- inertia/__init__.py | 2 +- inertia/tests/test_rendering.py | 26 +++++++++++++++++++++----- inertia/tests/testapp/urls.py | 1 + inertia/tests/testapp/views.py | 10 +++++++++- inertia/utils.py | 13 +++++++++++++ 8 files changed, 63 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 29d4f2a..321eb47 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -1,6 +1,14 @@ name: Unit tests -on: [push] +on: + push: + branches: + - main + paths-ignore: + - '**.md' + pull_request: + paths-ignore: + - '**.md' jobs: unit-test: diff --git a/.gitignore b/.gitignore index 7300498..e93fb9d 100644 --- a/.gitignore +++ b/.gitignore @@ -160,4 +160,7 @@ cython_debug/ #.idea/ # because this is a package, we don't want to commit the lock file -poetry.lock \ No newline at end of file +poetry.lock + +.DS_Store +.tool-versions \ No newline at end of file diff --git a/README.md b/README.md index d126639..0c3b93c 100644 --- a/README.md +++ b/README.md @@ -131,25 +131,25 @@ def external(): It will generate a `409 Conflict` response and include the destination URL in the `X-Inertia-Location` header. When this response is received client-side, Inertia will automatically perform a `window.location = url` visit. -### Lazy Props +### Optional Props On the front end, Inertia supports the concept of "partial reloads" where only the props requested -are returned by the server. Sometimes, you may want to use this flow to avoid processing a particularly slow prop on the intial load. In this case, you can use `Lazy props`. Lazy props aren't evaluated unless they're specifically requested by name in a partial reload. +are returned by the server. Sometimes, you may want to use this flow to avoid processing a particularly slow prop on the intial load. In this case, you can use `Optional props`. Optional props aren't evaluated unless they're specifically requested by name in a partial reload. ```python -from inertia import lazy, inertia +from inertia import optional, inertia @inertia('ExampleComponent') def example(request): return { 'name': lambda: 'Brandon', # this will be rendered on the first load as usual - 'data': lazy(lambda: some_long_calculation()), # this will only be run when specifically requested by partial props and WILL NOT be included on the initial load + 'data': optional(lambda: some_long_calculation()), # this will only be run when specifically requested by partial props and WILL NOT be included on the initial load } ``` ### Deferred Props -As of version 2.0, Inertia supports the ability to defer the fetching of props until after the page has been initially rendered. Essentially this is similar to the concept of `Lazy props` however Inertia provides convenient frontend components to automatically fetch the deferred props after the page has initially loaded, instead of requiring the user to initiate a reload. For more info, see [Deferred props](https://inertiajs.com/deferred-props) in the Inertia documentation. +As of version 2.0, Inertia supports the ability to defer the fetching of props until after the page has been initially rendered. Essentially this is similar to the concept of `Optional props` however Inertia provides convenient frontend components to automatically fetch the deferred props after the page has initially loaded, instead of requiring the user to initiate a reload. For more info, see [Deferred props](https://inertiajs.com/deferred-props) in the Inertia documentation. To mark props as deferred on the server side use the `defer` function. diff --git a/inertia/__init__.py b/inertia/__init__.py index 4f91952..4c1ea06 100644 --- a/inertia/__init__.py +++ b/inertia/__init__.py @@ -1,3 +1,3 @@ from .http import inertia, render, location -from .utils import lazy, defer +from .utils import lazy, optional, defer from .share import share diff --git a/inertia/tests/test_rendering.py b/inertia/tests/test_rendering.py index 89b93f0..c7d3a79 100644 --- a/inertia/tests/test_rendering.py +++ b/inertia/tests/test_rendering.py @@ -1,4 +1,5 @@ from inertia.test import InertiaTestCase, inertia_div, inertia_page +from pytest import warns class FirstLoadTestCase(InertiaTestCase): def test_with_props(self): @@ -74,15 +75,30 @@ def test_redirects_from_inertia_views(self): class LazyPropsTestCase(InertiaTestCase): def test_lazy_props_are_not_included(self): + with warns(DeprecationWarning): + self.assertJSONResponse( + self.inertia.get('/lazy/'), + inertia_page('lazy', props={'name': 'Brian'}) + ) + + def test_lazy_props_are_included_when_requested(self): + with warns(DeprecationWarning): + self.assertJSONResponse( + self.inertia.get('/lazy/', HTTP_X_INERTIA_PARTIAL_DATA='sport,grit', HTTP_X_INERTIA_PARTIAL_COMPONENT='TestComponent'), + inertia_page('lazy', props={'sport': 'Basketball', 'grit': 'intense'}) + ) + +class OptionalPropsTestCase(InertiaTestCase): + def test_optional_props_are_not_included(self): self.assertJSONResponse( - self.inertia.get('/lazy/'), - inertia_page('lazy', props={'name': 'Brian'}) + self.inertia.get('/optional/'), + inertia_page('optional', props={'name': 'Brian'}) ) - def test_lazy_props_are_included_when_requested(self): + def test_optional_props_are_included_when_requested(self): self.assertJSONResponse( - self.inertia.get('/lazy/', HTTP_X_INERTIA_PARTIAL_DATA='sport,grit', HTTP_X_INERTIA_PARTIAL_COMPONENT='TestComponent'), - inertia_page('lazy', props={'sport': 'Basketball', 'grit': 'intense'}) + self.inertia.get('/optional/', HTTP_X_INERTIA_PARTIAL_DATA='sport,grit', HTTP_X_INERTIA_PARTIAL_COMPONENT='TestComponent'), + inertia_page('optional', props={'sport': 'Basketball', 'grit': 'intense'}) ) class ComplexPropsTestCase(InertiaTestCase): diff --git a/inertia/tests/testapp/urls.py b/inertia/tests/testapp/urls.py index 80c352c..4d7e44a 100644 --- a/inertia/tests/testapp/urls.py +++ b/inertia/tests/testapp/urls.py @@ -8,6 +8,7 @@ path('props/', views.props_test), path('template_data/', views.template_data_test), path('lazy/', views.lazy_test), + path('optional/', views.optional_test), path('defer/', views.defer_test), path('defer-group/', views.defer_group_test), path('complex-props/', views.complex_props_test), diff --git a/inertia/tests/testapp/views.py b/inertia/tests/testapp/views.py index 1db82d8..a4f2072 100644 --- a/inertia/tests/testapp/views.py +++ b/inertia/tests/testapp/views.py @@ -1,7 +1,7 @@ from django.http.response import HttpResponse from django.shortcuts import redirect from django.utils.decorators import decorator_from_middleware -from inertia import inertia, render, lazy, defer, share, location +from inertia import inertia, render, lazy, optional, defer, share, location from inertia.http import INERTIA_SESSION_CLEAR_HISTORY, clear_history, encrypt_history class ShareMiddleware: @@ -52,6 +52,14 @@ def lazy_test(request): 'grit': lazy(lambda: 'intense'), } +@inertia('TestComponent') +def optional_test(request): + return { + 'name': 'Brian', + 'sport': optional(lambda: 'Basketball'), + 'grit': optional(lambda: 'intense'), + } + @inertia('TestComponent') def defer_test(request): return { diff --git a/inertia/utils.py b/inertia/utils.py index 93b96d4..465d61a 100644 --- a/inertia/utils.py +++ b/inertia/utils.py @@ -2,6 +2,7 @@ from django.db import models from django.db.models.query import QuerySet from django.forms.models import model_to_dict as base_model_to_dict +import warnings def model_to_dict(model): return base_model_to_dict(model, exclude=('password',)) @@ -18,10 +19,19 @@ def default(self, value): class LazyProp: def __init__(self, prop): + warnings.warn( + "lazy and LazyProp are deprecated and will be removed in a future version. Please use optional instead.", + DeprecationWarning, + stacklevel=2 + ) self.prop = prop def __call__(self): return self.prop() if callable(self.prop) else self.prop + +class OptionalProp(LazyProp): + def __init__(self, prop): + self.prop = prop class DeferredProp: def __init__(self, prop, group): @@ -34,5 +44,8 @@ def __call__(self): def lazy(prop): return LazyProp(prop) +def optional(prop): + return OptionalProp(prop) + def defer(prop, group="default"): return DeferredProp(prop, group)