예제 #1
0
파일: templates.py 프로젝트: muma378/moose
    def handle_template(self, template, subdir):
        """
        Determines where the app or project templates are.
        Use moose.__path__[0] as the default because we don't
        know into which directory Moose has been installed.
        """
        if template is None:
            return path.join(moose.__path__[0], 'conf', subdir)
        else:
            if template.startswith('file://'):
                template = template[7:]
            expanded_template = path.expanduser(template)
            expanded_template = path.normpath(expanded_template)
            if path.isdir(expanded_template):
                return expanded_template
            if self.is_url(template):
                # downloads the file and returns the path
                absolute_path = self.download(template)
            else:
                absolute_path = path.abspath(expanded_template)
            if path.exists(absolute_path):
                return self.extract(absolute_path)

        raise CommandError("couldn't handle %s template %s." %
                           (self.app_or_project, template))
예제 #2
0
파일: startapp.py 프로젝트: yuwenhui/moose
    def handle(self, **options):
        app_name, target = options.pop('name'), options.pop('directory')
        self.validate_name(app_name, "app")

        # Check that the app_name cannot be imported.
        try:
            import_module(app_name)
        except ImportError:
            pass
        else:
            raise CommandError(
                "%r conflicts with the name of an existing Python module and "
                "cannot be used as an app name. Please try another name." %
                app_name)

        super(Command, self).handle('app', app_name, target, **options)

        # copys the config template to the application
        config_template = options.pop('configfile')
        if not config_template.endswith(settings.CONFIG_EXTENSION):
            config_template += settings.CONFIG_EXTENSION

        project_name = os.path.basename(os.getcwd())
        project_template_path = os.path.join(os.getcwd(), project_name,
                                             config_template)

        app_template_path = os.path.join(os.getcwd(), app_name,
                                         settings.CONF_TEMPLATE_NAME)
        shutil.copyfile(project_template_path, app_template_path)
예제 #3
0
    def handle_action(self, app_config, action_alias, configs):
        # get user-defined class for the action
        action_klass = app_config.get_action_klass(action_alias)
        if not action_klass:
            raise CommandError("Unknown action alias '%s'." % action_alias)

        output = []
        if configs == None:
            actor = action_klass(app_config,
                                 stdout=self.stdout,
                                 stderr=self.stderr,
                                 style=self.style)
            # when option `-c` was None, run without arguments
            output.append(actor.run())
        else:
            # run with configs and get the output
            for conf_desc in configs:
                # Initialize the class each time to make it reentrancy
                actor = action_klass(app_config,
                                     stdout=self.stdout,
                                     stderr=self.stderr,
                                     style=self.style)

                config_loader = find_matched_conf(app_config, conf_desc)
                if not config_loader:
                    # Instead of raising an exception, makes a report after all done
                    err_msg = "No matched config found for description '%s', aborted." % conf_desc
                    output.append(err_msg)
                    continue
                else:
                    config = config_loader._parse()
                    output.append(actor.run(config=config))

        return '\n'.join(output)
예제 #4
0
def call_command(command_name, *args, **options):
    """
    Calls the given command, with the given options and args/kwargs.

    This is the primary API you should use for calling specific commands.

    `name` may be a string or a command object. Using a string is preferred
    unless the command object is required for further processing or testing.

    Some examples:
        call_command('migrate')
        call_command('shell', plain=True)
        call_command('sqlmigrate', 'myapp')

        from django.core.management.commands import flush
        cmd = flush.Command()
        call_command(cmd, verbosity=0, interactive=False)
        # Do something with cmd ...
    """
    if isinstance(command_name, BaseCommand):
        # Command object passed in.
        command = command_name
        command_name = command.__class__.__module__.split('.')[-1]
    else:
        # Load the command object by name.
        try:
            app_name = get_commands()[command_name]
        except KeyError:
            raise CommandError("Unknown command: %r" % command_name)

        if isinstance(app_name, BaseCommand):
            # If the command is already loaded, use it directly.
            command = app_name
        else:
            command = load_command_class(app_name, command_name)

    # Simulate argument parsing to get the option defaults (see #10080 for details).
    parser = command.create_parser('', command_name)
    # Use the `dest` option name from the parser option
    opt_mapping = {
        sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'):
        s_opt.dest
        for s_opt in parser._actions if s_opt.option_strings
    }
    arg_options = {
        opt_mapping.get(key, key): value
        for key, value in options.items()
    }
    defaults = parser.parse_args(args=[force_text(a) for a in args])
    defaults = dict(defaults._get_kwargs(), **arg_options)
    # Move positional args out of options to mimic legacy optparse
    args = defaults.pop('args', ())
    if 'skip_checks' not in options:
        defaults['skip_checks'] = True

    return command.execute(*args, **defaults)
예제 #5
0
파일: templates.py 프로젝트: muma378/moose
 def validate_name(self, name, app_or_project):
     if name is None:
         raise CommandError(
             "you must provide %s %s name" %
             ("an" if app_or_project == "app" else "a", app_or_project))
     # If it's not a valid directory name.
     if six.PY2:
         if not re.search(r'^[_a-zA-Z]\w*$', name):
             # Provide a smart error message, depending on the error.
             if not re.search(r'^[_a-zA-Z]', name):
                 message = 'make sure the name begins with a letter or underscore'
             else:
                 message = 'use only numbers, letters and underscores'
             raise CommandError("%r is not a valid %s name. Please %s." %
                                (name, app_or_project, message))
     else:
         if not name.isidentifier():
             raise CommandError(
                 "%r is not a valid %s name. Please make sure the name is "
                 "a valid identifier." % (name, app_or_project))
예제 #6
0
파일: templates.py 프로젝트: muma378/moose
    def download(self, url):
        """
        Downloads the given URL and returns the file name.
        """
        def cleanup_url(url):
            tmp = url.rstrip('/')
            filename = tmp.split('/')[-1]
            if url.endswith('/'):
                display_url = tmp + '/'
            else:
                display_url = url
            return filename, display_url

        prefix = 'moose_%s_template_' % self.app_or_project
        tempdir = tempfile.mkdtemp(prefix=prefix, suffix='_download')
        self.paths_to_remove.append(tempdir)
        filename, display_url = cleanup_url(url)

        if self.verbosity >= 2:
            self.stdout.write("Downloading %s\n" % display_url)
        try:
            the_path, info = urlretrieve(url, path.join(tempdir, filename))
        except IOError as e:
            raise CommandError("couldn't download URL %s to %s: %s" %
                               (url, filename, e))

        used_name = the_path.split('/')[-1]

        # Trying to get better name from response headers
        content_disposition = info.get('content-disposition')
        if content_disposition:
            _, params = cgi.parse_header(content_disposition)
            guessed_filename = params.get('filename') or used_name
        else:
            guessed_filename = used_name

        # Falling back to content type guessing
        ext = self.splitext(guessed_filename)[1]
        content_type = info.get('content-type')
        if not ext and content_type:
            ext = mimetypes.guess_extension(content_type)
            if ext:
                guessed_filename += ext

        # Move the temporary file to a filename that has better
        # chances of being recognized by the archive utils
        if used_name != guessed_filename:
            guessed_path = path.join(tempdir, guessed_filename)
            shutil.move(the_path, guessed_path)
            return guessed_path

        # Giving up
        return the_path
예제 #7
0
파일: templates.py 프로젝트: muma378/moose
 def extract(self, filename):
     """
     Extracts the given file to a temporarily and returns
     the path of the directory with the extracted content.
     """
     prefix = 'moose_%s_template_' % self.app_or_project
     tempdir = tempfile.mkdtemp(prefix=prefix, suffix='_extract')
     self.paths_to_remove.append(tempdir)
     if self.verbosity >= 2:
         self.stdout.write("Extracting %s\n" % filename)
     try:
         archive.extract(filename, tempdir)
         return tempdir
     except (archive.ArchiveException, IOError) as e:
         raise CommandError("couldn't extract file %s to %s: %s" %
                            (filename, tempdir, e))
예제 #8
0
파일: run.py 프로젝트: yuwenhui/moose
    def handle_app_config(self, app_config, **options):
        self.action_alias = options['action']
        self.configs = options['configs']

        keep_quite = options['quite']
        recipients = options['recipients']
        message = options.get('message', self.comment())

        # start to time
        record = CommandRecord(app_config, self, message)

        # get user-defined class for the action
        action_klass = app_config.get_action_klass(self.action_alias)
        if action_klass:
            actor = action_klass(app_config)
        else:
            raise CommandError("Unknown action alias '%s'." %
                               self.action_alias)

        # run with configs and get the output
        output = []
        for conf_desc in self.configs:
            config_loader = find_matched_conf(app_config, conf_desc)
            if not config_loader:
                # Instead of raising an exception, makes a report after all done
                err_msg = "No matched config found for description '%s', aborted." % conf_desc
                output.append(err_msg)
                continue
            else:
                config = config_loader._parse()
                output.append(actor.run(config=config, app=app_config))

        # to close the timer
        record.done()

        if not keep_quite:
            records.add(record)

        output_str = '\n'.join(output)
        if recipients:
            mail_sender = CommandRunNotifier(recipients)
            context = mail_sender.get_context(record, self, output_str)
            mail_sender.send(context)

        return output_str
예제 #9
0
    def handle(self, **options):
        project_name, target = options.pop('name'), options.pop('directory')
        self.validate_name(project_name, "project")

        # Check that the project_name cannot be imported.
        try:
            import_module(project_name)
        except ImportError:
            pass
        else:
            raise CommandError(
                "%r conflicts with the name of an existing Python module and "
                "cannot be used as a project name. Please try another name." %
                project_name)

        # Create a random SECRET_KEY to put it in the main settings.
        options['secret_key'] = get_random_secret_key()

        super(Command, self).handle('project', project_name, target, **options)
예제 #10
0
파일: templates.py 프로젝트: muma378/moose
    def handle(self, app_or_project, name, target=None, **options):
        self.app_or_project = app_or_project
        self.paths_to_remove = []
        self.verbosity = options['verbosity']

        self.validate_name(name, app_or_project)

        # if some directory is given, make sure it's nicely expanded
        if target is None:
            top_dir = path.join(os.getcwd(), name)
            try:
                os.makedirs(top_dir)
            except OSError as e:
                if e.errno == errno.EEXIST:
                    message = "'%s' already exists" % top_dir
                else:
                    message = e
                raise CommandError(message)
        else:
            top_dir = os.path.abspath(path.expanduser(target))
            if not os.path.exists(top_dir):
                raise CommandError("Destination directory '%s' does not "
                                   "exist, please create it first." % top_dir)

        extensions = tuple(handle_extensions(options['extensions']))
        extra_files = []
        for file in options['files']:
            extra_files.extend(map(lambda x: x.strip(), file.split(',')))
        if self.verbosity >= 2:
            self.stdout.write("Rendering %s template files with "
                              "extensions: %s\n" %
                              (app_or_project, ', '.join(extensions)))
            self.stdout.write("Rendering %s template files with "
                              "filenames: %s\n" %
                              (app_or_project, ', '.join(extra_files)))

        base_name = '%s_name' % app_or_project
        base_subdir = '%s_template' % app_or_project
        base_directory = '%s_directory' % app_or_project
        camel_case_name = 'camel_case_%s_name' % app_or_project
        camel_case_value = ''.join(x for x in name.title() if x != '_')

        # context = Context(dict(options, **{
        #     base_name: name,
        #     base_directory: top_dir,
        #     camel_case_name: camel_case_value,
        #     # 'docs_version': get_docs_version(),
        #     'moose_version': moose.__version__,
        #     'unicode_literals': '' if six.PY3 else '# -*- coding: utf-8 -*-\n'
        #                                            'from __future__ import unicode_literals\n\n',
        # }), autoescape=False)

        context = dict(
            options,
            **{
                base_name:
                name,
                base_directory:
                top_dir,
                camel_case_name:
                camel_case_value,
                # 'docs_version': get_docs_version(),
                'moose_version':
                moose.__version__,
                'unicode_literals':
                '' if six.PY3 else '# -*- coding: utf-8 -*-\n'
                'from __future__ import unicode_literals\n\n',
            })

        # Setup a stub settings environment for template rendering
        if not settings.configured:
            settings.configure()
            if app_or_project == 'app':
                moose.setup()

        template_dir = self.handle_template(options['template'], base_subdir)
        prefix_length = len(template_dir) + 1

        for root, dirs, files in os.walk(template_dir):
            path_rest = root[prefix_length:]
            relative_dir = path_rest.replace(base_name, name)
            if relative_dir:
                target_dir = path.join(top_dir, relative_dir)
                if not path.exists(target_dir):
                    os.mkdir(target_dir)

            for dirname in dirs[:]:
                if dirname.startswith('.') or dirname == '__pycache__':
                    dirs.remove(dirname)

            for filename in files:
                if filename.endswith(('.pyo', '.pyc', '.py.class')):
                    # Ignore some files as they cause various breakages.
                    continue
                old_path = path.join(root, filename)
                new_path = path.join(top_dir, relative_dir,
                                     filename.replace(base_name, name))
                for old_suffix, new_suffix in self.rewrite_template_suffixes:
                    if new_path.endswith(old_suffix):
                        new_path = new_path[:-len(old_suffix)] + new_suffix
                        break  # Only rewrite once

                if path.exists(new_path):
                    raise CommandError("%s already exists, overlaying a "
                                       "project or app into an existing "
                                       "directory won't replace conflicting "
                                       "files" % new_path)

                # Only render the Python files, as we don't want to
                # accidentally render Moose templates files
                if new_path.endswith(extensions) or filename in extra_files:
                    with io.open(old_path, 'r',
                                 encoding='utf-8') as template_file:
                        content = template_file.read()
                    # TODO: use Jinja2 instead of implementing template engine self
                    # template = Engine().from_string(content)
                    # content = template.render(context)
                    content = string.Template(content).substitute(**context)
                    with io.open(new_path, 'w', encoding='utf-8') as new_file:
                        new_file.write(content)
                else:
                    shutil.copyfile(old_path, new_path)

                if self.verbosity >= 2:
                    self.stdout.write("Creating %s\n" % new_path)
                try:
                    shutil.copymode(old_path, new_path)
                    self.make_writeable(new_path)
                except OSError:
                    self.stderr.write(
                        "Notice: Couldn't set permission bits on %s. You're "
                        "probably using an uncommon filesystem setup. No "
                        "problem." % new_path, self.style.NOTICE)

        if self.paths_to_remove:
            if self.verbosity >= 2:
                self.stdout.write("Cleaning up temporary files.\n")
            for path_to_remove in self.paths_to_remove:
                if path.isfile(path_to_remove):
                    os.remove(path_to_remove)
                else:
                    shutil.rmtree(path_to_remove)