Imported from SVN by Bitbucket
This commit is contained in:
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
|
||||
|
||||
Reference in New Issue
Block a user