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.
Files changed (44) hide show
  1. js/node_modules/flatted/python/flatted.py +149 -0
  2. js/node_modules/flatted/python/test.py +63 -0
  3. reactpy_django/__init__.py +28 -0
  4. reactpy_django/apps.py +11 -0
  5. reactpy_django/checks.py +542 -0
  6. reactpy_django/clean.py +141 -0
  7. reactpy_django/components.py +286 -0
  8. reactpy_django/config.py +135 -0
  9. reactpy_django/database.py +31 -0
  10. reactpy_django/decorators.py +101 -0
  11. reactpy_django/exceptions.py +34 -0
  12. reactpy_django/hooks.py +496 -0
  13. reactpy_django/http/__init__.py +0 -0
  14. reactpy_django/http/urls.py +18 -0
  15. reactpy_django/http/views.py +62 -0
  16. reactpy_django/management/__init__.py +0 -0
  17. reactpy_django/management/commands/__init__.py +0 -0
  18. reactpy_django/management/commands/clean_reactpy.py +37 -0
  19. reactpy_django/migrations/0001_initial.py +25 -0
  20. reactpy_django/migrations/0002_rename_created_at_componentparams_last_accessed.py +17 -0
  21. reactpy_django/migrations/0003_componentsession_delete_componentparams.py +28 -0
  22. reactpy_django/migrations/0004_config.py +27 -0
  23. reactpy_django/migrations/0005_alter_componentsession_last_accessed.py +17 -0
  24. reactpy_django/migrations/0006_userdatamodel.py +28 -0
  25. reactpy_django/migrations/__init__.py +0 -0
  26. reactpy_django/models.py +48 -0
  27. reactpy_django/py.typed +1 -0
  28. reactpy_django/router/__init__.py +5 -0
  29. reactpy_django/router/converters.py +7 -0
  30. reactpy_django/router/resolvers.py +58 -0
  31. reactpy_django/static/reactpy_django/client.js +1630 -0
  32. reactpy_django/templates/reactpy/component.html +27 -0
  33. reactpy_django/templatetags/__init__.py +0 -0
  34. reactpy_django/templatetags/reactpy.py +221 -0
  35. reactpy_django/types.py +121 -0
  36. reactpy_django/utils.py +384 -0
  37. reactpy_django/websocket/__init__.py +0 -0
  38. reactpy_django/websocket/consumer.py +218 -0
  39. reactpy_django/websocket/paths.py +17 -0
  40. reactpy_django-3.8.1.dist-info/LICENSE.md +9 -0
  41. reactpy_django-3.8.1.dist-info/METADATA +152 -0
  42. reactpy_django-3.8.1.dist-info/RECORD +44 -0
  43. reactpy_django-3.8.1.dist-info/WHEEL +6 -0
  44. 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
@@ -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()
@@ -0,0 +1 @@
1
+ # Marker file for PEP 561
@@ -0,0 +1,5 @@
1
+ from reactpy_router.core import create_router
2
+
3
+ from reactpy_django.router.resolvers import DjangoResolver
4
+
5
+ django_router = create_router(DjangoResolver)
@@ -0,0 +1,7 @@
1
+ from django.urls.converters import get_converters
2
+ from reactpy_router.simple import ConversionInfo
3
+
4
+ CONVERTERS: dict[str, ConversionInfo] = {
5
+ name: {"regex": converter.regex, "func": converter.to_python}
6
+ for name, converter in get_converters().items()
7
+ }
@@ -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