nicegui icon indicating copy to clipboard operation
nicegui copied to clipboard

Remove the "interactive mode"

Open falkoschindler opened this issue 3 years ago • 3 comments

Discussed in https://github.com/zauberzeug/nicegui/discussions/71

Originally posted by falkoschindler August 26, 2022 When NiceGUI doesn't find a ui.run(), it runs in a so-called "interactive mode". Originally it was introduced to be able to use NiceGUI interactively in Python shells like python or ipython.

Although it is of little use to interactively build UIs, it might be useful to allow importing modules that depend on NiceGUI. E.g. suppose you have written a prime number checker my_prime that comes with a function is_prime(n) and a tiny UI factory method show_sieve_of_eratosthenes(). Thanks to the interactive mode you can start python, import my_prime and fiddle around with the function is_prime(n). NiceGUI is fine with not finding ui.run() and simply doesn't start a server.

The other important use case are PyTests: We might need to import modules that depend on NiceGUI, but there is no ui.run() and thus no server needs to start.

So the purpose of this mode is actually quite clear. But the following questions remain:

  • Is it the right name? Interaction is actually not possible, since ui.run() is forbidden in interactive mode ("Error: Unexpected ui.run() in interactive mode.").
  • Is the warning correct when importing NiceGUI in a Python shell? "Could not find main script. Starting interactive mode without auto-reload." Actually it is not starting anything.
  • Can we detect when running in a PyTest and avoid printing a warning at all?

falkoschindler avatar Aug 31 '22 07:08 falkoschindler

I tried to remove the interactive mode on this branch: https://github.com/zauberzeug/nicegui/tree/remove_interactive_mode

Looks promising, but needs a bit more testing.

falkoschindler avatar Aug 31 '22 07:08 falkoschindler

Now I introduced a new flag globals.pre_evaluation_succeeded. This makes decisions in ui.run more explicit, but does not introduce an "internal" configuration flag like interactive was.

I tested the different scenarios with the following test script:

#!/usr/bin/env python3
from nicegui import ui

ui.label('Hello, world!')
print('MAIN', flush=True)

# ui.run(port=1234, title='Test', main_page_classes='', reload=False, dark=True, exclude='three')
# ui.run(port=1234, title='Test', main_page_classes='', reload=True, dark=True, exclude='three')
# ui.run(port=1234+0, title='Test', main_page_classes='', reload=False, dark=True, exclude='three')
# ui.run(port=1234+0, title='Test', main_page_classes='', reload=True, dark=True, exclude='three')

Uncommenting different ui.run lines I checked the following aspects:

  • Without ui.run: "MAIN" is be printed exactly once and no server is started (the script simply terminates).
  • With port=1234 pre-evaluation succeeds and all arguments are taken into account:
    • The page runs on port 1234.
    • The title is set to "Test".
    • There are no margins (caused by clearing main_page_classes).
    • The background is dark.
    • The three.js library is not served.
  • With port=1234+0 pre-evaluation fails. Everything still works, but:
    • If reload=True, a warning is shown that main will run a second time. "MAIN" is printed twice.
    • If exclude is non-empty, a warning is show that this argument is ignored (exclude has to be known at import phase).

Everything seems to work as expected.

falkoschindler avatar Aug 31 '22 12:08 falkoschindler

By the way: The previous implementation opens the browser on 127.0.0.1 if NiceGUI is started with host=0.0.0.0 - but only if reload=True. The new implementation uses 127.0.0.1 consistently.

falkoschindler avatar Aug 31 '22 17:08 falkoschindler

I merged the branch into main. This is the diff: https://github.com/zauberzeug/nicegui/compare/426f420a0fa427979797e1e0c275edf0fc771c0d...30010cd6a12142deff62ada34bf511750cc494ed

falkoschindler avatar Sep 01 '22 14:09 falkoschindler

I created a new release v0.8.9.

rodja avatar Sep 03 '22 04:09 rodja