PK q 5l??paste/__init__.pyimport pkg_resources pkg_resources.declare_namespace('paste') PKSq 5˚2paste/__init__.pyc; *'Dc@sdkZeiddS(Nspaste(s pkg_resourcessdeclare_namespace(s pkg_resources((s,build/bdist.linux-i686/egg/paste/__init__.pys?s PK q 5b@W#W#paste/script/templates.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import sys import os import inspect import copydir import command class Template(object): # Subclasses must define: # _template_dir (or template_dir()) # summary # Variables this template uses (mostly for documentation now) # a list of instances of var() vars = [] # Eggs that should be added as plugins: egg_plugins = [] # Templates that must be applied first: required_templates = [] # Use Cheetah for substituting templates: use_cheetah = False # If true, then read all the templates to find the variables: read_vars_from_templates = False def __init__(self, name): self.name = name self._read_vars = None def module_dir(self): """ Returns the module directory of this template. """ mod = sys.modules[self.__class__.__module__] return os.path.dirname(mod.__file__) def template_dir(self): assert self._template_dir is not None, ( "Template %r didn't set _template_dir" % self) return os.path.join(self.module_dir(), self._template_dir) def run(self, command, output_dir, vars): self.pre(command, output_dir, vars) self.write_files(command, output_dir, vars) self.post(command, output_dir, vars) def check_vars(self, vars, cmd): expect_vars = self.read_vars(cmd) if not expect_vars: # Assume that variables aren't defined return vars converted_vars = {} unused_vars = vars.copy() errors = [] for var in expect_vars: if var.name not in unused_vars: if cmd.interactive: prompt = 'Enter %s' % var.full_description() response = cmd.challenge(prompt, var.default) converted_vars[var.name] = response elif var.default is command.NoDefault: errors.append('Required variable missing: %s' % var.full_description()) else: converted_vars[var.name] = var.default else: converted_vars[var.name] = unused_vars.pop(var.name) if errors: raise command.BadCommand( 'Errors in variables:\n%s' % '\n'.join(errors)) converted_vars.update(unused_vars) vars.update(converted_vars) return converted_vars def read_vars(self, command=None): if self._read_vars is not None: return self._read_vars assert (not self.read_vars_from_templates or self.use_cheetah), ( "You can only read variables from templates if using Cheetah") if not self.read_vars_from_templates: self._read_vars = self.vars return self.vars vars = self.vars[:] var_names = [var.name for var in self.vars] read_vars = find_args_in_dir( self.template_dir(), verbose=command and command.verbose > 1).items() read_vars.sort() for var_name, var in read_vars: if var_name not in var_names: vars.append(var) self._read_vars = vars return vars def write_files(self, command, output_dir, vars): template_dir = self.template_dir() if not os.path.exists(output_dir): print "Creating directory %s" % output_dir if not command.simulate: # Don't let copydir create this top-level directory, # since copydir will svn add it sometimes: os.makedirs(output_dir) copydir.copy_dir(template_dir, output_dir, vars, verbosity=command.verbose, simulate=command.options.simulate, interactive=command.interactive, overwrite=command.options.overwrite, indent=1, use_cheetah=self.use_cheetah) def print_vars(self, indent=0): vars = self.read_vars() var.print_vars(vars) def pre(self, command, output_dir, vars): """ Called before template is applied. """ pass def post(self, command, output_dir, vars): """ Called after template is applied. """ pass class NoDefault: pass class var(object): def __init__(self, name, description, default=''): self.name = name self.description = description self.default = default def full_description(self): if self.description: return '%s (%s)' % (self.name, self.description) else: return self.name def print_vars(cls, vars, indent=0): max_name = max([len(v.name) for v in vars]) for var in vars: if var.description: print '%s%s%s %s' % ( ' '*indent, var.name, ' '*(max_name-len(var.name)), var.description) else: print ' %s' % var.name if var.default is not command.NoDefault: print ' default: %r' % var.default print print_vars = classmethod(print_vars) class BasicPackage(Template): _template_dir = 'templates/basic_package' summary = "A basic setuptools-enabled package" vars = [ var('version', 'Version (like 0.1)'), var('description', 'One-line description of the package'), var('long_description', 'Multi-line description (in reST)'), var('keywords', 'Space-separated keywords/tags'), var('author', 'Author name'), var('author_email', 'Author email'), var('url', 'URL of homepage'), var('license_name', 'License name'), var('zip_safe', 'True/False: if the package can be distributed as a .zip file', default=False), ] _skip_variables = ['VFN', 'currentTime', 'self', 'VFFSL', 'dummyTrans', 'getmtime', 'trans'] def find_args_in_template(template): if isinstance(template, (str, unicode)): # Treat as filename: import Cheetah.Template template = Cheetah.Template.Template(file=template) if not hasattr(template, 'body'): # Don't know... return None method = template.body args, varargs, varkw, defaults = inspect.getargspec(method) defaults=list(defaults or []) vars = [] while args: if len(args) == len(defaults): default = defaults.pop(0) else: default = command.NoDefault arg = args.pop(0) if arg in _skip_variables: continue # @@: No way to get description yet vars.append( var(arg, description=None, default=default)) return vars def find_args_in_dir(dir, verbose=False): all_vars = {} for fn in os.listdir(dir): if fn.startswith('.') or fn == 'CVS' or fn == '_darcs': continue full = os.path.join(dir, fn) if os.path.isdir(full): inner_vars = find_args_in_dir(full) elif full.endswith('_tmpl'): inner_vars = {} found = find_args_in_template(full) if found is None: # Couldn't read variables if verbose: print 'Template %s has no parseable variables' % full continue for var in found: inner_vars[var.name] = var else: # Not a template, don't read it continue if verbose: print 'Found variable(s) %s in Template %s' % ( ', '.join(inner_vars.keys()), full) for var_name, var in inner_vars.items(): # Easy case: if var_name not in all_vars: all_vars[var_name] = var continue # Emit warnings if the variables don't match well: cur_var = all_vars[var_name] if not cur_var.description: cur_var.description = var.description elif (cur_var.description and var.description and var.description != cur_var.description): print >> sys.stderr, ( "Variable descriptions do not match: %s: %s and %s" % (var_name, cur_var.description, var.description)) if (cur_var.default is not command.NoDefault and var.default is not command.NoDefault and cur_var.default != var.default): print >> sys.stderr, ( "Variable defaults do not match: %s: %r and %r" % (var_name, cur_var.default, var.default)) return all_vars PK q 5eŭpaste/script/help.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php from command import Command, get_commands from command import parser as base_parser class HelpCommand(Command): summary = "Display help" usage = '[COMMAND]' max_args = 1 parser = Command.standard_parser() def command(self): if not self.args: self.generic_help() return name = self.args[0] commands = get_commands() if name not in commands: print 'No such command: %s' % name self.generic_help() return command = commands[name].load() runner = command(name) runner.run(['-h']) def generic_help(self): base_parser.print_help() print commands_grouped = {} commands = get_commands() longest = max([len(n) for n in commands.keys()]) for name, command in commands.items(): try: command = command.load() except Exception, e: print 'Cannot load command %s: %s' % (name, e) continue if getattr(command, 'hidden', False): continue commands_grouped.setdefault( command.group_name, []).append((name, command)) commands_grouped = commands_grouped.items() commands_grouped.sort() print 'Commands:' for group, commands in commands_grouped: if group: print group + ':' commands.sort() for name, command in commands: print ' %s %s' % (self.pad(name, length=longest), command.summary) #if command.description: # print self.indent_block(command.description, 4) print PK q 5wpaste/script/grep.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import os import py_compile import marshal import inspect import re from command import Command import pluginlib class GrepCommand(Command): summary = 'Search project for symbol' usage = 'SYMBOL' max_args = 1 min_args = 1 bad_names = ['.svn', 'CVS', '_darcs'] parser = Command.standard_parser() parser.add_option( '-x', '--exclude-module', metavar="module.name", dest="exclude_modules", action="append", help="Don't search the given module") parser.add_option( '-t', '--add-type', metavar=".ext", dest="add_types", action="append", help="Search the given type of files") def command(self): self.exclude_modules = self.options.exclude_modules or [] self.add_types = self.options.add_types or [] self.symbol = self.args[0] self.basedir = os.path.dirname( pluginlib.find_egg_info_dir(os.getcwd())) if self.verbose: print "Searching in %s" % self.basedir self.total_files = 0 self.search_dir(self.basedir) if self.verbose > 1: print "Searched %i files" % self.total_files def search_dir(self, dir): names = os.listdir(dir) names.sort() dirs = [] for name in names: full = os.path.join(dir, name) if name in self.bad_names: continue if os.path.isdir(full): # Breadth-first; we'll do this later... dirs.append(full) continue for t in self.add_types: if name.lower().endswith(t.lower()): self.search_text(full) if not name.endswith('.py'): continue self.search_file(full) for dir in dirs: self.search_dir(dir) def search_file(self, filename): self.total_files += 1 if not filename.endswith('.py'): self.search_text(filename) return pyc = filename[:-2]+'pyc' if not os.path.exists(pyc): py_compile.compile(filename) if not os.path.exists(pyc): # Invalid syntax... self.search_text(filename, as_module=True) return f = open(pyc, 'rb') # .pyc Header: f.read(8) code = marshal.load(f) f.close() self.search_code(code, filename, []) def search_code(self, code, filename, path): if code.co_name != "?": path = path + [code.co_name] else: path = path sym = self.symbol if sym in code.co_varnames: self.found(code, filename, path) elif sym in code.co_names: self.found(code, filename, path) for const in code.co_consts: if const == sym: self.found(code, filename, path) if inspect.iscode(const): if not const.co_filename == filename: continue self.search_code(const, filename, path) def search_text(self, filename, as_module=False): f = open(filename, 'rb') lineno = 0 any = False for line in f: lineno += 1 if line.find(self.symbol) != -1: if not any: any = True if as_module: print '%s (unloadable)' % self.module_name(filename) else: print self.relative_name(filename) print ' %3i %s' % (lineno, line) if not self.verbose: break f.close() def found(self, code, filename, path): print self.display(filename, path) self.find_occurance(code) def find_occurance(self, code): f = open(code.co_filename, 'rb') lineno = 0 for index, line in zip(xrange(code.co_firstlineno), f): lineno += 1 pass lines = [] first_indent = None for line in f: lineno += 1 if line.find(self.symbol) != -1: this_indent = len(re.match(r'^[ \t]*', line).group(0)) if first_indent is None: first_indent = this_indent else: if this_indent < first_indent: break print ' %3i %s' % (lineno, line[first_indent:].rstrip()) if not self.verbose: break def module_name(self, filename): assert filename, startswith(self.basedir) mod = filename[len(self.basedir):].strip('/').strip(os.path.sep) mod = os.path.splitext(mod)[0] mod = mod.replace(os.path.sep, '.').replace('/', '.') return mod def relative_name(self, filename): assert filename, startswith(self.basedir) name = filename[len(self.basedir):].strip('/').strip(os.path.sep) return name def display(self, filename, path): parts = '.'.join(path) if parts: parts = ':' + parts return self.module_name(filename) + parts PK q 5"Wvpaste/script/cgi_server.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import os import sys def paste_run_cgi(wsgi_app, global_conf): run_with_cgi(wsgi_app) stdout = sys.__stdout__ # Taken from the WSGI spec: def run_with_cgi(application): environ = dict(os.environ.items()) environ['wsgi.input'] = sys.stdin environ['wsgi.errors'] = sys.stderr environ['wsgi.version'] = (1,0) environ['wsgi.multithread'] = False environ['wsgi.multiprocess'] = True environ['wsgi.run_once'] = True if environ.get('HTTPS','off') in ('on','1'): environ['wsgi.url_scheme'] = 'https' else: environ['wsgi.url_scheme'] = 'http' headers_set = [] headers_sent = [] def write(data): if not headers_set: raise AssertionError("write() before start_response()") elif not headers_sent: # Before the first output, send the stored headers status, response_headers = headers_sent[:] = headers_set stdout.write('Status: %s\r\n' % status) for header in response_headers: stdout.write('%s: %s\r\n' % header) stdout.write('\r\n') stdout.write(data) stdout.flush() def start_response(status,response_headers,exc_info=None): if exc_info: try: if headers_sent: # Re-raise original exception if headers sent raise exc_info[0], exc_info[1], exc_info[2] finally: exc_info = None # avoid dangling circular ref elif headers_set: raise AssertionError("Headers already set!") headers_set[:] = [status,response_headers] return write result = application(environ, start_response) try: for data in result: if data: # don't send headers until body appears write(data) if not headers_sent: write('') # send headers now if body was empty finally: if hasattr(result,'close'): result.close() PK q 5  paste/script/flup_server.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php from paste.deploy.converters import aslist, asbool from paste.script.serve import ensure_port_cleanup def run_ajp_thread(wsgi_app, global_conf, scriptName='', host='localhost', port='8009', allowedServers='127.0.0.1'): import flup.server.ajp addr = (host, int(port)) ensure_port_cleanup([addr]) s = flup.server.ajp.WSGIServer( wsgi_app, scriptName=scriptName, bindAddress=addr, allowedServers=aslist(allowedServers), ) s.run() def run_ajp_fork(wsgi_app, global_conf, scriptName='', host='localhost', port='8009', allowedServers='127.0.0.1'): import flup.server.ajp_fork addr = (host, int(port)) ensure_port_cleanup([addr]) s = flup.server.ajp_fork.WSGIServer( wsgi_app, scriptName=scriptName, bindAddress=addr, allowedServers=aslist(allowedServers), ) s.run() def run_fcgi_thread(wsgi_app, global_conf, host=None, port=None, socket=None, multiplexed=False): import flup.server.fcgi if socket: assert host is None and port is None sock = socket else: assert host is not None and port is not None sock = (host, int(port)) ensure_port_cleanup([sock]) s = flup.server.fcgi.WSGIServer( wsgi_app, bindAddress=sock, multiplexed=asbool(multiplexed)) s.run() def run_fcgi_fork(wsgi_app, global_conf, host=None, port=None, socket=None, multiplexed=False): import flup.server.fcgi_fork if socket: assert host is None and port is None sock = socket else: assert host is not None and port is not None sock = (host, int(port)) ensure_port_cleanup([sock]) s = flup.server.fcgi_fork.WSGIServer( wsgi_app, bindAddress=sock, multiplexed=asbool(multiplexed)) s.run() def run_scgi_thread(wsgi_app, global_conf, scriptName='', host='localhost', port='4000', allowedServers='127.0.0.1'): import flup.server.scgi addr = (host, int(port)) ensure_port_cleanup([addr]) s = flup.server.scgi.WSGIServer( wsgi_app, scriptName=scriptName, bindAddress=addr, allowedServers=aslist(allowedServers), ) s.run() def run_scgi_fork(wsgi_app, global_conf, scriptName='', host='localhost', port='4000', allowedServers='127.0.0.1'): import flup.server.scgi_fork addr = (host, int(port)) ensure_port_cleanup([addr]) s = flup.server.scgi_fork.WSGIServer( wsgi_app, scriptName=scriptName, bindAddress=addr, allowedServers=aslist(allowedServers), ) s.run() PK q 5KK#paste/script/twisted_web2_server.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php # @@: THIS IS INCOMPLETE! from paste.deploy.converters import asbool def conn_string(host, port, **params): s = 'tcp:%s' % port if host: s += ':interface=%s' % host for name, value in params.items(): s += ':%s=%s' % (name, value) return s def run_twisted(wsgi_app, global_conf, use_http=True, host='127.0.0.1', port='8080', use_https=False, https_host=None, https_port='443', https_private_key=None, use_scgi=False, scgi_host='127.0.0.1', scgi_port=4000): host = host or None import twisted.web2.wsgi import twisted.web2.log import twisted.web2.http import twisted.web2.server import twisted.application.service import twisted.application.strports wsgi_resource = twisted.web2.wsgi.WSGIResource(wsgi_app) res = twisted.web2.log.LogWrapperResource(wsgi_resource) twisted.web2.log.DefaultCommonAccessLoggingObserver().start() site = twisted.web2.server.Site(res) # @@: I don't get this: application = twisted.application.service.Application("paster") if asbool(use_http): s = twisted.application.strports.service( conn_string(host, port), twisted.web2.http.HTTPFactory(site)) s.setServiceParent(application) if asbool(use_https): s = twisted.application.strports.service( conn_string(https_host, https_port, privateKey=https_private_key), twisted.web2.http.HTTPFactory(site)) s.setServiceParent(application) if asbool(use_scgi): import twisted.web2.scgichannel s = twisted.application.strports.service( conn_string(scgi_host, scgi_port), twisted.web2.scgichannel.SCGIFactory(site)) s.setServiceParent(application) # @@: Now how the heck do I start it? PK q 5trx!paste/script/default_sysconfig.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ This module contains default sysconfig settings. The command object is inserted into this module as a global variable ``paste_command``, and can be used inside functions. """ def add_custom_options(parser): """ This method can modify the ``parser`` object (which is an ``optparse.OptionParser`` instance). This can be used to add new options to the command. """ pass def default_config_filename(installer): """ This function can return a default filename or directory for the configuration file, if none was explicitly given. Return None to mean no preference. The first non-None returning value will be used. Pay attention to ``installer.expect_config_directory`` here, and to ``installer.default_config_filename``. """ return installer.default_config_filename def install_variables(installer): """ Returns a dictionary of variables for use later in the process (e.g., filling a configuration file). These are combined from all sysconfig files. """ return {} def post_setup_hook(installer, config_file): """ This is called at the very end of ``paster setup-app``. You might use it to register an application globally. """ pass PK q 5I|paste/script/entrypoints.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import textwrap import os import pkg_resources from command import Command, BadCommand import fnmatch import re import traceback from cStringIO import StringIO class EntryPointCommand(Command): usage = "ENTRY_POINT" summary = "Show information about entry points" description = """\ Shows information about one or many entry points (you can use wildcards for entry point names). Entry points are used for Egg plugins, and are named resources -- like an application, template plugin, or other resource. Entry points have a [group] which defines what kind of object they describe, and inside groups each entry point is named. """ max_args = 1 parser = Command.standard_parser(verbose=False) parser.add_option('--list', '-l', dest='list_entry_points', action='store_true', help='List all the kinds of entry points on the system') parser.add_option('--egg', '-e', dest='show_egg', help="Show all the entry points for the given Egg") parser.add_option('--regex', dest='use_regex', action='store_true', help="Make pattern match as regular expression, not just a wildcard pattern") def command(self): if self.options.list_entry_points: return self.list_entry_points() if self.options.show_egg: return self.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]) 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) def print_entry_points_by_group(self, group): env = pkg_resources.Environment() project_names = list(env) project_names.sort() for project_name in project_names: dists = list(env[project_name]) assert dists dist = dists[0] entries = dist.get_entry_map(group).values() if not entries: continue if len(dists) > 1: print '%s (+ %i older versions)' % ( dist, len(dists)-1) else: print '%s' % dist entries.sort(lambda a, b: cmp(a.name, b.name)) longest_name = max([len(entry.name) for entry in entries]) for entry in entries: print ' %s%s = %s' % ( entry.name, ' '*(longest_name-len(entry.name)), entry.module_name) desc = self.get_entry_point_description(entry, group) if desc and desc.description: print self.wrap(desc.description, indent=4) def wrap(self, text, indent=0): text = textwrap.dedent(text) width = int(os.environ.get('COLUMNS', 70)) - indent lines = [ ' '*indent+line for line in textwrap.wrap(text, width)] return '\n'.join(lines) def get_pattern(self, s): if not s: return None if self.options.use_regex: return re.compile(s) else: return re.compile(fnmatch.translate(s), re.I) def list_entry_points(self): pattern = self.get_pattern(self.args and self.args[0]) groups = self.get_groups_by_pattern(pattern) print '%i entry point groups found:' % len(groups) for group in groups: desc = self.get_group_description(group) print '[%s]' % group if desc: print self.wrap(desc.description, indent=2) def get_groups_by_pattern(self, pattern): env = pkg_resources.Environment() eps = {} for project_name in env: for dist in env[project_name]: for name in pkg_resources.get_entry_map(dist): if pattern and not pattern.search(name): continue if (not pattern and name.startswith('paste.description.')): continue eps[name] = None eps = eps.keys() eps.sort() return eps def get_group_description(self, group): for entry in pkg_resources.iter_entry_points('paste.entry_point_description'): if entry.name == group: return entry.load() return None def get_entry_point_description(self, ep, group): try: return self._safe_get_entry_point_description(ep, group) except Exception, e: out = StringIO() traceback.print_exc(file=out) return ErrorDescription(e, out.getvalue()) def _safe_get_entry_point_description(self, ep, group): ep.dist.activate() meta_group = 'paste.description.'+group meta = ep.dist.get_entry_info(meta_group, ep.name) if not meta: generic = list(pkg_resources.iter_entry_points( meta_group, 'generic')) if not generic: return super_generic(ep.load()) # @@: Error if len(generic) > 1? print generic obj = generic[0].load() desc = obj(ep, group) else: desc = meta.load() return desc class EntryPointDescription(object): def __init__(self, group): self.group = group # Should define: # * description class MetaEntryPointDescription(object): description = """ This is an entry point that describes other entry points. """ class SuperGeneric(object): def __init__(self, doc_object): self.doc_object = doc_object self.description = self.doc_object.__doc__ def super_generic(obj): desc = SuperGeneric(obj) if not desc.description: return None return desc class ErrorDescription(object): def __init__(self, exc, tb): self.exc = exc self.tb = '\n'.join(tb) self.description = 'Error loading: %s' % exc PK q 56 g0g0paste/script/filemaker.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import os import glob from paste.script import pluginlib, copydir from paste.script.command import BadCommand try: import subprocess except ImportError: from paste.script.util import subprocess24 as subprocess class FileOp(object): """ Enhance the ease of file copying/processing from a package into a target project """ def __init__(self, simulate=False, verbose=True, interactive=True, source_dir=None, template_vars={}): """ Initialize our File operation helper object source_dir Should refer to the directory within the package that contains the templates to be used for the other copy operations. It is assumed that packages will keep all their templates under a hierarchy starting here. This should be an absolute path passed in, for example:: FileOp(source_dir=os.path.dirname(__file__) + '/templates') """ self.simulate=simulate self.verbose = verbose self.interactive = interactive self.template_vars = template_vars self.source_dir = source_dir def copy_file(self, template, dest, filename=None, add_py=True, package=True): """ Copy a file from the source location to somewhere in the destination. template The filename underneath self.source_dir to copy/process dest The destination directory in the project relative to where this command is being run filename What to name the file in the target project, use the same name as the template if not provided add_py Add a .py extension to all files copied package Whether or not this file is part of a Python package, and any directories created should contain a __init__.py file as well. """ if not filename: filename = template.split('/')[0] if filename.endswith('_tmpl'): filename = filename[:-5] base_package, cdir = self.find_dir(dest, package) self.template_vars['base_package'] = base_package content = self.load_content(base_package, cdir, filename, template) if add_py: # @@: Why is it a default to add a .py extension? filename = '%s.py' % filename dest = os.path.join(cdir, filename) self.ensure_file(dest, content, package) def copy_dir(self, template_dir, dest, destname=None, package=True): """ Copy a directory recursively, processing any files within it that need to be processed (end in _tmpl). template_dir Directory under self.source_dir to copy/process dest Destination directory into which this directory will be copied to. destname Use this name instead of the original template_dir name for creating the directory package This directory will be a Python package and needs to have a __init__.py file. """ # @@: This should actually be implemented pass def load_content(self, base_package, base, name, template): blank = os.path.join(base, name + '.py') if not os.path.exists(blank): blank = os.path.join(self.source_dir, template) f = open(blank, 'r') content = f.read() f.close() if blank.endswith('_tmpl'): content = copydir.substitute_content(content, self.template_vars, filename=blank) return content def find_dir(self, dirname, package=False): egg_info = pluginlib.find_egg_info_dir(os.getcwd()) # @@: Should give error about egg_info when top_level.txt missing f = open(os.path.join(egg_info, 'top_level.txt')) packages = [l.strip() for l in f.readlines() if l.strip() and not l.strip().startswith('#')] f.close() # @@: This doesn't support deeper servlet directories, # or packages not kept at the top level. base = os.path.dirname(egg_info) possible = [] for pkg in packages: d = os.path.join(base, pkg, dirname) if os.path.exists(d): possible.append((pkg, d)) if not possible: self.ensure_dir(os.path.join(base, pkg, dirname), package=package) return self.find_dir(dirname) if len(possible) > 1: raise BadCommand( "Multiple %s dirs found (%s)" % (dirname, possible)) return possible[0] def parse_path_name_args(self, name): """ Given the name, assume that the first argument is a path/filename combination. Return the name and dir of this. If the name ends with '.py' that will be erased. Examples: comments -> comments, '' admin/comments -> comments, 'admin' h/ab/fred -> fred, 'h/ab' """ if name.endswith('.py'): # Erase extensions name = name[:-3] if '.' in name: # Turn into directory name: name = name.replace('.', os.path.sep) if '/' != os.path.sep: name = name.replace('/', os.path.sep) parts = name.split(os.path.sep) name = parts[-1] if not parts[:-1]: dir = '' elif len(parts[:-1]) == 1: dir = parts[0] else: dir = os.path.join(*parts[:-1]) return name, dir def ensure_dir(self, dir, svn_add=True, package=False): """ Ensure that the directory exists, creating it if necessary. Respects verbosity and simulation. Adds directory to subversion if ``.svn/`` directory exists in parent, and directory was created. package If package is True, any directories created will contain a __init__.py file. """ dir = dir.rstrip(os.sep) if not dir: # we either reached the parent-most directory, or we got # a relative directory # @@: Should we make sure we resolve relative directories # first? Though presumably the current directory always # exists. return if not os.path.exists(dir): self.ensure_dir(os.path.dirname(dir), svn_add=svn_add, package=package) if self.verbose: print 'Creating %s' % self.shorten(dir) if not self.simulate: os.mkdir(dir) if (svn_add and os.path.exists(os.path.join(os.path.dirname(dir), '.svn'))): self.run_command('svn', 'add', dir) if package: initfile = os.path.join(dir, '__init__.py') f = open(initfile, 'wb') f.write("#\n") f.close() print 'Creating %s' % self.shorten(initfile) if (svn_add and os.path.exists(os.path.join(os.path.dirname(dir), '.svn'))): self.run_command('svn', 'add', initfile) else: if self.verbose > 1: print "Directory already exists: %s" % self.shorten(dir) def ensure_file(self, filename, content, svn_add=True, package=False): """ Ensure a file named ``filename`` exists with the given content. If ``--interactive`` has been enabled, this will ask the user what to do if a file exists with different content. """ global difflib self.ensure_dir(os.path.dirname(filename), svn_add=svn_add, package=package) if not os.path.exists(filename): if self.verbose: print 'Creating %s' % filename if not self.simulate: f = open(filename, 'wb') f.write(content) f.close() if svn_add and os.path.exists(os.path.join(os.path.dirname(filename), '.svn')): self.run_command('svn', 'add', filename) return f = open(filename, 'rb') old_content = f.read() f.close() if content == old_content: if self.verbose > 1: print 'File %s matches expected content' % filename return if not self.options.overwrite: print 'Warning: file %s does not match expected content' % filename if difflib is None: import difflib diff = difflib.context_diff( content.splitlines(), old_content.splitlines(), 'expected ' + filename, filename) print '\n'.join(diff) if self.interactive: while 1: s = raw_input( 'Overwrite file with new content? [y/N] ').strip().lower() if not s: s = 'n' if s.startswith('y'): break if s.startswith('n'): return print 'Unknown response; Y or N please' else: return if self.verbose: print 'Overwriting %s with new content' % filename if not self.simulate: f = open(filename, 'wb') f.write(content) f.close() def shorten(self, fn, *paths): """ Return a shorted form of the filename (relative to the current directory), typically for displaying in messages. If ``*paths`` are present, then use os.path.join to create the full filename before shortening. """ if paths: fn = os.path.join(fn, *paths) if fn.startswith(os.getcwd()): return fn[len(os.getcwd()):].lstrip(os.path.sep) else: return fn def run_command(self, cmd, *args, **kw): """ Runs the command, respecting verbosity and simulation. Returns stdout, or None if simulating. """ cwd = popdefault(kw, 'cwd', os.getcwd()) capture_stderr = popdefault(kw, 'capture_stderr', False) expect_returncode = popdefault(kw, 'expect_returncode', False) assert not kw, ("Arguments not expected: %s" % kw) if capture_stderr: stderr_pipe = subprocess.STDOUT else: stderr_pipe = subprocess.PIPE try: proc = subprocess.Popen([cmd] + list(args), cwd=cwd, stderr=stderr_pipe, stdout=subprocess.PIPE) except OSError, e: if e.errno != 2: # File not found raise raise OSError( "The expected executable %s was not found (%s)" % (cmd, e)) if self.verbose: print 'Running %s %s' % (cmd, ' '.join(args)) if self.simulate: return None stdout, stderr = proc.communicate() if proc.returncode and not expect_returncode: if not self.verbose: print 'Running %s %s' % (cmd, ' '.join(args)) print 'Error (exit code: %s)' % proc.returncode if stderr: print stderr raise OSError("Error executing command %s" % cmd) if self.verbose > 2: if stderr: print 'Command error output:' print stderr if stdout: print 'Command output:' print stdout return stdout def popdefault(dict, name, default=None): if name not in dict: return default else: v = dict[name] del dict[name] return v PK q 5U6paste/script/__init__.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php # PK q 5n2gZgZpaste/script/appinstall.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ Provides the two commands for preparing an application: ``prepare-app`` and ``setup-app`` """ import os import new from cStringIO import StringIO from paste.script.command import Command, BadCommand, run as run_command import paste.script.templates from paste.script import copydir import pkg_resources from Cheetah.Template import Template from ConfigParser import ConfigParser from paste.util import import_string from paste.deploy import appconfig from paste.script.util import uuid from paste.script.util import secret class AbstractInstallCommand(Command): default_interactive = 1 default_sysconfigs = [ (False, '/etc/paste/sysconfig.py'), (False, '/usr/local/etc/paste/sysconfig.py'), (True, 'paste.script.default_sysconfig'), ] if os.environ.get('HOME'): default_sysconfigs.insert( 0, (False, os.path.join(os.environ['HOME'], '.paste', 'config', 'sysconfig.py'))) if os.environ.get('PASTE_SYSCONFIG'): default_sysconfigs.insert( 0, (False, os.environ['PASTE_SYSCONFIG'])) def run(self, args): # This is overridden so we can parse sys-config before we pass # it to optparse self.sysconfigs = self.default_sysconfigs new_args = [] while args: if args[0].startswith('--no-default-sysconfig'): self.sysconfigs = [] args.pop(0) continue if args[0].startswith('--sysconfig='): self.sysconfigs.insert( 0, (True, args.pop(0)[len('--sysconfig='):])) continue if args[0] == '--sysconfig': args.pop(0) if not args: raise BadCommand, ( "You gave --sysconfig as the last argument without " "a value") self.sysconfigs.insert(0, (True, args.pop(0))) continue new_args.append(args.pop(0)) self.load_sysconfigs() return super(AbstractInstallCommand, self).run(new_args) #@classmethod def standard_parser(cls, **kw): parser = super(AbstractInstallCommand, cls).standard_parser(**kw) parser.add_option('--sysconfig', action="append", dest="sysconfigs", help="System configuration file") parser.add_option('--no-default-sysconfig', action='store_true', dest='no_default_sysconfig', help="Don't load the default sysconfig files") parser.add_option( '--easy-install', action='append', dest='easy_install_op', metavar='OP', help='An option to add if invoking easy_install (like --easy-install=exclude-scripts)') parser.add_option( '--no-install', action='store_true', dest='no_install', help="Don't try to install the package (it must already be installed)") parser.add_option( '-f', '--find-links', action='append', dest='easy_install_find_links', metavar='URL', help='Passed through to easy_install') return parser standard_parser = classmethod(standard_parser) ######################################## ## Sysconfig Handling ######################################## def load_sysconfigs(self): configs = self.sysconfigs[:] configs.reverse() self.sysconfig_modules = [] for index, (explicit, name) in enumerate(configs): # @@: At some point I'd like to give the specialized # modules some access to the values in earlier modules, # e.g., to specialize those values or functions. That's # why these modules are loaded backwards. if name.endswith('.py'): if not os.path.exists(name): if explicit: raise BadCommand, ( "sysconfig file %s does not exist" % name) else: continue globs = {} execfile(name, globs) mod = new.module('__sysconfig_%i__' % index) for name, value in globs.items(): setattr(mod, name, value) mod.__file__ = name else: try: mod = import_string.simple_import(name) except ImportError, e: if explicit: raise else: continue mod.paste_command = self self.sysconfig_modules.insert(0, mod) # @@: I'd really prefer to clone the parser here somehow, # not to modify it in place parser = self.parser self.call_sysconfig_functions('add_custom_options', parser) def get_sysconfig_option(self, name, default=None): """ Return the value of the given option in the first sysconfig module in which it is found, or ``default`` (None) if not found in any. """ for mod in self.sysconfig_modules: if hasattr(mod, name): return getattr(mod, name) return default def get_sysconfig_options(self, name): """ Return the option value for the given name in all the sysconfig modules in which is is found (``[]`` if none). """ return [getattr(mod, name) for mod in self.sysconfig_modules if hasattr(mod, name)] def call_sysconfig_function(self, name, *args, **kw): """ Call the specified function in the first sysconfig module it is defined in. ``NameError`` if no function is found. """ val = self.get_sysconfig_option(name) if val is None: raise NameError, ( "Method %s not found in any sysconfig module" % name) return val(*args, **kw) def call_sysconfig_functions(self, name, *args, **kw): """ Call all the named functions in the sysconfig modules, returning a list of the return values. """ return [method(*args, **kw) for method in self.get_sysconfig_options(name)] def sysconfig_install_vars(self, installer): """ Return the folded results of calling the ``install_variables()`` functions. """ result = {} all_vars = self.call_sysconfig_functions( 'install_variables', installer) all_vars.reverse() for vardict in all_vars: result.update(vardict) return result ######################################## ## Distributions ######################################## def get_distribution(self, req): """ This gets a distribution object, and installs the distribution if required. """ try: dist = pkg_resources.get_distribution(req) if self.verbose: print 'Distribution already installed:' print ' ', dist, 'from', dist.location return dist except pkg_resources.DistributionNotFound: if self.options.no_install: print "Because --no-install was given, we won't try to install the package %s" % req raise options = ['-v', '-m'] for op in self.options.easy_install_op or []: if not op.startswith('-'): op = '--'+op options.append(op) for op in self.options.easy_install_find_links or []: options.append('--find-links=%s' % op) if self.simulate: raise BadCommand( "Must install %s, but in simulation mode" % req) print "Must install %s" % req from setuptools.command import easy_install from setuptools import setup setup(script_args=['-q', 'easy_install'] + options + [req]) return pkg_resources.get_distribution(req) def get_installer(self, distro, ep_group, ep_name): installer_class = distro.load_entry_point( 'paste.app_install', ep_name) installer = installer_class( distro, ep_group, ep_name) return installer class MakeConfigCommand(AbstractInstallCommand): default_verbosity = 1 max_args = None min_args = 1 summary = "Install a package and create a fresh config file/directory" usage = "PACKAGE_NAME [CONFIG_FILE] [VAR=VALUE]" description = """\ Note: this is an experimental command, and it will probably change in several ways by the next release. make-config is part of a two-phase installation process (the second phase is setup-app). make-config installs the package (using easy_install) and asks it to create a bare configuration file or directory (possibly filling in defaults from the extra variables you give). """ parser = AbstractInstallCommand.standard_parser( simulate=True, quiet=True, no_interactive=True) parser.add_option('--info', action="store_true", dest="show_info", help="Show information on the package (after installing it), but do not write a config.") parser.add_option('--name', action='store', dest='ep_name', help='The name of the application contained in the distribution (default "main")') parser.add_option('--entry-group', action='store', dest='ep_group', default='paste.app_factory', help='The entry point group to install (i.e., the kind of application; default paste.app_factory') parser.add_option('--edit', action='store_true', dest='edit', help='Edit the configuration file after generating it (using $EDITOR)') parser.add_option('--setup', action='store_true', dest='run_setup', help='Run setup-app immediately after generating (and possibly editing) the configuration file') def command(self): self.requirement = self.args[0] if '#' in self.requirement: if self.options.ep_name is not None: raise BadCommand( "You may not give both --name and a requirement with " "#name") self.requirement, self.options.ep_name = self.requirement.split('#', 1) if not self.options.ep_name: self.options.ep_name = 'main' self.distro = self.get_distribution(self.requirement) self.installer = self.get_installer( self.distro, self.options.ep_group, self.options.ep_name) if self.options.show_info: if len(self.args) > 1: raise BadCommand( "With --info you can only give one argument") return self.show_info() if len(self.args) < 2: # See if sysconfig can give us a default filename options = filter(None, self.call_sysconfig_functions( 'default_config_filename', self.installer)) if not options: raise BadCommand( "You must give a configuration filename") self.config_file = options[0] else: self.config_file = self.args[1] self.check_config_file() self.project_name = self.distro.project_name self.vars = self.sysconfig_install_vars(self.installer) self.vars.update(self.parse_vars(self.args[2:])) self.vars['project_name'] = self.project_name self.vars['requirement'] = self.requirement self.vars['ep_name'] = self.options.ep_name self.vars['ep_group'] = self.options.ep_group self.vars.setdefault('app_name', self.project_name.lower()) self.vars.setdefault('app_instance_uuid', uuid.uuid4()) self.vars.setdefault('app_instance_secret', secret.secret_string()) if self.verbose > 1: print_vars = self.vars.items() print_vars.sort() print 'Variables for installation:' for name, value in print_vars: print ' %s: %r' % (name, value) self.installer.write_config(self, self.config_file, self.vars) edit_success = True if self.options.edit: edit_success = self.run_editor() setup_configs = self.installer.editable_config_files(self.config_file) # @@: We'll just assume the first file in the list is the one # that works with setup-app... setup_config = setup_configs[0] if self.options.run_setup: if not edit_success: print 'Config-file editing was not successful.' if self.ask('Run setup-app anyway?', default=False): self.run_setup(setup_config) else: self.run_setup(setup_config) else: filenames = self.installer.editable_config_files(self.config_file) assert not isinstance(filenames, basestring), ( "editable_config_files returned a string, not a list") if not filenames and filenames is not None: print 'No config files need editing' else: print 'Now you should edit the config files' if filenames: for fn in filenames: print ' %s' % fn def show_info(self): text = self.installer.description(None) print text def check_config_file(self): if self.installer.expect_config_directory is None: return fn = self.config_file if self.installer.expect_config_directory: if os.path.splitext(fn)[1]: raise BadCommand( "The CONFIG_FILE argument %r looks like a filename, " "and a directory name is expected" % fn) else: if fn.endswith('/') or not os.path.splitext(fn): raise BadCommand( "The CONFIG_FILE argument %r looks like a directory " "name and a filename is expected" % fn) def run_setup(self, filename): run_command(['setup-app', filename]) def run_editor(self): filenames = self.installer.editable_config_files(self.config_file) if filenames is None: print 'Warning: the config file is not known (--edit ignored)' return False if not filenames: print 'Warning: no config files need editing (--edit ignored)' return True if len(filenames) > 1: print 'Warning: there is more than one editable config file (--edit ignored)' return False if not os.environ.get('EDITOR'): print 'Error: you must set $EDITOR if using --edit' return False if self.verbose: print '%s %s' % (os.environ['EDITOR'], filenames[0]) retval = os.system('$EDITOR %s' % filenames[0]) if retval: print 'Warning: editor %s returned with error code %i' % ( os.environ['EDITOR'], retval) return False return True class SetupCommand(AbstractInstallCommand): default_verbosity = 1 max_args = 1 min_args = 1 summary = "Setup an application, given a config file" usage = "CONFIG_FILE" description = """\ Note: this is an experimental command, and it will probably change in several ways by the next release. Setup an application according to its configuration file. This is the second part of a two-phase web application installation process (the first phase is prepare-app). The setup process may consist of things like creating directories and setting up databases. """ parser = AbstractInstallCommand.standard_parser( simulate=True, quiet=True, interactive=True) parser.add_option('--name', action='store', dest='section_name', default=None, help='The name of the section to set up (default: app:main)') def command(self): config_spec = self.args[0] section = self.options.section_name if section is None: if '#' in config_spec: config_spec, section = config_spec.split('#', 1) else: section = 'main' if not ':' in section: plain_section = section section = 'app:'+section else: plain_section = section.split(':', 1)[0] if not config_spec.startswith('config:'): config_spec = 'config:' + config_spec if plain_section != 'main': config_spec += '#' + plain_section config_file = config_spec[len('config:'):].split('#', 1)[0] config_file = os.path.join(os.getcwd(), config_file) conf = appconfig(config_spec, relative_to=os.getcwd()) ep_name = conf.context.entry_point_name ep_group = conf.context.protocol dist = conf.context.distribution installer = self.get_installer(dist, ep_group, ep_name) installer.setup_config( self, config_file, section, self.sysconfig_install_vars(installer)) self.call_sysconfig_functions( 'post_setup_hook', installer, config_file) class Installer(object): """ Abstract base class for installers, and also a generic installer that will run off config files in the .egg-info directory of a distribution. Packages that simply refer to this installer can provide a file ``*.egg-info/paste_deploy_config.ini_tmpl`` that will be interpreted by Cheetah. They can also provide ``websetup`` modules with a ``setup_app(command, conf, vars)`` (or the now-deprecated ``setup_config(command, filename, section, vars)``) function, that will be called. In the future other functions or configuration files may be called. """ # If this is true, then try to detect filename-looking config_file # values, and reject them. Conversely, if false try to detect # directory-looking values and reject them. None means don't # check. expect_config_directory = False # Set this to give a default config filename when none is # specified: default_config_filename = None def __init__(self, dist, ep_group, ep_name): self.dist = dist self.ep_group = ep_group self.ep_name = ep_name def description(self, config): return 'An application' def write_config(self, command, filename, vars): """ Writes the content to the filename (directory or single file). You should use the ``command`` object, which respects things like simulation and interactive. ``vars`` is a dictionary of user-provided variables. """ command.ensure_file(filename, self.config_content(command, vars)) def editable_config_files(self, filename): """ Return a list of filenames; this is primarily used when the filename is treated as a directory and several configuration files are created. The default implementation returns the file itself. Return None if you don't know what files should be edited on installation. """ if not self.expect_config_directory: return [filename] else: return None def config_content(self, command, vars): """ Called by ``self.write_config``, this returns the text content for the config file, given the provided variables. The default implementation reads ``Package.egg-info/paste_deploy_config.ini_tmpl`` and fills it with the variables. """ meta_name = 'paste_deploy_config.ini_tmpl' if not self.dist.has_metadata(meta_name): if command.verbose: print 'No %s found' % meta_name return self.simple_config(vars) tmpl = Template(self.dist.get_metadata(meta_name), searchList=[vars]) return copydir.careful_sub( tmpl, vars, meta_name) def simple_config(self, vars): """ Return a very simple configuration file for this application. """ if self.ep_name != 'main': ep_name = '#'+self.ep_name else: ep_name = '' return ('[app:main]\n' 'use = egg:%s%s\n' % (self.dist.project_name, ep_name)) def setup_config(self, command, filename, section, vars): """ Called to setup an application, given its configuration file/directory. The default implementation calls ``package.websetup.setup_config(command, filename, section, vars)`` or ``package.websetup.setup_app(command, config, vars)`` With ``setup_app`` the ``config`` object is a dictionary with the extra attributes ``global_conf``, ``local_conf`` and ``filename`` """ for line in self.dist.get_metadata_lines('top_level.txt'): line = line.strip() if not line or line.startswith('#'): continue mod_name = line + '.websetup' try: mod = import_string.import_module(mod_name) except ImportError: if command.verbose > 1: print 'No %s module found for setup' % mod_name continue if command.verbose: print 'Running setup_config() from %s' % mod_name if hasattr(mod, 'setup_app'): self._call_setup_app( mod.setup_app, command, filename, section, vars) elif hasattr(mod, 'setup_config'): mod.setup_config(command, filename, section, vars) else: print 'No setup_app() or setup_config() function in %s (%s)' % ( mod.__name__, mod.__file__) def _call_setup_app(self, func, command, filename, section, vars): filename = os.path.abspath(filename) if ':' in section: section = section.split(':', 1)[1] conf = 'config:%s#%s' % (filename, section) conf = appconfig(conf) conf.filename = filename func(command, conf, vars) PK q 5.am.. paste/script/wsgiutils_server.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php from paste.script.serve import ensure_port_cleanup from paste.translogger import TransLogger def run_server(wsgi_app, global_conf, host='localhost', port=8080): from wsgiutils import wsgiServer import logging logged_app = TransLogger(wsgi_app) port = int(port) # For some reason this is problematic on this server: ensure_port_cleanup([(host, port)], maxtries=2, sleeptime=0.5) app_map = {'': logged_app} server = wsgiServer.WSGIServer((host, port), app_map) logged_app.logger.info('Starting HTTP server on http://%s:%s', host, port) server.serve_forever() PK q 56opaste/script/bool_optparse.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ A subclass of ``optparse.OptionParser`` that allows boolean long options (like ``--verbose``) to also take arguments (like ``--verbose=true``). Arguments *must* use ``=``. """ import optparse try: _ = optparse._ except AttributeError: from gettext import gettext as _ class BoolOptionParser(optparse.OptionParser): def _process_long_opt(self, rargs, values): arg = rargs.pop(0) # Value explicitly attached to arg? Pretend it's the next # argument. if "=" in arg: (opt, next_arg) = arg.split("=", 1) rargs.insert(0, next_arg) had_explicit_value = True else: opt = arg had_explicit_value = False opt = self._match_long_opt(opt) option = self._long_opt[opt] if option.takes_value(): nargs = option.nargs if len(rargs) < nargs: if nargs == 1: self.error(_("%s option requires an argument") % opt) else: self.error(_("%s option requires %d arguments") % (opt, nargs)) elif nargs == 1: value = rargs.pop(0) else: value = tuple(rargs[0:nargs]) del rargs[0:nargs] elif had_explicit_value: value = rargs[0].lower().strip() del rargs[0:1] if value in ('true', 'yes', 'on', '1', 'y', 't'): value = None elif value in ('false', 'no', 'off', '0', 'n', 'f'): # Don't process return else: self.error(_('%s option takes a boolean value only (true/false)') % opt) else: value = None option.process(opt, value, values, self) PK q 5e̢++paste/script/copydir.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import os import sys if sys.version_info < (2, 4): from paste.script.util import string24 as string else: import string import cgi import urllib import re Cheetah = None try: import subprocess except ImportError: from paste.script.util import subprocess24 as subprocess import inspect def copy_dir(source, dest, vars, verbosity, simulate, indent=0, use_cheetah=False, sub_vars=True, interactive=False, svn_add=True, overwrite=True): names = os.listdir(source) names.sort() pad = ' '*(indent*2) if not os.path.exists(dest): if verbosity >= 1: print '%sCreating %s/' % (pad, dest) if not simulate: svn_makedirs(dest, svn_add=svn_add, verbosity=verbosity, pad=pad) elif verbosity >= 2: print '%sDirectory %s exists' % (pad, dest) for name in names: full = os.path.join(source, name) if name.startswith('.'): if verbosity >= 2: print '%sSkipping hidden file %s' % (pad, full) continue if name.endswith('~') or name.endswith('.bak'): if verbosity >= 2: print '%sSkipping backup file %s' % (pad, full) continue if name.endswith('.pyc'): if verbosity >= 2: print '%sSkipping .pyc file %s' % (pad, full) continue if name in ('CVS', '_darcs'): if verbosity >= 2: print '%sSkipping version control directory %s' % (pad, full) continue if sub_vars: dest_full = os.path.join(dest, substitute_filename(name, vars)) sub_file = False if dest_full.endswith('_tmpl'): dest_full = dest_full[:-5] sub_file = sub_vars if os.path.isdir(full): if verbosity: print '%sRecursing into %s' % (pad, os.path.basename(full)) copy_dir(full, dest_full, vars, verbosity, simulate, indent=indent+1, use_cheetah=use_cheetah, sub_vars=sub_vars, interactive=interactive, svn_add=svn_add) continue f = open(full, 'rb') content = f.read() f.close() if sub_file: content = substitute_content(content, vars, filename=full, use_cheetah=use_cheetah) already_exists = os.path.exists(dest_full) if already_exists: f = open(dest_full, 'rb') old_content = f.read() f.close() if old_content == content: if verbosity: print '%s%s already exists (same content)' % (pad, dest_full) continue if interactive: if not query_interactive( full, dest_full, content, old_content, simulate=simulate): continue elif not overwrite: continue if verbosity: print '%sCopying %s to %s' % (pad, os.path.basename(full), dest_full) if not simulate: f = open(dest_full, 'wb') f.write(content) f.close() if svn_add and not already_exists: if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(dest_full)), '.svn')): if verbosity > 1: print '%s.svn/ does not exist; cannot add file' % pad else: cmd = ['svn', 'add', dest_full] if verbosity > 1: print '%sRunning: %s' % (pad, ' '.join(cmd)) if not simulate: # @@: Should proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) stdout, stderr = proc.communicate() if verbosity > 1 and stdout: print 'Script output:' print stdout elif svn_add and already_exists and verbosity > 1: print '%sFile already exists (not doing svn add)' % pad # Overridden on user's request: all_answer = None def query_interactive(src_fn, dest_fn, src_content, dest_content, simulate): global all_answer from difflib import unified_diff, context_diff u_diff = list(unified_diff( dest_content.splitlines(), src_content.splitlines(), dest_fn, src_fn)) c_diff = list(context_diff( dest_content.splitlines(), src_content.splitlines(), dest_fn, src_fn)) added = len([l for l in u_diff if l.startswith('+') and not l.startswith('+++')]) removed = len([l for l in u_diff if l.startswith('-') and not l.startswith('---')]) if added > removed: msg = '; %i lines added' % (added-removed) elif removed > added: msg = '; %i lines removed' % (removed-added) else: msg = '' print 'Replace %i bytes with %i bytes (%i/%i lines changed%s)' % ( len(dest_content), len(src_content), removed, len(dest_content.splitlines()), msg) prompt = 'Overwrite %s [y/n/d/B/?] ' % dest_fn while 1: if all_answer is None: response = raw_input(prompt).strip().lower() else: response = all_answer if not response or response[0] == 'b': import shutil new_dest_fn = dest_fn + '.bak' n = 0 while os.path.exists(new_dest_fn): n += 1 new_dest_fn = dest_fn + '.bak' + str(n) print 'Backing up %s to %s' % (dest_fn, new_dest_fn) if not simulate: shutil.copyfile(dest_fn, new_dest_fn) return True elif response.startswith('all '): rest = response[4:].strip() if not rest or rest[0] not in ('y', 'n', 'b'): print query_usage continue response = all_answer = rest[0] if response[0] == 'y': return True elif response[0] == 'n': return False elif response == 'dc': print '\n'.join(c_diff) elif response[0] == 'd': print '\n'.join(u_diff) else: print query_usage query_usage = """\ Responses: Y(es): Overwrite the file with the new content. N(o): Do not overwrite the file. D(iff): Show a unified diff of the proposed changes (dc=context diff) B(ackup): Save the current file contents to a .bak file (and overwrite) Use "all Y/N/B" to use Y/N/B for answer to all future questions """ def svn_makedirs(dir, svn_add, verbosity, pad): parent = os.path.dirname(os.path.abspath(dir)) if not os.path.exists(parent): svn_makedirs(parent, svn_add, verbosity, pad) os.mkdir(dir) if not svn_add: return if not os.path.exists(os.path.join(parent, '.svn')): if verbosity > 1: print '%s.svn/ does not exist; cannot add directory' % pad return cmd = ['svn', 'add', dir] if verbosity > 1: print '%sRunning: %s' % (pad, ' '.join(cmd)) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) stdout, stderr = proc.communicate() if verbosity > 1 and stdout: print 'Script output:' print stdout 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, filename='', use_cheetah=False): global Cheetah if not use_cheetah: v = standard_vars.copy() v.update(vars) tmpl = LaxTemplate(content) try: return tmpl.substitute(TypeMapper(v)) except Exception, e: _add_except(e, ' in file %s' % filename) raise if Cheetah is None: import Cheetah.Template tmpl = Cheetah.Template.Template(source=content, searchList=[vars]) return careful_sub(tmpl, vars, filename) def careful_sub(cheetah_template, vars, filename): """ Substitutes the template with the variables, using the .body() method if it exists. It assumes that the variables were also passed in via the searchList. """ if not hasattr(cheetah_template, 'body'): return sub_catcher(filename, vars, str, cheetah_template) body = cheetah_template.body args, varargs, varkw, defaults = inspect.getargspec(body) call_vars = {} for arg in args: if arg in vars: call_vars[arg] = vars[arg] return sub_catcher(filename, vars, body, **call_vars) def sub_catcher(filename, vars, func, *args, **kw): """ Run a substitution, returning the value. If an error occurs, show the filename. If the error is a NameError, show the variables. """ try: return func(*args, **kw) except Exception, e: print 'Error in file %s:' % filename if isinstance(e, NameError): items = vars.items() items.sort() for name, value in items: print '%s = %r' % (name, value) raise def html_quote(s): if s is None: return '' return cgi.escape(str(s), 1) def url_quote(s): if s is None: return '' return urllib.quote(str(s)) def test(conf, true_cond, false_cond=None): if conf: return true_cond else: return false_cond def _add_except(exc, info): if not hasattr(exc, 'args') or exc.args is None: return args = list(exc.args) args[0] += ' ' + info exc.args = tuple(args) return standard_vars = { 'nothing': None, 'html_quote': html_quote, 'url_quote': url_quote, 'empty': '""', 'test': test, 'repr': repr, 'str': str, 'bool': bool, } class TypeMapper(dict): def __getitem__(self, item): options = item.split('|') for op in options[:-1]: try: value = eval_with_catch(op, dict(self)) break except (NameError, KeyError): pass else: value = eval(options[-1], dict(self)) if value is None: return '' else: return str(value) def eval_with_catch(expr, vars): try: return eval(expr, vars) except Exception, e: _add_except(e, 'in expression %r' % expr) raise class LaxTemplate(string.Template): # This change of pattern allows for anything in braces, but # only identifiers outside of braces: pattern = re.compile(r""" \$(?: (?P\$) | # Escape sequence of two delimiters (?P[_a-z][_a-z0-9]*) | # delimiter and a Python identifier {(?P.*?)} | # delimiter and a braced identifier (?P) # Other ill-formed delimiter exprs ) """, re.VERBOSE | re.IGNORECASE) PK q 5\hddpaste/script/command.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import pkg_resources import sys import optparse import bool_optparse import os import re import textwrap import pluginlib import ConfigParser try: import subprocess except ImportError: from paste.script.util import subprocess24 as subprocess difflib = None class BadCommand(Exception): def __init__(self, message, exit_code=2): self.message = message self.exit_code = exit_code Exception.__init__(self, message) class NoDefault: pass dist = pkg_resources.get_distribution('PasteScript') python_version = sys.version.splitlines()[0].strip() parser = optparse.OptionParser(add_help_option=False, version='%s from %s (python %s)' % (dist, dist.location, python_version), usage='%prog [paster_options] COMMAND [command_options]') parser.add_option( '--plugin', action='append', dest='plugins', help="Add a plugin to the list of commands (plugins are Egg specs; will also require() the Egg)") parser.add_option( '-h', '--help', action='store_true', dest='do_help', help="Show this help message") parser.disable_interspersed_args() # @@: Add an option to run this in another Python interpreter system_plugins = [] def run(args=None): if (not args and len(sys.argv) >= 2 and os.environ.get('_') and sys.argv[0] != os.environ['_'] and os.environ['_'] == sys.argv[1]): # probably it's an exe execution args = ['exe', os.environ['_']] + sys.argv[2:] if args is None: args = sys.argv[1:] options, args = parser.parse_args(args) options.base_parser = parser system_plugins.extend(options.plugins or []) commands = get_commands() if options.do_help: args = ['help'] + args if not args: print 'Usage: %s COMMAND' % sys.argv[0] args = ['help'] command_name = args[0] if command_name not in commands: command = NotFoundCommand else: command = commands[command_name].load() invoke(command, command_name, options, args[1:]) def parse_exe_file(config): import shlex p = ConfigParser.RawConfigParser() p.read([config]) command_name = 'exe' options = [] if p.has_option('exe', 'command'): command_name = p.get('exe', 'command') if p.has_option('exe', 'options'): options = shlex.split(p.get('exe', 'options')) if p.has_option('exe', 'sys.path'): paths = shlex.split(p.get('exe', 'sys.path')) paths = [os.path.abspath(os.path.join(os.path.dirname(config), p)) for p in paths] for path in paths: pkg_resources.working_set.add_entry(path) sys.path.insert(0, path) args = [command_name, config] + options return args def get_commands(): plugins = system_plugins[:] egg_info_dir = pluginlib.find_egg_info_dir(os.getcwd()) if egg_info_dir: plugins.append(os.path.splitext(os.path.basename(egg_info_dir))[0]) base_dir = os.path.dirname(egg_info_dir) if base_dir not in sys.path: sys.path.insert(0, base_dir) pkg_resources.working_set.add_entry(base_dir) plugins = pluginlib.resolve_plugins(plugins) commands = pluginlib.load_commands_from_plugins(plugins) commands.update(pluginlib.load_global_commands()) return commands def invoke(command, command_name, options, args): try: runner = command(command_name) exit_code = runner.run(args) except BadCommand, e: print e.message exit_code = e.exit_code sys.exit(exit_code) class Command(object): def __init__(self, name): self.command_name = name max_args = None max_args_error = 'You must provide no more than %(max_args)s arguments' min_args = None min_args_error = 'You must provide at least %(min_args)s arguments' required_args = None # If this command takes a configuration file, set this to 1 or -1 # Then if invoked through #! the config file will be put into the positional # arguments -- at the beginning with 1, at the end with -1 takes_config_file = None # Grouped in help messages by this: group_name = '' required_args = () description = None usage = '' hidden = False # This is the default verbosity level; --quiet subtracts, # --verbose adds: default_verbosity = 0 # This is the default interactive state: default_interactive = 0 return_code = 0 BadCommand = BadCommand # Must define: # parser # summary # command() def run(self, args): self.parse_args(args) # Setup defaults: for name, default in [('verbose', 0), ('quiet', 0), ('interactive', False), ('overwrite', False)]: if not hasattr(self.options, name): setattr(self.options, name, default) if getattr(self.options, 'simulate', False): self.options.verbose = max(self.options.verbose, 1) self.interactive = self.default_interactive if getattr(self.options, 'interactive', False): self.interactive += self.options.interactive if getattr(self.options, 'no_interactive', False): self.interactive = False self.verbose = self.default_verbosity self.verbose += self.options.verbose self.verbose -= self.options.quiet self.simulate = getattr(self.options, 'simulate', False) # For #! situations: if (os.environ.get('PASTE_CONFIG_FILE') and self.takes_config_file is not None): take = self.takes_config_file filename = os.environ.get('PASTE_CONFIG_FILE') if take == 1: self.args.insert(0, filename) elif take == -1: self.args.append(filename) else: assert 0, ( "Value takes_config_file must be None, 1, or -1 (not %r)" % take) if (os.environ.get('PASTE_DEFAULT_QUIET')): self.verbose = 0 # Validate: if self.min_args is not None and len(self.args) < self.min_args: raise BadCommand( 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: raise BadCommand( 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): raise BadCommand( 'You must provide the option %s' % option_name) result = self.command() if result is None: return self.return_code else: return result def parse_args(self, args): if self.usage: usage = ' '+self.usage else: usage = '' self.parser.usage = "%%prog [options]%s\n%s" % ( usage, self.summary) self.parser.prog = '%s %s' % (sys.argv[0], self.command_name) if self.description: desc = self.description desc = textwrap.dedent(desc) self.parser.description = desc self.options, self.args = self.parser.parse_args(args) ######################################## ## Utility methods ######################################## def here(cls): mod = sys.modules[cls.__module__] return os.path.dirname(mod.__file__) here = classmethod(here) def ask(self, prompt, safe=False, default=True): """ Prompt the user. Default can be true, false, ``'careful'`` or ``'none'``. If ``'none'`` then the user must enter y/n. If ``'careful'`` then the user must enter yes/no (long form). If the interactive option is over two (``-ii``) then ``safe`` will be used as a default. This option should be the do-nothing option. """ # @@: Should careful be a separate argument? if self.options.interactive >= 2: default = safe if default == 'careful': prompt += ' [yes/no]?' elif default == 'none': prompt += ' [y/n]?' elif default: prompt += ' [Y/n]? ' else: prompt += ' [y/N]? ' while 1: response = raw_input(prompt).strip().lower() if not response: if default in ('careful', 'none'): print 'Please enter yes or no' continue return default if default == 'careful': if response in ('yes', 'no'): return response == 'yes' print 'Please enter "yes" or "no"' continue if response[0].lower() in ('y', 'n'): return response[0].lower() == 'y' print 'Y or N please' def challenge(self, prompt, default=NoDefault): """ Prompt the user for a variable. """ if default is not NoDefault: prompt += ' [%r]' % default prompt += ': ' while 1: response = raw_input(prompt).strip() if not response: if default is not NoDefault: return default else: continue else: return response def pad(self, s, length, dir='left'): if len(s) >= length: return s if dir == 'left': return s + ' '*(length-len(s)) else: return ' '*(length-len(s)) + s def standard_parser(cls, verbose=True, interactive=False, no_interactive=False, simulate=False, quiet=False, overwrite=False): """ Create a standard ``OptionParser`` instance. Typically used like:: class MyCommand(Command): parser = Command.standard_parser() Subclasses may redefine ``standard_parser``, so use the nearest superclass's class method. """ parser = bool_optparse.BoolOptionParser() if verbose: parser.add_option('-v', '--verbose', action='count', dest='verbose', default=0) if quiet: parser.add_option('-q', '--quiet', action='count', dest='quiet', default=0) if no_interactive: parser.add_option('--no-interactive', action="count", dest="no_interactive", default=0) if interactive: parser.add_option('-i', '--interactive', action='count', dest='interactive', default=0) if simulate: parser.add_option('-n', '--simulate', action='store_true', dest='simulate', default=False) if overwrite: parser.add_option('-f', '--overwrite', dest="overwrite", action="store_true", help="Overwrite files (warnings will be emitted for non-matching files otherwise)") return parser standard_parser = classmethod(standard_parser) def shorten(self, fn, *paths): """ Return a shorted form of the filename (relative to the current directory), typically for displaying in messages. If ``*paths`` are present, then use os.path.join to create the full filename before shortening. """ if paths: fn = os.path.join(fn, *paths) if fn.startswith(os.getcwd()): return fn[len(os.getcwd()):].lstrip(os.path.sep) else: return fn def ensure_dir(self, dir, svn_add=True): """ Ensure that the directory exists, creating it if necessary. Respects verbosity and simulation. Adds directory to subversion if ``.svn/`` directory exists in parent, and directory was created. """ dir = dir.rstrip(os.sep) if not dir: # we either reached the parent-most directory, or we got # a relative directory # @@: Should we make sure we resolve relative directories # first? Though presumably the current directory always # exists. return if not os.path.exists(dir): self.ensure_dir(os.path.dirname(dir)) if self.verbose: print 'Creating %s' % self.shorten(dir) if not self.simulate: os.mkdir(dir) if (svn_add and os.path.exists(os.path.join(os.path.dirname(dir), '.svn'))): self.run_command('svn', 'add', dir) else: if self.verbose > 1: print "Directory already exists: %s" % self.shorten(dir) def ensure_file(self, filename, content, svn_add=True): """ Ensure a file named ``filename`` exists with the given content. If ``--interactive`` has been enabled, this will ask the user what to do if a file exists with different content. """ global difflib assert content is not None, ( "You cannot pass a content of None") self.ensure_dir(os.path.dirname(filename), svn_add=svn_add) if not os.path.exists(filename): if self.verbose: print 'Creating %s' % filename if not self.simulate: f = open(filename, 'wb') f.write(content) f.close() if svn_add and os.path.exists(os.path.join(os.path.dirname(filename), '.svn')): self.run_command('svn', 'add', filename) return f = open(filename, 'rb') old_content = f.read() f.close() if content == old_content: if self.verbose > 1: print 'File %s matches expected content' % filename return if not self.options.overwrite: print 'Warning: file %s does not match expected content' % filename if difflib is None: import difflib diff = difflib.context_diff( content.splitlines(), old_content.splitlines(), 'expected ' + filename, filename) print '\n'.join(diff) if self.interactive: while 1: s = raw_input( 'Overwrite file with new content? [y/N] ').strip().lower() if not s: s = 'n' if s.startswith('y'): break if s.startswith('n'): return print 'Unknown response; Y or N please' else: return if self.verbose: print 'Overwriting %s with new content' % filename if not self.simulate: f = open(filename, 'wb') f.write(content) f.close() def insert_into_file(self, filename, marker_name, text, indent=False): """ Inserts ``text`` into the file, right after the given marker. Markers look like: ``-*- [:]? -*-``, and the text will go on the immediately following line. Raises ``ValueError`` if the marker is not found. If ``indent`` is true, then the text will be indented at the same level as the marker. """ if not text.endswith('\n'): raise ValueError( "The text must end with a newline: %r" % text) if not os.path.exists(filename) and self.simulate: # If we are doing a simulation, it's expected that some # files won't exist... if self.verbose: print 'Would (if not simulating) insert text into %s' % ( self.shorten(filename)) return f = open(filename) lines = f.readlines() f.close() regex = re.compile(r'-\*-\s+%s:?\s+-\*-' % re.escape(marker_name), re.I) for i in range(len(lines)): if regex.search(lines[i]): # Found it! if lines[i:] and len(lines[i:]) > 1 and lines[i+1].strip() == text.strip(): # Already have it! print 'Warning: line already found in %s (not inserting' % filename print ' %s' % lines[i] return if indent: text = text.lstrip() match = re.search(r'^[ \t]*', lines[i]) text = match.group(0) + text lines[i+1:i+1] = [text] break else: errstr = ( "Marker '-*- %s -*-' not found in %s" % (marker_name, filename)) if 1 or self.simulate: # @@: being permissive right now print 'Warning: %s' % errstr else: raise ValueError(errstr) if self.verbose: print 'Updating %s' % self.shorten(filename) if not self.simulate: f = open(filename, 'w') f.write(''.join(lines)) f.close() def run_command(self, cmd, *args, **kw): """ Runs the command, respecting verbosity and simulation. Returns stdout, or None if simulating. Keyword arguments: cwd: the current working directory to run the command in capture_stderr: if true, then both stdout and stderr will be returned expect_returncode: if true, then don't fail if the return code is not 0 force_no_simulate: if true, run the command even if --simulate """ cwd = popdefault(kw, 'cwd', os.getcwd()) capture_stderr = popdefault(kw, 'capture_stderr', False) expect_returncode = popdefault(kw, 'expect_returncode', False) force = popdefault(kw, 'force_no_simulate', False) simulate = self.simulate if force: simulate = False assert not kw, ("Arguments not expected: %s" % kw) if capture_stderr: stderr_pipe = subprocess.STDOUT else: stderr_pipe = subprocess.PIPE try: proc = subprocess.Popen([cmd] + list(args), cwd=cwd, stderr=stderr_pipe, stdout=subprocess.PIPE) except OSError, e: if e.errno != 2: # File not found raise raise OSError( "The expected executable %s was not found (%s)" % (cmd, e)) if self.verbose: print 'Running %s %s' % (cmd, ' '.join(args)) if simulate: return None stdout, stderr = proc.communicate() if proc.returncode and not expect_returncode: if not self.verbose: print 'Running %s %s' % (cmd, ' '.join(args)) print 'Error (exit code: %s)' % proc.returncode if stderr: print stderr raise OSError("Error executing command %s" % cmd) if self.verbose > 2: if stderr: print 'Command error output:' print stderr if stdout: print 'Command output:' print stdout return stdout def write_file(self, filename, content, source=None, binary=True, svn_add=True): """ Like ``ensure_file``, but without the interactivity. Mostly deprecated. (I think I forgot it existed) """ import warnings warnings.warn( "command.write_file has been replaced with " "command.ensure_file", DeprecationWarning, 2) if os.path.exists(filename): if binary: f = open(filename, 'rb') else: f = open(filename, 'r') old_content = f.read() f.close() if content == old_content: if self.verbose: print 'File %s exists with same content' % ( self.shorten(filename)) return if (not self.simulate and self.options.interactive): if not self.ask('Overwrite file %s?' % filename): return if self.verbose > 1 and source: print 'Writing %s from %s' % (self.shorten(filename), self.shorten(source)) elif self.verbose: print 'Writing %s' % self.shorten(filename) if not self.simulate: already_existed = os.path.exists(filename) if binary: f = open(filename, 'wb') else: f = open(filename, 'w') f.write(content) f.close() if (not already_existed and svn_add and os.path.exists(os.path.join(os.path.dirname(filename), '.svn'))): self.run_command('svn', 'add', filename) def parse_vars(self, args): """ Given variables like ``['a=b', 'c=d']`` turns it into ``{'a': 'b', 'c': 'd'}`` """ result = {} for arg in args: if '=' not in arg: raise BadCommand( 'Variable assignment %r invalid (no "=")' % arg) name, value = arg.split('=', 1) result[name] = value return result def read_vars(self, config, section='pastescript'): """ Given a configuration filename, this will return a map of values. """ result = {} p = ConfigParser.RawConfigParser() p.read([config]) if p.has_section(section): for key, value in p.items(section): if key.endswith('__eval__'): result[key[:-len('__eval__')]] = eval(value) else: result[key] = value return result def write_vars(self, config, vars, section='pastescript'): """ Given a configuration filename, this will add items in the vars mapping to the configuration file. Will create the configuration file if it doesn't exist. """ modified = False p = ConfigParser.RawConfigParser() if not os.path.exists(config): f = open(config, 'w') f.write('') f.close() modified = True p.read([config]) if not p.has_section(section): p.add_section(section) modified = True existing_options = p.options(section) for key, value in vars.items(): if (key not in existing_options and '%s__eval__' % key not in existing_options): if not isinstance(value, str): p.set(section, '%s__eval__' % key, repr(value)) else: p.set(section, key, value) modified = True if modified: p.write(open(config, 'w')) def indent_block(self, text, indent=2, initial=None): """ Indent the block of text (each line is indented). If you give ``initial``, then that is used in lieue of ``indent`` for the first line. """ if initial is None: initial = indent lines = text.splitlines() first = (' '*initial) + lines[0] rest = [(' '*indent)+l for l in lines[1:]] return '\n'.join([first]+rest) class NotFoundCommand(Command): def run(self, args): #for name, value in os.environ.items(): # print '%s: %s' % (name, value) #print sys.argv print 'Command %s not known' % self.command_name commands = get_commands().items() commands.sort() if not commands: print 'No commands registered.' print 'Have you installed Paste Script?' print '(try running python setup.py develop)' return 2 print 'Known commands:' longest = max([len(n) for n, c in commands]) for name, command in commands: print ' %s %s' % (self.pad(name, length=longest), command.load().summary) return 2 def popdefault(dict, name, default=None): if name not in dict: return default else: v = dict[name] del dict[name] return v PK q 5G`paste/script/testapp.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import cgi import os page_template = ''' Test Application

Test Application: Working!

%(environ)s

Note: to see an error report, append ?error=true to the URL

''' row_template = ''' %(key)s %(value_literal)s ''' def make_literal(value): value = cgi.escape(value, 1) value = value.replace('\n\r', '\n') value = value.replace('\r', '\n') value = value.replace('\n', '
\n') return value class TestApplication(object): """ A test WSGI application, that prints out all the environmental variables, and if you add ``?error=t`` to the URL it will deliberately throw an exception. """ def __init__(self, global_conf): self.global_conf = global_conf def __call__(self, environ, start_response): if environ.get('QUERY_STRING', '').find('error=') >= 0: assert 0, "Here is your error report, ordered and delivered" keys = environ.keys() keys.sort() rows = [] for key in keys: data = {'key': key} value = environ[key] data['value'] = value try: value = repr(value) except Exception, e: value = 'Cannot use repr(): %s' % e data['value_repr'] = value data['value_literal'] = make_literal(value) row = row_template % data rows.append(row) rows = ''.join(rows) page = page_template % {'environ': rows} if isinstance(page, unicode): page = page.encode('utf8') headers = [('Content-type', 'text/html; charset=utf8')] start_response('200 OK', headers) return [page] PK q 5w7xxpaste/script/pluginlib.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import os import pkg_resources def add_plugin(egg_info_dir, plugin_name): """ Add the plugin to the given distribution (or spec), in .egg-info/paster_plugins.txt """ fn = os.path.join(egg_info_dir, 'paster_plugins.txt') if not os.path.exists(fn): lines = [] else: f = open(fn) lines = [l.strip() for l in f.readlines() if l.strip()] f.close() if plugin_name in lines: # Nothing to do return lines.append(plugin_name) f = open(fn, 'w') for line in lines: f.write(line) f.write('\n') f.close() def remove_plugin(egg_info_dir, plugin_name): """ Remove the plugin to the given distribution (or spec), in .egg-info/paster_plugins.txt. Raises ValueError if the plugin is not in the file. """ fn = os.path.join(egg_info_dir, 'paster_plugins.txt') if not os.path.exists(fn): raise ValueError( "Cannot remove plugin from %s; file does not exist" % fn) f = open(fn) lines = [l.strip() for l in f.readlines() if l.strip()] f.close() for line in lines: # What about version specs? if line.lower() == plugin_name.lower(): break else: raise ValueError( "Plugin %s not found in file %s (from: %s)" % (plugin_name, fn, lines)) lines.remove(line) print 'writing', lines f = open(fn, 'w') for line in lines: f.write(line) f.write('\n') f.close() def find_egg_info_dir(dir): while 1: try: filenames = os.listdir(dir) except OSError: # Probably permission denied or something return None for fn in filenames: if fn.endswith('.egg-info'): return os.path.join(dir, fn) parent = os.path.dirname(dir) if parent == dir: # Top-most directory return None dir = parent def resolve_plugins(plugin_list): found = [] while plugin_list: plugin = plugin_list.pop() try: pkg_resources.require(plugin) except pkg_resources.DistributionNotFound, e: e.args = ('Not Found: %s (did you run python setup.py develop?)' % plugin), raise found.append(plugin) dist = get_distro(plugin) if dist.has_metadata('paster_plugins.txt'): data = dist.get_metadata('paster_plugins.txt') for add_plugin in parse_lines(data): if add_plugin not in found: plugin_list.append(add_plugin) return map(get_distro, found) def get_distro(spec): return pkg_resources.get_distribution(spec) def load_commands_from_plugins(plugins): commands = {} for plugin in plugins: commands.update(pkg_resources.get_entry_map( plugin, group='paste.paster_command')) return commands def parse_lines(data): result = [] for line in data.splitlines(): line = line.strip() if line and not line.startswith('#'): result.append(line) return result def load_global_commands(): commands = {} for p in pkg_resources.iter_entry_points('paste.global_paster_command'): commands[p.name] = p return commands def egg_name(dist_name): return pkg_resources.to_filename(pkg_resources.safe_name(dist_name)) def egg_info_dir(base_dir, dist_name): return os.path.join(base_dir, egg_name(dist_name) + '.egg-info') PK q 5e0[& & paste/script/exe.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import re import os import sys import shlex import pkg_resources import command class ExeCommand(command.Command): parser = command.Command.standard_parser(verbose=False) summary = "Run #! executable files" description = """\ Use this at the top of files like: #!/usr/bin/env /path/to/paster exe subcommand The rest of the file will be used as a config file for the given command, if it wants a config file. You can also include an [exe] section in the file, which looks like: [exe] command = serve log_file = /path/to/log add = /path/to/other/config.ini Which translates to: paster serve --log-file=/path/to/log /path/to/other/config.ini """ hidden = True _exe_section_re = re.compile(r'^\s*\[\s*exe\s*\]\s*$') _section_re = re.compile(r'^\s*\[') def run(self, argv): if argv and argv[0] in ('-h', '--help'): print self.description return if os.environ.get('REQUEST_METHOD'): # We're probably in a CGI environment sys.stdout = sys.stderr os.environ['PASTE_DEFAULT_QUIET'] = 'true' # Maybe import cgitb or something? if '_' not in os.environ: print "Warning: this command is intended to be run with a #! like:" print " #!/usr/bin/env paster exe" print "It only works with /usr/bin/env, and only as a #! line." # Should I actually shlex.split the args? filename = argv[-1] args = argv[:-1] extra_args = [] else: filename = os.environ['_'] extra_args = argv[:] args = [] while extra_args: if extra_args[0] == filename: extra_args.pop(0) break args.append(extra_args.pop(0)) f = open(filename) lines = f.readlines() f.close() options = {} lineno = 1 while lines: if self._exe_section_re.search(lines[0]): lines.pop(0) break lines.pop(0) lineno += 1 pre_options = [] options = args for line in lines: lineno += 1 line = line.strip() if not line or line.startswith('#'): continue if self._section_re.search(line): break if '=' not in line: raise command.BadCommand('Missing = in %s at %s: %r' % (filename, lineno, line)) name, value = line.split('=', 1) name = name.strip() value = value.strip() if name == 'require': pkg_resources.require(value) elif name == 'command' or name == 'add': options.extend(shlex.split(value)) elif name == 'plugin': options[:0] = ['--plugin', value] else: options.append('--%s=%s' % (name.replace('_', '-'), value)) os.environ['PASTE_CONFIG_FILE'] = filename options.extend(extra_args) command.run(options) PK q 5$@@paste/script/serve.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php # @@: This should be moved to paste.deploy # For discussion of daemonizing: # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731 # Code taken also from QP: # http://www.mems-exchange.org/software/qp/ # From lib/site.py import re import os import errno import signal import sys import time from command import Command, BadCommand from paste.deploy import loadapp, loadserver import threading import atexit MAXFD = 1024 class ServeCommand(Command): max_args = 2 min_args = 0 usage = 'CONFIG_FILE [start|stop|restart|status]' 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. """ # 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)") 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('--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 availble 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)') _scheme_re = re.compile(r'^[a-zA-Z0-9_-]+:') default_verbosity = 1 _reloader_environ_key = 'PYTHON_RELOADER_SHOULD_RUN' 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: cmd = self.args[1] else: cmd = None else: app_spec = "" if self.args: cmd = self.args[0] else: cmd = None if self.options.reload: 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 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 self.options.daemon: self.daemonize() if self.options.pid_file: self.record_pid(self.options.pid_file) if self.options.log_file: stdout_log = LazyWriter(self.options.log_file) sys.stdout = stdout_log sys.stderr = stdout_log # @@: Should we also redirect logging-based logs to this file? # e.g., the root logger? server = self.loadserver(server_spec, name=server_name, relative_to=base) app = self.loadapp(app_spec, name=app_name, relative_to=base) if self.verbose > 0: print 'Starting server in PID %i.' % os.getpid() try: server(app) except (SystemExit, KeyboardInterrupt), e: if self.verbose > 1: raise if str(e): msg = ' '+str(e) else: msg = '' print 'Exiting%s (-v to see traceback)' % msg def loadserver(self, server_spec, name, relative_to): return loadserver(server_spec, name=name, relative_to=relative_to) def loadapp(self, app_spec, name, relative_to): return loadapp(app_spec, name=name, relative_to=relative_to) def daemonize(self): if self.verbose > 0: print 'Entering daemon mode' pid = os.fork() if pid: # The forked process also has a handle on resources, so we # *don't* want proper termination of the process, we just # want to exit quick (which os._exit() does) os._exit(0) # Make this the session leader os.setsid() # Fork again for good measure! pid = os.fork() if pid: os._exit(0) # @@: Should we set the umask and cwd now? import resource # Resource usage information. maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] if (maxfd == resource.RLIM_INFINITY): maxfd = MAXFD # Iterate through and close all file descriptors. for fd in range(0, maxfd): try: os.close(fd) except OSError: # ERROR, fd wasn't open to begin with (ignored) pass if (hasattr(os, "devnull")): REDIRECT_TO = os.devnull else: REDIRECT_TO = "/dev/null" os.open(REDIRECT_TO, os.O_RDWR) # standard input (0) # Duplicate standard input to standard output and standard error. os.dup2(0, 1) # standard output (1) os.dup2(0, 2) # standard error (2) if not self.options.pid_file: self.options.pid_file = 'paster.pid' if not self.options.log_file: self.options.log_file = 'paster.log' def record_pid(self, pid_file): pid = os.getpid() if self.verbose > 1: print 'Writing PID %s to %s' % (pid, pid_file) f = open(pid_file, 'w') f.write(str(pid)) f.close() atexit.register(_remove_pid_file, pid, pid_file, self.verbose) def stop_daemon(self): pid_file = self.options.pid_file or 'paster.pid' if not os.path.exists(pid_file): print 'No PID file exists in %s' % pid_file return 1 pid = read_pidfile(pid_file) if not pid: print "Not a valid PID file in %s" % pid_file return 1 pid = live_pidfile(pid_file) if not pid: print "PID in %s is not valid (deleting)" % pid_file try: os.unlink(pid_file) except (OSError, IOError), e: print "Could not delete: %s" % e return 2 return 1 for j in range(10): if not live_pidfile(pid_file): break os.kill(pid, signal.SIGTERM) time.sleep(1) else: print "failed to kill web process %s" % pid return 3 if os.path.exists(pid_file): os.unlink(pid_file) return 0 def show_status(self): pid_file = self.options.pid_file or 'paster.pid' if not os.path.exists(pid_file): print 'No PID file %s' % pid_file return 1 pid = read_pidfile(pid_file) if not pid: print 'No PID in file %s' % pid_file return 1 pid = live_pidfile(pid_file) if not pid: print 'PID %s in %s is not running' % (pid, pid_file) return 1 print 'Server running in PID %s' % pid return 0 def restart_with_reloader(self): if self.verbose > 0: print 'Starting subprocess with file monitor' while 1: args = [sys.executable] + sys.argv new_environ = os.environ.copy() new_environ[self._reloader_environ_key] = 'true' exit_code = os.spawnve(os.P_WAIT, sys.executable, args, new_environ) if exit_code != 3: return exit_code if self.verbose > 0: print '-'*20, 'Restarting', '-'*20 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) class LazyWriter(object): def __init__(self, filename): self.filename = filename self.fileobj = None self.lock = threading.Lock() def open(self): if self.fileobj is None: self.lock.acquire() try: if self.fileobj is None: self.fileobj = open(self.filename, 'a') finally: self.lock.release() return self.fileobj def write(self, text): fileobj = self.open() fileobj.write(text) fileobj.flush() def writelines(self, text): fileobj = self.open() fileobj.writelines(text) fileobj.flush() def flush(self): self.open().flush() def live_pidfile(pidfile): """(pidfile:str) -> int | None Returns an int found in the named file, if there is one, and if there is a running process with that process id. Return None if no such process exists. """ pid = read_pidfile(pidfile) if pid: try: os.kill(int(pid), 0) return pid except OSError, e: if e.errno == errno.EPERM: return pid return None def read_pidfile(filename): if os.path.exists(filename): try: f = open(filename) content = f.read() f.close() return int(content.strip()) except (ValueError, IOError): return None else: return None def _remove_pid_file(written_pid, filename, verbosity): current_pid = os.getpid() if written_pid != current_pid: # A forked process must be exiting, not the process that # wrote the PID file return if not os.path.exists(filename): return f = open(filename) content = f.read().strip() f.close() try: pid_in_file = int(content) except ValueError: pass else: if pid_in_file != current_pid: print "PID file %s contains %s, not expected PID %s" % ( filename, pid_in_file, current_pid) return if verbosity > 0: print "Removing PID file %s" % filename try: os.unlink(filename) return except OSError, e: # Record, but don't give traceback print "Cannot remove PID file: %s" % e # well, at least lets not leave the invalid PID around... try: f = open(filename, 'w') f.write('') f.close() except OSError, e: print 'Stale PID left in file: %s (%e)' % (filename, e) else: print 'Stale PID removed' def ensure_port_cleanup(bound_addresses, maxtries=30, sleeptime=2): """ This makes sure any open ports are closed. Does this by connecting to them until they give connection refused. Servers should call like:: import paste.script ensure_port_cleanup([80, 443]) """ atexit.register(_cleanup_ports, bound_addresses, maxtries=maxtries, sleeptime=sleeptime) def _cleanup_ports(bound_addresses, maxtries=30, sleeptime=2): # Wait for the server to bind to the port. import socket import errno for bound_address in bound_addresses: for attempt in range(maxtries): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect(bound_address) except socket.error, e: if e.args[0] != errno.ECONNREFUSED: raise break else: time.sleep(sleeptime) else: raise SystemExit('Timeout waiting for port.') sock.close() PK q 5*Hpaste/script/interfaces.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php class IAppInstall: """ The interface for objects in the entry point group ``paste.app_install`` """ def __init__(distribution, entry_group, entry_name): """ An object representing a specific application (the distribution is a pkg_resource.Distribution object), for the given entry point name in the given group. Right now the only group used for this is ``'paste.app_factory'``. """ def description(sys_config): """ Return a text description of the application and its configuration. ``sys_config`` is a dictionary representing the system configuration, and can be used for giving more explicit defaults if the application preparation uses the system configuration. It may be None, in which case the description should be more abstract. Applications are free to ignore ``sys_config``. """ def write_config(command, filename, sys_config): """ Write a fresh config file to ``filename``. ``command`` is a ``paste.script.command.Command`` object, and should be used for the actual operations. It handles things like simulation and verbosity. ``sys_config`` is (if given) a dictionary of system-wide configuration options. """ def setup_config(command, config_filename, config_section, sys_config): """ Set up the application, using ``command`` (to ensure simulate, etc). The application is described by the configuration file ``config_filename``. ``sys_config`` is the system configuration (though probably the values from it should have already been encorporated into the configuration file). """ PK q 5r33paste/script/checkperms.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php """ This is a module to check the filesystem for the presence and permissions of certain files. It can also be used to correct the permissions (but not existance) of those files. Currently only supports Posix systems (with Posixy permissions). Permission stuff can probably be stubbed out later. """ import os import pwd import grp def read_perm_spec(spec): """ Reads a spec like 'rw-r--r--' into a octal number suitable for chmod. That is characters in groups of three -- first group is user, second for group, third for other (all other people). The characters are r (read), w (write), and x (executable), though the executable can also be s (sticky). Files in sticky directories get the directories permission setting. Examples:: >>> print oct(read_perm_spec('rw-r--r--')) 0644 >>> print oct(read_perm_spec('rw-rwsr--')) 02664 >>> print oct(read_perm_spec('r-xr--r--')) 0544 >>> print oct(read_perm_spec('r--------')) 0400 """ total_mask = 0 # suid/sgid modes give this mask in user, group, other mode: set_bits = (04000, 02000, 0) pieces = (spec[0:3], spec[3:6], spec[6:9]) for i, (mode, set_bit) in enumerate(zip(pieces, set_bits)): mask = 0 read, write, exe = list(mode) if read == 'r': mask = mask | 4 elif read != '-': raise ValueError, ( "Character %r unexpected (should be '-' or 'r')" % read) if write == 'w': mask = mask | 2 elif write != '-': raise ValueError, ( "Character %r unexpected (should be '-' or 'w')" % write) if exe == 'x': mask = mask | 1 elif exe not in ('s', '-'): raise ValueError, ( "Character %r unexpected (should be '-', 'x', or 's')" % exe) if exe == 's' and i == 2: raise ValueError, ( "The 'other' executable setting cannot be suid/sgid ('s')") mask = mask << ((2-i)*3) if exe == 's': mask = mask | set_bit total_mask = total_mask | mask return total_mask modes = [ (04000, 'setuid bit', 'setuid bit: make contents owned by directory owner'), (02000, 'setgid bit', 'setgid bit: make contents inherit permissions from directory'), (01000, 'sticky bit', 'sticky bit: append-only directory'), (00400, 'read by owner', 'read by owner'), (00200, 'write by owner', 'write by owner'), (00100, 'execute by owner', 'owner can search directory'), (00040, 'allow read by group members', 'allow read by group members',), (00020, 'allow write by group members', 'allow write by group members'), (00010, 'execute by group members', 'group members can search directory'), (00004, 'read by others', 'read by others'), (00002, 'write by others', 'write by others'), (00001, 'execution by others', 'others can search directory'), ] exe_bits = [0100, 0010, 0001] exe_mask = 0111 full_mask = 07777 def mode_diff(filename, mode, **kw): """ Returns the differences calculated using ``calc_mode_diff`` """ cur_mode = os.stat(filename).st_mode return calc_mode_diff(cur_mode, mode, **kw) def calc_mode_diff(cur_mode, mode, keep_exe=True, not_set='not set: ', set='set: '): """ Gives the difference between the actual mode of the file and the given mode. If ``keep_exe`` is true, then if the mode doesn't include any executable information the executable information will simply be ignored. High bits are also always ignored (except suid/sgid and sticky bit). Returns a list of differences (empty list if no differences) """ for exe_bit in exe_bits: if mode & exe_bit: keep_exe = False diffs = [] isdir = os.path.isdir(filename) for bit, file_desc, dir_desc in modes: if keep_exe and bit in exe_bits: continue if isdir: desc = dir_desc else: desc = file_desc if (mode & bit) and not (cur_mode & bit): diffs.append(not_set + desc) if not (mode & bit) and (cur_mode & bit): diffs.append(set + desc) return diffs def calc_set_mode(cur_mode, mode, keep_exe=True): """ Calculates the new mode given the current node ``cur_mode`` and the mode spec ``mode`` and if ``keep_exe`` is true then also keep the executable bits in ``cur_mode`` if ``mode`` has no executable bits in it. Return the new mode. Examples:: >>> print oct(calc_set_mode(0775, 0644)) 0755 >>> print oct(calc_set_mode(0775, 0744)) 0744 >>> print oct(calc_set_mode(010600, 0644)) 010644 >>> print oct(calc_set_mode(0775, 0644, False)) 0644 """ for exe_bit in exe_bits: if mode & exe_bit: keep_exe = False # This zeros-out full_mask parts of the current mode: keep_parts = (cur_mode | full_mask) ^ full_mask if keep_exe: keep_parts = keep_parts | (cur_mode & exe_mask) new_mode = keep_parts | mode return new_mode def set_mode(filename, mode, **kw): """ Sets the mode on ``filename`` using ``calc_set_mode`` """ cur_mode = os.stat(filename).st_mode new_mode = calc_set_mode(cur_mode, mode, **kw) os.chmod(filename, new_mode) def calc_ownership_spec(spec): """ Calculates what a string spec means, returning (uid, username, gid, groupname), where there can be None values meaning no preference. The spec is a string like ``owner:group``. It may use numbers instead of user/group names. It may leave out ``:group``. It may use '-' to mean any-user/any-group. """ user = group = None uid = gid = None if ':' in spec: user_spec, group_spec = spec.split(':', 1) else: user_spec, group_spec = spec, '-' if user_spec == '-': user_spec = '0' if group_spec == '-': group_spec = '0' try: uid = int(user_spec) except ValueError: uid = pwd.getpwnam(user_spec) user = user_spec else: if not uid: uid = user = None else: user = pwd.getpwuid(uid).pw_name try: gid = int(group_spec) except ValueError: gid = grp.getgrnam(group_spec) group = group_spec else: if not gid: gid = group = None else: group = grp.getgrgid(gid).gr_name return (uid, user, gid, group) def ownership_diff(filename, spec): """ Return a list of differences between the ownership of ``filename`` and the spec given. """ diffs = [] uid, user, gid, group = calc_ownership_spec(spec) st = os.stat(filename) if uid and uid != st.st_uid: diffs.append('owned by %s (should be %s)' % (pwd.getpwuid(st.st_uid).pw_name, user)) if gid and gid != st.st_gid: diffs.append('group %s (should be %s)' % (grp.getgrgid(st.st_gid).gr_name, group)) return diffs def set_ownership(filename, spec): """ Set the ownership of ``filename`` given the spec. """ uid, user, gid, group = calc_ownership_spec(spec) st = os.stat(filename) if not uid: uid = st.st_uid if not gid: gid = st.st_gid os.chmod(filename, uid, gid) class PermissionSpec(object): """ Represents a set of specifications for permissions. Typically reads from a file that looks like this:: rwxrwxrwx user:group filename If the filename ends in /, then it expected to be a directory, and the directory is made executable automatically, and the contents of the directory are given the same permission (recursively). By default the executable bit on files is left as-is, unless the permissions specifically say it should be on in some way. You can use 'nomodify filename' for permissions to say that any permission is okay, and permissions should not be changed. Use 'noexist filename' to say that a specific file should not exist. Use 'symlink filename symlinked_to' to assert a symlink destination The entire file is read, and most specific rules are used for each file (i.e., a rule for a subdirectory overrides the rule for a superdirectory). Order does not matter. """ def __init__(self): self.paths = {} def parsefile(self, filename): f = open(filename) lines = f.readlines() f.close() self.parselines(lines, filename=filename) commands = {} def parselines(self, lines, filename=None): for lineindex, line in enumerate(lines): line = line.strip() if not line or line.startswith('#'): continue parts = line.split() command = parts[0] if command in self.commands: cmd = self.commands[command](*parts[1:]) else: cmd = self.commands['*'](*parts) self.paths[cmd.path] = cmd def check(self): action = _Check(self) self.traverse(action) def fix(self): action = _Fixer(self) self.traverse(action) def traverse(self, action): paths = self.paths_sorted() checked = {} for path, checker in list(paths)[::-1]: self.check_tree(action, path, paths, checked) for path, checker in paths: if path not in checked: action.noexists(path, checker) def traverse_tree(self, action, path, paths, checked): if path in checked: return self.traverse_path(action, path, paths, checked) if os.path.isdir(path): for fn in os.listdir(path): fn = os.path.join(path, fn) self.traverse_tree(action, fn, paths, checked) def traverse_path(self, action, path, paths, checked): checked[path] = None for check_path, checker in paths: if path.startswith(check_path): action.check(check_path, checker) if not checker.inherit: break def paths_sorted(self): paths = self.paths.items() paths.sort(lambda a, b: -cmp(len(a[0]), len(b[0]))) class _Rule(object): class __metaclass__(type): def __new__(meta, class_name, bases, d): cls = type.__new__(meta, class_name, bases, d) PermissionSpec.commands[cls.__name__] = cls return cls inherit = False def noexists(self): return ['Path %s does not exist' % path] class _NoModify(_Rule): name = 'nomodify' def __init__(self, path): self.path = path def fix(self, path): pass class _NoExist(_Rule): name = 'noexist' def __init__(self, path): self.path = path def check(self, path): return ['Path %s should not exist' % path] def noexists(self, path): return [] def fix(self, path): # @@: Should delete? pass class _SymLink(_Rule): name = 'symlink' inherit = True def __init__(self, path, dest): self.path = path self.dest = dest def check(self, path): assert path == self.path, ( "_Symlink should only be passed specific path %s (not %s)" % (self.path, path)) try: link = os.path.readlink(path) except OSError: if e.errno != 22: raise return ['Path %s is not a symlink (should point to %s)' % (path, self.dest)] if link != self.dest: return ['Path %s should symlink to %s, not %s' % (path, self.dest, link)] return [] def fix(self, path): assert path == self.path, ( "_Symlink should only be passed specific path %s (not %s)" % (self.path, path)) if not os.path.exists(path): os.symlink(path, self.dest) else: # @@: This should correct the symlink or something: print 'Not symlinking %s' % path class _Permission(_Rule): name = '*' def __init__(self, perm, owner, dir): self.perm_spec = read_perm_spec(perm) self.owner = owner self.dir = dir def check(self, path): return mode_diff(path, self.perm_spec) def fix(self, path): set_mode(path, self.perm_spec) class _Strategy(object): def __init__(self, spec): self.spec = spec class _Check(_Strategy): def noexists(self, path, checker): checker.noexists(path) def check(self, path, checker): checker.check(path) class _Fixer(_Strategy): def noexists(self, path, checker): pass def check(self, path, checker): checker.fix(path) if __name__ == '__main__': import doctest doctest.testmod() PK q 5k\(-;-;paste/script/create_distro.py# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import re import sys import os import pkg_resources from command import Command, BadCommand import copydir import pluginlib import fnmatch class CreateDistroCommand(Command): usage = 'PACKAGE_NAME [VAR=VALUE VAR2=VALUE2 ...]' summary = "Create the file layout for a Python distribution" short_description = summary description = """\ Create a new project. Projects are typically Python packages, ready for distribution. Projects are created from templates, and represent different kinds of projects -- associated with a particular framework for instance. """ parser = Command.standard_parser( simulate=True, no_interactive=True, quiet=True, overwrite=True) parser.add_option('-t', '--template', dest='templates', metavar='TEMPLATE', action='append', help="Add a template to the create process") parser.add_option('-o', '--output-dir', dest='output_dir', metavar='DIR', default='.', help="Write put the directory into DIR (default current directory)") parser.add_option('--svn-repository', dest='svn_repository', metavar='REPOS', help="Create package at given repository location (this will create the standard trunk/ tags/ branches/ hierarchy)") parser.add_option('--list-templates', dest='list_templates', action='store_true', help="List all templates available") parser.add_option('--list-variables', dest="list_variables", action="store_true", help="List all variables expected by the given template (does not create a package)") parser.add_option('--inspect-files', dest='inspect_files', action='store_true', help="Show where the files in the given (already created) directory came from (useful when using multiple templates)") parser.add_option('--config', action='store', dest='config', help="Template variables file") _bad_chars_re = re.compile('[^a-zA-Z0-9_]') default_verbosity = 1 default_interactive = 1 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) if os.path.exists(os.path.join(output_dir, 'setup.py')): self.run_command(sys.executable, 'setup.py', 'egg_info', cwd=output_dir) elif self.verbose > 1: print 'No setup.py (cannot run egg_info)' 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) def create_template(self, template, output_dir, vars): if self.verbose: print 'Creating template %s' % template.name template.run(self, output_dir, vars) def setup_svn_repository(self, output_dir, dist_name): # @@: Use subprocess svn_repos = self.options.svn_repository svn_repos_path = os.path.join(svn_repos, dist_name).replace('\\','/') svn_command = 'svn' if sys.platform == 'win32': svn_command += '.exe' # @@: The previous method of formatting this string using \ doesn't work on Windows cmd = '%(svn_command)s mkdir %(svn_repos_path)s' + \ ' %(svn_repos_path)s/trunk %(svn_repos_path)s/tags' + \ ' %(svn_repos_path)s/branches -m "New project %(dist_name)s"' cmd = cmd % { 'svn_repos_path': svn_repos_path, 'dist_name': dist_name, 'svn_command':svn_command, } if self.verbose: print "Running:" print cmd if not self.simulate: os.system(cmd) svn_repos_path_trunk = os.path.join(svn_repos_path,'trunk').replace('\\','/') cmd = svn_command+' co "%s" "%s"' % (svn_repos_path_trunk, output_dir) if self.verbose: print "Running %s" % cmd if not self.simulate: os.system(cmd) ignore_egg_info_files = [ 'top_level.txt', 'entry_points.txt', 'requires.txt', 'PKG-INFO', 'namespace_packages.txt', 'SOURCES.txt', 'not-zip-safe'] def add_svn_repository(self, vars, output_dir): svn_repos = self.options.svn_repository egg_info_dir = pluginlib.egg_info_dir(output_dir, vars['project']) svn_command = 'svn' if sys.platform == 'win32': svn_command += '.exe' self.run_command(svn_command, 'add', '-N', egg_info_dir) paster_plugins_file = os.path.join( egg_info_dir, 'paster_plugins.txt') if os.path.exists(paster_plugins_file): self.run_command(svn_command, 'add', paster_plugins_file) self.run_command(svn_command, 'ps', 'svn:ignore', '\n'.join(self.ignore_egg_info_files), egg_info_dir) if self.verbose: print ("You must next run 'svn commit' to commit the " "files to repository") def extend_templates(self, templates, tmpl_name): if '#' in tmpl_name: dist_name, tmpl_name = tmpl_name.split('#', 1) else: dist_name, tmpl_name = None, tmpl_name if dist_name is None: for entry in self.all_entry_points(): if entry.name == tmpl_name: tmpl = entry.load()(entry.name) dist_name = entry.dist.project_name break else: raise LookupError( 'Template by name %r not found' % tmpl_name) else: dist = pkg_resources.get_distribution(dist_name) entry = dist.get_entry_info( 'paste.paster_create_template', tmpl_name) tmpl = entry.load()(entry.name) full_name = '%s#%s' % (dist_name, tmpl_name) for item_full_name, item_tmpl in templates: if item_full_name == full_name: # Already loaded return for req_name in tmpl.required_templates: self.extend_templates(templates, req_name) templates.append((full_name, tmpl)) def all_entry_points(self): if not hasattr(self, '_entry_points'): self._entry_points = list(pkg_resources.iter_entry_points( 'paste.paster_create_template')) return self._entry_points def display_vars(self, vars): vars = vars.items() vars.sort() print 'Variables:' max_var = max([len(n) for n, v in vars]) for name, value in vars: print ' %s:%s %s' % ( name, ' '*(max_var-len(name)), value) def list_templates(self): templates = [] for entry in self.all_entry_points(): try: templates.append(entry.load()(entry.name)) except Exception, e: # We will not be stopped! print 'Warning: could not load entry point %s (%s: %s)' % ( entry.name, e.__class__.__name__, e) max_name = max([len(t.name) for t in templates]) templates.sort(lambda a, b: cmp(a.name, b.name)) print 'Available templates:' for template in templates: # @@: Wrap description print ' %s:%s %s' % ( template.name, ' '*(max_name-len(template.name)), template.summary) def inspect_files(self, output_dir, templates, vars): file_sources = {} for template in templates: self._find_files(template, vars, file_sources) self._show_files(output_dir, file_sources) self._show_leftovers(output_dir, file_sources) def _find_files(self, template, vars, file_sources): tmpl_dir = template.template_dir() self._find_template_files( template, tmpl_dir, vars, file_sources) def _find_template_files(self, template, tmpl_dir, vars, file_sources, join=''): full_dir = os.path.join(tmpl_dir, join) for name in os.listdir(full_dir): if name.startswith('.'): continue if os.path.isdir(os.path.join(full_dir, name)): self._find_template_files( template, tmpl_dir, vars, file_sources, join=os.path.join(join, name)) continue partial = os.path.join(join, name) for name, value in vars.items(): partial = partial.replace('+%s+' % name, value) if partial.endswith('_tmpl'): partial = partial[:-5] file_sources.setdefault(partial, []).append(template) _ignore_filenames = ['.*', '*.pyc', '*.bak*'] _ignore_dirs = ['CVS', '_darcs', '.svn'] def _show_files(self, output_dir, file_sources, join='', indent=0): pad = ' '*(2*indent) full_dir = os.path.join(output_dir, join) names = os.listdir(full_dir) dirs = [n for n in names if os.path.isdir(os.path.join(full_dir, n))] fns = [n for n in names if not os.path.isdir(os.path.join(full_dir, n))] dirs.sort() names.sort() for name in names: skip_this = False for ext in self._ignore_filenames: if fnmatch.fnmatch(name, ext): if self.verbose > 1: print '%sIgnoring %s' % (pad, name) skip_this = True break if skip_this: continue partial = os.path.join(join, name) if partial not in file_sources: if self.verbose > 1: print '%s%s (not from template)' % (pad, name) continue templates = file_sources.pop(partial) print '%s%s from:' % (pad, name) for template in templates: print '%s %s' % (pad, template.name) for dir in dirs: if dir in self._ignore_dirs: continue print '%sRecursing into %s/' % (pad, dir) self._show_files( output_dir, file_sources, join=os.path.join(join, dir), indent=indent+1) def _show_leftovers(self, output_dir, file_sources): if not file_sources: return print print 'These files were supposed to be generated by templates' print 'but were not found:' file_sources = file_sources.items() file_sources.sort() for partial, templates in file_sources: print ' %s from:' % partial for template in templates: print ' %s' % template.name def list_variables(self, templates): for tmpl_name, tmpl in templates: if not tmpl.read_vars(): if self.verbose > 1: self._show_template_vars( tmpl_name, tmpl, 'No variables found') continue self._show_template_vars(tmpl_name, tmpl) def _show_template_vars(self, tmpl_name, tmpl, message=None): title = '%s (from %s)' % (tmpl.name, tmpl_name) print title print '-'*len(title) if message is not None: print ' %s' % message print return tmpl.print_vars(indent=2) PKSq 59T))paste/script/templates.pyc; *'Dc@sdkZdkZdkZdkZdkZdefdYZdfdYZdefdYZdefdYZ d d d d d ddgZ dZ e dZ dS(NsTemplatecBstZgZgZgZeZeZdZdZ dZ dZ dZ e dZdZdd Zd Zd ZRS( NcCs||_t|_dS(N(snamesselfsNones _read_vars(sselfsname((s4build/bdist.linux-i686/egg/paste/script/templates.pys__init__s cCs*ti|ii}tii|i SdS(s@ Returns the module directory of this template. N( ssyssmodulessselfs __class__s __module__smodsosspathsdirnames__file__(sselfsmod((s4build/bdist.linux-i686/egg/paste/script/templates.pys module_dir"scCs>|itj ptd|tii|i|iSdS(Ns$Template %r didn't set _template_dir(sselfs _template_dirsNonesAssertionErrorsosspathsjoins module_dir(sself((s4build/bdist.linux-i686/egg/paste/script/templates.pys template_dir)scCs=|i||||i||||i|||dS(N(sselfsprescommands output_dirsvarss write_filesspost(sselfscommands output_dirsvars((s4build/bdist.linux-i686/egg/paste/script/templates.pysrun.sc Cs<|i|}| o|Snh}|i}g}x|D]}|i |jo|i o6d|i }|i||i} | ||i |i|i ||i W|o tiddi|n|i||i||SdS(NsEnter %ssRequired variable missing: %ssErrors in variables: %ss (sselfs read_varsscmds expect_varssvarssconverted_varsscopys unused_varsserrorssvarsnames interactivesfull_descriptionsprompts challengesdefaultsresponsescommands NoDefaultsappendspops BadCommandsjoinsupdate( sselfsvarsscmdserrorss unused_varss expect_varssconverted_varssvarspromptsresponse((s4build/bdist.linux-i686/egg/paste/script/templates.pys check_vars3s,     cCs|itj o |iSn|i p|ip td|i o|i|_|iSn|i}gi}|iD]}||i qw~}t |i d|o |idji}|ix2|D]*\}}||jo|i|qqW||_|SdS(Ns;You can only read variables from templates if using Cheetahsverbosei(sselfs _read_varssNonesread_vars_from_templatess use_cheetahsAssertionErrorsvarssappends_[1]svarsnames var_namessfind_args_in_dirs template_dirscommandsverbosesitemss read_varsssortsvar_name(sselfscommands read_varssvarss var_namess_[1]svar_namesvar((s4build/bdist.linux-i686/egg/paste/script/templates.pys read_varsOs"     - "    cCs|i}tii| o)d|GH|i oti|qInt i |||d|i d|i id|id|i iddd|idS( NsCreating directory %ss verbosityssimulates interactives overwritesindentis use_cheetah(sselfs template_dirsosspathsexistss output_dirscommandssimulatesmakedirsscopydirscopy_dirsvarssverbosesoptionss interactives overwrites use_cheetah(sselfscommands output_dirsvarss template_dir((s4build/bdist.linux-i686/egg/paste/script/templates.pys write_fileses        icCs|i}ti|dS(N(sselfs read_varssvarssvars print_vars(sselfsindentsvars((s4build/bdist.linux-i686/egg/paste/script/templates.pys print_varsvs cCsdS(s4 Called before template is applied. N((sselfscommands output_dirsvars((s4build/bdist.linux-i686/egg/paste/script/templates.pysprezscCsdS(s3 Called after template is applied. N((sselfscommands output_dirsvars((s4build/bdist.linux-i686/egg/paste/script/templates.pysposts(s__name__s __module__svarss egg_pluginssrequired_templatessFalses use_cheetahsread_vars_from_templatess__init__s module_dirs template_dirsruns check_varssNones read_varss write_filess print_varssprespost(((s4build/bdist.linux-i686/egg/paste/script/templates.pysTemplate s         s NoDefaultcBstZRS(N(s__name__s __module__(((s4build/bdist.linux-i686/egg/paste/script/templates.pys NoDefaultssvarcBs5tZddZdZddZeeZRS(NscCs||_||_||_dS(N(snamesselfs descriptionsdefault(sselfsnames descriptionsdefault((s4build/bdist.linux-i686/egg/paste/script/templates.pys__init__s  cCs-|iod|i|ifSn|iSdS(Ns%s (%s)(sselfs descriptionsname(sself((s4build/bdist.linux-i686/egg/paste/script/templates.pysfull_descriptions icCstgi}|D]}|t|iq~}x{|D]s}|i o4dd||id|t|i|i fGHn d|iGH|i t i j od|i GHq=q=WHdS(Ns %s%s%s %ss s %ss default: %r(smaxsappends_[1]svarssvslensnamesmax_namesvars descriptionsindentsdefaultscommands NoDefault(sclssvarssindents_[1]smax_namesvsvar((s4build/bdist.linux-i686/egg/paste/script/templates.pys print_varss6 4 (s__name__s __module__s__init__sfull_descriptions print_varss classmethod(((s4build/bdist.linux-i686/egg/paste/script/templates.pysvars   s BasicPackagec BstZdZdZeddeddedded d ed d ed deddeddedddeg ZRS(Nstemplates/basic_packages"A basic setuptools-enabled packagesversionsVersion (like 0.1)s descriptions#One-line description of the packageslong_descriptions Multi-line description (in reST)skeywordssSpace-separated keywords/tagssauthors Author names author_emails Author emailsurlsURL of homepages license_names License nameszip_safes<True/False: if the package can be distributed as a .zip filesdefault(s__name__s __module__s _template_dirssummarysvarsFalsesvars(((s4build/bdist.linux-i686/egg/paste/script/templates.pys BasicPackagessVFNs currentTimesselfsVFFSLs dummyTranssgetmtimestransc Cst|ttfo"dk}|iid|}nt|d otSn|i } t i | \}}}}t|pg}g}x|o{t|t|jo|id}n ti}|id}|tjoqn|it|dtd|qW|SdS(Nsfilesbodyis descriptionsdefault(s isinstancestemplatesstrsunicodesCheetah.TemplatesCheetahsTemplateshasattrsNonesbodysmethodsinspects getargspecsargssvarargssvarkwsdefaultsslistsvarsslenspopsdefaultscommands NoDefaultsargs_skip_variablessappendsvar( stemplatesvarssdefaultsargsargssdefaultssvarargssCheetahsvarkwsmethod((s4build/bdist.linux-i686/egg/paste/script/templates.pysfind_args_in_templates(    c Cs1h}x ti|D]}|idp|djp |djoqntii||}tii |ot |} np|i do\h} t |}|tjo|o d|GHqqnx"|D]}|| |i|iD]3}|ii|io|i|qqW|id oq&n|i|q&Wx|D]}|i|qWdS(Ns.py(sosslistdirsdirsnamesssortsdirssnamespathsjoinsfullsselfs bad_namessisdirsappends add_typesstslowersendswiths search_texts search_files search_dir(sselfsdirsdirssfullsnamesnamesst((s/build/bdist.linux-i686/egg/paste/script/grep.pys search_dir2s*   cCs|id7_|id o|i|dSn|d d}tii| ot i |ntii| o|i|dt dSnt |d}|idti|}|i|i||gdS(Nis.pyispycs as_modulesrbi(sselfs total_filessfilenamesendswiths search_textspycsosspathsexistss py_compilescompilesTruesopensfsreadsmarshalsloadscodescloses search_code(sselfsfilenamescodesfspyc((s/build/bdist.linux-i686/egg/paste/script/grep.pys search_fileGs   cCs|idjo||ig}n|}|i}||ijo|i|||n(||i jo|i|||nxt|i D]i}||jo|i|||nt i |o/|i|j oqn|i|||qqWdS(Ns?(scodesco_namespathsselfssymbolssyms co_varnamessfoundsfilenamesco_namess co_constssconstsinspectsiscodes co_filenames search_code(sselfscodesfilenamespathsconstssym((s/build/bdist.linux-i686/egg/paste/script/grep.pys search_codeZs    cCst|d}d}t}x|D]}|d7}|i|i djo`| o5t }|od|i |GHq|i |GHnd||fGH|i oPqq"q"W|idS(Nsrbiiis%s (unloadable)s %3i %s(sopensfilenamesfslinenosFalsesanyslinesfindsselfssymbolsTrues as_modules module_names relative_namesverbosesclose(sselfsfilenames as_modulesfslinenoslinesany((s/build/bdist.linux-i686/egg/paste/script/grep.pys search_textls    cCs"|i||GH|i|dS(N(sselfsdisplaysfilenamespathsfind_occurancescode(sselfscodesfilenamespath((s/build/bdist.linux-i686/egg/paste/script/grep.pysfound~sc Cst|id}d}x0tt|i|D]\}}|d7}q1Wg}t }x|D]}|d7}|i |idjowttid|id}|t jo |}n||joPnd|||ifGH|i oPqq^q^WdS(Nsrbiiis^[ \t]*s %3i %s(sopenscodes co_filenamesfslinenoszipsxrangesco_firstlinenosindexslineslinessNones first_indentsfindsselfssymbolslensresmatchsgroups this_indentsrstripsverbose( sselfscodesindexsfs first_indentsliness this_indentslinenosline((s/build/bdist.linux-i686/egg/paste/script/grep.pysfind_occurances(   !    cCs|ptt|i|t|iiditii }tii |d}|i tii di dd}|SdS(Ns/is.( sfilenamesAssertionErrors startswithsselfsbasedirslensstripsosspathssepsmodssplitextsreplace(sselfsfilenamesmod((s/build/bdist.linux-i686/egg/paste/script/grep.pys module_names +$cCsM|ptt|i|t|iiditii }|SdS(Ns/( sfilenamesAssertionErrors startswithsselfsbasedirslensstripsosspathssepsname(sselfsfilenamesname((s/build/bdist.linux-i686/egg/paste/script/grep.pys relative_names+cCs9di|}|od|}n|i||SdS(Ns.s:(sjoinspathspartssselfs module_namesfilename(sselfsfilenamespathsparts((s/build/bdist.linux-i686/egg/paste/script/grep.pysdisplays(s__name__s __module__ssummarysusagesmax_argssmin_argss bad_namessCommandsstandard_parsersparsers add_optionscommands search_dirs search_files search_codesFalses search_textsfoundsfind_occurances module_names relative_namesdisplay(((s/build/bdist.linux-i686/egg/paste/script/grep.pys GrepCommand s4             ( soss py_compilesmarshalsinspectsrescommandsCommands pluginlibs GrepCommand(s pluginlibs py_compilesinspectsresCommands GrepCommandsossmarshal((s/build/bdist.linux-i686/egg/paste/script/grep.pys?s       PKSq 5NEO" paste/script/cgi_server.pyc; *'Dc@s1dkZdkZdZeiZdZdS(NcCst|dS(N(s run_with_cgiswsgi_app(swsgi_apps global_conf((s5build/bdist.linux-i686/egg/paste/script/cgi_server.pys paste_run_cgisc s9ttii}ti|dbuild/bdist.linux-i686/egg/paste/script/twisted_web2_server.pys conn_strings  s 127.0.0.1s8080s443ic Cs|pt}dk} dk} dk} dk} dk} dk} | i i i |} | i ii| }| i iii| i ii|}| iiid}t|oA| iiit||| i ii|}|i!|nt|oG| iiit||d|| i ii|}|i!|nt| oJdk'} | iiit| | | i i*i+|}|i!|ndS(Nspasters privateKey(,shostsNonestwisted.web2.wsgistwistedstwisted.web2.logstwisted.web2.httpstwisted.web2.serverstwisted.application.servicestwisted.application.strportssweb2swsgis WSGIResourceswsgi_apps wsgi_resourceslogsLogWrapperResourcesress"DefaultCommonAccessLoggingObserversstartsserversSitessites applicationsservices Applicationsasboolsuse_httpsstrportss conn_stringsportshttps HTTPFactoryssssetServiceParents use_httpss https_hosts https_portshttps_private_keysuse_scgistwisted.web2.scgichannels scgi_hosts scgi_ports scgichannels SCGIFactory(swsgi_apps global_confsuse_httpshostsports use_httpss https_hosts https_portshttps_private_keysuse_scgis scgi_hosts scgi_ports wsgi_resourcestwistedssites applicationsresss((s>build/bdist.linux-i686/egg/paste/script/twisted_web2_server.pys run_twisteds4            N(spaste.deploy.converterssasbools conn_stringsTruesFalsesNones run_twisted(sasbools run_twisteds conn_string((s>build/bdist.linux-i686/egg/paste/script/twisted_web2_server.pys?s  PKSq 5wwµBB"paste/script/default_sysconfig.pyc; *'Dc@s.dZdZdZdZdZdS(s This module contains default sysconfig settings. The command object is inserted into this module as a global variable ``paste_command``, and can be used inside functions. cCsdS(s This method can modify the ``parser`` object (which is an ``optparse.OptionParser`` instance). This can be used to add new options to the command. N((sparser((s<build/bdist.linux-i686/egg/paste/script/default_sysconfig.pysadd_custom_options scCs |iSdS(sT This function can return a default filename or directory for the configuration file, if none was explicitly given. Return None to mean no preference. The first non-None returning value will be used. Pay attention to ``installer.expect_config_directory`` here, and to ``installer.default_config_filename``. N(s installersdefault_config_filename(s installer((s<build/bdist.linux-i686/egg/paste/script/default_sysconfig.pysdefault_config_filenames cCshSdS(s Returns a dictionary of variables for use later in the process (e.g., filling a configuration file). These are combined from all sysconfig files. N((s installer((s<build/bdist.linux-i686/egg/paste/script/default_sysconfig.pysinstall_variablesscCsdS(s| This is called at the very end of ``paster setup-app``. You might use it to register an application globally. N((s installers config_file((s<build/bdist.linux-i686/egg/paste/script/default_sysconfig.pyspost_setup_hook'sN(s__doc__sadd_custom_optionssdefault_config_filenamesinstall_variablesspost_setup_hook(sadd_custom_optionsspost_setup_hooksinstall_variablessdefault_config_filename((s<build/bdist.linux-i686/egg/paste/script/default_sysconfig.pys?s  PKSq 5,mZ'Z'paste/script/entrypoints.pyc; *'Dc@sdkZdkZdkZdklZlZdkZdkZdkZdk l Z defdYZ de fdYZ de fdYZd e fd YZd Zd e fd YZdS(N(sCommands BadCommand(sStringIOsEntryPointCommandc BstZdZdZdZdZeideZ e i dddd d d d d e i ddddd de i dddd d d ddZ dZ ddZ dZdZdZdZdZdZRS(Ns ENTRY_POINTs#Show information about entry pointsss Shows information about one or many entry points (you can use wildcards for entry point names). Entry points are used for Egg plugins, and are named resources -- like an application, template plugin, or other resource. Entry points have a [group] which defines what kind of object they describe, and inside groups each entry point is named. isverboses--lists-lsdestslist_entry_pointssactions store_trueshelps0List all the kinds of entry points on the systems--eggs-esshow_eggs+Show all the entry points for the given Eggs--regexs use_regexsEMake pattern match as regular expression, not just a wildcard patterncCs|iio|iSn|iio|iSn|i otdn|i|id}|i|}| otd|idnxS|D]K}|i |}d|GH|o|i |GHHnh}|i|qWdS(Ns(You must give an entry point (or --list)isNo group matched %ss[%s](sselfsoptionsslist_entry_pointssshow_eggsargss BadCommands get_patternspatternsget_groups_by_patternsgroupssgroupsget_group_descriptionsdescswrapsby_distsprint_entry_points_by_group(sselfsgroupspatternsgroupssby_distsdesc((s6build/bdist.linux-i686/egg/paste/script/entrypoints.pyscommand)s&    c Cszti}t|}|ixQ|D]I}t||}|pt|d} | i |i } | oq)nt|djod| t|dfGHn d| GH| idtgi}| D]}|t|iq~}xu| D]m}d|id|t|i|ifGH|i||} | o| io|i| idd GHqqWq)WdS( Niis%s (+ %i older versions)s%scCst|i|iS(N(scmpsasnamesb(sasb((s6build/bdist.linux-i686/egg/paste/script/entrypoints.pysMss %s%s = %ss sindenti(s pkg_resourcess Environmentsenvslists project_namesssorts project_namesdistssAssertionErrorsdists get_entry_mapsgroupsvaluessentriesslensmaxsappends_[1]sentrysnames longest_names module_namesselfsget_entry_point_descriptionsdescs descriptionswrap( sselfsgroupsentrys project_namesdistss longest_names_[1]s project_namessenvsentriessdistsdesc((s6build/bdist.linux-i686/egg/paste/script/entrypoints.pysprint_entry_points_by_group=s,     6)icCszti|}ttiidd|}gi }ti ||D]}|d||qH~}di|SdS(NsCOLUMNSiFs s (stextwrapsdedentstextsintsossenvironsgetsindentswidthsappends_[1]swrapslineslinessjoin(sselfstextsindentsliness_[1]swidthsline((s6build/bdist.linux-i686/egg/paste/script/entrypoints.pyswrapWs;cCsN| otSn|iioti|Sntiti|ti SdS(N( sssNonesselfsoptionss use_regexsrescompilesfnmatchs translatesI(sselfss((s6build/bdist.linux-i686/egg/paste/script/entrypoints.pys get_pattern^s  cCs|i|io |id}|i|}dt|GHxH|D]@}|i|}d|GH|o|i |i ddGHqEqEWdS(Nis%i entry point groups found:s[%s]sindenti( sselfs get_patternsargsspatternsget_groups_by_patternsgroupsslensgroupsget_group_descriptionsdescswraps description(sselfsgroupspatternsgroupssdesc((s6build/bdist.linux-i686/egg/paste/script/entrypoints.pyslist_entry_pointsfs  cCsti}h}x|D]}}xt||D]h}x_ti|D]N}|o|i | oq@n| o |i doq@nt ||}|i o|i id o||i qDqD~} |itii| }g}xP| D]H} tii|| |}tii|o|i | |fqqW| o6|itii|| |d||i|Snt|djotd||fn|dSdS(Ns top_level.txts#spackageisMultiple %s dirs found (%s)i(s pluginlibsfind_egg_info_dirsossgetcwdsegg_infosopenspathsjoinsfsappends_[1]s readlinesslsstrips startswithspackagessclosesdirnamesbasespossiblespkgsdsexistssselfs ensure_dirspackagesfind_dirslens BadCommand( sselfsdirnamespackagesfsdslspossibles_[1]sbasespkgspackagessegg_info((s4build/bdist.linux-i686/egg/paste/script/filemaker.pysfind_dirls"[ %cCs|ido|d }nd|jo|idtii}ndtiijo|idtii}n|itii}|d}|d o d}n<t |d djo|d}ntii |d }||fSd S( s Given the name, assume that the first argument is a path/filename combination. Return the name and dir of this. If the name ends with '.py' that will be erased. Examples: comments -> comments, '' admin/comments -> comments, 'admin' h/ab/fred -> fred, 'h/ab' s.pyis.s/isiiN( snamesendswithsreplacesosspathssepssplitspartssdirslensjoin(sselfsnamespartssdir((s4build/bdist.linux-i686/egg/paste/script/filemaker.pysparse_path_name_argss     cCs|iti}| odSntii| oU|itii|d|d||i od|i |GHn|i oti|n|o+tiitiitii|do|idd|n|otii|d}t|d }|id |id|i |GH|o+tiitiitii|do|idd|qqn'|i d jod |i |GHndS( sq Ensure that the directory exists, creating it if necessary. Respects verbosity and simulation. Adds directory to subversion if ``.svn/`` directory exists in parent, and directory was created. package If package is True, any directories created will contain a __init__.py file. Nssvn_addspackages Creating %ss.svnssvnsadds __init__.pyswbs# isDirectory already exists: %s(sdirsrstripsosssepspathsexistssselfs ensure_dirsdirnamessvn_addspackagesverbosesshortenssimulatesmkdirsjoins run_commandsinitfilesopensfswritesclose(sselfsdirssvn_addspackagesfsinitfile((s4build/bdist.linux-i686/egg/paste/script/filemaker.pys ensure_dirs, %  5  5c Csh|itii|d|d|tii| o|i o d|GHn|i o*t |d}|i ||in|o+tiitiitii|do|idd|ndSnt |d }|i}|i||jo%|i d jo d |GHndSn|ii od |GHttjo dkanti|i|id ||}di|GH|iooxpno`tdii}| o d}n|i doPn|i dodSndGHqWqdSn|i o d|GHn|i o*t |d}|i ||indS(s Ensure a file named ``filename`` exists with the given content. If ``--interactive`` has been enabled, this will ask the user what to do if a file exists with different content. ssvn_addspackages Creating %sswbs.svnssvnsaddNsrbis File %s matches expected contents0Warning: file %s does not match expected contents expected s s'Overwrite file with new content? [y/N] snsysUnknown response; Y or N pleasesOverwriting %s with new content(!sselfs ensure_dirsosspathsdirnamesfilenamessvn_addspackagesexistssverbosessimulatesopensfswritescontentsclosesjoins run_commandsreads old_contentsoptionss overwritesdifflibsNones context_diffs splitlinessdiffs interactives raw_inputsstripslowersss startswith( sselfsfilenamescontentssvn_addspackagesfsssdiffs old_content((s4build/bdist.linux-i686/egg/paste/script/filemaker.pys ensure_files^%    5               cGse|otii||}n|itio'|ttiitii Sn|SdS(s Return a shorted form of the filename (relative to the current directory), typically for displaying in messages. If ``*paths`` are present, then use os.path.join to create the full filename before shortening. N( spathssosspathsjoinsfns startswithsgetcwdslenslstripssep(sselfsfnspaths((s4build/bdist.linux-i686/egg/paste/script/filemaker.pysshortens 'c Ost|dti} t|dt} t|dt}| ptd|| o t i }n t i }y5t i |gt|d| d|dt i }WnBtj o6} | idjontd|| fnX|iod |d i|fGHn|iotSn|i\}}|io| oW|i od |d i|fGHnd |iGH|o |GHntd |n|idjo.|od GH|GHn|odGH|GHqn|SdS(sw Runs the command, respecting verbosity and simulation. Returns stdout, or None if simulating. scwdscapture_stderrsexpect_returncodesArguments not expected: %ssstderrsstdoutis-The expected executable %s was not found (%s)s Running %s %ss sError (exit code: %s)sError executing command %ssCommand error output:sCommand output:N(s popdefaultskwsossgetcwdscwdsFalsescapture_stderrsexpect_returncodesAssertionErrors subprocesssSTDOUTs stderr_pipesPIPEsPopenscmdslistsargssprocsOSErrorseserrnosselfsverbosesjoinssimulatesNones communicatesstdoutsstderrs returncode( sselfscmdsargsskwsexpect_returncodesstdoutsprocs stderr_pipesstderrsescwdscapture_stderr((s4build/bdist.linux-i686/egg/paste/script/filemaker.pys run_commandsJ         (s__name__s __module__s__doc__sFalsesTruesNones__init__s copy_filescopy_dirs load_contentsfind_dirsparse_path_name_argss ensure_dirs ensure_filesshortens run_command(((s4build/bdist.linux-i686/egg/paste/script/filemaker.pysFileOp s !  +8 cCs.||jo|Sn||}||=|SdS(N(snamesdictsdefaultsv(sdictsnamesdefaultsv((s4build/bdist.linux-i686/egg/paste/script/filemaker.pys popdefault?s   (sossglobs paste.scripts pluginlibscopydirspaste.script.commands BadCommands subprocesss ImportErrorspaste.script.utils subprocess24sobjectsFileOpsNones popdefault(sFileOps pluginlibsglobs subprocessscopydirs popdefaultsoss BadCommand((s4build/bdist.linux-i686/egg/paste/script/filemaker.pys?s    4PKSq 5gpaste/script/__init__.pyc; *'Dc@sdS(N((((s3build/bdist.linux-i686/egg/paste/script/__init__.pys?sPKSq 5_8=``paste/script/appinstall.pyc; *'Dc@sdZdkZdkZdklZdklZlZlZ dk Z dk l Z dkZdklZdklZdklZdklZd klZd klZd efd YZd efdYZdefdYZdefdYZdS(s[ Provides the two commands for preparing an application: ``prepare-app`` and ``setup-app`` N(sStringIO(sCommands BadCommandsrun(scopydir(sTemplate(s ConfigParser(s import_string(s appconfig(suuid(ssecretsAbstractInstallCommandcBstZdZedfedfedfgZeiido6ei deei i eidddd fneiid o!ei deeid fnd Z d Z ee Z d ZedZdZdZdZdZdZdZRS(Nis/etc/paste/sysconfig.pys!/usr/local/etc/paste/sysconfig.pyspaste.script.default_sysconfigsHOMEis.pastesconfigs sysconfig.pysPASTE_SYSCONFIGcCs/|i|_g}x|o|didog|_|idqn|dido3|iidt|idt dfqn|ddjoK|id| o t dn|iidt|idfqn|i |idqW|i t t|i|SdS(Nis--no-default-sysconfigs --sysconfig=s --sysconfigs9You gave --sysconfig as the last argument without a value(sselfsdefault_sysconfigss sysconfigssnew_argssargss startswithspopsinsertsTrueslens BadCommandsappendsload_sysconfigsssupersAbstractInstallCommandsrun(sselfsargssnew_args((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysrun's(   ,  " c Kstt|i|}|iddddddd|iddd dd dd |id dddd dddd|iddd dddd|idddddddddd|SdS(Ns --sysconfigsactionsappendsdests sysconfigsshelpsSystem configuration files--no-default-sysconfigs store_truesno_default_sysconfigs&Don't load the default sysconfig filess--easy-installseasy_install_opsmetavarsOPsOAn option to add if invoking easy_install (like --easy-install=exclude-scripts)s --no-installs no_installs?Don't try to install the package (it must already be installed)s-fs --find-linksseasy_install_find_linkssURLsPassed through to easy_install(ssupersAbstractInstallCommandsclssstandard_parserskwsparsers add_option(sclsskwsparser((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysstandard_parserBs0          c CsX|i}|ig|_xt|D] \}\}}|i dot i i | o|ot d|qq*nh}t||tid|} x*|iD]\}}t| ||qW|| _n=yti|} Wn&tj o}|oqq*nX|| _|iid| q*W|i}|id|dS(Ns.pys sysconfig file %s does not exists__sysconfig_%i__isadd_custom_options(sselfs sysconfigssconfigssreversessysconfig_moduless enumeratesindexsexplicitsnamesendswithsosspathsexistss BadCommandsglobssexecfilesnewsmodulesmodsitemssvaluessetattrs__file__s import_strings simple_imports ImportErrorses paste_commandsinsertsparserscall_sysconfig_functions( sselfsindexsesnamesglobssparsersexplicitsvaluesconfigssmod((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysload_sysconfigsfs6         cCs=x2|iD]'}t||ot||Sq q W|SdS(s Return the value of the given option in the first sysconfig module in which it is found, or ``default`` (None) if not found in any. N(sselfssysconfig_modulessmodshasattrsnamesgetattrsdefault(sselfsnamesdefaultsmod((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysget_sysconfig_options  cCsIgi}|iD]-}t||o|t||qq~SdS(s Return the option value for the given name in all the sysconfig modules in which is is found (``[]`` if none). N(sappends_[1]sselfssysconfig_modulessmodshasattrsnamesgetattr(sselfsnames_[1]smod((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysget_sysconfig_optionsscOs>|i|}|tjotd|n|||SdS(s Call the specified function in the first sysconfig module it is defined in. ``NameError`` if no function is found. s+Method %s not found in any sysconfig moduleN(sselfsget_sysconfig_optionsnamesvalsNones NameErrorsargsskw(sselfsnamesargsskwsval((s5build/bdist.linux-i686/egg/paste/script/appinstall.pyscall_sysconfig_functions  cOs;gi}|i|D]}||||q~SdS(sw Call all the named functions in the sysconfig modules, returning a list of the return values. N(sappends_[1]sselfsget_sysconfig_optionssnamesmethodsargsskw(sselfsnamesargsskws_[1]smethod((s5build/bdist.linux-i686/egg/paste/script/appinstall.pyscall_sysconfig_functionsscCsHh}|id|}|ix|D]}|i|q)W|SdS(se Return the folded results of calling the ``install_variables()`` functions. sinstall_variablesN(sresultsselfscall_sysconfig_functionss installersall_varssreversesvardictsupdate(sselfs installersvardictsresultsall_vars((s5build/bdist.linux-i686/egg/paste/script/appinstall.pyssysconfig_install_varss cCsiy>ti|}|iodGHdG|GdG|iGHn|SWn$tij o|ii od|GHnddg}xG|ii pgD]2}|i d od|}n|i |qWx,|iipgD]}|i d |qW|iotd |nd |GHd kl}d kl}|dddg||gti|SnXdS(se This gets a distribution object, and installs the distribution if required. sDistribution already installed:s sfromsFBecause --no-install was given, we won't try to install the package %ss-vs-ms-s--s--find-links=%ss'Must install %s, but in simulation modesMust install %s(s easy_install(ssetups script_argss-qs easy_installN(s pkg_resourcessget_distributionsreqsdistsselfsverboseslocationsDistributionNotFoundsoptionss no_installseasy_install_opsops startswithsappendseasy_install_find_linksssimulates BadCommandssetuptools.commands easy_installs setuptoolsssetup(sselfsreqssetupsdists easy_installsoptionssop((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysget_distributions6        cCs,|id|}||||}|SdS(Nspaste.app_install(sdistrosload_entry_pointsep_namesinstaller_classsep_groups installer(sselfsdistrosep_groupsep_namesinstaller_classs installer((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys get_installers(s__name__s __module__sdefault_interactivesFalsesTruesdefault_sysconfigssossenvironsgetsinsertspathsjoinsrunsstandard_parsers classmethodsload_sysconfigssNonesget_sysconfig_optionsget_sysconfig_optionsscall_sysconfig_functionscall_sysconfig_functionsssysconfig_install_varssget_distributions get_installer(((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysAbstractInstallCommands$!%!    &    sMakeConfigCommandc BstZdZeZdZdZdZdZe i de de de Z e i dd d d d d de i dd dd dd de i dd dd dddd de i dd d d dd de i dd d d dd ddZdZd Zd!Zd"ZRS(#Nis:Install a package and create a fresh config file/directorys&PACKAGE_NAME [CONFIG_FILE] [VAR=VALUE]s Note: this is an experimental command, and it will probably change in several ways by the next release. make-config is part of a two-phase installation process (the second phase is setup-app). make-config installs the package (using easy_install) and asks it to create a bare configuration file or directory (possibly filling in defaults from the extra variables you give). ssimulatesquietsno_interactives--infosactions store_truesdests show_infoshelpsQShow information on the package (after installing it), but do not write a config.s--namesstoresep_namesJThe name of the application contained in the distribution (default "main")s --entry-groupsep_groupsdefaultspaste.app_factorysZThe entry point group to install (i.e., the kind of application; default paste.app_factorys--editsedits?Edit the configuration file after generating it (using $EDITOR)s--setups run_setupsXRun setup-app immediately after generating (and possibly editing) the configuration filec Cs|id|_d|ijoK|iitj otdn|iidd\|_|i_n|ii od|i_n|i|i|_ |i |i |ii |ii|_ |ii o4t|idjotdn|i Snt|idjoGtt|id|i }| otd n|d|_n|id|_|i|i i|_|i|i |_|ii|i|id|i|id <|i|id <|ii|id <|ii |id <|iid|ii|iidti|iidti|idjoH|ii}|i!dGHx'|D]\} }d| |fGHqWn|i i$||i|it%}|ii'o|i(}n|i i)|i}|d}|ii,oI| o0dGH|i-ddt.o|i,|q]q|i,|ny|i i)|i}t0|t1 p t2d| o |tj o dGHn+dGH|ox|D]}d|GHqWndS(Nis#s9You may not give both --name and a requirement with #nameismains*With --info you can only give one argumentisdefault_config_filenames&You must give a configuration filenames project_names requirementsep_namesep_groupsapp_namesapp_instance_uuidsapp_instance_secretsVariables for installation:s %s: %rs'Config-file editing was not successful.sRun setup-app anyway?sdefaults3editable_config_files returned a string, not a listsNo config files need editings$Now you should edit the config filess %s(4sselfsargss requirementsoptionssep_namesNones BadCommandssplitsget_distributionsdistros get_installersep_groups installers show_infoslensfilterscall_sysconfig_functionss config_filescheck_config_files project_namessysconfig_install_varssvarssupdates parse_varss setdefaultslowersuuidsuuid4ssecrets secret_stringsverbosesitemss print_varsssortsnamesvalues write_configsTrues edit_successsedits run_editorseditable_config_filess setup_configss setup_configs run_setupsasksFalses filenamess isinstances basestringsAssertionErrorsfn( sselfs print_varss edit_successs setup_configss setup_configsoptionssvalues filenamessfnsname((s5build/bdist.linux-i686/egg/paste/script/appinstall.pyscommandst('         cCs|iit}|GHdS(N(sselfs installers descriptionsNonestext(sselfstext((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys show_info^scCs|iitjodSn|i}|iio/tii|dot d|qn9|i dptii| ot d|ndS(NisSThe CONFIG_FILE argument %r looks like a filename, and a directory name is expecteds/sRThe CONFIG_FILE argument %r looks like a directory name and a filename is expected( sselfs installersexpect_config_directorysNones config_filesfnsosspathssplitexts BadCommandsendswith(sselfsfn((s5build/bdist.linux-i686/egg/paste/script/appinstall.pyscheck_config_filebs  $cCstd|gdS(Ns setup-app(s run_commandsfilename(sselfsfilename((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys run_setupqscCs|ii|i}|tjo dGHtSn| o dGHtSnt|djo dGHtSnt i i d o dGHtSn|i odt i d|dfGHnt i d |d}|od t i d|fGHtSntSdS( Ns6Warning: the config file is not known (--edit ignored)s6Warning: no config files need editing (--edit ignored)isEWarning: there is more than one editable config file (--edit ignored)sEDITORs+Error: you must set $EDITOR if using --edits%s %sis $EDITOR %ss.Warning: editor %s returned with error code %i(sselfs installerseditable_config_filess config_files filenamessNonesFalsesTrueslensossenvironsgetsverbosessystemsretval(sselfs filenamessretval((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys run_editorts(  (s__name__s __module__sdefault_verbositysNonesmax_argssmin_argsssummarysusages descriptionsAbstractInstallCommandsstandard_parsersTruesparsers add_optionscommands show_infoscheck_config_files run_setups run_editor(((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysMakeConfigCommandsB            H   s SetupCommandc BsxtZdZdZdZdZdZdZei de de de Z e i dd d d d d e dddZRS(Nis)Setup an application, given a config files CONFIG_FILEs Note: this is an experimental command, and it will probably change in several ways by the next release. Setup an application according to its configuration file. This is the second part of a two-phase web application installation process (the first phase is prepare-app). The setup process may consist of things like creating directories and setting up databases. ssimulatesquiets interactives--namesactionsstoresdests section_namesdefaultshelps5The name of the section to set up (default: app:main)c Cs|id}|ii}|tjo3d|jo|idd\}}qYd}nd|j o|}d|}n|iddd}|i d od|}n|djo|d|7}n|t diddd}t i it i|}t|dt i}|ii}|ii}|ii}|i|||} | i||||i| |id | |dS( Nis#ismains:sapp:sconfig:s relative_tospost_setup_hook(sselfsargss config_specsoptionss section_namessectionsNonessplits plain_sections startswithslens config_filesosspathsjoinsgetcwds appconfigsconfscontextsentry_point_namesep_namesprotocolsep_groups distributionsdists get_installers installers setup_configssysconfig_install_varsscall_sysconfig_functions( sselfs config_files plain_sectionsep_namesconfs config_specsdistsep_groupssections installer((s5build/bdist.linux-i686/egg/paste/script/appinstall.pyscommands.          (s__name__s __module__sdefault_verbositysmax_argssmin_argsssummarysusages descriptionsAbstractInstallCommandsstandard_parsersTruesparsers add_optionsNonescommand(((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys SetupCommands   s InstallercBsbtZdZeZeZdZdZdZ dZ dZ dZ dZ dZRS( sV Abstract base class for installers, and also a generic installer that will run off config files in the .egg-info directory of a distribution. Packages that simply refer to this installer can provide a file ``*.egg-info/paste_deploy_config.ini_tmpl`` that will be interpreted by Cheetah. They can also provide ``websetup`` modules with a ``setup_app(command, conf, vars)`` (or the now-deprecated ``setup_config(command, filename, section, vars)``) function, that will be called. In the future other functions or configuration files may be called. cCs||_||_||_dS(N(sdistsselfsep_groupsep_name(sselfsdistsep_groupsep_name((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys__init__s  cCsdSdS(NsAn application((sselfsconfig((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys descriptionscCs |i||i||dS(s Writes the content to the filename (directory or single file). You should use the ``command`` object, which respects things like simulation and interactive. ``vars`` is a dictionary of user-provided variables. N(scommands ensure_filesfilenamesselfsconfig_contentsvars(sselfscommandsfilenamesvars((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys write_configscCs|i o |gSntSdS(s> Return a list of filenames; this is primarily used when the filename is treated as a directory and several configuration files are created. The default implementation returns the file itself. Return None if you don't know what files should be edited on installation. N(sselfsexpect_config_directorysfilenamesNone(sselfsfilename((s5build/bdist.linux-i686/egg/paste/script/appinstall.pyseditable_config_filess  cCszd}|ii| o(|io d|GHn|i|Snt|ii |d|g}t i |||SdS(s Called by ``self.write_config``, this returns the text content for the config file, given the provided variables. The default implementation reads ``Package.egg-info/paste_deploy_config.ini_tmpl`` and fills it with the variables. spaste_deploy_config.ini_tmpls No %s founds searchListN( s meta_namesselfsdists has_metadatascommandsverboses simple_configsvarssTemplates get_metadatastmplscopydirs careful_sub(sselfscommandsvarsstmpls meta_name((s5build/bdist.linux-i686/egg/paste/script/appinstall.pysconfig_contents  cCs?|idjod|i}nd}d|ii|fSdS(sO Return a very simple configuration file for this application. smains#ss[app:main] use = egg:%s%s N(sselfsep_namesdists project_name(sselfsvarssep_name((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys simple_configs cCs%x|iidD] }|i}| p |idoqn|d}yti|}Wn3t j o'|i djo d|GHqqnX|i o d|GHnt |do |i|i||||qt |do|i||||qd |i|ifGHqWd S( s Called to setup an application, given its configuration file/directory. The default implementation calls ``package.websetup.setup_config(command, filename, section, vars)`` or ``package.websetup.setup_app(command, config, vars)`` With ``setup_app`` the ``config`` object is a dictionary with the extra attributes ``global_conf``, ``local_conf`` and ``filename`` s top_level.txts#s .websetupisNo %s module found for setupsRunning setup_config() from %ss setup_apps setup_configs4No setup_app() or setup_config() function in %s (%s)N(sselfsdistsget_metadata_linesslinesstrips startswithsmod_names import_strings import_modulesmods ImportErrorscommandsverboseshasattrs_call_setup_apps setup_appsfilenamessectionsvarss setup_configs__name__s__file__(sselfscommandsfilenamessectionsvarssmod_nameslinesmod((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys setup_configs(       cCsrtii|}d|jo|iddd}nd||f}t|}||_||||dS(Ns:is config:%s#%s( sosspathsabspathsfilenamessectionssplitsconfs appconfigsfuncscommandsvars(sselfsfuncscommandsfilenamessectionsvarssconf((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys_call_setup_appAs   (s__name__s __module__s__doc__sFalsesexpect_config_directorysNonesdefault_config_filenames__init__s descriptions write_configseditable_config_filessconfig_contents simple_configs setup_configs_call_setup_app(((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys Installers     $(s__doc__sossnews cStringIOsStringIOspaste.script.commandsCommands BadCommandsruns run_commandspaste.script.templatesspastes paste.scriptscopydirs pkg_resourcessCheetah.TemplatesTemplates ConfigParsers paste.utils import_strings paste.deploys appconfigspaste.script.utilsuuidssecretsAbstractInstallCommandsMakeConfigCommands SetupCommandsobjects Installer(s SetupCommandsuuidsStringIOspastes BadCommands pkg_resourcessMakeConfigCommands import_stringssecretscopydirsCommandsTemplates InstallersAbstractInstallCommandsnewsoss appconfigs run_commands ConfigParser((s5build/bdist.linux-i686/egg/paste/script/appinstall.pys?s"            9PKSq 5۰evv!paste/script/wsgiutils_server.pyc; *'Dc@s-dklZdklZdddZdS((sensure_port_cleanup(s TransLoggers localhostic Csdkl}dk}t|}t|}t||fgddddhd|<}|i ||f|}|i id|||idS(N(s wsgiServersmaxtriesis sleeptimef0.5ss$Starting HTTP server on http://%s:%s(s wsgiutilss wsgiServersloggings TransLoggerswsgi_apps logged_appsintsportsensure_port_cleanupshostsapp_maps WSGIServersserversloggersinfos serve_forever( swsgi_apps global_confshostsportsloggings wsgiServersserversapp_maps logged_app((s;build/bdist.linux-i686/egg/paste/script/wsgiutils_server.pys run_servers      N(spaste.script.servesensure_port_cleanupspaste.transloggers TransLoggers run_server(s TransLoggersensure_port_cleanups run_server((s;build/bdist.linux-i686/egg/paste/script/wsgiutils_server.pys?s  PKSq 5u33paste/script/bool_optparse.pyc; *'Dc@s\dZdkZy eiZWn ej odklZnXdeifdYZdS(s A subclass of ``optparse.OptionParser`` that allows boolean long options (like ``--verbose``) to also take arguments (like ``--verbose=true``). Arguments *must* use ``=``. N(sgettextsBoolOptionParsercBstZdZRS(Nc Cs|id} d| jo2| idd\}}|id|t}n | }t }|i |}|i |}|io|i}t||joI|djo|itd|q%|itd||fq|djo|id}qt|d|!}|d|5n|o|dii}|dd5|dddd d d fjo t}q|d d ddddfjodSq|itd|nt}|i||||dS(Nis=is%s option requires an arguments%s option requires %d argumentsstruesyessons1systsfalsesnosoffs0snsfs1%s option takes a boolean value only (true/false)(srargsspopsargssplitsoptsnext_argsinsertsTrueshad_explicit_valuesFalsesselfs_match_long_opts _long_optsoptions takes_valuesnargsslenserrors_svaluestupleslowersstripsNonesprocesssvalues( sselfsrargssvaluessoptsoptionsnext_argsnargsshad_explicit_valuesvaluesarg((s8build/bdist.linux-i686/egg/paste/script/bool_optparse.pys_process_long_opts:      !   (s__name__s __module__s_process_long_opt(((s8build/bdist.linux-i686/egg/paste/script/bool_optparse.pysBoolOptionParsers(s__doc__soptparses_sAttributeErrorsgettexts OptionParsersBoolOptionParser(soptparsesBoolOptionParsers_((s8build/bdist.linux-i686/egg/paste/script/bool_optparse.pys?s   PKSq 5XLw33paste/script/copydir.pyc; *'Dc@sdkZdkZeiddfjodklZn dkZdkZdkZdkZe a y dk Z Wn e j odkl Z nXdkZdeeeeedZe adZdZd Zd Zd ed Zd ZdZdZdZe dZdZhde <de<de<dd<de<de<de<de