From e8263de6e7b0a23069268ed563b59acd3fd8130e Mon Sep 17 00:00:00 2001 From: Ryan Morshead Date: Wed, 22 Feb 2023 20:56:47 -0800 Subject: [PATCH] Rewrite style props (#936) * rewrite style prop + other fixes * apply rewrites * changelog * remove extra print * minor annotation improvement * fix class_name * more helpful error message * fix types * fix typo --- docs/examples.py | 4 +- docs/source/_exts/custom_autosectionlabel.py | 7 +- docs/source/about/changelog.rst | 4 +- .../_examples/moving_dot.py | 6 +- .../_examples/moving_dot_broken.py | 6 +- .../_examples/set_remove.py | 2 +- .../_examples/set_update.py | 2 +- .../_examples/set_color_3_times.py | 5 +- .../_examples/audio_player.py | 2 +- .../_examples/stop_event_propagation.py | 8 +- .../_examples/character_movement/main.py | 2 +- .../source/reference/_examples/click_count.py | 3 +- .../reference/_examples/matplotlib_plot.py | 11 +-- .../reference/_examples/simple_dashboard.py | 2 +- docs/source/reference/_examples/slideshow.py | 2 +- docs/source/reference/_examples/snake_game.py | 13 ++- docs/source/reference/_examples/todo.py | 4 +- .../_examples/use_reducer_counter.py | 6 +- .../reference/_examples/use_state_counter.py | 6 +- src/idom/_console/ast_utils.py | 7 +- src/idom/_console/rewrite_camel_case_props.py | 93 ++++++++++++------- src/idom/core/layout.py | 5 +- .../test_rewrite_camel_case_props.py | 12 +++ tests/test_backend/test_all.py | 2 +- tests/test_client.py | 6 +- tests/test_core/test_events.py | 20 ++-- tests/test_core/test_hooks.py | 10 +- tests/test_core/test_layout.py | 18 ++-- tests/test_core/test_serve.py | 4 +- 29 files changed, 157 insertions(+), 115 deletions(-) diff --git a/docs/examples.py b/docs/examples.py index 7b9a5160a..4bcbf5148 100644 --- a/docs/examples.py +++ b/docs/examples.py @@ -122,7 +122,9 @@ def Wrapper(): def PrintView(): text, set_text = idom.hooks.use_state(print_buffer.getvalue()) print_buffer.set_callback(set_text) - return idom.html.pre({"class": "printout"}, text) if text else idom.html.div() + return ( + idom.html.pre({"class_name": "printout"}, text) if text else idom.html.div() + ) return Wrapper() diff --git a/docs/source/_exts/custom_autosectionlabel.py b/docs/source/_exts/custom_autosectionlabel.py index 573bc35dd..9610ad684 100644 --- a/docs/source/_exts/custom_autosectionlabel.py +++ b/docs/source/_exts/custom_autosectionlabel.py @@ -4,8 +4,10 @@ https://github.com/sphinx-doc/sphinx/blob/f9968594206e538f13fa1c27c065027f10d4ea27/LICENSE """ +from __future__ import annotations + from fnmatch import fnmatch -from typing import Any, Dict, cast +from typing import Any, cast from docutils import nodes from docutils.nodes import Node @@ -30,7 +32,6 @@ def get_node_depth(node: Node) -> int: def register_sections_as_label(app: Sphinx, document: Node) -> None: docname = app.env.docname - print(docname) for pattern in app.config.autosectionlabel_skip_docs: if fnmatch(docname, pattern): @@ -67,7 +68,7 @@ def register_sections_as_label(app: Sphinx, document: Node) -> None: domain.labels[name] = docname, labelid, sectname -def setup(app: Sphinx) -> Dict[str, Any]: +def setup(app: Sphinx) -> dict[str, Any]: app.add_config_value("autosectionlabel_prefix_document", False, "env") app.add_config_value("autosectionlabel_maxdepth", None, "env") app.add_config_value("autosectionlabel_skip_docs", [], "env") diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst index e4d213ab7..b110f7c73 100644 --- a/docs/source/about/changelog.rst +++ b/docs/source/about/changelog.rst @@ -23,7 +23,9 @@ more info, see the :ref:`Contributor Guide `. Unreleased ---------- -No changes. +**Fixed** + +- :pull:`936` - remaining issues from :pull:`934` v1.0.0-a5 diff --git a/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/moving_dot.py b/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/moving_dot.py index d2a62db14..6e5e66b67 100644 --- a/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/moving_dot.py +++ b/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/moving_dot.py @@ -22,15 +22,15 @@ async def handle_pointer_move(event): "position": "relative", "height": "200px", "width": "100%", - "backgroundColor": "white", + "background_color": "white", }, }, html.div( { "style": { "position": "absolute", - "backgroundColor": "red", - "borderRadius": "50%", + "background_color": "red", + "border_radius": "50%", "width": "20px", "height": "20px", "left": "-10px", diff --git a/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/moving_dot_broken.py b/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/moving_dot_broken.py index 446670d3c..68198c93a 100644 --- a/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/moving_dot_broken.py +++ b/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/moving_dot_broken.py @@ -20,15 +20,15 @@ def handle_pointer_move(event): "position": "relative", "height": "200px", "width": "100%", - "backgroundColor": "white", + "background_color": "white", }, }, html.div( { "style": { "position": "absolute", - "backgroundColor": "red", - "borderRadius": "50%", + "background_color": "red", + "border_radius": "50%", "width": "20px", "height": "20px", "left": "-10px", diff --git a/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/set_remove.py b/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/set_remove.py index a949f6e02..a56eaa9ab 100644 --- a/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/set_remove.py +++ b/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/set_remove.py @@ -24,7 +24,7 @@ def handle_click(event): "style": { "height": "30px", "width": "30px", - "backgroundColor": "black" + "background_color": "black" if index in selected_indices else "white", "outline": "1px solid grey", diff --git a/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/set_update.py b/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/set_update.py index 84ef48d94..0d38462fa 100644 --- a/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/set_update.py +++ b/docs/source/guides/adding-interactivity/dangers-of-mutability/_examples/set_update.py @@ -21,7 +21,7 @@ def handle_click(event): "style": { "height": "30px", "width": "30px", - "backgroundColor": "black" + "background_color": "black" if index in selected_indices else "white", "outline": "1px solid grey", diff --git a/docs/source/guides/adding-interactivity/multiple-state-updates/_examples/set_color_3_times.py b/docs/source/guides/adding-interactivity/multiple-state-updates/_examples/set_color_3_times.py index 4453bf9f0..d4c8f3e77 100644 --- a/docs/source/guides/adding-interactivity/multiple-state-updates/_examples/set_color_3_times.py +++ b/docs/source/guides/adding-interactivity/multiple-state-updates/_examples/set_color_3_times.py @@ -15,10 +15,11 @@ def handle_reset(event): return html.div( html.button( - {"on_click": handle_click, "style": {"backgroundColor": color}}, "Set Color" + {"on_click": handle_click, "style": {"background_color": color}}, + "Set Color", ), html.button( - {"on_click": handle_reset, "style": {"backgroundColor": color}}, "Reset" + {"on_click": handle_reset, "style": {"background_color": color}}, "Reset" ), ) diff --git a/docs/source/guides/adding-interactivity/responding-to-events/_examples/audio_player.py b/docs/source/guides/adding-interactivity/responding-to-events/_examples/audio_player.py index 582588a8c..41e216971 100644 --- a/docs/source/guides/adding-interactivity/responding-to-events/_examples/audio_player.py +++ b/docs/source/guides/adding-interactivity/responding-to-events/_examples/audio_player.py @@ -10,7 +10,7 @@ def PlayDinosaurSound(): idom.html.audio( { "controls": True, - "onTimeUpdate": lambda e: set_event(e), + "on_time_update": lambda e: set_event(e), "src": "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3", } ), diff --git a/docs/source/guides/adding-interactivity/responding-to-events/_examples/stop_event_propagation.py b/docs/source/guides/adding-interactivity/responding-to-events/_examples/stop_event_propagation.py index 944c48be0..0a7543ce7 100644 --- a/docs/source/guides/adding-interactivity/responding-to-events/_examples/stop_event_propagation.py +++ b/docs/source/guides/adding-interactivity/responding-to-events/_examples/stop_event_propagation.py @@ -10,7 +10,7 @@ def DivInDiv(): div_in_div = html.div( { "on_click": lambda event: set_outer_count(outer_count + 1), - "style": {"height": "100px", "width": "100px", "backgroundColor": "red"}, + "style": {"height": "100px", "width": "100px", "background_color": "red"}, }, html.div( { @@ -18,7 +18,11 @@ def DivInDiv(): lambda event: set_inner_count(inner_count + 1), stop_propagation=stop_propagatation, ), - "style": {"height": "50px", "width": "50px", "backgroundColor": "blue"}, + "style": { + "height": "50px", + "width": "50px", + "background_color": "blue", + }, } ), ) diff --git a/docs/source/reference/_examples/character_movement/main.py b/docs/source/reference/_examples/character_movement/main.py index 1c5e0a9d3..6183d9199 100644 --- a/docs/source/reference/_examples/character_movement/main.py +++ b/docs/source/reference/_examples/character_movement/main.py @@ -42,7 +42,7 @@ def Scene(): "style": { "width": "200px", "height": "200px", - "backgroundColor": "slategray", + "background_color": "slategray", } }, image( diff --git a/docs/source/reference/_examples/click_count.py b/docs/source/reference/_examples/click_count.py index 6f30ce517..040da3cf1 100644 --- a/docs/source/reference/_examples/click_count.py +++ b/docs/source/reference/_examples/click_count.py @@ -6,8 +6,7 @@ def ClickCount(): count, set_count = idom.hooks.use_state(0) return idom.html.button( - {"onClick": lambda event: set_count(count + 1)}, - [f"Click count: {count}"], + {"on_click": lambda event: set_count(count + 1)}, [f"Click count: {count}"] ) diff --git a/docs/source/reference/_examples/matplotlib_plot.py b/docs/source/reference/_examples/matplotlib_plot.py index eb8210544..c19d2b19b 100644 --- a/docs/source/reference/_examples/matplotlib_plot.py +++ b/docs/source/reference/_examples/matplotlib_plot.py @@ -39,8 +39,8 @@ def del_input(): return idom.html.div( idom.html.div( "add/remove term:", - idom.html.button({"onClick": lambda event: add_input()}, "+"), - idom.html.button({"onClick": lambda event: del_input()}, "-"), + idom.html.button({"on_click": lambda event: add_input()}, "+"), + idom.html.button({"on_click": lambda event: del_input()}, "-"), ), inputs, ) @@ -65,12 +65,7 @@ def poly_coef_input(index, callback): " × X", idom.html.sup(index), ), - idom.html.input( - { - "type": "number", - "onChange": callback, - }, - ), + idom.html.input({"type": "number", "on_change": callback}), ) diff --git a/docs/source/reference/_examples/simple_dashboard.py b/docs/source/reference/_examples/simple_dashboard.py index 540082f58..81e696489 100644 --- a/docs/source/reference/_examples/simple_dashboard.py +++ b/docs/source/reference/_examples/simple_dashboard.py @@ -83,7 +83,7 @@ def update_value(value): set_value_callback(value) return idom.html.fieldset( - {"class": "number-input-container"}, + {"class_name": "number-input-container"}, idom.html.legend({"style": {"font-size": "medium"}}, label), Input(update_value, "number", value, attributes=attrs, cast=float), Input(update_value, "range", value, attributes=attrs, cast=float), diff --git a/docs/source/reference/_examples/slideshow.py b/docs/source/reference/_examples/slideshow.py index 0d3116ac4..3c6488932 100644 --- a/docs/source/reference/_examples/slideshow.py +++ b/docs/source/reference/_examples/slideshow.py @@ -12,7 +12,7 @@ def next_image(event): { "src": f"https://picsum.photos/id/{index}/800/300", "style": {"cursor": "pointer"}, - "onClick": next_image, + "on_click": next_image, } ) diff --git a/docs/source/reference/_examples/snake_game.py b/docs/source/reference/_examples/snake_game.py index b9f9938dd..34955c438 100644 --- a/docs/source/reference/_examples/snake_game.py +++ b/docs/source/reference/_examples/snake_game.py @@ -21,8 +21,7 @@ def GameView(): return GameLoop(grid_size=6, block_scale=50, set_game_state=set_game_state) start_button = idom.html.button( - {"onClick": lambda event: set_game_state(GameState.play)}, - "Start", + {"on_click": lambda event: set_game_state(GameState.play)}, "Start" ) if game_state == GameState.won: @@ -40,7 +39,7 @@ def GameView(): """ ) - return idom.html.div({"className": "snake-game-menu"}, menu_style, menu) + return idom.html.div({"class_name": "snake-game-menu"}, menu_style, menu) class Direction(enum.Enum): @@ -72,7 +71,7 @@ def on_direction_change(event): if direction_vector_sum != (0, 0): direction.current = maybe_new_direction - grid_wrapper = idom.html.div({"onKeyDown": on_direction_change}, grid) + grid_wrapper = idom.html.div({"on_key_down": on_direction_change}, grid) assign_grid_block_color(grid, food, "blue") @@ -149,7 +148,7 @@ def create_grid(grid_size, block_scale): "grid-template-columns": f"repeat({grid_size}, {block_scale}px)", "grid-template-rows": f"repeat({grid_size}, {block_scale}px)", }, - "tabIndex": -1, + "tab_index": -1, }, [ idom.html.div( @@ -170,11 +169,11 @@ def create_grid_block(color, block_scale, key): "style": { "height": f"{block_scale}px", "width": f"{block_scale}px", - "backgroundColor": color, + "background_color": color, "outline": "1px solid grey", }, "key": key, - }, + } ) diff --git a/docs/source/reference/_examples/todo.py b/docs/source/reference/_examples/todo.py index 7b1f6f675..a6648e8b0 100644 --- a/docs/source/reference/_examples/todo.py +++ b/docs/source/reference/_examples/todo.py @@ -17,10 +17,10 @@ async def remove_task(event, index=index): set_items(items[:index] + items[index + 1 :]) task_text = idom.html.td(idom.html.p(text)) - delete_button = idom.html.td({"onClick": remove_task}, idom.html.button(["x"])) + delete_button = idom.html.td({"on_click": remove_task}, idom.html.button(["x"])) tasks.append(idom.html.tr(task_text, delete_button)) - task_input = idom.html.input({"onKeyDown": add_new_task}) + task_input = idom.html.input({"on_key_down": add_new_task}) task_table = idom.html.table(tasks) return idom.html.div( diff --git a/docs/source/reference/_examples/use_reducer_counter.py b/docs/source/reference/_examples/use_reducer_counter.py index ea1b780a0..22a43efdd 100644 --- a/docs/source/reference/_examples/use_reducer_counter.py +++ b/docs/source/reference/_examples/use_reducer_counter.py @@ -17,9 +17,9 @@ def Counter(): count, dispatch = idom.hooks.use_reducer(reducer, 0) return idom.html.div( f"Count: {count}", - idom.html.button({"onClick": lambda event: dispatch("reset")}, "Reset"), - idom.html.button({"onClick": lambda event: dispatch("increment")}, "+"), - idom.html.button({"onClick": lambda event: dispatch("decrement")}, "-"), + idom.html.button({"on_click": lambda event: dispatch("reset")}, "Reset"), + idom.html.button({"on_click": lambda event: dispatch("increment")}, "+"), + idom.html.button({"on_click": lambda event: dispatch("decrement")}, "-"), ) diff --git a/docs/source/reference/_examples/use_state_counter.py b/docs/source/reference/_examples/use_state_counter.py index 8626a60b9..42a8b249a 100644 --- a/docs/source/reference/_examples/use_state_counter.py +++ b/docs/source/reference/_examples/use_state_counter.py @@ -15,9 +15,9 @@ def Counter(): count, set_count = idom.hooks.use_state(initial_count) return idom.html.div( f"Count: {count}", - idom.html.button({"onClick": lambda event: set_count(initial_count)}, "Reset"), - idom.html.button({"onClick": lambda event: set_count(increment)}, "+"), - idom.html.button({"onClick": lambda event: set_count(decrement)}, "-"), + idom.html.button({"on_click": lambda event: set_count(initial_count)}, "Reset"), + idom.html.button({"on_click": lambda event: set_count(increment)}, "+"), + idom.html.button({"on_click": lambda event: set_count(decrement)}, "-"), ) diff --git a/src/idom/_console/ast_utils.py b/src/idom/_console/ast_utils.py index f2419b70b..c70833175 100644 --- a/src/idom/_console/ast_utils.py +++ b/src/idom/_console/ast_utils.py @@ -101,10 +101,9 @@ def find_element_constructor_usages( continue func = node.func - if ( - isinstance(func, ast.Attribute) - and isinstance(func.value, ast.Name) - and func.value.id == "html" + if isinstance(func, ast.Attribute) and ( + (isinstance(func.value, ast.Name) and func.value.id == "html") + or (isinstance(func.value, ast.Attribute) and func.value.attr == "html") ): name = func.attr elif isinstance(func, ast.Name): diff --git a/src/idom/_console/rewrite_camel_case_props.py b/src/idom/_console/rewrite_camel_case_props.py index 7335b2d7a..43b0cc75a 100644 --- a/src/idom/_console/rewrite_camel_case_props.py +++ b/src/idom/_console/rewrite_camel_case_props.py @@ -3,8 +3,10 @@ import ast import re import sys +from copy import copy from keyword import kwlist from pathlib import Path +from typing import Callable import click @@ -46,43 +48,66 @@ def generate_rewrite(file: Path, source: str) -> str | None: def find_nodes_to_change(tree: ast.AST) -> list[ChangedNode]: changed: list[ChangedNode] = [] for el_info in find_element_constructor_usages(tree): - if isinstance(el_info.props, ast.Dict): - did_change = False - keys: list[ast.expr | None] = [] - for k in el_info.props.keys: - if isinstance(k, ast.Constant) and isinstance(k.value, str): - new_prop_name = conv_attr_name(k.value) - if new_prop_name != k.value: - did_change = True - keys.append(ast.Constant(new_prop_name)) - else: - keys.append(k) - else: - keys.append(k) - if not did_change: - continue - el_info.props.keys = keys - else: - did_change = False - keywords: list[ast.keyword] = [] - for kw in el_info.props.keywords: - if kw.arg is not None: - new_prop_name = conv_attr_name(kw.arg) - if new_prop_name != kw.arg: - did_change = True - keywords.append(ast.keyword(arg=new_prop_name, value=kw.value)) - else: - keywords.append(kw) - else: - keywords.append(kw) - if not did_change: - continue - el_info.props.keywords = keywords - - changed.append(ChangedNode(el_info.call, el_info.parents)) + if _rewrite_props(el_info.props, _construct_prop_item): + changed.append(ChangedNode(el_info.call, el_info.parents)) return changed def conv_attr_name(name: str) -> str: new_name = CAMEL_CASE_SUB_PATTERN.sub("_", name).lower() return f"{new_name}_" if new_name in kwlist else new_name + + +def _construct_prop_item(key: str, value: ast.expr) -> tuple[str, ast.expr]: + if key == "style" and isinstance(value, (ast.Dict, ast.Call)): + new_value = copy(value) + if _rewrite_props( + new_value, + lambda k, v: ( + (k, v) + # avoid infinite recursion + if k == "style" + else _construct_prop_item(k, v) + ), + ): + value = new_value + else: + key = conv_attr_name(key) + return key, value + + +def _rewrite_props( + props_node: ast.Dict | ast.Call, + constructor: Callable[[str, ast.expr], tuple[str, ast.expr]], +) -> bool: + if isinstance(props_node, ast.Dict): + did_change = False + keys: list[ast.expr | None] = [] + values: list[ast.expr] = [] + for k, v in zip(props_node.keys, props_node.values): + if isinstance(k, ast.Constant) and isinstance(k.value, str): + k_value, new_v = constructor(k.value, v) + if k_value != k.value or new_v is not v: + did_change = True + k = ast.Constant(value=k_value) + v = new_v + keys.append(k) + values.append(v) + if not did_change: + return False + props_node.keys = keys + props_node.values = values + else: + did_change = False + keywords: list[ast.keyword] = [] + for kw in props_node.keywords: + if kw.arg is not None: + kw_arg, kw_value = constructor(kw.arg, kw.value) + if kw_arg != kw.arg or kw_value is not kw.value: + did_change = True + kw = ast.keyword(arg=kw_arg, value=kw_value) + keywords.append(kw) + if not did_change: + return False + props_node.keywords = keywords + return True diff --git a/src/idom/core/layout.py b/src/idom/core/layout.py index 167b70040..1e111f108 100644 --- a/src/idom/core/layout.py +++ b/src/idom/core/layout.py @@ -199,7 +199,10 @@ def _render_model( new_state: _ModelState, raw_model: Any, ) -> None: - new_state.model.current = {"tagName": raw_model["tagName"]} + try: + new_state.model.current = {"tagName": raw_model["tagName"]} + except Exception as e: # pragma: no cover + raise ValueError(f"Expected a VDOM element dict, not {raw_model}") from e if "key" in raw_model: new_state.key = new_state.model.current["key"] = raw_model["key"] if "importSource" in raw_model: diff --git a/tests/test__console/test_rewrite_camel_case_props.py b/tests/test__console/test_rewrite_camel_case_props.py index d460ca6f8..28532848e 100644 --- a/tests/test__console/test_rewrite_camel_case_props.py +++ b/tests/test__console/test_rewrite_camel_case_props.py @@ -49,6 +49,18 @@ def test_rewrite_camel_case_props_declarations_no_files(): "html.div(dict(camelCase='test'))", "html.div(dict(camel_case='test'))", ), + ( + "idom.html.button({'onClick': block_forever})", + "idom.html.button({'on_click': block_forever})", + ), + ( + "html.div(dict(style={'testThing': test}))", + "html.div(dict(style={'test_thing': test}))", + ), + ( + "html.div(dict(style=dict(testThing=test)))", + "html.div(dict(style=dict(test_thing=test)))", + ), ( "vdom('tag', dict(camelCase='test'))", "vdom('tag', dict(camel_case='test'))", diff --git a/tests/test_backend/test_all.py b/tests/test_backend/test_all.py index 98036cb16..8be33f212 100644 --- a/tests/test_backend/test_all.py +++ b/tests/test_backend/test_all.py @@ -58,7 +58,7 @@ def Counter(): return idom.html.button( { "id": "counter", - "onClick": lambda event: set_count(lambda old_count: old_count + 1), + "on_click": lambda event: set_count(lambda old_count: old_count + 1), }, f"Count: {count}", ) diff --git a/tests/test_client.py b/tests/test_client.py index 2f1501e8b..da32aaf95 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -87,8 +87,8 @@ def ButtonWithChangingColor(): return idom.html.button( { "id": "my-button", - "onClick": lambda event: set_color_toggle(not color_toggle), - "style": {"backgroundColor": color, "color": "white"}, + "on_click": lambda event: set_color_toggle(not color_toggle), + "style": {"background_color": color, "color": "white"}, }, f"color: {color}", ) @@ -126,7 +126,7 @@ async def handle_change(event): await asyncio.sleep(delay) set_value(event["target"]["value"]) - return idom.html.input({"onChange": handle_change, "id": "test-input"}) + return idom.html.input({"on_change": handle_change, "id": "test-input"}) await display.show(SomeComponent) diff --git a/tests/test_core/test_events.py b/tests/test_core/test_events.py index 89f1dfa4c..702518547 100644 --- a/tests/test_core/test_events.py +++ b/tests/test_core/test_events.py @@ -151,7 +151,7 @@ def Input(): async def on_key_down(value): pass - return idom.html.input({"onKeyDown": on_key_down, "id": "input"}) + return idom.html.input({"on_key_down": on_key_down, "id": "input"}) await display.show(Input) @@ -170,7 +170,9 @@ async def on_click(event): set_clicked(True) if not clicked: - return idom.html.button({"onClick": on_click, "id": "click"}, ["Click Me!"]) + return idom.html.button( + {"on_click": on_click, "id": "click"}, ["Click Me!"] + ) else: return idom.html.p({"id": "complete"}, ["Complete"]) @@ -195,12 +197,8 @@ def outer_click_is_not_triggered(event): outer = idom.html.div( { - "style": { - "height": "35px", - "width": "35px", - "backgroundColor": "red", - }, - "onClick": outer_click_is_not_triggered, + "style": {"height": "35px", "width": "35px", "background_color": "red"}, + "on_click": outer_click_is_not_triggered, "id": "outer", }, idom.html.div( @@ -208,11 +206,11 @@ def outer_click_is_not_triggered(event): "style": { "height": "30px", "width": "30px", - "backgroundColor": "blue", + "background_color": "blue", }, - "onClick": inner_click_no_op, + "on_click": inner_click_no_op, "id": "inner", - }, + } ), ) return outer diff --git a/tests/test_core/test_hooks.py b/tests/test_core/test_hooks.py index 91a00fe1d..6fe659aaf 100644 --- a/tests/test_core/test_hooks.py +++ b/tests/test_core/test_hooks.py @@ -183,14 +183,14 @@ def TestComponent(): idom.html.button( { "id": "r_1", - "onClick": event_count_tracker(lambda event: set_state(r_1)), + "on_click": event_count_tracker(lambda event: set_state(r_1)), }, "r_1", ), idom.html.button( { "id": "r_2", - "onClick": event_count_tracker(lambda event: set_state(r_2)), + "on_click": event_count_tracker(lambda event: set_state(r_2)), }, "r_2", ), @@ -237,7 +237,7 @@ async def on_change(event): set_message(event["target"]["value"]) if message is None: - return idom.html.input({"id": "input", "onChange": on_change}) + return idom.html.input({"id": "input", "on_change": on_change}) else: return idom.html.p({"id": "complete"}, ["Complete"]) @@ -267,7 +267,9 @@ def double_set_state(event): idom.html.div( {"id": "second", "data-value": state_2}, f"value is: {state_2}" ), - idom.html.button({"id": "button", "onClick": double_set_state}, "click me"), + idom.html.button( + {"id": "button", "on_click": double_set_state}, "click me" + ), ) await display.show(SomeComponent) diff --git a/tests/test_core/test_layout.py b/tests/test_core/test_layout.py index 657d2597b..b66352589 100644 --- a/tests/test_core/test_layout.py +++ b/tests/test_core/test_layout.py @@ -506,10 +506,10 @@ def bad_trigger(): children = [ idom.html.button( - {"onClick": good_trigger, "id": "good", "key": "good"}, "good" + {"on_click": good_trigger, "id": "good", "key": "good"}, "good" ), idom.html.button( - {"onClick": bad_trigger, "id": "bad", "key": "bad"}, "bad" + {"on_click": bad_trigger, "id": "bad", "key": "bad"}, "bad" ), ] @@ -567,7 +567,7 @@ def callback(): def callback(): raise ValueError("Called bad trigger") - return idom.html.button({"onClick": callback, "id": "good"}, "good") + return idom.html.button({"on_click": callback, "id": "good"}, "good") async with idom.Layout(RootComponent()) as layout: await layout.render() @@ -649,8 +649,8 @@ def HasEventHandlerAtRoot(): value, set_value = idom.hooks.use_state(False) set_value(not value) # trigger renders forever event_handler.current = weakref(set_value) - button = idom.html.button({"onClick": set_value}, "state is: ", value) - event_handler.current = weakref(button["eventHandlers"]["onClick"].function) + button = idom.html.button({"on_click": set_value}, "state is: ", value) + event_handler.current = weakref(button["eventHandlers"]["on_click"].function) return button async with idom.Layout(HasEventHandlerAtRoot()) as layout: @@ -671,8 +671,8 @@ def HasNestedEventHandler(): value, set_value = idom.hooks.use_state(False) set_value(not value) # trigger renders forever event_handler.current = weakref(set_value) - button = idom.html.button({"onClick": set_value}, "state is: ", value) - event_handler.current = weakref(button["eventHandlers"]["onClick"].function) + button = idom.html.button({"on_click": set_value}, "state is: ", value) + event_handler.current = weakref(button["eventHandlers"]["on_click"].function) return idom.html.div(idom.html.div(button)) async with idom.Layout(HasNestedEventHandler()) as layout: @@ -753,7 +753,7 @@ def ComponentWithBadEventHandler(): def raise_error(): raise Exception("bad event handler") - return idom.html.button({"onClick": raise_error}) + return idom.html.button({"on_click": raise_error}) with assert_idom_did_log(match_error="bad event handler"): async with idom.Layout(ComponentWithBadEventHandler()) as layout: @@ -850,7 +850,7 @@ def SomeComponent(): [ idom.html.div( {"key": i}, - idom.html.input({"onChange": lambda event: None}), + idom.html.input({"on_change": lambda event: None}), ) for i in items ] diff --git a/tests/test_core/test_serve.py b/tests/test_core/test_serve.py index 6798b5654..18ea8853e 100644 --- a/tests/test_core/test_serve.py +++ b/tests/test_core/test_serve.py @@ -115,8 +115,8 @@ async def handle_event(): second_event_did_execute.set() return idom.html.div( - idom.html.button({"onClick": block_forever}), - idom.html.button({"onClick": handle_event}), + idom.html.button({"on_click": block_forever}), + idom.html.button({"on_click": handle_event}), ) send_queue = asyncio.Queue()