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

Long callbacks are unintuitive #888

Open
AlexandreSajus opened this issue Mar 20, 2024 · 3 comments
Open

Long callbacks are unintuitive #888

AlexandreSajus opened this issue Mar 20, 2024 · 3 comments
Labels
📄 Documentation Internal or public documentation 🖰 GUI Related to GUI 📈 Improvement Improvement of a feature. 🟧 Priority: High Stalls work on the project or its dependents 🔒 Staff only Restricted to CC staff members

Comments

@AlexandreSajus
Copy link
Contributor

TLDR

Long callbacks have a weird and buggy argument structure. The documentation does not provide working examples

Documentation

The documentation contains three pages about long callbacks:

All three pages ramble with only text and code. They do not provide a single working example that the user can try out and instead use:

def heavy_function(...):
    # Do something that takes time...

This is so unclear that I read all three pages and could not do a long callback. I had to go through our demos to find out how to use a long callback and get the result.

Replacing all this text with a few working examples would go a long way:

import time
from taipy.gui import Gui, notify, invoke_long_callback

i = 0
counter = "Step 0"


def step():
    for _ in range(10):
        time.sleep(1)
    return None


def update(state):
    state.counter = f"Step {state.i}"
    state.i += 1
    print(f"Step {state.i}")


def launch_counter(state):
    notify(state, "info", "Starting the count")
    invoke_long_callback(state, step, [], update, [], 500)


page = """
<|Launch Counter|button|on_action=launch_counter|>
## <|{counter}|text|raw|>
"""

Gui(page).run()

image

Bugs

Even then, I still have a few questions:

  • The example I have given here does not work properly, it keeps counting infinitely instead of stopping at 10, why?
  • Why have both heavy_function and heavy_function_status? What is the point of heavy_function if I can't extract the result?
  • Not adding the last "500" argument to invoke_long_callback will break the function and never call heavy_function_update
@AlexandreSajus AlexandreSajus added 📈 Improvement Improvement of a feature. 📄 Documentation Internal or public documentation 🟧 Priority: High Stalls work on the project or its dependents 💬 Discussion Open for discussion and feedback labels Mar 20, 2024
@FredLL-Avaiga FredLL-Avaiga changed the title Long callbacks are unintuitive and unusable Long callbacks are unintuitive Mar 20, 2024
@FlorianJacta
Copy link
Member

FlorianJacta commented Mar 20, 2024

The example I have given here does not work properly, it keeps counting infinitely instead of stopping at 10, why?

It stops at 20, which is normal. Your interval is 500 so this function is called each 0.5 seconds and your heavy function takes 10 seconds.

Why have both heavy_function and heavy_function_status? What is the point of heavy_function if I can't extract the result?

You can extract it. Please take a look at the code below.

Not adding the last "500" argument to invoke_long_callback will break the function and never call heavy_function_update

It will not break. There's a bug if you don't specify user_function_args. We should create an issue on this.

We should create an issue on how to improve the doc and one on how to improve the ease of use of this feature.

I would want to add on example like this. Tell me if this example help you:

from taipy.gui import Gui, Markdown, invoke_long_callback, notify
import numpy as np

status = 0
num_iterations = 10_000_000
pi_list = []

def pi_approx(num_iterations):
    k, s = 3.0, 1.0
    pi_list = []
    for i in range(num_iterations):
        s = s-((1/k) * (-1)**i)
        k += 2
        if (i+1)%(int(num_iterations/1_000)+1) == 0:
            pi_list += [np.abs(4*s-np.pi)]

    return pi_list

    
def heavy_status(state, status, pi_list):
    notify(state, 'i', f"Status parameter: {status}")
    if isinstance(status, bool):
        if status:
            notify(state, 'success', "Finished")
            state.pi_list = pi_list
        else:
            notify(state, 'error', f"An error was raised")
    else:
        state.status += 1
    
def on_action(state):
    invoke_long_callback(state,
                         pi_approx, [int(state.num_iterations)],
                         heavy_status, [],
                         2000)  
        
page = Markdown("""
How many times was the status function called? <|{status}|>

## Number of approximation

<|{num_iterations}|number|label=# of approximation|>

<|Approximate pie|button|on_action=on_action|>

## Evolution of approximation
<|{pi_list}|chart|layout={layout}|>
""")

layout = {
    "yaxis": {
    "type": 'log',
    "autorange": True
    }
  }

Gui(page).run(port=1234, host="0.0.0.0")

@AlexandreSajus
Copy link
Contributor Author

@FlorianJacta added a good code example to the doc on long callback:
#882
#884

approx_pi

It might just be enough to fix this issue.

@jrobinAV
Copy link
Member

The Tutorial has been changed to include an example.

Remaining to do: Add a complete example downloadable from the user manual.

@jrobinAV jrobinAV removed the 💬 Discussion Open for discussion and feedback label Mar 22, 2024
@jrobinAV jrobinAV transferred this issue from Avaiga/taipy Mar 22, 2024
@jrobinAV jrobinAV added 🖰 GUI Related to GUI 🔒 Staff only Restricted to CC staff members labels Jul 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📄 Documentation Internal or public documentation 🖰 GUI Related to GUI 📈 Improvement Improvement of a feature. 🟧 Priority: High Stalls work on the project or its dependents 🔒 Staff only Restricted to CC staff members
Projects
None yet
Development

No branches or pull requests

3 participants