##// END OF EJS Templates
Merge with upstream.
gvaroquaux -
r1530:e49ab843 merge
parent child Browse files
Show More
@@ -0,0 +1,33 b''
1 """Simple example using doctests.
2
3 This file just contains doctests both using plain python and IPython prompts.
4 All tests should be loaded by nose.
5 """
6
7 def pyfunc():
8 """Some pure python tests...
9
10 >>> pyfunc()
11 'pyfunc'
12
13 >>> import os
14
15 >>> 2+3
16 5
17
18 >>> for i in range(3):
19 ... print i,
20 ... print i+1,
21 ...
22 0 1 1 2 2 3
23 """
24 return 'pyfunc'
25
26
27 def ipyfunc2():
28 """Some pure python tests...
29
30 >>> 1+1
31 2
32 """
33 return 'pyfunc2'
@@ -318,6 +318,9 b' def cd_completer(self, event):'
318 return ents
318 return ents
319 return []
319 return []
320
320
321 if event.symbol.startswith('--'):
322 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
323
321 if relpath.startswith('~'):
324 if relpath.startswith('~'):
322 relpath = os.path.expanduser(relpath).replace('\\','/')
325 relpath = os.path.expanduser(relpath).replace('\\','/')
323 found = []
326 found = []
@@ -12,6 +12,8 b' from IPython.ipapi import TryNext'
12 import IPython.macro
12 import IPython.macro
13 import IPython.Shell
13 import IPython.Shell
14
14
15 _leo_push_history = set()
16
15 def init_ipython(ipy):
17 def init_ipython(ipy):
16 """ This will be run by _ip.load('ipy_leo')
18 """ This will be run by _ip.load('ipy_leo')
17
19
@@ -25,17 +27,21 b' def init_ipython(ipy):'
25 ip.expose_magic('mb',mb_f)
27 ip.expose_magic('mb',mb_f)
26 ip.expose_magic('lee',lee_f)
28 ip.expose_magic('lee',lee_f)
27 ip.expose_magic('leoref',leoref_f)
29 ip.expose_magic('leoref',leoref_f)
30 ip.expose_magic('lleo',lleo_f)
31 # Note that no other push command should EVER have lower than 0
32 expose_ileo_push(push_mark_req, -1)
28 expose_ileo_push(push_cl_node,100)
33 expose_ileo_push(push_cl_node,100)
29 # this should be the LAST one that will be executed, and it will never raise TryNext
34 # this should be the LAST one that will be executed, and it will never raise TryNext
30 expose_ileo_push(push_ipython_script, 1000)
35 expose_ileo_push(push_ipython_script, 1000)
31 expose_ileo_push(push_plain_python, 100)
36 expose_ileo_push(push_plain_python, 100)
32 expose_ileo_push(push_ev_node, 100)
37 expose_ileo_push(push_ev_node, 100)
38 ip.set_hook('pre_prompt_hook', ileo_pre_prompt_hook)
33 global wb
39 global wb
34 wb = LeoWorkbook()
40 wb = LeoWorkbook()
35 ip.user_ns['wb'] = wb
41 ip.user_ns['wb'] = wb
36
42
37 show_welcome()
38
43
44 first_launch = True
39
45
40 def update_commander(new_leox):
46 def update_commander(new_leox):
41 """ Set the Leo commander to use
47 """ Set the Leo commander to use
@@ -45,7 +51,12 b' def update_commander(new_leox):'
45 ipython-launch to tell ILeo what document the commands apply to.
51 ipython-launch to tell ILeo what document the commands apply to.
46
52
47 """
53 """
48
54
55 global first_launch
56 if first_launch:
57 show_welcome()
58 first_launch = False
59
49 global c,g
60 global c,g
50 c,g = new_leox.c, new_leox.g
61 c,g = new_leox.c, new_leox.g
51 print "Set Leo Commander:",c.frame.getTitle()
62 print "Set Leo Commander:",c.frame.getTitle()
@@ -70,9 +81,10 b' def format_for_leo(obj):'
70 """ Convert obj to string representiation (for editing in Leo)"""
81 """ Convert obj to string representiation (for editing in Leo)"""
71 return pprint.pformat(obj)
82 return pprint.pformat(obj)
72
83
73 @format_for_leo.when_type(list)
84 # Just an example - note that this is a bad to actually do!
74 def format_list(obj):
85 #@format_for_leo.when_type(list)
75 return "\n".join(str(s) for s in obj)
86 #def format_list(obj):
87 # return "\n".join(str(s) for s in obj)
76
88
77
89
78 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
90 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
@@ -175,6 +187,7 b' class LeoNode(object, UserDict.DictMixin):'
175 def __get_h(self): return self.p.headString()
187 def __get_h(self): return self.p.headString()
176 def __set_h(self,val):
188 def __set_h(self,val):
177 c.setHeadString(self.p,val)
189 c.setHeadString(self.p,val)
190 LeoNode.last_edited = self
178 c.redraw()
191 c.redraw()
179
192
180 h = property( __get_h, __set_h, doc = "Node headline string")
193 h = property( __get_h, __set_h, doc = "Node headline string")
@@ -182,6 +195,7 b' class LeoNode(object, UserDict.DictMixin):'
182 def __get_b(self): return self.p.bodyString()
195 def __get_b(self): return self.p.bodyString()
183 def __set_b(self,val):
196 def __set_b(self,val):
184 c.setBodyString(self.p, val)
197 c.setBodyString(self.p, val)
198 LeoNode.last_edited = self
185 c.redraw()
199 c.redraw()
186
200
187 b = property(__get_b, __set_b, doc = "Nody body string")
201 b = property(__get_b, __set_b, doc = "Nody body string")
@@ -251,6 +265,14 b' class LeoNode(object, UserDict.DictMixin):'
251 p = c.createLastChildNode(self.p, head, '')
265 p = c.createLastChildNode(self.p, head, '')
252 LeoNode(p).v = val
266 LeoNode(p).v = val
253
267
268 def __delitem__(self, key):
269 """ Remove child
270
271 Allows stuff like wb.foo.clear() to remove all children
272 """
273 self[key].p.doDelete()
274 c.redraw()
275
254 def ipush(self):
276 def ipush(self):
255 """ Does push-to-ipython on the node """
277 """ Does push-to-ipython on the node """
256 push_from_leo(self)
278 push_from_leo(self)
@@ -260,6 +282,12 b' class LeoNode(object, UserDict.DictMixin):'
260 c.setCurrentPosition(self.p)
282 c.setCurrentPosition(self.p)
261 c.redraw()
283 c.redraw()
262
284
285 def append(self):
286 """ Add new node as the last child, return the new node """
287 p = self.p.insertAsLastChild()
288 return LeoNode(p)
289
290
263 def script(self):
291 def script(self):
264 """ Method to get the 'tangled' contents of the node
292 """ Method to get the 'tangled' contents of the node
265
293
@@ -319,6 +347,19 b' class LeoWorkbook:'
319 if re.match(cmp, node.h, re.IGNORECASE):
347 if re.match(cmp, node.h, re.IGNORECASE):
320 yield node
348 yield node
321 return
349 return
350
351 def require(self, req):
352 """ Used to control node push dependencies
353
354 Call this as first statement in nodes. If node has not been pushed, it will be pushed before proceeding
355
356 E.g. wb.require('foo') will do wb.foo.ipush() if it hasn't been done already
357 """
358
359 if req not in _leo_push_history:
360 es('Require: ' + req)
361 getattr(self,req).ipush()
362
322
363
323 @IPython.generics.complete_object.when_type(LeoWorkbook)
364 @IPython.generics.complete_object.when_type(LeoWorkbook)
324 def workbook_complete(obj, prev):
365 def workbook_complete(obj, prev):
@@ -361,9 +402,13 b' def push_ipython_script(node):'
361 hstart = len(ip.IP.input_hist)
402 hstart = len(ip.IP.input_hist)
362 script = node.script()
403 script = node.script()
363
404
405 # The current node _p needs to handle wb.require() and recursive ipushes
406 old_p = ip.user_ns.get('_p',None)
364 ip.user_ns['_p'] = node
407 ip.user_ns['_p'] = node
365 ip.runlines(script)
408 ip.runlines(script)
366 ip.user_ns.pop('_p',None)
409 ip.user_ns['_p'] = old_p
410 if old_p is None:
411 del ip.user_ns['_p']
367
412
368 has_output = False
413 has_output = False
369 for idx in range(hstart,len(ip.IP.input_hist)):
414 for idx in range(hstart,len(ip.IP.input_hist)):
@@ -428,6 +473,14 b' def push_ev_node(node):'
428 res = ip.ev(expr)
473 res = ip.ev(expr)
429 node.v = res
474 node.v = res
430
475
476 def push_mark_req(node):
477 """ This should be the first one that gets called.
478
479 It will mark the node as 'pushed', for wb.require.
480 """
481 _leo_push_history.add(node.h)
482 raise TryNext
483
431
484
432 def push_position_from_leo(p):
485 def push_position_from_leo(p):
433 try:
486 try:
@@ -521,13 +574,12 b' def lee_f(self,s):'
521 finally:
574 finally:
522 c.redraw()
575 c.redraw()
523
576
524
525
526 def leoref_f(self,s):
577 def leoref_f(self,s):
527 """ Quick reference for ILeo """
578 """ Quick reference for ILeo """
528 import textwrap
579 import textwrap
529 print textwrap.dedent("""\
580 print textwrap.dedent("""\
530 %leoe file/object - open file / object in leo
581 %lee file/object - open file / object in leo
582 %lleo Launch leo (use if you started ipython first!)
531 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
583 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
532 wb.foo.v = 12 - assign to body of node foo
584 wb.foo.v = 12 - assign to body of node foo
533 wb.foo.b - read or write the body of node foo
585 wb.foo.b - read or write the body of node foo
@@ -560,6 +612,16 b' def mb_completer(self,event):'
560 cmds.sort()
612 cmds.sort()
561 return cmds
613 return cmds
562
614
615 def ileo_pre_prompt_hook(self):
616 # this will fail if leo is not running yet
617 try:
618 c.outerUpdate()
619 except NameError:
620 pass
621 raise TryNext
622
623
624
563 def show_welcome():
625 def show_welcome():
564 print "------------------"
626 print "------------------"
565 print "Welcome to Leo-enabled IPython session!"
627 print "Welcome to Leo-enabled IPython session!"
@@ -574,5 +636,25 b' def run_leo_startup_node():'
574 print "Running @ipy-startup nodes"
636 print "Running @ipy-startup nodes"
575 for n in LeoNode(p):
637 for n in LeoNode(p):
576 push_from_leo(n)
638 push_from_leo(n)
577
578
639
640 def lleo_f(selg, args):
641 """ Launch leo from within IPython
642
643 This command will return immediately when Leo has been
644 launched, leaving a Leo session that is connected
645 with current IPython session (once you press alt+I in leo)
646
647 Usage::
648 lleo foo.leo
649 lleo
650 """
651
652 import shlex, sys
653 argv = ['leo'] + shlex.split(args)
654 sys.argv = argv
655 # if this var exists and is true, leo will "launch" (connect)
656 # ipython immediately when it's started
657 global _request_immediate_connect
658 _request_immediate_connect = True
659 import leo.core.runLeo
660 leo.core.runLeo.run()
@@ -193,7 +193,7 b' which already exists. But you must first start the logging process with'
193 try:
193 try:
194 input_hist = self.shell.user_ns['_ih']
194 input_hist = self.shell.user_ns['_ih']
195 except:
195 except:
196 print 'userns:',self.shell.user_ns.keys()
196 #print 'userns:',self.shell.user_ns.keys() # dbg
197 return
197 return
198
198
199 out_cache = self.shell.outputcache
199 out_cache = self.shell.outputcache
@@ -2693,6 +2693,8 b' Defaulting color scheme to \'NoColor\'"""'
2693
2693
2694 cd -<n>: changes to the n-th directory in the directory history.
2694 cd -<n>: changes to the n-th directory in the directory history.
2695
2695
2696 cd --foo: change to directory that matches 'foo' in history
2697
2696 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
2698 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
2697 (note: cd <bookmark_name> is enough if there is no
2699 (note: cd <bookmark_name> is enough if there is no
2698 directory <bookmark_name>, but a bookmark with the name exists.)
2700 directory <bookmark_name>, but a bookmark with the name exists.)
@@ -2722,6 +2724,31 b' Defaulting color scheme to \'NoColor\'"""'
2722 return
2724 return
2723 else:
2725 else:
2724 opts = {}
2726 opts = {}
2727 elif parameter_s.startswith('--'):
2728 ps = None
2729 fallback = None
2730 pat = parameter_s[2:]
2731 dh = self.shell.user_ns['_dh']
2732 # first search only by basename (last component)
2733 for ent in reversed(dh):
2734 if pat in os.path.basename(ent) and os.path.isdir(ent):
2735 ps = ent
2736 break
2737
2738 if fallback is None and pat in ent and os.path.isdir(ent):
2739 fallback = ent
2740
2741 # if we have no last part match, pick the first full path match
2742 if ps is None:
2743 ps = fallback
2744
2745 if ps is None:
2746 print "No matching entry in directory history"
2747 return
2748 else:
2749 opts = {}
2750
2751
2725 else:
2752 else:
2726 #turn all non-space-escaping backslashes to slashes,
2753 #turn all non-space-escaping backslashes to slashes,
2727 # for c:\windows\directory\names\
2754 # for c:\windows\directory\names\
@@ -22,10 +22,10 b" name = 'ipython'"
22 # because bdist_rpm does not accept dashes (an RPM) convention, and
22 # because bdist_rpm does not accept dashes (an RPM) convention, and
23 # bdist_deb does not accept underscores (a Debian convention).
23 # bdist_deb does not accept underscores (a Debian convention).
24
24
25 development = True # change this to False to do a release
25 development = False # change this to False to do a release
26 version_base = '0.9.0'
26 version_base = '0.9.beta'
27 branch = 'ipython'
27 branch = 'ipython'
28 revision = '1016'
28 revision = '1099'
29
29
30 if development:
30 if development:
31 if branch == 'ipython':
31 if branch == 'ipython':
@@ -1009,7 +1009,7 b' class InteractiveShell(object,Magic):'
1009 hello
1009 hello
1010
1010
1011 In [10]: _ip.IP.complete('x.l')
1011 In [10]: _ip.IP.complete('x.l')
1012 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip'] # random
1012 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1013 """
1013 """
1014
1014
1015 complete = self.Completer.complete
1015 complete = self.Completer.complete
@@ -128,8 +128,9 b' class IEngineCoreTestCase(object):'
128 return d
128 return d
129
129
130 @parametric
130 @parametric
131 def testExecuteFailures(cls):
131 def testExecuteFailuresEngineService(cls):
132 return [(cls.runTestExecuteFailures, cmd, exc) for cmd, exc in invalidCommands]
132 return [(cls.runTestExecuteFailures, cmd, exc)
133 for cmd, exc in invalidCommands]
133
134
134 def runTestPushPull(self, o):
135 def runTestPushPull(self, o):
135 d = self.engine.push(dict(a=o))
136 d = self.engine.push(dict(a=o))
@@ -187,7 +187,7 b' class IMultiEngineTestCase(IMultiEngineBaseTestCase):'
187 return d
187 return d
188
188
189 @parametric
189 @parametric
190 def testExecuteFailures(cls):
190 def testExecuteFailuresMultiEng(cls):
191 return [(cls.runExecuteFailures,cmd,exc) for
191 return [(cls.runExecuteFailures,cmd,exc) for
192 cmd,exc in invalidCommands]
192 cmd,exc in invalidCommands]
193
193
@@ -3,49 +3,70 b' PREFIX=~/usr/local'
3 PREFIX=~/tmp/local
3 PREFIX=~/tmp/local
4
4
5 NOSE0=nosetests -vs --with-doctest --doctest-tests --detailed-errors
5 NOSE0=nosetests -vs --with-doctest --doctest-tests --detailed-errors
6 NOSE=nosetests -vvs --with-ipdoctest --doctest-tests --doctest-extension=txt --detailed-errors
6 NOSE=nosetests -vvs --with-ipdoctest --doctest-tests --doctest-extension=txt \
7
7 --detailed-errors
8 #--with-color
9
8
10 SRC=ipdoctest.py setup.py ../decorators.py
9 SRC=ipdoctest.py setup.py ../decorators.py
11
10
11 # Default target for clean 'make'
12 default: iplib
13
14 # The actual plugin installation
12 plugin: IPython_doctest_plugin.egg-info
15 plugin: IPython_doctest_plugin.egg-info
13
16
17 # Simple targets that test one thing
18 simple: plugin simple.py
19 $(NOSE) simple.py
20
14 dtest: plugin dtexample.py
21 dtest: plugin dtexample.py
15 $(NOSE) dtexample.py
22 $(NOSE) dtexample.py
16
23
17 # Note: this test is double counting!!!
24 rtest: plugin test_refs.py
18 rtest: plugin dtexample.py
19 $(NOSE) test_refs.py
25 $(NOSE) test_refs.py
20
26
21 std: plugin
22 nosetests -vs --with-doctest --doctest-tests IPython.strdispatch
23 $(NOSE) IPython.strdispatch
24
25 test: plugin dtexample.py
27 test: plugin dtexample.py
26 $(NOSE) dtexample.py test*.py test*.txt
28 $(NOSE) dtexample.py test*.py test*.txt
27
29
28 deb: plugin dtexample.py
30 deb: plugin dtexample.py
29 $(NOSE) test_combo.txt
31 $(NOSE) test_combo.txt
30
32
31 iptest: plugin
33 # IPython tests
32 $(NOSE) IPython
33
34 deco:
34 deco:
35 $(NOSE0) IPython.testing.decorators
35 $(NOSE0) IPython.testing.decorators
36
36
37 mtest: plugin
37 magic: plugin
38 $(NOSE) -x IPython.Magic
38 $(NOSE) IPython.Magic
39
39
40 ipipe: plugin
40 ipipe: plugin
41 $(NOSE) -x IPython.Extensions.ipipe
41 $(NOSE) IPython.Extensions.ipipe
42
43 iplib: plugin
44 $(NOSE) IPython.iplib
45
46 strd: plugin
47 $(NOSE) IPython.strdispatch
48
49 engine: plugin
50 $(NOSE) IPython.kernel
51
52 tf: plugin
53 $(NOSE) IPython.config.traitlets
54
55 # All of ipython itself
56 ipython: plugin
57 $(NOSE) IPython
58
59
60 # Combined targets
61 sr: rtest strd
42
62
43 sr: rtest std
63 base: dtest rtest test strd deco
44
64
45 base: dtest rtest test std deco
65 quick: base iplib ipipe
46
66
47 all: base iptest
67 all: base ipython
48
68
69 # Main plugin and cleanup
49 IPython_doctest_plugin.egg-info: $(SRC)
70 IPython_doctest_plugin.egg-info: $(SRC)
50 python setup.py install --prefix=$(PREFIX)
71 python setup.py install --prefix=$(PREFIX)
51 touch $@
72 touch $@
@@ -58,6 +58,12 b' def ipfunc():'
58 numbered history of _NN outputs, since those won't exist under the
58 numbered history of _NN outputs, since those won't exist under the
59 doctest environment:
59 doctest environment:
60
60
61 In [7]: 'hi'
62 Out[7]: 'hi'
63
64 In [8]: print repr(_)
65 'hi'
66
61 In [7]: 3+4
67 In [7]: 3+4
62 Out[7]: 7
68 Out[7]: 7
63
69
@@ -13,21 +13,6 b' Limitations:'
13 '_34==True', for example). For IPython tests run via an external process the
13 '_34==True', for example). For IPython tests run via an external process the
14 prompt numbers may be different, and IPython tests run as normal python code
14 prompt numbers may be different, and IPython tests run as normal python code
15 won't even have these special _NN variables set at all.
15 won't even have these special _NN variables set at all.
16
17 - IPython functions that produce output as a side-effect of calling a system
18 process (e.g. 'ls') can be doc-tested, but they must be handled in an
19 external IPython process. Such doctests must be tagged with:
20
21 # ipdoctest: EXTERNAL
22
23 so that the testing machinery handles them differently. Since these are run
24 via pexpect in an external process, they can't deal with exceptions or other
25 fancy featurs of regular doctests. You must limit such tests to simple
26 matching of the output. For this reason, I recommend you limit these kinds
27 of doctests to features that truly require a separate process, and use the
28 normal IPython ones (which have all the features of normal doctests) for
29 everything else. See the examples at the bottom of this file for a
30 comparison of what can be done with both types.
31 """
16 """
32
17
33
18
@@ -63,9 +48,6 b' import nose.core'
63 from nose.plugins import doctests, Plugin
48 from nose.plugins import doctests, Plugin
64 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
49 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
65
50
66 # Our own imports
67 #from extdoctest import ExtensionDoctest, DocTestFinder
68 #from dttools import DocTestFinder, DocTestCase
69 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
70 # Module globals and other constants
52 # Module globals and other constants
71
53
@@ -79,9 +61,9 b' log = logging.getLogger(__name__)'
79 # gets the job done.
61 # gets the job done.
80
62
81
63
82 # XXX - Hack to modify the %run command so we can sync the user's namespace
64 # Hack to modify the %run command so we can sync the user's namespace with the
83 # with the test globals. Once we move over to a clean magic system, this will
65 # test globals. Once we move over to a clean magic system, this will be done
84 # be done with much less ugliness.
66 # with much less ugliness.
85
67
86 def _run_ns_sync(self,arg_s,runner=None):
68 def _run_ns_sync(self,arg_s,runner=None):
87 """Modified version of %run that syncs testing namespaces.
69 """Modified version of %run that syncs testing namespaces.
@@ -94,6 +76,35 b' def _run_ns_sync(self,arg_s,runner=None):'
94 return out
76 return out
95
77
96
78
79 class ipnsdict(dict):
80 """A special subclass of dict for use as an IPython namespace in doctests.
81
82 This subclass adds a simple checkpointing capability so that when testing
83 machinery clears it (we use it as the test execution context), it doesn't
84 get completely destroyed.
85 """
86
87 def __init__(self,*a):
88 dict.__init__(self,*a)
89 self._savedict = {}
90
91 def clear(self):
92 dict.clear(self)
93 self.update(self._savedict)
94
95 def _checkpoint(self):
96 self._savedict.clear()
97 self._savedict.update(self)
98
99 def update(self,other):
100 self._checkpoint()
101 dict.update(self,other)
102 # If '_' is in the namespace, python won't set it when executing code,
103 # and we have examples that test it. So we ensure that the namespace
104 # is always 'clean' of it before it's used for test code execution.
105 self.pop('_',None)
106
107
97 def start_ipython():
108 def start_ipython():
98 """Start a global IPython shell, which we need for IPython-specific syntax.
109 """Start a global IPython shell, which we need for IPython-specific syntax.
99 """
110 """
@@ -117,7 +128,10 b' def start_ipython():'
117 _main = sys.modules.get('__main__')
128 _main = sys.modules.get('__main__')
118
129
119 # Start IPython instance. We customize it to start with minimal frills.
130 # Start IPython instance. We customize it to start with minimal frills.
120 IPython.Shell.IPShell(['--classic','--noterm_title'])
131 user_ns,global_ns = IPython.ipapi.make_user_namespaces(ipnsdict(),dict())
132
133 IPython.Shell.IPShell(['--classic','--noterm_title'],
134 user_ns,global_ns)
121
135
122 # Deactivate the various python system hooks added by ipython for
136 # Deactivate the various python system hooks added by ipython for
123 # interactive convenience so we don't confuse the doctest system
137 # interactive convenience so we don't confuse the doctest system
@@ -257,7 +271,7 b' class IPDoctestOutputChecker(doctest.OutputChecker):'
257 output string for flags that tell us to ignore the output.
271 output string for flags that tell us to ignore the output.
258 """
272 """
259
273
260 random_re = re.compile(r'#\s*random')
274 random_re = re.compile(r'#\s*random\s+')
261
275
262 def check_output(self, want, got, optionflags):
276 def check_output(self, want, got, optionflags):
263 """Check output, accepting special markers embedded in the output.
277 """Check output, accepting special markers embedded in the output.
@@ -307,12 +321,20 b' class DocTestCase(doctests.DocTestCase):'
307 self._dt_setUp = setUp
321 self._dt_setUp = setUp
308 self._dt_tearDown = tearDown
322 self._dt_tearDown = tearDown
309
323
324 # XXX - store this runner once in the object!
325 runner = IPDocTestRunner(optionflags=optionflags,
326 checker=checker, verbose=False)
327 self._dt_runner = runner
328
329
310 # Each doctest should remember what directory it was loaded from...
330 # Each doctest should remember what directory it was loaded from...
311 self._ori_dir = os.getcwd()
331 self._ori_dir = os.getcwd()
312
332
313 # Modified runTest from the default stdlib
333 # Modified runTest from the default stdlib
314 def runTest(self):
334 def runTest(self):
315 test = self._dt_test
335 test = self._dt_test
336 runner = self._dt_runner
337
316 old = sys.stdout
338 old = sys.stdout
317 new = StringIO()
339 new = StringIO()
318 optionflags = self._dt_optionflags
340 optionflags = self._dt_optionflags
@@ -322,9 +344,6 b' class DocTestCase(doctests.DocTestCase):'
322 # so add the default reporting flags
344 # so add the default reporting flags
323 optionflags |= _unittest_reportflags
345 optionflags |= _unittest_reportflags
324
346
325 runner = IPDocTestRunner(optionflags=optionflags,
326 checker=self._dt_checker, verbose=False)
327
328 try:
347 try:
329 # Save our current directory and switch out to the one where the
348 # Save our current directory and switch out to the one where the
330 # test was originally created, in case another doctest did a
349 # test was originally created, in case another doctest did a
@@ -333,8 +352,8 b' class DocTestCase(doctests.DocTestCase):'
333 os.chdir(self._ori_dir)
352 os.chdir(self._ori_dir)
334
353
335 runner.DIVIDER = "-"*70
354 runner.DIVIDER = "-"*70
336 failures, tries = runner.run(
355 failures, tries = runner.run(test,out=new.write,
337 test, out=new.write, clear_globs=False)
356 clear_globs=False)
338 finally:
357 finally:
339 sys.stdout = old
358 sys.stdout = old
340 os.chdir(curdir)
359 os.chdir(curdir)
@@ -342,6 +361,19 b' class DocTestCase(doctests.DocTestCase):'
342 if failures:
361 if failures:
343 raise self.failureException(self.format_failure(new.getvalue()))
362 raise self.failureException(self.format_failure(new.getvalue()))
344
363
364 def setUp(self):
365 """Modified test setup that syncs with ipython namespace"""
366
367 if isinstance(self._dt_test.examples[0],IPExample):
368 # for IPython examples *only*, we swap the globals with the ipython
369 # namespace, after updating it with the globals (which doctest
370 # fills with the necessary info from the module being tested).
371 _ip.IP.user_ns.update(self._dt_test.globs)
372 self._dt_test.globs = _ip.IP.user_ns
373
374 doctests.DocTestCase.setUp(self)
375
376
345
377
346 # A simple subclassing of the original with a different class name, so we can
378 # A simple subclassing of the original with a different class name, so we can
347 # distinguish and treat differently IPython examples from pure python ones.
379 # distinguish and treat differently IPython examples from pure python ones.
@@ -403,7 +435,7 b' class IPDocTestParser(doctest.DocTestParser):'
403 # Mark a test as being fully random. In this case, we simply append the
435 # Mark a test as being fully random. In this case, we simply append the
404 # random marker ('#random') to each individual example's output. This way
436 # random marker ('#random') to each individual example's output. This way
405 # we don't need to modify any other code.
437 # we don't need to modify any other code.
406 _RANDOM_TEST = re.compile(r'#\s*all-random')
438 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
407
439
408 # Mark tests to be executed in an external process - currently unsupported.
440 # Mark tests to be executed in an external process - currently unsupported.
409 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
441 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
@@ -438,6 +470,8 b' class IPDocTestParser(doctest.DocTestParser):'
438 output = []
470 output = []
439 charno, lineno = 0, 0
471 charno, lineno = 0, 0
440
472
473 # We make 'all random' tests by adding the '# random' mark to every
474 # block of output in the test.
441 if self._RANDOM_TEST.search(string):
475 if self._RANDOM_TEST.search(string):
442 random_marker = '\n# random'
476 random_marker = '\n# random'
443 else:
477 else:
@@ -605,12 +639,6 b' class IPDocTestRunner(doctest.DocTestRunner,object):'
605 # for all examples, most of which won't be calling %run anyway).
639 # for all examples, most of which won't be calling %run anyway).
606 _run_ns_sync.test_globs = test.globs
640 _run_ns_sync.test_globs = test.globs
607
641
608 # dbg
609 ## print >> sys.stderr, "Test:",test
610 ## for ex in test.examples:
611 ## print >> sys.stderr, ex.source
612 ## print >> sys.stderr, 'Want:\n',ex.want,'\n--'
613
614 return super(IPDocTestRunner,self).run(test,
642 return super(IPDocTestRunner,self).run(test,
615 compileflags,out,clear_globs)
643 compileflags,out,clear_globs)
616
644
@@ -635,8 +663,10 b' class ExtensionDoctest(doctests.Doctest):'
635 Plugin.configure(self, options, config)
663 Plugin.configure(self, options, config)
636 self.doctest_tests = options.doctest_tests
664 self.doctest_tests = options.doctest_tests
637 self.extension = tolist(options.doctestExtension)
665 self.extension = tolist(options.doctestExtension)
638 self.finder = DocTestFinder()
666
639 self.parser = doctest.DocTestParser()
667 self.parser = doctest.DocTestParser()
668 self.finder = DocTestFinder()
669 self.checker = IPDoctestOutputChecker()
640 self.globs = None
670 self.globs = None
641 self.extraglobs = None
671 self.extraglobs = None
642
672
@@ -666,6 +696,9 b' class ExtensionDoctest(doctests.Doctest):'
666 if not tests:
696 if not tests:
667 return
697 return
668
698
699 # always use whitespace and ellipsis options
700 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
701
669 tests.sort()
702 tests.sort()
670 module_file = module.__file__
703 module_file = module.__file__
671 if module_file[-4:] in ('.pyc', '.pyo'):
704 if module_file[-4:] in ('.pyc', '.pyo'):
@@ -675,15 +708,11 b' class ExtensionDoctest(doctests.Doctest):'
675 continue
708 continue
676 if not test.filename:
709 if not test.filename:
677 test.filename = module_file
710 test.filename = module_file
678
679 # xxx - checker and options may be ok instantiated once outside loop
680 # always use whitespace and ellipsis options
681 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
682 checker = IPDoctestOutputChecker()
683
711
684 yield DocTestCase(test,
712 yield DocTestCase(test,
685 optionflags=optionflags,
713 optionflags=optionflags,
686 checker=checker)
714 checker=self.checker)
715
687
716
688 def loadTestsFromFile(self, filename):
717 def loadTestsFromFile(self, filename):
689 #print 'lTF',filename # dbg
718 #print 'lTF',filename # dbg
@@ -716,7 +745,7 b' class ExtensionDoctest(doctests.Doctest):'
716 """
745 """
717 #print 'Filename:',filename # dbg
746 #print 'Filename:',filename # dbg
718
747
719 # temporarily hardcoded list, will move to driver later
748 # XXX - temporarily hardcoded list, will move to driver later
720 exclude = ['IPython/external/',
749 exclude = ['IPython/external/',
721 'IPython/Extensions/ipy_',
750 'IPython/Extensions/ipy_',
722 'IPython/platutils_win32',
751 'IPython/platutils_win32',
@@ -747,7 +776,9 b' class IPythonDoctest(ExtensionDoctest):'
747 Plugin.configure(self, options, config)
776 Plugin.configure(self, options, config)
748 self.doctest_tests = options.doctest_tests
777 self.doctest_tests = options.doctest_tests
749 self.extension = tolist(options.doctestExtension)
778 self.extension = tolist(options.doctestExtension)
779
750 self.parser = IPDocTestParser()
780 self.parser = IPDocTestParser()
751 self.finder = DocTestFinder(parser=self.parser)
781 self.finder = DocTestFinder(parser=self.parser)
782 self.checker = IPDoctestOutputChecker()
752 self.globs = None
783 self.globs = None
753 self.extraglobs = None
784 self.extraglobs = None
@@ -1,6 +1,7 b''
1 include README_Windows.txt
1 include README_Windows.txt
2 include win32_manual_post_install.py
2 include win32_manual_post_install.py
3 include ipython.py
3 include ipython.py
4 include setupbase.py
4
5
5 graft scripts
6 graft scripts
6
7
@@ -13,14 +14,15 b' graft IPython/config'
13 graft IPython/testing
14 graft IPython/testing
14 graft IPython/tools
15 graft IPython/tools
15
16
17 recursive-include IPython/Extensions igrid_help*
18
16 graft docs
19 graft docs
17 exclude docs/\#*
20 exclude docs/\#*
18 exclude docs/man/*.1
21 exclude docs/man/*.1
19
22
20 # There seems to be no way of excluding whole subdirectories, other than
23 # docs subdirs we want to skip
21 # manually excluding all their subdirs. distutils really is horrible...
24 prune docs/attic
22 exclude docs/attic/*
25 prune docs/build
23 exclude docs/build/*
24
26
25 global-exclude *~
27 global-exclude *~
26 global-exclude *.flc
28 global-exclude *.flc
@@ -21,10 +21,27 b' help:'
21 @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
21 @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
22 @echo " changes to make an overview over all changed/added/deprecated items"
22 @echo " changes to make an overview over all changed/added/deprecated items"
23 @echo " linkcheck to check all external links for integrity"
23 @echo " linkcheck to check all external links for integrity"
24 @echo
25 @echo "Compound utility targets:"
26 @echo "pdf latex and then runs the PDF generation"
27 @echo "all html and pdf"
28 @echo "dist all, and then puts the results in dist/"
24
29
25 clean:
30 clean:
26 -rm -rf build/*
31 -rm -rf build/*
27
32
33 pdf: latex
34 cd build/latex && make all-pdf
35
36 all: html pdf
37
38 dist: all
39 mkdir -p dist
40 -rm -rf dist/*
41 ln build/latex/IPython.pdf dist/
42 cp -al build/html dist/
43 @echo "Build finished. Final docs are in dist/"
44
28 html:
45 html:
29 mkdir -p build/html build/doctrees
46 mkdir -p build/html build/doctrees
30 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
47 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
@@ -53,6 +53,9 b' New features'
53 the main usage of the script is for starting things on localhost. Eventually
53 the main usage of the script is for starting things on localhost. Eventually
54 when ipcluster is able to start things on other hosts, we will put security
54 when ipcluster is able to start things on other hosts, we will put security
55 back.
55 back.
56 * 'cd --foo' searches directory history for string foo, and jumps to that dir.
57 Last part of dir name is checked first. If no matches for that are found,
58 look at the whole path.
56
59
57 Bug fixes
60 Bug fixes
58 ---------
61 ---------
@@ -64,6 +67,8 b' Bug fixes'
64 * A few subpackages has missing `__init__.py` files.
67 * A few subpackages has missing `__init__.py` files.
65 * The documentation is only created is Sphinx is found. Previously, the `setup.py`
68 * The documentation is only created is Sphinx is found. Previously, the `setup.py`
66 script would fail if it was missing.
69 script would fail if it was missing.
70 * Greedy 'cd' completion has been disabled again (it was enabled in 0.8.4)
71
67
72
68 Backwards incompatible changes
73 Backwards incompatible changes
69 ------------------------------
74 ------------------------------
@@ -44,7 +44,7 b" copyright = '2008, The IPython Development Team'"
44 # The short X.Y version.
44 # The short X.Y version.
45 version = '0.9'
45 version = '0.9'
46 # The full version, including alpha/beta/rc tags.
46 # The full version, including alpha/beta/rc tags.
47 release = '0.9'
47 release = '0.9.beta1'
48
48
49 # There are two options for replacing |today|: either, you set today to some
49 # There are two options for replacing |today|: either, you set today to some
50 # non-false value, then it is used:
50 # non-false value, then it is used:
@@ -135,13 +135,17 b" htmlhelp_basename = 'IPythondoc'"
135 latex_paper_size = 'letter'
135 latex_paper_size = 'letter'
136
136
137 # The font size ('10pt', '11pt' or '12pt').
137 # The font size ('10pt', '11pt' or '12pt').
138 latex_font_size = '10pt'
138 latex_font_size = '11pt'
139
139
140 # Grouping the document tree into LaTeX files. List of tuples
140 # Grouping the document tree into LaTeX files. List of tuples
141 # (source start file, target name, title, author, document class [howto/manual]).
141 # (source start file, target name, title, author, document class [howto/manual]).
142 latex_documents = [
142
143 ('index', 'IPython.tex', 'IPython Documentation', 'The IPython Development Team', 'manual'),
143 latex_documents = [ ('index', 'IPython.tex', 'IPython Documentation',
144 ]
144 ur"""Brian Granger and Fernando Pérez\\
145 With contributions from:\\
146 Benjamin Ragan-Kelley and Ville Vainio.""",
147 'manual'),
148 ]
145
149
146 # The name of an image file (relative to this directory) to place at the top of
150 # The name of an image file (relative to this directory) to place at the top of
147 # the title page.
151 # the title page.
@@ -75,17 +75,17 b" if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):"
75 to_update = [
75 to_update = [
76 # FIXME - Disabled for now: we need to redo an automatic way
76 # FIXME - Disabled for now: we need to redo an automatic way
77 # of generating the magic info inside the rst.
77 # of generating the magic info inside the rst.
78 #('doc/magic.tex',
78 #('docs/magic.tex',
79 #['IPython/Magic.py'],
79 #['IPython/Magic.py'],
80 #"cd doc && ./update_magic.sh" ),
80 #"cd doc && ./update_magic.sh" ),
81
81
82 ('doc/ipython.1.gz',
82 ('docs/man/ipython.1.gz',
83 ['doc/ipython.1'],
83 ['docs/man/ipython.1'],
84 "cd doc && gzip -9c ipython.1 > ipython.1.gz"),
84 "cd docs/man && gzip -9c ipython.1 > ipython.1.gz"),
85
85
86 ('doc/pycolor.1.gz',
86 ('docs/man/pycolor.1.gz',
87 ['doc/pycolor.1'],
87 ['docs/man/pycolor.1'],
88 "cd doc && gzip -9c pycolor.1 > pycolor.1.gz"),
88 "cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz"),
89 ]
89 ]
90
90
91 # Only build the docs is sphinx is present
91 # Only build the docs is sphinx is present
@@ -101,12 +101,16 b" if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):"
101 # The do_sphinx scripts builds html and pdf, so just one
101 # The do_sphinx scripts builds html and pdf, so just one
102 # target is enough to cover all manual generation
102 # target is enough to cover all manual generation
103 # to_update.append(
103 # to_update.append(
104 # ('doc/manual/ipython.pdf',
104 # ('docs/manual/ipython.pdf',
105 # ['IPython/Release.py','doc/source/ipython.rst'],
105 # ['IPython/Release.py','docs/source/ipython.rst'],
106 # "cd docs && python do_sphinx.py")
106 # "cd docs && python do_sphinx.py")
107 # )
107 # )
108
108 [ target_update(*t) for t in to_update ]
109 [ target_update(*t) for t in to_update ]
109
110
111 # Build the docs
112 os.system('cd docs && make dist')
113
110 #---------------------------------------------------------------------------
114 #---------------------------------------------------------------------------
111 # Find all the packages, package data, scripts and data_files
115 # Find all the packages, package data, scripts and data_files
112 #---------------------------------------------------------------------------
116 #---------------------------------------------------------------------------
@@ -82,7 +82,8 b' setup_args = dict('
82 # Find packages
82 # Find packages
83 #---------------------------------------------------------------------------
83 #---------------------------------------------------------------------------
84
84
85 def add_package(packages, pname, config=False, tests=False, scripts=False, others=None):
85 def add_package(packages,pname,config=False,tests=False,scripts=False,
86 others=None):
86 """
87 """
87 Add a package to the list of packages, including certain subpackages.
88 Add a package to the list of packages, including certain subpackages.
88 """
89 """
@@ -140,37 +141,74 b' def find_package_data():'
140 # Find data files
141 # Find data files
141 #---------------------------------------------------------------------------
142 #---------------------------------------------------------------------------
142
143
144 def make_dir_struct(tag,base,out_base):
145 """Make the directory structure of all files below a starting dir.
146
147 This is just a convenience routine to help build a nested directory
148 hierarchy because distutils is too stupid to do this by itself.
149
150 XXX - this needs a proper docstring!
151 """
152
153 # we'll use these a lot below
154 lbase = len(base)
155 pathsep = os.path.sep
156 lpathsep = len(pathsep)
157
158 out = []
159 for (dirpath,dirnames,filenames) in os.walk(base):
160 # we need to strip out the dirpath from the base to map it to the
161 # output (installation) path. This requires possibly stripping the
162 # path separator, because otherwise pjoin will not work correctly
163 # (pjoin('foo/','/bar') returns '/bar').
164
165 dp_eff = dirpath[lbase:]
166 if dp_eff.startswith(pathsep):
167 dp_eff = dp_eff[lpathsep:]
168 # The output path must be anchored at the out_base marker
169 out_path = pjoin(out_base,dp_eff)
170 # Now we can generate the final filenames. Since os.walk only produces
171 # filenames, we must join back with the dirpath to get full valid file
172 # paths:
173 pfiles = [pjoin(dirpath,f) for f in filenames]
174 # Finally, generate the entry we need, which is a triple of (tag,output
175 # path, files) for use as a data_files parameter in install_data.
176 out.append((tag,out_path,pfiles))
177
178 return out
179
180
143 def find_data_files():
181 def find_data_files():
144 """
182 """
145 Find IPython's data_files.
183 Find IPython's data_files.
184
185 Most of these are docs.
146 """
186 """
147
187
148 # I can't find how to make distutils create a nested dir. structure, so
149 # in the meantime do it manually. Butt ugly.
150 # Note that http://www.redbrick.dcu.ie/~noel/distutils.html, ex. 2/3, contain
151 # information on how to do this more cleanly once python 2.4 can be assumed.
152 # Thanks to Noel for the tip.
153 docdirbase = 'share/doc/ipython'
188 docdirbase = 'share/doc/ipython'
154 manpagebase = 'share/man/man1'
189 manpagebase = 'share/man/man1'
155
190
156 # We only need to exclude from this things NOT already excluded in the
191 # Simple file lists can be made by hand
157 # MANIFEST.in file.
192 manpages = filter(isfile, glob('docs/man/*.1.gz'))
158 exclude = ('.sh','.1.gz')
159 # We need to figure out how we want to package all of our rst docs?
160 # docfiles = filter(lambda f:file_doesnt_endwith(f,exclude),glob('docs/*'))
161 examfiles = filter(isfile, glob('docs/examples/core/*.py'))
162 examfiles.append(filter(isfile, glob('docs/examples/kernel/*.py')))
163 manpages = filter(isfile, glob('docs/man/*.1.gz'))
164 igridhelpfiles = filter(isfile, glob('IPython/Extensions/igrid_help.*'))
193 igridhelpfiles = filter(isfile, glob('IPython/Extensions/igrid_help.*'))
194
195 # For nested structures, use the utility above
196 example_files = make_dir_struct('data','docs/examples',
197 pjoin(docdirbase,'examples'))
198 manual_files = make_dir_struct('data','docs/dist',pjoin(docdirbase,'manual'))
199
200 # And assemble the entire output list
201 data_files = [ ('data',manpagebase, manpages),
202 ('data',pjoin(docdirbase,'extensions'),igridhelpfiles),
203 ] + manual_files + example_files
204
205 ## import pprint # dbg
206 ## print '*'*80
207 ## print 'data files'
208 ## pprint.pprint(data_files)
209 ## print '*'*80
165
210
166 data_files = [#('data', docdirbase, docfiles),
211 return data_files
167 ('data', pjoin(docdirbase, 'examples'),examfiles),
168 ('data', manpagebase, manpages),
169 ('data',pjoin(docdirbase, 'extensions'),igridhelpfiles),
170 ]
171 # import pprint
172 # pprint.pprint(data_files)
173 return []
174
212
175 #---------------------------------------------------------------------------
213 #---------------------------------------------------------------------------
176 # Find scripts
214 # Find scripts
@@ -180,14 +218,14 b' def find_scripts():'
180 """
218 """
181 Find IPython's scripts.
219 Find IPython's scripts.
182 """
220 """
183 scripts = []
221 scripts = ['IPython/kernel/scripts/ipengine',
184 scripts.append('IPython/kernel/scripts/ipengine')
222 'IPython/kernel/scripts/ipcontroller',
185 scripts.append('IPython/kernel/scripts/ipcontroller')
223 'IPython/kernel/scripts/ipcluster',
186 scripts.append('IPython/kernel/scripts/ipcluster')
224 'scripts/ipython',
187 scripts.append('scripts/ipython')
225 'scripts/ipythonx',
188 scripts.append('scripts/ipythonx')
226 'scripts/pycolor',
189 scripts.append('scripts/pycolor')
227 'scripts/irunner',
190 scripts.append('scripts/irunner')
228 ]
191
229
192 # Script to be run by the windows binary installer after the default setup
230 # Script to be run by the windows binary installer after the default setup
193 # routine, to add shortcuts and similar windows-only things. Windows
231 # routine, to add shortcuts and similar windows-only things. Windows
@@ -202,7 +240,7 b' def find_scripts():'
202 return scripts
240 return scripts
203
241
204 #---------------------------------------------------------------------------
242 #---------------------------------------------------------------------------
205 # Find scripts
243 # Verify all dependencies
206 #---------------------------------------------------------------------------
244 #---------------------------------------------------------------------------
207
245
208 def check_for_dependencies():
246 def check_for_dependencies():
@@ -4,7 +4,7 b''
4
4
5 import os,sys,shutil
5 import os,sys,shutil
6
6
7 basever = '0.8.3'
7 basever = '0.9.0'
8
8
9 def oscmd(c):
9 def oscmd(c):
10 print ">",c
10 print ">",c
@@ -30,7 +30,7 b' ver = verinfo()'
30 if ver['branch-nick'] == 'ipython':
30 if ver['branch-nick'] == 'ipython':
31 tarname = 'ipython-%s.bzr.r%s.tgz' % (basever, ver['revno'])
31 tarname = 'ipython-%s.bzr.r%s.tgz' % (basever, ver['revno'])
32 else:
32 else:
33 tarname = 'ipython-%s.bzr.r%s.%s.tgz' % (basever, ver['revno'], ver['branch-nick'])
33 tarname = 'ipython-%s.bzr.r%s.%s.tgz' % (basever, ver['revno'],
34 ver['branch-nick'])
34
35
35 oscmd('bzr export ' + tarname)
36 oscmd('bzr export ' + tarname)
36
@@ -21,8 +21,8 b' cd $ipdir'
21 ./setup.py sdist --formats=gztar
21 ./setup.py sdist --formats=gztar
22
22
23 # Build rpms
23 # Build rpms
24 python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4
24 #python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4
25 python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5
25 #python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5
26
26
27 # Build eggs
27 # Build eggs
28 python2.4 ./setup_bdist_egg.py
28 python2.4 ./setup_bdist_egg.py
General Comments 0
You need to be logged in to leave comments. Login now