2023-05-20 21:26:16 +00:00
from __future__ import annotations
2022-08-27 18:32:28 +00:00
import os
2023-01-03 15:38:21 +00:00
import sys
2022-10-01 20:47:42 +00:00
import time
2022-10-01 21:50:03 +00:00
import importlib
2022-08-31 08:04:19 +00:00
import signal
2023-01-04 01:43:05 +00:00
import re
2023-03-12 12:51:12 +00:00
import warnings
2023-03-29 21:46:03 +00:00
import json
2023-05-02 06:08:00 +00:00
from threading import Thread
2023-05-19 14:28:41 +00:00
from typing import Iterable
2023-05-02 06:08:00 +00:00
2023-06-12 09:21:01 +00:00
from fastapi import FastAPI
2022-11-04 18:36:47 +00:00
from fastapi . middleware . cors import CORSMiddleware
2022-10-07 21:56:00 +00:00
from fastapi . middleware . gzip import GZipMiddleware
2023-01-23 14:17:31 +00:00
from packaging import version
2022-10-07 21:56:00 +00:00
2023-01-23 18:28:59 +00:00
import logging
2023-05-19 13:08:40 +00:00
2023-06-30 10:44:58 +00:00
# We can't use cmd_opts for this because it will not have been initialized at this point.
log_level = os . environ . get ( " SD_WEBUI_LOG_LEVEL " )
if log_level :
log_level = getattr ( logging , log_level . upper ( ) , None ) or logging . INFO
logging . basicConfig (
level = log_level ,
format = ' %(asctime)s %(levelname)s [ %(name)s ] %(message)s ' ,
datefmt = ' % Y- % m- %d % H: % M: % S ' ,
)
logging . getLogger ( " torch.distributed.nn " ) . setLevel ( logging . ERROR ) # sshh...
2023-01-23 18:28:59 +00:00
logging . getLogger ( " xformers " ) . addFilter ( lambda record : ' A matching Triton is not available ' not in record . getMessage ( ) )
2023-05-21 18:55:14 +00:00
from modules import paths , timer , import_hook , errors , devices # noqa: F401
2023-03-11 13:27:58 +00:00
2023-05-20 21:41:41 +00:00
startup_timer = timer . startup_timer
2022-10-06 10:21:32 +00:00
2023-01-04 01:43:05 +00:00
import torch
2023-05-10 06:02:23 +00:00
import pytorch_lightning # noqa: F401 # pytorch_lightning should be imported after torch, but it re-enables warnings on import so import once to disable them
2023-03-14 11:46:09 +00:00
warnings . filterwarnings ( action = " ignore " , category = DeprecationWarning , module = " pytorch_lightning " )
2023-03-30 14:57:54 +00:00
warnings . filterwarnings ( action = " ignore " , category = UserWarning , module = " torchvision " )
2023-04-29 09:36:50 +00:00
2023-03-30 14:57:54 +00:00
2023-03-11 13:27:58 +00:00
startup_timer . record ( " import torch " )
import gradio
startup_timer . record ( " import gradio " )
2023-05-10 06:02:23 +00:00
import ldm . modules . encoders . modules # noqa: F401
2023-03-11 13:27:58 +00:00
startup_timer . record ( " import ldm " )
2023-05-19 12:35:16 +00:00
from modules import extra_networks
2023-05-11 07:09:29 +00:00
from modules . call_queue import wrap_gradio_gpu_call , wrap_queued_call , queue_lock # noqa: F401
2023-01-21 05:36:07 +00:00
2023-01-04 01:43:05 +00:00
# Truncate version number of nightly/local build of PyTorch to not cause exceptions with CodeFormer or Safetensors
if " .dev " in torch . __version__ or " +git " in torch . __version__ :
2023-02-18 16:31:02 +00:00
torch . __long_version__ = torch . __version__
2023-01-06 12:06:26 +00:00
torch . __version__ = re . search ( r ' [ \ d.]+[ \ d] ' , torch . __version__ ) . group ( 0 )
2023-01-04 01:43:05 +00:00
2023-05-10 05:43:42 +00:00
from modules import shared , sd_samplers , upscaler , extensions , localization , ui_tempdir , ui_extra_networks , config_states
2022-09-26 14:29:50 +00:00
import modules . codeformer_model as codeformer
import modules . face_restoration
import modules . gfpgan_model as gfpgan
2022-09-03 09:08:45 +00:00
import modules . img2img
2022-10-02 12:56:22 +00:00
2022-09-26 14:29:50 +00:00
import modules . lowvram
import modules . scripts
import modules . sd_hijack
2023-05-18 19:48:28 +00:00
import modules . sd_hijack_optimizations
2022-09-17 09:05:04 +00:00
import modules . sd_models
2022-10-30 14:54:31 +00:00
import modules . sd_vae
2023-05-27 12:47:33 +00:00
import modules . sd_unet
2022-09-26 14:29:50 +00:00
import modules . txt2img
2022-10-30 14:46:43 +00:00
import modules . script_callbacks
2023-01-09 20:35:40 +00:00
import modules . textual_inversion . textual_inversion
2023-01-15 15:50:56 +00:00
import modules . progress
2022-10-02 12:56:22 +00:00
2022-09-26 14:29:50 +00:00
import modules . ui
2022-09-26 15:27:18 +00:00
from modules import modelloader
2022-09-26 14:29:50 +00:00
from modules . shared import cmd_opts
2022-10-11 12:51:22 +00:00
import modules . hypernetworks . hypernetwork
2022-09-03 09:08:45 +00:00
2023-03-11 13:27:58 +00:00
startup_timer . record ( " other imports " )
2022-11-27 08:52:53 +00:00
2022-11-14 20:07:13 +00:00
if cmd_opts . server_name :
server_name = cmd_opts . server_name
else :
server_name = " 0.0.0.0 " if cmd_opts . listen else None
2022-09-08 09:17:26 +00:00
2022-11-27 08:52:53 +00:00
2023-04-29 07:21:01 +00:00
def fix_asyncio_event_loop_policy ( ) :
"""
The default ` asyncio ` event loop policy only automatically creates
event loops in the main threads . Other threads must create event
loops explicitly or ` asyncio . get_event_loop ` ( and therefore
` . IOLoop . current ` ) will fail . Installing this policy allows event
loops to be created automatically on any thread , matching the
behavior of Tornado versions prior to 5.0 ( or 5.0 on Python 2 ) .
"""
2023-04-03 09:05:49 +00:00
2023-04-29 07:21:01 +00:00
import asyncio
2023-04-03 09:05:49 +00:00
2023-04-29 07:21:01 +00:00
if sys . platform == " win32 " and hasattr ( asyncio , " WindowsSelectorEventLoopPolicy " ) :
# "Any thread" and "selector" should be orthogonal, but there's not a clean
# interface for composing policies so pick the right base.
_BasePolicy = asyncio . WindowsSelectorEventLoopPolicy # type: ignore
else :
_BasePolicy = asyncio . DefaultEventLoopPolicy
2023-04-03 09:05:49 +00:00
2023-04-29 07:21:01 +00:00
class AnyThreadEventLoopPolicy ( _BasePolicy ) : # type: ignore
""" Event loop policy that allows loop creation on any thread.
Usage : :
2023-04-03 09:05:49 +00:00
2023-04-29 07:21:01 +00:00
asyncio . set_event_loop_policy ( AnyThreadEventLoopPolicy ( ) )
"""
2023-04-03 09:05:49 +00:00
2023-04-29 07:21:01 +00:00
def get_event_loop ( self ) - > asyncio . AbstractEventLoop :
try :
return super ( ) . get_event_loop ( )
except ( RuntimeError , AssertionError ) :
# This was an AssertionError in python 3.4.2 (which ships with debian jessie)
# and changed to a RuntimeError in 3.4.3.
# "There is no current event loop in thread %r"
loop = self . new_event_loop ( )
self . set_event_loop ( loop )
return loop
2023-04-03 09:05:49 +00:00
2023-04-29 07:21:01 +00:00
asyncio . set_event_loop_policy ( AnyThreadEventLoopPolicy ( ) )
2023-04-03 09:05:49 +00:00
2022-11-27 08:52:53 +00:00
2023-01-23 14:17:31 +00:00
def check_versions ( ) :
2023-01-30 11:56:28 +00:00
if shared . cmd_opts . skip_version_check :
return
2023-04-29 09:36:50 +00:00
expected_torch_version = " 2.0.0 "
2023-01-23 14:17:31 +00:00
if version . parse ( torch . __version__ ) < version . parse ( expected_torch_version ) :
errors . print_error_explanation ( f """
You are running torch { torch . __version__ } .
The program is tested to work with torch { expected_torch_version } .
To reinstall the desired version , run with commandline flag - - reinstall - torch .
2023-01-30 11:56:28 +00:00
Beware that this will cause a lot of large files to be downloaded , as well as
there are reports of issues with training tab on the latest version .
Use - - skip - version - check commandline argument to disable this check .
2023-01-23 14:17:31 +00:00
""" .strip())
2023-05-28 12:42:19 +00:00
expected_xformers_version = " 0.0.20 "
2023-01-23 14:17:31 +00:00
if shared . xformers_available :
import xformers
if version . parse ( xformers . __version__ ) < version . parse ( expected_xformers_version ) :
errors . print_error_explanation ( f """
You are running xformers { xformers . __version__ } .
The program is tested to work with xformers { expected_xformers_version } .
To reinstall the desired version , run with commandline flag - - reinstall - xformers .
2023-01-30 11:56:28 +00:00
Use - - skip - version - check commandline argument to disable this check .
2023-01-23 14:17:31 +00:00
""" .strip())
2023-05-17 14:06:45 +00:00
def restore_config_state_file ( ) :
2023-03-29 21:46:03 +00:00
config_state_file = shared . opts . restore_config_state_file
2023-05-17 14:06:45 +00:00
if config_state_file == " " :
return
2023-03-29 21:46:03 +00:00
shared . opts . restore_config_state_file = " "
shared . opts . save ( shared . config_filename )
if os . path . isfile ( config_state_file ) :
print ( f " *** About to restore extension state from file: { config_state_file } " )
with open ( config_state_file , " r " , encoding = " utf-8 " ) as f :
config_state = json . load ( f )
2023-03-29 23:32:54 +00:00
config_states . restore_extension_config ( config_state )
2023-03-29 21:46:03 +00:00
startup_timer . record ( " restore extension config " )
2023-03-30 00:22:45 +00:00
elif config_state_file :
2023-03-29 23:32:54 +00:00
print ( f " !!! Config state backup not found: { config_state_file } " )
2023-03-29 21:46:03 +00:00
2023-05-17 14:06:45 +00:00
2023-05-19 12:52:29 +00:00
def validate_tls_options ( ) :
if not ( cmd_opts . tls_keyfile and cmd_opts . tls_certfile ) :
return
try :
if not os . path . exists ( cmd_opts . tls_keyfile ) :
print ( " Invalid path to TLS keyfile given " )
if not os . path . exists ( cmd_opts . tls_certfile ) :
print ( f " Invalid path to TLS certfile: ' { cmd_opts . tls_certfile } ' " )
except TypeError :
cmd_opts . tls_keyfile = cmd_opts . tls_certfile = None
print ( " TLS setup invalid, running webui without TLS " )
else :
print ( " Running with TLS " )
startup_timer . record ( " TLS " )
2023-05-19 14:28:41 +00:00
def get_gradio_auth_creds ( ) - > Iterable [ tuple [ str , . . . ] ] :
"""
Convert the gradio_auth and gradio_auth_path commandline arguments into
an iterable of ( username , password ) tuples .
"""
def process_credential_line ( s ) - > tuple [ str , . . . ] | None :
s = s . strip ( )
if not s :
return None
return tuple ( s . split ( ' : ' , 1 ) )
if cmd_opts . gradio_auth :
for cred in cmd_opts . gradio_auth . split ( ' , ' ) :
cred = process_credential_line ( cred )
if cred :
yield cred
if cmd_opts . gradio_auth_path :
with open ( cmd_opts . gradio_auth_path , ' r ' , encoding = " utf8 " ) as file :
for line in file . readlines ( ) :
for cred in line . strip ( ) . split ( ' , ' ) :
cred = process_credential_line ( cred )
if cred :
yield cred
2023-05-19 12:54:47 +00:00
def configure_sigint_handler ( ) :
# make the program just exit at ctrl+c without waiting for anything
def sigint_handler ( sig , frame ) :
print ( f ' Interrupted with signal { sig } in { frame } ' )
os . _exit ( 0 )
if not os . environ . get ( " COVERAGE_RUN " ) :
# Don't install the immediate-quit handler when running under coverage,
# as then the coverage report won't be generated.
signal . signal ( signal . SIGINT , sigint_handler )
2023-05-19 13:00:53 +00:00
def configure_opts_onchange ( ) :
shared . opts . onchange ( " sd_model_checkpoint " , wrap_queued_call ( lambda : modules . sd_models . reload_model_weights ( ) ) , call = False )
shared . opts . onchange ( " sd_vae " , wrap_queued_call ( lambda : modules . sd_vae . reload_vae_weights ( ) ) , call = False )
shared . opts . onchange ( " sd_vae_as_default " , wrap_queued_call ( lambda : modules . sd_vae . reload_vae_weights ( ) ) , call = False )
shared . opts . onchange ( " temp_dir " , ui_tempdir . on_tmpdir_changed )
shared . opts . onchange ( " gradio_theme " , shared . reload_gradio_theme )
2023-05-20 19:29:51 +00:00
shared . opts . onchange ( " cross_attention_optimization " , wrap_queued_call ( lambda : modules . sd_hijack . model_hijack . redo_hijack ( shared . sd_model ) ) , call = False )
2023-05-19 13:00:53 +00:00
startup_timer . record ( " opts onchange " )
2023-05-17 14:06:45 +00:00
def initialize ( ) :
fix_asyncio_event_loop_policy ( )
2023-05-19 12:52:29 +00:00
validate_tls_options ( )
2023-05-19 12:54:47 +00:00
configure_sigint_handler ( )
2023-05-17 14:06:45 +00:00
check_versions ( )
2023-05-19 13:08:40 +00:00
modelloader . cleanup_models ( )
configure_opts_onchange ( )
modules . sd_models . setup_model ( )
startup_timer . record ( " setup SD model " )
codeformer . setup_model ( cmd_opts . codeformer_models_path )
startup_timer . record ( " setup codeformer " )
gfpgan . setup_model ( cmd_opts . gfpgan_models_path )
startup_timer . record ( " setup gfpgan " )
initialize_rest ( reload_script_modules = False )
2023-05-17 14:06:45 +00:00
2023-05-19 13:08:40 +00:00
def initialize_rest ( * , reload_script_modules = False ) :
"""
Called both from initialize ( ) and when reloading the webui .
"""
sd_samplers . set_samplers ( )
2023-05-17 14:06:45 +00:00
extensions . list_extensions ( )
startup_timer . record ( " list extensions " )
restore_config_state_file ( )
2022-10-20 15:58:52 +00:00
if cmd_opts . ui_debug_mode :
2022-10-24 06:39:46 +00:00
shared . sd_upscalers = upscaler . UpscalerLanczos ( ) . scalers
modules . scripts . load_scripts ( )
2022-10-20 15:58:52 +00:00
return
2022-10-24 06:39:46 +00:00
2023-05-19 13:08:40 +00:00
modules . sd_models . list_models ( )
2023-03-11 13:27:58 +00:00
startup_timer . record ( " list SD models " )
2023-05-19 13:08:40 +00:00
localization . list_localizations ( cmd_opts . localizations_dir )
2022-08-25 18:52:05 +00:00
2023-05-20 21:41:41 +00:00
with startup_timer . subcategory ( " load scripts " ) :
modules . scripts . load_scripts ( )
2023-03-11 13:27:58 +00:00
2023-05-19 13:08:40 +00:00
if reload_script_modules :
for module in [ module for name , module in sys . modules . items ( ) if name . startswith ( " modules.ui " ) ] :
importlib . reload ( module )
startup_timer . record ( " reload script modules " )
2023-05-02 15:44:16 +00:00
modelloader . load_upscalers ( )
2023-05-10 20:41:08 +00:00
startup_timer . record ( " load upscalers " )
2023-05-02 15:44:16 +00:00
2022-10-30 14:54:31 +00:00
modules . sd_vae . refresh_vae_list ( )
2023-03-11 13:27:58 +00:00
startup_timer . record ( " refresh VAE " )
2023-01-09 20:35:40 +00:00
modules . textual_inversion . textual_inversion . list_textual_inversion_templates ( )
2023-03-11 13:27:58 +00:00
startup_timer . record ( " refresh textual inversion templates " )
2023-01-09 20:35:40 +00:00
2023-05-18 19:48:28 +00:00
modules . script_callbacks . on_list_optimizers ( modules . sd_hijack_optimizations . list_optimizers )
modules . sd_hijack . list_optimizers ( )
startup_timer . record ( " scripts list_optimizers " )
2023-05-27 12:47:33 +00:00
modules . sd_unet . list_unets ( )
startup_timer . record ( " scripts list_unets " )
2023-05-23 15:02:09 +00:00
def load_model ( ) :
"""
Accesses shared . sd_model property to load model .
After it ' s available, if it has been loaded before this access by some extension,
its optimization may be None because the list of optimizaers has neet been filled
by that time , so we apply optimization again .
"""
shared . sd_model # noqa: B018
if modules . sd_hijack . current_optimizer is None :
modules . sd_hijack . apply_optimizations ( )
Thread ( target = load_model ) . start ( )
2023-01-14 06:56:59 +00:00
2023-05-21 18:55:14 +00:00
Thread ( target = devices . first_time_calculation ) . start ( )
2023-01-14 06:56:59 +00:00
2023-01-21 05:36:07 +00:00
shared . reload_hypernetworks ( )
2023-05-19 13:08:40 +00:00
startup_timer . record ( " reload hypernetworks " )
2023-01-21 05:36:07 +00:00
2023-05-19 12:27:23 +00:00
ui_extra_networks . initialize ( )
2023-05-19 12:35:16 +00:00
ui_extra_networks . register_default_pages ( )
2023-01-21 05:36:07 +00:00
extra_networks . initialize ( )
2023-05-19 12:35:16 +00:00
extra_networks . register_default_extra_networks ( )
2023-05-19 13:08:40 +00:00
startup_timer . record ( " initialize extra networks " )
2022-08-31 19:19:30 +00:00
2022-10-02 18:26:38 +00:00
2023-03-11 17:01:08 +00:00
def setup_middleware ( app ) :
2023-05-19 12:37:13 +00:00
app . middleware_stack = None # reset current middleware to allow modifying user provided list
2023-03-11 17:01:08 +00:00
app . add_middleware ( GZipMiddleware , minimum_size = 1000 )
2023-05-19 12:37:13 +00:00
configure_cors_middleware ( app )
app . build_middleware_stack ( ) # rebuild middleware stack on-the-fly
def configure_cors_middleware ( app ) :
cors_options = {
" allow_methods " : [ " * " ] ,
" allow_headers " : [ " * " ] ,
" allow_credentials " : True ,
}
if cmd_opts . cors_allow_origins :
cors_options [ " allow_origins " ] = cmd_opts . cors_allow_origins . split ( ' , ' )
if cmd_opts . cors_allow_origins_regex :
cors_options [ " allow_origin_regex " ] = cmd_opts . cors_allow_origins_regex
app . add_middleware ( CORSMiddleware , * * cors_options )
2022-11-04 18:36:47 +00:00
2022-10-17 16:58:34 +00:00
def create_api ( app ) :
2022-10-17 08:38:32 +00:00
from modules . api . api import Api
2022-10-18 06:51:53 +00:00
api = Api ( app , queue_lock )
2022-10-17 16:58:34 +00:00
return api
2022-10-31 14:36:45 +00:00
2022-10-17 16:58:34 +00:00
def api_only ( ) :
initialize ( )
2022-10-01 17:31:58 +00:00
2022-10-17 16:58:34 +00:00
app = FastAPI ( )
2023-03-11 17:01:08 +00:00
setup_middleware ( app )
2022-10-17 16:58:34 +00:00
api = create_api ( app )
2022-11-02 07:04:35 +00:00
modules . script_callbacks . app_started_callback ( None , app )
2023-03-11 13:27:58 +00:00
print ( f " Startup time: { startup_timer . summary ( ) } . " )
2023-06-28 10:15:01 +00:00
api . launch (
server_name = " 0.0.0.0 " if cmd_opts . listen else " 127.0.0.1 " ,
port = cmd_opts . port if cmd_opts . port else 7861 ,
root_path = f " / { cmd_opts . subpath } "
)
2022-10-06 09:08:48 +00:00
2023-05-16 17:58:35 +00:00
2022-10-20 15:32:17 +00:00
def webui ( ) :
launch_api = cmd_opts . api
2022-10-17 08:38:32 +00:00
initialize ( )
2022-10-17 06:58:42 +00:00
2022-10-17 08:38:32 +00:00
while 1 :
2022-11-27 08:52:53 +00:00
if shared . opts . clean_temp_dir_at_start :
ui_tempdir . cleanup_tmpdr ( )
2023-03-11 13:27:58 +00:00
startup_timer . record ( " cleanup temp dir " )
2022-11-27 08:52:53 +00:00
2023-01-21 13:15:53 +00:00
modules . script_callbacks . before_ui_callback ( )
2023-03-11 13:27:58 +00:00
startup_timer . record ( " scripts before_ui_callback " )
2023-01-21 13:15:53 +00:00
2022-11-28 06:00:10 +00:00
shared . demo = modules . ui . create_ui ( )
2023-03-11 13:27:58 +00:00
startup_timer . record ( " create ui " )
2022-10-18 15:51:36 +00:00
2023-03-21 05:49:08 +00:00
if not cmd_opts . no_gradio_queue :
2023-01-21 15:47:54 +00:00
shared . demo . queue ( 64 )
2023-05-19 14:28:41 +00:00
gradio_auth_creds = list ( get_gradio_auth_creds ( ) ) or None
2023-02-19 10:11:48 +00:00
2023-01-14 10:38:10 +00:00
app , local_url , share_url = shared . demo . launch (
2022-10-02 18:26:38 +00:00
share = cmd_opts . share ,
2022-11-05 09:06:51 +00:00
server_name = server_name ,
2022-10-02 18:26:38 +00:00
server_port = cmd_opts . port ,
2022-11-05 09:06:51 +00:00
ssl_keyfile = cmd_opts . tls_keyfile ,
ssl_certfile = cmd_opts . tls_certfile ,
2023-04-28 01:30:19 +00:00
ssl_verify = cmd_opts . disable_tls_verify ,
2022-10-02 18:26:38 +00:00
debug = cmd_opts . gradio_debug ,
2023-05-19 14:28:41 +00:00
auth = gradio_auth_creds ,
2023-06-05 17:52:05 +00:00
inbrowser = cmd_opts . autolaunch and os . getenv ( ' SD_WEBUI_RESTARTING ' ) != ' 1 ' ,
2023-05-18 07:36:11 +00:00
prevent_thread_lock = True ,
allowed_paths = cmd_opts . gradio_allowed_path ,
2023-05-22 06:53:24 +00:00
app_kwargs = {
" docs_url " : " /docs " ,
" redoc_url " : " /redoc " ,
} ,
2023-06-28 10:15:01 +00:00
root_path = f " / { cmd_opts . subpath } " ,
2022-10-02 18:26:38 +00:00
)
2023-05-11 20:46:45 +00:00
2023-06-05 17:47:18 +00:00
# after initial launch, disable --autolaunch for subsequent restarts
cmd_opts . autolaunch = False
2023-03-11 13:27:58 +00:00
startup_timer . record ( " gradio launch " )
2022-11-04 07:07:29 +00:00
# gradio uses a very open CORS policy via app.user_middleware, which makes it possible for
# an attacker to trick the user into opening a malicious HTML page, which makes a request to the
2022-12-15 02:01:32 +00:00
# running web ui and do whatever the attacker wants, including installing an extension and
# running its code. We disable this here. Suggested by RyotaK.
2022-11-04 07:07:29 +00:00
app . user_middleware = [ x for x in app . user_middleware if x . cls . __name__ != ' CORSMiddleware ' ]
2023-03-11 17:01:08 +00:00
setup_middleware ( app )
2022-10-02 18:26:38 +00:00
2023-01-15 15:50:56 +00:00
modules . progress . setup_progress_api ( app )
2023-05-08 13:46:35 +00:00
modules . ui . setup_ui_api ( app )
2023-01-15 15:50:56 +00:00
2022-10-31 14:36:45 +00:00
if launch_api :
2022-10-17 16:58:34 +00:00
create_api ( app )
2022-10-02 18:26:38 +00:00
2023-01-28 19:52:27 +00:00
ui_extra_networks . add_pages_to_demo ( app )
2023-05-20 21:41:41 +00:00
startup_timer . record ( " add APIs " )
with startup_timer . subcategory ( " app_started_callback " ) :
modules . script_callbacks . app_started_callback ( shared . demo , app )
2023-03-11 13:27:58 +00:00
2023-05-20 21:41:41 +00:00
timer . startup_record = startup_timer . dump ( )
2023-03-11 13:27:58 +00:00
print ( f " Startup time: { startup_timer . summary ( ) } . " )
2022-10-30 14:46:43 +00:00
2023-05-11 20:46:45 +00:00
try :
while True :
server_command = shared . state . wait_for_server_command ( timeout = 5 )
if server_command :
if server_command in ( " stop " , " restart " ) :
break
else :
print ( f " Unknown server command: { server_command } " )
except KeyboardInterrupt :
2023-05-16 17:58:35 +00:00
print ( ' Caught KeyboardInterrupt, stopping... ' )
2023-05-11 20:46:45 +00:00
server_command = " stop "
if server_command == " stop " :
2023-05-16 17:58:35 +00:00
print ( " Stopping server... " )
2023-05-11 20:46:45 +00:00
# If we catch a keyboard interrupt, we want to stop the server and exit.
shared . demo . close ( )
break
2023-05-20 21:41:41 +00:00
2023-01-03 15:38:21 +00:00
print ( ' Restarting UI... ' )
2023-05-11 20:46:45 +00:00
shared . demo . close ( )
time . sleep ( 0.5 )
2023-03-12 18:25:22 +00:00
startup_timer . reset ( )
2023-05-19 13:08:40 +00:00
modules . script_callbacks . app_reload_callback ( )
startup_timer . record ( " app reload callback " )
2023-01-06 10:55:50 +00:00
modules . script_callbacks . script_unloaded_callback ( )
2023-05-19 13:08:40 +00:00
startup_timer . record ( " scripts unloaded callback " )
initialize_rest ( reload_script_modules = True )
2023-01-21 05:36:07 +00:00
2022-09-11 15:48:36 +00:00
2022-09-08 09:17:26 +00:00
if __name__ == " __main__ " :
2022-10-18 06:51:53 +00:00
if cmd_opts . nowebui :
2022-10-17 16:58:34 +00:00
api_only ( )
2022-10-17 08:38:32 +00:00
else :
2022-10-20 15:32:17 +00:00
webui ( )