def execute_from_command_line(*args, **kwargs): ''' Top-level entry point. - figures out which subcommand is being run - sets up django & configures settings - runs the subcommand We have to ignore the args to this function. If the user runs "python manage.py [subcommand]", then argv is indeed passed, but if they run "otree [subcommand]", it executes the autogenerated console_scripts shim, which does not pass any args to this function, just: load_entry_point('otree', 'console_scripts', 'otree')() This is called if people use manage.py, or if people use the otree script. script_file is no longer used, but we need it for compat ''' if len(argv) == 1: # default command argv.append('help') subcommand = argv[1] if subcommand == 'runserver': sys.stdout.write( "Suggestion: use 'otree devserver' instead of 'otree runserver'. " "devserver automatically syncs your database.\n") if subcommand == 'runzip': runzip.main(argv[2:]) # better to return than sys.exit because testing is complicated # with sys.exit -- if you mock it, then the function keeps executing. return # Add the current directory to sys.path so that Python can find # the settings module. # when using "python manage.py" this is not necessary because # the entry-point script's dir is automatically added to sys.path. # but the 'otree' command script is located outside of the project # directory. if os.getcwd() not in sys.path: sys.path.insert(0, os.getcwd()) # to match manage.py # make it configurable so i can test it # note: we will never get ImproperlyConfigured, # because that only happens when DJANGO_SETTINGS_MODULE is not set os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') DJANGO_SETTINGS_MODULE = os.environ['DJANGO_SETTINGS_MODULE'] # help and --help must have settings configured, so that otree can be in # INSTALLED_APPS, so those management commands are available. if subcommand in [ 'startproject', 'version', '--version', 'compilemessages', 'makemessages', 'unzip', 'zip', ]: django_settings.configure(**get_default_settings({})) else: try: configure_settings(DJANGO_SETTINGS_MODULE) except ImportSettingsError: # need to differentiate between an ImportError because settings.py # was not found, vs. ImportError because settings.py imports another # module that is not found. if os.path.isfile('{}.py'.format(DJANGO_SETTINGS_MODULE)): raise else: msg = ("Cannot find oTree settings. " "Please 'cd' to your oTree project folder, " "which contains a settings.py file.") logger.warning(msg) return warning = check_update_needed( Path('.').resolve().joinpath('requirements_base.txt')) if warning: logger.warning(warning) runserver_or_devserver = subcommand in ['runserver', 'devserver'] if runserver_or_devserver: # apparently required by restart_with_reloader # otherwise, i get: # python.exe: can't open file 'C:\oTree\venv\Scripts\otree': # [Errno 2] No such file or directory # this doesn't work if you start runserver from another dir # like python my_project/manage.py runserver. but that doesn't seem # high-priority now. sys.argv = ['manage.py'] + argv[1:] # previous solution here was using subprocess.Popen, # but changing it to modifying sys.argv changed average # startup time on my machine from 2.7s to 2.3s. # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if runserver_or_devserver and '--noreload' not in argv: try: autoreload.check_errors(do_django_setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True else: do_django_setup() if subcommand in ['help', '--help', '-h'] and len(argv) == 2: sys.stdout.write(MAIN_HELP_TEXT) elif subcommand == 'help' and len(argv) >= 3: command_to_explain = argv[2] fetch_command(command_to_explain).print_help('otree', command_to_explain) elif subcommand in ("version", "--version"): sys.stdout.write(__version__ + '\n') else: fetch_command(subcommand).run_from_argv(argv)
def execute_from_command_line(*args, **kwargs): ''' This is called if people use manage.py, or if people use the otree script. script_file is no longer used, but we need it for compat Given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. ''' argv = sys.argv # so that we can patch it easily settings = django.conf.settings if len(argv) == 1: # default command argv.append('help') subcommand = argv[1] if subcommand == 'runserver': sys.stdout.write( "Suggestion: use 'otree devserver' instead of 'otree runserver'. " "devserver automatically syncs your database.\n" ) # Add the current directory to sys.path so that Python can find # the settings module. # when using "python manage.py" this is not necessary because # the entry-point script's dir is automatically added to sys.path. # but the 'otree' command script is located outside of the project # directory. if os.getcwd() not in sys.path: sys.path.insert(0, os.getcwd()) # to match manage.py # make it configurable so i can test it # note: we will never get ImproperlyConfigured, # because that only happens when DJANGO_SETTINGS_MODULE is not set os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') DJANGO_SETTINGS_MODULE = os.environ['DJANGO_SETTINGS_MODULE'] # some commands don't need settings.INSTALLED_APPS try: configure_settings(DJANGO_SETTINGS_MODULE) except ImportSettingsError: if subcommand in [ 'startproject', 'help', 'version', '--help', '--version', '-h', 'compilemessages', 'makemessages', 'upgrade_my_code', 'update_my_code' ]: if not settings.configured: settings.configure(**get_default_settings({})) # need to differentiate between an ImportError because settings.py # was not found, vs. ImportError because settings.py imports another # module that is not found. elif os.path.isfile('{}.py'.format(DJANGO_SETTINGS_MODULE)): raise else: print_settings_not_found_error() return runserver_or_devserver = subcommand in ['runserver', 'devserver'] if runserver_or_devserver: # apparently required by restart_with_reloader # otherwise, i get: # python.exe: can't open file 'C:\oTree\venv\Scripts\otree': # [Errno 2] No such file or directory # this doesn't work if you start runserver from another dir # like python my_project/manage.py runserver. but that doesn't seem # high-priority now. sys.argv = ['manage.py'] + argv[1:] # previous solution here was using subprocess.Popen, # but changing it to modifying sys.argv changed average # startup time on my machine from 2.7s to 2.3s. # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if runserver_or_devserver and '--noreload' not in argv: try: autoreload.check_errors(do_django_setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True else: do_django_setup() if subcommand in ['help', '--help', '-h'] and len(argv) == 2: sys.stdout.write(main_help_text() + '\n') elif subcommand == 'help' and len(argv) >= 3: command_to_explain = argv[2] fetch_command(command_to_explain).print_help('otree', command_to_explain) elif subcommand in ("version", "--version"): sys.stdout.write(otree.__version__ + '\n') try: pypi_updates_cli() except: pass else: fetch_command(subcommand).run_from_argv(argv)
def execute_from_command_line(*args, **kwargs): ''' This is called if people use manage.py, or if people use the otree script. script_file is no longer used, but we need it for compat Given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. ''' argv = sys.argv # so that we can patch it easily settings = django.conf.settings if len(argv) == 1: # default command argv.append('help') subcommand = argv[1] if subcommand == 'runserver': sys.stdout.write( "Suggestion: use 'otree devserver' instead of 'otree runserver'. " "devserver automatically syncs your database.\n") # Add the current directory to sys.path so that Python can find # the settings module. # when using "python manage.py" this is not necessary because # the entry-point script's dir is automatically added to sys.path. # but the 'otree' command script is located outside of the project # directory. if os.getcwd() not in sys.path: sys.path.insert(0, os.getcwd()) # to match manage.py # make it configurable so i can test it # note: we will never get ImproperlyConfigured, # because that only happens when DJANGO_SETTINGS_MODULE is not set os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') DJANGO_SETTINGS_MODULE = os.environ['DJANGO_SETTINGS_MODULE'] # some commands don't need settings.INSTALLED_APPS try: configure_settings(DJANGO_SETTINGS_MODULE) except ImportSettingsError: if subcommand in [ 'startproject', 'help', 'version', '--help', '--version', '-h', 'compilemessages', 'makemessages', 'upgrade_my_code', 'update_my_code' ]: if not settings.configured: settings.configure(**get_default_settings({})) # need to differentiate between an ImportError because settings.py # was not found, vs. ImportError because settings.py imports another # module that is not found. elif os.path.isfile('{}.py'.format(DJANGO_SETTINGS_MODULE)): raise else: print_settings_not_found_error() return runserver_or_devserver = subcommand in ['runserver', 'devserver'] if runserver_or_devserver: # apparently required by restart_with_reloader # otherwise, i get: # python.exe: can't open file 'C:\oTree\venv\Scripts\otree': # [Errno 2] No such file or directory # this doesn't work if you start runserver from another dir # like python my_project/manage.py runserver. but that doesn't seem # high-priority now. sys.argv = ['manage.py'] + argv[1:] # previous solution here was using subprocess.Popen, # but changing it to modifying sys.argv changed average # startup time on my machine from 2.7s to 2.3s. # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. block_use_of_random() if runserver_or_devserver and '--noreload' not in argv: try: autoreload.check_errors(do_django_setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True else: do_django_setup() unblock_use_of_random() if subcommand in ['help', '--help', '-h'] and len(argv) == 2: sys.stdout.write(main_help_text() + '\n') elif subcommand == 'help' and len(argv) >= 3: command_to_explain = argv[2] fetch_command(command_to_explain).print_help('otree', command_to_explain) elif subcommand in ("version", "--version"): sys.stdout.write(otree.__version__ + '\n') try: pypi_updates_cli() except: pass else: fetch_command(subcommand).run_from_argv(argv)
def execute_from_command_line(*args, **kwargs): ''' Top-level entry point. - figures out which subcommand is being run - sets up django & configures settings - runs the subcommand We have to ignore the args to this function. If the user runs "python manage.py [subcommand]", then argv is indeed passed, but if they run "otree [subcommand]", it executes the autogenerated console_scripts shim, which does not pass any args to this function, just: load_entry_point('otree', 'console_scripts', 'otree')() This is called if people use manage.py, or if people use the otree script. script_file is no longer used, but we need it for compat ''' if len(argv) == 1: # default command argv.append('help') subcommand = argv[1] if subcommand in ['runzip', 'zipserver']: zipserver.main(argv[2:]) # better to return than sys.exit because testing is complicated # with sys.exit -- if you mock it, then the function keeps executing. return # Add the current directory to sys.path so that Python can find # the settings module. # when using "python manage.py" this is not necessary because # the entry-point script's dir is automatically added to sys.path. # but the 'otree' command script is located outside of the project # directory. if os.getcwd() not in sys.path: sys.path.insert(0, os.getcwd()) # to match manage.py: # make it configurable so i can test it. # and it must be an env var, because # note: we will never get ImproperlyConfigured, # because that only happens when DJANGO_SETTINGS_MODULE is not set os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') DJANGO_SETTINGS_MODULE = os.environ['DJANGO_SETTINGS_MODULE'] if subcommand in ['help', '--help', '-h'] and len(argv) == 2: sys.stdout.write(MAIN_HELP_TEXT) return # this env var is necessary because if the botworker submits a wait page, # it needs to broadcast to redis channel layer, not in-memory. # this caused an obscure bug on 2019-09-21. # prodserver1of2, 2of2, etc # we now require REDIS_URL to be defined even if using default localhost:6379 # that is to avoid piling up stuff in redis if it's not being used. if ('prodserver' in subcommand or 'webandworkers' in subcommand or 'timeoutworker' in subcommand) and os.environ.get('REDIS_URL'): os.environ['OTREE_USE_REDIS'] = '1' if subcommand in [ 'startproject', 'version', '--version', 'compilemessages', 'makemessages', 'unzip', 'zip', ]: django_settings.configure(**get_default_settings({})) else: try: configure_settings(DJANGO_SETTINGS_MODULE) except ModuleNotFoundError as exc: if exc.name == DJANGO_SETTINGS_MODULE.split('.')[-1]: msg = ("Cannot find oTree settings. " "Please 'cd' to your oTree project folder, " "which contains a settings.py file.") logger.warning(msg) return raise warning = check_update_needed( Path('.').resolve().joinpath('requirements_base.txt')) if warning: logger.warning(warning) is_devserver = subcommand == 'devserver' if is_devserver: # apparently required by restart_with_reloader # otherwise, i get: # python.exe: can't open file 'C:\oTree\venv\Scripts\otree': # [Errno 2] No such file or directory # this doesn't work if you start runserver from another dir # like python my_project/manage.py runserver. but that doesn't seem # high-priority now. sys.argv = ['manage.py'] + argv[1:] # previous solution here was using subprocess.Popen, # but changing it to modifying sys.argv changed average # startup time on my machine from 2.7s to 2.3s. # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if is_devserver and '--noreload' not in argv: try: autoreload.check_errors(do_django_setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True else: do_django_setup() if subcommand == 'help' and len(argv) >= 3: command_to_explain = argv[2] fetch_command(command_to_explain).print_help('otree', command_to_explain) elif subcommand in ("version", "--version"): sys.stdout.write(__version__ + '\n') else: fetch_command(subcommand).run_from_argv(argv)