Avaiga / taipy-doc

Holds the documentation set for Taipy, not including the code documentation obviously.
https://docs.taipy.io/
Apache License 2.0
16 stars 23 forks source link

Long callbacks are unintuitive #888

Open AlexandreSajus opened 7 months ago

AlexandreSajus commented 7 months ago

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:

FlorianJacta commented 7 months ago

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 commented 7 months ago

@FlorianJacta added a good code example to the doc on long callback: https://github.com/Avaiga/taipy-doc/pull/882 https://github.com/Avaiga/taipy-doc/pull/884

approx_pi

It might just be enough to fix this issue.

jrobinAV commented 7 months ago

The Tutorial has been changed to include an example.

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