diff --git a/docs/check-autoreacton.ipynb b/docs/check-autoreacton.ipynb new file mode 100644 index 00000000..df41b088 --- /dev/null +++ b/docs/check-autoreacton.ipynb @@ -0,0 +1,143 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "10166727-57df-4c2b-9c1d-dc2ba12a3a13", + "metadata": {}, + "outputs": [], + "source": [ + "from ipyautoui import autoreacton as ar" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "52b8e1aa-f2b7-4e54-9ac8-0e6ec98b27c4", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "869397c387ae4f8f9e7d6cea008c68e1", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "Cannot show widget. You probably want to rerun the code cell above (Click in the code cell, and press Shift+Enter +)." + ], + "text/plain": [ + "Cannot show ipywidgets in text" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ar.AutoBox()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "722396e3-1c5e-4366-b8ef-a7221e9b1de4", + "metadata": {}, + "outputs": [ + { + "ename": "RuntimeError", + "evalue": "Could not create widget with {'data': a b\n0 1 3\n1 2 4}", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:388\u001b[0m, in \u001b[0;36mElement._create_widget\u001b[0;34m(self, kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 388\u001b[0m widget \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcomponent\u001b[38;5;241m.\u001b[39mwidget(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 389\u001b[0m hold_trait_notifications \u001b[38;5;241m=\u001b[39m widget\u001b[38;5;241m.\u001b[39mhold_trait_notifications\n", + "\u001b[0;31mTypeError\u001b[0m: EditGrid.__init__() missing 1 required positional argument: 'schema'", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/IPython/core/formatters.py:922\u001b[0m, in \u001b[0;36mIPythonDisplayFormatter.__call__\u001b[0;34m(self, obj)\u001b[0m\n\u001b[1;32m 920\u001b[0m method \u001b[38;5;241m=\u001b[39m get_real_method(obj, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprint_method)\n\u001b[1;32m 921\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m method \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 922\u001b[0m method()\n\u001b[1;32m 923\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:332\u001b[0m, in \u001b[0;36mElement._ipython_display_\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 331\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_ipython_display_\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m--> 332\u001b[0m display(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmime_bundle)\n", + "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:2211\u001b[0m, in \u001b[0;36mdisplay\u001b[0;34m(el, mime_bundle)\u001b[0m\n\u001b[1;32m 2209\u001b[0m box \u001b[38;5;241m=\u001b[39m widgets\u001b[38;5;241m.\u001b[39mVBox(_view_count\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0\u001b[39m)\n\u001b[1;32m 2210\u001b[0m el \u001b[38;5;241m=\u001b[39m _wrap(el, jupyter_decorator_components)\n\u001b[0;32m-> 2211\u001b[0m widget, rc \u001b[38;5;241m=\u001b[39m render(el, container\u001b[38;5;241m=\u001b[39mbox)\n\u001b[1;32m 2212\u001b[0m displayed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 2214\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcheck_view_count\u001b[39m(change):\n", + "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:2171\u001b[0m, in \u001b[0;36mrender\u001b[0;34m(element, container, children_trait, handle_error, initial_state)\u001b[0m\n\u001b[1;32m 2169\u001b[0m container \u001b[38;5;241m=\u001b[39m container \u001b[38;5;129;01mor\u001b[39;00m widgets\u001b[38;5;241m.\u001b[39mVBox()\n\u001b[1;32m 2170\u001b[0m _rc \u001b[38;5;241m=\u001b[39m _RenderContext(element, container, children_trait\u001b[38;5;241m=\u001b[39mchildren_trait, handle_error\u001b[38;5;241m=\u001b[39mhandle_error, initial_state\u001b[38;5;241m=\u001b[39minitial_state)\n\u001b[0;32m-> 2171\u001b[0m _rc\u001b[38;5;241m.\u001b[39mrender(element, _rc\u001b[38;5;241m.\u001b[39mcontainer)\n\u001b[1;32m 2172\u001b[0m local\u001b[38;5;241m.\u001b[39mlast_rc \u001b[38;5;241m=\u001b[39m weakref\u001b[38;5;241m.\u001b[39mref(_rc)\n\u001b[1;32m 2173\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m container, _rc\n", + "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:1469\u001b[0m, in \u001b[0;36m_RenderContext.render\u001b[0;34m(***failed resolving arguments***)\u001b[0m\n\u001b[1;32m 1467\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreconsolidating \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 1468\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1469\u001b[0m widget \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reconsolidate(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39melement, default_key\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/\u001b[39m\u001b[38;5;124m\"\u001b[39m, parent_key\u001b[38;5;241m=\u001b[39mROOT_KEY)\n\u001b[1;32m 1470\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 1471\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreconsolidating \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n", + "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:1939\u001b[0m, in \u001b[0;36m_RenderContext._reconsolidate\u001b[0;34m(self, el, default_key, parent_key)\u001b[0m\n\u001b[1;32m 1937\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1938\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCreating new widget: \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m\"\u001b[39m, el, key)\n\u001b[0;32m-> 1939\u001b[0m widget, orphan_ids \u001b[38;5;241m=\u001b[39m el\u001b[38;5;241m.\u001b[39m_create_widget(kwargs)\n\u001b[1;32m 1941\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m el\u001b[38;5;241m.\u001b[39mis_shared:\n\u001b[1;32m 1942\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_shared_widgets[el] \u001b[38;5;241m=\u001b[39m widget\n", + "File \u001b[0;32m~/miniforge3/envs/ipyautoui-dev/lib/python3.12/site-packages/reacton/core.py:401\u001b[0m, in \u001b[0;36mElement._create_widget\u001b[0;34m(self, kwargs)\u001b[0m\n\u001b[1;32m 399\u001b[0m widget\u001b[38;5;241m.\u001b[39m_react_meta \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mdict\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_meta)\n\u001b[1;32m 400\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m--> 401\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCould not create widget \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcomponent\u001b[38;5;241m.\u001b[39mwidget\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m with \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkwargs\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01me\u001b[39;00m\n\u001b[1;32m 402\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m name, callback \u001b[38;5;129;01min\u001b[39;00m listeners\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m 403\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m callback \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "\u001b[0;31mRuntimeError\u001b[0m: Could not create widget with {'data': a b\n0 1 3\n1 2 4}" + ] + }, + { + "data": { + "text/plain": [ + "ipyautoui.custom.editgrid.EditGrid(data = a b\n", + "0 1 3\n", + "1 2 4)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "41aef1de-7061-44ef-aa7c-642c64b1b3f2", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1ab26b73259148c69224b8f69c64c2a6", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "Cannot show widget. You probably want to rerun the code cell above (Click in the code cell, and press Shift+Enter +)." + ], + "text/plain": [ + "Cannot show ipywidgets in text" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ar.SaveButtonBar()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a9cca53-19ab-4b35-af8f-ff5b89d0920b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/environment.yml b/environment.yml index 1c3b66d6..dc43bc89 100644 --- a/environment.yml +++ b/environment.yml @@ -21,6 +21,7 @@ dependencies: - altair # optional - halo # optional - plotly # optional + - reacton - pip - pip: - maplocal==0.2.1 diff --git a/src/ipyautoui/autoreacton.py b/src/ipyautoui/autoreacton.py new file mode 100644 index 00000000..b223beab --- /dev/null +++ b/src/ipyautoui/autoreacton.py @@ -0,0 +1,173 @@ +import datetime +import typing +from typing import Any, Dict, Union + +import ipywidgets +import numpy as np +from numpy import ndarray + +import reacton +from reacton.core import ContainerAdder, Element, _get_render_context + +from reacton import ipywidgets as w +from reacton.ipywidgets import Layout +from reacton.utils import implements + +import ipyautoui +from ipyautoui import autoui +from ipywidgets import * + +from collections.abc import Sequence + +# to execute run: +# `python -m ipyautoui.autoreacton` + +if __name__ == "__main__": + from reacton import generate + + class CodeGen(generate.CodeGen): + def get_extra_argument(self, cls): + return {ipywidgets.Button: [("on_click", None, typing.Callable[[], Any])]}.get(cls, []) + + current_module = __import__(__name__) + + CodeGen([autoui]).generate(__file__) + +# generated code: + + +def _AutoBox( + align_horizontal: bool = True, + box_style: str = "", + children: Sequence[Element[ipywidgets.Widget]] = (), + description: str = None, + hide: bool = True, + indent: bool = False, + layout: Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]] = {}, + nested: bool = False, + show_description: bool = True, + show_title: bool = True, + tabbable: bool = None, + title: str = None, + tooltip: str = None, + widget: Any = ToggleButton(value=False, layout=Layout(width="600px"), tooltip="placeholder..."), + on_align_horizontal: typing.Callable[[bool], Any] = None, + on_box_style: typing.Callable[[str], Any] = None, + on_children: typing.Callable[[Sequence[Element[ipywidgets.Widget]]], Any] = None, + on_description: typing.Callable[[str], Any] = None, + on_hide: typing.Callable[[bool], Any] = None, + on_indent: typing.Callable[[bool], Any] = None, + on_layout: typing.Callable[[Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]]], Any] = None, + on_nested: typing.Callable[[bool], Any] = None, + on_show_description: typing.Callable[[bool], Any] = None, + on_show_title: typing.Callable[[bool], Any] = None, + on_tabbable: typing.Callable[[bool], Any] = None, + on_title: typing.Callable[[str], Any] = None, + on_tooltip: typing.Callable[[str], Any] = None, + on_widget: typing.Callable[[Any], Any] = None, +) -> Element[ipyautoui.autobox.AutoBox]: + """ + :param box_style: Use a predefined styling for the box. + :param children: List of widget children + :param tabbable: Is widget tabbable? + :param tooltip: A tooltip caption. + """ + ... + + +@implements(_AutoBox) +def AutoBox(**kwargs): + if isinstance(kwargs.get("layout"), dict): + kwargs["layout"] = w.Layout(**kwargs["layout"]) + widget_cls = ipyautoui.autobox.AutoBox + comp = reacton.core.ComponentWidget(widget=widget_cls) + return Element(comp, kwargs=kwargs) + + +del _AutoBox + + +def _EditGrid( + box_style: str = "", + children: Sequence[Element[ipywidgets.Widget]] = (), + close_crud_dialogue_on_action: bool = False, + description: str = None, + layout: Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]] = {}, + show_copy_dialogue: bool = False, + show_description: bool = True, + show_title: bool = True, + tabbable: bool = None, + title: str = None, + tooltip: str = None, + warn_on_delete: bool = False, + on_box_style: typing.Callable[[str], Any] = None, + on_children: typing.Callable[[Sequence[Element[ipywidgets.Widget]]], Any] = None, + on_close_crud_dialogue_on_action: typing.Callable[[bool], Any] = None, + on_description: typing.Callable[[str], Any] = None, + on_layout: typing.Callable[[Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]]], Any] = None, + on_show_copy_dialogue: typing.Callable[[bool], Any] = None, + on_show_description: typing.Callable[[bool], Any] = None, + on_show_title: typing.Callable[[bool], Any] = None, + on_tabbable: typing.Callable[[bool], Any] = None, + on_title: typing.Callable[[str], Any] = None, + on_tooltip: typing.Callable[[str], Any] = None, + on_warn_on_delete: typing.Callable[[bool], Any] = None, +) -> Element[ipyautoui.custom.editgrid.EditGrid]: + """ + :param box_style: Use a predefined styling for the box. + :param children: List of widget children + :param tabbable: Is widget tabbable? + :param tooltip: A tooltip caption. + """ + ... + + +@implements(_EditGrid) +def EditGrid(**kwargs): + if isinstance(kwargs.get("layout"), dict): + kwargs["layout"] = w.Layout(**kwargs["layout"]) + widget_cls = ipyautoui.custom.editgrid.EditGrid + comp = reacton.core.ComponentWidget(widget=widget_cls) + return Element(comp, kwargs=kwargs) + + +del _EditGrid + + +def _SaveButtonBar( + box_style: str = "", + children: Sequence[Element[ipywidgets.Widget]] = (), + fns_onrevert: list = [], + fns_onsave: list = [], + layout: Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]] = {}, + tabbable: bool = None, + tooltip: str = None, + unsaved_changes: bool = False, + on_box_style: typing.Callable[[str], Any] = None, + on_children: typing.Callable[[Sequence[Element[ipywidgets.Widget]]], Any] = None, + on_fns_onrevert: typing.Callable[[list], Any] = None, + on_fns_onsave: typing.Callable[[list], Any] = None, + on_layout: typing.Callable[[Union[Dict[str, Any], Element[ipywidgets.widgets.widget_layout.Layout]]], Any] = None, + on_tabbable: typing.Callable[[bool], Any] = None, + on_tooltip: typing.Callable[[str], Any] = None, + on_unsaved_changes: typing.Callable[[bool], Any] = None, +) -> Element[ipyautoui.custom.buttonbars.SaveButtonBar]: + """ + :param box_style: Use a predefined styling for the box. + :param children: List of widget children + :param tabbable: Is widget tabbable? + :param tooltip: A tooltip caption. + """ + ... + + +@implements(_SaveButtonBar) +def SaveButtonBar(**kwargs): + if isinstance(kwargs.get("layout"), dict): + kwargs["layout"] = w.Layout(**kwargs["layout"]) + widget_cls = ipyautoui.custom.buttonbars.SaveButtonBar + comp = reacton.core.ComponentWidget(widget=widget_cls) + return Element(comp, kwargs=kwargs) + + +del _SaveButtonBar