Repository: h2oai/wave
File: py/h2o_wave/cli.py (Python)

Code before:
    Run path/to/app.py without auto reload:
    $ wave run --no-reload path.to.app
    $ wave run --no-reload path/to/app.py
    """

    app_address = urlparse(os.environ.get('H2O_WAVE_APP_ADDRESS', f'http://{_localhost}:{_scan_free_port()}'))
    host = app_address.hostname
    port = app_address.port

    addr = f'http://{host}:{port}'
    os.environ['H2O_WAVE_INTERNAL_ADDRESS'] = addr  # TODO deprecated
    os.environ['H2O_WAVE_EXTERNAL_ADDRESS'] = addr  # TODO deprecated
    os.environ['H2O_WAVE_APP_ADDRESS'] = addr

    # Make "python -m h2o_wave run" behave identical to "wave run":
    # Insert cwd into path, otherwise uvicorn fails to locate the app module.
    # uvicorn.main() does this before calling uvicorn.run().
    sys.path.insert(0, '.')

    # DevX: treat foo/bar/baz.py as foo.bar.baz
    app_path, ext = os.path.splitext(app)
    if ext.lower() == '.py':
        app = app_path.replace(os.path.sep, '.')

    # Try to start Wave daemon.
    try:
        exe = './waved'
        cwd = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..', '..')

        if 'Windows' in platform.system():
            # Windows venv dir structure is different than unix-based OS.
            cwd = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..') + '\\'
            exe = 'waved.exe'

        subprocess.Popen([exe], cwd=cwd, env=os.environ.copy(), shell=True)
    finally:
        uvicorn.run(f'{app}:main', host=_localhost, port=port, reload=not no_reload)


@main.command()
def ide():
    uvicorn.run('h2o_wave.ide:ide', host=_localhost, port=10100)


Review comment (bug):
Just my observation.

`try`/`finally` block feels unnecessary, but maybe it's on purpose:
1. The only function you want to `try` seems to be `Popen()`. You can move the `try` keyword right before. 🤔 
2. `finally` is executed regardless of exception. This might be what you want to run the `wave` app even if the try block fails.


Code after:
    Run path/to/app.py without auto reload:
    $ wave run --no-reload path.to.app
    $ wave run --no-reload path/to/app.py
    """

    app_address = urlparse(os.environ.get('H2O_WAVE_APP_ADDRESS', f'http://{_localhost}:{_scan_free_port()}'))
    host = app_address.hostname
    port = app_address.port

    addr = f'http://{host}:{port}'
    os.environ['H2O_WAVE_INTERNAL_ADDRESS'] = addr  # TODO deprecated
    os.environ['H2O_WAVE_EXTERNAL_ADDRESS'] = addr  # TODO deprecated
    os.environ['H2O_WAVE_APP_ADDRESS'] = addr

    # Make "python -m h2o_wave run" behave identical to "wave run":
    # Insert cwd into path, otherwise uvicorn fails to locate the app module.
    # uvicorn.main() does this before calling uvicorn.run().
    sys.path.insert(0, '.')

    # DevX: treat foo/bar/baz.py as foo.bar.baz
    app_path, ext = os.path.splitext(app)
    if ext.lower() == '.py':
        app = app_path.replace(os.path.sep, '.')

    # Try to start Wave daemon.
    try:
        subprocess.Popen(['waved.exe' if 'Windows' in platform.system() else './waved'],
                         cwd=sys.exec_prefix, env=os.environ.copy(), shell=True)
    finally:
        uvicorn.run(f'{app}:main', host=_localhost, port=port, reload=not no_reload)


@main.command()
def ide():
    uvicorn.run('h2o_wave.ide:ide', host=_localhost, port=10100)