Beispiel #1
0
    def run (self):
        """
        Run the given command
        """

        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'

        parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all

        try:
            options,args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass # Ignore any option errors at this point.

        no_settings_commands = [
            'help', 'version', '--help', '--version', '-h',
            'startapp'
        ]

        try:
            settings.INSTALLED_SERVICES
        except ImproperlyConfigured as exc:
            self.setting_exception = exc

            if subcommand in no_settings_commands:
                settings.configure()
        
        if settings.configured:
            if subcommand == 'runapp' not in self.argv:
                try:
                    check_errors(molnframework.setup)()
                except Exception:
                    apps.ready = True
            else:
                molnframework.setup()

        #server.start()

        # TODO: activate command system once the framework is stable

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0])
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(molnframework.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #2
0
 def test_check_errors_catches_all_exceptions(self):
     """
     Since Python may raise arbitrary exceptions when importing code,
     check_errors() must catch Exception, not just some subclasses.
     """
     filename = self.temporary_file('test_exception.py')
     filename.write_text('raise Exception')
     with extend_sys_path(str(filename.parent)):
         with self.assertRaises(Exception):
             autoreload.check_errors(import_module)('test_exception')
     self.assertFileFound(filename)
Beispiel #3
0
 def test_check_errors_catches_all_exceptions(self):
     """
     Since Python may raise arbitrary exceptions when importing code,
     check_errors() must catch Exception, not just some subclasses.
     """
     filename = self.temporary_file('test_exception.py')
     filename.write_text('raise Exception')
     with extend_sys_path(str(filename.parent)):
         with self.assertRaises(Exception):
             autoreload.check_errors(import_module)('test_exception')
     self.assertFileFound(filename)
Beispiel #4
0
    def test_check_errors(self):
        """
        When a file containing an error is imported in a function wrapped by
        check_errors(), gen_filenames() returns it.
        """
        filename = self.temporary_file('test_syntax_error.py')
        filename.write_text("Ceci n'est pas du Python.")

        with extend_sys_path(str(filename.parent)):
            with self.assertRaises(SyntaxError):
                autoreload.check_errors(import_module)('test_syntax_error')
        self.assertFileFound(filename)
Beispiel #5
0
    def test_check_errors(self):
        """
        When a file containing an error is imported in a function wrapped by
        check_errors(), gen_filenames() returns it.
        """
        filename = self.temporary_file('test_syntax_error.py')
        filename.write_text("Ceci n'est pas du Python.")

        with extend_sys_path(str(filename.parent)):
            with self.assertRaises(SyntaxError):
                autoreload.check_errors(import_module)('test_syntax_error')
        self.assertFileFound(filename)
Beispiel #6
0
    def test_check_errors_only_new(self):
        """
        When a file containing an error is imported in a function wrapped by
        check_errors(), gen_filenames(only_new=True) returns it.
        """
        dirname = tempfile.mkdtemp()
        filename = os.path.join(dirname, 'test_syntax_error.py')
        self.addCleanup(shutil.rmtree, dirname)
        with open(filename, 'w') as f:
            f.write("Ceci n'est pas du Python.")

        with extend_sys_path(dirname):
            with self.assertRaises(SyntaxError):
                autoreload.check_errors(import_module)('test_syntax_error')
        self.assertFileFoundOnlyNew(filename)
Beispiel #7
0
    def test_check_errors_catches_all_exceptions(self):
        """
        Since Python may raise arbitrary exceptions when importing code,
        check_errors() must catch Exception, not just some subclasses.
        """
        dirname = tempfile.mkdtemp()
        filename = os.path.join(dirname, 'test_exception.py')
        self.addCleanup(shutil.rmtree, dirname)
        with open(filename, 'w') as f:
            f.write("raise Exception")

        with extend_sys_path(dirname):
            with self.assertRaises(Exception):
                autoreload.check_errors(import_module)('test_exception')
        self.assertFileFound(filename)
Beispiel #8
0
 def test_mutates_error_files(self):
     fake_method = mock.MagicMock(side_effect=RuntimeError())
     wrapped = autoreload.check_errors(fake_method)
     with mock.patch.object(autoreload, '_error_files') as mocked_error_files:
         with self.assertRaises(RuntimeError):
             wrapped()
     self.assertEqual(mocked_error_files.append.call_count, 1)
Beispiel #9
0
 def test_mutates_error_files(self):
     fake_method = mock.MagicMock(side_effect=RuntimeError())
     wrapped = autoreload.check_errors(fake_method)
     with mock.patch.object(autoreload, '_error_files') as mocked_error_files:
         with self.assertRaises(RuntimeError):
             wrapped()
     self.assertEqual(mocked_error_files.append.call_count, 1)
Beispiel #10
0
    def execute(self):
        """
        Given the command-line arguments, this figures out which subcommand is
        being run, creates a parser appropriate to that command, and runs it.
        """
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        try:
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc

        if settings.configured:
            # 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 subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    autoreload.check_errors(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

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser('django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            else:
                django.setup()

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #11
0
    def execute(self):
        """
        Given the command-line arguments, this figures out which subcommand is
        being run, creates a parser appropriate to that command, and runs it.
        """
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        no_settings_commands = [
            'help', 'version', '--help', '--version', '-h',
            'compilemessages', 'makemessages',
            'startapp', 'startproject',
        ]

        try:
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc
            # A handful of built-in management commands work without settings.
            # Load the default settings -- where INSTALLED_APPS is empty.
            if subcommand in no_settings_commands:
                settings.configure()

        if settings.configured:
            # 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 subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    autoreload.check_errors(django.setup)()
                except Exception:
                    # The exception will be raised later in the child process
                    # started by the autoreloader.
                    pass

            # In all other cases, django.setup() is required to succeed.
            else:
                django.setup()

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            self.fetch_command(subcommand).run_from_argv(self.argv)
from __future__ import unicode_literals
Beispiel #13
0
    def execute(self):
        """
        Given the command-line arguments, figure out which subcommand is being
        run, create a parser appropriate to that command, and run it.

        !!! OVERRIDED !!!
        Adding new user defined command-line arguments.
        """
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        parser = CommandParser(None,
                               usage="%(prog)s subcommand [options] [args]",
                               add_help=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        try:
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc

        if settings.configured:
            # 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 subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    autoreload.check_errors(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

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser(
                        'django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            else:
                django.setup()

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(
                    self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(
                    self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version',
        # 'django-admin --help' to work, for backwards compatibility and
        # !!! USER DEFINED !!!
        # 'django-admin --importdirs' to pre-populate directories database.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif subcommand == 'importdirs' or subcommand == '--importdirs':
            check = False
            continue_bool = False
            try:
                args.index("--check")
                check = True
            except ValueError:
                pass
            try:
                args.index("--continue")
                continue_bool = True
            except ValueError:
                pass
            populate_db(settings.ROOT_DIRECTORY,
                        settings.THUMBNAILS_DIRECTORIES, check, continue_bool)
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #14
0
    def execute(self):
        """
        Given the command-line arguments, figure out which subcommand is being
        run, create a parser appropriate to that command, and run it.
        1、命令行参数解析
        2、
        """
        try:
            # 如果在调用django-admin 的时候没有给出任何的 命令 & 选项
            # 那么slef.argv 列表只有一项 它就是slef.argv[0] 它的值为django-admin
            # 所以这种情况下正好会报 IndexError
            subcommand = self.argv[1]
        except IndexError:
            # 如果没有给出任何命令的情况下 把subcommand设置为help
            # 也就是说不给出命令的情况下 就当做是看django-admin的帮助.
            subcommand = 'help'  # Display help if no arguments were given.

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.

        # django 在标准库的argparser上作出了一些自定义
        # CommandParser 继承了argparser.ArgumentParser
        # CommandParser 位于 jango.core.management.base 这个包中.
        # usage & add_help 都是argparser.ArgumentParser.__init__中的参数
        # CommandParser.__init__(self, cmd, **kwargs): 由这里可以看了cmd=None
        parser = CommandParser(None,
                               usage="%(prog)s subcommand [options] [args]",
                               add_help=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        try:
            # settings 是在django.conf包中LazySettings类的实例
            # 这里有个问题,就是在LazySettings类的代码中没有找到INSTALLED_APPS 的定义
            # settings.INSTALLED_APPS 像这样的语句又有什么意义呢?难道它这样干就单单是为了引发异常?
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc

        if settings.configured:
            # 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 subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    autoreload.check_errors(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

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser(
                        'django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            else:
                django.setup()

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(
                    self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(
                    self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #15
0
    def execute(self):
        """
        Given the command-line arguments, figure out which subcommand is being
        run, create a parser appropriate to that command, and run it.
        """
        # 1 Subcommand: 子程序名, 默认为help, 见上面定义
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        # 2 处理和解析参数
        parser = CommandParser(None,
                               usage="%(prog)s subcommand [options] [args]",
                               add_help=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.
        MY(1.0, '解析后的参数:', '\n\toptions:', options, '\n\targs:', args)

        # 3 LazySetting对象, __getattr__/__setattr__方法,完成INSTALLED_APPS赋值
        #   懒加载.
        try:
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc

        # django.setup()
        #   4.1 配置日志
        #   4.2 加载自定义模块
        #   4.3 加载model模块
        if settings.configured:
            # 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.
            # a 重新导入所有配置信息
            if subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    autoreload.check_errors(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

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser(
                        'django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            # b 配置日志, 加载自定义模块, models模块, 使用Application
            else:
                django.setup()

        self.autocomplete()

        # 5 fetch_command, 返回不同的Command对象, 根据不同的参数运行不同的后台任务,
        #   5.1 调用各个 BaseCommand 子类的方法来完成对应的业务, 例如:
        #       runserver.py.Command
        #       flush.py.Command
        #       and so on
        #   5.2 不同Command流程(handle相当于钩子):
        #       run_from_argv, 进行参数解析和配置, 调用execute
        #       execute, 设置环境变量,运行handle, 在父类实现大部分逻辑;
        #       handle, 进入run, 由各个子类rewrite, (主要处理逻辑)
        #       run_from_argv, 处理善后
        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(
                    self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(
                    self.prog_name, options.args[0])
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            # Special-cases: We want 'django-admin --version' and
            # 'django-admin --help' to work, for backwards compatibility.
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            MY(1, '\n\tShell subcommand:', subcommand, ' Argv:', self.argv)
            # 执行一个django-admin命令, 当然也可以自定义该命令
            # 该函数: django.core.management.base
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #16
0
    def execute(self):
        """
        Given the command-line arguments, figure out which subcommand is being
        run, create a parser appropriate to that command, and run it.
        给定命令行参数后,找出正在运行的子命令,创建适合该命令的解析器,并运行它。
        """
        try:
            # 子命令,例如 runserver 、migrate
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        parser = CommandParser(usage='%(prog)s subcommand [options] [args]',
                               add_help=False,
                               allow_abbrev=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        try:
            # 此对象是 django.conf.__init__.LazySettings 类的实例
            # 此对象的全部属性都来自应用对象的 settings.py 配置文件
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc
        except ImportError as exc:
            self.settings_exception = exc

        if settings.configured:
            #print('【django.core.management.__init__.ManagementUtility.execute】subcommand:', subcommand)
            #print('【django.core.management.__init__.ManagementUtility.execute】self.argv:', self.argv)
            if subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    # 参数 django.setup 是定义在 django.__init__ 模块中的函数
                    # 而 check_errors 是作检测异常之用
                    # 这里会调用 django.setup 函数
                    # 将 settings.INSTALLED_APPS 列表中的应用程序放到 apps.app_configs 字典中
                    # apps 对象可以看做一个应用对象收集器
                    autoreload.check_errors(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(dict)
                    apps.app_configs = {}
                    apps.apps_ready = apps.models_ready = apps.ready = True

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser(
                        'django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            else:
                django.setup()

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(
                    self.main_help_text(commands_only=True) + '\n')
            elif not options.args:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(
                    self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            # 下面的 fetch_command 方法根据命令行参数找到对应的模块中的 Command 类的实例并返回
            # 它通过一个字典来找,每个命令都是字典中的一个 key
            # 根据命令找到对应的 value ,它是一个包的字符串,再据此找到包下面的 management/commands 子目录
            # 然后在这个子目录下面找到与命令同名的文件
            # 以 python manage.py makemigrate 命令为例
            # 这个方法就会返回 .../management/commands/makemigrate.py 文件中的 Command 类的实例

            # 下面的 cmd 我们称之为「命令处理对象」,以 runserver 命令为例
            # 此对象的父类是 django.contrib.staticfiles.management.commands.runserver.Command 类
            # 后者的父类是 django.core.management.commands.runserver.Command 类
            # 后者的父类是 django.core.management.base.BaseCommand 类
            cmd = self.fetch_command(subcommand)
            # 不论终端命令是啥
            # 下面这个方法都定义在 django.core.management.base.BaseCommand 父类中
            # 参数 self.argv 是终端命令参数列表,等同于 sys.argv
            # 这个方法会调用「命令处理对象」自身的 handle 方法控制其它对象启动线程和创建套接字啥的
            cmd.run_from_argv(self.argv)
Beispiel #17
0
    def execute(self):
        """
        Given the command-line arguments, figure out which subcommand is being
        run, create a parser appropriate to that command, and run it.
        给定命令行参数,找出正在执行的子命令
        运行,创建一个适合该命令的解析器,然后运行它。
        """
        # 1、是否取到位置1的参数, 否则显示帮助信息
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # 2、参数预处理
        # Preprocess options to extract --settings and --pythonpath. 提取一些 settings pythonPath的配置
        # These options could affect the commands that are available, so they
        # must be processed early. 这些选项可能会影响到可用的命令 必须尽早处理
        parser = CommandParser(None,
                               usage="%(prog)s subcommand [options] [args]",
                               add_help=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all

        # 3、
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        # 4、是否配置INSTALLED_APPS
        try:
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc

        # 5、判断是否已配置设置
        if settings.configured:
            # 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.

            # 5.1 命令== runserver 并且 noreload 不在传入的参数里面
            if subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    #5.1.1   检查django 项目的完整性 - 装饰器
                    autoreload.check_errors(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

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser(
                        'django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            # 5.2  其他的命令说明django 已经被安装成功
            else:
                django.setup()

        # 6、输出启动完成信息
        self.autocomplete()

        # 7 判断命令,最终并执行
        if subcommand == 'help':
            # 7.1 帮助
            if '--commands' in args:
                sys.stdout.write(
                    self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(
                    self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            # 7.2 django版本获得
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            # 7.3 获取帮助主文件
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            # 7.3 直接执行命令 - 链式调用
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #18
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)
Beispiel #19
0
    def execute(self):
        """
        Given the command-line arguments, figure out which subcommand is being
        run, create a parser appropriate to that command, and run it.
        """
        # 先找出二级指令,没有二级指令就打印帮助信息
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # 预处理的选项,这些选项会和当前传递的选项有冲突,所以先解析出这些选项,这样用户传递的选项才不会被影响.
        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False)
        # 这里是指定settings文件
        parser.add_argument('--settings')
        # 这里是指定python路径
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            # 修改环境settings和pythonpath
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        try:
            # django在启动时会创建settings = LazySettings()
            # 通过读取os.environ.get('DJANGO_SETTINGS_MODULE'),来初始化settings对象
            # settings是一个lazy对象,使用self._wrapped保存Settings对象,当读取属性时,lazy对象会先进行_setup,然后会调用getattr(self._wrapped,key)
            # 当要读取INSTALLED_APPS时,会先进行_setup
            # 说白了就是LazySetting对象读取属性时,会真正初始化Settings对象,并赋值给LazySetting._wrapped=Settings()
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc

        if settings.configured:
            # 就是返回self._wrapped is not empty,当前是否已经初始化好了settings
            # 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 subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    # 执行django.setup,如果有错误那么
                    autoreload.check_errors(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

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser('django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            else:
                # 执行django.setup
                django.setup()

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            # 这里执行fetch_command('runserver').run_from_argv(['/Users/mering/Proje...manage.py', 'runserver', '--noreload', '--nothreading'])
            # runserver 对应的是django.contrib.staticfiles
            # 加载该class import_module('%s.management.commands.%s' % (app_name, name))
            # import_module('django.contrib.staticfiles.management.commands.runserver')
            # 放回的fetch_command(subcommand)=django.contrib.staticfiles.management.commands.runserver.Command()
            # django.contrib.staticfiles.management.commands.runserver.Command继承自django.core.management.Command,
            # run_from_argv会调用django.core.management.Command.excute-->django.core.management.BaseCommand.excute
            # django.core.management.commands.runserver.Command.handle
            # django.core.management.commands.runserver.Command.run
            # django.core.management.commands.runserver.Command.inner_run
            # django.contrib.staticfiles.management.commands.runserver.Command.get_handler  获得wsgiapp
            #  Debug模式下返回StaticFilesHandler
            # django.core.servers.run
            # def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
            #     server_address = (addr, port)
            #     if threading:
            #         # 创建一个新类型继承自socketserver.ThreadingMixIn和WSGIServer
            #         httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
            #     else:
            #         httpd_cls = server_cls
            #     httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
            #     if threading:
            #         # ThreadingMixIn.daemon_threads indicates how threads will behave on an
            #         # abrupt shutdown; like quitting the server by the user or restarting
            #         # by the auto-reloader. True means the server will not wait for thread
            #         # termination before it quits. This will make auto-reloader faster
            #         # and will prevent the need to kill the server manually if a thread
            #         # isn't terminating correctly.
            #         httpd.daemon_threads = True
            #     httpd.set_app(wsgi_handler)
            #     httpd.serve_forever()
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #20
0
    def execute(self):
        """
        TODO:[-] 20-02-12 由入口函数调用的
        Given the command-line arguments, figure out which subcommand is being
        run, create a parser appropriate to that command, and run it.
        """
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        parser = CommandParser(usage='%(prog)s subcommand [options] [args]',
                               add_help=False,
                               allow_abbrev=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            # 设置系统参数添加至 os.environ
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        try:
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc
        except ImportError as exc:
            self.settings_exception = exc

        if settings.configured:
            # 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 subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    autoreload.check_errors(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(dict)
                    apps.app_configs = {}
                    apps.apps_ready = apps.models_ready = apps.ready = True

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser(
                        'django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            else:
                django.setup()

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(
                    self.main_help_text(commands_only=True) + '\n')
            elif not options.args:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(
                    self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #21
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)
Beispiel #22
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)
Beispiel #23
0
    def execute(self):
        """
        Given the command-line arguments, figure out which subcommand is being
        run, create a parser appropriate to that command, and run it.
        给出命令行参数,找出当前的子命令 运行,
        创建一个适合该命令的解析器,然后运行它
        """
        try:
            subcommand = self.argv[1]  # self.argv = sys.argv[:]
            # subcommand = "runserver"
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        parser = CommandParser(usage='%(prog)s subcommand [options] [args]',
                               add_help=False,
                               allow_abbrev=False)
        """
        usage : 帮助 文档 
        add_help : 是否显示命令帮助
        allow_abbrev: 可选参数  键 时候可以 简写 
        """

        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        # nargs : * 代表 可 连写 多个参数, 集合在一个列表中
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            # options=== Namespace(args=['0.0.0.0:8888'], pythonpath=None, settings=None)
            # options : Namespace()  , 所设定的 各选项 所对应的 值
            # args : []  除了 设定的 自定义选项, 在最后添加的 多余的 参数,

            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        try:

            # 1.0
            # 加载 默认全局的配置文件 global_settings.py  和  项目 自定义的 settings.py 文件
            # 所有配置 都存储 在 settings._wrapped 属性中,值为 类实例 <class django.conf.Settings objects >
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc
        except ImportError as exc:
            self.settings_exception = exc

# sys.argv == ['E:/DjangoProject/刘江/login-register-master/manage.py', 'runserver', '0.0.0.0:9999']
        if settings.configured:  # True, 代表 settings 配置 已 加载完毕
            # 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 subcommand == 'runserver' and '--noreload' not in self.argv:
                try:

                    # 2.0
                    autoreload.check_errors(
                        django.setup)()  # check_errors 为一个装饰器
                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

                    # Remove options not compatible with the built-in runserver
                    # (e.g. options for the contrib.staticfiles' runserver).
                    # Changes here require manually testing as described in
                    # #27522.
                    _parser = self.fetch_command('runserver').create_parser(
                        'django', 'runserver')
                    _options, _args = _parser.parse_known_args(self.argv[2:])
                    for _arg in _args:
                        self.argv.remove(_arg)

            # In all other cases, django.setup() is required to succeed.
            # 在所有其他情况下,需要 django.setup() 才能成功。
            else:
                django.setup()  # 配置设置

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(
                    self.main_help_text(commands_only=True) + '\n')
            elif not options.args:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(
                    self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:

            self.fetch_command(subcommand).run_from_argv(self.argv)  #  提取命令
Beispiel #24
0
    def execute(self):
        """
        Given the command-line arguments, this figures out which subcommand is
        being run, creates a parser appropriate to that command, and runs it.
        """
        try:
            subcommand = self.argv[1]
        except IndexError:
            subcommand = 'help'  # Display help if no arguments were given.

        # Preprocess options to extract --settings and --pythonpath.
        # These options could affect the commands that are available, so they
        # must be processed early.
        parser = CommandParser(None,
                               usage="%(prog)s subcommand [options] [args]",
                               add_help=False)
        parser.add_argument('--settings')
        parser.add_argument('--pythonpath')
        parser.add_argument('args', nargs='*')  # catch-all
        try:
            options, args = parser.parse_known_args(self.argv[2:])
            handle_default_options(options)
        except CommandError:
            pass  # Ignore any option errors at this point.

        no_settings_commands = [
            'help',
            'version',
            '--help',
            '--version',
            '-h',
            'compilemessages',
            'makemessages',
            'startapp',
            'startproject',
        ]

        try:
            settings.INSTALLED_APPS
        except ImproperlyConfigured as exc:
            self.settings_exception = exc
            # A handful of built-in management commands work without settings.
            # Load the default settings -- where INSTALLED_APPS is empty.
            if subcommand in no_settings_commands:
                settings.configure()

        if settings.configured:
            # 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 subcommand == 'runserver' and '--noreload' not in self.argv:
                try:
                    autoreload.check_errors(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

            # In all other cases, django.setup() is required to succeed.
            else:
                django.setup()

        self.autocomplete()

        if subcommand == 'help':
            if '--commands' in args:
                sys.stdout.write(
                    self.main_help_text(commands_only=True) + '\n')
            elif len(options.args) < 1:
                sys.stdout.write(self.main_help_text() + '\n')
            else:
                self.fetch_command(options.args[0]).print_help(
                    self.prog_name, options.args[0])
        # Special-cases: We want 'django-admin --version' and
        # 'django-admin --help' to work, for backwards compatibility.
        elif subcommand == 'version' or self.argv[1:] == ['--version']:
            sys.stdout.write(django.get_version() + '\n')
        elif self.argv[1:] in (['--help'], ['-h']):
            sys.stdout.write(self.main_help_text() + '\n')
        else:
            self.fetch_command(subcommand).run_from_argv(self.argv)
Beispiel #25
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)