diff options
author | Ian Bicking <ian@ianbicking.org> | 2005-08-22 21:20:19 +0000 |
---|---|---|
committer | Ian Bicking <ian@ianbicking.org> | 2005-08-22 21:20:19 +0000 |
commit | 9eda7b8dd739a698e7db1448315d32436b8e5041 (patch) | |
tree | 3e037dd06df830384cd5515a84ffcdbc83e79eef | |
parent | 2bc2372e7a4bdbcdbccf416b3305a09416108b85 (diff) | |
download | paste-git-9eda7b8dd739a698e7db1448315d32436b8e5041.tar.gz |
Removed configuration and other parts redundant with paste.deploy
-rw-r--r-- | paste/app_setup.py | 646 | ||||
-rw-r--r-- | paste/configmiddleware.py | 46 | ||||
-rw-r--r-- | paste/makeapp.py | 43 | ||||
-rw-r--r-- | paste/pyconfig.py | 439 | ||||
-rwxr-xr-x | paste/server.py | 248 | ||||
-rw-r--r-- | paste/tests/pyconfig_data/context.py | 8 | ||||
-rw-r--r-- | paste/tests/pyconfig_data/deriv.conf | 3 | ||||
-rw-r--r-- | paste/tests/pyconfig_data/loader.conf | 5 | ||||
-rw-r--r-- | paste/tests/pyconfig_data/loader_included.conf | 2 | ||||
-rw-r--r-- | paste/tests/pyconfig_data/loader_loaded.conf | 2 | ||||
-rw-r--r-- | paste/tests/pyconfig_data/nest1.conf | 3 | ||||
-rw-r--r-- | paste/tests/pyconfig_data/nest2.conf | 2 | ||||
-rw-r--r-- | paste/tests/pyconfig_data/one.py | 2 | ||||
-rw-r--r-- | paste/tests/test_pyconfig.py | 58 |
14 files changed, 0 insertions, 1507 deletions
diff --git a/paste/app_setup.py b/paste/app_setup.py deleted file mode 100644 index 666e194..0000000 --- a/paste/app_setup.py +++ /dev/null @@ -1,646 +0,0 @@ -#!/usr/bin/env python - -import optparse -import fnmatch -import os -import sys -import atexit -from cStringIO import StringIO -import re -import textwrap -try: - import signal -except ImportError: - # Not available on Windows? - pass - -if sys.version < (2, 4): - from paste.util import string24 as string -else: - import string - -from paste import pyconfig -from paste import urlparser -from paste import server -from paste import CONFIG -from paste.util import plugin -from paste.util import import_string - -class InvalidCommand(Exception): - pass - -def find_template_info(args): - """ - Given command-line arguments, this finds the app template - (paste.app_templates.<template_name>.command). It looks for a - -t or --template option (but ignores all other options), and if - none then looks in server.conf for a template_name option. - - Returns server_conf_fn, template_name, template_dir, module - """ - template_name = None - template_name, rest = find_template_option(args) - server_conf_fn = None - if template_name: - next_template_name, rest = find_template_option(rest) - if next_template_name: - raise InvalidCommand( - 'You cannot give two templates on the commandline ' - '(first I found %r, then %r)' - % (template_name, next_template_name)) - else: - server_conf_fn, template_name = find_template_config(args) - if not template_name: - template_name = 'default' - template_mod = plugin.load_plugin_module( - 'app_templates', 'paste.app_templates', - template_name, '_tmpl') - return (server_conf_fn, template_name, - os.path.dirname(template_mod.__file__), template_mod) - -def find_template_option(args): - copy = args[:] - while copy: - if copy[0] == '--': - return None, copy - if copy[0] == '-t' or copy[0] == '--template': - if not copy[1:] or copy[1].startswith('-'): - raise InvalidCommand( - '%s needs to be followed with a template name' % copy[0]) - return copy[1], copy[2:] - if copy[0].startswith('-t'): - return copy[0][2:], copy[1:] - if copy[0].startswith('--template='): - return copy[0][len('--template='):], copy[1:] - copy.pop(0) - return None, [] - -def find_template_config(args): - base = os.getcwd() - while 1: - conf_fn = os.path.join(base, 'server.conf') - if os.path.exists(conf_fn): - break - base, last_base = os.path.dirname(base), base - if last_base == base: # Root dir - return None, None - conf = pyconfig.Config(with_default=True) - conf.load(conf_fn) - return conf_fn, conf.get('app_template') - -def run(args): - try: - server_conf_fn, name, dir, mod = find_template_info(args) - except InvalidCommand, e: - print str(e) - return 2 - return mod.run(args, name, dir, mod, server_conf_fn) - -class CommandRunner(object): - - def __init__(self): - self.commands = {} - self.command_aliases = {} - self.register_standard_commands() - self.server_conf_fn = None - - def run(self, argv, template_name, template_dir, template_module, - server_conf_fn): - self.server_conf_fn = server_conf_fn - invoked_as = argv[0] - args = argv[1:] - for i in range(len(args)): - if not args[i].startswith('-'): - # this must be a command - command = args[i].lower() - del args[i] - break - else: - # no command found - self.invalid('No COMMAND given (try "%s help")' - % os.path.basename(invoked_as)) - real_command = self.command_aliases.get(command, command) - if real_command not in self.commands.keys(): - self.invalid('COMMAND %s unknown' % command) - runner = self.commands[real_command]( - invoked_as, command, args, self, - template_name, template_dir, template_module) - runner.run() - - def register(self, command): - name = command.name - self.commands[name] = command - for alias in command.aliases: - self.command_aliases[alias] = name - - def invalid(self, msg, code=2): - print msg - sys.exit(code) - - def register_standard_commands(self): - self.register(CommandHelp) - self.register(CommandList) - self.register(CommandServe) - #self.register(CommandInstall) - -############################################################ -## Command framework -############################################################ - -def standard_parser(verbose=True, simulate=True, interactive=False): - parser = optparse.OptionParser() - if verbose: - parser.add_option('-v', '--verbose', - help='Be verbose (multiple times for more verbosity)', - action='count', - dest='verbose', - default=0) - if simulate: - parser.add_option('-n', '--simulate', - help="Don't actually do anything (implies -v)", - action='store_true', - dest='simulate') - if interactive: - parser.add_option('-i', '--interactive', - help="Ask before doing anything (use twice to be more careful)", - action="count", - dest="interactive", - default=0) - parser.add_option('-t', '--template', - help='Use this template', - metavar='NAME', - dest='template_name') - return parser - -class Command(object): - - min_args = 0 - min_args_error = 'You must provide at least %(min_args)s arguments' - max_args = 0 - max_args_error = 'You must provide no more than %(max_args)s arguments' - aliases = () - required_args = [] - description = None - - def __init__(self, invoked_as, command_name, args, runner, - template_name, template_dir, template_module): - self.invoked_as = invoked_as - self.command_name = command_name - self.raw_args = args - self.runner = runner - self.template_name = template_name - self.template_dir = template_dir - self.template_module = template_module - - def run(self): - self.parse_args(self.raw_args) - if (getattr(self.options, 'simulate', False) - and not self.options.verbose): - self.options.verbose = 1 - if self.min_args is not None and len(self.args) < self.min_args: - self.runner.invalid( - self.min_args_error % {'min_args': self.min_args, - 'actual_args': len(self.args)}) - if self.max_args is not None and len(self.args) > self.max_args: - self.runner.invalid( - self.max_args_error % {'max_args': self.max_args, - 'actual_args': len(self.args)}) - for var_name, option_name in self.required_args: - if not getattr(self.options, var_name, None): - self.runner.invalid( - 'You must provide the option %s' % option_name) - self.command() - - def parse_args(self, args): - self.parser.usage = "%%prog [options]\n%s" % self.summary - self.parser.prog = '%s %s' % ( - os.path.basename(self.invoked_as), - self.command_name) - if self.description: - self.parser.description = self.description - self.options, self.args = self.parser.parse_args(args) - - def ask(self, prompt, safe=False, default=True): - if self.options.interactive >= 2: - default = safe - if default: - prompt += ' [Y/n]? ' - else: - prompt += ' [y/N]? ' - while 1: - response = raw_input(prompt).strip() - if not response.strip(): - return default - if response and response[0].lower() in ('y', 'n'): - return response[0].lower() == 'y' - print 'Y or N please' - - def _get_prog_name(self): - return os.path.basename(self.invoked_as) - prog_name = property(_get_prog_name) - -############################################################ -## Standard commands -############################################################ - -class CommandList(Command): - - name = 'list' - summary = 'Show available templates' - - parser = standard_parser(simulate=False) - - max_args = 1 - - def command(self): - any = False - app_template_dir = os.path.join(os.path.dirname(__file__), 'app_templates') - for name in os.listdir(app_template_dir): - dir = os.path.join(app_template_dir, name) - if not os.path.exists(os.path.join(dir, 'description.txt')): - if self.options.verbose >= 2: - print 'Skipping %s (no description.txt)' % dir - continue - if self.args and not fnmatch.fnmatch(name, self.args[0]): - continue - if not self.options.verbose: - print '%s: %s\n' % ( - name, self.template_description(dir).splitlines()[0]) - else: - return '%s: %s\n' % ( - self.name, self.template_description(dir)) - # @@: for verbosity >= 2 we should give lots of metadata - any = True - if not any: - print 'No application templates found' - - def template_description(self, dir): - f = open(os.path.join(dir, 'description.txt')) - content = f.read().strip() - f.close() - return content - -class CommandServe(Command): - - name = 'serve' - summary = 'Run server' - parser = standard_parser(simulate=False) - parser.add_option( - '--daemon', - help="Run in daemon (background) mode", - dest="daemon", - action="store_true") - parser.add_option( - '--user', - metavar="USER_OR_UID", - help="User to run as (only works if started as root)", - dest="user") - parser.add_option( - '--group', - metavar="GROUP_OR_GID", - help="Group to run as (only works if started as root)", - dest="group") - parser.add_option( - '--pid-file', - metavar="FILENAME", - help="Write PID to FILENAME", - dest="pid_file") - parser.add_option( - '--log-file', - metavar="FILENAME", - help="File to write stdout/stderr to (other log files may still be generated by the application)", - dest="log_file") - parser.add_option( - '--server', - metavar='SERVER_NAME', - help="The kind of server to start", - dest="server") - parser.add_option( - '--stop-daemon', - help="Stop a daemon process (given the PID file)", - action="store_true", - dest="stop_daemon") - - def command(self): - conf = self.config - verbose = conf.get('verbose') or 0 - if conf.get('stop_daemon'): - return self.stop_daemon() - if conf.get('daemon'): - if not conf.get('pid_file'): - conf['pid_file'] = 'server.pid' - # We must enter daemon mode! - if verbose > 1: - print 'Entering daemon mode' - pid = os.fork() - if pid: - sys.exit() - # Always record PID and output when daemonized - if not conf.get('log_file'): - conf['log_file'] = 'server.log' - if conf.get('pid_file'): - pid_file = conf['pid_file'] - if os.path.exists(pid_file): - f = open(pid_file) - pid = int(f.read().strip()) - f.close() - pid_exists = False - try: - os.kill(pid, 0) - except OSError: - print 'Warning: PID file %s exists, but process does not exist' % pid_file - os.unlink(pid_file) - except Exception, e: - raise InvalidCommand( - 'Could not check for process existance: %s' % e) - else: - raise InvalidCommand( - 'Server process already running with pid %s' % pid) - - # @@: We should check if the pid file exists and has - # an active process in it - if verbose > 1: - print 'Writing pid %s to %s' % (os.getpid(), conf['pid_file']) - f = open(conf['pid_file'], 'w') - f.write(str(os.getpid())) - f.close() - if conf.get('log_file'): - if verbose > 1: - print 'Logging to %s' % conf['log_file'] - f = open(conf['log_file'], 'a', 1) # 1==line buffered - sys.stdout = sys.stderr = f - f.write('-'*20 - + ' Starting server PID: %s ' % os.getpid() - + '-'*20 + '\n') - self.change_user_group(conf.get('user'), conf.get('group')) - if conf.get('pid_file'): - atexit.register(_remove_pid_file, conf['pid_file']) - sys.exit(server.run_server(conf, self.app)) - - def change_user_group(self, user, group): - if not user and not group: - return - uid = gid = None - if group: - try: - gid = int(group) - except ValueError: - import grp - try: - entry = grp.getgrnam(group) - except KeyError: - raise KeyError( - "Bad group: %r; no such group exists" % group) - gid = entry[2] - try: - uid = int(user) - except ValueError: - import pwd - try: - entry = pwd.getpwnam(user) - except KeyError: - raise KeyError( - "Bad username: %r; no such user exists" % user) - if not gid: - gid = entry[3] - uid = entry[2] - if gid: - os.setgid(gid) - if uid: - os.setuid(uid) - - def stop_daemon(self): - pid_file = self.config.get('pid_file', 'server.pid') - if not os.path.exists(pid_file): - print 'No PID file exists in %s' % pid_file - return 1 - f = open(pid_file) - pid = int(f.read().strip()) - f.close() - os.kill(pid, signal.SIGTERM) - if self.config.get('verbose'): - print 'Process %i killed' % pid - return 0 - - def parse_args(self, args): - # Unlike most commands, this takes arbitrary options and folds - # them into the configuration - conf, app = server.load_commandline( - args, extra_boolean=['stop_daemon']) - if conf is None: - sys.exit(app) - if app == 'help': - self.help(conf) - sys.exit() - if conf.get('list_servers'): - self.list_servers(conf) - sys.exit() - CONFIG.push_process_config(conf) - self.config = conf - self.options = None - self.args = [] - self.app = app - - def help(self, config): - # Here we make a fake parser just to get the help - parser = optparse.OptionParser() - group = parser.add_option_group("general options") - group.add_options(server.load_commandline_options()) - extra_help = None - if config.get('server'): - try: - server_mod = server.get_server_mod(config['server']) - except plugin.PluginNotFound, e: - print "Server %s not found" % config['server'] - print " (%s)" % e - sys.exit(1) - ops = getattr(server_mod, 'options', None) - if ops: - group = parser.add_option_group( - "%s options" % server_mod.plugin_name, - description=getattr(server_mod, 'description', None)) - group.add_options(ops) - extra_help = getattr(server_mod, 'help', None) - parser.print_help() - if extra_help: - print - # @@: textwrap kills any special formatting, so maybe - # we just can't use it - #print self.fill_text(extra_help) - print extra_help - - def list_servers(self, config): - server_ops = plugin.find_plugins('servers', '_server') - server_ops.sort() - print 'These servers are available:' - print - for server_name in server_ops: - self.show_server(server_name) - - def show_server(self, server_name): - server_mod = server.get_server_mod(server_name) - print '%s:' % server_mod.plugin_name - desc = getattr(server_mod, 'description', None) - if not desc: - print ' No description available' - else: - print self.fill_text(desc) - - def fill_text(self, text): - try: - width = int(os.environ['COLUMNS']) - except (KeyError, ValueError): - width = 80 - width -= 2 - return textwrap.fill( - text, - width, - initial_indent=' '*4, - subsequent_indent=' '*4) - - -class CommandHelp(Command): - - name = 'help' - summary = 'Show help' - - parser = standard_parser(verbose=False) - - max_args = 1 - - def command(self): - if self.args: - self.runner.run([self.invoked_as, self.args[0], '-h'], - self.template_name, self.template_dir, - self.template_module, - self.runner.server_conf_fn) - else: - print 'Available commands:' - print ' (use "%s help COMMAND" or "%s COMMAND -h" ' % ( - self.prog_name, self.prog_name) - print ' for more information)' - items = self.runner.commands.items() - items.sort() - max_len = max([len(cn) for cn, c in items]) - for command_name, command in items: - print '%s:%s %s' % (command_name, - ' '*(max_len-len(command_name)), - command.summary) - if command.aliases: - print '%s (Aliases: %s)' % ( - ' '*max_len, ', '.join(command.aliases)) - -############################################################ -## Optional helper commands -############################################################ - -class CommandCreate(Command): - - name = 'create' - summary = 'Create application from template' - - max_args = 1 - min_args = 1 - - parser = standard_parser() - - default_options = { - 'server': 'wsgiutils', - 'verbose': True, - 'reload': True, - 'debug': True, - } - - def command(self): - self.output_dir = self.args[0] - self.create(self.output_dir) - if self.options.verbose: - print 'Now do:' - print ' cd %s' % self.options.output_dir - print ' wsgi-server' - - def create(self, output_dir): - file_dir = self.file_source_dir() - if not os.path.exists(file_dir): - raise OSError( - 'No %s directory, I don\'t know what to do next' % file_dir) - template_options = self.default_options.copy() - template_options.update(self.options.__dict__) - template_options['app_name'] = os.path.basename(output_dir) - template_options['base_dir'] = output_dir - template_options['absolute_base_dir'] = os.path.abspath(output_dir) - template_options['absolute_parent'] = os.path.dirname( - os.path.abspath(output_dir)) - template_options['template_name'] = self.template_name - self.copy_dir(file_dir, output_dir, template_options, - self.options.verbose, self.options.simulate) - - def file_source_dir(self): - return os.path.join(self.template_dir, 'template') - - def copy_dir(self, *args, **kw): - copy_dir(*args, **kw) - -def copy_dir(source, dest, vars, verbosity, simulate): - names = os.listdir(source) - names.sort() - if not os.path.exists(dest): - if verbosity >= 1: - print 'Creating %s/' % dest - if not simulate: - os.makedirs(dest) - elif verbosity >= 2: - print 'Directory %s exists' % dest - for name in names: - full = os.path.join(source, name) - if name.startswith('.'): - if verbosity >= 2: - print 'Skipping hidden file %s' % full - continue - dest_full = os.path.join(dest, _substitute_filename(name, vars)) - if dest_full.endswith('_tmpl'): - dest_full = dest_full[:-5] - if os.path.isdir(full): - if verbosity: - print 'Recursing into %s' % full - copy_dir(full, dest_full, vars, verbosity, simulate) - continue - f = open(full, 'rb') - content = f.read() - f.close() - content = _substitute_content(content, vars) - if verbosity: - print 'Copying %s to %s' % (full, dest_full) - if not simulate: - f = open(dest_full, 'wb') - f.write(content) - f.close() - -def _substitute_filename(fn, vars): - for var, value in vars.items(): - fn = fn.replace('+%s+' % var, str(value)) - return fn - -def _substitute_content(content, vars): - tmpl = string.Template(content) - return tmpl.substitute(TypeMapper(vars)) - -class TypeMapper(dict): - - def __getitem__(self, item): - if item.startswith('str_'): - return repr(str(self[item[4:]])) - elif item.startswith('bool_'): - if self[item[5:]]: - return 'True' - else: - return 'False' - else: - return dict.__getitem__(self, item) - -def _remove_pid_file(filename): - print "Removing %s" % filename - os.unlink(filename) - -if __name__ == '__main__': - run(sys.argv) diff --git a/paste/configmiddleware.py b/paste/configmiddleware.py deleted file mode 100644 index ddbe4ec..0000000 --- a/paste/configmiddleware.py +++ /dev/null @@ -1,46 +0,0 @@ -from paste import CONFIG -from paste import wsgilib -from paste.docsupport import metadata - -__all__ = ['ConfigMiddleware'] - -class ConfigMiddleware(object): - - """ - A WSGI middleware that adds a ``paste.config`` key to the request - environment, as well as registering the configuration temporarily - (for the length of the request) with ``paste.CONFIG``. - """ - - _wsgi_add1 = metadata.WSGIKey('paste.config', - interface='paste.pyconfig.Config') - - def __init__(self, application, config): - """ - This delegates all requests to `application`, adding a *copy* - of the configuration `config`. - """ - self.application = application - self.config = config - - def __call__(self, environ, start_response): - conf = environ['paste.config'] = self.config.copy() - app_iter = None - CONFIG.push_thread_config(conf) - try: - app_iter = self.application(environ, start_response) - finally: - if app_iter is None: - # An error occurred... - CONFIG.pop_thread_config(conf) - if type(app_iter) in (list, tuple): - # Because it is a concrete iterator (not a generator) we - # know the configuration for this thread is no longer - # needed: - CONFIG.pop_thread_config(conf) - return app_iter - else: - def close_config(): - CONFIG.pop_thread_config(conf) - new_app_iter = wsgilib.add_close(app_iter, close_config) - return new_app_iter diff --git a/paste/makeapp.py b/paste/makeapp.py deleted file mode 100644 index 9beae7b..0000000 --- a/paste/makeapp.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Helper functions for framework build_application functions. -""" - -from paste.util import import_string -from paste import lint -from paste import errormiddleware -from paste import configmiddleware - -def apply_conf_middleware(app, conf, first_middleware=()): - """ - Applies any middleware that the configuration specifies, - returning the wrapped configuration. - - If first_middleware is given, this middleware is applied most - closely to the application (before configuration middleware). - """ - all_middleware = list(first_middleware) - all_middleware.extend(conf.get('middleware', [])) - for middleware in all_middleware: - # @@: Should this use plugins too? - if isinstance(middleware, (str, unicode)): - middleware = import_string.eval_import(middleware) - app = middleware(app) - if conf.get('lint', False): - app = lint.middleware(app) - return app - -def apply_default_middleware(app, conf): - """ - Applies middleware that is generally always used. - """ - app = errormiddleware.ErrorMiddleware(app) - if conf.get('lint', False): - app = lint.middleware(app) - for middleware in conf.get('important_middleware', []): - if isinstance(middleware, (str, unicode)): - middleware = import_string.eval_import(middleware) - app = middleware(app) - if conf.get('lint', False): - app = lint.middleware(app) - app = configmiddleware.ConfigMiddleware(app, conf) - return app diff --git a/paste/pyconfig.py b/paste/pyconfig.py deleted file mode 100644 index 6823e9c..0000000 --- a/paste/pyconfig.py +++ /dev/null @@ -1,439 +0,0 @@ -""" -Python-syntax configuration loader and abstractor - -Usage:: - - conf = Config() - conf.load('file1.py') - conf.load('file2.py') - -Loads files as Python files, gets all global variables as configuration -keys. You can load multiple files, which will overwrite previous -values (but will not delete previous values). You can use attribute -or dictionary access to get values. -""" - -__all__ = ['Config', 'setup_config', 'parse_commandline', - 'DispatchingConfig', 'make_bool', 'make_list'] - -import types -import os -import sys -if sys.version_info < (2, 3): - from paste.util import UserDict24 as UserDict -else: - import UserDict -from paste.reloader import watch_file -from paste.util.threadinglocal import local -import threading -try: - import pkg_resources - require = pkg_resources.require -except ImportError: - require = None - -def load(filename): - conf = Config(with_default=True) - conf.load(filename) - return conf - -class NoContext: - pass - -class BadCommandLine(Exception): - pass - -config_local = local() - -def local_dict(): - try: - return config_local.wsgi_dict - except AttributeError: - config_local.wsgi_dict = result = {} - return result - -class Config(UserDict.DictMixin, object): - - """ - A dictionary-like object that represents configuration. - """ - - builtins = {} - - def __init__(self, with_default=False): - self.namespaces = [] - if with_default: - default_config_fn = os.path.join(os.path.dirname(__file__), - 'default_config.conf') - if os.path.exists(default_config_fn): - self.load(default_config_fn) - - def __getitem__(self, attr): - for space in self.namespaces: - if space.has_key(attr): - return space[attr] - raise KeyError( - "Configuration key %r not found" % attr) - - def __setitem__(self, attr, value): - self.namespaces[0][attr] = value - - def keys(self): - keys = {} - for ns in self.namespaces: - for key in ns.keys(): - keys[key] = None - return keys.keys() - - def copy(self): - namespaces = [d.copy() for d in self.namespaces] - new = self.__class__() - new.namespaces = namespaces - return new - - def read_file(self, filename, namespace=None, - load_self=True): - special_keys = ['__file__', 'load', 'include'] + self.builtins.keys() - watch_file(filename) - f = open(filename, 'rb') - content = f.read() - f.close() - if not namespace: - namespace = {} - old_values = {} - for key in special_keys: - old_values[key] = namespace.get(key) - if load_self: - for key in self: - namespace[key] = self[key] - orig = namespace.copy() - namespace['__file__'] = os.path.abspath(filename) - namespace['load'] = self.make_loader(filename, namespace) - namespace['include'] = self.make_includer(filename, namespace) - for key, builder in self.builtins.items(): - namespace[key] = builder(self, filename, namespace) - content = content.replace("\r\n","\n") - exec content in namespace - added_ns = {} - for name in namespace.keys(): - if (hasattr(__builtins__, name) - or name.startswith('_')): - continue - if (load_self - and orig.has_key(name) - and namespace[name] is orig[name]): - continue - if isinstance(namespace[name], types.ModuleType): - continue - added_ns[name] = namespace[name] - for key, value in old_values.items(): - if value is None and key in added_ns: - del added_ns[key] - elif value is not None: - added_ns[key] = value - return added_ns - - def make_loader(self, relative_to, namespace): - def load(filename): - filename = os.path.join(os.path.dirname(relative_to), - filename) - return self.read_file(filename, namespace=namespace.copy()) - return load - - def make_includer(self, relative_to, namespace): - def include(filename): - filename = os.path.join(os.path.dirname(relative_to), - filename) - self.read_file(filename, namespace=namespace, - load_self=False) - return include - - def load(self, filename, default=False): - """ - Load the `filename`, which is a Python-syntax configuration - file. If default is a positive value, do not put the values - at the top of the configuration stack (used to insert default - values that may already be overrided by a loaded - configuration). - """ - namespace = self.read_file(filename) - self.load_dict(namespace, default) - - def load_dict(self, d, default=False): - """ - Like `load`, but loads a dictionary (doesn't do any parsing). - """ - if default: - self.namespaces.insert(default, d) - else: - self.namespaces.insert(0, d) - - def load_commandline(self, *args, **kw): - """ - Loads a command line. - """ - if 'default' in kw: - default = kw['default'] - del kw['default'] - else: - default = False - options, args = parse_commandline(*args, **kw) - self.load_dict(options, default=default) - return args - load_commandline.proxy = 'parse_commandline' - - def update_sys_path(self): - update_sys_path(self.get('sys_path'), self.get('verbose')) - -if require: - def make_require(config, filename, namespace): - return require - Config.builtins['require'] = make_require - -def setup_config(filename, add_config=None, conf=None): - """ - Load the configuration with all default configs also applied, - and, apply sys_path. - - If add_config is given, this configuration (a dictionary or - filename) is loaded before the filename is loaded. - """ - conf = Config(with_default=True) - if add_config: - if isinstance(add_config, (str, unicode)): - conf.load(add_config) - else: - conf.load_dict(add_config) - conf.load(filename) - if conf.get('sys_path'): - update_sys_path(conf['sys_path'], conf['verbose']) - from paste import CONFIG - CONFIG.push_process_config(conf) - return conf - -def update_sys_path(paths, verbose): - if paths is None: - return - if isinstance(paths, (str, unicode)): - paths = [paths] - for path in paths: - path = os.path.abspath(path) - if path not in sys.path: - if verbose: - print 'Adding %s to path' % path - sys.path.insert(0, path) - -def parse_commandline(items, bool_options, aliases={}): - """ - Parses options from the command line. bool_options take no - arguments, everything else is supposed to take arguments. aliases - is a mapping of arguments to other arguments. All -'s are turned - to _, like --config-file=... becomes config_file. Any extra - arguments are returned as a list. - """ - options = {} - args = [] - while items: - if items[0] == '--': - args.extend(items[1:]) - break - elif items[0].startswith('--'): - name = items[0][2:] - value = None - if '=' in name: - name, value = name.split('=', 1) - name = aliases.get(name, name) - if (name in bool_options - or name.replace('-', '_') in bool_options): - if value is not None: - raise BadCommandLine( - "%s does not take any arguments" - % items[0]) - # For things like -vv (extra verbose) - if options.get(name): - options[name] += 1 - else: - options[name] = True - items.pop(0) - continue - if value is None: - if len(items) <= 1: - raise BadCommandLine( - "%s takes an argument, but no argument given" - % items[0]) - value = items[1] - items.pop(0) - items.pop(0) - value = convert_commandline(value) - options[name] = value - elif items[0].startswith('-'): - orig = items[0] - name = items[0][1:] - items.pop(0) - if '=' in name: - raise BadCommandLine( - "Single-character options may not have arguments (%r)" - % orig) - for i in range(len(name)): - op_name = aliases.get(name[i], name[i]) - if op_name in bool_options: - options[op_name] = True - else: - if i != len(name)-1: - raise BadCommandLine( - "-%s takes an argument, it cannot be followed " - "by other options (in %s)" - % (name[i], orig)) - if not items: - raise BadCommandLine( - "-%s takes an argument, but no argument given" - % name[i]) - value = convert_commandline(items[0]) - items.pop(0) - options[op_name] = value - break - else: - args.append(items[0]) - items.pop(0) - for key in options.keys(): - options[key.replace('-', '_')] = options[key] - return options, args - -def convert_commandline(value): - """ - Converts command-line strings to Python objects; just converting - integer strings to integers now. - """ - # @@: In most cases we should anticipate string options and parse - # them appropriately, instead of this conversion which cannot be - # context-sensitive - try: - return int(value) - except ValueError: - return value - -class DispatchingConfig(object): - - """ - This is a configuration object that can be used globally, - imported, have references held onto. The configuration may differ - by thread (or may not). - - Specific configurations are registered (and deregistered) either - for the process or for threads. - """ - - # @@: What should happen when someone tries to add this - # configuration to itself? Probably the conf should become - # resolved, and get rid of this delegation wrapper - - _constructor_lock = threading.Lock() - - def __init__(self): - self._constructor_lock.acquire() - try: - self.dispatching_id = 0 - while 1: - self._local_key = 'paste.processconfig_%i' % self.dispatching_id - if not local_dict().has_key(self._local_key): - break - self.dispatching_id += 1 - finally: - self._constructor_lock.release() - self._process_configs = [] - - def push_thread_config(self, conf): - """ - Make ``conf`` the active configuration for this thread. - Thread-local configuration always overrides process-wide - configuration. - - This should be used like:: - - conf = make_conf() - dispatching_config.push_thread_config(conf) - try: - ... do stuff ... - finally: - dispatching_config.pop_thread_config(conf) - """ - local_dict().setdefault(self._local_key, []).append(conf) - - def pop_thread_config(self, conf=None): - """ - Remove a thread-local configuration. If ``conf`` is given, - it is checked against the popped configuration and an error - is emitted if they don't match. - """ - self._pop_from(local_dict()[self._local_key], conf) - - def _pop_from(self, lst, conf): - popped = lst.pop() - if conf is not None and popped is not conf: - raise AssertionError( - "The config popped (%s) is not the same as the config " - "expected (%s)" - % (popped, conf)) - - def push_process_config(self, conf): - """ - Like push_thread_config, but applies the configuration to - the entire process. - """ - self._process_configs.append(conf) - - def pop_process_config(self, conf=None): - self._pop_from(self._process_configs, conf) - - def __getattr__(self, attr): - conf = self.current_conf() - if not conf: - raise AttributeError( - "No configuration has been registered for this process " - "or thread") - return getattr(conf, attr) - - def current_conf(self): - thread_configs = local_dict().get(self._local_key) - if thread_configs: - return thread_configs[-1] - elif self._process_configs: - return self._process_configs[-1] - else: - return None - - def __getitem__(self, key): - # I thought __getattr__ would catch this, but apparently not - conf = self.current_conf() - if not conf: - raise TypeError( - "No configuration has been registered for this process " - "or thread") - return conf[key] - -def make_bool(option): - """ - Convert a string option to a boolean, e.g. yes/no, true/false - """ - if not isinstance(option, (str, unicode)): - return option - if option.lower() in ('y', 'yes', 't', 'true', '1', 'on'): - return True - if option.lower() in ('n', 'no', 'f', 'false', '0', 'off'): - return False - raise ValueError( - "Boolean (yes/no) value expected (got: %r)" % option) - -def make_list(option): - """ - Convert a string to a list, with commas for separators. - """ - if not option: - return [] - if not isinstance(option, (str, unicode)): - if not isinstance(option, (list, tuple)): - return [option] - else: - return option - return [s.strip() for s in option.split(',')] - diff --git a/paste/server.py b/paste/server.py deleted file mode 100755 index 6e1d294..0000000 --- a/paste/server.py +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env python -""" -A generic Paste server, useable for multiple backends -""" - -help_message = """\ -usage: %(program)s [OPTIONS] servername -Runs a server with the given options. The following servers are available: - -OPTIONS --f FILENAME ---config-file=FILENAME - The configuration file (default: no configuration). --h Help ---server=NAME - Name is one of: - wsgiutils: - Runs an HTTP server. Use --port for the port (default: 8080), - and --host for the interface (default: all interfaces). - cgi: - Creates a CGI script -- outputs the script to stdout. ---publish-dir=PATH - Serves Webware servlets (or other applications) out of PATH ---debug -D - Turn on debugging (shows errors in the browser) ---verbose -v - Be verbose -""" - -import sys -import os - -# This way you can run this out of a checkout, and we'll fix up -# the path... -try: - here = os.path.normpath(os.path.abspath(__file__)) -except NameError: - here = os.path.normpath(os.path.abspath(sys.argv[0])) -try: - import paste -except ImportError: - sys.path.append(os.path.dirname(os.path.dirname(here))) - import paste -paste_path = os.path.normpath( - os.path.dirname(os.path.abspath(paste.__file__))) - -if os.path.dirname(here) != paste_path: - sys.stderr.write( - 'Warning: server.py is running out of %s, but paste is loaded ' - 'out of %s\n' % (here, paste_path)) - -from paste import reloader -from paste import CONFIG -from paste.util import plugin -from paste import pyconfig -from paste import urlmap - -reloader_environ_key = 'WSGI_RELOADER_SHOULD_RUN' - -default_config_fn = os.path.join(os.path.dirname(__file__), - 'default_config.conf') - -def load_commandline(args, extra_boolean=(), allow_reload=True): - conf = pyconfig.Config(with_default=True) - boolean_options = ['help', 'verbose', 'reload', 'debug', - 'quiet', 'no_verbose', 'list_servers', - 'daemon'] + list(extra_boolean) - conf.load_commandline( - args, bool_options=boolean_options, - aliases={'h': 'help', 'v': 'verbose', 'f': 'config_file', - 'D': 'debug', 'q': 'quiet'}) - if conf.get('no_verbose'): - conf['verbose'] = False - if not conf.get('no_server_conf') and os.path.exists('server.conf'): - load_conf(conf, 'server.conf', True) - if conf.get('config_file'): - load_conf(conf, conf['config_file'], True) - if conf['quiet']: - conf['verbose'] = False - if conf.get('help'): - return conf, 'help' - if conf.get('list_servers'): - return conf, None - server = conf.get('server') - if not server: - server_ops = plugin.find_plugins('servers', '_server') - server_ops.sort() - print "Missing --server=NAME" - print "Use --list-servers for a description of available servers" - return None, 0 - if conf['reload'] and allow_reload: - if os.environ.get(reloader_environ_key): - if conf['verbose']: - print "Running reloading file monitor" - reloader.install(conf.get('reload_interval', 1), False) - else: - try: - return restart_with_reloader(conf) - except KeyboardInterrupt: - return None, 0 - conf.update_sys_path() - app = make_app(conf) - return conf, app - -def load_commandline_options(): - """ - Fake command line options, for use with help messages - """ - from optparse import Option, OptionGroup - return [ - Option('-v', '--verbose', - help="Be verbose", - action="store_true"), - Option('--reload', - help="Activate reloader", - action="store_true"), - Option('-D', '--debug', - help="Turn on debug mode (tracebacks display in browser)", - action="store_true"), - Option('-q', '--quiet', - help="Display as little output as possible", - action="store_true"), - Option('-f', '--config-file', - help="Load the given configuration file (default: server.conf)", - metavar="FILENAME"), - Option('--no-verbose', - help="Suppress verbose (useful if configuration specifies verbose)", - action="store_true"), - Option('--list-servers', - help="List available servers", - action="store_true"), - ] - - -def run_commandline(args): - conf, app = load_commandline(args) - if conf is None: - return app - CONFIG.push_process_config(conf) - return run_server(conf, app) - -def get_server_mod(server_name): - try: - server_mod = plugin.load_plugin_module( - dir='servers', - dir_package='paste.servers', - name=server_name, - name_extension='_server') - except plugin.PluginNotFound, e: - print "Error loading server: %s" % e - print "Available servers:" - server_ops = plugin.find_plugins('servers', '_server') - server_ops.sort() - print ', '.join(server_ops) - sys.exit(1) - return server_mod - -def run_server(conf, app): - server_mod = get_server_mod(conf['server']) - if conf['verbose']: - print "Starting server." - if conf.get('profile_server'): - return run_server_profiled(conf, app, server_mod) - try: - server_mod.serve(conf, app) - except KeyboardInterrupt: - # This is an okay error - pass - return 0 - -def run_server_profiled(conf, app, server_mod): - import hotshot - try: - prof_filename = conf.get('profile_server_log', 'hotshot_server.log') - if conf['verbose']: - print 'Logging profiling to %s' % prof_filename - prof = hotshot.Profile(prof_filename) - try: - prof.runcall(server_mod.serve, conf, app) - finally: - prof.close() - except KeyboardInterrupt: - # This is an okay error - pass - return 0 - -def load_conf(conf, filename, default=False): - if isinstance(filename, (list, tuple)): - for fn in filename: - load_conf(conf, fn, default=default) - return - if os.path.exists(filename): - if conf['verbose']: - print 'Loading configuration from %s' % filename - conf.load(filename, default=default) - -def help(): - program = sys.argv[0] - return help_message % {'program': program} - -def make_app_from_filename(filename): - conf = pyconfig.setup_config(filename) - return make_app(conf) - -def make_app(conf): - framework_name = conf.get('framework', 'default') - framework = plugin.load_plugin_module( - os.path.join(os.path.dirname(__file__), 'frameworks'), - 'paste.frameworks', - framework_name, - '_framework') - app = framework.build_application(conf) - mapper = conf.get('system_urlmap') - if mapper: - mapper[''] = app - return mapper - else: - return app - -def make_proxy(conf, filename, namespace): - mapper = conf.get('system_urlmap') - if mapper is None: - namespace['system_urlmap'] = mapper = urlmap.URLMap() - current_url = conf.get('base_paste_url') - if current_url is None: - namespace['base_paste_url'] = current_url = '' - return urlmap.PathProxyURLMap( - mapper, current_url, os.path.dirname(filename), - make_app_from_filename) - -pyconfig.Config.builtins['urlmap'] = make_proxy - -def restart_with_reloader(conf): - if conf['verbose']: - print "Restarting process with reloading on" - while 1: - args = [sys.executable] + sys.argv - new_environ = os.environ.copy() - new_environ[reloader_environ_key] = 'true' - exit_code = os.spawnve(os.P_WAIT, sys.executable, - args, new_environ) - if exit_code != 3: - return None, exit_code - if conf['verbose']: - print '-'*20, 'Restarting', '-'*20 - -if __name__ == '__main__': - sys.exit(run_commandline(sys.argv[1:])) diff --git a/paste/tests/pyconfig_data/context.py b/paste/tests/pyconfig_data/context.py deleted file mode 100644 index 73fa626..0000000 --- a/paste/tests/pyconfig_data/context.py +++ /dev/null @@ -1,8 +0,0 @@ -def simplehook(): - return 'calc' -simplehook.config_hook = True - -def complexhook(context): - return context -complexhook.config_hook = True - diff --git a/paste/tests/pyconfig_data/deriv.conf b/paste/tests/pyconfig_data/deriv.conf deleted file mode 100644 index c7cdf3c..0000000 --- a/paste/tests/pyconfig_data/deriv.conf +++ /dev/null @@ -1,3 +0,0 @@ -import os - -test1 = test1 + '+another' diff --git a/paste/tests/pyconfig_data/loader.conf b/paste/tests/pyconfig_data/loader.conf deleted file mode 100644 index a8b0e55..0000000 --- a/paste/tests/pyconfig_data/loader.conf +++ /dev/null @@ -1,5 +0,0 @@ -value1 = 'value' -lst = ['a'] -loaded = load('loader_loaded.conf') - -include('loader_included.conf') diff --git a/paste/tests/pyconfig_data/loader_included.conf b/paste/tests/pyconfig_data/loader_included.conf deleted file mode 100644 index 230a3e1..0000000 --- a/paste/tests/pyconfig_data/loader_included.conf +++ /dev/null @@ -1,2 +0,0 @@ -new_value = 10 -value1 += 'more' diff --git a/paste/tests/pyconfig_data/loader_loaded.conf b/paste/tests/pyconfig_data/loader_loaded.conf deleted file mode 100644 index fcf44e7..0000000 --- a/paste/tests/pyconfig_data/loader_loaded.conf +++ /dev/null @@ -1,2 +0,0 @@ -value1 = value1 + ' a test' -lst.append('b') diff --git a/paste/tests/pyconfig_data/nest1.conf b/paste/tests/pyconfig_data/nest1.conf deleted file mode 100644 index 4eb06c6..0000000 --- a/paste/tests/pyconfig_data/nest1.conf +++ /dev/null @@ -1,3 +0,0 @@ -a = 1 -b = 'shadow' - diff --git a/paste/tests/pyconfig_data/nest2.conf b/paste/tests/pyconfig_data/nest2.conf deleted file mode 100644 index c70b217..0000000 --- a/paste/tests/pyconfig_data/nest2.conf +++ /dev/null @@ -1,2 +0,0 @@ -b = 2 -c = 3 diff --git a/paste/tests/pyconfig_data/one.py b/paste/tests/pyconfig_data/one.py deleted file mode 100644 index e03cf8b..0000000 --- a/paste/tests/pyconfig_data/one.py +++ /dev/null @@ -1,2 +0,0 @@ -name1 = 'n1' -name2 = 'n2' diff --git a/paste/tests/test_pyconfig.py b/paste/tests/test_pyconfig.py deleted file mode 100644 index 9c1af73..0000000 --- a/paste/tests/test_pyconfig.py +++ /dev/null @@ -1,58 +0,0 @@ -import os -from paste import pyconfig -from py.test import raises -from paste import reloader - -def path(name): - return os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'pyconfig_data', name) - -def test_load(): - conf = pyconfig.load(path('one.py')) - assert conf['name1'] == 'n1' - assert conf['name2'] == "n2" - raises(KeyError, "conf['name3']") - -def test_nest(): - conf = pyconfig.load(path('nest1.conf')) - conf.load(path('nest2.conf')) - assert conf['a'] == 1 - assert conf['b'] == 2 - assert conf['c'] == 3 - -def test_derivative(): - conf = pyconfig.Config() - conf.load_dict({'test1': 'a'}) - assert conf['test1'] == 'a' - conf.load(path('deriv.conf')) - assert conf['test1'] == 'a+another' - conf = pyconfig.Config() - conf.load_dict({'test1': 'b'}) - conf.load(path('deriv.conf')) - assert conf['test1'] == 'b+another' - assert not conf.has_key('os') - -def test_command(): - conf = pyconfig.load(path('one.py')) - extra = conf.load_commandline( - ['-h', '--host', 'localhost', '--port=8080', 'arg1', '-f', 'arg2'], - bool_options=['help', 'verbose'], - aliases={'f': 'config_file', 'h': 'help', 'v': 'verbose'}) - assert extra == ['arg1'] - assert conf['name1'] == 'n1' - assert conf['host'] == 'localhost' - assert conf['port'] == 8080 - assert conf['config_file'] == 'arg2' - raises(KeyError, "conf['h']") - raises(KeyError, "conf['f']") - -def test_load(): - conf = pyconfig.load(path('loader.conf')) - print conf - assert conf['value1'] == 'valuemore' - assert conf['new_value'] == 10 - assert conf['lst'] == ['a', 'b'] - assert conf['loaded']['value1'] == 'value a test' - extra = reloader.Monitor.global_extra_files - for fn in 'loader.conf', 'loader_loaded.conf', 'loader_included.conf': - assert path(fn) in extra |