diff options
Diffstat (limited to 'paste')
-rw-r--r-- | paste/docsupport/__init__.py | 1 | ||||
-rw-r--r-- | paste/docsupport/extract.py | 355 | ||||
-rw-r--r-- | paste/docsupport/findmodules.py | 33 | ||||
-rwxr-xr-x | paste/docsupport/gensite.py | 146 | ||||
-rw-r--r-- | paste/docsupport/metadata.py | 19 | ||||
-rw-r--r-- | paste/docsupport/metadata_real.py | 118 |
6 files changed, 0 insertions, 672 deletions
diff --git a/paste/docsupport/__init__.py b/paste/docsupport/__init__.py deleted file mode 100644 index 792d600..0000000 --- a/paste/docsupport/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/paste/docsupport/extract.py b/paste/docsupport/extract.py deleted file mode 100644 index 3837863..0000000 --- a/paste/docsupport/extract.py +++ /dev/null @@ -1,355 +0,0 @@ -# (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 - -if __name__ == '__main__': - # This has to be done very early on, to make the real module - # replace the stubby version - from paste.docsupport import metadata_real - metadata_real.install() - -import types -import inspect -from cStringIO import StringIO -import textwrap -import re -import findmodules - -from paste.docsupport import metadata -from paste.util.classinit import ClassInitMeta -from paste.httpexceptions import HTTPException - -extractors = [] - -class Extractor(object): - - __metaclass__ = ClassInitMeta - match_type = None - match_level = None - - def __classinit__(cls, new_attrs): - if cls.__bases__ != (object,): - if cls.match_level is None: - extractors.append(cls) - else: - extractors.insert(cls.match_level, cls) - - def __init__(self, obj, context): - self.obj = obj - self.context = context - - def extract(self): - raise NotImplementedError - - def applies(cls, obj, context): - return isinstance(obj, cls.match_type) - applies = classmethod(applies) - -class ModuleExtractor(Extractor): - - match_type = types.ModuleType - - def extract(self): - objs = getattr(self.obj, '__all__', []) - if not objs: - return - self.context.writeheader(self.obj.__name__, type='Module') - self.context.writedoc(self.obj.__doc__) - for name in objs: - self.context.push_name(name) - self.context.extract(getattr(self.obj, name)) - self.context.pop_name(name) - self.context.endheader() - -class ClassExtractor(Extractor): - - match_type = (type, types.ClassType) - - def extract(self): - self.context.writeheader(self.context.last_name, type='Class') - self.context.writedoc(self.obj.__doc__) - attrs = self.getattrs(self.obj) - for name, value in attrs: - self.context.push_name(name) - self.context.extract(value) - self.context.pop_name(name) - methods = self.getmethods(self.obj) - for name, value in methods: - self.context.push_name(name) - self.context.extract(value) - self.context.pop_name(name) - self.context.endheader() - - def getattrs(self, cls): - bases = inspect.getmro(cls) - attrs = {} - for i, base in enumerate(bases): - for name, value in base.__dict__.items(): - if not isinstance(value, metadata.DocItem): - continue - if name in attrs: - continue - attrs[name] = (i, value.__creationorder__, value) - attrs = attrs.items() - attrs.sort(lambda a, b: cmp(a[1], b[1])) - return [ - (m[0], m[1][2]) for m in attrs] - - def getmethods(self, cls): - bases = inspect.getmro(cls) - methods = {} - for i, base in enumerate(bases): - if base.__dict__.has_key('__all__'): - all = base.__all__ or [] - else: - all = None - for name, value in base.__dict__.items(): - if all is not None and name not in all: - continue - if not isinstance(value, types.FunctionType): - continue - if name in methods: - continue - methods[name] = (i, value.func_code.co_firstlineno, value) - methods = methods.items() - methods.sort(lambda a, b: cmp(a[1], b[1])) - return [ - (m[0], m[1][2]) for m in methods] - -class DetectedExtractor(Extractor): - - def applies(cls, obj, context): - return isinstance(obj, metadata.DocItem) - applies = classmethod(applies) - - def extract(self): - self.obj.writeto(self.context) - -class MethodExtractor(Extractor): - - match_type = types.FunctionType - - def extract(self): - if not self.obj.__doc__: - return - sig = self.make_sig() - self.context.writekey('def %s(%s)' % (self.obj.func_name, sig), - monospace=True) - self.context.writedoc(self.obj.__doc__) - if self.get_attr('proxy'): - self.context.writedoc(self.get_attr('proxy').__doc__) - if getattr(self.obj, 'returns', None): - returns = self.obj.returns - if isinstance(returns, str): - returns = self.obj.func_globals[returns] - self.context.extract(self.obj.returns) - self.context.endkey() - - def make_sig(self): - proxy = self.get_attr('proxy') - args, varargs, varkw, defaults = inspect.getargspec( - proxy or self.obj) - sig = [] - args.reverse() - for arg in args: - if defaults: - sig.append('%s=%r' % (arg, defaults[-1])) - defaults = defaults[:-1] - else: - sig.append(arg) - sig.reverse() - if varargs: - sig.append('*%s' % varargs) - if varkw: - sig.append('**%s' % varkw) - return ', '.join(sig) - - def get_attr(self, attr): - if not getattr(self.obj, attr, None): - return None - value = getattr(self.obj, attr) - if isinstance(value, str): - value = self.obj.func_globals[value] - return value - -class HTTPExtractor(Extractor): - - match_level = 0 - - def extract(self): - self.context.writekey(self.obj.__name__) - self.context.write('%s %s\n' % (self.obj.code, self.obj.title)) - self.context.endkey() - - def applies(cls, obj, context): - return (isinstance(obj, types.ClassType) - and issubclass(obj, HTTPException)) - applies = classmethod(applies) - -############################################################ -## Context -############################################################ - -class DocContext(object): - - headerchars = '+=-~.\'_`' - - def __init__(self): - self.out = StringIO() - self.header_level = 0 - self.indent_level = 0 - self.names = [] - self.need_break = False - self.indexes = {} - - def push_name(self, name): - self.names.append(name) - - def pop_name(self, name=None): - if name is not None: - assert self.names[-1] == name, ( - "Out of order pop (popping %r; expected %r)" - % (self.names[-1], name)) - self.names.pop() - - def last_name__get(self): - return self.names[-1] - last_name = property(last_name__get) - - def writeheader(self, name, type=None): - self.need_break = False - if self.indent_level: - self.writekey(name, type=type, monospace=False) - return - if type: - name = '%s: %s' % (type, name) - self.write(name + '\n') - self.write(self.headerchars[self.header_level] - * len(name)) - self.write('\n\n') - self.header_level += 1 - - def endheader(self): - if self.indent_level: - self.endkey() - return - self.header_level -= 1 - assert self.header_level >= 0, ( - "Too many endheader() calls.") - self.need_break = True - - def writedoc(self, doc): - if doc is None: - return - doc = self.clean(doc) - if not doc: - return - self.write(doc) - self.write('\n\n') - - def writelist(self, seq, header=None, with_titles=False): - seq = list(seq) - if not seq: - return - if header: - self.writeheader(header) - for name, value in seq: - if with_titles: - self.writeheader(name) - value.write(self) - if with_titles: - self.endheader() - if header: - self.endheader() - - def writekey(self, key, type=None, monospace=True): - if monospace: - key = '``%s``' % key - if type: - key = '%s: %s' % (type, key) - self.write('%s:\n' % key) - self.indent_level += 2 - - def endkey(self): - self.indent_level -= 2 - assert self.indent_level >= 0, ( - "Too many endkeys or dedents (indent %s)" % self.indent_level) - - def addindex(self, index_type, name, description=None): - full_name = '%s.%s' % (index_type, name) - self.write('.. _%s:\n\n' % full_name) - self.indexes.setdefault(index_type, []).append( - (name, description)) - - def write(self, s): - if self.need_break: - self.out.write('\n\n%s\n\n' % ('-'*40)) - self.need_break = False - if self.indent_level: - self.out.write(self.indent(s, self.indent_level)) - else: - self.out.write(s) - - def clean(self, s): - return textwrap.dedent(s).rstrip().lstrip('\n') - - def indent(self, s, indent=2): - new = '\n'.join([' '*indent + l for l in s.splitlines()]) - if s.endswith('\n'): - new += '\n' - return new - - def capture(self, obj): - old_out = self.out - self.out = StringIO() - obj.write(self) - result = self.out.getvalue() - self.out = old_out - return result - - def extract(self, obj): - for extractor in extractors: - if extractor.applies(obj, self): - ext = extractor(obj, self) - ext.extract() - break - else: - print >> sys.stderr, 'No extractor applies to %r\n' % obj - - def close(self): - self.writeindexes() - - def writeindexes(self): - index_types = self.indexes.keys() - index_types.sort() - for index_type in index_types: - self.writeindex(index_type, self.indexes[index_type]) - - def writeindex(self, index_type, indexes): - indexes.sort() - self.writeheader('Index: %s' % index_type) - for n, (name, description) in enumerate(indexes): - self.write('* `%s <#%s>`_\n' - % (description or name, - self.munge_link(index_type + '.' + name))) - self.write('\n') - self.endheader() - - def munge_link(self, link): - link = link.lower() - link = re.sub(r'[ ._-]+', '-', link) - link = re.sub(r'[^a-z0-9-]', '', link) - return link - -def build_doc(package): - context = DocContext() - for module in findmodules.find_modules(package): - context.extract(module) - context.close() - return context.out.getvalue() - -if __name__ == '__main__': - import sys - from paste.util.import_string import import_module - base = import_module(sys.argv[1]) - print build_doc(base) - diff --git a/paste/docsupport/findmodules.py b/paste/docsupport/findmodules.py deleted file mode 100644 index d917291..0000000 --- a/paste/docsupport/findmodules.py +++ /dev/null @@ -1,33 +0,0 @@ -# (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 - -""" -Finds all modules in a packages, loads them, and returns them. -""" - -import os -import re -from paste.util.import_string import import_module - -module_name = re.compile(r'^[a-zA-Z][a-zA-Z0-9_]*$') - -def find_modules(package): - pkg_name = package.__name__ - modules = [] - base = os.path.abspath(package.__file__) - if os.path.basename(os.path.splitext(base)[0]) == '__init__': - base = os.path.dirname(base) - if os.path.isdir(base): - for module_fn in os.listdir(base): - base, ext = os.path.splitext(module_fn) - full = os.path.join(base, module_fn) - if not module_name.search(base): - continue - if (os.path.isdir(full) - and os.path.exists(os.path.join(full, '__ini__.py'))): - modules.extend(import_module(pkg_name + '.' + base)) - elif ext == '.py': - modules.append(import_module(pkg_name + '.' + base)) - else: - modules.append(package) - return modules diff --git a/paste/docsupport/gensite.py b/paste/docsupport/gensite.py deleted file mode 100755 index a5f4459..0000000 --- a/paste/docsupport/gensite.py +++ /dev/null @@ -1,146 +0,0 @@ -# (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 - -#!/usr/bin/env python -""" -This is a very basic script to generate a site from a set of ReST -documents. -""" - -import os -import re -import shutil -import optparse -from Cheetah.Template import Template -from paste import pyconfig - -__version__ = '0.1' - -parser = optparse.OptionParser( - version=__version__, - usage="%prog [OPTIONS]") - -parser.add_option( - '-f', '--config-file', - dest='config_file', - metavar='FILENAME', - default='doc.conf', - help="The configuration file to load (default doc.conf)") - -def main(): - options, args = parser.parse_args() - assert not args, ( - "No arguments are allowed") - conf = pyconfig.Config(with_default=True) - conf.load_dict({'dirs': {}, - 'dest_base': os.getcwd()}) - conf.load(options.config_file) - dirs = conf['dirs'] - base = conf['dest_base'] - for source, dest in dirs.items(): - dirs[source] = os.path.join(base, dest) - gen_site(conf) - -def gen_site(conf): - template = make_template(conf) - files = find_files(conf) - for source, dest in files.items(): - if not source.endswith('.html'): - shutil.copyfile(source, dest) - continue - f = RestFile(source) - template.ns.clear() - f.update_ns(template.ns) - content = str(template) - print 'Writing %s (%i bytes)' % (os.path.basename(source), len(content)) - dest_dir = os.path.dirname(dest) - if not os.path.exists(dest_dir): - print 'Creating %s' % dest_dir - os.makedirs(dest_dir) - f = open(dest, 'w') - f.write(content) - f.close() - -def find_files(conf): - files = {} - for source, dest in conf['dirs'].items(): - find_files_dir(source, dest, conf, files) - return files - -def find_files_dir(source, dest, conf, files): - for name in os.listdir(source): - source_fn = os.path.join(source, name) - if os.path.isdir(source_fn): - continue - files[source_fn] = os.path.join(os.path.join(dest, name)) - -def make_template(conf): - template_fn = os.path.join(os.getcwd(), conf['template']) - ns = {} - template = Template( - file=template_fn, searchList=[ns]) - template.ns = ns - return template - -class RestFile(object): - - def __init__(self, fn): - self.filename = fn - f = open(fn) - self.html = f.read() - f.close() - self.read_properties() - self.read_content() - - def update_ns(self, ns): - ns['file'] = self - ns['content'] = self.content - ns.update(self.properties) - - _title_re = re.compile(r'<title>(.*?)</title>') - def read_properties(self): - props = self.properties = {} - m = self._title_re.search(self.html) - if m: - props['title'] = m.group(1) - else: - print 'No title in %s' % self.filename - props['title'] = '' - - #_start_re = re.compile(r'<div class=".*?" id="contents">') - _start_re = re.compile(r'<body>[ \n]*(?:<div.*?>[ \n]*)?<h1.*?>.*?</h1>') - _end_re = re.compile(r'(?:</div>[ \n]*)?</div>[ \n]*</body>[\n\r ]*</html>[\n\r ]*$') - _bad_res = [ - (re.compile(r'<link rel="stylesheet".*?>'), ''), - (re.compile(r'<h1 class="title">.*?</h1>'), ''), - (re.compile(r'(<p class=".*?"><a name="contents">.*?</p>)[ \n]*' - r'(<ul class="simple">)'), - '<div><ul class="simple contents">\n' - '<li class="header">Contents</li>\n'), - (re.compile(r'(<th class="docinfo-name">Date:</th>[ \n]*)' - r'(<td>).*?\((.*?)\)'), - r'\1\2\3'), - ] - - def read_content(self): - c = self.html - m = self._start_re.search(c) - if m: - c = c[m.end():] - else: - print 'Bad beginning in %s' % self.filename - m = self._end_re.search(c) - if m: - c = c[:m.start()] - else: - print 'Bad ending in %s' % self.filename - for regex, sub in self._bad_res: - c = regex.sub(sub, c) - self.content = c - - def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, self.filename) - -if __name__ == '__main__': - main() - diff --git a/paste/docsupport/metadata.py b/paste/docsupport/metadata.py deleted file mode 100644 index a0e71c4..0000000 --- a/paste/docsupport/metadata.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -This module provides the basic metadata_real classes, but without any -functionality. This way the import is fast and low-overhead. But -when running docsupport.extract it will replace this module with the -real (more functional) thing. - -Everything here is stubs. -""" - -class DocItem(object): - - def __init__(self, *args, **kw): - pass - -WSGIKey = DocItem -Config = DocItem -Attribute = DocItem - - diff --git a/paste/docsupport/metadata_real.py b/paste/docsupport/metadata_real.py deleted file mode 100644 index bea51f9..0000000 --- a/paste/docsupport/metadata_real.py +++ /dev/null @@ -1,118 +0,0 @@ -# (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 inspect -from itertools import count -from paste.util import import_string -from paste.util.classinit import ClassInitMeta - -doc_count = count() - -class DocItem(object): - - __metaclass__ = ClassInitMeta - - def __classinit__(cls, new_attrs): - cls.__creationorder__ = doc_count.next() - - def __init__(self): - self.__creationorder__ = doc_count.next() - stack = inspect.stack() - try: - while 1: - name = stack[0][0].f_globals['__name__'] - if name != __name__: - break - stack.pop(0) - self.call_module_name = name - finally: - # Break reference to frames - stack = None - - def get_object(self, name): - if '.' in name: - return import_string.eval_import(name) - else: - return getattr(sys.modules[self.call_module_name], name) - - def writeto(self, context): - raise NotImplementedError - - def writeobj(self, name, context): - """ - Write the named object to the context - """ - if name is None: - return - obj = self.get_object(name) - context.push_name(name) - context.extract(obj) - context.pop_name(name) - - -class WSGIKey(DocItem): - - def __init__(self, name, doc=None, interface=None): - self.name = name - self.doc = doc - self.interface = interface - super(WSGIKey, self).__init__() - - def writeto(self, context): - context.addindex('wsgikey', self.name) - context.writekey(self.name, type='WSGI Environment Key') - context.writedoc(self.doc) - self.writeobj(self.interface, context) - context.endkey() - -class NoDefault: pass - -class Config(DocItem): - - def __init__(self, doc, name=None, default=NoDefault): - self.doc = doc - self.name = name - self.default = default - - def writeto(self, context): - name = self.name - if not self.name: - name = context.last_name - if name.startswith('_config_'): - name = name[len('_config_'):] - context.addindex('config', name) - name = "``%s``" % name - if self.default is not NoDefault: - name += ' (default: ``%r``)' % self.default - context.writekey(name, type='Paste Configuration', - monospace=False) - context.writedoc(self.doc) - context.endkey() - -class Attribute(DocItem): - - def __init__(self, doc, name=None, interface=None): - self.doc = doc - self.name = name - self.interface = interface - super(Attribute, self).__init__() - - def writeto(self, context): - name = self.name or context.last_name - context.writekey(self.name, type='Attribute') - context.writedoc(self.doc) - if self.interface: - context.write(self.interface) - context.endkey() - -def install(): - """ - Puts this module in place of the normal paste.docsupport.metadata - module, which is all stubby because this functional module takes - longer to import. - """ - from paste.docsupport import metadata - for name, value in globals().items(): - setattr(metadata, name, value) - |