Files
caotek_zidol_theme/PasteScript-1.7.4.2-py2.6.egg/paste/script/create_distro.py

418 lines
17 KiB
Python
Executable File

# (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)