reactpy_django 5.0.0__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 (118) hide show
  1. js/node_modules/@pyscript/core/src/stdlib/pyscript/__init__.py +61 -0
  2. js/node_modules/@pyscript/core/src/stdlib/pyscript/display.py +177 -0
  3. js/node_modules/@pyscript/core/src/stdlib/pyscript/event_handling.py +76 -0
  4. js/node_modules/@pyscript/core/src/stdlib/pyscript/fetch.py +87 -0
  5. js/node_modules/@pyscript/core/src/stdlib/pyscript/ffi.py +18 -0
  6. js/node_modules/@pyscript/core/src/stdlib/pyscript/flatted.py +148 -0
  7. js/node_modules/@pyscript/core/src/stdlib/pyscript/magic_js.py +79 -0
  8. js/node_modules/@pyscript/core/src/stdlib/pyscript/storage.py +60 -0
  9. js/node_modules/@pyscript/core/src/stdlib/pyscript/util.py +33 -0
  10. js/node_modules/@pyscript/core/src/stdlib/pyscript/web.py +1176 -0
  11. js/node_modules/@pyscript/core/src/stdlib/pyscript/websocket.py +71 -0
  12. js/node_modules/@pyscript/core/src/stdlib/pyscript/workers.py +43 -0
  13. js/node_modules/flatted/python/flatted.py +149 -0
  14. js/node_modules/flatted/python/test.py +63 -0
  15. js/node_modules/polyscript/python/mip.py +288 -0
  16. reactpy_django/__init__.py +32 -0
  17. reactpy_django/apps.py +11 -0
  18. reactpy_django/checks.py +558 -0
  19. reactpy_django/clean.py +141 -0
  20. reactpy_django/components.py +284 -0
  21. reactpy_django/config.py +128 -0
  22. reactpy_django/database.py +31 -0
  23. reactpy_django/decorators.py +65 -0
  24. reactpy_django/exceptions.py +34 -0
  25. reactpy_django/hooks.py +469 -0
  26. reactpy_django/html.py +3 -0
  27. reactpy_django/http/__init__.py +0 -0
  28. reactpy_django/http/urls.py +18 -0
  29. reactpy_django/http/views.py +62 -0
  30. reactpy_django/management/__init__.py +0 -0
  31. reactpy_django/management/commands/__init__.py +0 -0
  32. reactpy_django/management/commands/clean_reactpy.py +37 -0
  33. reactpy_django/migrations/0001_initial.py +25 -0
  34. reactpy_django/migrations/0002_rename_created_at_componentparams_last_accessed.py +17 -0
  35. reactpy_django/migrations/0003_componentsession_delete_componentparams.py +28 -0
  36. reactpy_django/migrations/0004_config.py +27 -0
  37. reactpy_django/migrations/0005_alter_componentsession_last_accessed.py +17 -0
  38. reactpy_django/migrations/0006_userdatamodel.py +28 -0
  39. reactpy_django/migrations/__init__.py +0 -0
  40. reactpy_django/models.py +48 -0
  41. reactpy_django/py.typed +1 -0
  42. reactpy_django/pyscript/__init__.py +0 -0
  43. reactpy_django/pyscript/component_template.py +26 -0
  44. reactpy_django/pyscript/layout_handler.py +139 -0
  45. reactpy_django/router/__init__.py +5 -0
  46. reactpy_django/router/converters.py +8 -0
  47. reactpy_django/router/resolvers.py +22 -0
  48. reactpy_django/static/reactpy_django/client.js +1 -0
  49. reactpy_django/static/reactpy_django/morphdom/morphdom-esm.js +769 -0
  50. reactpy_django/static/reactpy_django/morphdom/morphdom-factory.js +705 -0
  51. reactpy_django/static/reactpy_django/morphdom/morphdom-umd.js +777 -0
  52. reactpy_django/static/reactpy_django/morphdom/morphdom-umd.min.js +1 -0
  53. reactpy_django/static/reactpy_django/morphdom/morphdom.js +771 -0
  54. reactpy_django/static/reactpy_django/pyscript/codemirror-BEtcgaoQ.js +2 -0
  55. reactpy_django/static/reactpy_django/pyscript/codemirror-BEtcgaoQ.js.map +1 -0
  56. reactpy_django/static/reactpy_django/pyscript/codemirror_commands-DDxffOmd.js +2 -0
  57. reactpy_django/static/reactpy_django/pyscript/codemirror_commands-DDxffOmd.js.map +1 -0
  58. reactpy_django/static/reactpy_django/pyscript/codemirror_lang-python-CnWnFqxD.js +2 -0
  59. reactpy_django/static/reactpy_django/pyscript/codemirror_lang-python-CnWnFqxD.js.map +1 -0
  60. reactpy_django/static/reactpy_django/pyscript/codemirror_language-CjmvX4ix.js +2 -0
  61. reactpy_django/static/reactpy_django/pyscript/codemirror_language-CjmvX4ix.js.map +1 -0
  62. reactpy_django/static/reactpy_django/pyscript/codemirror_state-D1qTXrff.js +2 -0
  63. reactpy_django/static/reactpy_django/pyscript/codemirror_state-D1qTXrff.js.map +1 -0
  64. reactpy_django/static/reactpy_django/pyscript/codemirror_view-DVb8uYMr.js +2 -0
  65. reactpy_django/static/reactpy_django/pyscript/codemirror_view-DVb8uYMr.js.map +1 -0
  66. reactpy_django/static/reactpy_django/pyscript/core-CjO3FOKB.js +2 -0
  67. reactpy_django/static/reactpy_django/pyscript/core-CjO3FOKB.js.map +1 -0
  68. reactpy_django/static/reactpy_django/pyscript/core.css +1 -0
  69. reactpy_django/static/reactpy_django/pyscript/core.js +2 -0
  70. reactpy_django/static/reactpy_django/pyscript/core.js.map +1 -0
  71. reactpy_django/static/reactpy_django/pyscript/deprecations-manager-pFtn19mE.js +2 -0
  72. reactpy_django/static/reactpy_django/pyscript/deprecations-manager-pFtn19mE.js.map +1 -0
  73. reactpy_django/static/reactpy_django/pyscript/error-tq-z48YI.js +2 -0
  74. reactpy_django/static/reactpy_django/pyscript/error-tq-z48YI.js.map +1 -0
  75. reactpy_django/static/reactpy_django/pyscript/index-S1Do43bx.js +2 -0
  76. reactpy_django/static/reactpy_django/pyscript/index-S1Do43bx.js.map +1 -0
  77. reactpy_django/static/reactpy_django/pyscript/mpy-DovD7Qjy.js +2 -0
  78. reactpy_django/static/reactpy_django/pyscript/mpy-DovD7Qjy.js.map +1 -0
  79. reactpy_django/static/reactpy_django/pyscript/py-BUsUWVJg.js +2 -0
  80. reactpy_django/static/reactpy_django/pyscript/py-BUsUWVJg.js.map +1 -0
  81. reactpy_django/static/reactpy_django/pyscript/py-editor-CeySmmer.js +2 -0
  82. reactpy_django/static/reactpy_django/pyscript/py-editor-CeySmmer.js.map +1 -0
  83. reactpy_django/static/reactpy_django/pyscript/py-terminal-CH_wV7wQ.js +2 -0
  84. reactpy_django/static/reactpy_django/pyscript/py-terminal-CH_wV7wQ.js.map +1 -0
  85. reactpy_django/static/reactpy_django/pyscript/storage.js +2 -0
  86. reactpy_django/static/reactpy_django/pyscript/storage.js.map +1 -0
  87. reactpy_django/static/reactpy_django/pyscript/toml-CvAfdf9_.js +3 -0
  88. reactpy_django/static/reactpy_django/pyscript/toml-CvAfdf9_.js.map +1 -0
  89. reactpy_django/static/reactpy_django/pyscript/toml-DiUM0_qs.js +3 -0
  90. reactpy_django/static/reactpy_django/pyscript/toml-DiUM0_qs.js.map +1 -0
  91. reactpy_django/static/reactpy_django/pyscript/xterm-BY7uk_OU.js +2 -0
  92. reactpy_django/static/reactpy_django/pyscript/xterm-BY7uk_OU.js.map +1 -0
  93. reactpy_django/static/reactpy_django/pyscript/xterm-readline-CZfBw7ic.js +2 -0
  94. reactpy_django/static/reactpy_django/pyscript/xterm-readline-CZfBw7ic.js.map +1 -0
  95. reactpy_django/static/reactpy_django/pyscript/xterm.css +7 -0
  96. reactpy_django/static/reactpy_django/pyscript/xterm_addon-fit--gyF3PcZ.js +2 -0
  97. reactpy_django/static/reactpy_django/pyscript/xterm_addon-fit--gyF3PcZ.js.map +1 -0
  98. reactpy_django/static/reactpy_django/pyscript/xterm_addon-web-links-Cnej-nJ6.js +2 -0
  99. reactpy_django/static/reactpy_django/pyscript/xterm_addon-web-links-Cnej-nJ6.js.map +1 -0
  100. reactpy_django/static/reactpy_django/pyscript/zip-DrwYHuF9.js +2 -0
  101. reactpy_django/static/reactpy_django/pyscript/zip-DrwYHuF9.js.map +1 -0
  102. reactpy_django/static/reactpy_django/pyscript-custom.css +3 -0
  103. reactpy_django/static/reactpy_django/pyscript-hide-debug.css +3 -0
  104. reactpy_django/templates/reactpy/component.html +27 -0
  105. reactpy_django/templates/reactpy/pyscript_component.html +2 -0
  106. reactpy_django/templates/reactpy/pyscript_setup.html +8 -0
  107. reactpy_django/templatetags/__init__.py +0 -0
  108. reactpy_django/templatetags/reactpy.py +250 -0
  109. reactpy_django/types.py +81 -0
  110. reactpy_django/utils.py +560 -0
  111. reactpy_django/websocket/__init__.py +0 -0
  112. reactpy_django/websocket/consumer.py +227 -0
  113. reactpy_django/websocket/paths.py +15 -0
  114. reactpy_django-5.0.0.dist-info/LICENSE.md +9 -0
  115. reactpy_django-5.0.0.dist-info/METADATA +152 -0
  116. reactpy_django-5.0.0.dist-info/RECORD +118 -0
  117. reactpy_django-5.0.0.dist-info/WHEEL +5 -0
  118. reactpy_django-5.0.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,71 @@
1
+ import js
2
+ from pyscript.ffi import create_proxy
3
+ from pyscript.util import as_bytearray
4
+
5
+ code = "code"
6
+ protocols = "protocols"
7
+ reason = "reason"
8
+ methods = ["onclose", "onerror", "onmessage", "onopen"]
9
+
10
+
11
+ class EventMessage:
12
+ def __init__(self, event):
13
+ self._event = event
14
+
15
+ def __getattr__(self, attr):
16
+ value = getattr(self._event, attr)
17
+
18
+ if attr == "data" and not isinstance(value, str):
19
+ if hasattr(value, "to_py"):
20
+ return value.to_py()
21
+ # shims in MicroPython
22
+ return memoryview(as_bytearray(value))
23
+
24
+ return value
25
+
26
+
27
+ class WebSocket(object):
28
+ CONNECTING = 0
29
+ OPEN = 1
30
+ CLOSING = 2
31
+ CLOSED = 3
32
+
33
+ def __init__(self, **kw):
34
+ url = kw["url"]
35
+ if protocols in kw:
36
+ socket = js.WebSocket.new(url, kw[protocols])
37
+ else:
38
+ socket = js.WebSocket.new(url)
39
+ object.__setattr__(self, "_ws", socket)
40
+
41
+ for t in methods:
42
+ if t in kw:
43
+ # Pyodide fails at setting socket[t] directly
44
+ setattr(socket, t, create_proxy(kw[t]))
45
+
46
+ def __getattr__(self, attr):
47
+ return getattr(self._ws, attr)
48
+
49
+ def __setattr__(self, attr, value):
50
+ if attr in methods:
51
+ m = lambda e: value(EventMessage(e))
52
+ setattr(self._ws, attr, create_proxy(m))
53
+ else:
54
+ setattr(self._ws, attr, value)
55
+
56
+ def close(self, **kw):
57
+ if code in kw and reason in kw:
58
+ self._ws.close(kw[code], kw[reason])
59
+ elif code in kw:
60
+ self._ws.close(kw[code])
61
+ else:
62
+ self._ws.close()
63
+
64
+ def send(self, data):
65
+ if isinstance(data, str):
66
+ self._ws.send(data)
67
+ else:
68
+ buffer = js.Uint8Array.new(len(data))
69
+ for pos, b in enumerate(data):
70
+ buffer[pos] = b
71
+ self._ws.send(buffer)
@@ -0,0 +1,43 @@
1
+ import js as _js
2
+ from polyscript import workers as _workers
3
+
4
+ _get = _js.Reflect.get
5
+
6
+
7
+ def _set(script, name, value=""):
8
+ script.setAttribute(name, value)
9
+
10
+
11
+ # this solves an inconsistency between Pyodide and MicroPython
12
+ # @see https://github.com/pyscript/pyscript/issues/2106
13
+ class _ReadOnlyProxy:
14
+ def __getitem__(self, name):
15
+ return _get(_workers, name)
16
+
17
+ def __getattr__(self, name):
18
+ return _get(_workers, name)
19
+
20
+
21
+ workers = _ReadOnlyProxy()
22
+
23
+
24
+ async def create_named_worker(src="", name="", config=None, type="py"):
25
+ from json import dumps
26
+
27
+ if not src:
28
+ raise ValueError("Named workers require src")
29
+
30
+ if not name:
31
+ raise ValueError("Named workers require a name")
32
+
33
+ s = _js.document.createElement("script")
34
+ s.type = type
35
+ s.src = src
36
+ _set(s, "worker")
37
+ _set(s, "name", name)
38
+
39
+ if config:
40
+ _set(s, "config", isinstance(config, str) and config or dumps(config))
41
+
42
+ _js.document.body.append(s)
43
+ return await workers[name]
@@ -0,0 +1,149 @@
1
+ # ISC License
2
+ #
3
+ # Copyright (c) 2018-2021, Andrea Giammarchi, @WebReflection
4
+ #
5
+ # Permission to use, copy, modify, and/or distribute this software for any
6
+ # purpose with or without fee is hereby granted, provided that the above
7
+ # copyright notice and this permission notice appear in all copies.
8
+ #
9
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14
+ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ # PERFORMANCE OF THIS SOFTWARE.
16
+
17
+ import json as _json
18
+
19
+ class _Known:
20
+ def __init__(self):
21
+ self.key = []
22
+ self.value = []
23
+
24
+ class _String:
25
+ def __init__(self, value):
26
+ self.value = value
27
+
28
+
29
+ def _array_keys(value):
30
+ keys = []
31
+ i = 0
32
+ for _ in value:
33
+ keys.append(i)
34
+ i += 1
35
+ return keys
36
+
37
+ def _object_keys(value):
38
+ keys = []
39
+ for key in value:
40
+ keys.append(key)
41
+ return keys
42
+
43
+ def _is_array(value):
44
+ return isinstance(value, list) or isinstance(value, tuple)
45
+
46
+ def _is_object(value):
47
+ return isinstance(value, dict)
48
+
49
+ def _is_string(value):
50
+ return isinstance(value, str)
51
+
52
+ def _index(known, input, value):
53
+ input.append(value)
54
+ index = str(len(input) - 1)
55
+ known.key.append(value)
56
+ known.value.append(index)
57
+ return index
58
+
59
+ def _loop(keys, input, known, output):
60
+ for key in keys:
61
+ value = output[key]
62
+ if isinstance(value, _String):
63
+ _ref(key, input[int(value.value)], input, known, output)
64
+
65
+ return output
66
+
67
+ def _ref(key, value, input, known, output):
68
+ if _is_array(value) and not value in known:
69
+ known.append(value)
70
+ value = _loop(_array_keys(value), input, known, value)
71
+ elif _is_object(value) and not value in known:
72
+ known.append(value)
73
+ value = _loop(_object_keys(value), input, known, value)
74
+
75
+ output[key] = value
76
+
77
+ def _relate(known, input, value):
78
+ if _is_string(value) or _is_array(value) or _is_object(value):
79
+ try:
80
+ return known.value[known.key.index(value)]
81
+ except:
82
+ return _index(known, input, value)
83
+
84
+ return value
85
+
86
+ def _transform(known, input, value):
87
+ if _is_array(value):
88
+ output = []
89
+ for val in value:
90
+ output.append(_relate(known, input, val))
91
+ return output
92
+
93
+ if _is_object(value):
94
+ obj = {}
95
+ for key in value:
96
+ obj[key] = _relate(known, input, value[key])
97
+ return obj
98
+
99
+ return value
100
+
101
+ def _wrap(value):
102
+ if _is_string(value):
103
+ return _String(value)
104
+
105
+ if _is_array(value):
106
+ i = 0
107
+ for val in value:
108
+ value[i] = _wrap(val)
109
+ i += 1
110
+
111
+ elif _is_object(value):
112
+ for key in value:
113
+ value[key] = _wrap(value[key])
114
+
115
+ return value
116
+
117
+ def parse(value, *args, **kwargs):
118
+ json = _json.loads(value, *args, **kwargs)
119
+ wrapped = []
120
+ for value in json:
121
+ wrapped.append(_wrap(value))
122
+
123
+ input = []
124
+ for value in wrapped:
125
+ if isinstance(value, _String):
126
+ input.append(value.value)
127
+ else:
128
+ input.append(value)
129
+
130
+ value = input[0]
131
+
132
+ if _is_array(value):
133
+ return _loop(_array_keys(value), input, [value], value)
134
+
135
+ if _is_object(value):
136
+ return _loop(_object_keys(value), input, [value], value)
137
+
138
+ return value
139
+
140
+
141
+ def stringify(value, *args, **kwargs):
142
+ known = _Known()
143
+ input = []
144
+ output = []
145
+ i = int(_index(known, input, value))
146
+ while i < len(input):
147
+ output.append(_transform(known, input, input[i]))
148
+ i += 1
149
+ return _json.dumps(output, *args, **kwargs)
@@ -0,0 +1,63 @@
1
+ from flatted import stringify as _stringify, parse
2
+
3
+ def stringify(value):
4
+ return _stringify(value, separators=(',', ':'))
5
+
6
+ assert stringify([None, None]) == '[[null,null]]'
7
+
8
+ a = []
9
+ o = {}
10
+
11
+ assert stringify(a) == '[[]]'
12
+ assert stringify(o) == '[{}]'
13
+
14
+ a.append(a)
15
+ o['o'] = o
16
+
17
+ assert stringify(a) == '[["0"]]'
18
+ assert stringify(o) == '[{"o":"0"}]'
19
+
20
+ b = parse(stringify(a))
21
+ assert isinstance(b, list) and b[0] == b
22
+
23
+ a.append(1)
24
+ a.append('two')
25
+ a.append(True)
26
+ o['one'] = 1
27
+ o['two'] = 'two'
28
+ o['three'] = True
29
+
30
+ assert stringify(a) == '[["0",1,"1",true],"two"]'
31
+ assert stringify(o) == '[{"o":"0","one":1,"two":"1","three":true},"two"]'
32
+
33
+ a.append(o)
34
+ o['a'] = a
35
+
36
+ assert stringify(a) == '[["0",1,"1",true,"2"],"two",{"o":"2","one":1,"two":"1","three":true,"a":"0"}]'
37
+ assert stringify(o) == '[{"o":"0","one":1,"two":"1","three":true,"a":"2"},"two",["2",1,"1",true,"0"]]'
38
+
39
+ a.append({'test': 'OK'})
40
+ a.append([1, 2, 3])
41
+
42
+ o['test'] = {'test': 'OK'}
43
+ o['array'] = [1, 2, 3]
44
+
45
+ assert stringify(a) == '[["0",1,"1",true,"2","3","4"],"two",{"o":"2","one":1,"two":"1","three":true,"a":"0","test":"3","array":"4"},{"test":"5"},[1,2,3],"OK"]'
46
+ assert stringify(o) == '[{"o":"0","one":1,"two":"1","three":true,"a":"2","test":"3","array":"4"},"two",["2",1,"1",true,"0","3","4"],{"test":"5"},[1,2,3],"OK"]'
47
+
48
+ a2 = parse(stringify(a));
49
+ o2 = parse(stringify(o));
50
+
51
+ assert a2[0] == a2
52
+ assert o2['o'] == o2
53
+
54
+ assert a2[1] == 1 and a2[2] == 'two' and a2[3] == True and isinstance(a2[4], dict)
55
+ assert a2[4] == a2[4]['o'] and a2 == a2[4]['o']['a']
56
+
57
+ str = parse('[{"prop":"1","a":"2","b":"3"},{"value":123},["4","5"],{"e":"6","t":"7","p":4},{},{"b":"8"},"f",{"a":"9"},["10"],"sup",{"a":1,"d":2,"c":"7","z":"11","h":1},{"g":2,"a":"7","b":"12","f":6},{"r":4,"u":"7","c":5}]')
58
+ assert str['b']['t']['a'] == 'sup' and str['a'][1]['b'][0]['c'] == str['b']['t']
59
+
60
+ oo = parse('[{"a":"1","b":"0","c":"2"},{"aa":"3"},{"ca":"4","cb":"5","cc":"6","cd":"7","ce":"8","cf":"9"},{"aaa":"10"},{"caa":"4"},{"cba":"5"},{"cca":"2"},{"cda":"4"},"value2","value3","value1"]');
61
+ assert oo['a']['aa']['aaa'] == 'value1' and oo == oo['b'] and oo['c']['ca']['caa'] == oo['c']['ca']
62
+
63
+ print('OK')
@@ -0,0 +1,288 @@
1
+ from uio import StringIO
2
+ import sys
3
+
4
+ class Response:
5
+ def __init__(self, f):
6
+ self.raw = f
7
+ self.encoding = "utf-8"
8
+ self._cached = None
9
+
10
+ def close(self):
11
+ if self.raw:
12
+ self.raw.close()
13
+ self.raw = None
14
+ self._cached = None
15
+
16
+ @property
17
+ def content(self):
18
+ if self._cached is None:
19
+ try:
20
+ self._cached = self.raw.read()
21
+ finally:
22
+ self.raw.close()
23
+ self.raw = None
24
+ return self._cached
25
+
26
+ @property
27
+ def text(self):
28
+ return str(self.content, self.encoding)
29
+
30
+ def json(self):
31
+ import ujson
32
+
33
+ return ujson.loads(self.content)
34
+
35
+
36
+ # TODO try to support streaming xhr requests, a-la pyodide-http
37
+ HEADERS_TO_IGNORE = ("user-agent",)
38
+
39
+
40
+ try:
41
+ import js
42
+ except Exception as err:
43
+ raise OSError("This version of urequests can only be used in the browser")
44
+
45
+ # TODO try to support streaming xhr requests, a-la pyodide-http
46
+
47
+ HEADERS_TO_IGNORE = ("user-agent",)
48
+
49
+
50
+ def request(
51
+ method,
52
+ url,
53
+ data=None,
54
+ json=None,
55
+ headers={},
56
+ stream=None,
57
+ auth=None,
58
+ timeout=None,
59
+ parse_headers=True,
60
+ ):
61
+ from js import XMLHttpRequest
62
+
63
+ xhr = XMLHttpRequest.new()
64
+ xhr.withCredentials = False
65
+
66
+ if auth is not None:
67
+ import ubinascii
68
+
69
+ username, password = auth
70
+ xhr.open(method, url, False, username, password)
71
+ else:
72
+ xhr.open(method, url, False)
73
+
74
+ for name, value in headers.items():
75
+ if name.lower() not in HEADERS_TO_IGNORE:
76
+ xhr.setRequestHeader(name, value)
77
+
78
+ if timeout:
79
+ xhr.timeout = int(timeout * 1000)
80
+
81
+ if json is not None:
82
+ assert data is None
83
+ import ujson
84
+
85
+ data = ujson.dumps(json)
86
+ # s.write(b"Content-Type: application/json\r\n")
87
+ xhr.setRequestHeader("Content-Type", "application/json")
88
+
89
+ xhr.send(data)
90
+
91
+ # Emulates the construction process in the original urequests
92
+ resp = Response(StringIO(xhr.responseText))
93
+ resp.status_code = xhr.status
94
+ resp.reason = xhr.statusText
95
+ resp.headers = xhr.getAllResponseHeaders()
96
+
97
+ return resp
98
+
99
+
100
+ # Other methods - head, post, put, patch, delete - are not used by
101
+ # mip and therefore not included
102
+
103
+
104
+ def get(url, **kw):
105
+ return request("GET", url, **kw)
106
+
107
+
108
+ # Content below this line is from the Micropython MIP package and is covered
109
+ # by the applicable MIT license:
110
+ #
111
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
112
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
113
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
114
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
115
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
116
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
117
+ # DEALINGS IN THE SOFTWARE.
118
+
119
+ # MicroPython package installer
120
+ # MIT license; Copyright (c) 2022 Jim Mussared
121
+
122
+
123
+ _PACKAGE_INDEX = const("https://micropython.org/pi/v2")
124
+ _CHUNK_SIZE = 128
125
+
126
+
127
+ # This implements os.makedirs(os.dirname(path))
128
+ def _ensure_path_exists(path):
129
+ import os
130
+
131
+ split = path.split("/")
132
+
133
+ # Handle paths starting with "/".
134
+ if not split[0]:
135
+ split.pop(0)
136
+ split[0] = "/" + split[0]
137
+
138
+ prefix = ""
139
+ for i in range(len(split) - 1):
140
+ prefix += split[i]
141
+ try:
142
+ os.stat(prefix)
143
+ except:
144
+ os.mkdir(prefix)
145
+ prefix += "/"
146
+
147
+
148
+ # Copy from src (stream) to dest (function-taking-bytes)
149
+ def _chunk(src, dest):
150
+ buf = memoryview(bytearray(_CHUNK_SIZE))
151
+ while True:
152
+ n = src.readinto(buf)
153
+ if n == 0:
154
+ break
155
+ dest(buf if n == _CHUNK_SIZE else buf[:n])
156
+
157
+
158
+ # Check if the specified path exists and matches the hash.
159
+ def _check_exists(path, short_hash):
160
+ import os
161
+
162
+ try:
163
+ import binascii
164
+ import hashlib
165
+
166
+ with open(path, "rb") as f:
167
+ hs256 = hashlib.sha256()
168
+ _chunk(f, hs256.update)
169
+ existing_hash = str(binascii.hexlify(hs256.digest())[: len(short_hash)], "utf-8")
170
+ return existing_hash == short_hash
171
+ except:
172
+ return False
173
+
174
+
175
+ def _rewrite_url(url, branch=None):
176
+ if not branch:
177
+ branch = "HEAD"
178
+ if url.startswith("github:"):
179
+ url = url[7:].split("/")
180
+ url = (
181
+ "https://raw.githubusercontent.com/"
182
+ + url[0]
183
+ + "/"
184
+ + url[1]
185
+ + "/"
186
+ + branch
187
+ + "/"
188
+ + "/".join(url[2:])
189
+ )
190
+ return url
191
+
192
+
193
+ def _download_file(url, dest):
194
+ response = get(url)
195
+ try:
196
+ if response.status_code != 200:
197
+ print("Error", response.status_code, "requesting", url)
198
+ return False
199
+
200
+ print("Copying:", dest)
201
+ _ensure_path_exists(dest)
202
+ with open(dest, "wb") as f:
203
+ _chunk(response.raw, f.write)
204
+
205
+ return True
206
+ finally:
207
+ response.close()
208
+
209
+
210
+ def _install_json(package_json_url, index, target, version, mpy):
211
+ response = get(_rewrite_url(package_json_url, version))
212
+ try:
213
+ if response.status_code != 200:
214
+ print("Package not found:", package_json_url)
215
+ return False
216
+
217
+ package_json = response.json()
218
+ finally:
219
+ response.close()
220
+ for target_path, short_hash in package_json.get("hashes", ()):
221
+ fs_target_path = target + "/" + target_path
222
+ if _check_exists(fs_target_path, short_hash):
223
+ print("Exists:", fs_target_path)
224
+ else:
225
+ file_url = "{}/file/{}/{}".format(index, short_hash[:2], short_hash)
226
+ if not _download_file(file_url, fs_target_path):
227
+ print("File not found: {} {}".format(target_path, short_hash))
228
+ return False
229
+ for target_path, url in package_json.get("urls", ()):
230
+ fs_target_path = target + "/" + target_path
231
+ if not _download_file(_rewrite_url(url, version), fs_target_path):
232
+ print("File not found: {} {}".format(target_path, url))
233
+ return False
234
+ for dep, dep_version in package_json.get("deps", ()):
235
+ if not _install_package(dep, index, target, dep_version, mpy):
236
+ return False
237
+ return True
238
+
239
+
240
+ def _install_package(package, index, target, version, mpy):
241
+ if (
242
+ package.startswith("http://")
243
+ or package.startswith("https://")
244
+ or package.startswith("github:")
245
+ ):
246
+ if package.endswith(".py") or package.endswith(".mpy"):
247
+ print("Downloading {} to {}".format(package, target))
248
+ return _download_file(
249
+ _rewrite_url(package, version), target + "/" + package.rsplit("/")[-1]
250
+ )
251
+ else:
252
+ if not package.endswith(".json"):
253
+ if not package.endswith("/"):
254
+ package += "/"
255
+ package += "package.json"
256
+ print("Installing {} to {}".format(package, target))
257
+ else:
258
+ if not version:
259
+ version = "latest"
260
+ print("Installing {} ({}) from {} to {}".format(package, version, index, target))
261
+
262
+ mpy_version = (
263
+ sys.implementation._mpy & 0xFF if mpy and hasattr(sys.implementation, "_mpy") else "py"
264
+ )
265
+
266
+ # WARNING: mpy_version fails miserably with 1.22.0-380
267
+ package = "{}/package/{}/{}/{}.json".format(index, "py", package, version)
268
+
269
+ return _install_json(package, index, target, version, mpy)
270
+
271
+
272
+ def install(package, index=None, target=None, version=None, mpy=True):
273
+ if not target:
274
+ for p in sys.path:
275
+ if p.endswith("/lib"):
276
+ target = p
277
+ break
278
+ else:
279
+ print("Unable to find lib dir in sys.path")
280
+ return
281
+
282
+ if not index:
283
+ index = _PACKAGE_INDEX
284
+
285
+ if _install_package(package, index.rstrip("/"), target, version, mpy):
286
+ print("Done")
287
+ else:
288
+ print("Package may be partially installed")
@@ -0,0 +1,32 @@
1
+ import contextlib
2
+
3
+ import nest_asyncio
4
+
5
+ from reactpy_django import (
6
+ components,
7
+ decorators,
8
+ hooks,
9
+ html,
10
+ router,
11
+ types,
12
+ utils,
13
+ )
14
+ from reactpy_django.websocket.paths import REACTPY_WEBSOCKET_ROUTE
15
+
16
+ __version__ = "5.0.0"
17
+ __all__ = [
18
+ "REACTPY_WEBSOCKET_ROUTE",
19
+ "html",
20
+ "hooks",
21
+ "components",
22
+ "decorators",
23
+ "types",
24
+ "utils",
25
+ "router",
26
+ ]
27
+
28
+ # Fixes bugs with REACTPY_BACKHAUL_THREAD + built-in asyncio event loops.
29
+ # Previously, Uvicorn could generate `assert f is self._write_fut` exceptions, and Daphne
30
+ # had jittery rendering behaviors. Demonstrated using our "Renders Per Second" test page.
31
+ with contextlib.suppress(ValueError):
32
+ nest_asyncio.apply()
reactpy_django/apps.py ADDED
@@ -0,0 +1,11 @@
1
+ from django.apps import AppConfig
2
+
3
+ from reactpy_django.utils import RootComponentFinder
4
+
5
+
6
+ class ReactPyConfig(AppConfig):
7
+ name = "reactpy_django"
8
+
9
+ def ready(self):
10
+ # Populate the ReactPy component registry when Django is ready
11
+ RootComponentFinder().run()