Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic loading maximum recursion error #46

Closed
dhnam opened this issue Sep 20, 2023 · 2 comments
Closed

Dynamic loading maximum recursion error #46

dhnam opened this issue Sep 20, 2023 · 2 comments

Comments

@dhnam
Copy link

dhnam commented Sep 20, 2023

import edifice as ed
from edifice import Label, TextInput, View, Button

METER_TO_FEET = 3.28084

def str_to_float(s:str):
    try:
        return float(s)
    except ValueError:
        return 0.0

class ConversionWidget(ed.Component):
    @ed.register_props
    def __init__(self, from_unit, to_unit, factor):
        super().__init__()
        self.current_text = "0.0"

    def render(self):
        from_text = self.current_text
        to_text = "%.3f" % (str_to_float(from_text) * self.props.factor)

        from_label_style = {"width": 170}
        to_label_style = {"margin-left": 20, "width": 200}
        input_style = {"padding": 2, "width": 120}
        return View(layout="row", style={"margin": 10, "width": 560})(
            Label(f"Measurement in {self.props.from_unit}:", style=from_label_style),
            TextInput(self.current_text, style=input_style,
                      on_change=lambda text: self.set_state(current_text=text)),
            Label(f"Measurement in {self.props.to_unit}: {to_text}", style=to_label_style),
        )

class MyApp(ed.Component):
    def __init__(self):
        super().__init__()
        self.meters:str = "0.0"
        self.conversions: list[ConversionWidget] = [
            ConversionWidget("meters", "feet", METER_TO_FEET),
            ConversionWidget("feet", "meters", 1/METER_TO_FEET),
        ]
        self.new_from:str = ""
        self.new_to:str = ""
        self.new_factor:str = ""

    def render(self):
        conversion = self.conversions
        return View(layout="column")(
            *conversion,
            View(layout="row")(
                Label("From"),
                TextInput(self.new_from, on_change=lambda text:self.set_state(new_from=text)),
                Label("To"),
                TextInput(self.new_to, on_change=lambda text:self.set_state(new_to=text)),
                Label("Factor"),
                TextInput(self.new_factor, on_change=lambda text:self.set_state(new_factor=text)),
                Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
            )
        )

if __name__ == "__main__":
    ed.App(MyApp()).start()

So was trying to add dynamic button in tutorial code.
This ran into problem (I didn't make on_click at the button to callable, adding lambda x: before self.set_state solved the problem)
And this is what I get when I run the code

Traceback (most recent call last):
  File "/workspaces/test-edifice/test.py", line 60, in <module>
    ed.App(MyApp()).start()
    ^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/app.py", line 121, in __init__
    rendered_component = component.render()
                         ^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-edifice/test.py", line 55, in render
    Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 408, in set_state
    raise e
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 404, in set_state
    self._controller._request_rerender([self], kwargs)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute '_request_rerender'

However, if I try to dynamic load the code using python -m pyedifice ./test.py MyApp from the code which can be run properly, something like this is occured

(...)
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 408, in set_state
    raise e
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 404, in set_state
    self._controller._request_rerender([self], kwargs)
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/app.py", line 193, in _request_rerender
    render_result = self._render_engine._request_rerender(components)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 425, in _request_rerender
    widget_trees = self._gen_widget_trees(components, render_context)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 418, in _gen_widget_trees
    widget_trees.append(self._render(component, render_context))
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 387, in _render
    sub_component = component.render()
                    ^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-edifice/test.py", line 55, in render
    Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 408, in set_state
    raise e
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 404, in set_state
    self._controller._request_rerender([self], kwargs)
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/app.py", line 193, in _request_rerender
    render_result = self._render_engine._request_rerender(components)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 425, in _request_rerender
    widget_trees = self._gen_widget_trees(components, render_context)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 418, in _gen_widget_trees
    widget_trees.append(self._render(component, render_context))
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 387, in _render
    sub_component = component.render()
                    ^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-edifice/test.py", line 55, in render
    Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 408, in set_state
    raise e
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 404, in set_state
    self._controller._request_rerender([self], kwargs)
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/app.py", line 193, in _request_rerender
    render_result = self._render_engine._request_rerender(components)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 425, in _request_rerender
    widget_trees = self._gen_widget_trees(components, render_context)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 418, in _gen_widget_trees
    widget_trees.append(self._render(component, render_context))
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 387, in _render
    sub_component = component.render()
                    ^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-edifice/test.py", line 55, in render
    Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 408, in set_state
    raise e
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 404, in set_state
    self._controller._request_rerender([self], kwargs)
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/app.py", line 193, in _request_rerender
    render_result = self._render_engine._request_rerender(components)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 425, in _request_rerender
    widget_trees = self._gen_widget_trees(components, render_context)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 418, in _gen_widget_trees
    widget_trees.append(self._render(component, render_context))
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 387, in _render
    sub_component = component.render()
                    ^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-edifice/test.py", line 55, in render
    Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 408, in set_state
    raise e
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/_component.py", line 404, in set_state
    self._controller._request_rerender([self], kwargs)
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/app.py", line 193, in _request_rerender
    render_result = self._render_engine._request_rerender(components)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 423, in _request_rerender
    with _storage_manager() as storage_manager:
  File "/usr/local/lib/python3.11/contextlib.py", line 155, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 47, in _storage_manager
    changes.unwind()
  File "/home/vscode/.local/lib/python3.11/site-packages/edifice/engine.py", line 27, in unwind
    logger.warning("Encountered error while rendering. Unwinding changes.")
  File "/usr/local/lib/python3.11/logging/__init__.py", line 1501, in warning
    self._log(WARNING, msg, args, **kwargs)
  File "/usr/local/lib/python3.11/logging/__init__.py", line 1632, in _log
    record = self.makeRecord(self.name, level, fn, lno, msg, args,
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/logging/__init__.py", line 1601, in makeRecord
    rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/logging/__init__.py", line 326, in __init__
    self.filename = os.path.basename(pathname)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen posixpath>", line 143, in basename
Stemming from these renders:
  File "/workspaces/test-edifice/test.py", line 55, in render
    Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-edifice/test.py", line 55, in render
    Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspaces/test-edifice/test.py", line 55, in render
    Button("Press Me", on_click=self.set_state(conversions=conversion + [ConversionWidget(self.new_from, self.new_to, str_to_float(self.new_factor))])),
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 160 more times]
  File "/usr/local/lib/python3.11/contextlib.py", line 155, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/usr/local/lib/python3.11/logging/__init__.py", line 1501, in warning
    self._log(WARNING, msg, args, **kwargs)
  File "/usr/local/lib/python3.11/logging/__init__.py", line 1632, in _log
    record = self.makeRecord(self.name, level, fn, lno, msg, args,
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/logging/__init__.py", line 1601, in makeRecord
    rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/logging/__init__.py", line 326, in __init__
    self.filename = os.path.basename(pathname)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen posixpath>", line 143, in basename
RecursionError: maximum recursion depth exceeded
@jamesdbrock
Copy link
Member

Does

make on_click at the button to callable, adding lambda x: before self.set_state solved the problem

also solve the maximum recursion depth problem?

@dhnam
Copy link
Author

dhnam commented Sep 22, 2023

Yup... As it removes the exception itself.

If the code has no error, it works as excepted; but I expected this to work 'normally' with error too - showing which error/exception is occurred with current code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants