This is an archival dump of old wiki content --- see scipy.org for current material

If you want to update the Numpy Example List With Doc page just follow these instructions:

  1. Go to the Numpy Example List and make necessary changes to the examples.

  2. Make sure you have the latest version of Numpy installed.

  3. Get the below script and run it. It will fetch the raw Numpy Example List wiki page, add documentation and save the output to specified file (default is Numpy_Example_List_With_Doc.txt).
  4. Log in to the Scipy Wiki and update the Numpy Example List With Doc page with newly generated content.


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Filip Wasilewski <filip.wasilewski@gmail.com>
# Licence: public domain

"""
A tool to process wiki list of NumPy Examples (http://www.scipy.org/Numpy_Example_List)
and supplement it with documentation generated from doc strings and function
argument specification of corresponding functions and methods.

The input file consists of sections beginning with optional Anchor
([[Anchor(name)]]) and mandatory Title 3 heading (=== title ===).
Everything (except of the footer) that follows the Title is being treated
as Example content and is copied to the output file unchanged.

    [[Anchor(array)]]
    === array ===
    ...
    
    === array2string ===
    ...

The title is being used to lookup and extract corresponding documentation
from specified namespaces.
"""

import re
import sys
import types
import urllib
import inspect
import logging

import numpy

INPUT_PAGE_URL = "http://www.scipy.org/Numpy_Example_List?action=raw"

OUTPUT_FILE = "Numpy_Example_List_With_Doc.txt"

NUMPY_VERSION = numpy.__version__

WIKI_PAGE_HEADER = \
"""#format wiki
#language en
~-This is an [wiki:/script auto-generated] version of [wiki:Numpy_Example_List Numpy Example List]
with added documentation from doc strings and arguments specification for methods and functions
of Numpy %(numpy_version)s.

Please do not edit this page directly. To update this page just follow the [wiki:/script instructions].
-~

----
 . [[TableOfContents]]

""" % {"numpy_version" : NUMPY_VERSION}

WIKI_PAGE_FOOTER = """----\n . CategoryCategory"""

re_title = re.compile('=== ([\w\.]+)[()\[\]]{0,2} ===')
re_anchor = re.compile('\[\[Anchor\(([\w.\[\]]+)\)\]\]')

logging.basicConfig(level=logging.DEBUG, format='%(levelname)-8s %(message)s')
logger = logging.getLogger()

class Scope(object):
    def __init__(self, obj):
        self.obj = obj

    def get_attr(self, name):
        try:
            attr = getattr(self.obj, name)
        except AttributeError, e:
            raise AttributeError("Name '%s' not found in '%s' namespace." % (name, self.obj.__name__))
        return attr

    def get_argspec(self, name):
        attr = self.get_attr(name)
        try:
            argspec = inspect.getargspec(attr)
            args = inspect.formatargspec(*argspec)
        except TypeError, e:
            logger.info("No argspec for '%s.%s', (OK, just not a plain Python function)." % (self.obj.__name__, name))
            if callable(attr):
                args = '(...)'
            else:
                args = ''
        return args

    def get_doc(self, name):
        attr = self.get_attr(name)
        doc = inspect.getdoc(attr)
        if isinstance(doc, str):
            return doc.strip()
        return ''

    def get_scope_name(self):
        return self.obj.__name__

    def get_names(self):
        return [name for name in dir(self.obj) if not name.startswith('__')]

    def is_functionlike(self, name):
        attr = self.get_attr(name)
        return inspect.isfunction(attr) or inspect.isbuiltin(attr) or inspect.ismethod(attr) \
               or inspect.ismethoddescriptor(attr) or type(attr) is numpy.ufunc

class WikiFormatter(object):
    def format_doc(self, doc):
        if doc:
            doc = ["\n\n{{{\n", doc, "\n}", "}}\n\n"]
            return ''.join(doc)
        else:
            return ''

    def format_title(self, title):
        return '=== %s ===\n' % title

    def format_anchor(self, anchor):
        return '[[Anchor(%s)]]\n' % anchor

    def format_attr_content(self, scope, name, add_doc=True):
        fragment = []
        try:
            argspec = scope.get_argspec(name)
            doc = scope.get_doc(name)
        except AttributeError, e:
            return ''

        attr_str = "`%s`.%s%s\n\n" % (scope.get_scope_name() , name, argspec.replace("''", '""'))

        fragment.append(attr_str)

        if add_doc:
            doc = self.format_doc(scope.get_doc(name))
            fragment.append(doc)

        return ''.join(fragment)


if __name__ == '__main__':

    import numpy

    examples_only = False # True - output only functions from the input wiki page
                          # False - include doc for functions from additional_doc_scopes

    # Look for doc strings in these namespaces
    example_scopes = map(Scope, [
            numpy,
            numpy.ndarray,
            numpy.random,
            numpy.linalg,
            numpy.core.records
        ])

    # If examples_only is Fales, doc strings from these scopes will be added
    # even if corresponding identifiers are not found in the Example List.
    additional_doc_scopes = map(Scope, [numpy, numpy.ndarray])

    # ignore these functions
    ignored_names = set(['add_docstring', 'add_newdoc', 'rand', 'randn'])

    ## process input file
    anchor_name = ''
    anchor_line = 0
    anchor_names = {}
    content = {}
    fragment = head = []
    footer = []
    formatter = WikiFormatter()

    logger.info("Fetching original Numpy Example List wiki page content.")
    request = urllib.urlopen(INPUT_PAGE_URL)

    logger.info("Processing data.")
    for i, line in enumerate(request):
        # look for optional anchor name
        line = line.strip()
        match = re_anchor.match(line)
        if match:
            anchor_name = match.group(1)
            anchor_line = i
            continue

        # look for heading title
        match = re_title.match(line)
        if match:
            name = match.group(1)
            fragment = content.setdefault(name, [])

            if i == anchor_line+1:
                anchor_names[name] = anchor_name
            else:
                logger.warning("No anchor defined for '%s'. Using default value." % name)
                anchor_names[name] = name

            for scope in example_scopes:
                attr_doc = formatter.format_attr_content(scope, name)
                fragment.append(attr_doc)
            continue

        if line.strip() == '----':
            fragment = footer

        # process content
        if line.lstrip().startswith("{{{#"):
            fragment.append("''' Example: '''")
            line = line.replace("{{{#", "{{{\n#", 1)
        fragment.append(line)

    with_examples = set(content)
    if examples_only:
        names = with_examples
    else:
        doc_names = set()
        for scope in additional_doc_scopes:
            scope_content_names = set([name for name in scope.get_names() if scope.is_functionlike(name)])
            doc_names |= scope_content_names
        names = with_examples | doc_names

    names -= ignored_names

    output_file = open(OUTPUT_FILE, 'w')
    output_file.write(WIKI_PAGE_HEADER)

    for name in sorted(names):
        # anchor
        anchor = formatter.format_anchor(anchor_names.get(name, name))
        output_file.write(anchor)

        # heading
        functionlike = False
        notfunctionlike = False
        for scope in example_scopes:
            try:
                if callable(scope.get_attr(name)):
                    functionlike = True
                else:
                    notfunctionlike = True
            except AttributeError:
                pass
        if functionlike:
            if notfunctionlike:
                title = name + '() or .' + name
            else:
                title = name + '()'
        else:
            title = name
        title = formatter.format_title(title)
        output_file.write(title)

        # body
        if name in content:
            fragment = content[name]
        else:
            fragment = [formatter.format_attr_content(scope, name) for scope in additional_doc_scopes]
        output_file.writelines([line + "\n" for line in fragment])

    output_file.writelines(WIKI_PAGE_FOOTER)
    output_file.close()

    logger.info("The output was written to '%s' file." % OUTPUT_FILE)

SciPy: Numpy_Example_List_With_Doc/script (last edited 2015-10-24 17:48:25 by anonymous)