Skip to content

Commit c8ec533

Browse files
authored
More intuitive channel layer hook (#284)
- Updated the interface for `reactpy.hooks.use_channel_layer` to be more intuitive. - Arguments now must be provided as keyworded arguments. - The `name` argument has been renamed to `channel`. - The `group_name` argument has been renamed to `group`. - The `group_add` and `group_discard` arguments have been removed for simplicity. - Preemptively do some changes related to reactpy v2 - Migrate `del_html_head_body_transform` from `reactpy` to `django-reactpy` - Add logging when `RESOLVED_WEB_MODULES_PATH` fails to fetch
1 parent 923e309 commit c8ec533

30 files changed

+242
-145
lines changed

.github/workflows/test-python.yml

+5-22
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ on:
1212

1313
jobs:
1414
python-source:
15-
runs-on: ubuntu-latest
15+
runs-on: ${{ matrix.operating-system }}
1616
strategy:
1717
matrix:
1818
python-version: ["3.9", "3.10", "3.11", "3.12"]
19+
settings-module: ["single_db", "multi_db"]
20+
operating-system: ["ubuntu-latest", "windows-latest"]
1921
steps:
2022
- uses: actions/checkout@v4
2123
- uses: oven-sh/setup-bun@v2
@@ -28,26 +30,7 @@ jobs:
2830
- name: Install Python Dependencies
2931
run: pip install --upgrade pip hatch uv
3032
- name: Run Single DB Tests
31-
run: hatch test --python ${{ matrix.python-version }} --ds=test_app.settings_single_db -v
32-
33-
python-source-multi-db:
34-
runs-on: ubuntu-latest
35-
strategy:
36-
matrix:
37-
python-version: ["3.9", "3.10", "3.11", "3.12"]
38-
steps:
39-
- uses: actions/checkout@v4
40-
- uses: oven-sh/setup-bun@v2
41-
with:
42-
bun-version: latest
43-
- name: Use Python ${{ matrix.python-version }}
44-
uses: actions/setup-python@v5
45-
with:
46-
python-version: ${{ matrix.python-version }}
47-
- name: Install Python Dependencies
48-
run: pip install --upgrade pip hatch uv
49-
- name: Run Multi-DB Tests
50-
run: hatch test --python ${{ matrix.python-version }} --ds=test_app.settings_multi_db -v
33+
run: hatch test --python ${{ matrix.python-version }} --ds=test_app.settings_${{matrix.settings-module}} -v
5134

5235
python-formatting:
5336
runs-on: ubuntu-latest
@@ -76,5 +59,5 @@ jobs:
7659
python-version: 3.x
7760
- name: Install Python Dependencies
7861
run: pip install --upgrade pip hatch uv
79-
- name: Check Python formatting
62+
- name: Run Python type checker
8063
run: hatch run python:type_check

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# ReactPy-Django Build Artifacts
2-
src/reactpy_django/static/reactpy_django/client.js
2+
src/reactpy_django/static/reactpy_django/index.js
3+
src/reactpy_django/static/reactpy_django/index.js.map
34
src/reactpy_django/static/reactpy_django/pyscript
45
src/reactpy_django/static/reactpy_django/morphdom
56

CHANGELOG.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ Don't forget to remove deprecated code on each major release!
1919

2020
## [Unreleased]
2121

22-
- Nothing (yet)!
22+
### Changed
23+
24+
- Updated the interface for `reactpy.hooks.use_channel_layer` to be more intuitive.
25+
- Arguments now must be provided as keyworded arguments.
26+
- The `name` argument has been renamed to `channel`.
27+
- The `group_name` argument has been renamed to `group`.
28+
- The `group_add` and `group_discard` arguments have been removed for simplicity.
2329

2430
### [5.2.1] - 2025-01-10
2531

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# <img src="https://raw.githubusercontent.com/reactive-python/reactpy/main/branding/svg/reactpy-logo-square.svg" align="left" height="45"/> ReactPy-Django
22

33
<p>
4-
<a href="https://github.com/reactive-python/reactpy-django/actions?query=workflow%3ATest">
5-
<img src="https://github.com/reactive-python/reactpy-django/workflows/Test/badge.svg?event=push">
4+
<a href="https://github.com/reactive-python/reactpy-django/actions/workflows/test-python.yml">
5+
<img src="https://github.com/reactive-python/reactpy-django/actions/workflows/test-python.yml/badge.svg">
66
</a>
77
<a href="https://pypi.python.org/pypi/reactpy-django">
88
<img src="https://img.shields.io/pypi/v/reactpy-django.svg?label=PyPI">

docs/examples/python/use_channel_layer.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@
66
@component
77
def my_component():
88
async def receive_message(message):
9-
set_message(message["text"])
9+
set_message_data(message["text"])
1010

1111
async def send_message(event):
1212
if event["key"] == "Enter":
1313
await sender({"text": event["target"]["value"]})
1414

15-
message, set_message = hooks.use_state("")
16-
sender = use_channel_layer("my-channel-name", receiver=receive_message)
15+
message_data, set_message_data = hooks.use_state("")
16+
sender = use_channel_layer(group="my-group-name", receiver=receive_message)
1717

1818
return html.div(
19-
f"Received: {message}",
19+
f"Received: {message_data}",
2020
html.br(),
2121
"Send: ",
2222
html.input({"type": "text", "onKeyDown": send_message}),

docs/examples/python/use_channel_layer_group.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
@component
77
def my_sender_component():
8-
sender = use_channel_layer(group_name="my-group-name")
8+
sender = use_channel_layer(group="my-group-name")
99

1010
async def submit_event(event):
1111
if event["key"] == "Enter":
@@ -21,10 +21,10 @@ async def submit_event(event):
2121
def my_receiver_component_1():
2222
message, set_message = hooks.use_state("")
2323

24-
async def receive_event(message):
24+
async def receive_message(message):
2525
set_message(message["text"])
2626

27-
use_channel_layer(group_name="my-group-name", receiver=receive_event)
27+
use_channel_layer(group="my-group-name", receiver=receive_message)
2828

2929
return html.div(f"Message Receiver 1: {message}")
3030

@@ -33,9 +33,9 @@ async def receive_event(message):
3333
def my_receiver_component_2():
3434
message, set_message = hooks.use_state("")
3535

36-
async def receive_event(message):
36+
async def receive_message(message):
3737
set_message(message["text"])
3838

39-
use_channel_layer(group_name="my-group-name", receiver=receive_event)
39+
use_channel_layer(group="my-group-name", receiver=receive_message)
4040

4141
return html.div(f"Message Receiver 2: {message}")

docs/examples/python/use_channel_layer_signal_receiver.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
def my_receiver_component():
88
message, set_message = hooks.use_state("")
99

10-
async def receive_event(message):
10+
async def receive_message(message):
1111
set_message(message["text"])
1212

13-
use_channel_layer("my-channel-name", receiver=receive_event)
13+
# This is defined to receive any messages from both "my-channel-name" and "my-group-name".
14+
use_channel_layer(channel="my-channel-name", group="my-group-name", receiver=receive_message)
1415

1516
return html.div(f"Message Receiver: {message}")

docs/examples/python/use_channel_layer_signal_sender.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ class ExampleModel(Model): ...
1212
def my_sender_signal(sender, instance, **kwargs):
1313
layer = get_channel_layer()
1414

15-
# Example of sending a message to a channel
16-
async_to_sync(layer.send)("my-channel-name", {"text": "Hello World!"})
17-
18-
# Example of sending a message to a group channel
15+
# EXAMPLE 1: Sending a message to a group.
16+
# Note that `group_send` requires using the `group` argument in `use_channel_layer`.
1917
async_to_sync(layer.group_send)("my-group-name", {"text": "Hello World!"})
18+
19+
# EXAMPLE 2: Sending a message to a single channel.
20+
# Note that this is typically only used for channels that use point-to-point communication
21+
async_to_sync(layer.send)("my-channel-name", {"text": "Hello World!"})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from reactpy import component, hooks, html
2+
3+
from reactpy_django.hooks import use_channel_layer
4+
5+
6+
@component
7+
def my_sender_component():
8+
sender = use_channel_layer(channel="my-channel-name")
9+
10+
async def submit_event(event):
11+
if event["key"] == "Enter":
12+
await sender({"text": event["target"]["value"]})
13+
14+
return html.div(
15+
"Message Sender: ",
16+
html.input({"type": "text", "onKeyDown": submit_event}),
17+
)
18+
19+
20+
@component
21+
def my_receiver_component():
22+
message, set_message = hooks.use_state("")
23+
24+
async def receive_message(message):
25+
set_message(message["text"])
26+
27+
use_channel_layer(channel="my-channel-name", receiver=receive_message)
28+
29+
return html.div(f"Message Receiver 1: {message}")

docs/src/about/contributing.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ By utilizing `hatch`, the following commands are available to manage the develop
5050

5151
The `hatch test` command is a wrapper for `pytest`. Hatch "intercepts" a handful of arguments, which can be previewed by typing `hatch test --help`.
5252

53-
Any additional arguments in the `test` command are directly passed on to pytest. See the [pytest documentation](https://docs.pytest.org/en/stable/reference/reference.html#command-line-flags) for what additional arguments are available.
53+
Any additional arguments in the `test` command are provided directly to pytest. See the [pytest documentation](https://docs.pytest.org/en/stable/reference/reference.html#command-line-flags) for what additional arguments are available.
5454

5555
### Linting and Formatting
5656

docs/src/learn/your-first-component.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Additionally, you can pass in `#!python args` and `#!python kwargs` into your co
6868

6969
???+ tip "Components are automatically registered!"
7070

71-
ReactPy-Django will automatically register any component that is referenced in a Django HTML template. This means you [typically](../reference/utils.md#register-component) do not need to manually register components in your **Django app**.
71+
ReactPy-Django will automatically register any component that is referenced in a Django HTML template. This means you typically do not need to [manually register](../reference/utils.md#register-component) components in your **Django app**.
7272

7373
Please note that this HTML template must be properly stored within a registered Django app. ReactPy-Django will output a console log message containing all detected components when the server starts up.
7474

docs/src/reference/components.md

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ This allows you to embedded any number of client-side PyScript components within
5858

5959
<!--pyscript-setup-required-end-->
6060

61+
{% include-markdown "./template-tag.md" start="<!--pyscript-webtypy-start-->" end="<!--pyscript-webtypy-end-->" %}
62+
6163
{% include-markdown "./template-tag.md" start="<!--pyscript-js-exec-start-->" end="<!--pyscript-js-exec-end-->" %}
6264

6365
{% include-markdown "./template-tag.md" start="<!--pyscript-multifile-start-->" end="<!--pyscript-multifile-end-->" trailing-newlines=false preserve-includer-indent=false %}

0 commit comments

Comments
 (0)