This is a little Python module that goes and fetches the Numpy examples from the Numpy_Example_List page, parses them, and prints out entries.
Here's an example of use:
In [1]: import numpy In [2]: from NumpyExamples import examples In [3]: examples(numpy.hstack) --- hstack --- >>> from numpy import * >>> a =array([[1],[2]]) # 2x1 array >>> b = array([[3,4],[5,6]]) # 2x2 array >>> hstack((a,b,a)) # only the 2nd dimension of the arrays is allowed to be different array([[1, 3, 4, 1], [2, 5, 6, 2]]) See also: column_stack, concatenate, dstack, vstack, hsplit
NumpyExamples.py
1 """This module retrieves the Numpy examples page from
2
3 http://www.scipy.org/Numpy_Example_List
4
5 parses the data a bit, and provides a simple interface to query for
6 various bits of example info.
7
8 Expected usage is:
9
10 from NumpyExamples import examples
11 examples('fft')
12
13 But it can also be called as a script from the command line:
14
15 python NumpyExamples fft arccos dot
16
17 (The command line usage is not really recommended, though, because it
18 re-downloads the examples page every time you call it. Caching to a
19 local file is not currently supported.)
20
21 You can also create your own instance of the NumpyExamples object if
22 you feel like it
23
24 Author: Bill Baxter
25 Date of creation: March 19 2007
26 version: 0.1
27 License: public domain
28 """
29 import urllib2, re
30
31 #--- MODULE GLOBALS ---
32
33 DEFAULT_URL = 'http://www.scipy.org/Numpy_Example_List?action=raw'
34
35 default_getter = None
36
37 #--- IMPLEMENTATION ---
38
39 class NumpyExamples:
40 '''Object that can download and parse examples from the Numpy examples wiki page.
41 The url used defaults to 'http://www.scipy.org/Numpy_Example_List?action=raw'
42 '''
43 def __init__(self, url=DEFAULT_URL,comments=True, fixcomments=True):
44 # try to read the target HTML document
45 try:
46 # TODO: cache the file on disk somewhere
47 conn = urllib2.urlopen(url)
48 self.fulltext = conn.read()
49 except:
50 raise ValueError('Could not fetch Numpy example list wiki page')
51 # reset our parser and try to parse the newly fetched examples
52 #print self.text
53 self.comments = comments
54 self.fixcomments = fixcomments
55 self.example_dict = self.parse_examples(self.fulltext)
56
57
58 def parse_examples(self, text):
59 """Parse the text of the examples web page into a dict of
60 mapping command names to the example text.
61 """
62 # strip the PRE {{{ type tags from the example code
63 text = re.sub(r'(\{\{\{.*)|\}\}\}', '', text)
64
65 # fix the see also lines
66 #re_seealso = re.compile(r'(See\s+also\s*:.*)$',re.IGNORECASE)
67 re_seealso = re.compile(r'See\s*(also)?\s*(:)?[^[]*\[.*')
68 def seealso_sub(matchobj):
69 ret= munge_see_also(matchobj.group(0))
70 return ret
71 text = re_seealso.sub(seealso_sub, text)
72
73 # Now split the examples based on headers that look like this:
74 # [[Anchor(broadcast)]]
75 # === broadcast() ===
76 # Pick out both flavors of the name to use as keys
77 # (sometimes they're different)
78
79 re_header = re.compile(r'\[\[\s*Anchor\s*\((\w+)\)\s*\]\]\s*'+
80 r'===\s*([^( ]+).*$',re.MULTILINE)
81 all = re_header.split(text)
82
83 alliter = iter(all)
84 alliter.next() # discard first chunk, which is a header
85 ret = dict()
86 re_blanks = re.compile(r'^\s*$',re.MULTILINE)
87 try:
88 while True:
89 k1 = alliter.next()
90 k2 = alliter.next()
91 txt = alliter.next()
92 # replace multiple blank lines with just one
93 txt = re_blanks.sub('', txt)
94 ret[k1] = txt
95 if k1 != k2:
96 ret[k2] = txt
97 except StopIteration:
98 pass
99 return ret
100
101 def get_example(self, name, comments=None, fixcomments=None):
102 """Retrieve the examples for the given Numpy function.
103
104 If comments is True
105 leave comments in the example code
106 elif comments is False
107 then strip comments from the example code
108 else:
109 use default behavior of self.comments (no stripping)
110
111 fixcomments is intended for reflowing comments to a width
112 more appropriate for a tty. Set to True/False to turn it on or off.
113 None gets default behavior.
114 """
115 # Try to convert a non str argument to something useful
116 if type(name) is not type(str):
117 if hasattr(name,'__name__'):
118 name = name.__name__
119 else:
120 name = str(name)
121 if name.startswith('numpy.'):
122 ## Maybe this isn't needed, but fft for instance
123 ## is a module name, so it's likely that get_example(fft)
124 ## look for 'numpy.fft' instead of 'fft'
125 name = name.replace('numpy.','')
126
127 text = self.example_dict.get(name)
128 if text is None:
129 return "<No example available>"
130
131 # strip comments conditionally
132 comments_off = (comments is False) or (comments is None and self.comments is False)
133 fix_on = not comments_off and (fixcomments or self.fixcomments)
134 if comments_off:
135 text = re.sub(r'#.*', '', text)
136
137 def comment_fixer(mobj):
138 return "\n "+mobj.group(1)
139 if fix_on:
140 # TODO: the idea here is to reflow comments to a more sane
141 # width for a tty somehow
142 text = re.sub(r'\s*(#.*)', comment_fixer, text)
143
144 # strip all trailing whitespace
145 text = re.sub(r'\s*$', '', text)
146
147 return text
148
149
150 def munge_see_also(line):
151 """This parses and re-formats a 'see also' information line from the
152 Numpy examples page. These lines take the form:
153
154 See also: [#bbracket []] [#dots ...], [#newaxis newaxis], [#ix_ ix_]'
155
156 And the generated output from that looks like:
157
158 See also: bbracket ([]), dots (...), newaxis, ix_
159 """
160
161 # A simple regexp won't work here, mainly because of the nested []
162 # used inside the bbracket see also.
163 # It's also nice to be able to remove duplicates.
164
165 import shlex;
166
167 parser = shlex.shlex(line)
168 parser.commenters = []
169 out = 'See also: '
170 in_alt = False
171 def add_char(txt,c,_in_alt):
172 if not _in_alt:
173 return (txt+' ('+c,True)
174 return (txt+c,_in_alt)
175
176 def parse_one(p):
177 in_alt = False
178 txt = ""
179 blevel = 1
180 after_pound = 'notyet'
181 while True:
182 t = p.get_token()
183 if t==p.eof:
184 break
185 if after_pound=='notyet' and t=='#':
186 after_pound = 'justgot'
187 continue
188
189 if after_pound=='justgot':
190 txt = t
191 after_pound='pastanchor'
192 continue
193
194 if after_pound=='pastanchor':
195 if t==']':
196 blevel -= 1
197 if blevel==0:
198 break
199 else:
200 txt,in_alt = add_char(txt,t,in_alt)
201 elif t=='[':
202 blevel += 1
203 txt,in_alt = add_char(txt,t,in_alt)
204 elif t != txt:
205 txt,in_alt = add_char(txt,t,in_alt)
206 elif t==p.eof:
207 break
208
209 if in_alt: txt+=")"
210 return txt
211
212 toks = []
213 while True:
214 t = parser.get_token()
215 if t=='[':
216 toks.append(parse_one(parser))
217 elif t==parser.eof:
218 break
219 out += ", ".join(toks)
220 return out
221
222
223
224 #--- CONVENIENCE FUNCTION ---
225 def examples(name=None,comments=None,fixcomments=None):
226 """Retrieve the examples for the given Numpy function.
227
228 If comments is True
229 leave comments in the example code
230 elif comments is False
231 then strip comments from the example code
232 else:
233 use default behavior (no stripping)
234
235 fixcomments is intended for reflowing comments to a width
236 more appropriate for a tty. Set to True/False to turn it on or off.
237 None gets default behavior.
238
239 If name is None then it will print out a list of all known commands.
240 """
241 global default_getter
242 if default_getter is None:
243 default_getter = NumpyExamples()
244
245 if name is None:
246 print "--- Known commands ---"
247 k = default_getter.example_dict.keys()
248 k.sort()
249 print ", ".join(k)
250 return
251
252 if type(name) is not type(str):
253 if hasattr(name,'__name__'):
254 name = name.__name__
255 else:
256 name = str(name)
257
258 print "---", name, "---"
259 print default_getter.get_example(name,comments,fixcomments)
260
261
262 #--- SCRIPT CALL INTERFACE ---
263 if __name__ == '__main__':
264 import sys,os
265 if len(sys.argv)==1:
266 print "Looks up usage examples for Numpy functions from the Numpy examples page at"
267 print " ", DEFAULT_URL.split('?')[0]
268 print "Usage: python", sys.argv[0].split(os.sep)[-1], "<commands>"
269 else:
270 for a in sys.argv[1:]:
271 examples(a)