summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Bicking <ian@ianbicking.org>2005-08-22 21:20:19 +0000
committerIan Bicking <ian@ianbicking.org>2005-08-22 21:20:19 +0000
commit9eda7b8dd739a698e7db1448315d32436b8e5041 (patch)
tree3e037dd06df830384cd5515a84ffcdbc83e79eef
parent2bc2372e7a4bdbcdbccf416b3305a09416108b85 (diff)
downloadpaste-git-9eda7b8dd739a698e7db1448315d32436b8e5041.tar.gz
Removed configuration and other parts redundant with paste.deploy
-rw-r--r--paste/app_setup.py646
-rw-r--r--paste/configmiddleware.py46
-rw-r--r--paste/makeapp.py43
-rw-r--r--paste/pyconfig.py439
-rwxr-xr-xpaste/server.py248
-rw-r--r--paste/tests/pyconfig_data/context.py8
-rw-r--r--paste/tests/pyconfig_data/deriv.conf3
-rw-r--r--paste/tests/pyconfig_data/loader.conf5
-rw-r--r--paste/tests/pyconfig_data/loader_included.conf2
-rw-r--r--paste/tests/pyconfig_data/loader_loaded.conf2
-rw-r--r--paste/tests/pyconfig_data/nest1.conf3
-rw-r--r--paste/tests/pyconfig_data/nest2.conf2
-rw-r--r--paste/tests/pyconfig_data/one.py2
-rw-r--r--paste/tests/test_pyconfig.py58
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