예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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)