Imported from SVN by Bitbucket
This commit is contained in:
52
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/PKG-INFO
Executable file
52
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/PKG-INFO
Executable file
@@ -0,0 +1,52 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: PasteScript
|
||||
Version: 1.7.4.2
|
||||
Summary: A pluggable command-line frontend, including commands to setup package file layouts
|
||||
Home-page: http://pythonpaste.org/script/
|
||||
Author: Ian Bicking
|
||||
Author-email: ianb@colorstudy.com
|
||||
License: MIT
|
||||
Description: This is a pluggable command-line tool.
|
||||
|
||||
It includes some built-in features;
|
||||
|
||||
* Create file layouts for packages. For instance, ``paste create
|
||||
--template=basic_package MyPackage`` will create a `setuptools
|
||||
<http://peak.telecommunity.com/DevCenter/setuptools>`_-ready
|
||||
file layout.
|
||||
|
||||
* Serving up web applications, with configuration based on
|
||||
`paste.deploy <http://pythonpaste.org/deploy/paste-deploy.html>`_.
|
||||
|
||||
The latest version is available in a `Mercurial repository
|
||||
<http://bitbucket.org/ianb/pastescript/>`_.
|
||||
|
||||
For the latest changes see the `news file
|
||||
<http://pythonpaste.org/script/news.html>`_.
|
||||
|
||||
Changes in 1.7.4.2
|
||||
------------------
|
||||
|
||||
* 1.7.4 had package release problems, was reverted; 1.7.4.1 also had
|
||||
package problems.
|
||||
|
||||
* Include special ``here`` and ``__file__`` default vars for logging
|
||||
config files, similar to PasteDeploy config loading.
|
||||
|
||||
* Allow Jython to import various bits from ``paste.script.command`` and
|
||||
``paste.script.copydir`` without throwing an import error (subprocess
|
||||
module cannot be imported on Jython). This allows PasteScript to work
|
||||
minimally on Jython, although execution will fail for
|
||||
``command.run_command`` and ``copydir.copydir``.
|
||||
|
||||
|
||||
Keywords: web wsgi setuptools framework command-line setup
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Topic :: Internet :: WWW/HTTP
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Framework :: Paste
|
||||
92
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/SOURCES.txt
Executable file
92
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/SOURCES.txt
Executable file
@@ -0,0 +1,92 @@
|
||||
MANIFEST.in
|
||||
setup.cfg
|
||||
setup.py
|
||||
PasteScript.egg-info/PKG-INFO
|
||||
PasteScript.egg-info/SOURCES.txt
|
||||
PasteScript.egg-info/dependency_links.txt
|
||||
PasteScript.egg-info/entry_points.txt
|
||||
PasteScript.egg-info/namespace_packages.txt
|
||||
PasteScript.egg-info/not-zip-safe
|
||||
PasteScript.egg-info/requires.txt
|
||||
PasteScript.egg-info/top_level.txt
|
||||
docs/conf.py
|
||||
docs/developer.txt
|
||||
docs/index.txt
|
||||
docs/license.txt
|
||||
docs/news.txt
|
||||
docs/_build/developer.html
|
||||
docs/_build/genindex.html
|
||||
docs/_build/index.html
|
||||
docs/_build/license.html
|
||||
docs/_build/news.html
|
||||
docs/_build/py-modindex.html
|
||||
docs/_build/search.html
|
||||
docs/_build/modules/checkperms.html
|
||||
docs/_build/modules/cherrypy_server.html
|
||||
docs/_build/modules/command.html
|
||||
docs/_build/modules/copydir.html
|
||||
docs/_build/modules/filemaker.html
|
||||
docs/_build/modules/templates.html
|
||||
docs/_build/modules/testapp.html
|
||||
docs/_build/modules/util.secret.html
|
||||
docs/modules/checkperms.txt
|
||||
docs/modules/cherrypy_server.txt
|
||||
docs/modules/command.txt
|
||||
docs/modules/copydir.txt
|
||||
docs/modules/filemaker.txt
|
||||
docs/modules/templates.txt
|
||||
docs/modules/testapp.txt
|
||||
docs/modules/util.secret.txt
|
||||
paste/__init__.py
|
||||
paste/script/__init__.py
|
||||
paste/script/appinstall.py
|
||||
paste/script/bool_optparse.py
|
||||
paste/script/cgi_server.py
|
||||
paste/script/checkperms.py
|
||||
paste/script/cherrypy_server.py
|
||||
paste/script/command.py
|
||||
paste/script/copydir.py
|
||||
paste/script/create_distro.py
|
||||
paste/script/default_sysconfig.py
|
||||
paste/script/entrypoints.py
|
||||
paste/script/epdesc.py
|
||||
paste/script/exe.py
|
||||
paste/script/filemaker.py
|
||||
paste/script/flup_server.py
|
||||
paste/script/grep.py
|
||||
paste/script/help.py
|
||||
paste/script/interfaces.py
|
||||
paste/script/pluginlib.py
|
||||
paste/script/request.py
|
||||
paste/script/serve.py
|
||||
paste/script/templates.py
|
||||
paste/script/testapp.py
|
||||
paste/script/twisted_web2_server.py
|
||||
paste/script/wsgiutils_server.py
|
||||
paste/script/paster-templates/basic_package/setup.cfg
|
||||
paste/script/paster-templates/basic_package/setup.py_tmpl
|
||||
paste/script/paster-templates/basic_package/+package+/__init__.py
|
||||
paste/script/paster-templates/basic_package/docs/license.txt_tmpl
|
||||
paste/script/util/__init__.py
|
||||
paste/script/util/logging_config.py
|
||||
paste/script/util/secret.py
|
||||
paste/script/util/string24.py
|
||||
paste/script/util/subprocess24.py
|
||||
paste/script/util/uuid.py
|
||||
tests/__init__.py
|
||||
tests/test_egg_finder.py
|
||||
tests/test_logging_config.py
|
||||
tests/test_plugin_adder.py
|
||||
tests/test_template_introspect.py
|
||||
tests/appsetup/__init__.py
|
||||
tests/appsetup/test_make_project.py
|
||||
tests/appsetup/testfiles/admin_index.py
|
||||
tests/appsetup/testfiles/conftest.py
|
||||
tests/appsetup/testfiles/iscape.txt
|
||||
tests/appsetup/testfiles/test_forbidden.py
|
||||
tests/fake_packages/FakePlugin.egg/setup.py
|
||||
tests/fake_packages/FakePlugin.egg/FakePlugin.egg-info/entry_points.txt
|
||||
tests/fake_packages/FakePlugin.egg/FakePlugin.egg-info/paster_plugins.txt
|
||||
tests/fake_packages/FakePlugin.egg/FakePlugin.egg-info/top_level.txt
|
||||
tests/fake_packages/FakePlugin.egg/fakeplugin/__init__.py
|
||||
tests/sample_templates/test1.txt
|
||||
1
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/dependency_links.txt
Executable file
1
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/dependency_links.txt
Executable file
@@ -0,0 +1 @@
|
||||
|
||||
59
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/entry_points.txt
Executable file
59
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/entry_points.txt
Executable file
@@ -0,0 +1,59 @@
|
||||
|
||||
[paste.global_paster_command]
|
||||
help=paste.script.help:HelpCommand
|
||||
create=paste.script.create_distro:CreateDistroCommand [Templating]
|
||||
serve=paste.script.serve:ServeCommand [Config]
|
||||
request=paste.script.request:RequestCommand [Config]
|
||||
post=paste.script.request:RequestCommand [Config]
|
||||
exe=paste.script.exe:ExeCommand
|
||||
points=paste.script.entrypoints:EntryPointCommand
|
||||
make-config=paste.script.appinstall:MakeConfigCommand
|
||||
setup-app=paste.script.appinstall:SetupCommand
|
||||
|
||||
[paste.paster_command]
|
||||
grep = paste.script.grep:GrepCommand
|
||||
|
||||
[paste.paster_create_template]
|
||||
basic_package=paste.script.templates:BasicPackage
|
||||
|
||||
[paste.server_runner]
|
||||
wsgiutils=paste.script.wsgiutils_server:run_server [WSGIUtils]
|
||||
flup_ajp_thread=paste.script.flup_server:run_ajp_thread [Flup]
|
||||
flup_ajp_fork=paste.script.flup_server:run_ajp_fork [Flup]
|
||||
flup_fcgi_thread=paste.script.flup_server:run_fcgi_thread [Flup]
|
||||
flup_fcgi_fork=paste.script.flup_server:run_fcgi_fork [Flup]
|
||||
flup_scgi_thread=paste.script.flup_server:run_scgi_thread [Flup]
|
||||
flup_scgi_fork=paste.script.flup_server:run_scgi_fork [Flup]
|
||||
cgi=paste.script.cgi_server:paste_run_cgi
|
||||
cherrypy=paste.script.cherrypy_server:cpwsgi_server
|
||||
twisted=paste.script.twisted_web2_server:run_twisted
|
||||
|
||||
[paste.app_factory]
|
||||
test=paste.script.testapp:make_test_application
|
||||
|
||||
[paste.entry_point_description]
|
||||
paste.entry_point_description = paste.script.epdesc:MetaEntryPointDescription
|
||||
paste.paster_create_template = paste.script.epdesc:CreateTemplateDescription
|
||||
paste.paster_command = paste.script.epdesc:PasterCommandDescription
|
||||
paste.global_paster_command = paste.script.epdesc:GlobalPasterCommandDescription
|
||||
paste.app_install = paste.script.epdesc:AppInstallDescription
|
||||
|
||||
# These aren't part of Paste Script particularly, but
|
||||
# we'll document them here
|
||||
console_scripts = paste.script.epdesc:ConsoleScriptsDescription
|
||||
# @@: Need non-console scripts...
|
||||
distutils.commands = paste.script.epdesc:DistutilsCommandsDescription
|
||||
distutils.setup_keywords = paste.script.epdesc:SetupKeywordsDescription
|
||||
egg_info.writers = paste.script.epdesc:EggInfoWriters
|
||||
# @@: Not sure what this does:
|
||||
#setuptools.file_finders = paste.script.epdesc:SetuptoolsFileFinders
|
||||
|
||||
[console_scripts]
|
||||
paster=paste.script.command:run
|
||||
|
||||
[distutils.setup_keywords]
|
||||
paster_plugins = setuptools.dist:assert_string_list
|
||||
|
||||
[egg_info.writers]
|
||||
paster_plugins.txt = setuptools.command.egg_info:write_arg
|
||||
|
||||
1
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/namespace_packages.txt
Executable file
1
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/namespace_packages.txt
Executable file
@@ -0,0 +1 @@
|
||||
paste
|
||||
1
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/not-zip-safe
Executable file
1
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/not-zip-safe
Executable file
@@ -0,0 +1 @@
|
||||
|
||||
21
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/requires.txt
Executable file
21
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/requires.txt
Executable file
@@ -0,0 +1,21 @@
|
||||
Paste>=1.3
|
||||
PasteDeploy
|
||||
|
||||
[Templating]
|
||||
|
||||
|
||||
[Config]
|
||||
PasteDeploy
|
||||
|
||||
[WSGIUtils]
|
||||
WSGIUtils
|
||||
|
||||
[Flup]
|
||||
Flup
|
||||
|
||||
[Cheetah]
|
||||
Cheetah
|
||||
|
||||
[Paste]
|
||||
PasteDeploy
|
||||
Cheetah
|
||||
2
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/top_level.txt
Executable file
2
PasteScript-1.7.4.2-py2.6.egg/EGG-INFO/top_level.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
tests
|
||||
paste
|
||||
18
PasteScript-1.7.4.2-py2.6.egg/paste/__init__.py
Executable file
18
PasteScript-1.7.4.2-py2.6.egg/paste/__init__.py
Executable file
@@ -0,0 +1,18 @@
|
||||
# (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
|
||||
try:
|
||||
import pkg_resources
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
except ImportError:
|
||||
# don't prevent use of paste if pkg_resources isn't installed
|
||||
from pkgutil import extend_path
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
|
||||
try:
|
||||
import modulefinder
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
for p in __path__:
|
||||
modulefinder.AddPackagePath(__name__, p)
|
||||
|
||||
3
PasteScript-1.7.4.2-py2.6.egg/paste/script/__init__.py
Executable file
3
PasteScript-1.7.4.2-py2.6.egg/paste/script/__init__.py
Executable file
@@ -0,0 +1,3 @@
|
||||
# (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
|
||||
#
|
||||
615
PasteScript-1.7.4.2-py2.6.egg/paste/script/appinstall.py
Executable file
615
PasteScript-1.7.4.2-py2.6.egg/paste/script/appinstall.py
Executable file
@@ -0,0 +1,615 @@
|
||||
# (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 sys
|
||||
if sys.version_info < (2, 4):
|
||||
from paste.script.util import string24 as string
|
||||
else:
|
||||
import string
|
||||
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
|
||||
Cheetah = None
|
||||
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)
|
||||
self.logging_file_config(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
|
||||
if dist is None:
|
||||
raise BadCommand(
|
||||
"The section %r is not the application (probably a filter). You should add #section_name, where section_name is the section that configures your application" % plain_section)
|
||||
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
|
||||
|
||||
# Set this to true to use Cheetah to fill your templates, or false
|
||||
# to not do so:
|
||||
use_cheetah = True
|
||||
|
||||
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.
|
||||
"""
|
||||
global Cheetah
|
||||
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)
|
||||
return self.template_renderer(
|
||||
self.dist.get_metadata(meta_name), vars, filename=meta_name)
|
||||
|
||||
def template_renderer(self, content, vars, filename=None):
|
||||
"""
|
||||
Subclasses may override this to provide different template
|
||||
substitution (e.g., use a different template engine).
|
||||
"""
|
||||
if self.use_cheetah:
|
||||
import Cheetah.Template
|
||||
tmpl = Cheetah.Template.Template(content,
|
||||
searchList=[vars])
|
||||
return copydir.careful_sub(
|
||||
tmpl, vars, filename)
|
||||
else:
|
||||
tmpl = string.Template(content)
|
||||
return tmpl.substitute(vars)
|
||||
|
||||
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``
|
||||
"""
|
||||
modules = [
|
||||
line.strip()
|
||||
for line in self.dist.get_metadata_lines('top_level.txt')
|
||||
if line.strip() and not line.strip().startswith('#')]
|
||||
if not modules:
|
||||
print 'No modules are listed in top_level.txt'
|
||||
print 'Try running python setup.py egg_info to regenerate that file'
|
||||
for mod_name in modules:
|
||||
mod_name = mod_name + '.websetup'
|
||||
mod = import_string.try_import_module(mod_name)
|
||||
if mod is None:
|
||||
continue
|
||||
if hasattr(mod, 'setup_app'):
|
||||
if command.verbose:
|
||||
print 'Running setup_app() from %s' % mod_name
|
||||
self._call_setup_app(
|
||||
mod.setup_app, command, filename, section, vars)
|
||||
elif hasattr(mod, 'setup_config'):
|
||||
if command.verbose:
|
||||
print 'Running setup_config() from %s' % mod_name
|
||||
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)
|
||||
|
||||
60
PasteScript-1.7.4.2-py2.6.egg/paste/script/bool_optparse.py
Executable file
60
PasteScript-1.7.4.2-py2.6.egg/paste/script/bool_optparse.py
Executable file
@@ -0,0 +1,60 @@
|
||||
# (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)
|
||||
71
PasteScript-1.7.4.2-py2.6.egg/paste/script/cgi_server.py
Executable file
71
PasteScript-1.7.4.2-py2.6.egg/paste/script/cgi_server.py
Executable file
@@ -0,0 +1,71 @@
|
||||
# (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
|
||||
|
||||
## FIXME: this should be deprecated in favor of wsgiref
|
||||
|
||||
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()
|
||||
441
PasteScript-1.7.4.2-py2.6.egg/paste/script/checkperms.py
Executable file
441
PasteScript-1.7.4.2-py2.6.egg/paste/script/checkperms.py
Executable file
@@ -0,0 +1,441 @@
|
||||
# (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
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
import grp
|
||||
import pwd
|
||||
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.
|
||||
"""
|
||||
import grp
|
||||
import pwd
|
||||
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()
|
||||
|
||||
101
PasteScript-1.7.4.2-py2.6.egg/paste/script/cherrypy_server.py
Executable file
101
PasteScript-1.7.4.2-py2.6.egg/paste/script/cherrypy_server.py
Executable file
@@ -0,0 +1,101 @@
|
||||
"""
|
||||
Entry point for CherryPy's WSGI server
|
||||
"""
|
||||
import paste.script.wsgiserver as wsgiserver
|
||||
|
||||
def cpwsgi_server(app, global_conf=None, host='127.0.0.1', port=None,
|
||||
ssl_pem=None, protocol_version=None, numthreads=None,
|
||||
server_name=None, max=None, request_queue_size=None,
|
||||
timeout=None):
|
||||
"""
|
||||
Serves the specified WSGI app via CherryPyWSGIServer.
|
||||
|
||||
``app``
|
||||
|
||||
The WSGI 'application callable'; multiple WSGI applications
|
||||
may be passed as (script_name, callable) pairs.
|
||||
|
||||
``host``
|
||||
|
||||
This is the ipaddress to bind to (or a hostname if your
|
||||
nameserver is properly configured). This defaults to
|
||||
127.0.0.1, which is not a public interface.
|
||||
|
||||
``port``
|
||||
|
||||
The port to run on, defaults to 8080 for HTTP, or 4443 for
|
||||
HTTPS. This can be a string or an integer value.
|
||||
|
||||
``ssl_pem``
|
||||
|
||||
This an optional SSL certificate file (via OpenSSL) You can
|
||||
generate a self-signed test PEM certificate file as follows:
|
||||
|
||||
$ openssl genrsa 1024 > host.key
|
||||
$ chmod 400 host.key
|
||||
$ openssl req -new -x509 -nodes -sha1 -days 365 \\
|
||||
-key host.key > host.cert
|
||||
$ cat host.cert host.key > host.pem
|
||||
$ chmod 400 host.pem
|
||||
|
||||
``protocol_version``
|
||||
|
||||
The protocol used by the server, by default ``HTTP/1.1``.
|
||||
|
||||
``numthreads``
|
||||
|
||||
The number of worker threads to create.
|
||||
|
||||
``server_name``
|
||||
|
||||
The string to set for WSGI's SERVER_NAME environ entry.
|
||||
|
||||
``max``
|
||||
|
||||
The maximum number of queued requests. (defaults to -1 = no
|
||||
limit).
|
||||
|
||||
``request_queue_size``
|
||||
|
||||
The 'backlog' argument to socket.listen(); specifies the
|
||||
maximum number of queued connections.
|
||||
|
||||
``timeout``
|
||||
|
||||
The timeout in seconds for accepted connections.
|
||||
"""
|
||||
is_ssl = False
|
||||
if ssl_pem:
|
||||
port = port or 4443
|
||||
is_ssl = True
|
||||
|
||||
if not port:
|
||||
if ':' in host:
|
||||
host, port = host.split(':', 1)
|
||||
else:
|
||||
port = 8080
|
||||
bind_addr = (host, int(port))
|
||||
|
||||
kwargs = {}
|
||||
for var_name in ('numthreads', 'max', 'request_queue_size', 'timeout'):
|
||||
var = locals()[var_name]
|
||||
if var is not None:
|
||||
kwargs[var_name] = int(var)
|
||||
|
||||
server = wsgiserver.CherryPyWSGIServer(bind_addr, app,
|
||||
server_name=server_name, **kwargs)
|
||||
server.ssl_certificate = server.ssl_private_key = ssl_pem
|
||||
if protocol_version:
|
||||
server.protocol = protocol_version
|
||||
|
||||
try:
|
||||
protocol = is_ssl and 'https' or 'http'
|
||||
if host == '0.0.0.0':
|
||||
print 'serving on 0.0.0.0:%s view at %s://127.0.0.1:%s' % \
|
||||
(port, protocol, port)
|
||||
else:
|
||||
print "serving on %s://%s:%s" % (protocol, host, port)
|
||||
server.start()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
server.stop()
|
||||
return server
|
||||
818
PasteScript-1.7.4.2-py2.6.egg/paste/script/command.py
Executable file
818
PasteScript-1.7.4.2-py2.6.egg/paste/script/command.py
Executable file
@@ -0,0 +1,818 @@
|
||||
# (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
|
||||
import getpass
|
||||
try:
|
||||
import subprocess
|
||||
except ImportError:
|
||||
try:
|
||||
from paste.script.util import subprocess24 as subprocess
|
||||
except ImportError:
|
||||
subprocess = None # jython
|
||||
|
||||
difflib = None
|
||||
|
||||
if sys.version_info >= (2, 6):
|
||||
from logging.config import fileConfig
|
||||
else:
|
||||
# Use our custom fileConfig -- 2.5.1's with a custom Formatter class
|
||||
# and less strict whitespace (which were incorporated into 2.6's)
|
||||
from paste.script.util.logging_config import fileConfig
|
||||
|
||||
class BadCommand(Exception):
|
||||
|
||||
def __init__(self, message, exit_code=2):
|
||||
self.message = message
|
||||
self.exit_code = exit_code
|
||||
Exception.__init__(self, message)
|
||||
|
||||
def _get_message(self):
|
||||
"""Getter for 'message'; needed only to override deprecation
|
||||
in BaseException."""
|
||||
return self.__message
|
||||
|
||||
def _set_message(self, value):
|
||||
"""Setter for 'message'; needed only to override deprecation
|
||||
in BaseException."""
|
||||
self.__message = value
|
||||
|
||||
# BaseException.message has been deprecated since Python 2.6.
|
||||
# To prevent DeprecationWarning from popping up over this
|
||||
# pre-existing attribute, use a new property that takes lookup
|
||||
# precedence.
|
||||
message = property(_get_message, _set_message)
|
||||
|
||||
class NoDefault(object):
|
||||
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 = self._prog_name()
|
||||
if self.description:
|
||||
desc = self.description
|
||||
desc = textwrap.dedent(desc)
|
||||
self.parser.description = desc
|
||||
self.options, self.args = self.parser.parse_args(args)
|
||||
|
||||
def _prog_name(self):
|
||||
return '%s %s' % (os.path.basename(sys.argv[0]), self.command_name)
|
||||
|
||||
########################################
|
||||
## 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, should_echo=True):
|
||||
"""
|
||||
Prompt the user for a variable.
|
||||
"""
|
||||
if default is not NoDefault:
|
||||
prompt += ' [%r]' % default
|
||||
prompt += ': '
|
||||
while 1:
|
||||
if should_echo:
|
||||
prompt_method = raw_input
|
||||
else:
|
||||
prompt_method = getpass.getpass
|
||||
response = prompt_method(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.svn_command('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.svn_command('add', filename,
|
||||
warn_returncode=True)
|
||||
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: ``-*- <marker_name>[:]? -*-``, 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
|
||||
''.join(lines[i+1:]).strip().startswith(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
|
||||
"""
|
||||
if subprocess is None:
|
||||
raise RuntimeError('Environment does not support subprocess '
|
||||
'module, cannot run command.')
|
||||
cmd = self.quote_first_command_arg(cmd)
|
||||
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)
|
||||
warn_returncode = popdefault(kw, 'warn_returncode', False)
|
||||
if warn_returncode:
|
||||
expect_returncode = True
|
||||
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
|
||||
elif proc.returncode and warn_returncode:
|
||||
print 'Warning: command failed (%s %s)' % (cmd, ' '.join(args))
|
||||
print 'Exited with code %s' % proc.returncode
|
||||
return stdout
|
||||
|
||||
def quote_first_command_arg(self, arg):
|
||||
"""
|
||||
There's a bug in Windows when running an executable that's
|
||||
located inside a path with a space in it. This method handles
|
||||
that case, or on non-Windows systems or an executable with no
|
||||
spaces, it just leaves well enough alone.
|
||||
"""
|
||||
if (sys.platform != 'win32'
|
||||
or ' ' not in arg):
|
||||
# Problem does not apply:
|
||||
return arg
|
||||
try:
|
||||
import win32api
|
||||
except ImportError:
|
||||
raise ValueError(
|
||||
"The executable %r contains a space, and in order to "
|
||||
"handle this issue you must have the win32api module "
|
||||
"installed" % arg)
|
||||
arg = win32api.GetShortPathName(arg)
|
||||
return arg
|
||||
|
||||
_svn_failed = False
|
||||
|
||||
def svn_command(self, *args, **kw):
|
||||
"""
|
||||
Run an svn command, but don't raise an exception if it fails.
|
||||
"""
|
||||
try:
|
||||
return self.run_command('svn', *args, **kw)
|
||||
except OSError, e:
|
||||
if not self._svn_failed:
|
||||
print 'Unable to run svn command (%s); proceeding anyway' % e
|
||||
self._svn_failed = True
|
||||
|
||||
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.svn_command('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)
|
||||
|
||||
def logging_file_config(self, config_file):
|
||||
"""
|
||||
Setup logging via the logging module's fileConfig function with the
|
||||
specified ``config_file``, if applicable.
|
||||
|
||||
ConfigParser defaults are specified for the special ``__file__``
|
||||
and ``here`` variables, similar to PasteDeploy config loading.
|
||||
"""
|
||||
parser = ConfigParser.ConfigParser()
|
||||
parser.read([config_file])
|
||||
if parser.has_section('loggers'):
|
||||
config_file = os.path.abspath(config_file)
|
||||
fileConfig(config_file, dict(__file__=config_file,
|
||||
here=os.path.dirname(config_file)))
|
||||
|
||||
class NotFoundCommand(Command):
|
||||
|
||||
def run(self, args):
|
||||
#for name, value in os.environ.items():
|
||||
# print '%s: %s' % (name, value)
|
||||
#print sys.argv
|
||||
print ('Command %r not known (you may need to run setup.py egg_info)'
|
||||
% 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
|
||||
438
PasteScript-1.7.4.2-py2.6.egg/paste/script/copydir.py
Executable file
438
PasteScript-1.7.4.2-py2.6.egg/paste/script/copydir.py
Executable file
@@ -0,0 +1,438 @@
|
||||
# (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
|
||||
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:
|
||||
try:
|
||||
from paste.script.util import subprocess24 as subprocess
|
||||
except ImportError:
|
||||
subprocess = None # jython
|
||||
import inspect
|
||||
|
||||
class SkipTemplate(Exception):
|
||||
"""
|
||||
Raised to indicate that the template should not be copied over.
|
||||
Raise this exception during the substitution of your template
|
||||
"""
|
||||
|
||||
def copy_dir(source, dest, vars, verbosity, simulate, indent=0,
|
||||
use_cheetah=False, sub_vars=True, interactive=False,
|
||||
svn_add=True, overwrite=True, template_renderer=None):
|
||||
"""
|
||||
Copies the ``source`` directory to the ``dest`` directory.
|
||||
|
||||
``vars``: A dictionary of variables to use in any substitutions.
|
||||
|
||||
``verbosity``: Higher numbers will show more about what is happening.
|
||||
|
||||
``simulate``: If true, then don't actually *do* anything.
|
||||
|
||||
``indent``: Indent any messages by this amount.
|
||||
|
||||
``sub_vars``: If true, variables in ``_tmpl`` files and ``+var+``
|
||||
in filenames will be substituted.
|
||||
|
||||
``use_cheetah``: If true, then any templates encountered will be
|
||||
substituted with Cheetah. Otherwise ``template_renderer`` or
|
||||
``string.Template`` will be used for templates.
|
||||
|
||||
``svn_add``: If true, any files written out in directories with
|
||||
``.svn/`` directories will be added (via ``svn add``).
|
||||
|
||||
``overwrite``: If false, then don't every overwrite anything.
|
||||
|
||||
``interactive``: If you are overwriting a file and interactive is
|
||||
true, then ask before overwriting.
|
||||
|
||||
``template_renderer``: This is a function for rendering templates
|
||||
(if you don't want to use Cheetah or string.Template). It should
|
||||
have the signature ``template_renderer(content_as_string,
|
||||
vars_as_dict, filename=filename)``.
|
||||
"""
|
||||
# This allows you to use a leading +dot+ in filenames which would
|
||||
# otherwise be skipped because leading dots make the file hidden:
|
||||
vars.setdefault('dot', '.')
|
||||
vars.setdefault('plus', '+')
|
||||
use_pkg_resources = isinstance(source, tuple)
|
||||
if use_pkg_resources:
|
||||
names = pkg_resources.resource_listdir(source[0], source[1])
|
||||
else:
|
||||
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:
|
||||
if use_pkg_resources:
|
||||
full = '/'.join([source[1], name])
|
||||
else:
|
||||
full = os.path.join(source, name)
|
||||
reason = should_skip_file(name)
|
||||
if reason:
|
||||
if verbosity >= 2:
|
||||
reason = pad + reason % {'filename': full}
|
||||
print reason
|
||||
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 use_pkg_resources and pkg_resources.resource_isdir(source[0], full):
|
||||
if verbosity:
|
||||
print '%sRecursing into %s' % (pad, os.path.basename(full))
|
||||
copy_dir((source[0], full), dest_full, vars, verbosity, simulate,
|
||||
indent=indent+1, use_cheetah=use_cheetah,
|
||||
sub_vars=sub_vars, interactive=interactive,
|
||||
svn_add=svn_add, template_renderer=template_renderer)
|
||||
continue
|
||||
elif not use_pkg_resources and 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, template_renderer=template_renderer)
|
||||
continue
|
||||
elif use_pkg_resources:
|
||||
content = pkg_resources.resource_string(source[0], full)
|
||||
else:
|
||||
f = open(full, 'rb')
|
||||
content = f.read()
|
||||
f.close()
|
||||
if sub_file:
|
||||
try:
|
||||
content = substitute_content(content, vars, filename=full,
|
||||
use_cheetah=use_cheetah,
|
||||
template_renderer=template_renderer)
|
||||
except SkipTemplate:
|
||||
continue
|
||||
if content is None:
|
||||
continue
|
||||
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 and use_pkg_resources:
|
||||
print '%sCopying %s to %s' % (pad, full, dest_full)
|
||||
elif 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
|
||||
if subprocess is None:
|
||||
raise RuntimeError('copydir failed, environment '
|
||||
'does not support subprocess '
|
||||
'module')
|
||||
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
|
||||
|
||||
def should_skip_file(name):
|
||||
"""
|
||||
Checks if a file should be skipped based on its name.
|
||||
|
||||
If it should be skipped, returns the reason, otherwise returns
|
||||
None.
|
||||
"""
|
||||
if name.startswith('.'):
|
||||
return 'Skipping hidden file %(filename)s'
|
||||
if name.endswith('~') or name.endswith('.bak'):
|
||||
return 'Skipping backup file %(filename)s'
|
||||
if name.endswith('.pyc') or name.endswith('.pyo'):
|
||||
return 'Skipping %s file %%(filename)s' % os.path.splitext(name)[1]
|
||||
if name.endswith('$py.class'):
|
||||
return 'Skipping $py.class file %(filename)s'
|
||||
if name in ('CVS', '_darcs'):
|
||||
return 'Skipping version control directory %(filename)s'
|
||||
return None
|
||||
|
||||
# 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)
|
||||
Type "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='<string>',
|
||||
use_cheetah=False, template_renderer=None):
|
||||
global Cheetah
|
||||
v = standard_vars.copy()
|
||||
v.update(vars)
|
||||
vars = v
|
||||
if template_renderer is not None:
|
||||
return template_renderer(content, vars, filename=filename)
|
||||
if not use_cheetah:
|
||||
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 SkipTemplate, e:
|
||||
print 'Skipping file %s' % filename
|
||||
if str(e):
|
||||
print str(e)
|
||||
raise
|
||||
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 skip_template(condition=True, *args):
|
||||
"""
|
||||
Raise SkipTemplate, which causes copydir to skip the template
|
||||
being processed. If you pass in a condition, only raise if that
|
||||
condition is true (allows you to use this with string.Template)
|
||||
|
||||
If you pass any additional arguments, they will be used to
|
||||
instantiate SkipTemplate (generally use like
|
||||
``skip_template(license=='GPL', 'Skipping file; not using GPL')``)
|
||||
"""
|
||||
if condition:
|
||||
raise SkipTemplate(*args)
|
||||
|
||||
def _add_except(exc, info):
|
||||
if not hasattr(exc, 'args') or exc.args is None:
|
||||
return
|
||||
args = list(exc.args)
|
||||
if args:
|
||||
args[0] += ' ' + info
|
||||
else:
|
||||
args = [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,
|
||||
'SkipTemplate': SkipTemplate,
|
||||
'skip_template': skip_template,
|
||||
}
|
||||
|
||||
class TypeMapper(dict):
|
||||
|
||||
def __getitem__(self, item):
|
||||
options = item.split('|')
|
||||
for op in options[:-1]:
|
||||
try:
|
||||
value = eval_with_catch(op, dict(self.items()))
|
||||
break
|
||||
except (NameError, KeyError):
|
||||
pass
|
||||
else:
|
||||
value = eval(options[-1], dict(self.items()))
|
||||
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 = r"""
|
||||
\$(?:
|
||||
(?P<escaped>\$) | # Escape sequence of two delimiters
|
||||
(?P<named>[_a-z][_a-z0-9]*) | # delimiter and a Python identifier
|
||||
{(?P<braced>.*?)} | # delimiter and a braced identifier
|
||||
(?P<invalid>) # Other ill-formed delimiter exprs
|
||||
)
|
||||
"""
|
||||
417
PasteScript-1.7.4.2-py2.6.egg/paste/script/create_distro.py
Executable file
417
PasteScript-1.7.4.2-py2.6.egg/paste/script/create_distro.py
Executable file
@@ -0,0 +1,417 @@
|
||||
# (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
|
||||
try:
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set
|
||||
|
||||
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)
|
||||
|
||||
# Gather all the templates egg_plugins into one var
|
||||
egg_plugins = set()
|
||||
for template in templates:
|
||||
egg_plugins.update(template.egg_plugins)
|
||||
egg_plugins = list(egg_plugins)
|
||||
egg_plugins.sort()
|
||||
vars['egg_plugins'] = egg_plugins
|
||||
|
||||
for template in templates:
|
||||
self.create_template(
|
||||
template, output_dir, vars)
|
||||
|
||||
found_setup_py = False
|
||||
paster_plugins_mtime = None
|
||||
if os.path.exists(os.path.join(output_dir, 'setup.py')):
|
||||
# Grab paster_plugins.txt's mtime; used to determine if the
|
||||
# egg_info command wrote to it
|
||||
try:
|
||||
egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
|
||||
except IOError:
|
||||
egg_info_dir = None
|
||||
if egg_info_dir is not None:
|
||||
plugins_path = os.path.join(egg_info_dir, 'paster_plugins.txt')
|
||||
if os.path.exists(plugins_path):
|
||||
paster_plugins_mtime = os.path.getmtime(plugins_path)
|
||||
|
||||
self.run_command(sys.executable, 'setup.py', 'egg_info',
|
||||
cwd=output_dir,
|
||||
# This shouldn't be necessary, but a bug in setuptools 0.6c3 is causing a (not entirely fatal) problem that I don't want to fix right now:
|
||||
expect_returncode=True)
|
||||
found_setup_py = True
|
||||
elif self.verbose > 1:
|
||||
print 'No setup.py (cannot run egg_info)'
|
||||
|
||||
package_dir = vars.get('package_dir', None)
|
||||
if package_dir:
|
||||
output_dir = os.path.join(output_dir, package_dir)
|
||||
|
||||
# With no setup.py this doesn't make sense:
|
||||
if found_setup_py:
|
||||
# Only write paster_plugins.txt if it wasn't written by
|
||||
# egg_info (the correct way). leaving us to do it is
|
||||
# deprecated and you'll get warned
|
||||
egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
|
||||
plugins_path = os.path.join(egg_info_dir, 'paster_plugins.txt')
|
||||
if len(egg_plugins) and (not os.path.exists(plugins_path) or \
|
||||
os.path.getmtime(plugins_path) == paster_plugins_mtime):
|
||||
if self.verbose:
|
||||
print >> sys.stderr, \
|
||||
('Manually creating paster_plugins.txt (deprecated! '
|
||||
'pass a paster_plugins keyword to setup() instead)')
|
||||
for plugin in egg_plugins:
|
||||
if self.verbose:
|
||||
print 'Adding %s to paster_plugins.txt' % plugin
|
||||
if not self.simulate:
|
||||
pluginlib.add_plugin(egg_info_dir, plugin)
|
||||
|
||||
if self.options.svn_repository:
|
||||
self.add_svn_repository(vars, output_dir)
|
||||
|
||||
if self.options.config:
|
||||
write_vars = vars.copy()
|
||||
del write_vars['project']
|
||||
del write_vars['package']
|
||||
self.write_vars(self.options.config, write_vars)
|
||||
|
||||
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',
|
||||
'dependency_links.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)
|
||||
44
PasteScript-1.7.4.2-py2.6.egg/paste/script/default_sysconfig.py
Executable file
44
PasteScript-1.7.4.2-py2.6.egg/paste/script/default_sysconfig.py
Executable file
@@ -0,0 +1,44 @@
|
||||
# (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
|
||||
269
PasteScript-1.7.4.2-py2.6.egg/paste/script/entrypoints.py
Executable file
269
PasteScript-1.7.4.2-py2.6.egg/paste/script/entrypoints.py
Executable file
@@ -0,0 +1,269 @@
|
||||
# (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
|
||||
import inspect
|
||||
import types
|
||||
|
||||
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 = 2
|
||||
|
||||
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(self.options.show_egg)
|
||||
if not self.args:
|
||||
raise BadCommand("You must give an entry point (or --list)")
|
||||
pattern = self.get_pattern(self.args[0])
|
||||
groups = self.get_groups_by_pattern(pattern)
|
||||
if not groups:
|
||||
raise BadCommand('No group matched %s' % self.args[0])
|
||||
ep_pat = None
|
||||
if len(self.args) > 1:
|
||||
ep_pat = self.get_pattern(self.args[1])
|
||||
for group in groups:
|
||||
desc = self.get_group_description(group)
|
||||
print '[%s]' % group
|
||||
if desc:
|
||||
print self.wrap(desc)
|
||||
print
|
||||
by_dist = {}
|
||||
self.print_entry_points_by_group(group, ep_pat)
|
||||
|
||||
def print_entry_points_by_group(self, group, ep_pat):
|
||||
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 ep_pat:
|
||||
entries = [e for e in entries
|
||||
if ep_pat.search(e.name)]
|
||||
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))
|
||||
for entry in entries:
|
||||
print self._ep_description(entry)
|
||||
desc = self.get_entry_point_description(entry, group)
|
||||
if desc and desc.description:
|
||||
print self.wrap(desc.description, indent=4)
|
||||
|
||||
def show_egg(self, egg_name):
|
||||
group_pat = None
|
||||
if self.args:
|
||||
group_pat = self.get_pattern(self.args[0])
|
||||
ep_pat = None
|
||||
if len(self.args) > 1:
|
||||
ep_pat = self.get_pattern(self.args[1])
|
||||
if egg_name.startswith('egg:'):
|
||||
egg_name = egg_name[4:]
|
||||
dist = pkg_resources.get_distribution(egg_name)
|
||||
entry_map = dist.get_entry_map()
|
||||
entry_groups = entry_map.items()
|
||||
entry_groups.sort()
|
||||
for group, points in entry_groups:
|
||||
if group_pat and not group_pat.search(group):
|
||||
continue
|
||||
print '[%s]' % group
|
||||
points = points.items()
|
||||
points.sort()
|
||||
for name, entry in points:
|
||||
if ep_pat:
|
||||
if not ep_pat.search(name):
|
||||
continue
|
||||
print self._ep_description(entry)
|
||||
desc = self.get_entry_point_description(entry, group)
|
||||
if desc and desc.description:
|
||||
print self.wrap(desc.description, indent=2)
|
||||
print
|
||||
|
||||
def wrap(self, text, indent=0):
|
||||
text = dedent(text)
|
||||
width = int(os.environ.get('COLUMNS', 70)) - indent
|
||||
text = '\n'.join([line.rstrip() for line in text.splitlines()])
|
||||
paras = text.split('\n\n')
|
||||
new_paras = []
|
||||
for para in paras:
|
||||
if para.lstrip() == para:
|
||||
# leading whitespace means don't rewrap
|
||||
para = '\n'.join(textwrap.wrap(para, width))
|
||||
new_paras.append(para)
|
||||
text = '\n\n'.join(new_paras)
|
||||
lines = [' '*indent + line
|
||||
for line in text.splitlines()]
|
||||
return '\n'.join(lines)
|
||||
|
||||
def _ep_description(self, ep, pad_name=None):
|
||||
name = ep.name
|
||||
if pad_name is not None:
|
||||
name = name + ' '*(pad_name-len(name))
|
||||
dest = ep.module_name
|
||||
if ep.attrs:
|
||||
dest = dest + ':' + '.'.join(ep.attrs)
|
||||
return '%s = %s' % (name, dest)
|
||||
|
||||
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:
|
||||
if hasattr(desc, 'description'):
|
||||
desc = desc.description
|
||||
print self.wrap(desc, 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:
|
||||
ep = entry.load()
|
||||
if hasattr(ep, 'description'):
|
||||
return ep.description
|
||||
else:
|
||||
return ep
|
||||
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?
|
||||
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 SuperGeneric(object):
|
||||
|
||||
def __init__(self, doc_object):
|
||||
self.doc_object = doc_object
|
||||
self.description = dedent(self.doc_object.__doc__)
|
||||
try:
|
||||
if isinstance(self.doc_object, (type, types.ClassType)):
|
||||
func = self.doc_object.__init__.im_func
|
||||
elif (hasattr(self.doc_object, '__call__')
|
||||
and not isinstance(self.doc_object, types.FunctionType)):
|
||||
func = self.doc_object.__call__
|
||||
else:
|
||||
func = self.doc_object
|
||||
if hasattr(func, '__paste_sig__'):
|
||||
sig = func.__paste_sig__
|
||||
else:
|
||||
sig = inspect.getargspec(func)
|
||||
sig = inspect.formatargspec(*sig)
|
||||
except TypeError:
|
||||
sig = None
|
||||
if sig:
|
||||
if self.description:
|
||||
self.description = '%s\n\n%s' % (
|
||||
sig, self.description)
|
||||
else:
|
||||
self.description = sig
|
||||
|
||||
def dedent(s):
|
||||
if s is None:
|
||||
return s
|
||||
s = s.strip('\n').strip('\r')
|
||||
return textwrap.dedent(s)
|
||||
|
||||
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
|
||||
|
||||
57
PasteScript-1.7.4.2-py2.6.egg/paste/script/epdesc.py
Executable file
57
PasteScript-1.7.4.2-py2.6.egg/paste/script/epdesc.py
Executable file
@@ -0,0 +1,57 @@
|
||||
class MetaEntryPointDescription(object):
|
||||
description = """
|
||||
This is an entry point that describes other entry points.
|
||||
"""
|
||||
|
||||
class CreateTemplateDescription(object):
|
||||
description = """
|
||||
Entry point for creating the file layout for a new project
|
||||
from a template.
|
||||
"""
|
||||
|
||||
class PasterCommandDescription(object):
|
||||
description = """
|
||||
Entry point that adds a command to the ``paster`` script
|
||||
to a project that has specifically enabled the command.
|
||||
"""
|
||||
|
||||
class GlobalPasterCommandDescription(object):
|
||||
description = """
|
||||
Entry point that adds a command to the ``paster`` script
|
||||
globally.
|
||||
"""
|
||||
|
||||
class AppInstallDescription(object):
|
||||
description = """
|
||||
This defines a runner that can install the application given a
|
||||
configuration file.
|
||||
"""
|
||||
|
||||
##################################################
|
||||
## Not in Paste per se, but we'll document
|
||||
## them...
|
||||
|
||||
class ConsoleScriptsDescription(object):
|
||||
description = """
|
||||
When a package is installed, any entry point listed here will be
|
||||
turned into a command-line script.
|
||||
"""
|
||||
|
||||
class DistutilsCommandsDescription(object):
|
||||
description = """
|
||||
This will add a new command when running
|
||||
``python setup.py entry-point-name`` if the
|
||||
package uses setuptools.
|
||||
"""
|
||||
|
||||
class SetupKeywordsDescription(object):
|
||||
description = """
|
||||
This adds a new keyword to setup.py's setup() function, and a
|
||||
validator to validate the value.
|
||||
"""
|
||||
|
||||
class EggInfoWriters(object):
|
||||
description = """
|
||||
This adds a new writer that creates files in the PkgName.egg-info/
|
||||
directory.
|
||||
"""
|
||||
107
PasteScript-1.7.4.2-py2.6.egg/paste/script/exe.py
Executable file
107
PasteScript-1.7.4.2-py2.6.egg/paste/script/exe.py
Executable file
@@ -0,0 +1,107 @@
|
||||
# (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 <command options>
|
||||
|
||||
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))
|
||||
vars = {'here': os.path.dirname(filename),
|
||||
'__file__': filename}
|
||||
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:
|
||||
value = value % vars
|
||||
options.append('--%s=%s' % (name.replace('_', '-'), value))
|
||||
os.environ['PASTE_CONFIG_FILE'] = filename
|
||||
options.extend(extra_args)
|
||||
command.run(options)
|
||||
362
PasteScript-1.7.4.2-py2.6.egg/paste/script/filemaker.py
Executable file
362
PasteScript-1.7.4.2-py2.6.egg/paste/script/filemaker.py
Executable file
@@ -0,0 +1,362 @@
|
||||
# (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
|
||||
import pkg_resources
|
||||
from paste.script import pluginlib, copydir
|
||||
from paste.script.command import BadCommand
|
||||
difflib = None
|
||||
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=None):
|
||||
"""
|
||||
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
|
||||
if template_vars is None:
|
||||
template_vars = {}
|
||||
self.template_vars = template_vars
|
||||
self.source_dir = source_dir
|
||||
self.use_pkg_resources = isinstance(source_dir, tuple)
|
||||
|
||||
def copy_file(self, template, dest, filename=None, add_py=True, package=True,
|
||||
template_renderer=None):
|
||||
"""
|
||||
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.
|
||||
template_renderer
|
||||
An optional template renderer
|
||||
|
||||
"""
|
||||
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,
|
||||
template_renderer=template_renderer)
|
||||
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
|
||||
raise NotImplementedError
|
||||
|
||||
def load_content(self, base_package, base, name, template,
|
||||
template_renderer=None):
|
||||
blank = os.path.join(base, name + '.py')
|
||||
read_content = True
|
||||
if not os.path.exists(blank):
|
||||
if self.use_pkg_resources:
|
||||
fullpath = '/'.join([self.source_dir[1], template])
|
||||
content = pkg_resources.resource_string(
|
||||
self.source_dir[0], fullpath)
|
||||
read_content = False
|
||||
blank = fullpath
|
||||
else:
|
||||
blank = os.path.join(self.source_dir,
|
||||
template)
|
||||
if read_content:
|
||||
f = open(blank, 'r')
|
||||
content = f.read()
|
||||
f.close()
|
||||
if blank.endswith('_tmpl'):
|
||||
content = copydir.substitute_content(
|
||||
content, self.template_vars, filename=blank,
|
||||
template_renderer=template_renderer)
|
||||
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()
|
||||
if not len(packages):
|
||||
raise BadCommand("No top level dir found for %s" % dirname)
|
||||
# @@: 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, packages[0], 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.svn_command('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.svn_command('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.svn_command('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 self.interactive:
|
||||
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
|
||||
|
||||
_svn_failed = False
|
||||
|
||||
def svn_command(self, *args, **kw):
|
||||
"""
|
||||
Run an svn command, but don't raise an exception if it fails.
|
||||
"""
|
||||
try:
|
||||
return self.run_command('svn', *args, **kw)
|
||||
except OSError, e:
|
||||
if not self._svn_failed:
|
||||
print 'Unable to run svn command (%s); proceeding anyway' % e
|
||||
self._svn_failed = True
|
||||
|
||||
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
|
||||
|
||||
119
PasteScript-1.7.4.2-py2.6.egg/paste/script/flup_server.py
Executable file
119
PasteScript-1.7.4.2-py2.6.egg/paste/script/flup_server.py
Executable file
@@ -0,0 +1,119 @@
|
||||
# (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
|
||||
import warnings
|
||||
|
||||
def warn(name, stacklevel=3):
|
||||
# Deprecated 2007-12-17
|
||||
warnings.warn(
|
||||
'The egg:PasteScript#flup_%s entry point is deprecated; please use egg:Flup#%s instead'
|
||||
% (name, name),
|
||||
DeprecationWarning, stacklevel=stacklevel)
|
||||
|
||||
def run_ajp_thread(wsgi_app, global_conf,
|
||||
scriptName='', host='localhost', port='8009',
|
||||
allowedServers='127.0.0.1'):
|
||||
import flup.server.ajp
|
||||
warn('ajp_thread')
|
||||
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
|
||||
warn('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, umask=None,
|
||||
multiplexed=False):
|
||||
import flup.server.fcgi
|
||||
warn('fcgi_thread')
|
||||
if socket:
|
||||
assert host is None and port is None
|
||||
sock = socket
|
||||
elif host:
|
||||
assert host is not None and port is not None
|
||||
sock = (host, int(port))
|
||||
ensure_port_cleanup([sock])
|
||||
else:
|
||||
sock = None
|
||||
if umask is not None:
|
||||
umask = int(umask)
|
||||
s = flup.server.fcgi.WSGIServer(
|
||||
wsgi_app,
|
||||
bindAddress=sock, umask=umask,
|
||||
multiplexed=asbool(multiplexed))
|
||||
s.run()
|
||||
|
||||
def run_fcgi_fork(wsgi_app, global_conf,
|
||||
host=None, port=None,
|
||||
socket=None, umask=None,
|
||||
multiplexed=False):
|
||||
import flup.server.fcgi_fork
|
||||
warn('fcgi_fork')
|
||||
if socket:
|
||||
assert host is None and port is None
|
||||
sock = socket
|
||||
elif host:
|
||||
assert host is not None and port is not None
|
||||
sock = (host, int(port))
|
||||
ensure_port_cleanup([sock])
|
||||
else:
|
||||
sock = None
|
||||
if umask is not None:
|
||||
umask = int(umask)
|
||||
s = flup.server.fcgi_fork.WSGIServer(
|
||||
wsgi_app,
|
||||
bindAddress=sock, umask=umask,
|
||||
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
|
||||
warn('scgi_thread')
|
||||
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
|
||||
warn('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()
|
||||
|
||||
168
PasteScript-1.7.4.2-py2.6.egg/paste/script/grep.py
Executable file
168
PasteScript-1.7.4.2-py2.6.egg/paste/script/grep.py
Executable file
@@ -0,0 +1,168 @@
|
||||
# (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
|
||||
|
||||
60
PasteScript-1.7.4.2-py2.6.egg/paste/script/help.py
Executable file
60
PasteScript-1.7.4.2-py2.6.egg/paste/script/help.py
Executable file
@@ -0,0 +1,60 @@
|
||||
# (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
|
||||
|
||||
49
PasteScript-1.7.4.2-py2.6.egg/paste/script/interfaces.py
Executable file
49
PasteScript-1.7.4.2-py2.6.egg/paste/script/interfaces.py
Executable file
@@ -0,0 +1,49 @@
|
||||
# (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(object):
|
||||
|
||||
"""
|
||||
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).
|
||||
"""
|
||||
@@ -0,0 +1 @@
|
||||
#
|
||||
@@ -0,0 +1,3 @@
|
||||
[egg_info]
|
||||
tag_build = dev
|
||||
tag_svn_revision = true
|
||||
@@ -0,0 +1,26 @@
|
||||
from setuptools import setup, find_packages
|
||||
import sys, os
|
||||
|
||||
version = {{repr(version or "0.0")}}
|
||||
|
||||
setup(name={{repr(project)}},
|
||||
version=version,
|
||||
description="{{description or ''}}",
|
||||
long_description="""\
|
||||
{{long_description or ''}}""",
|
||||
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
keywords={{repr(keywords or '')}},
|
||||
author={{repr(author or '')}},
|
||||
author_email={{repr(author_email or '')}},
|
||||
url={{repr(url or '')}},
|
||||
license={{repr(license_name or '')}},
|
||||
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
|
||||
include_package_data=True,
|
||||
zip_safe={{repr(bool(zip_safe or False))}},
|
||||
install_requires=[
|
||||
# -*- Extra requirements: -*-
|
||||
],
|
||||
entry_points="""
|
||||
# -*- Entry points: -*-
|
||||
""",
|
||||
)
|
||||
135
PasteScript-1.7.4.2-py2.6.egg/paste/script/pluginlib.py
Executable file
135
PasteScript-1.7.4.2-py2.6.egg/paste/script/pluginlib.py
Executable file
@@ -0,0 +1,135 @@
|
||||
# (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)
|
||||
if not os.path.exists(os.path.dirname(fn)):
|
||||
os.makedirs(os.path.dirname(fn))
|
||||
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')
|
||||
and os.path.isdir(os.path.join(dir, fn))):
|
||||
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:
|
||||
msg = '%sNot Found%s: %s (did you run python setup.py develop?)'
|
||||
if str(e) != plugin:
|
||||
e.args = (msg % (str(e) + ': ', ' for', plugin)),
|
||||
else:
|
||||
e.args = (msg % ('', '', 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):
|
||||
all = []
|
||||
for dir_extension in ['.'] + os.listdir(base_dir):
|
||||
full = os.path.join(base_dir, dir_extension,
|
||||
egg_name(dist_name)+'.egg-info')
|
||||
all.append(full)
|
||||
if os.path.exists(full):
|
||||
return full
|
||||
raise IOError("No egg-info directory found (looked in %s)"
|
||||
% ', '.join(all))
|
||||
189
PasteScript-1.7.4.2-py2.6.egg/paste/script/request.py
Executable file
189
PasteScript-1.7.4.2-py2.6.egg/paste/script/request.py
Executable file
@@ -0,0 +1,189 @@
|
||||
# (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 re
|
||||
import sys
|
||||
import urlparse
|
||||
import urllib
|
||||
from command import Command, BadCommand
|
||||
from paste.deploy import loadapp, loadserver
|
||||
from paste.wsgilib import raw_interactive
|
||||
|
||||
class RequestCommand(Command):
|
||||
|
||||
min_args = 2
|
||||
usage = 'CONFIG_FILE URL [OPTIONS/ARGUMENTS]'
|
||||
takes_config_file = 1
|
||||
summary = "Run a request for the described application"
|
||||
description = """\
|
||||
This command makes an artifical request to a web application that
|
||||
uses a paste.deploy configuration file for the server and
|
||||
application.
|
||||
|
||||
Use 'paster request config.ini /url' to request /url. Use
|
||||
'paster post config.ini /url < data' to do a POST with the given
|
||||
request body.
|
||||
|
||||
If the URL is relative (doesn't begin with /) it is interpreted as
|
||||
relative to /.command/. The variable environ['paste.command_request']
|
||||
will be set to True in the request, so your application can distinguish
|
||||
these calls from normal requests.
|
||||
|
||||
Note that you can pass options besides the options listed here; any unknown
|
||||
options will be passed to the application in environ['QUERY_STRING'].
|
||||
"""
|
||||
|
||||
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('--config-var',
|
||||
dest='config_vars',
|
||||
metavar='NAME:VALUE',
|
||||
action='append',
|
||||
help="Variable to make available in the config for %()s substitution "
|
||||
"(you can use this option multiple times)")
|
||||
parser.add_option('--header',
|
||||
dest='headers',
|
||||
metavar='NAME:VALUE',
|
||||
action='append',
|
||||
help="Header to add to request (you can use this option multiple times)")
|
||||
parser.add_option('--display-headers',
|
||||
dest='display_headers',
|
||||
action='store_true',
|
||||
help='Display headers before the response body')
|
||||
|
||||
ARG_OPTIONS = ['-n', '--app-name', '--config-var', '--header']
|
||||
OTHER_OPTIONS = ['--display-headers']
|
||||
|
||||
## FIXME: some kind of verbosity?
|
||||
## FIXME: allow other methods than POST and GET?
|
||||
|
||||
_scheme_re = re.compile(r'^[a-z][a-z]+:', re.I)
|
||||
|
||||
def command(self):
|
||||
vars = {}
|
||||
app_spec = self.args[0]
|
||||
url = self.args[1]
|
||||
url = urlparse.urljoin('/.command/', url)
|
||||
if self.options.config_vars:
|
||||
for item in self.option.config_vars:
|
||||
if ':' not in item:
|
||||
raise BadCommand(
|
||||
"Bad option, should be name:value : --config-var=%s" % item)
|
||||
name, value = item.split(':', 1)
|
||||
vars[name] = value
|
||||
headers = {}
|
||||
if self.options.headers:
|
||||
for item in self.options.headers:
|
||||
if ':' not in item:
|
||||
raise BadCommand(
|
||||
"Bad option, should be name:value : --header=%s" % item)
|
||||
name, value = item.split(':', 1)
|
||||
headers[name] = value.strip()
|
||||
if not self._scheme_re.search(app_spec):
|
||||
app_spec = 'config:'+app_spec
|
||||
if self.options.app_name:
|
||||
if '#' in app_spec:
|
||||
app_spec = app_spec.split('#', 1)[0]
|
||||
app_spec = app_spec + '#' + options.app_name
|
||||
app = loadapp(app_spec, relative_to=os.getcwd(), global_conf=vars)
|
||||
if self.command_name.lower() == 'post':
|
||||
request_method = 'POST'
|
||||
else:
|
||||
request_method = 'GET'
|
||||
qs = []
|
||||
for item in self.args[2:]:
|
||||
if '=' in item:
|
||||
item = urllib.quote(item.split('=', 1)[0]) + '=' + urllib.quote(item.split('=', 1)[1])
|
||||
else:
|
||||
item = urllib.quote(item)
|
||||
qs.append(item)
|
||||
qs = '&'.join(qs)
|
||||
|
||||
environ = {
|
||||
'REQUEST_METHOD': request_method,
|
||||
## FIXME: shouldn't be static (an option?):
|
||||
'CONTENT_TYPE': 'text/plain',
|
||||
'wsgi.run_once': True,
|
||||
'wsgi.multithread': False,
|
||||
'wsgi.multiprocess': False,
|
||||
'wsgi.errors': sys.stderr,
|
||||
'QUERY_STRING': qs,
|
||||
'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1',
|
||||
'paste.command_request': True,
|
||||
}
|
||||
if request_method == 'POST':
|
||||
environ['wsgi.input'] = sys.stdin
|
||||
environ['CONTENT_LENGTH'] = '-1'
|
||||
for name, value in headers.items():
|
||||
if name.lower() == 'content-type':
|
||||
name = 'CONTENT_TYPE'
|
||||
else:
|
||||
name = 'HTTP_'+name.upper().replace('-', '_')
|
||||
environ[name] = value
|
||||
|
||||
status, headers, output, errors = raw_interactive(app, url, **environ)
|
||||
assert not errors, "errors should be printed directly to sys.stderr"
|
||||
if self.options.display_headers:
|
||||
for name, value in headers:
|
||||
sys.stdout.write('%s: %s\n' % (name, value))
|
||||
sys.stdout.write('\n')
|
||||
sys.stdout.write(output)
|
||||
sys.stdout.flush()
|
||||
status_int = int(status.split()[0])
|
||||
if status_int != 200:
|
||||
return status_int
|
||||
|
||||
def parse_args(self, args):
|
||||
if args == ['-h']:
|
||||
Command.parse_args(self, args)
|
||||
return
|
||||
# These are the arguments parsed normally:
|
||||
normal_args = []
|
||||
# And these are arguments passed to the URL:
|
||||
extra_args = []
|
||||
# This keeps track of whether we have the two required positional arguments:
|
||||
pos_args = 0
|
||||
while args:
|
||||
start = args[0]
|
||||
if not start.startswith('-'):
|
||||
if pos_args < 2:
|
||||
pos_args += 1
|
||||
normal_args.append(start)
|
||||
args.pop(0)
|
||||
continue
|
||||
else:
|
||||
normal_args.append(start)
|
||||
args.pop(0)
|
||||
continue
|
||||
else:
|
||||
found = False
|
||||
for option in self.ARG_OPTIONS:
|
||||
if start == option:
|
||||
normal_args.append(start)
|
||||
args.pop(0)
|
||||
if not args:
|
||||
raise BadCommand(
|
||||
"Option %s takes an argument" % option)
|
||||
normal_args.append(args.pop(0))
|
||||
found = True
|
||||
break
|
||||
elif start.startswith(option+'='):
|
||||
normal_args.append(start)
|
||||
args.pop(0)
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
continue
|
||||
if start in self.OTHER_OPTIONS:
|
||||
normal_args.append(start)
|
||||
args.pop(0)
|
||||
continue
|
||||
extra_args.append(start)
|
||||
args.pop(0)
|
||||
Command.parse_args(self, normal_args)
|
||||
# Add the extra arguments back in:
|
||||
self.args = self.args + extra_args
|
||||
|
||||
650
PasteScript-1.7.4.2-py2.6.egg/paste/script/serve.py
Executable file
650
PasteScript-1.7.4.2-py2.6.egg/paste/script/serve.py
Executable file
@@ -0,0 +1,650 @@
|
||||
# (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 sys
|
||||
import time
|
||||
try:
|
||||
import subprocess
|
||||
except ImportError:
|
||||
from paste.util import subprocess24 as subprocess
|
||||
from command import Command, BadCommand
|
||||
from paste.deploy import loadapp, loadserver
|
||||
import threading
|
||||
import atexit
|
||||
import logging
|
||||
import ConfigParser
|
||||
|
||||
MAXFD = 1024
|
||||
|
||||
jython = sys.platform.startswith('java')
|
||||
|
||||
class DaemonizeException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ServeCommand(Command):
|
||||
|
||||
min_args = 0
|
||||
usage = 'CONFIG_FILE [start|stop|restart|status] [var=value]'
|
||||
takes_config_file = 1
|
||||
summary = "Serve the described application"
|
||||
description = """\
|
||||
This command serves a web application that uses a paste.deploy
|
||||
configuration file for the server and application.
|
||||
|
||||
If start/stop/restart is given, then --daemon is implied, and it will
|
||||
start (normal operation), stop (--stop-daemon), or do both.
|
||||
|
||||
You can also include variable assignments like 'http_port=8080'
|
||||
and then use %(http_port)s in your config files.
|
||||
"""
|
||||
|
||||
# used by subclasses that configure apps and servers differently
|
||||
requires_config_file = True
|
||||
|
||||
parser = Command.standard_parser(quiet=True)
|
||||
parser.add_option('-n', '--app-name',
|
||||
dest='app_name',
|
||||
metavar='NAME',
|
||||
help="Load the named application (default main)")
|
||||
parser.add_option('-s', '--server',
|
||||
dest='server',
|
||||
metavar='SERVER_TYPE',
|
||||
help="Use the named server.")
|
||||
parser.add_option('--server-name',
|
||||
dest='server_name',
|
||||
metavar='SECTION_NAME',
|
||||
help="Use the named server as defined in the configuration file (default: main)")
|
||||
if hasattr(os, 'fork'):
|
||||
parser.add_option('--daemon',
|
||||
dest="daemon",
|
||||
action="store_true",
|
||||
help="Run in daemon (background) mode")
|
||||
parser.add_option('--pid-file',
|
||||
dest='pid_file',
|
||||
metavar='FILENAME',
|
||||
help="Save PID to file (default to paster.pid if running in daemon mode)")
|
||||
parser.add_option('--log-file',
|
||||
dest='log_file',
|
||||
metavar='LOG_FILE',
|
||||
help="Save output to the given log file (redirects stdout)")
|
||||
parser.add_option('--reload',
|
||||
dest='reload',
|
||||
action='store_true',
|
||||
help="Use auto-restart file monitor")
|
||||
parser.add_option('--reload-interval',
|
||||
dest='reload_interval',
|
||||
default=1,
|
||||
help="Seconds between checking files (low number can cause significant CPU usage)")
|
||||
parser.add_option('--monitor-restart',
|
||||
dest='monitor_restart',
|
||||
action='store_true',
|
||||
help="Auto-restart server if it dies")
|
||||
parser.add_option('--status',
|
||||
action='store_true',
|
||||
dest='show_status',
|
||||
help="Show the status of the (presumably daemonized) server")
|
||||
|
||||
|
||||
if hasattr(os, 'setuid'):
|
||||
# I don't think these are available on Windows
|
||||
parser.add_option('--user',
|
||||
dest='set_user',
|
||||
metavar="USERNAME",
|
||||
help="Set the user (usually only possible when run as root)")
|
||||
parser.add_option('--group',
|
||||
dest='set_group',
|
||||
metavar="GROUP",
|
||||
help="Set the group (usually only possible when run as root)")
|
||||
|
||||
parser.add_option('--stop-daemon',
|
||||
dest='stop_daemon',
|
||||
action='store_true',
|
||||
help='Stop a daemonized server (given a PID file, or default paster.pid file)')
|
||||
|
||||
if jython:
|
||||
parser.add_option('--disable-jython-reloader',
|
||||
action='store_true',
|
||||
dest='disable_jython_reloader',
|
||||
help="Disable the Jython reloader")
|
||||
|
||||
|
||||
_scheme_re = re.compile(r'^[a-z][a-z]+:', re.I)
|
||||
|
||||
default_verbosity = 1
|
||||
|
||||
_reloader_environ_key = 'PYTHON_RELOADER_SHOULD_RUN'
|
||||
_monitor_environ_key = 'PASTE_MONITOR_SHOULD_RUN'
|
||||
|
||||
possible_subcommands = ('start', 'stop', 'restart', 'status')
|
||||
def command(self):
|
||||
if self.options.stop_daemon:
|
||||
return self.stop_daemon()
|
||||
|
||||
if not hasattr(self.options, 'set_user'):
|
||||
# Windows case:
|
||||
self.options.set_user = self.options.set_group = None
|
||||
# @@: Is this the right stage to set the user at?
|
||||
self.change_user_group(
|
||||
self.options.set_user, self.options.set_group)
|
||||
|
||||
if self.requires_config_file:
|
||||
if not self.args:
|
||||
raise BadCommand('You must give a config file')
|
||||
app_spec = self.args[0]
|
||||
if (len(self.args) > 1
|
||||
and self.args[1] in self.possible_subcommands):
|
||||
cmd = self.args[1]
|
||||
restvars = self.args[2:]
|
||||
else:
|
||||
cmd = None
|
||||
restvars = self.args[1:]
|
||||
else:
|
||||
app_spec = ""
|
||||
if (self.args
|
||||
and self.args[0] in self.possible_subcommands):
|
||||
cmd = self.args[0]
|
||||
restvars = self.args[1:]
|
||||
else:
|
||||
cmd = None
|
||||
restvars = self.args[:]
|
||||
|
||||
if (getattr(self.options, 'daemon', False)
|
||||
and getattr(self.options, 'reload', False)):
|
||||
raise BadCommand('The --daemon and --reload options may not be used together')
|
||||
|
||||
jython_monitor = False
|
||||
if self.options.reload:
|
||||
if jython and not self.options.disable_jython_reloader:
|
||||
# JythonMonitor raises the special SystemRestart
|
||||
# exception that'll cause the Jython interpreter to
|
||||
# reload in the existing Java process (avoiding
|
||||
# subprocess startup time)
|
||||
try:
|
||||
from paste.reloader import JythonMonitor
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
jython_monitor = JythonMonitor(poll_interval=int(
|
||||
self.options.reload_interval))
|
||||
if self.requires_config_file:
|
||||
jython_monitor.watch_file(self.args[0])
|
||||
|
||||
if not jython_monitor:
|
||||
if os.environ.get(self._reloader_environ_key):
|
||||
from paste import reloader
|
||||
if self.verbose > 1:
|
||||
print 'Running reloading file monitor'
|
||||
reloader.install(int(self.options.reload_interval))
|
||||
if self.requires_config_file:
|
||||
reloader.watch_file(self.args[0])
|
||||
else:
|
||||
return self.restart_with_reloader()
|
||||
|
||||
if cmd not in (None, 'start', 'stop', 'restart', 'status'):
|
||||
raise BadCommand(
|
||||
'Error: must give start|stop|restart (not %s)' % cmd)
|
||||
|
||||
if cmd == 'status' or self.options.show_status:
|
||||
return self.show_status()
|
||||
|
||||
if cmd == 'restart' or cmd == 'stop':
|
||||
result = self.stop_daemon()
|
||||
if result:
|
||||
if cmd == 'restart':
|
||||
print "Could not stop daemon; aborting"
|
||||
else:
|
||||
print "Could not stop daemon"
|
||||
return result
|
||||
if cmd == 'stop':
|
||||
return result
|
||||
self.options.daemon = True
|
||||
|
||||
if cmd == 'start':
|
||||
self.options.daemon = True
|
||||
|
||||
app_name = self.options.app_name
|
||||
vars = self.parse_vars(restvars)
|
||||
if not self._scheme_re.search(app_spec):
|
||||
app_spec = 'config:' + app_spec
|
||||
server_name = self.options.server_name
|
||||
if self.options.server:
|
||||
server_spec = 'egg:PasteScript'
|
||||
assert server_name is None
|
||||
server_name = self.options.server
|
||||
else:
|
||||
server_spec = app_spec
|
||||
base = os.getcwd()
|
||||
|
||||
if getattr(self.options, 'daemon', False):
|
||||
if not self.options.pid_file:
|
||||
self.options.pid_file = 'paster.pid'
|
||||
if not self.options.log_file:
|
||||
self.options.log_file = 'paster.log'
|
||||
|
||||
# Ensure the log file is writeable
|
||||
if self.options.log_file:
|
||||
try:
|
||||
writeable_log_file = open(self.options.log_file, 'a')
|
||||
except IOError, ioe:
|
||||
msg = 'Error: Unable to write to log file: %s' % ioe
|
||||
raise BadCommand(msg)
|
||||
writeable_log_file.close()
|
||||
|
||||
# Ensure the pid file is writeable
|
||||
if self.options.pid_file:
|
||||
try:
|
||||
writeable_pid_file = open(self.options.pid_file, 'a')
|
||||
except IOError, ioe:
|
||||
msg = 'Error: Unable to write to pid file: %s' % ioe
|
||||
raise BadCommand(msg)
|
||||
writeable_pid_file.close()
|
||||
|
||||
if getattr(self.options, 'daemon', False):
|
||||
try:
|
||||
self.daemonize()
|
||||
except DaemonizeException, ex:
|
||||
if self.verbose > 0:
|
||||
print str(ex)
|
||||
return
|
||||
|
||||
if (self.options.monitor_restart
|
||||
and not os.environ.get(self._monitor_environ_key)):
|
||||
return self.restart_with_monitor()
|
||||
|
||||
if self.options.pid_file:
|
||||
self.record_pid(self.options.pid_file)
|
||||
|
||||
if self.options.log_file:
|
||||
stdout_log = LazyWriter(self.options.log_file, 'a')
|
||||
sys.stdout = stdout_log
|
||||
sys.stderr = stdout_log
|
||||
logging.basicConfig(stream=stdout_log)
|
||||
|
||||
log_fn = app_spec
|
||||
if log_fn.startswith('config:'):
|
||||
log_fn = app_spec[len('config:'):]
|
||||
elif log_fn.startswith('egg:'):
|
||||
log_fn = None
|
||||
if log_fn:
|
||||
log_fn = os.path.join(base, log_fn)
|
||||
self.logging_file_config(log_fn)
|
||||
|
||||
server = self.loadserver(server_spec, name=server_name,
|
||||
relative_to=base, global_conf=vars)
|
||||
app = self.loadapp(app_spec, name=app_name,
|
||||
relative_to=base, global_conf=vars)
|
||||
|
||||
if self.verbose > 0:
|
||||
if hasattr(os, 'getpid'):
|
||||
msg = 'Starting server in PID %i.' % os.getpid()
|
||||
else:
|
||||
msg = 'Starting server.'
|
||||
print msg
|
||||
|
||||
def serve():
|
||||
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
|
||||
|
||||
if jython_monitor:
|
||||
# JythonMonitor has to be ran from the main thread
|
||||
threading.Thread(target=serve).start()
|
||||
print 'Starting Jython file monitor'
|
||||
jython_monitor.periodic_reload()
|
||||
else:
|
||||
serve()
|
||||
|
||||
def loadserver(self, server_spec, name, relative_to, **kw):
|
||||
return loadserver(
|
||||
server_spec, name=name,
|
||||
relative_to=relative_to, **kw)
|
||||
|
||||
def loadapp(self, app_spec, name, relative_to, **kw):
|
||||
return loadapp(
|
||||
app_spec, name=name, relative_to=relative_to,
|
||||
**kw)
|
||||
|
||||
def daemonize(self):
|
||||
pid = live_pidfile(self.options.pid_file)
|
||||
if pid:
|
||||
raise DaemonizeException(
|
||||
"Daemon is already running (PID: %s from PID file %s)"
|
||||
% (pid, self.options.pid_file))
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
import signal
|
||||
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):
|
||||
self.restart_with_monitor(reloader=True)
|
||||
|
||||
def restart_with_monitor(self, reloader=False):
|
||||
if self.verbose > 0:
|
||||
if reloader:
|
||||
print 'Starting subprocess with file monitor'
|
||||
else:
|
||||
print 'Starting subprocess with monitor parent'
|
||||
while 1:
|
||||
args = [self.quote_first_command_arg(sys.executable)] + sys.argv
|
||||
new_environ = os.environ.copy()
|
||||
if reloader:
|
||||
new_environ[self._reloader_environ_key] = 'true'
|
||||
else:
|
||||
new_environ[self._monitor_environ_key] = 'true'
|
||||
proc = None
|
||||
try:
|
||||
try:
|
||||
_turn_sigterm_into_systemexit()
|
||||
proc = subprocess.Popen(args, env=new_environ)
|
||||
exit_code = proc.wait()
|
||||
proc = None
|
||||
except KeyboardInterrupt:
|
||||
print '^C caught in monitor process'
|
||||
if self.verbose > 1:
|
||||
raise
|
||||
return 1
|
||||
finally:
|
||||
if (proc is not None
|
||||
and hasattr(os, 'kill')):
|
||||
import signal
|
||||
try:
|
||||
os.kill(proc.pid, signal.SIGTERM)
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
|
||||
if reloader:
|
||||
# Reloader always exits with code 3; but if we are
|
||||
# a monitor, any exit code will restart
|
||||
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):
|
||||
|
||||
"""
|
||||
File-like object that opens a file lazily when it is first written
|
||||
to.
|
||||
"""
|
||||
|
||||
def __init__(self, filename, mode='w'):
|
||||
self.filename = filename
|
||||
self.fileobj = None
|
||||
self.lock = threading.Lock()
|
||||
self.mode = mode
|
||||
|
||||
def open(self):
|
||||
if self.fileobj is None:
|
||||
self.lock.acquire()
|
||||
try:
|
||||
if self.fileobj is None:
|
||||
self.fileobj = open(self.filename, self.mode)
|
||||
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()
|
||||
|
||||
def _turn_sigterm_into_systemexit():
|
||||
"""
|
||||
Attempts to turn a SIGTERM exception into a SystemExit exception.
|
||||
"""
|
||||
try:
|
||||
import signal
|
||||
except ImportError:
|
||||
return
|
||||
def handle_term(signo, frame):
|
||||
raise SystemExit
|
||||
signal.signal(signal.SIGTERM, handle_term)
|
||||
278
PasteScript-1.7.4.2-py2.6.egg/paste/script/templates.py
Executable file
278
PasteScript-1.7.4.2-py2.6.egg/paste/script/templates.py
Executable file
@@ -0,0 +1,278 @@
|
||||
# (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
|
||||
|
||||
from paste.util.template import paste_script_template_renderer
|
||||
|
||||
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
|
||||
|
||||
# You can also give this function/method to use something other
|
||||
# than Cheetah or string.Template. The function should be of the
|
||||
# signature template_renderer(content, vars, filename=filename).
|
||||
# Careful you don't turn this into a method by putting a function
|
||||
# here (without staticmethod)!
|
||||
template_renderer = None
|
||||
|
||||
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)
|
||||
if isinstance( self._template_dir, tuple):
|
||||
return self._template_dir
|
||||
else:
|
||||
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, var.should_echo)
|
||||
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,
|
||||
template_renderer=self.template_renderer)
|
||||
|
||||
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
|
||||
|
||||
NoDefault = command.NoDefault
|
||||
|
||||
class var(object):
|
||||
|
||||
def __init__(self, name, description,
|
||||
default='', should_echo=True):
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.default = default
|
||||
self.should_echo = should_echo
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %s default=%r should_echo=%s>' % (
|
||||
self.__class__.__name__,
|
||||
self.name, self.default, self.should_echo)
|
||||
|
||||
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
|
||||
if var.should_echo is True:
|
||||
print ' should_echo: %s' % var.should_echo
|
||||
print
|
||||
|
||||
print_vars = classmethod(print_vars)
|
||||
|
||||
class BasicPackage(Template):
|
||||
|
||||
_template_dir = 'paster-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),
|
||||
]
|
||||
|
||||
template_renderer = staticmethod(paste_script_template_renderer)
|
||||
|
||||
_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
|
||||
|
||||
101
PasteScript-1.7.4.2-py2.6.egg/paste/script/testapp.py
Executable file
101
PasteScript-1.7.4.2-py2.6.egg/paste/script/testapp.py
Executable file
@@ -0,0 +1,101 @@
|
||||
# (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
|
||||
|
||||
html_page_template = '''
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Application</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test Application: Working!</h1>
|
||||
|
||||
<table border="1">
|
||||
%(environ)s
|
||||
</table>
|
||||
|
||||
<p>
|
||||
Note: to see an error report, append <code>?error=true</code>
|
||||
to the URL
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
html_row_template = '''
|
||||
<tr>
|
||||
<td><b>%(key)s</b></td>
|
||||
<td><tt>%(value_literal)s</b></td>
|
||||
</tr>
|
||||
'''
|
||||
|
||||
text_page_template = '%(environ)s'
|
||||
text_row_template = '%(key)s: %(value_repr)s\n'
|
||||
|
||||
def make_literal(value):
|
||||
value = cgi.escape(value, 1)
|
||||
value = value.replace('\n\r', '\n')
|
||||
value = value.replace('\r', '\n')
|
||||
value = value.replace('\n', '<br>\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=None, text=False):
|
||||
self.global_conf = global_conf
|
||||
self.text = text
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
if environ.get('QUERY_STRING', '').find('error=') >= 0:
|
||||
assert 0, "Here is your error report, ordered and delivered"
|
||||
if self.text:
|
||||
page_template = text_page_template
|
||||
row_template = text_row_template
|
||||
content_type = 'text/plain; charset=utf8'
|
||||
else:
|
||||
page_template = html_page_template
|
||||
row_template = html_row_template
|
||||
content_type = 'text/html; charset=utf8'
|
||||
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', content_type)]
|
||||
start_response('200 OK', headers)
|
||||
return [page]
|
||||
|
||||
|
||||
def make_test_application(global_conf, text=False, lint=False):
|
||||
from paste.deploy.converters import asbool
|
||||
text = asbool(text)
|
||||
lint = asbool(lint)
|
||||
app = TestApplication(global_conf=global_conf, text=text)
|
||||
if lint:
|
||||
from paste.lint import middleware
|
||||
app = middleware(app)
|
||||
return app
|
||||
|
||||
make_test_application.__doc__ = TestApplication.__doc__
|
||||
20
PasteScript-1.7.4.2-py2.6.egg/paste/script/twisted_web2_server.py
Executable file
20
PasteScript-1.7.4.2-py2.6.egg/paste/script/twisted_web2_server.py
Executable file
@@ -0,0 +1,20 @@
|
||||
# (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!
|
||||
|
||||
def run_twisted(wsgi_app, global_conf,
|
||||
host='127.0.0.1', port='8080'):
|
||||
host = host or None
|
||||
import twisted.web2.wsgi
|
||||
import twisted.web2.log
|
||||
import twisted.web2.channel
|
||||
import twisted.web2.server
|
||||
import twisted.internet.reactor
|
||||
wsgi_resource = twisted.web2.wsgi.WSGIResource(wsgi_app)
|
||||
resource = twisted.web2.log.LogWrapperResource(wsgi_resource)
|
||||
twisted.web2.log.DefaultCommonAccessLoggingObserver().start()
|
||||
site = twisted.web2.server.Site(resource)
|
||||
factory = twisted.web2.channel.HTTPFactory(site)
|
||||
# --- start reactor for listen port
|
||||
twisted.internet.reactor.listenTCP(int(port), factory, interface=host)
|
||||
twisted.internet.reactor.run()
|
||||
3
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/__init__.py
Executable file
3
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/__init__.py
Executable file
@@ -0,0 +1,3 @@
|
||||
# (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
|
||||
#
|
||||
354
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/logging_config.py
Executable file
354
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/logging_config.py
Executable file
@@ -0,0 +1,354 @@
|
||||
# Copyright 2001-2005 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""
|
||||
Configuration functions for the logging package for Python. The core package
|
||||
is based on PEP 282 and comments thereto in comp.lang.python, and influenced
|
||||
by Apache's log4j system.
|
||||
|
||||
Should work under Python versions >= 1.5.2, except that source line
|
||||
information is not available unless 'sys._getframe()' is.
|
||||
|
||||
Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
|
||||
|
||||
To use, simply 'import logging' and log away!
|
||||
"""
|
||||
|
||||
import sys, logging, logging.handlers, string, socket, struct, os, traceback, types
|
||||
|
||||
try:
|
||||
import thread
|
||||
import threading
|
||||
except ImportError:
|
||||
thread = None
|
||||
|
||||
from SocketServer import ThreadingTCPServer, StreamRequestHandler
|
||||
|
||||
|
||||
DEFAULT_LOGGING_CONFIG_PORT = 9030
|
||||
|
||||
if sys.platform == "win32":
|
||||
RESET_ERROR = 10054 #WSAECONNRESET
|
||||
else:
|
||||
RESET_ERROR = 104 #ECONNRESET
|
||||
|
||||
#
|
||||
# The following code implements a socket listener for on-the-fly
|
||||
# reconfiguration of logging.
|
||||
#
|
||||
# _listener holds the server object doing the listening
|
||||
_listener = None
|
||||
|
||||
def fileConfig(fname, defaults=None):
|
||||
"""
|
||||
Read the logging configuration from a ConfigParser-format file.
|
||||
|
||||
This can be called several times from an application, allowing an end user
|
||||
the ability to select from various pre-canned configurations (if the
|
||||
developer provides a mechanism to present the choices and load the chosen
|
||||
configuration).
|
||||
In versions of ConfigParser which have the readfp method [typically
|
||||
shipped in 2.x versions of Python], you can pass in a file-like object
|
||||
rather than a filename, in which case the file-like object will be read
|
||||
using readfp.
|
||||
"""
|
||||
import ConfigParser
|
||||
|
||||
cp = ConfigParser.ConfigParser(defaults)
|
||||
if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
|
||||
cp.readfp(fname)
|
||||
else:
|
||||
cp.read(fname)
|
||||
|
||||
formatters = _create_formatters(cp)
|
||||
|
||||
# critical section
|
||||
logging._acquireLock()
|
||||
try:
|
||||
logging._handlers.clear()
|
||||
if hasattr(logging, '_handlerList'):
|
||||
del logging._handlerList[:]
|
||||
# Handlers add themselves to logging._handlers
|
||||
handlers = _install_handlers(cp, formatters)
|
||||
_install_loggers(cp, handlers)
|
||||
finally:
|
||||
logging._releaseLock()
|
||||
|
||||
|
||||
def _resolve(name):
|
||||
"""Resolve a dotted name to a global object."""
|
||||
name = string.split(name, '.')
|
||||
used = name.pop(0)
|
||||
found = __import__(used)
|
||||
for n in name:
|
||||
used = used + '.' + n
|
||||
try:
|
||||
found = getattr(found, n)
|
||||
except AttributeError:
|
||||
__import__(used)
|
||||
found = getattr(found, n)
|
||||
return found
|
||||
|
||||
|
||||
def _create_formatters(cp):
|
||||
"""Create and return formatters"""
|
||||
flist = cp.get("formatters", "keys")
|
||||
if not len(flist):
|
||||
return {}
|
||||
flist = string.split(flist, ",")
|
||||
formatters = {}
|
||||
for form in flist:
|
||||
form = string.strip(form)
|
||||
sectname = "formatter_%s" % form
|
||||
opts = cp.options(sectname)
|
||||
if "format" in opts:
|
||||
fs = cp.get(sectname, "format", 1)
|
||||
else:
|
||||
fs = None
|
||||
if "datefmt" in opts:
|
||||
dfs = cp.get(sectname, "datefmt", 1)
|
||||
else:
|
||||
dfs = None
|
||||
c = logging.Formatter
|
||||
if "class" in opts:
|
||||
class_name = cp.get(sectname, "class")
|
||||
if class_name:
|
||||
c = _resolve(class_name)
|
||||
f = c(fs, dfs)
|
||||
formatters[form] = f
|
||||
return formatters
|
||||
|
||||
|
||||
def _install_handlers(cp, formatters):
|
||||
"""Install and return handlers"""
|
||||
hlist = cp.get("handlers", "keys")
|
||||
if not len(hlist):
|
||||
return {}
|
||||
hlist = string.split(hlist, ",")
|
||||
handlers = {}
|
||||
fixups = [] #for inter-handler references
|
||||
for hand in hlist:
|
||||
hand = string.strip(hand)
|
||||
sectname = "handler_%s" % hand
|
||||
klass = cp.get(sectname, "class")
|
||||
opts = cp.options(sectname)
|
||||
if "formatter" in opts:
|
||||
fmt = cp.get(sectname, "formatter")
|
||||
else:
|
||||
fmt = ""
|
||||
try:
|
||||
klass = eval(klass, vars(logging))
|
||||
except (AttributeError, NameError):
|
||||
klass = _resolve(klass)
|
||||
args = cp.get(sectname, "args")
|
||||
args = eval(args, vars(logging))
|
||||
h = apply(klass, args)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
h.setLevel(logging._levelNames[level])
|
||||
if len(fmt):
|
||||
h.setFormatter(formatters[fmt])
|
||||
#temporary hack for FileHandler and MemoryHandler.
|
||||
if klass == logging.handlers.MemoryHandler:
|
||||
if "target" in opts:
|
||||
target = cp.get(sectname,"target")
|
||||
else:
|
||||
target = ""
|
||||
if len(target): #the target handler may not be loaded yet, so keep for later...
|
||||
fixups.append((h, target))
|
||||
handlers[hand] = h
|
||||
#now all handlers are loaded, fixup inter-handler references...
|
||||
for h, t in fixups:
|
||||
h.setTarget(handlers[t])
|
||||
return handlers
|
||||
|
||||
|
||||
def _install_loggers(cp, handlers):
|
||||
"""Create and install loggers"""
|
||||
|
||||
# configure the root first
|
||||
llist = cp.get("loggers", "keys")
|
||||
llist = string.split(llist, ",")
|
||||
llist = map(lambda x: string.strip(x), llist)
|
||||
llist.remove("root")
|
||||
sectname = "logger_root"
|
||||
root = logging.root
|
||||
log = root
|
||||
opts = cp.options(sectname)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
log.setLevel(logging._levelNames[level])
|
||||
for h in root.handlers[:]:
|
||||
root.removeHandler(h)
|
||||
hlist = cp.get(sectname, "handlers")
|
||||
if len(hlist):
|
||||
hlist = string.split(hlist, ",")
|
||||
for hand in hlist:
|
||||
log.addHandler(handlers[string.strip(hand)])
|
||||
|
||||
#and now the others...
|
||||
#we don't want to lose the existing loggers,
|
||||
#since other threads may have pointers to them.
|
||||
#existing is set to contain all existing loggers,
|
||||
#and as we go through the new configuration we
|
||||
#remove any which are configured. At the end,
|
||||
#what's left in existing is the set of loggers
|
||||
#which were in the previous configuration but
|
||||
#which are not in the new configuration.
|
||||
existing = root.manager.loggerDict.keys()
|
||||
#now set up the new ones...
|
||||
for log in llist:
|
||||
sectname = "logger_%s" % log
|
||||
qn = cp.get(sectname, "qualname")
|
||||
opts = cp.options(sectname)
|
||||
if "propagate" in opts:
|
||||
propagate = cp.getint(sectname, "propagate")
|
||||
else:
|
||||
propagate = 1
|
||||
logger = logging.getLogger(qn)
|
||||
if qn in existing:
|
||||
existing.remove(qn)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
logger.setLevel(logging._levelNames[level])
|
||||
for h in logger.handlers[:]:
|
||||
logger.removeHandler(h)
|
||||
logger.propagate = propagate
|
||||
logger.disabled = 0
|
||||
hlist = cp.get(sectname, "handlers")
|
||||
if len(hlist):
|
||||
hlist = string.split(hlist, ",")
|
||||
for hand in hlist:
|
||||
logger.addHandler(handlers[string.strip(hand)])
|
||||
|
||||
#Disable any old loggers. There's no point deleting
|
||||
#them as other threads may continue to hold references
|
||||
#and by disabling them, you stop them doing any logging.
|
||||
for log in existing:
|
||||
root.manager.loggerDict[log].disabled = 1
|
||||
|
||||
|
||||
def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
|
||||
"""
|
||||
Start up a socket server on the specified port, and listen for new
|
||||
configurations.
|
||||
|
||||
These will be sent as a file suitable for processing by fileConfig().
|
||||
Returns a Thread object on which you can call start() to start the server,
|
||||
and which you can join() when appropriate. To stop the server, call
|
||||
stopListening().
|
||||
"""
|
||||
if not thread:
|
||||
raise NotImplementedError, "listen() needs threading to work"
|
||||
|
||||
class ConfigStreamHandler(StreamRequestHandler):
|
||||
"""
|
||||
Handler for a logging configuration request.
|
||||
|
||||
It expects a completely new logging configuration and uses fileConfig
|
||||
to install it.
|
||||
"""
|
||||
def handle(self):
|
||||
"""
|
||||
Handle a request.
|
||||
|
||||
Each request is expected to be a 4-byte length, packed using
|
||||
struct.pack(">L", n), followed by the config file.
|
||||
Uses fileConfig() to do the grunt work.
|
||||
"""
|
||||
import tempfile
|
||||
try:
|
||||
conn = self.connection
|
||||
chunk = conn.recv(4)
|
||||
if len(chunk) == 4:
|
||||
slen = struct.unpack(">L", chunk)[0]
|
||||
chunk = self.connection.recv(slen)
|
||||
while len(chunk) < slen:
|
||||
chunk = chunk + conn.recv(slen - len(chunk))
|
||||
#Apply new configuration. We'd like to be able to
|
||||
#create a StringIO and pass that in, but unfortunately
|
||||
#1.5.2 ConfigParser does not support reading file
|
||||
#objects, only actual files. So we create a temporary
|
||||
#file and remove it later.
|
||||
file = tempfile.mktemp(".ini")
|
||||
f = open(file, "w")
|
||||
f.write(chunk)
|
||||
f.close()
|
||||
try:
|
||||
fileConfig(file)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
traceback.print_exc()
|
||||
os.remove(file)
|
||||
except socket.error, e:
|
||||
if type(e.args) != types.TupleType:
|
||||
raise
|
||||
else:
|
||||
errcode = e.args[0]
|
||||
if errcode != RESET_ERROR:
|
||||
raise
|
||||
|
||||
class ConfigSocketReceiver(ThreadingTCPServer):
|
||||
"""
|
||||
A simple TCP socket-based logging config receiver.
|
||||
"""
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
|
||||
handler=None):
|
||||
ThreadingTCPServer.__init__(self, (host, port), handler)
|
||||
logging._acquireLock()
|
||||
self.abort = 0
|
||||
logging._releaseLock()
|
||||
self.timeout = 1
|
||||
|
||||
def serve_until_stopped(self):
|
||||
import select
|
||||
abort = 0
|
||||
while not abort:
|
||||
rd, wr, ex = select.select([self.socket.fileno()],
|
||||
[], [],
|
||||
self.timeout)
|
||||
if rd:
|
||||
self.handle_request()
|
||||
logging._acquireLock()
|
||||
abort = self.abort
|
||||
logging._releaseLock()
|
||||
|
||||
def serve(rcvr, hdlr, port):
|
||||
server = rcvr(port=port, handler=hdlr)
|
||||
global _listener
|
||||
logging._acquireLock()
|
||||
_listener = server
|
||||
logging._releaseLock()
|
||||
server.serve_until_stopped()
|
||||
|
||||
return threading.Thread(target=serve,
|
||||
args=(ConfigSocketReceiver,
|
||||
ConfigStreamHandler, port))
|
||||
|
||||
def stopListening():
|
||||
"""
|
||||
Stop the listening server which was created with a call to listen().
|
||||
"""
|
||||
global _listener
|
||||
if _listener:
|
||||
logging._acquireLock()
|
||||
_listener.abort = 1
|
||||
_listener = None
|
||||
logging._releaseLock()
|
||||
32
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/secret.py
Executable file
32
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/secret.py
Executable file
@@ -0,0 +1,32 @@
|
||||
# (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
|
||||
"""
|
||||
Create random secrets.
|
||||
"""
|
||||
|
||||
import os
|
||||
import random
|
||||
|
||||
def random_bytes(length):
|
||||
"""
|
||||
Return a string of the given length. Uses ``os.urandom`` if it
|
||||
can, or just pseudo-random numbers otherwise.
|
||||
"""
|
||||
try:
|
||||
return os.urandom(length)
|
||||
except AttributeError:
|
||||
return ''.join([
|
||||
chr(random.randrange(256)) for i in xrange(length)])
|
||||
|
||||
def secret_string(length=25):
|
||||
"""
|
||||
Returns a random string of the given length. The string
|
||||
is a base64-encoded version of a set of random bytes, truncated
|
||||
to the given length (and without any newlines).
|
||||
"""
|
||||
s = random_bytes(length).encode('base64')
|
||||
for badchar in '\n\r=':
|
||||
s = s.replace(badchar, '')
|
||||
# We're wasting some characters here. But random characters are
|
||||
# cheap ;)
|
||||
return s[:length]
|
||||
533
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/string24.py
Executable file
533
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/string24.py
Executable file
@@ -0,0 +1,533 @@
|
||||
# (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 collection of string operations (most are no longer used).
|
||||
|
||||
Warning: most of the code you see here isn't normally used nowadays.
|
||||
Beginning with Python 1.6, many of these functions are implemented as
|
||||
methods on the standard string object. They used to be implemented by
|
||||
a built-in module called strop, but strop is now obsolete itself.
|
||||
|
||||
Public module variables:
|
||||
|
||||
whitespace -- a string containing all characters considered whitespace
|
||||
lowercase -- a string containing all characters considered lowercase letters
|
||||
uppercase -- a string containing all characters considered uppercase letters
|
||||
letters -- a string containing all characters considered letters
|
||||
digits -- a string containing all characters considered decimal digits
|
||||
hexdigits -- a string containing all characters considered hexadecimal digits
|
||||
octdigits -- a string containing all characters considered octal digits
|
||||
punctuation -- a string containing all characters considered punctuation
|
||||
printable -- a string containing all characters considered printable
|
||||
|
||||
"""
|
||||
|
||||
# Some strings for ctype-style character classification
|
||||
whitespace = ' \t\n\r\v\f'
|
||||
lowercase = 'abcdefghijklmnopqrstuvwxyz'
|
||||
uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
letters = lowercase + uppercase
|
||||
ascii_lowercase = lowercase
|
||||
ascii_uppercase = uppercase
|
||||
ascii_letters = ascii_lowercase + ascii_uppercase
|
||||
digits = '0123456789'
|
||||
hexdigits = digits + 'abcdef' + 'ABCDEF'
|
||||
octdigits = '01234567'
|
||||
punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||
printable = digits + letters + punctuation + whitespace
|
||||
|
||||
# Case conversion helpers
|
||||
# Use str to convert Unicode literal in case of -U
|
||||
# Note that Cookie.py bogusly uses _idmap :(
|
||||
l = map(chr, xrange(256))
|
||||
_idmap = str('').join(l)
|
||||
del l
|
||||
|
||||
# Functions which aren't available as string methods.
|
||||
|
||||
# Capitalize the words in a string, e.g. " aBc dEf " -> "Abc Def".
|
||||
# See also regsub.capwords().
|
||||
def capwords(s, sep=None):
|
||||
"""capwords(s, [sep]) -> string
|
||||
|
||||
Split the argument into words using split, capitalize each
|
||||
word using capitalize, and join the capitalized words using
|
||||
join. Note that this replaces runs of whitespace characters by
|
||||
a single space.
|
||||
|
||||
"""
|
||||
return (sep or ' ').join([x.capitalize() for x in s.split(sep)])
|
||||
|
||||
|
||||
# Construct a translation string
|
||||
_idmapL = None
|
||||
def maketrans(fromstr, tostr):
|
||||
"""maketrans(frm, to) -> string
|
||||
|
||||
Return a translation table (a string of 256 bytes long)
|
||||
suitable for use in string.translate. The strings frm and to
|
||||
must be of the same length.
|
||||
|
||||
"""
|
||||
if len(fromstr) != len(tostr):
|
||||
raise ValueError, "maketrans arguments must have same length"
|
||||
global _idmapL
|
||||
if not _idmapL:
|
||||
_idmapL = map(None, _idmap)
|
||||
L = _idmapL[:]
|
||||
fromstr = map(ord, fromstr)
|
||||
for i in range(len(fromstr)):
|
||||
L[fromstr[i]] = tostr[i]
|
||||
return ''.join(L)
|
||||
|
||||
|
||||
|
||||
####################################################################
|
||||
import re as _re
|
||||
|
||||
class _multimap:
|
||||
"""Helper class for combining multiple mappings.
|
||||
|
||||
Used by .{safe_,}substitute() to combine the mapping and keyword
|
||||
arguments.
|
||||
"""
|
||||
def __init__(self, primary, secondary):
|
||||
self._primary = primary
|
||||
self._secondary = secondary
|
||||
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
return self._primary[key]
|
||||
except KeyError:
|
||||
return self._secondary[key]
|
||||
|
||||
|
||||
class _TemplateMetaclass(type):
|
||||
pattern = r"""
|
||||
%(delim)s(?:
|
||||
(?P<escaped>%(delim)s) | # Escape sequence of two delimiters
|
||||
(?P<named>%(id)s) | # delimiter and a Python identifier
|
||||
{(?P<braced>%(id)s)} | # delimiter and a braced identifier
|
||||
(?P<invalid>) # Other ill-formed delimiter exprs
|
||||
)
|
||||
"""
|
||||
|
||||
def __init__(cls, name, bases, dct):
|
||||
super(_TemplateMetaclass, cls).__init__(name, bases, dct)
|
||||
if 'pattern' in dct:
|
||||
pattern = cls.pattern
|
||||
else:
|
||||
pattern = _TemplateMetaclass.pattern % {
|
||||
'delim' : _re.escape(cls.delimiter),
|
||||
'id' : cls.idpattern,
|
||||
}
|
||||
cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
|
||||
|
||||
|
||||
class Template:
|
||||
"""A string class for supporting $-substitutions."""
|
||||
__metaclass__ = _TemplateMetaclass
|
||||
|
||||
delimiter = '$'
|
||||
idpattern = r'[_a-z][_a-z0-9]*'
|
||||
|
||||
def __init__(self, template):
|
||||
self.template = template
|
||||
|
||||
# Search for $$, $identifier, ${identifier}, and any bare $'s
|
||||
|
||||
def _invalid(self, mo):
|
||||
i = mo.start('invalid')
|
||||
lines = self.template[:i].splitlines(True)
|
||||
if not lines:
|
||||
colno = 1
|
||||
lineno = 1
|
||||
else:
|
||||
colno = i - len(''.join(lines[:-1]))
|
||||
lineno = len(lines)
|
||||
raise ValueError('Invalid placeholder in string: line %d, col %d' %
|
||||
(lineno, colno))
|
||||
|
||||
def substitute(self, *args, **kws):
|
||||
if len(args) > 1:
|
||||
raise TypeError('Too many positional arguments')
|
||||
if not args:
|
||||
mapping = kws
|
||||
elif kws:
|
||||
mapping = _multimap(kws, args[0])
|
||||
else:
|
||||
mapping = args[0]
|
||||
# Helper function for .sub()
|
||||
def convert(mo):
|
||||
# Check the most common path first.
|
||||
named = mo.group('named') or mo.group('braced')
|
||||
if named is not None:
|
||||
val = mapping[named]
|
||||
# We use this idiom instead of str() because the latter will
|
||||
# fail if val is a Unicode containing non-ASCII characters.
|
||||
return '%s' % val
|
||||
if mo.group('escaped') is not None:
|
||||
return self.delimiter
|
||||
if mo.group('invalid') is not None:
|
||||
self._invalid(mo)
|
||||
raise ValueError('Unrecognized named group in pattern',
|
||||
self.pattern)
|
||||
return self.pattern.sub(convert, self.template)
|
||||
|
||||
def safe_substitute(self, *args, **kws):
|
||||
if len(args) > 1:
|
||||
raise TypeError('Too many positional arguments')
|
||||
if not args:
|
||||
mapping = kws
|
||||
elif kws:
|
||||
mapping = _multimap(kws, args[0])
|
||||
else:
|
||||
mapping = args[0]
|
||||
# Helper function for .sub()
|
||||
def convert(mo):
|
||||
named = mo.group('named')
|
||||
if named is not None:
|
||||
try:
|
||||
# We use this idiom instead of str() because the latter
|
||||
# will fail if val is a Unicode containing non-ASCII
|
||||
return '%s' % mapping[named]
|
||||
except KeyError:
|
||||
return self.delimiter + named
|
||||
braced = mo.group('braced')
|
||||
if braced is not None:
|
||||
try:
|
||||
return '%s' % mapping[braced]
|
||||
except KeyError:
|
||||
return self.delimiter + '{' + braced + '}'
|
||||
if mo.group('escaped') is not None:
|
||||
return self.delimiter
|
||||
if mo.group('invalid') is not None:
|
||||
return self.delimiter
|
||||
raise ValueError('Unrecognized named group in pattern',
|
||||
self.pattern)
|
||||
return self.pattern.sub(convert, self.template)
|
||||
|
||||
|
||||
|
||||
####################################################################
|
||||
# NOTE: Everything below here is deprecated. Use string methods instead.
|
||||
# This stuff will go away in Python 3.0.
|
||||
|
||||
# Backward compatible names for exceptions
|
||||
index_error = ValueError
|
||||
atoi_error = ValueError
|
||||
atof_error = ValueError
|
||||
atol_error = ValueError
|
||||
|
||||
# convert UPPER CASE letters to lower case
|
||||
def lower(s):
|
||||
"""lower(s) -> string
|
||||
|
||||
Return a copy of the string s converted to lowercase.
|
||||
|
||||
"""
|
||||
return s.lower()
|
||||
|
||||
# Convert lower case letters to UPPER CASE
|
||||
def upper(s):
|
||||
"""upper(s) -> string
|
||||
|
||||
Return a copy of the string s converted to uppercase.
|
||||
|
||||
"""
|
||||
return s.upper()
|
||||
|
||||
# Swap lower case letters and UPPER CASE
|
||||
def swapcase(s):
|
||||
"""swapcase(s) -> string
|
||||
|
||||
Return a copy of the string s with upper case characters
|
||||
converted to lowercase and vice versa.
|
||||
|
||||
"""
|
||||
return s.swapcase()
|
||||
|
||||
# Strip leading and trailing tabs and spaces
|
||||
def strip(s, chars=None):
|
||||
"""strip(s [,chars]) -> string
|
||||
|
||||
Return a copy of the string s with leading and trailing
|
||||
whitespace removed.
|
||||
If chars is given and not None, remove characters in chars instead.
|
||||
If chars is unicode, S will be converted to unicode before stripping.
|
||||
|
||||
"""
|
||||
return s.strip(chars)
|
||||
|
||||
# Strip leading tabs and spaces
|
||||
def lstrip(s, chars=None):
|
||||
"""lstrip(s [,chars]) -> string
|
||||
|
||||
Return a copy of the string s with leading whitespace removed.
|
||||
If chars is given and not None, remove characters in chars instead.
|
||||
|
||||
"""
|
||||
return s.lstrip(chars)
|
||||
|
||||
# Strip trailing tabs and spaces
|
||||
def rstrip(s, chars=None):
|
||||
"""rstrip(s [,chars]) -> string
|
||||
|
||||
Return a copy of the string s with trailing whitespace removed.
|
||||
If chars is given and not None, remove characters in chars instead.
|
||||
|
||||
"""
|
||||
return s.rstrip(chars)
|
||||
|
||||
|
||||
# Split a string into a list of space/tab-separated words
|
||||
def split(s, sep=None, maxsplit=-1):
|
||||
"""split(s [,sep [,maxsplit]]) -> list of strings
|
||||
|
||||
Return a list of the words in the string s, using sep as the
|
||||
delimiter string. If maxsplit is given, splits at no more than
|
||||
maxsplit places (resulting in at most maxsplit+1 words). If sep
|
||||
is not specified or is None, any whitespace string is a separator.
|
||||
|
||||
(split and splitfields are synonymous)
|
||||
|
||||
"""
|
||||
return s.split(sep, maxsplit)
|
||||
splitfields = split
|
||||
|
||||
# Split a string into a list of space/tab-separated words
|
||||
def rsplit(s, sep=None, maxsplit=-1):
|
||||
"""rsplit(s [,sep [,maxsplit]]) -> list of strings
|
||||
|
||||
Return a list of the words in the string s, using sep as the
|
||||
delimiter string, starting at the end of the string and working
|
||||
to the front. If maxsplit is given, at most maxsplit splits are
|
||||
done. If sep is not specified or is None, any whitespace string
|
||||
is a separator.
|
||||
"""
|
||||
return s.rsplit(sep, maxsplit)
|
||||
|
||||
# Join fields with optional separator
|
||||
def join(words, sep = ' '):
|
||||
"""join(list [,sep]) -> string
|
||||
|
||||
Return a string composed of the words in list, with
|
||||
intervening occurrences of sep. The default separator is a
|
||||
single space.
|
||||
|
||||
(joinfields and join are synonymous)
|
||||
|
||||
"""
|
||||
return sep.join(words)
|
||||
joinfields = join
|
||||
|
||||
# Find substring, raise exception if not found
|
||||
def index(s, *args):
|
||||
"""index(s, sub [,start [,end]]) -> int
|
||||
|
||||
Like find but raises ValueError when the substring is not found.
|
||||
|
||||
"""
|
||||
return s.index(*args)
|
||||
|
||||
# Find last substring, raise exception if not found
|
||||
def rindex(s, *args):
|
||||
"""rindex(s, sub [,start [,end]]) -> int
|
||||
|
||||
Like rfind but raises ValueError when the substring is not found.
|
||||
|
||||
"""
|
||||
return s.rindex(*args)
|
||||
|
||||
# Count non-overlapping occurrences of substring
|
||||
def count(s, *args):
|
||||
"""count(s, sub[, start[,end]]) -> int
|
||||
|
||||
Return the number of occurrences of substring sub in string
|
||||
s[start:end]. Optional arguments start and end are
|
||||
interpreted as in slice notation.
|
||||
|
||||
"""
|
||||
return s.count(*args)
|
||||
|
||||
# Find substring, return -1 if not found
|
||||
def find(s, *args):
|
||||
"""find(s, sub [,start [,end]]) -> in
|
||||
|
||||
Return the lowest index in s where substring sub is found,
|
||||
such that sub is contained within s[start,end]. Optional
|
||||
arguments start and end are interpreted as in slice notation.
|
||||
|
||||
Return -1 on failure.
|
||||
|
||||
"""
|
||||
return s.find(*args)
|
||||
|
||||
# Find last substring, return -1 if not found
|
||||
def rfind(s, *args):
|
||||
"""rfind(s, sub [,start [,end]]) -> int
|
||||
|
||||
Return the highest index in s where substring sub is found,
|
||||
such that sub is contained within s[start,end]. Optional
|
||||
arguments start and end are interpreted as in slice notation.
|
||||
|
||||
Return -1 on failure.
|
||||
|
||||
"""
|
||||
return s.rfind(*args)
|
||||
|
||||
# for a bit of speed
|
||||
_float = float
|
||||
_int = int
|
||||
_long = long
|
||||
|
||||
# Convert string to float
|
||||
def atof(s):
|
||||
"""atof(s) -> float
|
||||
|
||||
Return the floating point number represented by the string s.
|
||||
|
||||
"""
|
||||
return _float(s)
|
||||
|
||||
|
||||
# Convert string to integer
|
||||
def atoi(s , base=10):
|
||||
"""atoi(s [,base]) -> int
|
||||
|
||||
Return the integer represented by the string s in the given
|
||||
base, which defaults to 10. The string s must consist of one
|
||||
or more digits, possibly preceded by a sign. If base is 0, it
|
||||
is chosen from the leading characters of s, 0 for octal, 0x or
|
||||
0X for hexadecimal. If base is 16, a preceding 0x or 0X is
|
||||
accepted.
|
||||
|
||||
"""
|
||||
return _int(s, base)
|
||||
|
||||
|
||||
# Convert string to long integer
|
||||
def atol(s, base=10):
|
||||
"""atol(s [,base]) -> long
|
||||
|
||||
Return the long integer represented by the string s in the
|
||||
given base, which defaults to 10. The string s must consist
|
||||
of one or more digits, possibly preceded by a sign. If base
|
||||
is 0, it is chosen from the leading characters of s, 0 for
|
||||
octal, 0x or 0X for hexadecimal. If base is 16, a preceding
|
||||
0x or 0X is accepted. A trailing L or l is not accepted,
|
||||
unless base is 0.
|
||||
|
||||
"""
|
||||
return _long(s, base)
|
||||
|
||||
|
||||
# Left-justify a string
|
||||
def ljust(s, width, *args):
|
||||
"""ljust(s, width[, fillchar]) -> string
|
||||
|
||||
Return a left-justified version of s, in a field of the
|
||||
specified width, padded with spaces as needed. The string is
|
||||
never truncated. If specified the fillchar is used instead of spaces.
|
||||
|
||||
"""
|
||||
return s.ljust(width, *args)
|
||||
|
||||
# Right-justify a string
|
||||
def rjust(s, width, *args):
|
||||
"""rjust(s, width[, fillchar]) -> string
|
||||
|
||||
Return a right-justified version of s, in a field of the
|
||||
specified width, padded with spaces as needed. The string is
|
||||
never truncated. If specified the fillchar is used instead of spaces.
|
||||
|
||||
"""
|
||||
return s.rjust(width, *args)
|
||||
|
||||
# Center a string
|
||||
def center(s, width, *args):
|
||||
"""center(s, width[, fillchar]) -> string
|
||||
|
||||
Return a center version of s, in a field of the specified
|
||||
width. padded with spaces as needed. The string is never
|
||||
truncated. If specified the fillchar is used instead of spaces.
|
||||
|
||||
"""
|
||||
return s.center(width, *args)
|
||||
|
||||
# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
|
||||
# Decadent feature: the argument may be a string or a number
|
||||
# (Use of this is deprecated; it should be a string as with ljust c.s.)
|
||||
def zfill(x, width):
|
||||
"""zfill(x, width) -> string
|
||||
|
||||
Pad a numeric string x with zeros on the left, to fill a field
|
||||
of the specified width. The string x is never truncated.
|
||||
|
||||
"""
|
||||
if not isinstance(x, basestring):
|
||||
x = repr(x)
|
||||
return x.zfill(width)
|
||||
|
||||
# Expand tabs in a string.
|
||||
# Doesn't take non-printing chars into account, but does understand \n.
|
||||
def expandtabs(s, tabsize=8):
|
||||
"""expandtabs(s [,tabsize]) -> string
|
||||
|
||||
Return a copy of the string s with all tab characters replaced
|
||||
by the appropriate number of spaces, depending on the current
|
||||
column, and the tabsize (default 8).
|
||||
|
||||
"""
|
||||
return s.expandtabs(tabsize)
|
||||
|
||||
# Character translation through look-up table.
|
||||
def translate(s, table, deletions=""):
|
||||
"""translate(s,table [,deletions]) -> string
|
||||
|
||||
Return a copy of the string s, where all characters occurring
|
||||
in the optional argument deletions are removed, and the
|
||||
remaining characters have been mapped through the given
|
||||
translation table, which must be a string of length 256. The
|
||||
deletions argument is not allowed for Unicode strings.
|
||||
|
||||
"""
|
||||
if deletions:
|
||||
return s.translate(table, deletions)
|
||||
else:
|
||||
# Add s[:0] so that if s is Unicode and table is an 8-bit string,
|
||||
# table is converted to Unicode. This means that table *cannot*
|
||||
# be a dictionary -- for that feature, use u.translate() directly.
|
||||
return s.translate(table + s[:0])
|
||||
|
||||
# Capitalize a string, e.g. "aBc dEf" -> "Abc def".
|
||||
def capitalize(s):
|
||||
"""capitalize(s) -> string
|
||||
|
||||
Return a copy of the string s with only its first character
|
||||
capitalized.
|
||||
|
||||
"""
|
||||
return s.capitalize()
|
||||
|
||||
# Substring replacement (global)
|
||||
def replace(s, old, new, maxsplit=-1):
|
||||
"""replace (str, old, new[, maxsplit]) -> string
|
||||
|
||||
Return a copy of string str with all occurrences of substring
|
||||
old replaced by new. If the optional argument maxsplit is
|
||||
given, only the first maxsplit occurrences are replaced.
|
||||
|
||||
"""
|
||||
return s.replace(old, new, maxsplit)
|
||||
|
||||
|
||||
# Try importing optional built-in module "strop" -- if it exists,
|
||||
# it redefines some string operations that are 100-1000 times faster.
|
||||
# It also defines values for whitespace, lowercase and uppercase
|
||||
# that match <ctype.h>'s definitions.
|
||||
|
||||
try:
|
||||
from strop import maketrans, lowercase, uppercase, whitespace
|
||||
letters = lowercase + uppercase
|
||||
except ImportError:
|
||||
pass # Use the original versions
|
||||
1154
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/subprocess24.py
Executable file
1154
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/subprocess24.py
Executable file
File diff suppressed because it is too large
Load Diff
240
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/uuid.py
Executable file
240
PasteScript-1.7.4.2-py2.6.egg/paste/script/util/uuid.py
Executable file
@@ -0,0 +1,240 @@
|
||||
# (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
|
||||
"""UUID (universally unique identifiers) as specified in RFC 4122.
|
||||
|
||||
This module provides the UUID class and the functions uuid1(), uuid3(),
|
||||
uuid4(), uuid5() for generating version 1, 3, 4, and 5 UUIDs respectively.
|
||||
|
||||
This module works with Python 2.3 or higher."""
|
||||
|
||||
__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
|
||||
__date__ = '$Date: 2005/11/30 11:51:58 $'.split()[1].replace('/', '-')
|
||||
__version__ = '$Revision: 1.10 $'
|
||||
|
||||
RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
|
||||
'reserved for NCS compatibility', 'specified in RFC 4122',
|
||||
'reserved for Microsoft compatibility', 'reserved for future definition']
|
||||
|
||||
class UUID(object):
|
||||
"""Instances of the UUID class represent UUIDs as specified in RFC 4122.
|
||||
Converting a UUID to a string using str() produces a string in the form
|
||||
"{12345678-1234-1234-1234-123456789abc}". The UUID constructor accepts
|
||||
a similar string (braces and hyphens optional), or six integer arguments
|
||||
(with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 48-bit values
|
||||
respectively). UUID objects have the following attributes:
|
||||
|
||||
bytes gets or sets the UUID as a 16-byte string
|
||||
|
||||
urn gets the UUID as a URN as specified in RFC 4122
|
||||
|
||||
variant gets or sets the UUID variant as one of the constants
|
||||
RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE
|
||||
|
||||
version gets or sets the UUID version number (1 through 5)
|
||||
"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""Create a UUID either from a string representation in hexadecimal
|
||||
or from six integers (32-bit time_low, 16-bit time_mid, 16-bit
|
||||
time_hi_ver, 8-bit clock_hi_res, 8-bit clock_low, 48-bit node)."""
|
||||
if len(args) == 1:
|
||||
digits = args[0].replace('urn:', '').replace('uuid:', '')
|
||||
digits = digits.replace('{', '').replace('}', '').replace('-', '')
|
||||
assert len(digits) == 32, ValueError('badly formed UUID string')
|
||||
time_low = int(digits[:8], 16)
|
||||
time_mid = int(digits[8:12], 16)
|
||||
time_hi_ver = int(digits[12:16], 16)
|
||||
clock_hi_res = int(digits[16:18], 16)
|
||||
clock_low = int(digits[18:20], 16)
|
||||
node = int(digits[20:32], 16)
|
||||
else:
|
||||
(time_low, time_mid, time_hi_ver,
|
||||
clock_hi_res, clock_low, node) = args
|
||||
assert 0 <= time_low < 0x100000000, ValueError('time_low out of range')
|
||||
assert 0 <= time_mid < 1<<16, ValueError('time_mid out of range')
|
||||
assert 0 <= time_hi_ver < 1<<16, ValueError('time_hi_ver out of range')
|
||||
assert 0 <= clock_hi_res < 1<<8, ValueError('clock_hi_res out of range')
|
||||
assert 0 <= clock_low < 1<<8, ValueError('clock_low out of range')
|
||||
assert 0 <= node < 0x1000000000000, ValueError('node out of range')
|
||||
self.time_low = time_low
|
||||
self.time_mid = time_mid
|
||||
self.time_hi_ver = time_hi_ver
|
||||
self.clock_hi_res = clock_hi_res
|
||||
self.clock_low = clock_low
|
||||
self.node = node
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.bytes, getattr(other, 'bytes', other))
|
||||
|
||||
def __str__(self):
|
||||
return '{%08x-%04x-%04x-%02x%02x-%012x}' % (
|
||||
self.time_low, self.time_mid, self.time_hi_ver,
|
||||
self.clock_hi_res, self.clock_low, self.node)
|
||||
|
||||
def __repr__(self):
|
||||
return 'UUID(%r)' % str(self)
|
||||
|
||||
def get_bytes(self):
|
||||
def byte(n):
|
||||
return chr(n & 0xff)
|
||||
|
||||
return (byte(self.time_low >> 24) + byte(self.time_low >> 16) +
|
||||
byte(self.time_low >> 8) + byte(self.time_low) +
|
||||
byte(self.time_mid >> 8) + byte(self.time_mid) +
|
||||
byte(self.time_hi_ver >> 8) + byte(self.time_hi_ver) +
|
||||
byte(self.clock_hi_res) + byte(self.clock_low) +
|
||||
byte(self.node >> 40) + byte(self.node >> 32) +
|
||||
byte(self.node >> 24) + byte(self.node >> 16) +
|
||||
byte(self.node >> 8) + byte(self.node))
|
||||
|
||||
def set_bytes(self, bytes):
|
||||
values = map(ord, bytes)
|
||||
self.time_low = ((values[0] << 24) + (values[1] << 16) +
|
||||
(values[2] << 8) + values[3])
|
||||
self.time_mid = (values[4] << 8) + values[5]
|
||||
self.time_hi_ver = (values[6] << 8) + values[7]
|
||||
self.clock_hi_res = values[8]
|
||||
self.clock_low = values[9]
|
||||
self.node = ((values[10] << 40) + (values[11] << 32) +
|
||||
(values[12] << 24) + (values[13] << 16) +
|
||||
(values[14] << 8) + values[15])
|
||||
|
||||
bytes = property(get_bytes, set_bytes)
|
||||
|
||||
def get_urn(self):
|
||||
return 'urn:uuid:%08x-%04x-%04x-%02x%02x-%012x' % (
|
||||
self.time_low, self.time_mid, self.time_hi_ver,
|
||||
self.clock_hi_res, self.clock_low, self.node)
|
||||
|
||||
urn = property(get_urn)
|
||||
|
||||
def get_variant(self):
|
||||
if not self.clock_hi_res & 0x80:
|
||||
return RESERVED_NCS
|
||||
elif not self.clock_hi_res & 0x40:
|
||||
return RFC_4122
|
||||
elif not self.clock_hi_res & 0x20:
|
||||
return RESERVED_MICROSOFT
|
||||
else:
|
||||
return RESERVED_FUTURE
|
||||
|
||||
def set_variant(self, variant):
|
||||
if variant == RESERVED_NCS:
|
||||
self.clock_hi_res &= 0x7f
|
||||
elif variant == RFC_4122:
|
||||
self.clock_hi_res &= 0x3f
|
||||
self.clock_hi_res |= 0x80
|
||||
elif variant == RESERVED_MICROSOFT:
|
||||
self.clock_hi_res &= 0x1f
|
||||
self.clock_hi_res |= 0xc0
|
||||
elif variant == RESERVED_FUTURE:
|
||||
self.clock_hi_res &= 0x1f
|
||||
self.clock_hi_res |= 0xe0
|
||||
else:
|
||||
raise ValueError('illegal variant identifier')
|
||||
|
||||
variant = property(get_variant, set_variant)
|
||||
|
||||
def get_version(self):
|
||||
return self.time_hi_ver >> 12
|
||||
|
||||
def set_version(self, version):
|
||||
assert 1 <= version <= 5, ValueError('illegal version number')
|
||||
self.time_hi_ver &= 0x0fff
|
||||
self.time_hi_ver |= (version << 12)
|
||||
|
||||
version = property(get_version, set_version)
|
||||
|
||||
def unixgetaddr(program):
|
||||
"""Get the hardware address on a Unix machine."""
|
||||
from os import popen
|
||||
for line in popen(program):
|
||||
words = line.lower().split()
|
||||
if 'hwaddr' in words:
|
||||
addr = words[words.index('hwaddr') + 1]
|
||||
return int(addr.replace(':', ''), 16)
|
||||
if 'ether' in words:
|
||||
addr = words[words.index('ether') + 1]
|
||||
return int(addr.replace(':', ''), 16)
|
||||
|
||||
def wingetaddr(program):
|
||||
"""Get the hardware address on a Windows machine."""
|
||||
from os import popen
|
||||
for line in popen(program + ' /all'):
|
||||
if line.strip().lower().startswith('physical address'):
|
||||
addr = line.split(':')[-1].strip()
|
||||
return int(addr.replace('-', ''), 16)
|
||||
|
||||
def getaddr():
|
||||
"""Get the hardware address as a 48-bit integer."""
|
||||
from os.path import join, isfile
|
||||
for dir in ['/sbin', '/usr/sbin', r'c:\windows',
|
||||
r'c:\windows\system', r'c:\windows\system32']:
|
||||
if isfile(join(dir, 'ifconfig')):
|
||||
return unixgetaddr(join(dir, 'ifconfig'))
|
||||
if isfile(join(dir, 'ipconfig.exe')):
|
||||
return wingetaddr(join(dir, 'ipconfig.exe'))
|
||||
|
||||
def uuid1():
|
||||
"""Generate a UUID based on the time and hardware address."""
|
||||
from time import time
|
||||
from random import randrange
|
||||
nanoseconds = int(time() * 1e9)
|
||||
# 0x01b21dd213814000 is the number of 100-ns intervals between the
|
||||
# UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
|
||||
timestamp = int(nanoseconds/100) + 0x01b21dd213814000
|
||||
clock = randrange(1<<16) # don't use stable storage
|
||||
time_low = timestamp & (0x100000000 - 1)
|
||||
time_mid = (timestamp >> 32) & 0xffff
|
||||
time_hi_ver = (timestamp >> 48) & 0x0fff
|
||||
clock_low = clock & 0xff
|
||||
clock_hi_res = (clock >> 8) & 0x3f
|
||||
node = getaddr()
|
||||
uuid = UUID(time_low, time_mid, time_hi_ver, clock_low, clock_hi_res, node)
|
||||
uuid.variant = RFC_4122
|
||||
uuid.version = 1
|
||||
return uuid
|
||||
|
||||
def uuid3(namespace, name):
|
||||
"""Generate a UUID from the MD5 hash of a namespace UUID and a name."""
|
||||
try:
|
||||
from hashlib import md5
|
||||
except ImportError:
|
||||
from md5 import md5
|
||||
uuid = UUID(0, 0, 0, 0, 0, 0)
|
||||
uuid.bytes = md5(namespace.bytes + name).digest()[:16]
|
||||
uuid.variant = RFC_4122
|
||||
uuid.version = 3
|
||||
return uuid
|
||||
|
||||
def uuid4():
|
||||
"""Generate a random UUID."""
|
||||
try:
|
||||
from os import urandom
|
||||
except:
|
||||
from random import randrange
|
||||
uuid = UUID(randrange(1<<32L), randrange(1<<16), randrange(1<<16),
|
||||
randrange(1<<8), randrange(1<<8), randrange(1<<48L))
|
||||
else:
|
||||
uuid = UUID(0, 0, 0, 0, 0, 0)
|
||||
uuid.bytes = urandom(16)
|
||||
uuid.variant = RFC_4122
|
||||
uuid.version = 4
|
||||
return uuid
|
||||
|
||||
def uuid5(namespace, name):
|
||||
"""Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
|
||||
try:
|
||||
from hashlib import sha1
|
||||
except ImportError:
|
||||
from sha import sha as sha1
|
||||
uuid = UUID(0, 0, 0, 0, 0, 0)
|
||||
uuid.bytes = sha1(namespace.bytes + name).digest()[:16]
|
||||
uuid.variant = RFC_4122
|
||||
uuid.version = 5
|
||||
return uuid
|
||||
|
||||
NAMESPACE_DNS = UUID('{6ba7b810-9dad-11d1-80b4-00c04fd430c8}')
|
||||
NAMESPACE_URL = UUID('{6ba7b811-9dad-11d1-80b4-00c04fd430c8}')
|
||||
NAMESPACE_OID = UUID('{6ba7b812-9dad-11d1-80b4-00c04fd430c8}')
|
||||
NAMESPACE_X500 = UUID('{6ba7b814-9dad-11d1-80b4-00c04fd430c8}')
|
||||
19
PasteScript-1.7.4.2-py2.6.egg/paste/script/wsgiutils_server.py
Executable file
19
PasteScript-1.7.4.2-py2.6.egg/paste/script/wsgiutils_server.py
Executable file
@@ -0,0 +1,19 @@
|
||||
# (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()
|
||||
|
||||
34
PasteScript-1.7.4.2-py2.6.egg/tests/__init__.py
Executable file
34
PasteScript-1.7.4.2-py2.6.egg/tests/__init__.py
Executable file
@@ -0,0 +1,34 @@
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import pkg_resources
|
||||
|
||||
here = os.path.dirname(__file__)
|
||||
base = os.path.dirname(here)
|
||||
fake_packages = os.path.join(here, 'fake_packages')
|
||||
sys.path.append(fake_packages)
|
||||
sys.path.append(here)
|
||||
sys.path.insert(0, base)
|
||||
|
||||
here = os.path.dirname(__file__)
|
||||
egg_info_dir = os.path.join(here, 'fake_packages', 'FakePlugin.egg',
|
||||
'EGG-INFO')
|
||||
info_dir = os.path.join(here, 'fake_packages', 'FakePlugin.egg',
|
||||
'FakePlugin.egg-info')
|
||||
|
||||
if not os.path.exists(egg_info_dir):
|
||||
try:
|
||||
os.symlink(info_dir, egg_info_dir)
|
||||
except:
|
||||
shutil.copytree(info_dir, egg_info_dir)
|
||||
|
||||
pkg_resources.working_set.add_entry(fake_packages)
|
||||
pkg_resources.working_set.add_entry(base)
|
||||
|
||||
if not os.environ.get('PASTE_TESTING'):
|
||||
output_dir = os.path.join(here, 'appsetup', 'output')
|
||||
if os.path.exists(output_dir):
|
||||
shutil.rmtree(output_dir)
|
||||
|
||||
pkg_resources.require('FakePlugin')
|
||||
|
||||
0
PasteScript-1.7.4.2-py2.6.egg/tests/appsetup/__init__.py
Executable file
0
PasteScript-1.7.4.2-py2.6.egg/tests/appsetup/__init__.py
Executable file
139
PasteScript-1.7.4.2-py2.6.egg/tests/appsetup/test_make_project.py
Executable file
139
PasteScript-1.7.4.2-py2.6.egg/tests/appsetup/test_make_project.py
Executable file
@@ -0,0 +1,139 @@
|
||||
import urllib
|
||||
import os
|
||||
from nose import SkipTest
|
||||
from paste.fixture import *
|
||||
import pkg_resources
|
||||
for spec in ['PasteScript', 'Paste', 'PasteDeploy', 'PasteWebKit',
|
||||
'ZPTKit']:
|
||||
try:
|
||||
pkg_resources.require(spec)
|
||||
except pkg_resources.DistributionNotFound, dnf:
|
||||
raise SkipTest(repr(dnf))
|
||||
|
||||
template_path = os.path.join(
|
||||
os.path.dirname(__file__), 'testfiles')
|
||||
|
||||
test_environ = os.environ.copy()
|
||||
test_environ['PASTE_TESTING'] = 'true'
|
||||
|
||||
testenv = TestFileEnvironment(
|
||||
os.path.join(os.path.dirname(__file__), 'output'),
|
||||
template_path=template_path,
|
||||
environ=test_environ)
|
||||
|
||||
def svn_repos_setup():
|
||||
res = testenv.run('svnadmin', 'create', 'REPOS',
|
||||
printresult=False)
|
||||
testenv.svn_url = 'file://' + testenv.base_path + '/REPOS'
|
||||
assert 'REPOS' in res.files_created
|
||||
testenv.ignore_paths.append('REPOS')
|
||||
|
||||
def paster_create():
|
||||
global projenv
|
||||
res = testenv.run('paster', 'create', '--verbose',
|
||||
'--svn-repository=' + testenv.svn_url,
|
||||
'--template=paste_deploy',
|
||||
'--template=webkit',
|
||||
'--template=zpt',
|
||||
'--no-interactive',
|
||||
'ProjectName',
|
||||
'version=0.1',
|
||||
'author=Test Author',
|
||||
'author_email=test@example.com')
|
||||
expect_fn = ['tests', 'docs', 'projectname', 'docs',
|
||||
'setup.py', 'ProjectName.egg-info',
|
||||
]
|
||||
for fn in expect_fn:
|
||||
fn = os.path.join('ProjectName', fn)
|
||||
assert fn in res.files_created
|
||||
assert fn in res.stdout
|
||||
setup = res.files_created['ProjectName/setup.py']
|
||||
setup.mustcontain('test@example.com')
|
||||
setup.mustcontain('Test Author')
|
||||
setup.mustcontain('0.1')
|
||||
setup.mustcontain('projectname.wsgiapp:make_app')
|
||||
# ZPTKit should add this:
|
||||
setup.mustcontain("include_package_data")
|
||||
assert '0.1' in setup
|
||||
sitepage = res.files_created['ProjectName/projectname/sitepage.py']
|
||||
proj_dir = os.path.join(testenv.cwd, 'ProjectName')
|
||||
testenv.run('svn commit -m "new project"',
|
||||
cwd=proj_dir)
|
||||
testenv.run('python setup.py egg_info',
|
||||
cwd=proj_dir,
|
||||
expect_stderr=True)
|
||||
testenv.run('svn', 'commit', '-m', 'Created project', 'ProjectName')
|
||||
# A new environment with a new
|
||||
projenv = TestFileEnvironment(
|
||||
os.path.join(testenv.base_path, 'ProjectName'),
|
||||
start_clear=False,
|
||||
template_path=template_path,
|
||||
environ=test_environ)
|
||||
projenv.environ['PYTHONPATH'] = (
|
||||
projenv.environ.get('PYTHONPATH', '') + ':'
|
||||
+ projenv.base_path)
|
||||
projenv.proj_dir = proj_dir
|
||||
|
||||
def make_servlet():
|
||||
res = projenv.run(
|
||||
'paster servlet --verbose --simulate test1',
|
||||
cwd=projenv.proj_dir)
|
||||
assert not res.files_created and not res.files_updated
|
||||
res = projenv.run('paster servlet -vvv test1')
|
||||
assert 'projectname/web/test1.py' in res.files_created
|
||||
assert 'projectname/templates/test1.pt' in res.files_created
|
||||
res = projenv.run('paster servlet -vvv ack.test2')
|
||||
assert 'projectname/web/ack/test2.py' in res.files_created
|
||||
assert 'projectname/templates/ack/test2.pt' in res.files_created
|
||||
res = projenv.run('paster servlet --no-servlet -vvv test3')
|
||||
assert 'projectname/web/test3.py' not in res.files_created
|
||||
assert 'projectname/templates/test3.pt' in res.files_created
|
||||
res = projenv.run('svn status')
|
||||
# Make sure all files are added to the repository:
|
||||
assert '?' not in res.stdout
|
||||
|
||||
def do_pytest():
|
||||
res = projenv.run('py.test tests/',
|
||||
cwd=os.path.join(testenv.cwd, 'ProjectName'),
|
||||
expect_stderr=True)
|
||||
assert len(res.stderr.splitlines()) <= 1, (
|
||||
"Too much info on stderr: %s" % res.stderr)
|
||||
|
||||
def config_permissions():
|
||||
projenv.writefile('ProjectName.egg-info/iscape.txt',
|
||||
frompath='iscape.txt')
|
||||
projenv.writefile('projectname/web/admin/index.py',
|
||||
frompath='admin_index.py')
|
||||
projenv.writefile('tests/test_forbidden.py',
|
||||
frompath='test_forbidden.py')
|
||||
res = projenv.run('py.test tests/test_forbidden.py',
|
||||
expect_stderr=True)
|
||||
assert len(res.stderr.splitlines()) <= 1, (
|
||||
"Too much info on stderr: %s" % res.stderr)
|
||||
|
||||
def make_tag():
|
||||
global tagenv
|
||||
res = projenv.run('svn commit -m "updates"')
|
||||
res = projenv.run('python setup.py svntag --version=0.5')
|
||||
assert 'Tagging 0.5 version' in res.stdout
|
||||
assert 'Auto-update of version strings' in res.stdout
|
||||
res = testenv.run('svn co %s/ProjectName/tags/0.5 Proj-05'
|
||||
% testenv.svn_url)
|
||||
setup = res.files_created['Proj-05/setup.py']
|
||||
setup.mustcontain('0.5')
|
||||
assert 'Proj-05/setup.cfg' not in res.files_created
|
||||
tagenv = TestFileEnvironment(
|
||||
os.path.join(testenv.base_path, 'Proj-05'),
|
||||
start_clear=False,
|
||||
template_path=template_path)
|
||||
|
||||
def test_project():
|
||||
global projenv
|
||||
projenv = None
|
||||
yield svn_repos_setup
|
||||
yield paster_create
|
||||
yield make_servlet
|
||||
yield do_pytest
|
||||
yield config_permissions
|
||||
yield make_tag
|
||||
|
||||
25
PasteScript-1.7.4.2-py2.6.egg/tests/test_egg_finder.py
Executable file
25
PasteScript-1.7.4.2-py2.6.egg/tests/test_egg_finder.py
Executable file
@@ -0,0 +1,25 @@
|
||||
import os
|
||||
from paste.script import pluginlib
|
||||
|
||||
def test_egg_info():
|
||||
egg_dir = os.path.join(os.path.dirname(__file__),
|
||||
'fake_packages', 'FakePlugin.egg')
|
||||
found = pluginlib.find_egg_info_dir(os.path.join(egg_dir, 'fakeplugin'))
|
||||
assert found == os.path.join(egg_dir, 'FakePlugin.egg-info')
|
||||
found = pluginlib.find_egg_info_dir(os.path.dirname(__file__))
|
||||
assert found == os.path.join(
|
||||
os.path.dirname(os.path.dirname(__file__)),
|
||||
'PasteScript.egg-info')
|
||||
|
||||
def test_resolve_plugins():
|
||||
plugins = ['FakePlugin']
|
||||
all = pluginlib.resolve_plugins(plugins)
|
||||
assert all
|
||||
assert len(all) == 2
|
||||
|
||||
def test_find_commands():
|
||||
all = pluginlib.resolve_plugins(['PasteScript', 'FakePlugin'])
|
||||
commands = pluginlib.load_commands_from_plugins(all)
|
||||
print commands
|
||||
assert 'testcom' in commands
|
||||
|
||||
232
PasteScript-1.7.4.2-py2.6.egg/tests/test_logging_config.py
Executable file
232
PasteScript-1.7.4.2-py2.6.egg/tests/test_logging_config.py
Executable file
@@ -0,0 +1,232 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. Run all tests.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import os, sys, string
|
||||
import tempfile
|
||||
import logging
|
||||
|
||||
from paste.script.util import logging_config
|
||||
|
||||
def message(s):
|
||||
sys.stdout.write("%s\n" % s)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Test 4
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# config0 is a standard configuration.
|
||||
config0 = """
|
||||
[loggers]
|
||||
keys=root
|
||||
|
||||
[handlers]
|
||||
keys=hand1
|
||||
|
||||
[formatters]
|
||||
keys=form1
|
||||
|
||||
[logger_root]
|
||||
level=NOTSET
|
||||
handlers=hand1
|
||||
|
||||
[handler_hand1]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form1
|
||||
args=(sys.stdout,)
|
||||
|
||||
[formatter_form1]
|
||||
format=%(levelname)s:%(name)s:%(message)s
|
||||
datefmt=
|
||||
"""
|
||||
|
||||
# config1 adds a little to the standard configuration.
|
||||
config1 = """
|
||||
[loggers]
|
||||
keys=root,parser
|
||||
|
||||
[handlers]
|
||||
keys=hand1, hand2
|
||||
|
||||
[formatters]
|
||||
keys=form1, form2
|
||||
|
||||
[logger_root]
|
||||
level=NOTSET
|
||||
handlers=hand1,hand2
|
||||
|
||||
[logger_parser]
|
||||
level=DEBUG
|
||||
handlers=hand1
|
||||
propagate=1
|
||||
qualname=compiler.parser
|
||||
|
||||
[handler_hand1]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form1
|
||||
args=(sys.stdout,)
|
||||
|
||||
[handler_hand2]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form2
|
||||
args=(sys.stderr,)
|
||||
|
||||
[formatter_form1]
|
||||
format=%(levelname)s:%(name)s:%(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form2]
|
||||
format=:%(message)s
|
||||
datefmt=
|
||||
"""
|
||||
|
||||
# config2 has a subtle configuration error that should be reported
|
||||
config2 = string.replace(config1, "sys.stdout", "sys.stbout")
|
||||
|
||||
# config3 has a less subtle configuration error
|
||||
config3 = string.replace(
|
||||
config1, "formatter=form1", "formatter=misspelled_name")
|
||||
|
||||
# config4: support custom Handler classes
|
||||
config4 = string.replace(
|
||||
config1, "class=StreamHandler", "class=logging.StreamHandler")
|
||||
|
||||
def test4():
|
||||
for i in range(5):
|
||||
conf = globals()['config%d' % i]
|
||||
sys.stdout.write('config%d: ' % i)
|
||||
loggerDict = logging.getLogger().manager.loggerDict
|
||||
logging._acquireLock()
|
||||
try:
|
||||
saved_handlers = logging._handlers.copy()
|
||||
if hasattr(logging, '_handlerList'):
|
||||
saved_handler_list = logging._handlerList[:]
|
||||
saved_loggers = loggerDict.copy()
|
||||
finally:
|
||||
logging._releaseLock()
|
||||
try:
|
||||
fn = tempfile.mktemp(".ini")
|
||||
f = open(fn, "w")
|
||||
f.write(conf)
|
||||
f.close()
|
||||
try:
|
||||
logging_config.fileConfig(fn)
|
||||
#call again to make sure cleanup is correct
|
||||
logging_config.fileConfig(fn)
|
||||
except:
|
||||
if i not in (2, 3):
|
||||
raise
|
||||
t = sys.exc_info()[0]
|
||||
message(str(t) + ' (expected)')
|
||||
else:
|
||||
message('ok.')
|
||||
os.remove(fn)
|
||||
finally:
|
||||
logging._acquireLock()
|
||||
try:
|
||||
logging._handlers.clear()
|
||||
logging._handlers.update(saved_handlers)
|
||||
if hasattr(logging, '_handlerList'):
|
||||
logging._handlerList[:] = saved_handler_list
|
||||
loggerDict = logging.getLogger().manager.loggerDict
|
||||
loggerDict.clear()
|
||||
loggerDict.update(saved_loggers)
|
||||
finally:
|
||||
logging._releaseLock()
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Test 5
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
test5_config = """
|
||||
[loggers]
|
||||
keys=root
|
||||
|
||||
[handlers]
|
||||
keys=hand1
|
||||
|
||||
[formatters]
|
||||
keys=form1
|
||||
|
||||
[logger_root]
|
||||
level=NOTSET
|
||||
handlers=hand1
|
||||
|
||||
[handler_hand1]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form1
|
||||
args=(sys.stdout,)
|
||||
|
||||
[formatter_form1]
|
||||
#class=test.test_logging.FriendlyFormatter
|
||||
class=test_logging_config.FriendlyFormatter
|
||||
format=%(levelname)s:%(name)s:%(message)s
|
||||
datefmt=
|
||||
"""
|
||||
|
||||
class FriendlyFormatter (logging.Formatter):
|
||||
def formatException(self, ei):
|
||||
return "%s... Don't panic!" % str(ei[0])
|
||||
|
||||
|
||||
def test5():
|
||||
loggerDict = logging.getLogger().manager.loggerDict
|
||||
logging._acquireLock()
|
||||
try:
|
||||
saved_handlers = logging._handlers.copy()
|
||||
if hasattr(logging, '_handlerList'):
|
||||
saved_handler_list = logging._handlerList[:]
|
||||
saved_loggers = loggerDict.copy()
|
||||
finally:
|
||||
logging._releaseLock()
|
||||
try:
|
||||
fn = tempfile.mktemp(".ini")
|
||||
f = open(fn, "w")
|
||||
f.write(test5_config)
|
||||
f.close()
|
||||
logging_config.fileConfig(fn)
|
||||
try:
|
||||
raise KeyError
|
||||
except KeyError:
|
||||
logging.exception("just testing")
|
||||
os.remove(fn)
|
||||
hdlr = logging.getLogger().handlers[0]
|
||||
logging.getLogger().handlers.remove(hdlr)
|
||||
finally:
|
||||
logging._acquireLock()
|
||||
try:
|
||||
logging._handlers.clear()
|
||||
logging._handlers.update(saved_handlers)
|
||||
if hasattr(logging, '_handlerList'):
|
||||
logging._handlerList[:] = saved_handler_list
|
||||
loggerDict = logging.getLogger().manager.loggerDict
|
||||
loggerDict.clear()
|
||||
loggerDict.update(saved_loggers)
|
||||
finally:
|
||||
logging._releaseLock()
|
||||
25
PasteScript-1.7.4.2-py2.6.egg/tests/test_plugin_adder.py
Executable file
25
PasteScript-1.7.4.2-py2.6.egg/tests/test_plugin_adder.py
Executable file
@@ -0,0 +1,25 @@
|
||||
import os
|
||||
from paste.script import pluginlib
|
||||
|
||||
egg_dir = os.path.join(os.path.dirname(__file__),
|
||||
'fake_packages', 'FakePlugin.egg')
|
||||
|
||||
plugin_file = os.path.join(egg_dir, 'paster_plugins.txt')
|
||||
|
||||
def plugin_lines():
|
||||
if not os.path.exists(plugin_file):
|
||||
return []
|
||||
f = open(plugin_file)
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
return [l.strip() for l in lines if l.strip()]
|
||||
|
||||
def test_add_remove():
|
||||
prev = plugin_lines()
|
||||
pluginlib.add_plugin(egg_dir, 'Test')
|
||||
assert 'Test' in plugin_lines()
|
||||
pluginlib.remove_plugin(egg_dir, 'Test')
|
||||
assert 'Test' not in plugin_lines()
|
||||
assert prev == plugin_lines()
|
||||
if not prev and os.path.exists(plugin_file):
|
||||
os.unlink(plugin_file)
|
||||
13
PasteScript-1.7.4.2-py2.6.egg/tests/test_template_introspect.py
Executable file
13
PasteScript-1.7.4.2-py2.6.egg/tests/test_template_introspect.py
Executable file
@@ -0,0 +1,13 @@
|
||||
import os
|
||||
from paste.script import templates
|
||||
|
||||
tmpl_dir = os.path.join(os.path.dirname(__file__), 'sample_templates')
|
||||
|
||||
def test_find():
|
||||
vars = templates.find_args_in_dir(tmpl_dir, True)
|
||||
assert 'a' in vars
|
||||
assert vars['a'].default is templates.NoDefault
|
||||
assert 'b' in vars
|
||||
assert vars['b'].default == 1
|
||||
assert len(vars) == 2
|
||||
|
||||
Reference in New Issue
Block a user