diff --git a/CHANGELOG.md b/CHANGELOG.md index 4438ce55..060a9cfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,16 @@ Using the following categories, list your changes in this order: - Nothing (yet)! +## [3.3.1] - 2023-08-08 + +### Added + +- Additional system checks for ReactPy misconfigurations. + +### Changed + +- `REACTPY_BACKHAUL_THREAD` now defaults to `False`. + ## [3.3.0] - 2023-08-05 ### Added @@ -313,7 +323,8 @@ Using the following categories, list your changes in this order: - Support for IDOM within the Django -[unreleased]: https://github.com/reactive-python/reactpy-django/compare/3.3.0...HEAD +[unreleased]: https://github.com/reactive-python/reactpy-django/compare/3.3.1...HEAD +[3.3.1]: https://github.com/reactive-python/reactpy-django/compare/3.3.0...3.3.1 [3.3.0]: https://github.com/reactive-python/reactpy-django/compare/3.2.1...3.3.0 [3.2.1]: https://github.com/reactive-python/reactpy-django/compare/3.2.0...3.2.1 [3.2.0]: https://github.com/reactive-python/reactpy-django/compare/3.1.0...3.2.0 diff --git a/docs/python/auth-required-attribute.py b/docs/python/auth-required-attribute.py index eaef7aec..51c806ac 100644 --- a/docs/python/auth-required-attribute.py +++ b/docs/python/auth-required-attribute.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.decorators import auth_required diff --git a/docs/python/auth-required-component-fallback.py b/docs/python/auth-required-component-fallback.py index 4d134eca..97e5d057 100644 --- a/docs/python/auth-required-component-fallback.py +++ b/docs/python/auth-required-component-fallback.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.decorators import auth_required diff --git a/docs/python/auth-required-custom-attribute.py b/docs/python/auth-required-custom-attribute.py index ad38011c..84452a22 100644 --- a/docs/python/auth-required-custom-attribute.py +++ b/docs/python/auth-required-custom-attribute.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.decorators import auth_required diff --git a/docs/python/auth-required-vdom-fallback.py b/docs/python/auth-required-vdom-fallback.py index c1a6ae3e..7da20fb6 100644 --- a/docs/python/auth-required-vdom-fallback.py +++ b/docs/python/auth-required-vdom-fallback.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.decorators import auth_required diff --git a/docs/python/auth-required.py b/docs/python/auth-required.py index 57337a65..18416503 100644 --- a/docs/python/auth-required.py +++ b/docs/python/auth-required.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.decorators import auth_required diff --git a/docs/python/configure-asgi-middleware.py b/docs/python/configure-asgi-middleware.py index 0ee33a8a..3e8e6523 100644 --- a/docs/python/configure-asgi-middleware.py +++ b/docs/python/configure-asgi-middleware.py @@ -1,9 +1,7 @@ # Broken load order, only used for linting from channels.routing import ProtocolTypeRouter, URLRouter - from reactpy_django import REACTPY_WEBSOCKET_PATH - django_asgi_app = "" @@ -11,7 +9,6 @@ from channels.auth import AuthMiddlewareStack # noqa: E402 from channels.sessions import SessionMiddlewareStack # noqa: E402 - application = ProtocolTypeRouter( { "http": django_asgi_app, diff --git a/docs/python/configure-asgi.py b/docs/python/configure-asgi.py index 6ae7cf8a..b574c684 100644 --- a/docs/python/configure-asgi.py +++ b/docs/python/configure-asgi.py @@ -2,7 +2,6 @@ from django.core.asgi import get_asgi_application - # Ensure DJANGO_SETTINGS_MODULE is set properly based on your project name! os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example_project.settings") @@ -11,10 +10,8 @@ from channels.routing import ProtocolTypeRouter, URLRouter # noqa: E402 - from reactpy_django import REACTPY_WEBSOCKET_PATH # noqa: E402 - application = ProtocolTypeRouter( { "http": django_asgi_app, diff --git a/docs/python/configure-urls.py b/docs/python/configure-urls.py index 49ae5ec1..1f57e843 100644 --- a/docs/python/configure-urls.py +++ b/docs/python/configure-urls.py @@ -1,6 +1,5 @@ from django.urls import include, path - urlpatterns = [ ..., path("reactpy/", include("reactpy_django.http.urls")), diff --git a/docs/python/django-css.py b/docs/python/django-css.py index c7f60881..aeb4addb 100644 --- a/docs/python/django-css.py +++ b/docs/python/django-css.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.components import django_css diff --git a/docs/python/django-js.py b/docs/python/django-js.py index 37868184..b4af014c 100644 --- a/docs/python/django-js.py +++ b/docs/python/django-js.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.components import django_js diff --git a/docs/python/django-query-postprocessor.py b/docs/python/django-query-postprocessor.py index ecb95ed8..ff7419b5 100644 --- a/docs/python/django-query-postprocessor.py +++ b/docs/python/django-query-postprocessor.py @@ -1,6 +1,5 @@ from example.models import TodoItem from reactpy import component - from reactpy_django.hooks import use_query from reactpy_django.types import QueryOptions from reactpy_django.utils import django_query_postprocessor diff --git a/docs/python/example/urls.py b/docs/python/example/urls.py index e3d7175d..74f72806 100644 --- a/docs/python/example/urls.py +++ b/docs/python/example/urls.py @@ -1,7 +1,6 @@ from django.urls import path from example import views - urlpatterns = [ path("example/", views.index), ] diff --git a/docs/python/settings.py b/docs/python/settings.py index 7454818d..d5cfc4ae 100644 --- a/docs/python/settings.py +++ b/docs/python/settings.py @@ -29,4 +29,4 @@ # Whether to enable rendering ReactPy via a dedicated backhaul thread # This allows the webserver to process traffic while during ReactPy rendering -REACTPY_BACKHAUL_THREAD = True +REACTPY_BACKHAUL_THREAD = False diff --git a/docs/python/use-connection.py b/docs/python/use-connection.py index 6050e744..ff158f95 100644 --- a/docs/python/use-connection.py +++ b/docs/python/use-connection.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.hooks import use_connection diff --git a/docs/python/use-location.py b/docs/python/use-location.py index 42303b64..18611789 100644 --- a/docs/python/use-location.py +++ b/docs/python/use-location.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.hooks import use_location diff --git a/docs/python/use-mutation-args-kwargs.py b/docs/python/use-mutation-args-kwargs.py index 19453aba..e7166806 100644 --- a/docs/python/use-mutation-args-kwargs.py +++ b/docs/python/use-mutation-args-kwargs.py @@ -1,5 +1,4 @@ from reactpy import component - from reactpy_django.hooks import use_mutation diff --git a/docs/python/use-mutation-query-refetch.py b/docs/python/use-mutation-query-refetch.py index c3651e4f..1371c869 100644 --- a/docs/python/use-mutation-query-refetch.py +++ b/docs/python/use-mutation-query-refetch.py @@ -1,6 +1,5 @@ from example.models import TodoItem from reactpy import component, html - from reactpy_django.hooks import use_mutation, use_query diff --git a/docs/python/use-mutation-reset.py b/docs/python/use-mutation-reset.py index 874cb002..f5ed568b 100644 --- a/docs/python/use-mutation-reset.py +++ b/docs/python/use-mutation-reset.py @@ -1,6 +1,5 @@ from example.models import TodoItem from reactpy import component, html - from reactpy_django.hooks import use_mutation diff --git a/docs/python/use-mutation.py b/docs/python/use-mutation.py index 80a698d8..7c5c94fd 100644 --- a/docs/python/use-mutation.py +++ b/docs/python/use-mutation.py @@ -1,6 +1,5 @@ from example.models import TodoItem from reactpy import component, html - from reactpy_django.hooks import use_mutation @@ -10,11 +9,12 @@ def add_item(text: str): @component def todo_list(): + item_mutation = use_mutation(add_item) + def submit_event(event): if event["key"] == "Enter": item_mutation.execute(text=event["target"]["value"]) - item_mutation = use_mutation(add_item) if item_mutation.loading: mutation_status = html.h2("Adding...") elif item_mutation.error: diff --git a/docs/python/use-origin.py b/docs/python/use-origin.py index 6908fb17..d21947c1 100644 --- a/docs/python/use-origin.py +++ b/docs/python/use-origin.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.hooks import use_origin diff --git a/docs/python/use-query-args.py b/docs/python/use-query-args.py index b2c705de..60e8851a 100644 --- a/docs/python/use-query-args.py +++ b/docs/python/use-query-args.py @@ -1,5 +1,4 @@ from reactpy import component - from reactpy_django.hooks import use_query diff --git a/docs/python/use-query-async.py b/docs/python/use-query-async.py index 3b532fc5..e546ed59 100644 --- a/docs/python/use-query-async.py +++ b/docs/python/use-query-async.py @@ -1,7 +1,6 @@ from channels.db import database_sync_to_async from example.models import TodoItem from reactpy import component, html - from reactpy_django.hooks import use_query diff --git a/docs/python/use-query-postprocessor-change.py b/docs/python/use-query-postprocessor-change.py index 0c3f552a..c331285e 100644 --- a/docs/python/use-query-postprocessor-change.py +++ b/docs/python/use-query-postprocessor-change.py @@ -1,5 +1,4 @@ from reactpy import component - from reactpy_django.hooks import use_query from reactpy_django.types import QueryOptions diff --git a/docs/python/use-query-postprocessor-disable.py b/docs/python/use-query-postprocessor-disable.py index 722366f8..32e981f1 100644 --- a/docs/python/use-query-postprocessor-disable.py +++ b/docs/python/use-query-postprocessor-disable.py @@ -1,5 +1,4 @@ from reactpy import component - from reactpy_django.hooks import use_query from reactpy_django.types import QueryOptions diff --git a/docs/python/use-query-postprocessor-kwargs.py b/docs/python/use-query-postprocessor-kwargs.py index 39f0f965..b11eb2b5 100644 --- a/docs/python/use-query-postprocessor-kwargs.py +++ b/docs/python/use-query-postprocessor-kwargs.py @@ -1,6 +1,5 @@ from example.models import TodoItem from reactpy import component - from reactpy_django.hooks import use_query from reactpy_django.types import QueryOptions diff --git a/docs/python/use-query-thread-sensitive.py b/docs/python/use-query-thread-sensitive.py index ab806bf4..9af19f2b 100644 --- a/docs/python/use-query-thread-sensitive.py +++ b/docs/python/use-query-thread-sensitive.py @@ -1,5 +1,4 @@ from reactpy import component - from reactpy_django.hooks import use_query from reactpy_django.types import QueryOptions diff --git a/docs/python/use-query.py b/docs/python/use-query.py index 9a15c525..a8ed8b46 100644 --- a/docs/python/use-query.py +++ b/docs/python/use-query.py @@ -1,6 +1,5 @@ from example.models import TodoItem from reactpy import component, html - from reactpy_django.hooks import use_query diff --git a/docs/python/use-scope.py b/docs/python/use-scope.py index 07f12aad..7bb34f70 100644 --- a/docs/python/use-scope.py +++ b/docs/python/use-scope.py @@ -1,5 +1,4 @@ from reactpy import component, html - from reactpy_django.hooks import use_scope diff --git a/docs/python/vtc-args-kwargs.py b/docs/python/vtc-args-kwargs.py index c9187415..e4973e6b 100644 --- a/docs/python/vtc-args-kwargs.py +++ b/docs/python/vtc-args-kwargs.py @@ -1,6 +1,5 @@ from django.http import HttpResponse from reactpy import component, html - from reactpy_django.components import view_to_component diff --git a/docs/python/vtc-cbv-compatibility.py b/docs/python/vtc-cbv-compatibility.py index 9667562c..aa616cf8 100644 --- a/docs/python/vtc-cbv-compatibility.py +++ b/docs/python/vtc-cbv-compatibility.py @@ -1,7 +1,6 @@ from django.contrib.auth.decorators import user_passes_test from django.utils.decorators import method_decorator from django.views.generic import TemplateView - from reactpy_django.components import view_to_component diff --git a/docs/python/vtc-cbv.py b/docs/python/vtc-cbv.py index d9b5ed29..a0b2fe45 100644 --- a/docs/python/vtc-cbv.py +++ b/docs/python/vtc-cbv.py @@ -1,7 +1,6 @@ from django.http import HttpResponse from django.views import View from reactpy import component, html - from reactpy_django.components import view_to_component diff --git a/docs/python/vtc-compatibility.py b/docs/python/vtc-compatibility.py index 337096b7..93d15536 100644 --- a/docs/python/vtc-compatibility.py +++ b/docs/python/vtc-compatibility.py @@ -1,6 +1,5 @@ from django.http import HttpResponse from reactpy import component, html - from reactpy_django.components import view_to_component diff --git a/docs/python/vtc-fbv-compat.py b/docs/python/vtc-fbv-compat.py index 3cb8016c..6ef3e40a 100644 --- a/docs/python/vtc-fbv-compat.py +++ b/docs/python/vtc-fbv-compat.py @@ -1,5 +1,4 @@ from django.contrib.auth.decorators import user_passes_test - from reactpy_django.components import view_to_component diff --git a/docs/python/vtc-func.py b/docs/python/vtc-func.py index f7f9582e..82f1bcd0 100644 --- a/docs/python/vtc-func.py +++ b/docs/python/vtc-func.py @@ -1,9 +1,7 @@ from example.views import example_view from reactpy import component, html - from reactpy_django.components import view_to_component - example_vtc = view_to_component(example_view) diff --git a/docs/python/vtc-request.py b/docs/python/vtc-request.py index 9eff206c..cf3d3cb0 100644 --- a/docs/python/vtc-request.py +++ b/docs/python/vtc-request.py @@ -1,9 +1,7 @@ from django.http import HttpRequest, HttpResponse from reactpy import component, html - from reactpy_django.components import view_to_component - example_request = HttpRequest() example_request.method = "PUT" diff --git a/docs/python/vtc-strict-parsing.py b/docs/python/vtc-strict-parsing.py index 1946ca93..d4da513c 100644 --- a/docs/python/vtc-strict-parsing.py +++ b/docs/python/vtc-strict-parsing.py @@ -1,6 +1,5 @@ from django.http import HttpResponse from reactpy import component, html - from reactpy_django.components import view_to_component diff --git a/docs/python/vtc-transforms.py b/docs/python/vtc-transforms.py index 4c3ba446..3d8c716a 100644 --- a/docs/python/vtc-transforms.py +++ b/docs/python/vtc-transforms.py @@ -1,6 +1,5 @@ from django.http import HttpResponse from reactpy import component, html - from reactpy_django.components import view_to_component diff --git a/docs/python/vtc.py b/docs/python/vtc.py index 47618afc..92fea793 100644 --- a/docs/python/vtc.py +++ b/docs/python/vtc.py @@ -1,6 +1,5 @@ from django.http import HttpResponse from reactpy import component, html - from reactpy_django.components import view_to_component diff --git a/src/reactpy_django/__init__.py b/src/reactpy_django/__init__.py index 36483154..de84506e 100644 --- a/src/reactpy_django/__init__.py +++ b/src/reactpy_django/__init__.py @@ -1,7 +1,7 @@ from reactpy_django import checks, components, decorators, hooks, types, utils from reactpy_django.websocket.paths import REACTPY_WEBSOCKET_PATH -__version__ = "3.3.0" +__version__ = "3.3.1" __all__ = [ "REACTPY_WEBSOCKET_PATH", "hooks", diff --git a/src/reactpy_django/checks.py b/src/reactpy_django/checks.py index 03955950..b60be689 100644 --- a/src/reactpy_django/checks.py +++ b/src/reactpy_django/checks.py @@ -2,6 +2,7 @@ from django.contrib.staticfiles.finders import find from django.core.checks import Error, Tags, Warning, register +from django.template import loader @register(Tags.compatibility) @@ -48,7 +49,7 @@ def reactpy_warnings(app_configs, **kwargs): if ( sys.argv and sys.argv[0].endswith("daphne") - and getattr(settings, "REACTPY_BACKHAUL_THREAD", True) + and getattr(settings, "REACTPY_BACKHAUL_THREAD", False) and sys.platform == "linux" ): warnings.append( @@ -76,11 +77,47 @@ def reactpy_warnings(app_configs, **kwargs): Warning( "ReactPy failed to register the following components:\n\t+ " + "\n\t+ ".join(REACTPY_FAILED_COMPONENTS), - hint="Check if these paths are valid, or if an exception is being raised during import.", + hint="Check if these paths are valid, or if an exception is being " + "raised during import.", id="reactpy_django.W005", ) ) + # Check if the reactpy/component.html template exists + try: + loader.get_template("reactpy/component.html") + except Exception: + warnings.append( + Warning( + "ReactPy HTML templates could not be found!", + hint="Check your settings.py:TEMPLATES configuration and make sure " + "ReactPy-Django is installed properly.", + id="reactpy_django.W006", + ) + ) + + # Check if REACTPY_WEBSOCKET_URL doesn't end with a slash + REACTPY_WEBSOCKET_URL = getattr(settings, "REACTPY_WEBSOCKET_URL", "") + if isinstance(REACTPY_WEBSOCKET_URL, str): + if not REACTPY_WEBSOCKET_URL or not REACTPY_WEBSOCKET_URL.endswith("/"): + warnings.append( + Warning( + "REACTPY_WEBSOCKET_URL did not end with a forward slash.", + hint="Change your URL to be written in the following format: 'example_url/'", + id="reactpy_django.W007", + ) + ) + + # Check if REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character + if not REACTPY_WEBSOCKET_URL or not REACTPY_WEBSOCKET_URL[0].isalnum(): + warnings.append( + Warning( + "REACTPY_WEBSOCKET_URL did not start with an alphanumeric character.", + hint="Change your URL to be written in the following format: 'example_url/'", + id="reactpy_django.W008", + ) + ) + return warnings diff --git a/src/reactpy_django/config.py b/src/reactpy_django/config.py index ab9bebfb..c0ee14be 100644 --- a/src/reactpy_django/config.py +++ b/src/reactpy_django/config.py @@ -61,5 +61,5 @@ REACTPY_BACKHAUL_THREAD: bool = getattr( settings, "REACTPY_BACKHAUL_THREAD", - True, + False, ) diff --git a/src/reactpy_django/hooks.py b/src/reactpy_django/hooks.py index e9f80908..c60bbf1c 100644 --- a/src/reactpy_django/hooks.py +++ b/src/reactpy_django/hooks.py @@ -32,7 +32,6 @@ ) from reactpy_django.utils import generate_obj_name - _logger = logging.getLogger(__name__) _REFETCH_CALLBACKS: DefaultDict[ Callable[..., Any], set[Callable[[], None]] diff --git a/src/reactpy_django/http/urls.py b/src/reactpy_django/http/urls.py index a44aeb71..05bac8e5 100644 --- a/src/reactpy_django/http/urls.py +++ b/src/reactpy_django/http/urls.py @@ -2,7 +2,6 @@ from . import views - app_name = "reactpy" urlpatterns = [ diff --git a/src/reactpy_django/templatetags/reactpy.py b/src/reactpy_django/templatetags/reactpy.py index 20e9b0de..d8e94e2b 100644 --- a/src/reactpy_django/templatetags/reactpy.py +++ b/src/reactpy_django/templatetags/reactpy.py @@ -19,7 +19,6 @@ func_has_args, ) - REACTPY_WEB_MODULES_URL = reverse("reactpy:web_modules", args=["x"])[:-1][1:] register = template.Library() _logger = getLogger(__name__) diff --git a/src/reactpy_django/types.py b/src/reactpy_django/types.py index b02b5161..02fdec6e 100644 --- a/src/reactpy_django/types.py +++ b/src/reactpy_django/types.py @@ -20,7 +20,6 @@ from reactpy.types import Connection as _Connection from typing_extensions import ParamSpec - __all__ = [ "_Result", "_Params", diff --git a/src/reactpy_django/websocket/paths.py b/src/reactpy_django/websocket/paths.py index ab308fe9..afd410c3 100644 --- a/src/reactpy_django/websocket/paths.py +++ b/src/reactpy_django/websocket/paths.py @@ -4,7 +4,6 @@ from .consumer import ReactpyAsyncWebsocketConsumer - REACTPY_WEBSOCKET_PATH = path( f"{REACTPY_WEBSOCKET_URL}//", ReactpyAsyncWebsocketConsumer.as_asgi(),