Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
253 commits
Select commit Hold shift + click to select a range
d06a0c3
0.36.1 release
rmorshea Feb 3, 2022
2e1f6ea
fix rst formatting
rmorshea Feb 3, 2022
e4fca65
fix typo
rmorshea Feb 3, 2022
c146dfb
DeprecatedOption must mirror regular option
rmorshea Feb 3, 2022
755a203
0.36.2 hotfix
rmorshea Feb 3, 2022
73fe7f0
fix type annotation
rmorshea Feb 3, 2022
4723d7d
new_opt is never None
rmorshea Feb 3, 2022
742cf57
configure pydocstyle
rmorshea Feb 5, 2022
3a8a5a1
compare definition ID to see if changed in layout
rmorshea Feb 9, 2022
f0a2766
fix mispellings
rmorshea Feb 9, 2022
96fce16
try another approach to fixing switching component def and resetting …
rmorshea Feb 10, 2022
a407913
fix types
rmorshea Feb 11, 2022
dcd507f
Remove work items section of task plan
rmorshea Feb 16, 2022
99219f3
fix #652
rmorshea Feb 16, 2022
781c6f6
implement element fragment + try to fix tests
rmorshea Feb 16, 2022
35e5b99
fix errors
rmorshea Feb 17, 2022
c8e7181
allow components to return None
rmorshea Feb 17, 2022
009cea2
fix one more test
rmorshea Feb 17, 2022
896771c
add tests for coverage
rmorshea Feb 18, 2022
0ce9ca6
remove flake8 pre-commit
rmorshea Feb 18, 2022
e39404d
require markupsafe<2.1
rmorshea Feb 18, 2022
dcd30c2
fix mypy
rmorshea Feb 18, 2022
3748f38
release 0.36.3 (#679)
rmorshea Feb 18, 2022
e8ae05a
docs for components sharing state (#571)
acivitillo Feb 19, 2022
9546b52
clean up docs
rmorshea Feb 19, 2022
182317a
remove temp file
rmorshea Feb 20, 2022
545f2f1
support keys in HTML fragments (#683)
rmorshea Feb 20, 2022
82a7edf
Add Use Context Hook (#585)
rmorshea Feb 21, 2022
5b8ab7d
reset schedule_render_later flag after triggering (#688)
rmorshea Feb 25, 2022
fdad4fd
test reset schedule_render_later
rmorshea Feb 25, 2022
2a54b34
reorganize creating-interfaces + add info on fragments (#685)
rmorshea Feb 25, 2022
3f8803e
Re-organize docs + start using "Keep a Changelog" style (#689)
rmorshea Feb 27, 2022
a66eae4
load import source in effect (#691)
rmorshea Feb 28, 2022
e6e9190
'update version to 0.37.0'
rmorshea Feb 28, 2022
856487c
noxfile correction
rmorshea Feb 28, 2022
78f33ff
minor changes to nox tag process
rmorshea Feb 28, 2022
fddd1d8
set target value onchange client-side (#694)
rmorshea Feb 28, 2022
c9536f6
'version 0.37.1-a1'
rmorshea Feb 28, 2022
a029189
actually fix #684 (#696)
rmorshea Mar 2, 2022
857c789
fix flicker with observedValues buffer (#697)
rmorshea Mar 3, 2022
1e11b22
'version 0.37.1-a2'
rmorshea Mar 3, 2022
506d40e
0.37.1 has no changes
rmorshea Mar 5, 2022
d73b79f
'version 0.37.1'
rmorshea Mar 5, 2022
f96538c
rename proto modules to types (#701)
rmorshea Mar 5, 2022
3664706
Update running-idom.rst (#710)
jmtaysom Mar 17, 2022
a7c4d6c
Bugfix for wss protocol issue. (#716)
liberty-rising Mar 26, 2022
99d3792
remove 0.37.2 section
rmorshea Mar 27, 2022
ad49f29
'version 0.37.2'
rmorshea Mar 27, 2022
f2c1070
Rework How IDOM Integrates With Servers (#703)
rmorshea Mar 28, 2022
6708394
version 0.38.0-a1
rmorshea Mar 28, 2022
1d4d942
sort main first in docs
rmorshea Mar 31, 2022
e43bcc0
Implement use_location (#721)
rmorshea Apr 8, 2022
7621e37
Use "backend" instead of "server" (#726)
rmorshea Apr 13, 2022
fc8ff68
version 0.38.0-a2
rmorshea Apr 15, 2022
5091501
make Layout context management async (#730)
rmorshea Apr 15, 2022
3e542ac
Improve Changelog (#731)
rmorshea Apr 15, 2022
31317b0
fix version update script
rmorshea Apr 15, 2022
ce2e3ae
version 0.38.0-a3
rmorshea Apr 15, 2022
fb39848
add use debug value hook (#733)
rmorshea Apr 16, 2022
0bbd2d5
version 0.38.0-a4
rmorshea Apr 16, 2022
9e8e849
version 0.38.0
rmorshea Apr 16, 2022
3a313d9
add missing file extension (#736)
rmorshea Apr 16, 2022
e302f2e
version 0.38.1
rmorshea Apr 16, 2022
c7be65e
tweak changelog entry
rmorshea Apr 16, 2022
3242da6
Readme Overhaul (#705)
Archmonger Apr 16, 2022
e93ae19
fix docs
rmorshea Apr 16, 2022
2af7590
Update changelog.rst
rmorshea Apr 17, 2022
f25970d
update docstring
rmorshea Apr 18, 2022
fb45e7e
Update good_conditional_todo_list.py (#745)
jmtaysom Apr 22, 2022
32dfb26
Another Readme Update (#747)
Archmonger Apr 29, 2022
0177411
Replace changelog CI with greetings (#752)
Archmonger May 31, 2022
a975260
remove accidentally committed temp file
rmorshea Jun 14, 2022
5004ca7
use pr template
rmorshea Jun 16, 2022
009617d
fix mimetype issue (#762)
rmorshea Jun 16, 2022
d157e10
Fix idom.run and more renaming of server to backend (#763)
rmorshea Jun 17, 2022
b0c7f93
Change function name in readme example (#750)
Archmonger Jun 17, 2022
8e3b0b1
ability to specify version in template + no more exports_default (#765)
rmorshea Jun 19, 2022
d547122
version 0.39.0
rmorshea Jun 20, 2022
a2bd7ad
test py3.10 (#767)
rmorshea Jun 21, 2022
535d746
Update pull_request_template.md
rmorshea Jun 26, 2022
4500d55
add asgiref dep + set default timeout on page (#776)
rmorshea Jul 1, 2022
7bebc4d
Track contexts in hooks as state (#787)
rmorshea Jul 14, 2022
2720911
use strict equality for text, numeric, and binary types (#790)
rmorshea Jul 16, 2022
30732cc
make nox-session reusable workflow (#791)
rmorshea Jul 18, 2022
3db3881
update error messages (#792)
rmorshea Jul 18, 2022
3a0d459
Bump jsdom from 16.3.0 to 16.5.0 in /src/client (#774)
dependabot[bot] Jul 18, 2022
f593ee3
Bump got from 11.8.3 to 11.8.5 in /src/client (#772)
dependabot[bot] Aug 9, 2022
2f0bb98
Fix: Accidental mutation of old model causes invalid JSON Patch (#802)
rmorshea Aug 13, 2022
b06977a
Use LXML for html_to_vdom (#795)
Archmonger Aug 14, 2022
842389f
version 0.40.0
rmorshea Aug 14, 2022
a1ebebd
Remove old "missing react hooks" note (#805)
Archmonger Sep 2, 2022
d682407
fix append to stale children ref (#807)
rmorshea Sep 12, 2022
824eeb5
version 0.40.1
rmorshea Sep 12, 2022
7caa4ab
bypass jsonpatch (#809)
rmorshea Sep 13, 2022
b17a951
version 0.40.2
rmorshea Sep 13, 2022
dbd88e2
remove extra element in testing (#812)
rmorshea Sep 18, 2022
1254aaa
Bump vm2 from 3.9.9 to 3.9.11 in /src/client (#814)
dependabot[bot] Oct 3, 2022
f59af55
Update badge image link
rmorshea Oct 4, 2022
6fe9fa2
changed first name to last name and email (#815)
Kurtsley Oct 5, 2022
d7a71b3
allow string return type (#817)
rmorshea Oct 7, 2022
cba66aa
Fix model state ID logging (#818)
Archmonger Oct 7, 2022
688a16d
schedule test once a week rather than one per day
rmorshea Oct 11, 2022
50e42c0
set event loop policy for windows (#820)
rmorshea Oct 18, 2022
64c9e82
add use_connection hook (#823)
rmorshea Oct 30, 2022
8ff09d2
Vite (#824)
rmorshea Oct 31, 2022
77e7f98
define state as a generic named tuple (#827)
rmorshea Nov 2, 2022
d44ab8b
version 0.41.0
rmorshea Nov 2, 2022
cc9518d
fix cov (#831)
rmorshea Nov 6, 2022
f7c553e
remove IDOM_FEATURE_INDEX_AS_DEFAULT_KEY opt (#840)
rmorshea Nov 23, 2022
97c0f42
allow users to configure html head (#835)
rmorshea Nov 29, 2022
8f3785b
add deprecation warning to module_from_template
rmorshea Nov 30, 2022
0d4def4
better run func warning (#842)
rmorshea Nov 30, 2022
4fd5cde
Make IDOM_DEBUG_MODE mutable + add Option.subscribe method (#843)
rmorshea Nov 30, 2022
98a3d1e
Form serialize (#699)
acivitillo Dec 1, 2022
9c3c300
`html_to_vdom` transform to remove html/body but preserve head conten…
Archmonger Dec 1, 2022
55a4d16
add svg elements (#844)
rmorshea Dec 1, 2022
039d08d
remove body from all
rmorshea Dec 1, 2022
f196fbb
version 0.42.0
rmorshea Dec 2, 2022
1e3fac1
Bump qs from 6.5.2 to 6.5.3 in /src/client (#853)
dependabot[bot] Dec 12, 2022
4bc4a2a
fix tests + upgrade doc dependencies (#862)
rmorshea Jan 5, 2023
9760280
fix docs in docker
rmorshea Jan 5, 2023
b04ec36
misc updates to docs (#872)
rmorshea Jan 8, 2023
0621716
remove should_render (#870)
rmorshea Jan 9, 2023
80e7141
remove fake user agent (#873)
rmorshea Jan 9, 2023
0894df2
Bump fast-json-patch from 3.1.0 to 3.1.1 in /src/client (#864)
dependabot[bot] Jan 9, 2023
b1d0507
remove setup.cfg file (#874)
rmorshea Jan 9, 2023
ea485a4
version 0.43.0
rmorshea Jan 9, 2023
b0ea49a
use non-editable install
rmorshea Jan 9, 2023
d1a69f6
Deprecate hotswap (#876)
rmorshea Jan 12, 2023
981fd43
remove json patch (#881)
rmorshea Jan 24, 2023
f7d7e29
check that url prefix starts with / (#885)
rmorshea Jan 24, 2023
6dfa5b5
no need to unmount on reconnect (#886)
rmorshea Jan 24, 2023
7bdcdfe
remove deprecated code (#887)
rmorshea Jan 24, 2023
cc47748
version 0.44.0
rmorshea Jan 27, 2023
764a5a8
Unify vdom interface (#841)
rmorshea Jan 28, 2023
e9c6f3c
update docs + changelog + fix warning (#891)
rmorshea Jan 28, 2023
cc723de
version 1.0.0-a1
rmorshea Jan 29, 2023
491c05a
Fix unmount (#901)
rmorshea Feb 1, 2023
53b8cc0
add entry points (#902)
rmorshea Feb 1, 2023
9f879a6
version 1.0.0-a2
rmorshea Feb 1, 2023
aa26caa
avoid importing testing module (#907)
rmorshea Feb 3, 2023
c8adf95
fix type hint annoyance (#908)
rmorshea Feb 3, 2023
bd87407
version 1.0.0-a3
rmorshea Feb 3, 2023
d415bcf
Update issue-form.yml
rmorshea Feb 15, 2023
f0ff025
revert #841 (#919)
rmorshea Feb 21, 2023
6e9b99f
version 1.0.0-a4
rmorshea Feb 21, 2023
b8af14c
fix rewrite camelCase (#934)
rmorshea Feb 21, 2023
86e3af9
version 1.0.0-a5
rmorshea Feb 21, 2023
3aa249d
update changelog
rmorshea Feb 21, 2023
e8263de
Rewrite style props (#936)
rmorshea Feb 23, 2023
b8eeaa9
Fix pylint issues (#937)
Archmonger Feb 23, 2023
cfdd83a
version 1.0.0-a6
rmorshea Feb 24, 2023
51d82df
version 1.0 (#940)
rmorshea Feb 26, 2023
3dfb8f1
rename idom to reactpy (#892)
rmorshea Feb 26, 2023
c791ac8
improve logo/readme
rmorshea Feb 26, 2023
67e6181
Update README.md
rmorshea Feb 27, 2023
637c1b7
improve readme (#944)
rmorshea Mar 1, 2023
83d6c28
fix docs links (#942)
Archmonger Mar 1, 2023
0a66918
add logo for social card (#945)
rmorshea Mar 1, 2023
75343c9
Update README.md
rmorshea Mar 1, 2023
95c4107
Update README.md
rmorshea Mar 1, 2023
79dcb7b
fix nox
rmorshea Mar 1, 2023
7194d41
fix nox tag session (#948)
rmorshea Mar 2, 2023
2fc8228
More readme link fixes (#947)
Archmonger Mar 2, 2023
665196a
allow independent py/js package releases (#949)
rmorshea Mar 14, 2023
304126c
improve publishing logic (#954)
rmorshea Mar 15, 2023
d664944
fix publish action
rmorshea Mar 15, 2023
4b5ebed
try to fix publish action
rmorshea Mar 15, 2023
997aae6
try one more time to fix secrets
rmorshea Mar 15, 2023
cb6a8c3
use install instead of ci
rmorshea Mar 15, 2023
6e7fa1b
more fixes
rmorshea Mar 15, 2023
04c3e9f
fix types
rmorshea Mar 15, 2023
3d6e501
more typing fixes
rmorshea Mar 15, 2023
599af39
simplify publish action
rmorshea Mar 15, 2023
cf65abb
revert back to .nox-session base action
rmorshea Mar 15, 2023
b5d61d3
add registry url
rmorshea Mar 15, 2023
bf86c61
reactpy v1.0.0 (#955)
rmorshea Mar 15, 2023
6a4c947
handle case where file does not exist
rmorshea Mar 15, 2023
82a8bd6
rewrite the client in typescript (#951)
rmorshea Mar 23, 2023
3a009b6
fix event-to-object + fix npm release (#962)
rmorshea Apr 2, 2023
b15b43d
fix JS dist artifacts (#963)
rmorshea Apr 2, 2023
8caf973
Fix `idom.run` uvicorn self.servers exception (#943)
Archmonger Apr 5, 2023
b1951cc
define a better client interface (#967)
rmorshea Apr 11, 2023
0aab4b0
use abstract class (#968)
rmorshea Apr 11, 2023
849df98
Update pull_request_template.md
rmorshea Apr 19, 2023
46bdf8c
WSGIContainer.environ changed (#971)
rmorshea Apr 23, 2023
0f34eb8
added warning for html.script (#970)
ZEUS-03 Apr 23, 2023
9ffaf93
use newly released reactpy-flake8
rmorshea Apr 30, 2023
472d831
Use span instead of div (#974)
rmorshea May 15, 2023
07f5521
fix js template links (#979)
rmorshea May 20, 2023
c86c59d
doc improvements (#984)
rmorshea May 24, 2023
daf9102
docstrings for backend hooks (#994)
rmorshea May 25, 2023
cf7950d
Clean up readme (#1000)
Archmonger May 29, 2023
ac58266
Poetry+Hatch Monorepo (#1002)
rmorshea Jun 3, 2023
e950966
fix poetry docs (#1003)
rmorshea Jun 3, 2023
4f98dcf
Fix typos (#1007)
kianmeng Jun 6, 2023
4f5a251
Update README.md (#1009)
Iddorot Jun 6, 2023
309bd5a
Create CODEOWNERS (#1011)
rmorshea Jun 6, 2023
1173224
Emphasize the `pip install reactpy` does not include a backend (#1012)
rmorshea Jun 6, 2023
09679e2
Remove HR from readme (#1013)
Archmonger Jun 6, 2023
9552441
fix noqas (#1016)
rmorshea Jun 7, 2023
a6eb1dc
Fix the Django project URL (#1015)
Jun 7, 2023
7428340
avoid importing backend-specific dependencies (#1006)
rmorshea Jun 7, 2023
0a89ecb
Fixed FileNotFound error while running hatch run lint-py (#1023)
Smit-Parmar Jun 8, 2023
9c707d3
Unpin reactpy client version (#1027)
Archmonger Jun 9, 2023
e7a6b5b
Update index.rst (#1026)
Not-Sarthak Jun 10, 2023
2962ed9
docs: fix typo in distributing-javascript.rst (#1028)
eltociear Jun 10, 2023
b1a2516
Update parameter name in starlette.py (#1031)
mrjunos Jun 10, 2023
81d6343
docs:fixed two typos inside Dangers of mutability (#1038)
danish-mehmood Jun 10, 2023
c80bc51
Fixed while running hatch run lint-js --fix (#1030)
Smit-Parmar Jun 10, 2023
f559e23
docs fixes (#1039)
rmorshea Jun 10, 2023
8120ddc
Better Error message if no backend installed #1042 (#1045)
geckguy Jun 13, 2023
1e31419
Added pre-commit hook (#1024)
Smit-Parmar Jun 13, 2023
8785a2a
Bump vite from 3.2.5 to 3.2.7 in /src/js/app (#1005)
dependabot[bot] Jun 13, 2023
1dcdc9c
Update LICENSE date
rmorshea Jun 14, 2023
678afe0
Add contributor license agreement
rmorshea Jun 15, 2023
a3d79aa
report better error for attrs that cannot be serialized (#1008)
rmorshea Jun 15, 2023
bd60e6e
Warn and fix missing mime types (#1050)
Archmonger Jun 15, 2023
403e5f2
fix docs typos (#1061)
Daemo00 Jun 16, 2023
6df7ecd
pre for 1.0.1 release (#1062)
rmorshea Jun 16, 2023
9bf3db7
fix how we collect tags on current commit (#1063)
rmorshea Jun 16, 2023
3f804ca
Update pull_request_template.md
rmorshea Jun 16, 2023
754a619
minor improvements to project setup (#1082)
rmorshea Jul 2, 2023
f065655
Fix publish (#1064)
rmorshea Jul 2, 2023
e82ffdf
Fix issue from #1081 (#1085)
rmorshea Jul 4, 2023
77303a3
`django-reactpy` -> `reactpy-django` (#1080)
Archmonger Jul 4, 2023
5582431
reactpy-v1.0.2 (#1087)
rmorshea Jul 4, 2023
773570b
V1.0.2 changelog (#1088)
rmorshea Jul 4, 2023
ff60ae7
Update pull_request_template.md
rmorshea Jul 4, 2023
778057d
fix ruff error + pin ruff ver for now (#1107)
rmorshea Jul 15, 2023
fb9c57f
`reactpy.run` and `configure(...)` refactoring (#1051)
Archmonger Jul 18, 2023
c42d85c
setsockopt on mac too
rmorshea Jul 24, 2023
99cd7b1
need to copy scheme from base url (#1118)
rmorshea Jul 24, 2023
f053551
delete accidentally committed file
rmorshea Jul 24, 2023
3faa10f
Try to fix lint (#1157)
rmorshea Oct 22, 2023
d3959e4
fix flaky test (#1158)
rmorshea Oct 22, 2023
701e462
Fix flask backend mimetype for modules (#1131)
elro444 Oct 22, 2023
341a492
Concurrent Renders (#1165)
rmorshea Dec 9, 2023
d6f9bfe
update nodejs install method in docker (#1168)
rmorshea Dec 9, 2023
43009e4
fix strict eq effect test (#1170)
rmorshea Dec 10, 2023
3a3ad3f
Skip rendering None in all situations (#1171)
rmorshea Dec 28, 2023
2101191
fix black lint (#1193)
rmorshea Feb 10, 2024
618e579
Update PR template and VSCode workspace (#1053)
Archmonger Mar 6, 2024
3f05f81
Use `utf-8` for reading files (#1200)
Archmonger Mar 6, 2024
2c6a1f7
Bump postcss from 8.4.24 to 8.4.35 in /src/js (#1205)
dependabot[bot] Mar 6, 2024
34a2d24
Bump postcss from 8.4.21 to 8.4.35 in /src/js/app (#1208)
dependabot[bot] Mar 6, 2024
97c3b19
Bump vite from 3.2.7 to 3.2.8 in /src/js (#1207)
dependabot[bot] Mar 6, 2024
044eb17
Bump vite from 3.2.7 to 3.2.8 in /src/js/app (#1206)
dependabot[bot] Mar 6, 2024
4307a09
Bump word-wrap from 1.2.3 to 1.2.5 in /src/js (#1209)
dependabot[bot] Mar 6, 2024
cc7830e
Concurrent rendering naming fixes
Archmonger Mar 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
report better error for attrs that cannot be serialized (reactive-pyt…
…hon#1008)

* report better error for attrs that cannot be serialized

also misc changes to config options to make this eaiser
in particular ability to specify options as parents

* add more tests

* no need to be clever - just inherit

* fix tests

* ignore missing cov

* add test for non-json serializable attrs

* add changelog entry

* fix tests

* try node 16?

https://github.com/nodesource/distributions#using-ubuntu-3

* install npm explicitey

* try install in different order

* update first

* explicitely install npm i guess...
  • Loading branch information
rmorshea authored Jun 15, 2023
commit a3d79aa8f5743ddbe4b0c229832bcf48d86d19e1
4 changes: 2 additions & 2 deletions docs/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ WORKDIR /app/

# Install NodeJS
# --------------
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get install -yq nodejs build-essential
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
RUN apt-get install -y build-essential nodejs npm
RUN npm install -g npm@8.5.0

# Install Poetry
Expand Down
5 changes: 4 additions & 1 deletion docs/source/about/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ more info, see the :ref:`Contributor Guide <Creating a Changelog Entry>`.
Unreleased
----------

No changes.
**Fixed**

- :issue:`930` - better traceback for JSON serialization errors (via :pull:`1008`)
- :issue:`437` - explain that JS component attributes must be JSON (via :pull:`1008`)


v1.0.0
Expand Down
51 changes: 36 additions & 15 deletions src/py/reactpy/reactpy/_option.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

_O = TypeVar("_O")
logger = getLogger(__name__)
UNDEFINED = cast(Any, object())


class Option(Generic[_O]):
Expand All @@ -16,8 +17,9 @@ class Option(Generic[_O]):
def __init__(
self,
name: str,
default: _O | Option[_O],
default: _O = UNDEFINED,
mutable: bool = True,
parent: Option[_O] | None = None,
validator: Callable[[Any], _O] = lambda x: cast(_O, x),
) -> None:
self._name = name
Expand All @@ -28,12 +30,15 @@ def __init__(
if name in os.environ:
self._current = validator(os.environ[name])

self._default: _O
if isinstance(default, Option):
self._default = default.default
default.subscribe(lambda value: setattr(self, "_default", value))
else:
if parent is not None:
if not (parent.mutable and self.mutable):
raise TypeError("Parent and child options must be mutable")
self._default = parent.default
parent.subscribe(self.set_current)
elif default is not UNDEFINED:
self._default = default
else:
raise TypeError("Must specify either a default or a parent option")

logger.debug(f"{self._name}={self.current}")

Expand Down Expand Up @@ -81,11 +86,19 @@ def set_current(self, new: Any) -> None:

Raises a ``TypeError`` if this option is not :attr:`Option.mutable`.
"""
old = self.current
if new is old:
return None

if not self._mutable:
msg = f"{self} cannot be modified after initial load"
raise TypeError(msg)
old = self.current
new = self._current = self._validator(new)

try:
new = self._current = self._validator(new)
except ValueError as error:
raise ValueError(f"Invalid value for {self._name}: {new!r}") from error

logger.debug(f"{self._name}={self._current}")
if new != old:
for sub_func in self._subscribers:
Expand Down Expand Up @@ -119,15 +132,23 @@ def __repr__(self) -> str:
return f"Option({self._name}={self.current!r})"


class DeprecatedOption(Option[_O]): # nocov
def __init__(self, message: str, *args: Any, **kwargs: Any) -> None:
self._deprecation_message = message
class DeprecatedOption(Option[_O]):
"""An option that will warn when it is accessed"""

def __init__(self, *args: Any, message: str, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self._deprecation_message = message

@Option.current.getter # type: ignore
def current(self) -> _O:
warn(
self._deprecation_message,
DeprecationWarning,
)
try:
# we access the current value during init to debug log it
# no need to warn unless it's actually used. since this attr
# is only set after super().__init__ is called, we can check
# for it to determine if it's being accessed by a user.
msg = self._deprecation_message
except AttributeError:
pass
else:
warn(msg, DeprecationWarning)
return super().current
2 changes: 1 addition & 1 deletion src/py/reactpy/reactpy/backend/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def vdom_head_elements_to_html(head: Sequence[VdomDict] | VdomDict | str) -> str
head = cast(VdomDict, {**head, "tagName": ""})
return vdom_to_html(head)
else:
return vdom_to_html(html._(head))
return vdom_to_html(html._(*head))


@dataclass
Expand Down
67 changes: 44 additions & 23 deletions src/py/reactpy/reactpy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,65 @@
variables or, for those which allow it, a programmatic interface.
"""

from __future__ import annotations

from pathlib import Path
from tempfile import TemporaryDirectory

from reactpy._option import Option as _Option
from reactpy._option import Option

REACTPY_DEBUG_MODE = _Option(
"REACTPY_DEBUG_MODE",
default=False,
validator=lambda x: bool(int(x)),
)
"""This immutable option turns on/off debug mode
TRUE_VALUES = {"true", "1"}
FALSE_VALUES = {"false", "0"}

The string values ``1`` and ``0`` are mapped to ``True`` and ``False`` respectively.

When debug is on, extra validation measures are applied that negatively impact
performance but can be used to catch bugs during development. Additionally, the default
log level for ReactPy is set to ``DEBUG``.
"""
def boolean(value: str | bool | int) -> bool:
if isinstance(value, bool):
return value
elif isinstance(value, int):
return bool(value)
elif not isinstance(value, str):
raise TypeError(f"Expected str or bool, got {type(value).__name__}")

if value.lower() in TRUE_VALUES:
return True
elif value.lower() in FALSE_VALUES:
return False
else:
raise ValueError(
f"Invalid boolean value {value!r} - expected "
f"one of {list(TRUE_VALUES | FALSE_VALUES)}"
)


REACTPY_CHECK_VDOM_SPEC = _Option(
"REACTPY_CHECK_VDOM_SPEC",
default=REACTPY_DEBUG_MODE,
validator=lambda x: bool(int(x)),
REACTPY_DEBUG_MODE = Option(
"REACTPY_DEBUG_MODE", default=False, validator=boolean, mutable=True
)
"""This immutable option turns on/off checks which ensure VDOM is rendered to spec
"""Get extra logs and validation checks at the cost of performance.

The string values ``1`` and ``0`` are mapped to ``True`` and ``False`` respectively.
This will enable the following:

By default this check is off. When ``REACTPY_DEBUG_MODE=1`` this will be turned on but can
be manually disablled by setting ``REACTPY_CHECK_VDOM_SPEC=0`` in addition.
- :data:`REACTPY_CHECK_VDOM_SPEC`
- :data:`REACTPY_CHECK_JSON_ATTRS`
"""

REACTPY_CHECK_VDOM_SPEC = Option("REACTPY_CHECK_VDOM_SPEC", parent=REACTPY_DEBUG_MODE)
"""Checks which ensure VDOM is rendered to spec

For more info on the VDOM spec, see here: :ref:`VDOM JSON Schema`
"""

# Because these web modules will be linked dynamically at runtime this can be temporary
REACTPY_CHECK_JSON_ATTRS = Option("REACTPY_CHECK_JSON_ATTRS", parent=REACTPY_DEBUG_MODE)
"""Checks that all VDOM attributes are JSON serializable

The VDOM spec is not able to enforce this on its own since attributes could anything.
"""

# Because these web modules will be linked dynamically at runtime this can be temporary.
# Assigning to a variable here ensures that the directory is not deleted until the end
# of the program.
_DEFAULT_WEB_MODULES_DIR = TemporaryDirectory()

REACTPY_WEB_MODULES_DIR = _Option(
REACTPY_WEB_MODULES_DIR = Option(
"REACTPY_WEB_MODULES_DIR",
default=Path(_DEFAULT_WEB_MODULES_DIR.name),
validator=Path,
Expand All @@ -52,7 +73,7 @@
set of publicly available APIs for working with the client.
"""

REACTPY_TESTING_DEFAULT_TIMEOUT = _Option(
REACTPY_TESTING_DEFAULT_TIMEOUT = Option(
"REACTPY_TESTING_DEFAULT_TIMEOUT",
5.0,
mutable=False,
Expand Down
14 changes: 13 additions & 1 deletion src/py/reactpy/reactpy/core/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from anyio import create_task_group
from anyio.abc import TaskGroup

from reactpy.config import REACTPY_DEBUG_MODE
from reactpy.core.types import LayoutEventMessage, LayoutType, LayoutUpdateMessage

logger = getLogger(__name__)
Expand Down Expand Up @@ -49,7 +50,18 @@ async def _single_outgoing_loop(
layout: LayoutType[LayoutUpdateMessage, LayoutEventMessage], send: SendCoroutine
) -> None:
while True:
await send(await layout.render())
update = await layout.render()
try:
await send(update)
except Exception: # nocov
if not REACTPY_DEBUG_MODE.current:
msg = (
"Failed to send update. More info may be available "
"if you enabling debug mode by setting "
"`reactpy.config.REACTPY_DEBUG_MODE.current = True`."
)
logger.error(msg)
raise


async def _single_incoming_loop(
Expand Down
15 changes: 7 additions & 8 deletions src/py/reactpy/reactpy/core/vdom.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from __future__ import annotations

import logging
import json
from collections.abc import Mapping, Sequence
from functools import wraps
from typing import Any, Protocol, cast, overload

from fastjsonschema import compile as compile_json_schema

from reactpy._warnings import warn
from reactpy.config import REACTPY_DEBUG_MODE
from reactpy.config import REACTPY_CHECK_JSON_ATTRS, REACTPY_DEBUG_MODE
from reactpy.core._f_back import f_module_name
from reactpy.core.events import EventHandler, to_event_handler_function
from reactpy.core.types import (
Expand All @@ -25,9 +25,6 @@
VdomJson,
)

logger = logging.getLogger()


VDOM_JSON_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema",
"$ref": "#/definitions/element",
Expand Down Expand Up @@ -199,6 +196,8 @@ def vdom(
attributes, event_handlers = separate_attributes_and_event_handlers(attributes)

if attributes:
if REACTPY_CHECK_JSON_ATTRS.current:
json.dumps(attributes)
model["attributes"] = attributes

if children:
Expand Down Expand Up @@ -325,18 +324,18 @@ def _is_single_child(value: Any) -> bool:

def _validate_child_key_integrity(value: Any) -> None:
if hasattr(value, "__iter__") and not hasattr(value, "__len__"):
logger.error(
warn(
f"Did not verify key-path integrity of children in generator {value} "
"- pass a sequence (i.e. list of finite length) in order to verify"
)
else:
for child in value:
if isinstance(child, ComponentType) and child.key is None:
logger.error(f"Key not specified for child in list {child}")
warn(f"Key not specified for child in list {child}", UserWarning)
elif isinstance(child, Mapping) and "key" not in child:
# remove 'children' to reduce log spam
child_copy = {**child, "children": _EllipsisRepr()}
logger.error(f"Key not specified for child in list {child_copy}")
warn(f"Key not specified for child in list {child_copy}", UserWarning)


class _CustomVdomDictConstructor(Protocol):
Expand Down
30 changes: 28 additions & 2 deletions src/py/reactpy/tests/test__option.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_option_validator():
opt.current = "0"
assert opt.current is False

with pytest.raises(ValueError, match="invalid literal for int"):
with pytest.raises(ValueError, match="Invalid value"):
opt.current = "not-an-int"


Expand Down Expand Up @@ -102,10 +102,36 @@ def test_option_subscribe():


def test_deprecated_option():
opt = DeprecatedOption("is deprecated!", "A_FAKE_OPTION", None)
opt = DeprecatedOption("A_FAKE_OPTION", None, message="is deprecated!")

with pytest.warns(DeprecationWarning, match="is deprecated!"):
assert opt.current is None

with pytest.warns(DeprecationWarning, match="is deprecated!"):
opt.current = "something"


def test_option_parent():
parent_opt = Option("A_FAKE_OPTION", "default-value", mutable=True)
child_opt = Option("A_FAKE_OPTION", parent=parent_opt)
assert child_opt.mutable
assert child_opt.current == "default-value"

parent_opt.current = "new-value"
assert child_opt.current == "new-value"


def test_option_parent_child_must_be_mutable():
mut_parent_opt = Option("A_FAKE_OPTION", "default-value", mutable=True)
immu_parent_opt = Option("A_FAKE_OPTION", "default-value", mutable=False)
with pytest.raises(TypeError, match="must be mutable"):
Option("A_FAKE_OPTION", parent=mut_parent_opt, mutable=False)
with pytest.raises(TypeError, match="must be mutable"):
Option("A_FAKE_OPTION", parent=immu_parent_opt, mutable=None)


def test_no_default_or_parent():
with pytest.raises(
TypeError, match="Must specify either a default or a parent option"
):
Option("A_FAKE_OPTION")
24 changes: 24 additions & 0 deletions src/py/reactpy/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,27 @@ def test_reactpy_debug_mode_toggle():
# just check that nothing breaks
config.REACTPY_DEBUG_MODE.current = True
config.REACTPY_DEBUG_MODE.current = False


def test_boolean():
assert config.boolean(True) is True
assert config.boolean(False) is False
assert config.boolean(1) is True
assert config.boolean(0) is False
assert config.boolean("true") is True
assert config.boolean("false") is False
assert config.boolean("True") is True
assert config.boolean("False") is False
assert config.boolean("TRUE") is True
assert config.boolean("FALSE") is False
assert config.boolean("1") is True
assert config.boolean("0") is False

with pytest.raises(ValueError):
config.boolean("2")

with pytest.raises(ValueError):
config.boolean("")

with pytest.raises(TypeError):
config.boolean(None)
Loading