If you want to update the Numpy Example List With Doc page just follow these instructions:
Go to the Numpy Example List and make necessary changes to the examples.
Make sure you have the latest version of Numpy installed.
- 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).
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)