reactpy_django 3.8.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- js/node_modules/flatted/python/flatted.py +149 -0
- js/node_modules/flatted/python/test.py +63 -0
- reactpy_django/__init__.py +28 -0
- reactpy_django/apps.py +11 -0
- reactpy_django/checks.py +542 -0
- reactpy_django/clean.py +141 -0
- reactpy_django/components.py +286 -0
- reactpy_django/config.py +135 -0
- reactpy_django/database.py +31 -0
- reactpy_django/decorators.py +101 -0
- reactpy_django/exceptions.py +34 -0
- reactpy_django/hooks.py +496 -0
- reactpy_django/http/__init__.py +0 -0
- reactpy_django/http/urls.py +18 -0
- reactpy_django/http/views.py +62 -0
- reactpy_django/management/__init__.py +0 -0
- reactpy_django/management/commands/__init__.py +0 -0
- reactpy_django/management/commands/clean_reactpy.py +37 -0
- reactpy_django/migrations/0001_initial.py +25 -0
- reactpy_django/migrations/0002_rename_created_at_componentparams_last_accessed.py +17 -0
- reactpy_django/migrations/0003_componentsession_delete_componentparams.py +28 -0
- reactpy_django/migrations/0004_config.py +27 -0
- reactpy_django/migrations/0005_alter_componentsession_last_accessed.py +17 -0
- reactpy_django/migrations/0006_userdatamodel.py +28 -0
- reactpy_django/migrations/__init__.py +0 -0
- reactpy_django/models.py +48 -0
- reactpy_django/py.typed +1 -0
- reactpy_django/router/__init__.py +5 -0
- reactpy_django/router/converters.py +7 -0
- reactpy_django/router/resolvers.py +58 -0
- reactpy_django/static/reactpy_django/client.js +1630 -0
- reactpy_django/templates/reactpy/component.html +27 -0
- reactpy_django/templatetags/__init__.py +0 -0
- reactpy_django/templatetags/reactpy.py +221 -0
- reactpy_django/types.py +121 -0
- reactpy_django/utils.py +384 -0
- reactpy_django/websocket/__init__.py +0 -0
- reactpy_django/websocket/consumer.py +218 -0
- reactpy_django/websocket/paths.py +17 -0
- reactpy_django-3.8.1.dist-info/LICENSE.md +9 -0
- reactpy_django-3.8.1.dist-info/METADATA +152 -0
- reactpy_django-3.8.1.dist-info/RECORD +44 -0
- reactpy_django-3.8.1.dist-info/WHEEL +6 -0
- reactpy_django-3.8.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Generated by Django 4.2.3 on 2023-08-04 05:49
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
("reactpy_django", "0003_componentsession_delete_componentparams"),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
operations = [
|
|
12
|
+
migrations.CreateModel(
|
|
13
|
+
name="Config",
|
|
14
|
+
fields=[
|
|
15
|
+
(
|
|
16
|
+
"id",
|
|
17
|
+
models.BigAutoField(
|
|
18
|
+
auto_created=True,
|
|
19
|
+
primary_key=True,
|
|
20
|
+
serialize=False,
|
|
21
|
+
verbose_name="ID",
|
|
22
|
+
),
|
|
23
|
+
),
|
|
24
|
+
("cleaned_at", models.DateTimeField(auto_now_add=True)),
|
|
25
|
+
],
|
|
26
|
+
),
|
|
27
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Generated by Django 4.2.3 on 2023-08-23 19:56
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
("reactpy_django", "0004_config"),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
operations = [
|
|
12
|
+
migrations.AlterField(
|
|
13
|
+
model_name="componentsession",
|
|
14
|
+
name="last_accessed",
|
|
15
|
+
field=models.DateTimeField(auto_now=True),
|
|
16
|
+
),
|
|
17
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Generated by Django 4.2.5 on 2023-10-09 01:02
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
("reactpy_django", "0005_alter_componentsession_last_accessed"),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
operations = [
|
|
12
|
+
migrations.CreateModel(
|
|
13
|
+
name="UserDataModel",
|
|
14
|
+
fields=[
|
|
15
|
+
(
|
|
16
|
+
"id",
|
|
17
|
+
models.BigAutoField(
|
|
18
|
+
auto_created=True,
|
|
19
|
+
primary_key=True,
|
|
20
|
+
serialize=False,
|
|
21
|
+
verbose_name="ID",
|
|
22
|
+
),
|
|
23
|
+
),
|
|
24
|
+
("user_pk", models.CharField(max_length=255, unique=True)),
|
|
25
|
+
("data", models.BinaryField(blank=True, null=True)),
|
|
26
|
+
],
|
|
27
|
+
),
|
|
28
|
+
]
|
|
File without changes
|
reactpy_django/models.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from django.contrib.auth import get_user_model
|
|
2
|
+
from django.db import models
|
|
3
|
+
from django.db.models.signals import pre_delete
|
|
4
|
+
from django.dispatch import receiver
|
|
5
|
+
|
|
6
|
+
from reactpy_django.utils import get_pk
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ComponentSession(models.Model):
|
|
10
|
+
"""A model for storing component sessions."""
|
|
11
|
+
|
|
12
|
+
uuid = models.UUIDField(primary_key=True, editable=False, unique=True) # type: ignore
|
|
13
|
+
params = models.BinaryField(editable=False) # type: ignore
|
|
14
|
+
last_accessed = models.DateTimeField(auto_now=True) # type: ignore
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Config(models.Model):
|
|
18
|
+
"""A singleton model for storing ReactPy configuration."""
|
|
19
|
+
|
|
20
|
+
cleaned_at = models.DateTimeField(auto_now_add=True) # type: ignore
|
|
21
|
+
|
|
22
|
+
def save(self, *args, **kwargs):
|
|
23
|
+
"""Singleton save method."""
|
|
24
|
+
self.pk = 1
|
|
25
|
+
super().save(*args, **kwargs)
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def load(cls):
|
|
29
|
+
obj, _ = cls.objects.get_or_create(pk=1)
|
|
30
|
+
return obj
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class UserDataModel(models.Model):
|
|
34
|
+
"""A model for storing `user_state` data."""
|
|
35
|
+
|
|
36
|
+
# We can't store User as a ForeignKey/OneToOneField because it may not be in the same database
|
|
37
|
+
# and Django does not allow cross-database relations. Also, since we can't know the type of the UserModel PK,
|
|
38
|
+
# we store it as a string to normalize.
|
|
39
|
+
user_pk = models.CharField(max_length=255, unique=True) # type: ignore
|
|
40
|
+
data = models.BinaryField(null=True, blank=True) # type: ignore
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@receiver(pre_delete, sender=get_user_model(), dispatch_uid="reactpy_delete_user_data")
|
|
44
|
+
def delete_user_data(sender, instance, **kwargs):
|
|
45
|
+
"""Delete ReactPy's `UserDataModel` when a Django `User` is deleted."""
|
|
46
|
+
pk = get_pk(instance)
|
|
47
|
+
|
|
48
|
+
UserDataModel.objects.filter(user_pk=pk).delete()
|
reactpy_django/py.typed
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Marker file for PEP 561
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from reactpy_router.simple import ConverterMapping
|
|
7
|
+
from reactpy_router.types import Route
|
|
8
|
+
|
|
9
|
+
from reactpy_django.router.converters import CONVERTERS
|
|
10
|
+
|
|
11
|
+
PARAM_PATTERN = re.compile(r"<(?P<type>\w+:)?(?P<name>\w+)>")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# TODO: Make reactpy_router's SimpleResolver generic enough to where we don't have to define our own
|
|
15
|
+
class DjangoResolver:
|
|
16
|
+
"""A simple route resolver that uses regex to match paths"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, route: Route) -> None:
|
|
19
|
+
self.element = route.element
|
|
20
|
+
self.pattern, self.converters = parse_path(route.path)
|
|
21
|
+
self.key = self.pattern.pattern
|
|
22
|
+
|
|
23
|
+
def resolve(self, path: str) -> tuple[Any, dict[str, Any]] | None:
|
|
24
|
+
match = self.pattern.match(path)
|
|
25
|
+
if match:
|
|
26
|
+
return (
|
|
27
|
+
self.element,
|
|
28
|
+
{k: self.converters[k](v) for k, v in match.groupdict().items()},
|
|
29
|
+
)
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# TODO: Make reactpy_router's parse_path generic enough to where we don't have to define our own
|
|
34
|
+
def parse_path(path: str) -> tuple[re.Pattern[str], ConverterMapping]:
|
|
35
|
+
# Convert path to regex pattern, and make sure to interpret the registered converters (ex. <int:foo>)
|
|
36
|
+
pattern = "^"
|
|
37
|
+
last_match_end = 0
|
|
38
|
+
converters: ConverterMapping = {}
|
|
39
|
+
for match in PARAM_PATTERN.finditer(path):
|
|
40
|
+
param_name = match.group("name")
|
|
41
|
+
param_type = (match.group("type") or "str").strip(":")
|
|
42
|
+
try:
|
|
43
|
+
param_conv = CONVERTERS[param_type]
|
|
44
|
+
except KeyError as e:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"Unknown conversion type {param_type!r} in {path!r}"
|
|
47
|
+
) from e
|
|
48
|
+
pattern += re.escape(path[last_match_end : match.start()])
|
|
49
|
+
pattern += f"(?P<{param_name}>{param_conv['regex']})"
|
|
50
|
+
converters[param_name] = param_conv["func"]
|
|
51
|
+
last_match_end = match.end()
|
|
52
|
+
pattern += f"{re.escape(path[last_match_end:])}$"
|
|
53
|
+
|
|
54
|
+
# Replace literal `*` with "match anything" regex pattern, if it's at the end of the path
|
|
55
|
+
if pattern.endswith(r"\*$"):
|
|
56
|
+
pattern = f"{pattern[:-3]}.*$"
|
|
57
|
+
|
|
58
|
+
return re.compile(pattern), converters
|