コード例 #1
0
 def command(self):
     if self.options.list_entry_points:
         return self.list_entry_points()
     if self.options.show_egg:
         return self.show_egg(self.options.show_egg)
     if not self.args:
         raise BadCommand("You must give an entry point (or --list)")
     pattern = self.get_pattern(self.args[0])
     groups = self.get_groups_by_pattern(pattern)
     if not groups:
         raise BadCommand('No group matched %s' % self.args[0])
     ep_pat = None
     if len(self.args) > 1:
         ep_pat = self.get_pattern(self.args[1])
     for group in groups:
         desc = self.get_group_description(group)
         print '[%s]' % group
         if desc:
             print self.wrap(desc)
             print
         by_dist = {}
         self.print_entry_points_by_group(group, ep_pat)
コード例 #2
0
 def parse_args(self, args):
     if args == ['-h']:
         Command.parse_args(self, args)
         return
     # These are the arguments parsed normally:
     normal_args = []
     # And these are arguments passed to the URL:
     extra_args = []
     # This keeps track of whether we have the two required positional arguments:
     pos_args = 0
     while args:
         start = args[0]
         if not start.startswith('-'):
             if pos_args < 2:
                 pos_args += 1
                 normal_args.append(start)
                 args.pop(0)
                 continue
             else:
                 normal_args.append(start)
                 args.pop(0)
                 continue
         else:
             found = False
             for option in self.ARG_OPTIONS:
                 if start == option:
                     normal_args.append(start)
                     args.pop(0)
                     if not args:
                         raise BadCommand("Option %s takes an argument" %
                                          option)
                     normal_args.append(args.pop(0))
                     found = True
                     break
                 elif start.startswith(option + '='):
                     normal_args.append(start)
                     args.pop(0)
                     found = True
                     break
             if found:
                 continue
             if start in self.OTHER_OPTIONS:
                 normal_args.append(start)
                 args.pop(0)
                 continue
             extra_args.append(start)
             args.pop(0)
     Command.parse_args(self, normal_args)
     # Add the extra arguments back in:
     self.args = self.args + extra_args
コード例 #3
0
 def change_user_group(self, user, group):
     if not user and not group:
         return
     import pwd, grp
     uid = gid = None
     if group:
         try:
             gid = int(group)
             group = grp.getgrgid(gid).gr_name
         except ValueError:
             import grp
             try:
                 entry = grp.getgrnam(group)
             except KeyError:
                 raise BadCommand("Bad group: %r; no such group exists" %
                                  group)
             gid = entry.gr_gid
     try:
         uid = int(user)
         user = pwd.getpwuid(uid).pw_name
     except ValueError:
         try:
             entry = pwd.getpwnam(user)
         except KeyError:
             raise BadCommand("Bad username: %r; no such user exists" %
                              user)
         if not gid:
             gid = entry.pw_gid
         uid = entry.pw_uid
     if self.verbose > 0:
         print 'Changing user to %s:%s (%s:%s)' % (user, group
                                                   or '(unknown)', uid, gid)
     if gid:
         os.setgid(gid)
     if uid:
         os.setuid(uid)
コード例 #4
0
    def command(self):
        if self.options.list_templates:
            return self.list_templates()
        asked_tmpls = self.options.templates or ['basic_package']
        templates = []
        for tmpl_name in asked_tmpls:
            self.extend_templates(templates, tmpl_name)
        if self.options.list_variables:
            return self.list_variables(templates)
        if self.verbose:
            print 'Selected and implied templates:'
            max_tmpl_name = max([len(tmpl_name) for tmpl_name, tmpl in templates])
            for tmpl_name, tmpl in templates:
                print '  %s%s  %s' % (
                    tmpl_name, ' '*(max_tmpl_name-len(tmpl_name)),
                    tmpl.summary)
            print
        if not self.args:
            if self.interactive:
                dist_name = self.challenge('Enter project name')
            else:
                raise BadCommand('You must provide a PACKAGE_NAME')
        else:
            dist_name = self.args[0].lstrip(os.path.sep)

        templates = [tmpl for name, tmpl in templates]
        output_dir = os.path.join(self.options.output_dir, dist_name)
        
        pkg_name = self._bad_chars_re.sub('', dist_name.lower())
        vars = {'project': dist_name,
                'package': pkg_name,
                'egg': pluginlib.egg_name(dist_name),
                }
        vars.update(self.parse_vars(self.args[1:]))
        if self.options.config and os.path.exists(self.options.config):
            for key, value in self.read_vars(self.options.config).items():
                vars.setdefault(key, value)
        
        if self.verbose: # @@: > 1?
            self.display_vars(vars)

        if self.options.inspect_files:
            self.inspect_files(
                output_dir, templates, vars)
            return
        if not os.path.exists(output_dir):
            # We want to avoid asking questions in copydir if the path
            # doesn't exist yet
            copydir.all_answer = 'y'
        
        if self.options.svn_repository:
            self.setup_svn_repository(output_dir, dist_name)

        # First we want to make sure all the templates get a chance to
        # set their variables, all at once, with the most specialized
        # template going first (the last template is the most
        # specialized)...
        for template in templates[::-1]:
            vars = template.check_vars(vars, self)
            
        for template in templates:
            self.create_template(
                template, output_dir, vars)

        found_setup_py = False
        if os.path.exists(os.path.join(output_dir, 'setup.py')):
            self.run_command(sys.executable, 'setup.py', 'egg_info',
                             cwd=output_dir,
                             # This shouldn't be necessary, but a bug in setuptools 0.6c3 is causing a (not entirely fatal) problem that I don't want to fix right now:
                             expect_returncode=True)
            found_setup_py = True
        elif self.verbose > 1:
            print 'No setup.py (cannot run egg_info)'

        package_dir = vars.get('package_dir', None)
        if package_dir:
            output_dir = os.path.join(output_dir, package_dir)

        # With no setup.py this doesn't make sense:
        if found_setup_py:
            egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
            for template in templates:
                for spec in template.egg_plugins:
                    if self.verbose:
                        print 'Adding %s to paster_plugins.txt' % spec
                    if not self.simulate:
                        pluginlib.add_plugin(egg_info_dir, spec)
            if not self.simulate:
                # We'll include this by default, but you can remove
                # it later if you want:
                pluginlib.add_plugin(egg_info_dir, 'PasteScript')
        
        if self.options.svn_repository:
            self.add_svn_repository(vars, output_dir)

        if self.options.config:
            write_vars = vars.copy()
            del write_vars['project']
            del write_vars['package']
            self.write_vars(self.options.config, write_vars)
コード例 #5
0
    def command(self):
        if self.options.list_templates:
            return self.list_templates()
        asked_tmpls = self.options.templates or ['basic_package']
        templates = []
        for tmpl_name in asked_tmpls:
            self.extend_templates(templates, tmpl_name)
        if self.options.list_variables:
            return self.list_variables(templates)
        if self.verbose:
            print 'Selected and implied templates:'
            max_tmpl_name = max(
                [len(tmpl_name) for tmpl_name, tmpl in templates])
            for tmpl_name, tmpl in templates:
                print '  %s%s  %s' % (tmpl_name, ' ' *
                                      (max_tmpl_name - len(tmpl_name)),
                                      tmpl.summary)
            print
        if not self.args:
            if self.interactive:
                dist_name = self.challenge('Enter project name')
            else:
                raise BadCommand('You must provide a PACKAGE_NAME')
        else:
            dist_name = self.args[0].lstrip(os.path.sep)

        templates = [tmpl for name, tmpl in templates]
        output_dir = os.path.join(self.options.output_dir, dist_name)

        pkg_name = self._bad_chars_re.sub('', dist_name.lower())
        vars = {
            'project': dist_name,
            'package': pkg_name,
            'egg': pluginlib.egg_name(dist_name),
        }
        vars.update(self.parse_vars(self.args[1:]))
        if self.options.config and os.path.exists(self.options.config):
            for key, value in self.read_vars(self.options.config).items():
                vars.setdefault(key, value)

        if self.verbose:  # @@: > 1?
            self.display_vars(vars)

        if self.options.inspect_files:
            self.inspect_files(output_dir, templates, vars)
            return
        if not os.path.exists(output_dir):
            # We want to avoid asking questions in copydir if the path
            # doesn't exist yet
            copydir.all_answer = 'y'

        if self.options.svn_repository:
            self.setup_svn_repository(output_dir, dist_name)

        # First we want to make sure all the templates get a chance to
        # set their variables, all at once, with the most specialized
        # template going first (the last template is the most
        # specialized)...
        for template in templates[::-1]:
            vars = template.check_vars(vars, self)

        # Gather all the templates egg_plugins into one var
        egg_plugins = set()
        for template in templates:
            egg_plugins.update(template.egg_plugins)
        egg_plugins = list(egg_plugins)
        egg_plugins.sort()
        vars['egg_plugins'] = egg_plugins

        for template in templates:
            self.create_template(template, output_dir, vars)

        found_setup_py = False
        paster_plugins_mtime = None
        if os.path.exists(os.path.join(output_dir, 'setup.py')):
            # Grab paster_plugins.txt's mtime; used to determine if the
            # egg_info command wrote to it
            try:
                egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
            except IOError:
                egg_info_dir = None
            if egg_info_dir is not None:
                plugins_path = os.path.join(egg_info_dir, 'paster_plugins.txt')
                if os.path.exists(plugins_path):
                    paster_plugins_mtime = os.path.getmtime(plugins_path)

            self.run_command(
                sys.executable,
                'setup.py',
                'egg_info',
                cwd=output_dir,
                # This shouldn't be necessary, but a bug in setuptools 0.6c3 is causing a (not entirely fatal) problem that I don't want to fix right now:
                expect_returncode=True)
            found_setup_py = True
        elif self.verbose > 1:
            print 'No setup.py (cannot run egg_info)'

        package_dir = vars.get('package_dir', None)
        if package_dir:
            output_dir = os.path.join(output_dir, package_dir)

        # With no setup.py this doesn't make sense:
        if found_setup_py:
            # Only write paster_plugins.txt if it wasn't written by
            # egg_info (the correct way). leaving us to do it is
            # deprecated and you'll get warned
            egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
            plugins_path = os.path.join(egg_info_dir, 'paster_plugins.txt')
            if len(egg_plugins) and (not os.path.exists(plugins_path) or \
                    os.path.getmtime(plugins_path) == paster_plugins_mtime):
                if self.verbose:
                    print >> sys.stderr, \
                        ('Manually creating paster_plugins.txt (deprecated! '
                         'pass a paster_plugins keyword to setup() instead)')
                for plugin in egg_plugins:
                    if self.verbose:
                        print 'Adding %s to paster_plugins.txt' % plugin
                    if not self.simulate:
                        pluginlib.add_plugin(egg_info_dir, plugin)

        if self.options.svn_repository:
            self.add_svn_repository(vars, output_dir)

        if self.options.config:
            write_vars = vars.copy()
            del write_vars['project']
            del write_vars['package']
            self.write_vars(self.options.config, write_vars)
コード例 #6
0
    def command(self):
        vars = {}
        app_spec = self.args[0]
        url = self.args[1]
        url = urlparse.urljoin('/.command/', url)
        if self.options.config_vars:
            for item in self.option.config_vars:
                if ':' not in item:
                    raise BadCommand(
                        "Bad option, should be name:value : --config-var=%s" %
                        item)
                name, value = item.split(':', 1)
                vars[name] = value
        headers = {}
        if self.options.headers:
            for item in self.options.headers:
                if ':' not in item:
                    raise BadCommand(
                        "Bad option, should be name:value : --header=%s" %
                        item)
                name, value = item.split(':', 1)
                headers[name] = value.strip()
        if not self._scheme_re.search(app_spec):
            app_spec = 'config:' + app_spec
        if self.options.app_name:
            if '#' in app_spec:
                app_spec = app_spec.split('#', 1)[0]
            app_spec = app_spec + '#' + options.app_name
        app = loadapp(app_spec, relative_to=os.getcwd(), global_conf=vars)
        if self.command_name.lower() == 'post':
            request_method = 'POST'
        else:
            request_method = 'GET'
        qs = []
        for item in self.args[2:]:
            if '=' in item:
                item = urllib.quote(item.split(
                    '=', 1)[0]) + '=' + urllib.quote(item.split('=', 1)[1])
            else:
                item = urllib.quote(item)
            qs.append(item)
        qs = '&'.join(qs)

        environ = {
            'REQUEST_METHOD': request_method,
            ## FIXME: shouldn't be static (an option?):
            'CONTENT_TYPE': 'text/plain',
            'wsgi.run_once': True,
            'wsgi.multithread': False,
            'wsgi.multiprocess': False,
            'wsgi.errors': sys.stderr,
            'QUERY_STRING': qs,
            'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1',
            'paste.command_request': True,
        }
        if request_method == 'POST':
            environ['wsgi.input'] = sys.stdin
            environ['CONTENT_LENGTH'] = '-1'
        for name, value in headers.items():
            if name.lower() == 'content-type':
                name = 'CONTENT_TYPE'
            else:
                name = 'HTTP_' + name.upper().replace('-', '_')
            environ[name] = value

        status, headers, output, errors = raw_interactive(app, url, **environ)
        assert not errors, "errors should be printed directly to sys.stderr"
        if self.options.display_headers:
            for name, value in headers:
                sys.stdout.write('%s: %s\n' % (name, value))
            sys.stdout.write('\n')
        sys.stdout.write(output)
        sys.stdout.flush()
        status_int = int(status.split()[0])
        if status_int != 200:
            return status_int
コード例 #7
0
class ServeCommand(Command):

    min_args = 0
    usage = 'CONFIG_FILE [start|stop|restart|status] [var=value]'
    takes_config_file = 1
    summary = "Serve the described application"
    description = """\
    This command serves a web application that uses a paste.deploy
    configuration file for the server and application.  
    
    If start/stop/restart is given, then --daemon is implied, and it will
    start (normal operation), stop (--stop-daemon), or do both.

    You can also include variable assignments like 'http_port=8080'
    and then use %(http_port)s in your config files.
    """

    # used by subclasses that configure apps and servers differently
    requires_config_file = True

    parser = Command.standard_parser(quiet=True)
    parser.add_option('-n',
                      '--app-name',
                      dest='app_name',
                      metavar='NAME',
                      help="Load the named application (default main)")
    parser.add_option('-s',
                      '--server',
                      dest='server',
                      metavar='SERVER_TYPE',
                      help="Use the named server.")
    parser.add_option(
        '--server-name',
        dest='server_name',
        metavar='SECTION_NAME',
        help=
        "Use the named server as defined in the configuration file (default: main)"
    )
    if hasattr(os, 'fork'):
        parser.add_option('--daemon',
                          dest="daemon",
                          action="store_true",
                          help="Run in daemon (background) mode")
    parser.add_option(
        '--pid-file',
        dest='pid_file',
        metavar='FILENAME',
        help=
        "Save PID to file (default to paster.pid if running in daemon mode)")
    parser.add_option(
        '--log-file',
        dest='log_file',
        metavar='LOG_FILE',
        help="Save output to the given log file (redirects stdout)")
    parser.add_option('--reload',
                      dest='reload',
                      action='store_true',
                      help="Use auto-restart file monitor")
    parser.add_option(
        '--reload-interval',
        dest='reload_interval',
        default=1,
        help=
        "Seconds between checking files (low number can cause significant CPU usage)"
    )
    parser.add_option('--monitor-restart',
                      dest='monitor_restart',
                      action='store_true',
                      help="Auto-restart server if it dies")
    parser.add_option(
        '--status',
        action='store_true',
        dest='show_status',
        help="Show the status of the (presumably daemonized) server")

    if hasattr(os, 'setuid'):
        # I don't think these are available on Windows
        parser.add_option(
            '--user',
            dest='set_user',
            metavar="USERNAME",
            help="Set the user (usually only possible when run as root)")
        parser.add_option(
            '--group',
            dest='set_group',
            metavar="GROUP",
            help="Set the group (usually only possible when run as root)")

    parser.add_option(
        '--stop-daemon',
        dest='stop_daemon',
        action='store_true',
        help=
        'Stop a daemonized server (given a PID file, or default paster.pid file)'
    )

    if jython:
        parser.add_option('--disable-jython-reloader',
                          action='store_true',
                          dest='disable_jython_reloader',
                          help="Disable the Jython reloader")

    _scheme_re = re.compile(r'^[a-z][a-z]+:', re.I)

    default_verbosity = 1

    _reloader_environ_key = 'PYTHON_RELOADER_SHOULD_RUN'
    _monitor_environ_key = 'PASTE_MONITOR_SHOULD_RUN'

    possible_subcommands = ('start', 'stop', 'restart', 'status')

    def command(self):
        if self.options.stop_daemon:
            return self.stop_daemon()

        if not hasattr(self.options, 'set_user'):
            # Windows case:
            self.options.set_user = self.options.set_group = None
        # @@: Is this the right stage to set the user at?
        self.change_user_group(self.options.set_user, self.options.set_group)

        if self.requires_config_file:
            if not self.args:
                raise BadCommand('You must give a config file')
            app_spec = self.args[0]
            if (len(self.args) > 1
                    and self.args[1] in self.possible_subcommands):
                cmd = self.args[1]
                restvars = self.args[2:]
            else:
                cmd = None
                restvars = self.args[1:]
        else:
            app_spec = ""
            if (self.args and self.args[0] in self.possible_subcommands):
                cmd = self.args[0]
                restvars = self.args[1:]
            else:
                cmd = None
                restvars = self.args[:]

        jython_monitor = False
        if self.options.reload:
            if jython and not self.options.disable_jython_reloader:
                # JythonMonitor raises the special SystemRestart
                # exception that'll cause the Jython interpreter to
                # reload in the existing Java process (avoiding
                # subprocess startup time)
                try:
                    from paste.reloader import JythonMonitor
                except ImportError:
                    pass
                else:
                    jython_monitor = JythonMonitor(
                        poll_interval=int(self.options.reload_interval))
                    if self.requires_config_file:
                        jython_monitor.watch_file(self.args[0])

            if not jython_monitor:
                if os.environ.get(self._reloader_environ_key):
                    from paste import reloader
                    if self.verbose > 1:
                        print 'Running reloading file monitor'
                    reloader.install(int(self.options.reload_interval))
                    if self.requires_config_file:
                        reloader.watch_file(self.args[0])
                else:
                    return self.restart_with_reloader()

        if cmd not in (None, 'start', 'stop', 'restart', 'status'):
            raise BadCommand('Error: must give start|stop|restart (not %s)' %
                             cmd)

        if cmd == 'status' or self.options.show_status:
            return self.show_status()

        if cmd == 'restart' or cmd == 'stop':
            result = self.stop_daemon()
            if result:
                if cmd == 'restart':
                    print "Could not stop daemon; aborting"
                else:
                    print "Could not stop daemon"
                return result
            if cmd == 'stop':
                return result

        app_name = self.options.app_name
        vars = self.parse_vars(restvars)
        if not self._scheme_re.search(app_spec):
            app_spec = 'config:' + app_spec
        server_name = self.options.server_name
        if self.options.server:
            server_spec = 'egg:PasteScript'
            assert server_name is None
            server_name = self.options.server
        else:
            server_spec = app_spec
        base = os.getcwd()

        if getattr(self.options, 'daemon', False):
            if not self.options.pid_file:
                self.options.pid_file = 'paster.pid'
            if not self.options.log_file:
                self.options.log_file = 'paster.log'

        # Ensure the log file is writeable
        if self.options.log_file:
            try:
                writeable_log_file = open(self.options.log_file, 'a')
            except IOError, ioe:
                msg = 'Error: Unable to write to log file: %s' % ioe
                raise BadCommand(msg)
            writeable_log_file.close()

        # Ensure the pid file is writeable
        if self.options.pid_file:
            try:
                writeable_pid_file = open(self.options.pid_file, 'a')
            except IOError, ioe:
                msg = 'Error: Unable to write to pid file: %s' % ioe
                raise BadCommand(msg)
            writeable_pid_file.close()
コード例 #8
0
    def command(self):
        if self.options.stop_daemon:
            return self.stop_daemon()

        if not hasattr(self.options, 'set_user'):
            # Windows case:
            self.options.set_user = self.options.set_group = None
        # @@: Is this the right stage to set the user at?
        self.change_user_group(self.options.set_user, self.options.set_group)

        if self.requires_config_file:
            if not self.args:
                raise BadCommand('You must give a config file')
            app_spec = self.args[0]
            if (len(self.args) > 1
                    and self.args[1] in self.possible_subcommands):
                cmd = self.args[1]
                restvars = self.args[2:]
            else:
                cmd = None
                restvars = self.args[1:]
        else:
            app_spec = ""
            if (self.args and self.args[0] in self.possible_subcommands):
                cmd = self.args[0]
                restvars = self.args[1:]
            else:
                cmd = None
                restvars = self.args[:]

        jython_monitor = False
        if self.options.reload:
            if jython and not self.options.disable_jython_reloader:
                # JythonMonitor raises the special SystemRestart
                # exception that'll cause the Jython interpreter to
                # reload in the existing Java process (avoiding
                # subprocess startup time)
                try:
                    from paste.reloader import JythonMonitor
                except ImportError:
                    pass
                else:
                    jython_monitor = JythonMonitor(
                        poll_interval=int(self.options.reload_interval))
                    if self.requires_config_file:
                        jython_monitor.watch_file(self.args[0])

            if not jython_monitor:
                if os.environ.get(self._reloader_environ_key):
                    from paste import reloader
                    if self.verbose > 1:
                        print 'Running reloading file monitor'
                    reloader.install(int(self.options.reload_interval))
                    if self.requires_config_file:
                        reloader.watch_file(self.args[0])
                else:
                    return self.restart_with_reloader()

        if cmd not in (None, 'start', 'stop', 'restart', 'status'):
            raise BadCommand('Error: must give start|stop|restart (not %s)' %
                             cmd)

        if cmd == 'status' or self.options.show_status:
            return self.show_status()

        if cmd == 'restart' or cmd == 'stop':
            result = self.stop_daemon()
            if result:
                if cmd == 'restart':
                    print "Could not stop daemon; aborting"
                else:
                    print "Could not stop daemon"
                return result
            if cmd == 'stop':
                return result

        app_name = self.options.app_name
        vars = self.parse_vars(restvars)
        if not self._scheme_re.search(app_spec):
            app_spec = 'config:' + app_spec
        server_name = self.options.server_name
        if self.options.server:
            server_spec = 'egg:PasteScript'
            assert server_name is None
            server_name = self.options.server
        else:
            server_spec = app_spec
        base = os.getcwd()

        if getattr(self.options, 'daemon', False):
            if not self.options.pid_file:
                self.options.pid_file = 'paster.pid'
            if not self.options.log_file:
                self.options.log_file = 'paster.log'

        # Ensure the log file is writeable
        if self.options.log_file:
            try:
                writeable_log_file = open(self.options.log_file, 'a')
            except IOError, ioe:
                msg = 'Error: Unable to write to log file: %s' % ioe
                raise BadCommand(msg)
            writeable_log_file.close()