Show More
@@ -0,0 +1,56 b'' | |||||
|
1 | """ Utilities for accessing the platform's clipboard. | |||
|
2 | """ | |||
|
3 | ||||
|
4 | import subprocess | |||
|
5 | import sys | |||
|
6 | ||||
|
7 | from IPython.core.ipapi import TryNext | |||
|
8 | ||||
|
9 | ||||
|
10 | def win32_clipboard_get(): | |||
|
11 | """ Get the current clipboard's text on Windows. | |||
|
12 | ||||
|
13 | Requires Mark Hammond's pywin32 extensions. | |||
|
14 | """ | |||
|
15 | try: | |||
|
16 | import win32clipboard | |||
|
17 | except ImportError: | |||
|
18 | message = ("Getting text from the clipboard requires the pywin32 " | |||
|
19 | "extensions: http://sourceforge.net/projects/pywin32/") | |||
|
20 | raise TryNext(message) | |||
|
21 | win32clipboard.OpenClipboard() | |||
|
22 | text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT) | |||
|
23 | # FIXME: convert \r\n to \n? | |||
|
24 | win32clipboard.CloseClipboard() | |||
|
25 | return text | |||
|
26 | ||||
|
27 | def osx_clipboard_get(): | |||
|
28 | """ Get the clipboard's text on OS X. | |||
|
29 | """ | |||
|
30 | p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'], | |||
|
31 | stdout=subprocess.PIPE) | |||
|
32 | text, stderr = p.communicate() | |||
|
33 | # Text comes in with old Mac \r line endings. Change them to \n. | |||
|
34 | text = text.replace('\r', '\n') | |||
|
35 | return text | |||
|
36 | ||||
|
37 | def tkinter_clipboard_get(): | |||
|
38 | """ Get the clipboard's text using Tkinter. | |||
|
39 | ||||
|
40 | This is the default on systems that are not Windows or OS X. It may | |||
|
41 | interfere with other UI toolkits and should be replaced with an | |||
|
42 | implementation that uses that toolkit. | |||
|
43 | """ | |||
|
44 | try: | |||
|
45 | import Tkinter | |||
|
46 | except ImportError: | |||
|
47 | message = ("Getting text from the clipboard on this platform " | |||
|
48 | "requires Tkinter.") | |||
|
49 | raise TryNext(message) | |||
|
50 | root = Tkinter.Tk() | |||
|
51 | root.withdraw() | |||
|
52 | text = root.clipboard_get() | |||
|
53 | root.destroy() | |||
|
54 | return text | |||
|
55 | ||||
|
56 |
@@ -0,0 +1,85 b'' | |||||
|
1 | """This is meant to be run from the IPython prompt: | |||
|
2 | ||||
|
3 | %run demo-exercizer.py | |||
|
4 | ||||
|
5 | It will create demo objects of the example that is embedded in demo.py in a | |||
|
6 | number of ways and allow you to see how they work, just follow the printed | |||
|
7 | directions.""" | |||
|
8 | ||||
|
9 | #----------------------------------------------------------------------------- | |||
|
10 | # Imports | |||
|
11 | #----------------------------------------------------------------------------- | |||
|
12 | ||||
|
13 | # From std lib | |||
|
14 | import StringIO | |||
|
15 | import os | |||
|
16 | import shutil | |||
|
17 | import tempfile | |||
|
18 | ||||
|
19 | # From IPython | |||
|
20 | from IPython.demo import (Demo, IPythonDemo, LineDemo, IPythonLineDemo, | |||
|
21 | ClearDemo, ClearIPDemo) | |||
|
22 | ||||
|
23 | #----------------------------------------------------------------------------- | |||
|
24 | # Demo code | |||
|
25 | #----------------------------------------------------------------------------- | |||
|
26 | ||||
|
27 | example1 = """ | |||
|
28 | '''A simple interactive demo to illustrate the use of IPython's Demo class.''' | |||
|
29 | ||||
|
30 | print 'Hello, welcome to an interactive IPython demo.' | |||
|
31 | ||||
|
32 | # The mark below defines a block boundary, which is a point where IPython will | |||
|
33 | # stop execution and return to the interactive prompt. The dashes are actually | |||
|
34 | # optional and used only as a visual aid to clearly separate blocks while | |||
|
35 | # editing the demo code. | |||
|
36 | # <demo> stop | |||
|
37 | ||||
|
38 | x = 1 | |||
|
39 | y = 2 | |||
|
40 | ||||
|
41 | # <demo> stop | |||
|
42 | ||||
|
43 | # the mark below makes this block as silent | |||
|
44 | # <demo> silent | |||
|
45 | ||||
|
46 | print 'This is a silent block, which gets executed but not printed.' | |||
|
47 | ||||
|
48 | # <demo> stop | |||
|
49 | # <demo> auto | |||
|
50 | print 'This is an automatic block.' | |||
|
51 | print 'It is executed without asking for confirmation, but printed.' | |||
|
52 | z = x+y | |||
|
53 | ||||
|
54 | print 'z=',x | |||
|
55 | ||||
|
56 | # <demo> stop | |||
|
57 | # This is just another normal block. | |||
|
58 | print 'z is now:', z | |||
|
59 | ||||
|
60 | print 'bye!' | |||
|
61 | """ | |||
|
62 | fp = tempfile.mkdtemp(prefix = 'DemoTmp') | |||
|
63 | fd, filename = tempfile.mkstemp(prefix = 'demoExample1File', suffix = '.py', | |||
|
64 | dir = fp) | |||
|
65 | f = os.fdopen(fd, 'wt') | |||
|
66 | ||||
|
67 | f.write(example1) | |||
|
68 | f.close() | |||
|
69 | ||||
|
70 | my_d = Demo(filename) | |||
|
71 | my_cd = ClearDemo(filename) | |||
|
72 | ||||
|
73 | fobj = StringIO.StringIO(example1) | |||
|
74 | str_d = Demo(fobj, title='via stringio') | |||
|
75 | ||||
|
76 | print ''' | |||
|
77 | The example that is embeded in demo.py file has been used to create | |||
|
78 | the following 3 demos, and should now be available to use: | |||
|
79 | my_d() -- created from a file | |||
|
80 | my_cd() -- created from a file, a ClearDemo | |||
|
81 | str_d() -- same as above, but created via a StringIO object | |||
|
82 | Call by typing their name, (with parentheses), at the | |||
|
83 | ipython prompt, interact with the block, then call again | |||
|
84 | to run the next block. | |||
|
85 | ''' |
@@ -0,0 +1,48 b'' | |||||
|
1 | .TH IPCLUSTER 1 "October 28, 2008" "" "" | |||
|
2 | .SH NAME | |||
|
3 | \fBipcluster \- IPython parallel computing cluster control tool | |||
|
4 | .SH SYNOPSIS | |||
|
5 | .nf | |||
|
6 | .fam C | |||
|
7 | \fBipcluster\fP {\fmpiexec,local,mpirun,pbs,ssh\fP} [\fIoptions\fP] | |||
|
8 | .fam T | |||
|
9 | .fi | |||
|
10 | .SH DESCRIPTION | |||
|
11 | ipcluster is a control tool for IPython's parallel computing functions. | |||
|
12 | ||||
|
13 | IPython cluster startup. This starts a controller and engines using various | |||
|
14 | approaches. Use the IPYTHONDIR environment variable to change your IPython | |||
|
15 | directory from the default of .ipython or _ipython. The log and security | |||
|
16 | subdirectories of your IPython directory will be used by this script for log | |||
|
17 | files and security files. | |||
|
18 | .SH POSITIONAL ARGUMENTS | |||
|
19 | ||||
|
20 | The first positional argument should be one of: {mpiexec, local, mpirun, pbs, | |||
|
21 | ssh}, which are the available cluster types. | |||
|
22 | ||||
|
23 | For detailed help on each, type "ipcluster TYPE --help". Briefly: | |||
|
24 | ||||
|
25 | local run a local cluster | |||
|
26 | mpirun run a cluster using mpirun (mpiexec also works) | |||
|
27 | mpiexec run a cluster using mpiexec (mpirun also works) | |||
|
28 | pbs run a pbs cluster | |||
|
29 | ssh run a cluster using ssh, should have ssh-keys setup | |||
|
30 | .SH OPTIONS | |||
|
31 | .TP | |||
|
32 | .B | |||
|
33 | \-h, \-\-help | |||
|
34 | show help message and exit | |||
|
35 | .SH EXAMPLE | |||
|
36 | ipcluster local -n 4 | |||
|
37 | ||||
|
38 | This command will start 4 IPython engines on the local computer. | |||
|
39 | .SH SEE ALSO | |||
|
40 | .BR ipython(1), ipcontroller(1), ipengine(1) | |||
|
41 | .br | |||
|
42 | .SH AUTHOR | |||
|
43 | \fBipcluster\fP is a tool that ships with IPython, created by | |||
|
44 | the IPython Development Team. | |||
|
45 | .PP | |||
|
46 | This manual page was written by Stephan Peijnik <debian@sp.or.at>, | |||
|
47 | for the Debian project (but may be used by others). Modified by Fernando Perez | |||
|
48 | <Fernando.Perez@berkeley.edu> for inclusion in IPython. |
@@ -0,0 +1,87 b'' | |||||
|
1 | .TH IPCONTROLLER 1 "October 29, 2008" "" "" | |||
|
2 | .SH NAME | |||
|
3 | \fBipcontroller \- IPython parallel computing controller control tool | |||
|
4 | .SH SYNOPSIS | |||
|
5 | .nf | |||
|
6 | .fam C | |||
|
7 | \fBipengine\fP [\fIoptions\fP] | |||
|
8 | .fam T | |||
|
9 | .fi | |||
|
10 | .SH DESCRIPTION | |||
|
11 | ipcontroller is a control tool for IPython's parallel computing functions. | |||
|
12 | .SH OPTIONS | |||
|
13 | .TP | |||
|
14 | .B | |||
|
15 | \-h, \-\-help | |||
|
16 | show this help message and exit | |||
|
17 | .TP | |||
|
18 | .B | |||
|
19 | \-\-client\-ip=CLIENT_IP | |||
|
20 | the IP address or hostname the controller will listen on for | |||
|
21 | client connections | |||
|
22 | .TP | |||
|
23 | .B | |||
|
24 | \-\-client\-port=CLIENT_PORT | |||
|
25 | the port the controller will listen on for client connections | |||
|
26 | .TP | |||
|
27 | .B | |||
|
28 | \-\-client\-location=CLIENT_LOCATION | |||
|
29 | hostname or ip for clients to connect to | |||
|
30 | .TP | |||
|
31 | .B | |||
|
32 | \-x | |||
|
33 | turn off all client security | |||
|
34 | .TP | |||
|
35 | .B | |||
|
36 | \-\-client\-cert\-file=CLIENT_CERT_FILE | |||
|
37 | file to store the client SSL certificate | |||
|
38 | .TP | |||
|
39 | .B | |||
|
40 | \-\-task\-furl\-file=TASK_FURL_FILE | |||
|
41 | file to store the FURL for task clients to connect with | |||
|
42 | .TP | |||
|
43 | .B | |||
|
44 | \-\-multiengine\-furl\-file=MULTIENGINE_FURL_FILE | |||
|
45 | file to store the FURL for multiengine clients to connect with | |||
|
46 | .TP | |||
|
47 | .B | |||
|
48 | \-\-engine\-ip=ENGINE_IP | |||
|
49 | the IP address or hostname the controller will listen on for engine connections | |||
|
50 | .TP | |||
|
51 | .B | |||
|
52 | \-\-engine\-port=ENGINE_PORT | |||
|
53 | the port the controller will listen on for engine connections | |||
|
54 | .TP | |||
|
55 | .B | |||
|
56 | \-\-engine\-location=ENGINE_LOCATION | |||
|
57 | the IP address or hostname for engine to connect to | |||
|
58 | .TP | |||
|
59 | .B | |||
|
60 | \-y | |||
|
61 | turn off all engine security | |||
|
62 | .TP | |||
|
63 | .B | |||
|
64 | \-\-engine\-cert\-file=ENGINE_CERT_FILE | |||
|
65 | file to store the engine SSL certificate | |||
|
66 | .TP | |||
|
67 | .B | |||
|
68 | \-\-engine\-furl\-file=ENGINE_FURL_FILE | |||
|
69 | file to store the FURL for engines to connect with | |||
|
70 | .TP | |||
|
71 | .B | |||
|
72 | \-l LOGFILE, \-\-logfile=LOGFILE | |||
|
73 | log file name (default is stdout) | |||
|
74 | .TP | |||
|
75 | .B | |||
|
76 | \-r | |||
|
77 | try to reuse all furl files | |||
|
78 | .SH SEE ALSO | |||
|
79 | .BR ipython(1), ipcluster(1), ipengine(1) | |||
|
80 | .br | |||
|
81 | .SH AUTHOR | |||
|
82 | \fBipcontroller\fP is a tool that ships with IPython, created by | |||
|
83 | the IPython Development Team. | |||
|
84 | .PP | |||
|
85 | This manual page was written by Stephan Peijnik <debian@sp.or.at>, | |||
|
86 | for the Debian project (but may be used by others). Modified by Fernando Perez | |||
|
87 | <Fernando.Perez@berkeley.edu> for inclusion in IPython. |
@@ -0,0 +1,38 b'' | |||||
|
1 | .TH IPENGINE 1 "October 28, 2008" "" "" | |||
|
2 | .SH NAME | |||
|
3 | \fBipengine \- IPython parallel computing engine control tool | |||
|
4 | .SH SYNOPSIS | |||
|
5 | .nf | |||
|
6 | .fam C | |||
|
7 | \fBipengine\fP [\fIoptions\fP] | |||
|
8 | .fam T | |||
|
9 | .fi | |||
|
10 | .SH DESCRIPTION | |||
|
11 | ipengine is a control tool for IPython's parallel computing functions. | |||
|
12 | .SH OPTIONS | |||
|
13 | .TP | |||
|
14 | .B | |||
|
15 | \-h, \-\-help | |||
|
16 | show this help message and exit | |||
|
17 | .TP | |||
|
18 | .B | |||
|
19 | \-\-furl\-file=FURL_FILE | |||
|
20 | The filename containing the FURL of the controller | |||
|
21 | .TP | |||
|
22 | .B | |||
|
23 | \-\-mpi=MPI | |||
|
24 | How to enable MPI (mpi4py, pytrilions, or empty string to disable) | |||
|
25 | .TP | |||
|
26 | .B | |||
|
27 | \-l LOGFILE, \-\-logfile=LOGFILE | |||
|
28 | log file name (defaults to stdout) | |||
|
29 | .SH SEE ALSO | |||
|
30 | .BR ipython(1), ipcluster(1), ipcontroller(1) | |||
|
31 | .br | |||
|
32 | .SH AUTHOR | |||
|
33 | \fBipengine\fP is a tool that ships with IPython, created by | |||
|
34 | the IPython Development Team. | |||
|
35 | .PP | |||
|
36 | This manual page was written by Stephan Peijnik <debian@sp.or.at>, | |||
|
37 | for the Debian project (but may be used by others). Modified by Fernando Perez | |||
|
38 | <Fernando.Perez@berkeley.edu> for inclusion in IPython. |
@@ -0,0 +1,25 b'' | |||||
|
1 | .TH IPYTHON-WX 1 "October 29, 2008" "" "" | |||
|
2 | .SH NAME | |||
|
3 | \fBipython-wx \- Graphical frontend that embeds a multithreaded IPython Shell | |||
|
4 | .SH SYNOPSIS | |||
|
5 | .nf | |||
|
6 | .fam C | |||
|
7 | \fBipython-wx\fP | |||
|
8 | .fam T | |||
|
9 | .fi | |||
|
10 | .SH DESCRIPTION | |||
|
11 | ipython-wx is, compared to ipythonx, a more advanced graphical frontend | |||
|
12 | to IPython. It is implemented using WxWidgets. | |||
|
13 | .SH OPTIONS | |||
|
14 | .TP | |||
|
15 | .B | |||
|
16 | ipython-wx does not accept any command line options. | |||
|
17 | .SH SEE ALSO | |||
|
18 | .BR ipython(1), ipythonx(1) | |||
|
19 | .br | |||
|
20 | .SH AUTHOR | |||
|
21 | \fBipython-wx\fP is a tool that ships with IPython, created by | |||
|
22 | the IPython Development Team. | |||
|
23 | .PP | |||
|
24 | This manual page was written by Stephan Peijnik <debian@sp.or.at>, | |||
|
25 | for the Debian project (but may be used by others). |
@@ -0,0 +1,30 b'' | |||||
|
1 | .TH IPYTHONX 1 "October 29, 2008" "" "" | |||
|
2 | .SH NAME | |||
|
3 | \fBipythonx \- Simple graphical frontend to IPython, using WxWidgets. | |||
|
4 | .SH SYNOPSIS | |||
|
5 | .nf | |||
|
6 | .fam C | |||
|
7 | \fBipengine\fP [\fIoptions\fP] | |||
|
8 | .fam T | |||
|
9 | .fi | |||
|
10 | .SH DESCRIPTION | |||
|
11 | ipythonx is a simple graphical frontend to IPython, using WxWidgets. | |||
|
12 | .SH OPTIONS | |||
|
13 | .TP | |||
|
14 | .B | |||
|
15 | \-h, \-\-help | |||
|
16 | show this help message and exit | |||
|
17 | .TP | |||
|
18 | .B | |||
|
19 | \-d, \-\-debug | |||
|
20 | Enable debug messages for the wx frontend. | |||
|
21 | look for config files and profiles in this directory | |||
|
22 | .SH SEE ALSO | |||
|
23 | .BR ipython(1), ipython-wx(1) | |||
|
24 | .br | |||
|
25 | .SH AUTHOR | |||
|
26 | \fBipythonx\fP is a tool that ships with IPython, created by | |||
|
27 | the IPython Development Team. | |||
|
28 | .PP | |||
|
29 | This manual page was written by Stephan Peijnik <debian@sp.or.at>, | |||
|
30 | for the Debian project (but may be used by others). |
@@ -0,0 +1,49 b'' | |||||
|
1 | .TH IRUNNER 1 "April 24, 2007" "" "" | |||
|
2 | .SH NAME | |||
|
3 | \fBirunner \- interactive runner interface | |||
|
4 | .SH SYNOPSIS | |||
|
5 | .nf | |||
|
6 | .fam C | |||
|
7 | \fBirunner\fP [\fIoptions\fP] \fIfile_to_run\fP | |||
|
8 | .fam T | |||
|
9 | .fi | |||
|
10 | .SH DESCRIPTION | |||
|
11 | irunner is an interface to the various interactive runners | |||
|
12 | available in IPython's \fBirunner\fP module. | |||
|
13 | .PP | |||
|
14 | The already implemented runners are listed below; adding | |||
|
15 | one for a new program is a trivial task, see the source | |||
|
16 | for examples. | |||
|
17 | .SH OPTIONS | |||
|
18 | .TP | |||
|
19 | .B | |||
|
20 | \-h, \-\-help | |||
|
21 | show this help message and exit | |||
|
22 | .TP | |||
|
23 | .B | |||
|
24 | \-\-ipython | |||
|
25 | IPython interactive runner (default). | |||
|
26 | .TP | |||
|
27 | .B | |||
|
28 | \-\-python | |||
|
29 | Python interactive runner. | |||
|
30 | .TP | |||
|
31 | .B | |||
|
32 | \-\-sage | |||
|
33 | SAGE interactive runner. | |||
|
34 | .SH EXAMPLE | |||
|
35 | irunner.py \-\-python \-\- \-\-help | |||
|
36 | will pass \-\-help to the python runner. | |||
|
37 | Similarly, | |||
|
38 | irunner.py \-\-ipython \-\- \-\-interact script.ipy | |||
|
39 | .SH SEE ALSO | |||
|
40 | .BR ipython(1) | |||
|
41 | .br | |||
|
42 | .SH AUTHOR | |||
|
43 | \fBirunner\fP is an extension of Ken Schutte <kschutte-AT-csail.mit.edu>'s | |||
|
44 | script contributed on the ipython-user list: | |||
|
45 | http://scipy.net/pipermail/ipython-user/2006-May/001705.html | |||
|
46 | .PP | |||
|
47 | This manual page was written by Bernd Zeimetz <bernd@bzed.de>, for the Debian | |||
|
48 | project (but may be used by others). Modified by Fernando Perez | |||
|
49 | <Fernando.Perez@berkeley.edu> for inclusion in IPython. |
@@ -0,0 +1,42 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | """IPython release build script. | |||
|
3 | """ | |||
|
4 | from toollib import * | |||
|
5 | ||||
|
6 | # Get main ipython dir, this will raise if it doesn't pass some checks | |||
|
7 | ipdir = get_ipdir() | |||
|
8 | cd(ipdir) | |||
|
9 | ||||
|
10 | # Load release info | |||
|
11 | execfile(pjoin('IPython','core','release.py')) | |||
|
12 | ||||
|
13 | # Check that everything compiles | |||
|
14 | compile_tree() | |||
|
15 | ||||
|
16 | # Cleanup | |||
|
17 | for d in ['build','dist',pjoin('docs','build'),pjoin('docs','dist')]: | |||
|
18 | if os.path.isdir(d): | |||
|
19 | remove_tree(d) | |||
|
20 | ||||
|
21 | # Build source and binary distros | |||
|
22 | c('./setup.py sdist --formats=gztar') | |||
|
23 | ||||
|
24 | # Build version-specific RPMs, where we must use the --python option to ensure | |||
|
25 | # that the resulting RPM is really built with the requested python version (so | |||
|
26 | # things go to lib/python2.X/...) | |||
|
27 | c("python2.5 ./setup.py bdist_rpm --binary-only --release=py25 " | |||
|
28 | "--python=/usr/bin/python2.5") | |||
|
29 | c("python2.6 ./setup.py bdist_rpm --binary-only --release=py26 " | |||
|
30 | "--python=/usr/bin/python2.6") | |||
|
31 | ||||
|
32 | # Build eggs | |||
|
33 | c('python2.5 ./setupegg.py bdist_egg') | |||
|
34 | c('python2.6 ./setupegg.py bdist_egg') | |||
|
35 | ||||
|
36 | # Call the windows build separately, so that the extra Windows scripts don't | |||
|
37 | # get pulled into Unix builds (setup.py has code which checks for | |||
|
38 | # bdist_wininst) | |||
|
39 | c("python setup.py bdist_wininst --install-script=ipython_win_post_install.py") | |||
|
40 | ||||
|
41 | # Change name so retarded Vista runs the installer correctly | |||
|
42 | c("rename 's/linux-i686/win32-setup/' dist/*.exe") |
@@ -0,0 +1,55 b'' | |||||
|
1 | """Various utilities common to IPython release and maintenance tools. | |||
|
2 | """ | |||
|
3 | # Library imports | |||
|
4 | import os | |||
|
5 | import sys | |||
|
6 | ||||
|
7 | from distutils.dir_util import remove_tree | |||
|
8 | ||||
|
9 | # Useful shorthands | |||
|
10 | pjoin = os.path.join | |||
|
11 | cd = os.chdir | |||
|
12 | ||||
|
13 | # Utility functions | |||
|
14 | def c(cmd): | |||
|
15 | """Run system command, raise SystemExit if it returns an error.""" | |||
|
16 | print "$",cmd | |||
|
17 | stat = os.system(cmd) | |||
|
18 | #stat = 0 # Uncomment this and comment previous to run in debug mode | |||
|
19 | if stat: | |||
|
20 | raise SystemExit("Command %s failed with code: %s" % (cmd, stat)) | |||
|
21 | ||||
|
22 | ||||
|
23 | def get_ipdir(): | |||
|
24 | """Get IPython directory from command line, or assume it's the one above.""" | |||
|
25 | ||||
|
26 | # Initialize arguments and check location | |||
|
27 | try: | |||
|
28 | ipdir = sys.argv[1] | |||
|
29 | except IndexError: | |||
|
30 | ipdir = '..' | |||
|
31 | ||||
|
32 | ipdir = os.path.abspath(ipdir) | |||
|
33 | ||||
|
34 | cd(ipdir) | |||
|
35 | if not os.path.isdir('IPython') and os.path.isfile('setup.py'): | |||
|
36 | raise SystemExit('Invalid ipython directory: %s' % ipdir) | |||
|
37 | return ipdir | |||
|
38 | ||||
|
39 | ||||
|
40 | def compile_tree(): | |||
|
41 | """Compile all Python files below current directory.""" | |||
|
42 | vstr = '.'.join(map(str,sys.version_info[:2])) | |||
|
43 | stat = os.system('python %s/lib/python%s/compileall.py .' % | |||
|
44 | (sys.prefix,vstr)) | |||
|
45 | if stat: | |||
|
46 | msg = '*** ERROR: Some Python files in tree do NOT compile! ***\n' | |||
|
47 | msg += 'See messages above for the actual file that produced it.\n' | |||
|
48 | raise SystemExit(msg) | |||
|
49 | ||||
|
50 | ||||
|
51 | def version_info(): | |||
|
52 | """Return bzr version info as a dict.""" | |||
|
53 | out = os.popen('bzr version-info') | |||
|
54 | pairs = (l.split(':',1) for l in out) | |||
|
55 | return dict(((k,v.strip()) for (k,v) in pairs)) |
@@ -190,7 +190,7 b' class IPythonCrashHandler(CrashHandler):' | |||||
190 | def __init__(self,IP): |
|
190 | def __init__(self,IP): | |
191 |
|
191 | |||
192 | # Set here which of the IPython authors should be listed as contact |
|
192 | # Set here which of the IPython authors should be listed as contact | |
193 |
AUTHOR_CONTACT = ' |
|
193 | AUTHOR_CONTACT = 'Fernando' | |
194 |
|
194 | |||
195 | # Set argument defaults |
|
195 | # Set argument defaults | |
196 | app_name = 'IPython' |
|
196 | app_name = 'IPython' |
@@ -43,8 +43,9 b' somewhere in your configuration files or ipython command line.' | |||||
43 |
|
43 | |||
44 | from IPython.core import ipapi |
|
44 | from IPython.core import ipapi | |
45 |
|
45 | |||
46 | import os,bisect |
|
46 | import os, bisect | |
47 | from IPython.utils.genutils import Term,shell |
|
47 | import sys | |
|
48 | from IPython.utils.genutils import Term, shell | |||
48 | from pprint import PrettyPrinter |
|
49 | from pprint import PrettyPrinter | |
49 |
|
50 | |||
50 | # List here all the default hooks. For now it's just the editor functions |
|
51 | # List here all the default hooks. For now it's just the editor functions | |
@@ -53,7 +54,8 b' from pprint import PrettyPrinter' | |||||
53 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display', |
|
54 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display', | |
54 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', |
|
55 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', | |
55 | 'generate_prompt', 'generate_output_prompt','shell_hook', |
|
56 | 'generate_prompt', 'generate_output_prompt','shell_hook', | |
56 |
'show_in_pager','pre_prompt_hook', 'pre_runcode_hook' |
|
57 | 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook', | |
|
58 | 'clipboard_get'] | |||
57 | # vds: << |
|
59 | # vds: << | |
58 |
|
60 | |||
59 | pformat = PrettyPrinter().pformat |
|
61 | pformat = PrettyPrinter().pformat | |
@@ -109,7 +111,7 b' def fix_error_editor(self,filename,linenum,column,msg):' | |||||
109 |
|
111 | |||
110 | # vds: >> |
|
112 | # vds: >> | |
111 | def synchronize_with_editor(self, filename, linenum, column): |
|
113 | def synchronize_with_editor(self, filename, linenum, column): | |
112 | pass |
|
114 | pass | |
113 | # vds: << |
|
115 | # vds: << | |
114 |
|
116 | |||
115 | class CommandChainDispatcher: |
|
117 | class CommandChainDispatcher: | |
@@ -243,5 +245,22 b' def pre_prompt_hook(self):' | |||||
243 | def pre_runcode_hook(self): |
|
245 | def pre_runcode_hook(self): | |
244 | """ Executed before running the (prefiltered) code in IPython """ |
|
246 | """ Executed before running the (prefiltered) code in IPython """ | |
245 | return None |
|
247 | return None | |
246 |
|
||||
247 |
|
248 | |||
|
249 | def clipboard_get(self): | |||
|
250 | """ Get text from the clipboard. | |||
|
251 | """ | |||
|
252 | from IPython.lib.clipboard import ( | |||
|
253 | osx_clipboard_get, tkinter_clipboard_get, | |||
|
254 | win32_clipboard_get | |||
|
255 | ) | |||
|
256 | if sys.platform == 'win32': | |||
|
257 | chain = [win32_clipboard_get, tkinter_clipboard_get] | |||
|
258 | elif sys.platform == 'darwin': | |||
|
259 | chain = [osx_clipboard_get, tkinter_clipboard_get] | |||
|
260 | else: | |||
|
261 | chain = [tkinter_clipboard_get] | |||
|
262 | dispatcher = CommandChainDispatcher() | |||
|
263 | for func in chain: | |||
|
264 | dispatcher.add(func) | |||
|
265 | text = dispatcher() | |||
|
266 | return text |
@@ -927,8 +927,8 b' class InteractiveShell(object,Magic):' | |||||
927 | Certain history lists are also initialized here, as they effectively |
|
927 | Certain history lists are also initialized here, as they effectively | |
928 | act as user namespaces. |
|
928 | act as user namespaces. | |
929 |
|
929 | |||
930 | Note |
|
930 | Notes | |
931 | ---- |
|
931 | ----- | |
932 | All data structures here are only filled in, they are NOT reset by this |
|
932 | All data structures here are only filled in, they are NOT reset by this | |
933 | method. If they were not empty before, data will simply be added to |
|
933 | method. If they were not empty before, data will simply be added to | |
934 | therm. |
|
934 | therm. | |
@@ -1315,8 +1315,8 b' class InteractiveShell(object,Magic):' | |||||
1315 | def user_setup(self,ipythondir,rc_suffix,mode='install'): |
|
1315 | def user_setup(self,ipythondir,rc_suffix,mode='install'): | |
1316 | """Install the user configuration directory. |
|
1316 | """Install the user configuration directory. | |
1317 |
|
1317 | |||
1318 | Note |
|
1318 | Notes | |
1319 | ---- |
|
1319 | ----- | |
1320 | DEPRECATED: use the top-level user_setup() function instead. |
|
1320 | DEPRECATED: use the top-level user_setup() function instead. | |
1321 | """ |
|
1321 | """ | |
1322 | return user_setup(ipythondir,rc_suffix,mode) |
|
1322 | return user_setup(ipythondir,rc_suffix,mode) |
@@ -1707,7 +1707,12 b' Currently the magic system has the following functions:\\n"""' | |||||
1707 | # (leaving dangling references). |
|
1707 | # (leaving dangling references). | |
1708 | self.shell.cache_main_mod(prog_ns,filename) |
|
1708 | self.shell.cache_main_mod(prog_ns,filename) | |
1709 | # update IPython interactive namespace |
|
1709 | # update IPython interactive namespace | |
1710 | del prog_ns['__name__'] |
|
1710 | ||
|
1711 | # Some forms of read errors on the file may mean the | |||
|
1712 | # __name__ key was never set; using pop we don't have to | |||
|
1713 | # worry about a possible KeyError. | |||
|
1714 | prog_ns.pop('__name__', None) | |||
|
1715 | ||||
1711 | self.shell.user_ns.update(prog_ns) |
|
1716 | self.shell.user_ns.update(prog_ns) | |
1712 | finally: |
|
1717 | finally: | |
1713 | # It's a bit of a mystery why, but __builtins__ can change from |
|
1718 | # It's a bit of a mystery why, but __builtins__ can change from | |
@@ -3262,6 +3267,61 b' Defaulting color scheme to \'NoColor\'"""' | |||||
3262 | page(self.shell.pycolorize(cont), |
|
3267 | page(self.shell.pycolorize(cont), | |
3263 | screen_lines=self.shell.rc.screen_length) |
|
3268 | screen_lines=self.shell.rc.screen_length) | |
3264 |
|
3269 | |||
|
3270 | def _rerun_pasted(self): | |||
|
3271 | """ Rerun a previously pasted command. | |||
|
3272 | """ | |||
|
3273 | b = self.user_ns.get('pasted_block', None) | |||
|
3274 | if b is None: | |||
|
3275 | raise UsageError('No previous pasted block available') | |||
|
3276 | print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)) | |||
|
3277 | exec b in self.user_ns | |||
|
3278 | ||||
|
3279 | def _get_pasted_lines(self, sentinel): | |||
|
3280 | """ Yield pasted lines until the user enters the given sentinel value. | |||
|
3281 | """ | |||
|
3282 | from IPython.core import iplib | |||
|
3283 | print "Pasting code; enter '%s' alone on the line to stop." % sentinel | |||
|
3284 | while True: | |||
|
3285 | l = iplib.raw_input_original(':') | |||
|
3286 | if l == sentinel: | |||
|
3287 | return | |||
|
3288 | else: | |||
|
3289 | yield l | |||
|
3290 | ||||
|
3291 | def _strip_pasted_lines_for_code(self, raw_lines): | |||
|
3292 | """ Strip non-code parts of a sequence of lines to return a block of | |||
|
3293 | code. | |||
|
3294 | """ | |||
|
3295 | # Regular expressions that declare text we strip from the input: | |||
|
3296 | strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt | |||
|
3297 | r'^\s*(\s?>)+', # Python input prompt | |||
|
3298 | r'^\s*\.{3,}', # Continuation prompts | |||
|
3299 | r'^\++', | |||
|
3300 | ] | |||
|
3301 | ||||
|
3302 | strip_from_start = map(re.compile,strip_re) | |||
|
3303 | ||||
|
3304 | lines = [] | |||
|
3305 | for l in raw_lines: | |||
|
3306 | for pat in strip_from_start: | |||
|
3307 | l = pat.sub('',l) | |||
|
3308 | lines.append(l) | |||
|
3309 | ||||
|
3310 | block = "\n".join(lines) + '\n' | |||
|
3311 | #print "block:\n",block | |||
|
3312 | return block | |||
|
3313 | ||||
|
3314 | def _execute_block(self, block, par): | |||
|
3315 | """ Execute a block, or store it in a variable, per the user's request. | |||
|
3316 | """ | |||
|
3317 | if not par: | |||
|
3318 | b = textwrap.dedent(block) | |||
|
3319 | self.user_ns['pasted_block'] = b | |||
|
3320 | exec b in self.user_ns | |||
|
3321 | else: | |||
|
3322 | self.user_ns[par] = SList(block.splitlines()) | |||
|
3323 | print "Block assigned to '%s'" % par | |||
|
3324 | ||||
3265 | def magic_cpaste(self, parameter_s=''): |
|
3325 | def magic_cpaste(self, parameter_s=''): | |
3266 | """Allows you to paste & execute a pre-formatted code block from clipboard. |
|
3326 | """Allows you to paste & execute a pre-formatted code block from clipboard. | |
3267 |
|
3327 | |||
@@ -3287,50 +3347,60 b' Defaulting color scheme to \'NoColor\'"""' | |||||
3287 | will be what was just pasted. |
|
3347 | will be what was just pasted. | |
3288 |
|
3348 | |||
3289 | IPython statements (magics, shell escapes) are not supported (yet). |
|
3349 | IPython statements (magics, shell escapes) are not supported (yet). | |
|
3350 | ||||
|
3351 | See also | |||
|
3352 | -------- | |||
|
3353 | paste: automatically pull code from clipboard. | |||
3290 | """ |
|
3354 | """ | |
|
3355 | ||||
3291 | opts,args = self.parse_options(parameter_s,'rs:',mode='string') |
|
3356 | opts,args = self.parse_options(parameter_s,'rs:',mode='string') | |
3292 | par = args.strip() |
|
3357 | par = args.strip() | |
3293 | if opts.has_key('r'): |
|
3358 | if opts.has_key('r'): | |
3294 |
|
|
3359 | self._rerun_pasted() | |
3295 | if b is None: |
|
|||
3296 | raise UsageError('No previous pasted block available') |
|
|||
3297 | print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)) |
|
|||
3298 | exec b in self.user_ns |
|
|||
3299 | return |
|
3360 | return | |
3300 |
|
3361 | |||
3301 | sentinel = opts.get('s','--') |
|
3362 | sentinel = opts.get('s','--') | |
3302 |
|
3363 | |||
3303 | # Regular expressions that declare text we strip from the input: |
|
3364 | block = self._strip_pasted_lines_for_code( | |
3304 | strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt |
|
3365 | self._get_pasted_lines(sentinel)) | |
3305 | r'^\s*(\s?>)+', # Python input prompt |
|
|||
3306 | r'^\s*\.{3,}', # Continuation prompts |
|
|||
3307 | r'^\++', |
|
|||
3308 | ] |
|
|||
3309 |
|
3366 | |||
3310 | strip_from_start = map(re.compile,strip_re) |
|
3367 | self._execute_block(block, par) | |
|
3368 | ||||
|
3369 | def magic_paste(self, parameter_s=''): | |||
|
3370 | """Allows you to paste & execute a pre-formatted code block from clipboard. | |||
3311 |
|
|
3371 | ||
3312 | from IPython.core import iplib |
|
3372 | The text is pulled directly from the clipboard without user | |
3313 | lines = [] |
|
3373 | intervention. | |
3314 | print "Pasting code; enter '%s' alone on the line to stop." % sentinel |
|
3374 | ||
3315 | while 1: |
|
3375 | The block is dedented prior to execution to enable execution of method | |
3316 | l = iplib.raw_input_original(':') |
|
3376 | definitions. '>' and '+' characters at the beginning of a line are | |
3317 | if l ==sentinel: |
|
3377 | ignored, to allow pasting directly from e-mails, diff files and | |
3318 | break |
|
3378 | doctests (the '...' continuation prompt is also stripped). The | |
3319 |
|
3379 | executed block is also assigned to variable named 'pasted_block' for | ||
3320 | for pat in strip_from_start: |
|
3380 | later editing with '%edit pasted_block'. | |
3321 | l = pat.sub('',l) |
|
3381 | ||
3322 | lines.append(l) |
|
3382 | You can also pass a variable name as an argument, e.g. '%paste foo'. | |
3323 |
|
3383 | This assigns the pasted block to variable 'foo' as string, without | ||
3324 | block = "\n".join(lines) + '\n' |
|
3384 | dedenting or executing it (preceding >>> and + is still stripped) | |
3325 | #print "block:\n",block |
|
3385 | ||
3326 | if not par: |
|
3386 | '%paste -r' re-executes the block previously entered by cpaste. | |
3327 | b = textwrap.dedent(block) |
|
3387 | ||
3328 | self.user_ns['pasted_block'] = b |
|
3388 | IPython statements (magics, shell escapes) are not supported (yet). | |
3329 | exec b in self.user_ns |
|
3389 | ||
3330 |
|
|
3390 | See also | |
3331 | self.user_ns[par] = SList(block.splitlines()) |
|
3391 | -------- | |
3332 | print "Block assigned to '%s'" % par |
|
3392 | cpaste: manually paste code into terminal until you mark its end. | |
3333 |
|
|
3393 | """ | |
|
3394 | opts,args = self.parse_options(parameter_s,'r:',mode='string') | |||
|
3395 | par = args.strip() | |||
|
3396 | if opts.has_key('r'): | |||
|
3397 | self._rerun_pasted() | |||
|
3398 | return | |||
|
3399 | ||||
|
3400 | text = self.shell.hooks.clipboard_get() | |||
|
3401 | block = self._strip_pasted_lines_for_code(text.splitlines()) | |||
|
3402 | self._execute_block(block, par) | |||
|
3403 | ||||
3334 | def magic_quickref(self,arg): |
|
3404 | def magic_quickref(self,arg): | |
3335 | """ Show a quick reference sheet """ |
|
3405 | """ Show a quick reference sheet """ | |
3336 | import IPython.core.usage |
|
3406 | import IPython.core.usage |
@@ -2,8 +2,8 b'' | |||||
2 | """Release data for the IPython project.""" |
|
2 | """Release data for the IPython project.""" | |
3 |
|
3 | |||
4 | #***************************************************************************** |
|
4 | #***************************************************************************** | |
5 | # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu> |
|
5 | # Copyright (C) 2008-2009 The IPython Development Team | |
6 | # |
|
6 | # Copyright (C) 2001-2008 Fernando Perez <fperez@colorado.edu> | |
7 | # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray |
|
7 | # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray | |
8 | # <n8gray@caltech.edu> |
|
8 | # <n8gray@caltech.edu> | |
9 | # |
|
9 | # | |
@@ -20,10 +20,10 b" name = 'ipython'" | |||||
20 | # because bdist_rpm does not accept dashes (an RPM) convention, and |
|
20 | # because bdist_rpm does not accept dashes (an RPM) convention, and | |
21 | # bdist_deb does not accept underscores (a Debian convention). |
|
21 | # bdist_deb does not accept underscores (a Debian convention). | |
22 |
|
22 | |||
23 |
development = |
|
23 | development = False # change this to False to do a release | |
24 | version_base = '0.10' |
|
24 | version_base = '0.10' | |
25 | branch = 'ipython' |
|
25 | branch = 'ipython' | |
26 |
revision = '11 |
|
26 | revision = '1188' | |
27 |
|
27 | |||
28 | if development: |
|
28 | if development: | |
29 | if branch == 'ipython': |
|
29 | if branch == 'ipython': | |
@@ -100,7 +100,7 b' site <http://launchpad.net/ipython>`_.' | |||||
100 |
|
100 | |||
101 | license = 'BSD' |
|
101 | license = 'BSD' | |
102 |
|
102 | |||
103 |
authors = {'Fernando' : ('Fernando Perez','fperez |
|
103 | authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'), | |
104 | 'Janko' : ('Janko Hauser','jhauser@zscout.de'), |
|
104 | 'Janko' : ('Janko Hauser','jhauser@zscout.de'), | |
105 | 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'), |
|
105 | 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'), | |
106 | 'Ville' : ('Ville Vainio','vivainio@gmail.com'), |
|
106 | 'Ville' : ('Ville Vainio','vivainio@gmail.com'), |
@@ -25,14 +25,14 b' def test_rehashx():' | |||||
25 | _ip.magic('rehashx') |
|
25 | _ip.magic('rehashx') | |
26 | # Practically ALL ipython development systems will have more than 10 aliases |
|
26 | # Practically ALL ipython development systems will have more than 10 aliases | |
27 |
|
27 | |||
28 | assert len(_ip.IP.alias_table) > 10 |
|
28 | yield (nt.assert_true, len(_ip.IP.alias_table) > 10) | |
29 | for key, val in _ip.IP.alias_table.items(): |
|
29 | for key, val in _ip.IP.alias_table.items(): | |
30 | # we must strip dots from alias names |
|
30 | # we must strip dots from alias names | |
31 |
assert |
|
31 | nt.assert_true('.' not in key) | |
32 |
|
32 | |||
33 | # rehashx must fill up syscmdlist |
|
33 | # rehashx must fill up syscmdlist | |
34 | scoms = _ip.db['syscmdlist'] |
|
34 | scoms = _ip.db['syscmdlist'] | |
35 | assert len(scoms) > 10 |
|
35 | yield (nt.assert_true, len(scoms) > 10) | |
36 |
|
36 | |||
37 |
|
37 | |||
38 | def doctest_hist_f(): |
|
38 | def doctest_hist_f(): | |
@@ -42,7 +42,7 b' def doctest_hist_f():' | |||||
42 |
|
42 | |||
43 | In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-') |
|
43 | In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-') | |
44 |
|
44 | |||
45 |
In [11]: %hist |
|
45 | In [11]: %hist -n -f $tfile 3 | |
46 | """ |
|
46 | """ | |
47 |
|
47 | |||
48 |
|
48 | |||
@@ -51,9 +51,12 b' def doctest_hist_r():' | |||||
51 |
|
51 | |||
52 | XXX - This test is not recording the output correctly. Not sure why... |
|
52 | XXX - This test is not recording the output correctly. Not sure why... | |
53 |
|
53 | |||
|
54 | In [20]: 'hist' in _ip.IP.lsmagic() | |||
|
55 | Out[20]: True | |||
|
56 | ||||
54 | In [6]: x=1 |
|
57 | In [6]: x=1 | |
55 |
|
58 | |||
56 | In [7]: hist -n -r 2 |
|
59 | In [7]: %hist -n -r 2 | |
57 | x=1 # random |
|
60 | x=1 # random | |
58 | hist -n -r 2 # random |
|
61 | hist -n -r 2 # random | |
59 | """ |
|
62 | """ | |
@@ -94,12 +97,13 b' def test_shist():' | |||||
94 |
|
97 | |||
95 | @dec.skipif_not_numpy |
|
98 | @dec.skipif_not_numpy | |
96 | def test_numpy_clear_array_undec(): |
|
99 | def test_numpy_clear_array_undec(): | |
|
100 | from IPython.extensions import clearcmd | |||
|
101 | ||||
97 | _ip.ex('import numpy as np') |
|
102 | _ip.ex('import numpy as np') | |
98 | _ip.ex('a = np.empty(2)') |
|
103 | _ip.ex('a = np.empty(2)') | |
99 |
|
104 | yield (nt.assert_true, 'a' in _ip.user_ns) | ||
100 | yield nt.assert_true,'a' in _ip.user_ns |
|
|||
101 | _ip.magic('clear array') |
|
105 | _ip.magic('clear array') | |
102 | yield nt.assert_false,'a' in _ip.user_ns |
|
106 | yield (nt.assert_false, 'a' in _ip.user_ns) | |
103 |
|
107 | |||
104 |
|
108 | |||
105 | @dec.skip() |
|
109 | @dec.skip() | |
@@ -159,7 +163,6 b' def doctest_run_ns2():' | |||||
159 | tclass.py: deleting object: C-first_pass |
|
163 | tclass.py: deleting object: C-first_pass | |
160 | """ |
|
164 | """ | |
161 |
|
165 | |||
162 | @dec.skip_win32 |
|
|||
163 | def doctest_run_builtins(): |
|
166 | def doctest_run_builtins(): | |
164 | """Check that %run doesn't damage __builtins__ via a doctest. |
|
167 | """Check that %run doesn't damage __builtins__ via a doctest. | |
165 |
|
168 | |||
@@ -172,24 +175,34 b' def doctest_run_builtins():' | |||||
172 |
|
175 | |||
173 | In [2]: bid1 = id(__builtins__) |
|
176 | In [2]: bid1 = id(__builtins__) | |
174 |
|
177 | |||
175 |
In [3]: f = tempfile. |
|
178 | In [3]: fname = tempfile.mkstemp()[1] | |
|
179 | ||||
|
180 | In [3]: f = open(fname,'w') | |||
176 |
|
181 | |||
177 | In [4]: f.write('pass\\n') |
|
182 | In [4]: f.write('pass\\n') | |
178 |
|
183 | |||
179 | In [5]: f.flush() |
|
184 | In [5]: f.flush() | |
180 |
|
185 | |||
181 |
In [6]: print |
|
186 | In [6]: print type(__builtins__) | |
182 |
|
|
187 | <type 'module'> | |
183 |
|
188 | |||
184 |
In [7]: %run $f |
|
189 | In [7]: %run "$fname" | |
|
190 | ||||
|
191 | In [7]: f.close() | |||
185 |
|
192 | |||
186 | In [8]: bid2 = id(__builtins__) |
|
193 | In [8]: bid2 = id(__builtins__) | |
187 |
|
194 | |||
188 |
In [9]: print |
|
195 | In [9]: print type(__builtins__) | |
189 |
|
|
196 | <type 'module'> | |
190 |
|
197 | |||
191 | In [10]: bid1 == bid2 |
|
198 | In [10]: bid1 == bid2 | |
192 | Out[10]: True |
|
199 | Out[10]: True | |
|
200 | ||||
|
201 | In [12]: try: | |||
|
202 | ....: os.unlink(fname) | |||
|
203 | ....: except: | |||
|
204 | ....: pass | |||
|
205 | ....: | |||
193 | """ |
|
206 | """ | |
194 |
|
207 | |||
195 | # For some tests, it will be handy to organize them in a class with a common |
|
208 | # For some tests, it will be handy to organize them in a class with a common | |
@@ -199,23 +212,18 b' class TestMagicRun(object):' | |||||
199 |
|
212 | |||
200 | def setup(self): |
|
213 | def setup(self): | |
201 | """Make a valid python temp file.""" |
|
214 | """Make a valid python temp file.""" | |
202 |
f = tempfile. |
|
215 | fname = tempfile.mkstemp()[1] | |
|
216 | f = open(fname,'w') | |||
203 | f.write('pass\n') |
|
217 | f.write('pass\n') | |
204 | f.flush() |
|
218 | f.flush() | |
205 | self.tmpfile = f |
|
219 | self.tmpfile = f | |
|
220 | self.fname = fname | |||
206 |
|
221 | |||
207 | def run_tmpfile(self): |
|
222 | def run_tmpfile(self): | |
208 | # This fails on Windows if self.tmpfile.name has spaces or "~" in it. |
|
223 | # This fails on Windows if self.tmpfile.name has spaces or "~" in it. | |
209 | # See below and ticket https://bugs.launchpad.net/bugs/366353 |
|
224 | # See below and ticket https://bugs.launchpad.net/bugs/366353 | |
210 |
_ip.magic('run %s' % self. |
|
225 | _ip.magic('run "%s"' % self.fname) | |
211 |
|
||||
212 | # See https://bugs.launchpad.net/bugs/366353 |
|
|||
213 | @dec.skip_if_not_win32 |
|
|||
214 | def test_run_tempfile_path(self): |
|
|||
215 | tt.assert_equals(True,False,"%run doesn't work with tempfile paths on win32.") |
|
|||
216 |
|
226 | |||
217 | # See https://bugs.launchpad.net/bugs/366353 |
|
|||
218 | @dec.skip_win32 |
|
|||
219 | def test_builtins_id(self): |
|
227 | def test_builtins_id(self): | |
220 | """Check that %run doesn't damage __builtins__ """ |
|
228 | """Check that %run doesn't damage __builtins__ """ | |
221 |
|
229 | |||
@@ -225,8 +233,6 b' class TestMagicRun(object):' | |||||
225 | bid2 = id(_ip.user_ns['__builtins__']) |
|
233 | bid2 = id(_ip.user_ns['__builtins__']) | |
226 | tt.assert_equals(bid1, bid2) |
|
234 | tt.assert_equals(bid1, bid2) | |
227 |
|
235 | |||
228 | # See https://bugs.launchpad.net/bugs/366353 |
|
|||
229 | @dec.skip_win32 |
|
|||
230 | def test_builtins_type(self): |
|
236 | def test_builtins_type(self): | |
231 | """Check that the type of __builtins__ doesn't change with %run. |
|
237 | """Check that the type of __builtins__ doesn't change with %run. | |
232 |
|
238 | |||
@@ -237,8 +243,6 b' class TestMagicRun(object):' | |||||
237 | self.run_tmpfile() |
|
243 | self.run_tmpfile() | |
238 | tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys)) |
|
244 | tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys)) | |
239 |
|
245 | |||
240 | # See https://bugs.launchpad.net/bugs/366353 |
|
|||
241 | @dec.skip_win32 |
|
|||
242 | def test_prompts(self): |
|
246 | def test_prompts(self): | |
243 | """Test that prompts correctly generate after %run""" |
|
247 | """Test that prompts correctly generate after %run""" | |
244 | self.run_tmpfile() |
|
248 | self.run_tmpfile() | |
@@ -247,3 +251,52 b' class TestMagicRun(object):' | |||||
247 |
|
251 | |||
248 | def teardown(self): |
|
252 | def teardown(self): | |
249 | self.tmpfile.close() |
|
253 | self.tmpfile.close() | |
|
254 | try: | |||
|
255 | os.unlink(self.fname) | |||
|
256 | except: | |||
|
257 | # On Windows, even though we close the file, we still can't delete | |||
|
258 | # it. I have no clue why | |||
|
259 | pass | |||
|
260 | ||||
|
261 | # Multiple tests for clipboard pasting | |||
|
262 | def test_paste(): | |||
|
263 | ||||
|
264 | def paste(txt): | |||
|
265 | hooks.clipboard_get = lambda : txt | |||
|
266 | _ip.magic('paste') | |||
|
267 | ||||
|
268 | # Inject fake clipboard hook but save original so we can restore it later | |||
|
269 | hooks = _ip.IP.hooks | |||
|
270 | user_ns = _ip.user_ns | |||
|
271 | original_clip = hooks.clipboard_get | |||
|
272 | ||||
|
273 | try: | |||
|
274 | # This try/except with an emtpy except clause is here only because | |||
|
275 | # try/yield/finally is invalid syntax in Python 2.4. This will be | |||
|
276 | # removed when we drop 2.4-compatibility, and the emtpy except below | |||
|
277 | # will be changed to a finally. | |||
|
278 | ||||
|
279 | # Run tests with fake clipboard function | |||
|
280 | user_ns.pop('x', None) | |||
|
281 | paste('x=1') | |||
|
282 | yield (nt.assert_equal, user_ns['x'], 1) | |||
|
283 | ||||
|
284 | user_ns.pop('x', None) | |||
|
285 | paste('>>> x=2') | |||
|
286 | yield (nt.assert_equal, user_ns['x'], 2) | |||
|
287 | ||||
|
288 | paste(""" | |||
|
289 | >>> x = [1,2,3] | |||
|
290 | >>> y = [] | |||
|
291 | >>> for i in x: | |||
|
292 | ... y.append(i**2) | |||
|
293 | ... | |||
|
294 | """) | |||
|
295 | yield (nt.assert_equal, user_ns['x'], [1,2,3]) | |||
|
296 | yield (nt.assert_equal, user_ns['y'], [1,4,9]) | |||
|
297 | except: | |||
|
298 | pass | |||
|
299 | ||||
|
300 | # This should be in a finally clause, instead of the bare except above. | |||
|
301 | # Restore original hook | |||
|
302 | hooks.clipboard_get = original_clip |
@@ -91,7 +91,7 b' from inspect import getsourcefile, getfile, getmodule,\\' | |||||
91 | # IPython's own modules |
|
91 | # IPython's own modules | |
92 | # Modified pdb which doesn't damage IPython's readline handling |
|
92 | # Modified pdb which doesn't damage IPython's readline handling | |
93 | from IPython.utils import PyColorize |
|
93 | from IPython.utils import PyColorize | |
94 | from IPython.core import debugger |
|
94 | from IPython.core import debugger, ipapi | |
95 | from IPython.utils.ipstruct import Struct |
|
95 | from IPython.utils.ipstruct import Struct | |
96 | from IPython.core.excolors import exception_colors |
|
96 | from IPython.core.excolors import exception_colors | |
97 | from IPython.utils.genutils import Term,uniq_stable,error,info |
|
97 | from IPython.utils.genutils import Term,uniq_stable,error,info | |
@@ -268,10 +268,12 b' def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):' | |||||
268 |
|
268 | |||
269 | # This lets us get fully syntax-highlighted tracebacks. |
|
269 | # This lets us get fully syntax-highlighted tracebacks. | |
270 | if scheme is None: |
|
270 | if scheme is None: | |
271 | try: |
|
271 | ipinst = ipapi.get() | |
272 | scheme = __IPYTHON__.rc.colors |
|
272 | if ipinst is not None: | |
273 | except: |
|
273 | scheme = ipinst.IP.rc.colors | |
|
274 | else: | |||
274 | scheme = DEFAULT_SCHEME |
|
275 | scheme = DEFAULT_SCHEME | |
|
276 | ||||
275 | _line_format = _parser.format2 |
|
277 | _line_format = _parser.format2 | |
276 |
|
278 | |||
277 | for line in lines: |
|
279 | for line in lines: | |
@@ -490,7 +492,9 b' class ListTB(TBTools):' | |||||
490 |
|
492 | |||
491 | # vds:>> |
|
493 | # vds:>> | |
492 | if have_filedata: |
|
494 | if have_filedata: | |
493 | __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0) |
|
495 | ipinst = ipapi.get() | |
|
496 | if ipinst is not None: | |||
|
497 | ipinst.IP.hooks.synchronize_with_editor(filename, lineno, 0) | |||
494 | # vds:<< |
|
498 | # vds:<< | |
495 |
|
499 | |||
496 | return list |
|
500 | return list | |
@@ -810,7 +814,9 b' class VerboseTB(TBTools):' | |||||
810 | filepath, lnum = records[-1][1:3] |
|
814 | filepath, lnum = records[-1][1:3] | |
811 | #print "file:", str(file), "linenb", str(lnum) # dbg |
|
815 | #print "file:", str(file), "linenb", str(lnum) # dbg | |
812 | filepath = os.path.abspath(filepath) |
|
816 | filepath = os.path.abspath(filepath) | |
813 | __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0) |
|
817 | ipinst = ipapi.get() | |
|
818 | if ipinst is not None: | |||
|
819 | ipinst.IP.hooks.synchronize_with_editor(filepath, lnum, 0) | |||
814 | # vds: << |
|
820 | # vds: << | |
815 |
|
821 | |||
816 | # return all our info assembled as a single string |
|
822 | # return all our info assembled as a single string |
@@ -2,6 +2,9 b'' | |||||
2 |
|
2 | |||
3 | XXX - This module is missing proper docs. |
|
3 | XXX - This module is missing proper docs. | |
4 | """ |
|
4 | """ | |
|
5 | # Tell nose to skip this module | |||
|
6 | __test__ = {} | |||
|
7 | ||||
5 | import sys |
|
8 | import sys | |
6 |
|
9 | |||
7 | from twisted.internet import reactor, threads |
|
10 | from twisted.internet import reactor, threads |
@@ -1,7 +1,7 b'' | |||||
1 | """ |
|
1 | """ | |
2 | IPython extension: autoreload modules before executing the next line |
|
2 | IPython extension: autoreload modules before executing the next line | |
3 |
|
3 | |||
4 |
Try:: |
|
4 | Try:: | |
5 |
|
5 | |||
6 | %autoreload? |
|
6 | %autoreload? | |
7 |
|
7 | |||
@@ -32,7 +32,7 b' PY_COMPILED_EXT = _get_compiled_ext()' | |||||
32 | class ModuleReloader(object): |
|
32 | class ModuleReloader(object): | |
33 | failed = {} |
|
33 | failed = {} | |
34 | """Modules that failed to reload: {module: mtime-on-failed-reload, ...}""" |
|
34 | """Modules that failed to reload: {module: mtime-on-failed-reload, ...}""" | |
35 |
|
35 | |||
36 | modules = {} |
|
36 | modules = {} | |
37 | """Modules specially marked as autoreloadable.""" |
|
37 | """Modules specially marked as autoreloadable.""" | |
38 |
|
38 | |||
@@ -44,39 +44,39 b' class ModuleReloader(object):' | |||||
44 |
|
44 | |||
45 | old_objects = {} |
|
45 | old_objects = {} | |
46 | """(module-name, name) -> weakref, for replacing old code objects""" |
|
46 | """(module-name, name) -> weakref, for replacing old code objects""" | |
47 |
|
47 | |||
48 | def check(self, check_all=False): |
|
48 | def check(self, check_all=False): | |
49 | """Check whether some modules need to be reloaded.""" |
|
49 | """Check whether some modules need to be reloaded.""" | |
50 |
|
50 | |||
51 | if check_all or self.check_all: |
|
51 | if check_all or self.check_all: | |
52 | modules = sys.modules.keys() |
|
52 | modules = sys.modules.keys() | |
53 | else: |
|
53 | else: | |
54 | modules = self.modules.keys() |
|
54 | modules = self.modules.keys() | |
55 |
|
55 | |||
56 | for modname in modules: |
|
56 | for modname in modules: | |
57 | m = sys.modules.get(modname, None) |
|
57 | m = sys.modules.get(modname, None) | |
58 |
|
58 | |||
59 | if modname in self.skip_modules: |
|
59 | if modname in self.skip_modules: | |
60 | continue |
|
60 | continue | |
61 |
|
61 | |||
62 | if not hasattr(m, '__file__'): |
|
62 | if not hasattr(m, '__file__'): | |
63 | continue |
|
63 | continue | |
64 |
|
64 | |||
65 | if m.__name__ == '__main__': |
|
65 | if m.__name__ == '__main__': | |
66 | # we cannot reload(__main__) |
|
66 | # we cannot reload(__main__) | |
67 | continue |
|
67 | continue | |
68 |
|
68 | |||
69 | filename = m.__file__ |
|
69 | filename = m.__file__ | |
70 | dirname = os.path.dirname(filename) |
|
70 | dirname = os.path.dirname(filename) | |
71 | path, ext = os.path.splitext(filename) |
|
71 | path, ext = os.path.splitext(filename) | |
72 |
|
72 | |||
73 | if ext.lower() == '.py': |
|
73 | if ext.lower() == '.py': | |
74 | ext = PY_COMPILED_EXT |
|
74 | ext = PY_COMPILED_EXT | |
75 | filename = os.path.join(dirname, path + PY_COMPILED_EXT) |
|
75 | filename = os.path.join(dirname, path + PY_COMPILED_EXT) | |
76 |
|
76 | |||
77 | if ext != PY_COMPILED_EXT: |
|
77 | if ext != PY_COMPILED_EXT: | |
78 | continue |
|
78 | continue | |
79 |
|
79 | |||
80 | try: |
|
80 | try: | |
81 | pymtime = os.stat(filename[:-1]).st_mtime |
|
81 | pymtime = os.stat(filename[:-1]).st_mtime | |
82 | if pymtime <= os.stat(filename).st_mtime: |
|
82 | if pymtime <= os.stat(filename).st_mtime: | |
@@ -85,7 +85,7 b' class ModuleReloader(object):' | |||||
85 | continue |
|
85 | continue | |
86 | except OSError: |
|
86 | except OSError: | |
87 | continue |
|
87 | continue | |
88 |
|
88 | |||
89 | try: |
|
89 | try: | |
90 | superreload(m, reload, self.old_objects) |
|
90 | superreload(m, reload, self.old_objects) | |
91 | if filename[:-1] in self.failed: |
|
91 | if filename[:-1] in self.failed: | |
@@ -118,12 +118,12 b' def update_class(old, new):' | |||||
118 | new_obj = getattr(new, key) |
|
118 | new_obj = getattr(new, key) | |
119 | except AttributeError: |
|
119 | except AttributeError: | |
120 | # obsolete attribute: remove it |
|
120 | # obsolete attribute: remove it | |
121 |
try: |
|
121 | try: | |
122 | delattr(old, key) |
|
122 | delattr(old, key) | |
123 | except (AttributeError, TypeError): |
|
123 | except (AttributeError, TypeError): | |
124 | pass |
|
124 | pass | |
125 | continue |
|
125 | continue | |
126 |
|
126 | |||
127 | if update_generic(old_obj, new_obj): continue |
|
127 | if update_generic(old_obj, new_obj): continue | |
128 |
|
128 | |||
129 | try: |
|
129 | try: | |
@@ -146,9 +146,9 b' UPDATE_RULES = [' | |||||
146 | (lambda a, b: isinstance2(a, b, types.TypeType), |
|
146 | (lambda a, b: isinstance2(a, b, types.TypeType), | |
147 | update_class), |
|
147 | update_class), | |
148 | (lambda a, b: isinstance2(a, b, types.FunctionType), |
|
148 | (lambda a, b: isinstance2(a, b, types.FunctionType), | |
149 |
update_function), |
|
149 | update_function), | |
150 | (lambda a, b: isinstance2(a, b, property), |
|
150 | (lambda a, b: isinstance2(a, b, property), | |
151 |
update_property), |
|
151 | update_property), | |
152 | (lambda a, b: isinstance2(a, b, types.MethodType), |
|
152 | (lambda a, b: isinstance2(a, b, types.MethodType), | |
153 | lambda a, b: update_function(a.im_func, b.im_func)), |
|
153 | lambda a, b: update_function(a.im_func, b.im_func)), | |
154 | ] |
|
154 | ] | |
@@ -168,15 +168,15 b' class StrongRef(object):' | |||||
168 |
|
168 | |||
169 | def superreload(module, reload=reload, old_objects={}): |
|
169 | def superreload(module, reload=reload, old_objects={}): | |
170 | """Enhanced version of the builtin reload function. |
|
170 | """Enhanced version of the builtin reload function. | |
171 |
|
171 | |||
172 | superreload remembers objects previously in the module, and |
|
172 | superreload remembers objects previously in the module, and | |
173 |
|
173 | |||
174 | - upgrades the class dictionary of every old class in the module |
|
174 | - upgrades the class dictionary of every old class in the module | |
175 | - upgrades the code object of every old function and method |
|
175 | - upgrades the code object of every old function and method | |
176 | - clears the module's namespace before reloading |
|
176 | - clears the module's namespace before reloading | |
177 |
|
177 | |||
178 | """ |
|
178 | """ | |
179 |
|
179 | |||
180 | # collect old objects in the module |
|
180 | # collect old objects in the module | |
181 | for name, obj in module.__dict__.items(): |
|
181 | for name, obj in module.__dict__.items(): | |
182 | if not hasattr(obj, '__module__') or obj.__module__ != module.__name__: |
|
182 | if not hasattr(obj, '__module__') or obj.__module__ != module.__name__: | |
@@ -199,7 +199,7 b' def superreload(module, reload=reload, old_objects={}):' | |||||
199 | except (TypeError, AttributeError, KeyError): |
|
199 | except (TypeError, AttributeError, KeyError): | |
200 | pass |
|
200 | pass | |
201 | module = reload(module) |
|
201 | module = reload(module) | |
202 |
|
202 | |||
203 | # iterate over all objects and update functions & classes |
|
203 | # iterate over all objects and update functions & classes | |
204 | for name, new_obj in module.__dict__.items(): |
|
204 | for name, new_obj in module.__dict__.items(): | |
205 | key = (module.__name__, name) |
|
205 | key = (module.__name__, name) | |
@@ -248,40 +248,46 b' def disable_autoreload():' | |||||
248 |
|
248 | |||
249 | def autoreload_f(self, parameter_s=''): |
|
249 | def autoreload_f(self, parameter_s=''): | |
250 | r""" %autoreload => Reload modules automatically |
|
250 | r""" %autoreload => Reload modules automatically | |
251 |
|
251 | |||
252 | %autoreload |
|
252 | %autoreload | |
253 | Reload all modules (except those excluded by %aimport) automatically now. |
|
253 | Reload all modules (except those excluded by %aimport) automatically now. | |
254 |
|
254 | |||
|
255 | %autoreload 0 | |||
|
256 | Disable automatic reloading. | |||
|
257 | ||||
255 | %autoreload 1 |
|
258 | %autoreload 1 | |
256 | Reload all modules imported with %aimport every time before executing |
|
259 | Reload all modules imported with %aimport every time before executing | |
257 | the Python code typed. |
|
260 | the Python code typed. | |
258 |
|
261 | |||
259 | %autoreload 2 |
|
262 | %autoreload 2 | |
260 | Reload all modules (except those excluded by %aimport) every time |
|
263 | Reload all modules (except those excluded by %aimport) every time | |
261 | before executing the Python code typed. |
|
264 | before executing the Python code typed. | |
262 |
|
265 | |||
263 |
Reloading Python modules in a reliable way is in general |
|
266 | Reloading Python modules in a reliable way is in general | |
264 |
and unexpected things may occur. %autoreload tries to |
|
267 | difficult, and unexpected things may occur. %autoreload tries to | |
265 |
around common pitfalls by replacing code objects |
|
268 | work around common pitfalls by replacing function code objects and | |
266 |
previously in the module with new versions. This |
|
269 | parts of classes previously in the module with new versions. This | |
267 | things to work: |
|
270 | makes the following things to work: | |
268 |
|
271 | |||
269 | - Functions and classes imported via 'from xxx import foo' are upgraded |
|
272 | - Functions and classes imported via 'from xxx import foo' are upgraded | |
270 | to new versions when 'xxx' is reloaded. |
|
273 | to new versions when 'xxx' is reloaded. | |
|
274 | ||||
271 | - Methods and properties of classes are upgraded on reload, so that |
|
275 | - Methods and properties of classes are upgraded on reload, so that | |
272 | calling 'c.foo()' on an object 'c' created before the reload causes |
|
276 | calling 'c.foo()' on an object 'c' created before the reload causes | |
273 | the new code for 'foo' to be executed. |
|
277 | the new code for 'foo' to be executed. | |
274 |
|
278 | |||
275 | Some of the known remaining caveats are: |
|
279 | Some of the known remaining caveats are: | |
276 |
|
280 | |||
277 | - Replacing code objects does not always succeed: changing a @property |
|
281 | - Replacing code objects does not always succeed: changing a @property | |
278 | in a class to an ordinary method or a method to a member variable |
|
282 | in a class to an ordinary method or a method to a member variable | |
279 | can cause problems (but in old objects only). |
|
283 | can cause problems (but in old objects only). | |
|
284 | ||||
280 | - Functions that are removed (eg. via monkey-patching) from a module |
|
285 | - Functions that are removed (eg. via monkey-patching) from a module | |
281 | before it is reloaded are not upgraded. |
|
286 | before it is reloaded are not upgraded. | |
|
287 | ||||
282 | - C extension modules cannot be reloaded, and so cannot be |
|
288 | - C extension modules cannot be reloaded, and so cannot be | |
283 | autoreloaded. |
|
289 | autoreloaded. | |
284 |
|
290 | |||
285 | """ |
|
291 | """ | |
286 | if parameter_s == '': |
|
292 | if parameter_s == '': | |
287 | reloader.check(True) |
|
293 | reloader.check(True) | |
@@ -307,7 +313,7 b" def aimport_f(self, parameter_s=''):" | |||||
307 | Mark module 'foo' to not be autoreloaded for %autoreload 1 |
|
313 | Mark module 'foo' to not be autoreloaded for %autoreload 1 | |
308 |
|
314 | |||
309 | """ |
|
315 | """ | |
310 |
|
316 | |||
311 | modname = parameter_s |
|
317 | modname = parameter_s | |
312 | if not modname: |
|
318 | if not modname: | |
313 | to_reload = reloader.modules.keys() |
|
319 | to_reload = reloader.modules.keys() | |
@@ -329,12 +335,15 b" def aimport_f(self, parameter_s=''):" | |||||
329 | except KeyError: pass |
|
335 | except KeyError: pass | |
330 | reloader.modules[modname] = True |
|
336 | reloader.modules[modname] = True | |
331 |
|
337 | |||
332 | mod = __import__(modname) |
|
338 | # Inject module to user namespace; handle also submodules properly | |
333 |
|
|
339 | __import__(modname) | |
|
340 | basename = modname.split('.')[0] | |||
|
341 | mod = sys.modules[basename] | |||
|
342 | ip.to_user_ns({basename: mod}) | |||
334 |
|
343 | |||
335 | def init(): |
|
344 | def init(): | |
336 | ip.expose_magic('autoreload', autoreload_f) |
|
345 | ip.expose_magic('autoreload', autoreload_f) | |
337 | ip.expose_magic('aimport', aimport_f) |
|
346 | ip.expose_magic('aimport', aimport_f) | |
338 | ip.set_hook('pre_runcode_hook', runcode_hook) |
|
347 | ip.set_hook('pre_runcode_hook', runcode_hook) | |
339 |
|
348 | |||
340 | init() |
|
349 | init() |
@@ -3,6 +3,9 b' Base front end class for all async frontends.' | |||||
3 | """ |
|
3 | """ | |
4 | __docformat__ = "restructuredtext en" |
|
4 | __docformat__ = "restructuredtext en" | |
5 |
|
5 | |||
|
6 | # Tell nose to skip this module | |||
|
7 | __test__ = {} | |||
|
8 | ||||
6 | #------------------------------------------------------------------------------- |
|
9 | #------------------------------------------------------------------------------- | |
7 | # Copyright (C) 2008 The IPython Development Team |
|
10 | # Copyright (C) 2008 The IPython Development Team | |
8 | # |
|
11 | # | |
@@ -10,20 +13,25 b' __docformat__ = "restructuredtext en"' | |||||
10 | # the file COPYING, distributed as part of this software. |
|
13 | # the file COPYING, distributed as part of this software. | |
11 | #------------------------------------------------------------------------------- |
|
14 | #------------------------------------------------------------------------------- | |
12 |
|
15 | |||
13 |
|
||||
14 | #------------------------------------------------------------------------------- |
|
16 | #------------------------------------------------------------------------------- | |
15 | # Imports |
|
17 | # Imports | |
16 | #------------------------------------------------------------------------------- |
|
18 | #------------------------------------------------------------------------------- | |
17 |
|
19 | |||
|
20 | # Third-party | |||
|
21 | from twisted.python.failure import Failure | |||
|
22 | from zope.interface import implements, classProvides | |||
|
23 | ||||
|
24 | # From IPython | |||
18 | from IPython.external import guid |
|
25 | from IPython.external import guid | |
19 |
|
26 | |||
20 | from zope.interface import Interface, Attribute, implements, classProvides |
|
27 | from IPython.frontend.frontendbase import (FrontEndBase, IFrontEnd, | |
21 | from twisted.python.failure import Failure |
|
28 | IFrontEndFactory) | |
22 | from IPython.frontend.frontendbase import ( |
|
|||
23 | FrontEndBase, IFrontEnd, IFrontEndFactory) |
|
|||
24 | from IPython.kernel.core.history import FrontEndHistory |
|
29 | from IPython.kernel.core.history import FrontEndHistory | |
25 | from IPython.kernel.engineservice import IEngineCore |
|
30 | from IPython.kernel.engineservice import IEngineCore | |
26 |
|
31 | |||
|
32 | #----------------------------------------------------------------------------- | |||
|
33 | # Classes and functions | |||
|
34 | #----------------------------------------------------------------------------- | |||
27 |
|
35 | |||
28 | class AsyncFrontEndBase(FrontEndBase): |
|
36 | class AsyncFrontEndBase(FrontEndBase): | |
29 | """ |
|
37 | """ | |
@@ -41,8 +49,7 b' class AsyncFrontEndBase(FrontEndBase):' | |||||
41 | self.history = FrontEndHistory(input_cache=['']) |
|
49 | self.history = FrontEndHistory(input_cache=['']) | |
42 | else: |
|
50 | else: | |
43 | self.history = history |
|
51 | self.history = history | |
44 |
|
52 | |||
45 |
|
||||
46 | def execute(self, block, blockID=None): |
|
53 | def execute(self, block, blockID=None): | |
47 | """Execute the block and return the deferred result. |
|
54 | """Execute the block and return the deferred result. | |
48 |
|
55 | |||
@@ -73,5 +80,3 b' class AsyncFrontEndBase(FrontEndBase):' | |||||
73 | errback=self.render_error) |
|
80 | errback=self.render_error) | |
74 |
|
81 | |||
75 | return d |
|
82 | return d | |
76 |
|
||||
77 |
|
@@ -19,17 +19,17 b' __docformat__ = "restructuredtext en"' | |||||
19 | from setuptools import setup |
|
19 | from setuptools import setup | |
20 |
|
20 | |||
21 | infoPlist = dict( |
|
21 | infoPlist = dict( | |
22 |
|
|
22 | CFBundleDevelopmentRegion='English', | |
23 |
|
|
23 | CFBundleIdentifier='org.scipy.ipython.cocoa_frontend', | |
24 |
|
|
24 | NSPrincipalClass='IPythonCocoaController', | |
25 | ) |
|
25 | ) | |
26 |
|
26 | |||
27 | setup( |
|
27 | setup( | |
28 |
|
|
28 | plugin=['IPythonCocoaFrontendLoader.py'], | |
29 | setup_requires=['py2app'], |
|
29 | setup_requires=['py2app'], | |
30 |
|
|
30 | options=dict(py2app=dict( | |
31 |
|
|
31 | plist=infoPlist, | |
32 |
|
|
32 | site_packages=True, | |
33 |
|
|
33 | excludes=['IPython','twisted','PyObjCTools'] | |
34 | )), |
|
34 | )), | |
35 | ) No newline at end of file |
|
35 | ) |
@@ -97,8 +97,8 b' class LineFrontEndBase(FrontEndBase):' | |||||
97 | ---------- |
|
97 | ---------- | |
98 | line : string |
|
98 | line : string | |
99 |
|
99 | |||
100 |
Res |
|
100 | Returns | |
101 | ------ |
|
101 | ------- | |
102 | The replacement for the line and the list of possible completions. |
|
102 | The replacement for the line and the list of possible completions. | |
103 | """ |
|
103 | """ | |
104 | completions = self.shell.complete(line) |
|
104 | completions = self.shell.complete(line) |
@@ -65,8 +65,8 b' class PrefilterFrontEnd(LineFrontEndBase):' | |||||
65 | debug = False |
|
65 | debug = False | |
66 |
|
66 | |||
67 | def __init__(self, ipython0=None, argv=None, *args, **kwargs): |
|
67 | def __init__(self, ipython0=None, argv=None, *args, **kwargs): | |
68 |
""" Parameters |
|
68 | """ Parameters | |
69 |
---------- |
|
69 | ---------- | |
70 |
|
70 | |||
71 | ipython0: an optional ipython0 instance to use for command |
|
71 | ipython0: an optional ipython0 instance to use for command | |
72 | prefiltering and completion. |
|
72 | prefiltering and completion. |
@@ -3,6 +3,9 b'' | |||||
3 | """This file contains unittests for the asyncfrontendbase module.""" |
|
3 | """This file contains unittests for the asyncfrontendbase module.""" | |
4 |
|
4 | |||
5 | __docformat__ = "restructuredtext en" |
|
5 | __docformat__ = "restructuredtext en" | |
|
6 | ||||
|
7 | # Tell nose to skip this module | |||
|
8 | __test__ = {} | |||
6 |
|
9 | |||
7 | #--------------------------------------------------------------------------- |
|
10 | #--------------------------------------------------------------------------- | |
8 | # Copyright (C) 2008 The IPython Development Team |
|
11 | # Copyright (C) 2008 The IPython Development Team | |
@@ -10,20 +13,21 b' __docformat__ = "restructuredtext en"' | |||||
10 | # Distributed under the terms of the BSD License. The full license is in |
|
13 | # Distributed under the terms of the BSD License. The full license is in | |
11 | # the file COPYING, distributed as part of this software. |
|
14 | # the file COPYING, distributed as part of this software. | |
12 | #--------------------------------------------------------------------------- |
|
15 | #--------------------------------------------------------------------------- | |
13 |
|
16 | |||
14 | #--------------------------------------------------------------------------- |
|
17 | #--------------------------------------------------------------------------- | |
15 | # Imports |
|
18 | # Imports | |
16 | #--------------------------------------------------------------------------- |
|
19 | #--------------------------------------------------------------------------- | |
17 |
|
20 | |||
18 | # Tell nose to skip this module |
|
|||
19 | __test__ = {} |
|
|||
20 |
|
||||
21 | from twisted.trial import unittest |
|
21 | from twisted.trial import unittest | |
|
22 | ||||
22 | from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase |
|
23 | from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase | |
23 | from IPython.frontend import frontendbase |
|
24 | from IPython.frontend import frontendbase | |
24 | from IPython.kernel.engineservice import EngineService |
|
25 | from IPython.kernel.engineservice import EngineService | |
25 | from IPython.testing.parametric import Parametric, parametric |
|
26 | from IPython.testing.parametric import Parametric, parametric | |
26 |
|
27 | |||
|
28 | #----------------------------------------------------------------------------- | |||
|
29 | # Classes and functions | |||
|
30 | #----------------------------------------------------------------------------- | |||
27 |
|
31 | |||
28 | class FrontEndCallbackChecker(AsyncFrontEndBase): |
|
32 | class FrontEndCallbackChecker(AsyncFrontEndBase): | |
29 | """FrontEndBase subclass for checking callbacks""" |
|
33 | """FrontEndBase subclass for checking callbacks""" | |
@@ -106,4 +110,3 b' class TestAsyncFrontendBase(unittest.TestCase):' | |||||
106 | def test_history_returns_none_at_startup(self): |
|
110 | def test_history_returns_none_at_startup(self): | |
107 | self.assert_(self.fb.get_history_previous("")==None) |
|
111 | self.assert_(self.fb.get_history_previous("")==None) | |
108 | self.assert_(self.fb.get_history_next()==None) |
|
112 | self.assert_(self.fb.get_history_next()==None) | |
109 |
|
@@ -15,6 +15,7 b' __docformat__ = "restructuredtext en"' | |||||
15 | from copy import copy, deepcopy |
|
15 | from copy import copy, deepcopy | |
16 | from cStringIO import StringIO |
|
16 | from cStringIO import StringIO | |
17 | import string |
|
17 | import string | |
|
18 | import sys | |||
18 |
|
19 | |||
19 | from nose.tools import assert_equal |
|
20 | from nose.tools import assert_equal | |
20 |
|
21 | |||
@@ -23,22 +24,6 b' from IPython.core.ipapi import get as get_ipython0' | |||||
23 | from IPython.testing.plugin.ipdoctest import default_argv |
|
24 | from IPython.testing.plugin.ipdoctest import default_argv | |
24 |
|
25 | |||
25 |
|
26 | |||
26 | def safe_deepcopy(d): |
|
|||
27 | """ Deep copy every key of the given dict, when possible. Elsewhere |
|
|||
28 | do a copy. |
|
|||
29 | """ |
|
|||
30 | copied_d = dict() |
|
|||
31 | for key, value in d.iteritems(): |
|
|||
32 | try: |
|
|||
33 | copied_d[key] = deepcopy(value) |
|
|||
34 | except: |
|
|||
35 | try: |
|
|||
36 | copied_d[key] = copy(value) |
|
|||
37 | except: |
|
|||
38 | copied_d[key] = value |
|
|||
39 | return copied_d |
|
|||
40 |
|
||||
41 |
|
||||
42 | class TestPrefilterFrontEnd(PrefilterFrontEnd): |
|
27 | class TestPrefilterFrontEnd(PrefilterFrontEnd): | |
43 |
|
28 | |||
44 | input_prompt_template = string.Template('') |
|
29 | input_prompt_template = string.Template('') | |
@@ -72,17 +57,34 b' def isolate_ipython0(func):' | |||||
72 | with arguments. |
|
57 | with arguments. | |
73 | """ |
|
58 | """ | |
74 | def my_func(): |
|
59 | def my_func(): | |
75 |
ip |
|
60 | ip0 = get_ipython0() | |
76 |
if ip |
|
61 | if ip0 is None: | |
77 | return func() |
|
62 | return func() | |
78 | ipython0 = iplib.IP |
|
63 | # We have a real ipython running... | |
79 | global_ns = safe_deepcopy(ipython0.user_global_ns) |
|
64 | user_ns = ip0.IP.user_ns | |
80 |
user_ns = |
|
65 | user_global_ns = ip0.IP.user_global_ns | |
|
66 | ||||
|
67 | # Previously the isolation was attempted with a deep copy of the user | |||
|
68 | # dicts, but we found cases where this didn't work correctly. I'm not | |||
|
69 | # quite sure why, but basically it did damage the user namespace, such | |||
|
70 | # that later tests stopped working correctly. Instead we use a simpler | |||
|
71 | # approach, just computing the list of added keys to the namespace and | |||
|
72 | # eliminating those afterwards. Existing keys that may have been | |||
|
73 | # modified remain modified. So far this has proven to be robust. | |||
|
74 | ||||
|
75 | # Compute set of old local/global keys | |||
|
76 | old_locals = set(user_ns.keys()) | |||
|
77 | old_globals = set(user_global_ns.keys()) | |||
81 | try: |
|
78 | try: | |
82 | out = func() |
|
79 | out = func() | |
83 | finally: |
|
80 | finally: | |
84 | ipython0.user_ns = user_ns |
|
81 | # Find new keys, and if any, remove them | |
85 | ipython0.user_global_ns = global_ns |
|
82 | new_locals = set(user_ns.keys()) - old_locals | |
|
83 | new_globals = set(user_global_ns.keys()) - old_globals | |||
|
84 | for k in new_locals: | |||
|
85 | del user_ns[k] | |||
|
86 | for k in new_globals: | |||
|
87 | del user_global_ns[k] | |||
86 | # Undo the hack at creation of PrefilterFrontEnd |
|
88 | # Undo the hack at creation of PrefilterFrontEnd | |
87 | from IPython.core import iplib |
|
89 | from IPython.core import iplib | |
88 | iplib.InteractiveShell.isthreaded = False |
|
90 | iplib.InteractiveShell.isthreaded = False | |
@@ -97,7 +99,7 b' def test_execution():' | |||||
97 | """ Test execution of a command. |
|
99 | """ Test execution of a command. | |
98 | """ |
|
100 | """ | |
99 | f = TestPrefilterFrontEnd() |
|
101 | f = TestPrefilterFrontEnd() | |
100 |
f.input_buffer = 'print |
|
102 | f.input_buffer = 'print(1)' | |
101 | f._on_enter() |
|
103 | f._on_enter() | |
102 | out_value = f.out.getvalue() |
|
104 | out_value = f.out.getvalue() | |
103 | assert_equal(out_value, '1\n') |
|
105 | assert_equal(out_value, '1\n') | |
@@ -228,7 +230,14 b' def test_completion_indexing():' | |||||
228 | f._on_enter() |
|
230 | f._on_enter() | |
229 | f.input_buffer = 'a[0].' |
|
231 | f.input_buffer = 'a[0].' | |
230 | f.complete_current_input() |
|
232 | f.complete_current_input() | |
231 | assert_equal(f.input_buffer, 'a[0].__') |
|
233 | ||
|
234 | if sys.version_info[:2] >= (2,6): | |||
|
235 | # In Python 2.6, ints picked up a few non __ methods, so now there are | |||
|
236 | # no completions. | |||
|
237 | assert_equal(f.input_buffer, 'a[0].') | |||
|
238 | else: | |||
|
239 | # Right answer for 2.4/2.5 | |||
|
240 | assert_equal(f.input_buffer, 'a[0].__') | |||
232 |
|
241 | |||
233 |
|
242 | |||
234 | @isolate_ipython0 |
|
243 | @isolate_ipython0 | |
@@ -238,8 +247,13 b' def test_completion_equal():' | |||||
238 | f = TestPrefilterFrontEnd() |
|
247 | f = TestPrefilterFrontEnd() | |
239 | f.input_buffer = 'a=1.' |
|
248 | f.input_buffer = 'a=1.' | |
240 | f.complete_current_input() |
|
249 | f.complete_current_input() | |
241 | assert_equal(f.input_buffer, 'a=1.__') |
|
250 | if sys.version_info[:2] >= (2,6): | |
242 |
|
251 | # In Python 2.6, ints picked up a few non __ methods, so now there are | ||
|
252 | # no completions. | |||
|
253 | assert_equal(f.input_buffer, 'a=1.') | |||
|
254 | else: | |||
|
255 | # Right answer for 2.4/2.5 | |||
|
256 | assert_equal(f.input_buffer, 'a=1.__') | |||
243 |
|
257 | |||
244 |
|
258 | |||
245 | if __name__ == '__main__': |
|
259 | if __name__ == '__main__': |
@@ -447,29 +447,30 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
447 | # different callbacks share local variables? |
|
447 | # different callbacks share local variables? | |
448 |
|
448 | |||
449 | # Intercept some specific keys. |
|
449 | # Intercept some specific keys. | |
450 | if event.KeyCode == ord('L') and event.ControlDown() : |
|
450 | key_code = event.GetKeyCode() | |
|
451 | if key_code == ord('L') and event.ControlDown() : | |||
451 | self.scroll_to_bottom() |
|
452 | self.scroll_to_bottom() | |
452 |
elif |
|
453 | elif key_code == ord('K') and event.ControlDown() : | |
453 | self.input_buffer = '' |
|
454 | self.input_buffer = '' | |
454 |
elif |
|
455 | elif key_code == ord('A') and event.ControlDown() : | |
455 | self.GotoPos(self.GetLength()) |
|
456 | self.GotoPos(self.GetLength()) | |
456 | self.SetSelectionStart(self.current_prompt_pos) |
|
457 | self.SetSelectionStart(self.current_prompt_pos) | |
457 | self.SetSelectionEnd(self.GetCurrentPos()) |
|
458 | self.SetSelectionEnd(self.GetCurrentPos()) | |
458 | catched = True |
|
459 | catched = True | |
459 |
elif |
|
460 | elif key_code == ord('E') and event.ControlDown() : | |
460 | self.GotoPos(self.GetLength()) |
|
461 | self.GotoPos(self.GetLength()) | |
461 | catched = True |
|
462 | catched = True | |
462 |
elif |
|
463 | elif key_code == wx.WXK_PAGEUP: | |
463 | self.ScrollPages(-1) |
|
464 | self.ScrollPages(-1) | |
464 |
elif |
|
465 | elif key_code == wx.WXK_PAGEDOWN: | |
465 | self.ScrollPages(1) |
|
466 | self.ScrollPages(1) | |
466 |
elif |
|
467 | elif key_code == wx.WXK_HOME: | |
467 | self.GotoPos(self.GetLength()) |
|
468 | self.GotoPos(self.GetLength()) | |
468 |
elif |
|
469 | elif key_code == wx.WXK_END: | |
469 | self.GotoPos(self.GetLength()) |
|
470 | self.GotoPos(self.GetLength()) | |
470 |
elif |
|
471 | elif key_code == wx.WXK_UP and event.ShiftDown(): | |
471 | self.ScrollLines(-1) |
|
472 | self.ScrollLines(-1) | |
472 |
elif |
|
473 | elif key_code == wx.WXK_DOWN and event.ShiftDown(): | |
473 | self.ScrollLines(1) |
|
474 | self.ScrollLines(1) | |
474 | else: |
|
475 | else: | |
475 | catched = False |
|
476 | catched = False | |
@@ -477,13 +478,12 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
477 | if self.AutoCompActive(): |
|
478 | if self.AutoCompActive(): | |
478 | event.Skip() |
|
479 | event.Skip() | |
479 | else: |
|
480 | else: | |
480 |
if |
|
481 | if key_code in (13, wx.WXK_NUMPAD_ENTER): | |
481 | event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN, |
|
482 | # XXX: not catching modifiers, to be wx2.6-compatible | |
482 | wx.MOD_SHIFT): |
|
|||
483 | catched = True |
|
483 | catched = True | |
484 | if not self.enter_catched: |
|
484 | if not self.enter_catched: | |
485 | self.CallTipCancel() |
|
485 | self.CallTipCancel() | |
486 |
if event. |
|
486 | if event.ShiftDown(): | |
487 | # Try to force execution |
|
487 | # Try to force execution | |
488 | self.GotoPos(self.GetLength()) |
|
488 | self.GotoPos(self.GetLength()) | |
489 | self.write('\n' + self.continuation_prompt(), |
|
489 | self.write('\n' + self.continuation_prompt(), | |
@@ -493,19 +493,18 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
493 | self._on_enter() |
|
493 | self._on_enter() | |
494 | self.enter_catched = True |
|
494 | self.enter_catched = True | |
495 |
|
495 | |||
496 |
elif |
|
496 | elif key_code == wx.WXK_HOME: | |
497 | if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN): |
|
497 | if not event.ShiftDown(): | |
498 | self.GotoPos(self.current_prompt_pos) |
|
498 | self.GotoPos(self.current_prompt_pos) | |
499 | catched = True |
|
499 | catched = True | |
500 |
|
500 | else: | ||
501 | elif event.Modifiers == wx.MOD_SHIFT: |
|
|||
502 | # FIXME: This behavior is not ideal: if the selection |
|
501 | # FIXME: This behavior is not ideal: if the selection | |
503 | # is already started, it will jump. |
|
502 | # is already started, it will jump. | |
504 | self.SetSelectionStart(self.current_prompt_pos) |
|
503 | self.SetSelectionStart(self.current_prompt_pos) | |
505 | self.SetSelectionEnd(self.GetCurrentPos()) |
|
504 | self.SetSelectionEnd(self.GetCurrentPos()) | |
506 | catched = True |
|
505 | catched = True | |
507 |
|
506 | |||
508 |
elif |
|
507 | elif key_code == wx.WXK_UP: | |
509 | if self.GetCurrentLine() > self.current_prompt_line: |
|
508 | if self.GetCurrentLine() > self.current_prompt_line: | |
510 | if self.GetCurrentLine() == self.current_prompt_line + 1 \ |
|
509 | if self.GetCurrentLine() == self.current_prompt_line + 1 \ | |
511 | and self.GetColumn(self.GetCurrentPos()) < \ |
|
510 | and self.GetColumn(self.GetCurrentPos()) < \ | |
@@ -515,18 +514,18 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
515 | event.Skip() |
|
514 | event.Skip() | |
516 | catched = True |
|
515 | catched = True | |
517 |
|
516 | |||
518 |
elif |
|
517 | elif key_code in (wx.WXK_LEFT, wx.WXK_BACK): | |
519 | if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1): |
|
518 | if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1): | |
520 | event.Skip() |
|
519 | event.Skip() | |
521 | catched = True |
|
520 | catched = True | |
522 |
|
521 | |||
523 |
elif |
|
522 | elif key_code == wx.WXK_RIGHT: | |
524 | if not self._keep_cursor_in_buffer(self.GetCurrentPos() + 1): |
|
523 | if not self._keep_cursor_in_buffer(self.GetCurrentPos() + 1): | |
525 | event.Skip() |
|
524 | event.Skip() | |
526 | catched = True |
|
525 | catched = True | |
527 |
|
526 | |||
528 |
|
527 | |||
529 |
elif |
|
528 | elif key_code == wx.WXK_DELETE: | |
530 | if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1): |
|
529 | if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1): | |
531 | event.Skip() |
|
530 | event.Skip() | |
532 | catched = True |
|
531 | catched = True | |
@@ -535,7 +534,7 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
535 | # Put the cursor back in the edit region |
|
534 | # Put the cursor back in the edit region | |
536 | if not self._keep_cursor_in_buffer(): |
|
535 | if not self._keep_cursor_in_buffer(): | |
537 | if not (self.GetCurrentPos() == self.GetLength() |
|
536 | if not (self.GetCurrentPos() == self.GetLength() | |
538 |
and |
|
537 | and key_code == wx.WXK_DELETE): | |
539 | event.Skip() |
|
538 | event.Skip() | |
540 | catched = True |
|
539 | catched = True | |
541 |
|
540 |
@@ -389,7 +389,8 b' class WxController(ConsoleWidget, PrefilterFrontEnd):' | |||||
389 | """ |
|
389 | """ | |
390 | # FIXME: This method needs to be broken down in smaller ones. |
|
390 | # FIXME: This method needs to be broken down in smaller ones. | |
391 | current_line_num = self.GetCurrentLine() |
|
391 | current_line_num = self.GetCurrentLine() | |
392 | if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown(): |
|
392 | key_code = event.GetKeyCode() | |
|
393 | if key_code in (ord('c'), ord('C')) and event.ControlDown(): | |||
393 | # Capture Control-C |
|
394 | # Capture Control-C | |
394 | if self._input_state == 'subprocess': |
|
395 | if self._input_state == 'subprocess': | |
395 | if self.debug: |
|
396 | if self.debug: | |
@@ -403,40 +404,39 b' class WxController(ConsoleWidget, PrefilterFrontEnd):' | |||||
403 | # XXX: We need to make really sure we |
|
404 | # XXX: We need to make really sure we | |
404 | # get back to a prompt. |
|
405 | # get back to a prompt. | |
405 | elif self._input_state == 'subprocess' and ( |
|
406 | elif self._input_state == 'subprocess' and ( | |
406 |
( |
|
407 | ( key_code <256 and not event.ControlDown() ) | |
407 | not event.ControlDown() ) |
|
|||
408 | or |
|
408 | or | |
409 |
( |
|
409 | ( key_code in (ord('d'), ord('D')) and | |
410 | event.ControlDown())): |
|
410 | event.ControlDown())): | |
411 | # We are running a process, we redirect keys. |
|
411 | # We are running a process, we redirect keys. | |
412 | ConsoleWidget._on_key_down(self, event, skip=skip) |
|
412 | ConsoleWidget._on_key_down(self, event, skip=skip) | |
413 |
char = chr( |
|
413 | char = chr(key_code) | |
414 | # Deal with some inconsistency in wx keycodes: |
|
414 | # Deal with some inconsistency in wx keycodes: | |
415 | if char == '\r': |
|
415 | if char == '\r': | |
416 | char = '\n' |
|
416 | char = '\n' | |
417 | elif not event.ShiftDown(): |
|
417 | elif not event.ShiftDown(): | |
418 | char = char.lower() |
|
418 | char = char.lower() | |
419 |
if event.ControlDown() and |
|
419 | if event.ControlDown() and key_code in (ord('d'), ord('D')): | |
420 | char = '\04' |
|
420 | char = '\04' | |
421 | self._running_process.process.stdin.write(char) |
|
421 | self._running_process.process.stdin.write(char) | |
422 | self._running_process.process.stdin.flush() |
|
422 | self._running_process.process.stdin.flush() | |
423 |
elif |
|
423 | elif key_code in (ord('('), 57, 53): | |
424 | # Calltips |
|
424 | # Calltips | |
425 | event.Skip() |
|
425 | event.Skip() | |
426 | self.do_calltip() |
|
426 | self.do_calltip() | |
427 |
elif self.AutoCompActive() and not |
|
427 | elif self.AutoCompActive() and not key_code == ord('\t'): | |
428 | event.Skip() |
|
428 | event.Skip() | |
429 |
if |
|
429 | if key_code in (wx.WXK_BACK, wx.WXK_DELETE): | |
430 | wx.CallAfter(self._popup_completion, create=True) |
|
430 | wx.CallAfter(self._popup_completion, create=True) | |
431 |
elif not |
|
431 | elif not key_code in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT, | |
432 | wx.WXK_RIGHT, wx.WXK_ESCAPE): |
|
432 | wx.WXK_RIGHT, wx.WXK_ESCAPE): | |
433 | wx.CallAfter(self._popup_completion) |
|
433 | wx.CallAfter(self._popup_completion) | |
434 | else: |
|
434 | else: | |
435 | # Up history |
|
435 | # Up history | |
436 |
if |
|
436 | if key_code == wx.WXK_UP and ( | |
437 | ( current_line_num == self.current_prompt_line and |
|
437 | event.ControlDown() or | |
438 | event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) ) |
|
438 | current_line_num == self.current_prompt_line | |
439 |
|
|
439 | ): | |
440 | new_buffer = self.get_history_previous( |
|
440 | new_buffer = self.get_history_previous( | |
441 | self.input_buffer) |
|
441 | self.input_buffer) | |
442 | if new_buffer is not None: |
|
442 | if new_buffer is not None: | |
@@ -445,23 +445,24 b' class WxController(ConsoleWidget, PrefilterFrontEnd):' | |||||
445 | # Go to first line, for seemless history up. |
|
445 | # Go to first line, for seemless history up. | |
446 | self.GotoPos(self.current_prompt_pos) |
|
446 | self.GotoPos(self.current_prompt_pos) | |
447 | # Down history |
|
447 | # Down history | |
448 |
elif |
|
448 | elif key_code == wx.WXK_DOWN and ( | |
449 | ( current_line_num == self.LineCount -1 and |
|
449 | event.ControlDown() or | |
450 | event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) ) |
|
450 | current_line_num == self.LineCount -1 | |
451 |
|
|
451 | ): | |
452 | new_buffer = self.get_history_next() |
|
452 | new_buffer = self.get_history_next() | |
453 | if new_buffer is not None: |
|
453 | if new_buffer is not None: | |
454 | self.input_buffer = new_buffer |
|
454 | self.input_buffer = new_buffer | |
455 | # Tab-completion |
|
455 | # Tab-completion | |
456 |
elif |
|
456 | elif key_code == ord('\t'): | |
457 | current_line, current_line_num = self.CurLine |
|
457 | current_line, current_line_num = self.CurLine | |
458 |
if not re.match(r'^\s*$', |
|
458 | if not re.match(r'^%s\s*$' % self.continuation_prompt(), | |
|
459 | current_line): | |||
459 | self.complete_current_input() |
|
460 | self.complete_current_input() | |
460 | if self.AutoCompActive(): |
|
461 | if self.AutoCompActive(): | |
461 | wx.CallAfter(self._popup_completion, create=True) |
|
462 | wx.CallAfter(self._popup_completion, create=True) | |
462 | else: |
|
463 | else: | |
463 | event.Skip() |
|
464 | event.Skip() | |
464 |
elif |
|
465 | elif key_code == wx.WXK_BACK: | |
465 | # If characters where erased, check if we have to |
|
466 | # If characters where erased, check if we have to | |
466 | # remove a line. |
|
467 | # remove a line. | |
467 | # XXX: What about DEL? |
|
468 | # XXX: What about DEL? | |
@@ -496,7 +497,7 b' class WxController(ConsoleWidget, PrefilterFrontEnd):' | |||||
496 | def _on_key_up(self, event, skip=True): |
|
497 | def _on_key_up(self, event, skip=True): | |
497 | """ Called when any key is released. |
|
498 | """ Called when any key is released. | |
498 | """ |
|
499 | """ | |
499 | if event.KeyCode in (59, ord('.')): |
|
500 | if event.GetKeyCode() in (59, ord('.')): | |
500 | # Intercepting '.' |
|
501 | # Intercepting '.' | |
501 | event.Skip() |
|
502 | event.Skip() | |
502 | wx.CallAfter(self._popup_completion, create=True) |
|
503 | wx.CallAfter(self._popup_completion, create=True) |
@@ -46,7 +46,7 b' class _Helper(object):' | |||||
46 |
|
46 | |||
47 | def __call__(self, *args, **kwds): |
|
47 | def __call__(self, *args, **kwds): | |
48 | class DummyWriter(object): |
|
48 | class DummyWriter(object): | |
49 |
'''Dumy class to handle help output''' |
|
49 | '''Dumy class to handle help output''' | |
50 | def __init__(self, pager): |
|
50 | def __init__(self, pager): | |
51 | self._pager = pager |
|
51 | self._pager = pager | |
52 |
|
52 |
@@ -76,12 +76,12 b' class WxNonBlockingIPShell(NonBlockingIPShell):' | |||||
76 | """ A replacement from python's raw_input. |
|
76 | """ A replacement from python's raw_input. | |
77 | """ |
|
77 | """ | |
78 | self.answer = None |
|
78 | self.answer = None | |
79 |
if(self._threading == True): |
|
79 | if(self._threading == True): | |
80 |
|
|
80 | wx.CallAfter(self._yesNoBox, prompt) | |
81 |
|
|
81 | while self.answer is None: | |
82 | time.sleep(.1) |
|
82 | time.sleep(.1) | |
83 | else: |
|
83 | else: | |
84 |
|
|
84 | self._yesNoBox(prompt) | |
85 | return self.answer |
|
85 | return self.answer | |
86 |
|
86 | |||
87 | def _yesNoBox(self, prompt): |
|
87 | def _yesNoBox(self, prompt): |
@@ -26,7 +26,7 b' import sys' | |||||
26 |
|
26 | |||
27 | from twisted.internet.error import ConnectionRefusedError |
|
27 | from twisted.internet.error import ConnectionRefusedError | |
28 |
|
28 | |||
29 |
from IPython. |
|
29 | from IPython.core.ultratb import _fixed_getinnerframes, findsource | |
30 | from IPython.core import ipapi |
|
30 | from IPython.core import ipapi | |
31 |
|
31 | |||
32 | from IPython.kernel import error |
|
32 | from IPython.kernel import error |
@@ -29,7 +29,7 b' import sys' | |||||
29 | import traceback |
|
29 | import traceback | |
30 |
|
30 | |||
31 | # Local imports. |
|
31 | # Local imports. | |
32 |
from IPython. |
|
32 | from IPython.core import ultratb | |
33 | from IPython.kernel.core.display_trap import DisplayTrap |
|
33 | from IPython.kernel.core.display_trap import DisplayTrap | |
34 | from IPython.kernel.core.macro import Macro |
|
34 | from IPython.kernel.core.macro import Macro | |
35 | from IPython.kernel.core.prompts import CachedOutput |
|
35 | from IPython.kernel.core.prompts import CachedOutput | |
@@ -167,9 +167,9 b' class Interpreter(object):' | |||||
167 | formatters=self.traceback_formatters) |
|
167 | formatters=self.traceback_formatters) | |
168 |
|
168 | |||
169 | # This is used temporarily for reformating exceptions in certain |
|
169 | # This is used temporarily for reformating exceptions in certain | |
170 |
# cases. It will go away once the ultra |
|
170 | # cases. It will go away once the ultratb stuff is ported | |
171 | # to ipython1 |
|
171 | # to ipython1 | |
172 |
self.tbHandler = ultra |
|
172 | self.tbHandler = ultratb.FormattedTB(color_scheme='NoColor', | |
173 | mode='Context', |
|
173 | mode='Context', | |
174 | tb_offset=2) |
|
174 | tb_offset=2) | |
175 |
|
175 | |||
@@ -729,8 +729,8 b' class Interpreter(object):' | |||||
729 | def error(self, text): |
|
729 | def error(self, text): | |
730 | """ Pass an error message back to the shell. |
|
730 | """ Pass an error message back to the shell. | |
731 |
|
731 | |||
732 | Preconditions |
|
732 | Notes | |
733 |
----- |
|
733 | ----- | |
734 | This should only be called when self.message is set. In other words, |
|
734 | This should only be called when self.message is set. In other words, | |
735 | when code is being executed. |
|
735 | when code is being executed. | |
736 |
|
736 |
@@ -21,8 +21,8 b' __test__ = {}' | |||||
21 | class NotificationCenter(object): |
|
21 | class NotificationCenter(object): | |
22 | """Synchronous notification center |
|
22 | """Synchronous notification center | |
23 |
|
23 | |||
24 | Example |
|
24 | Examples | |
25 | ------- |
|
25 | -------- | |
26 | >>> import IPython.kernel.core.notification as notification |
|
26 | >>> import IPython.kernel.core.notification as notification | |
27 | >>> def callback(theType, theSender, args={}): |
|
27 | >>> def callback(theType, theSender, args={}): | |
28 | ... print theType,theSender,args |
|
28 | ... print theType,theSender,args | |
@@ -47,10 +47,10 b' class NotificationCenter(object):' | |||||
47 |
|
47 | |||
48 | def post_notification(self, theType, sender, **kwargs): |
|
48 | def post_notification(self, theType, sender, **kwargs): | |
49 | """Post notification (type,sender,**kwargs) to all registered |
|
49 | """Post notification (type,sender,**kwargs) to all registered | |
50 |
observers. |
|
50 | observers. | |
51 |
|
51 | |||
52 | Implementation |
|
52 | Implementation notes: | |
53 | -------------- |
|
53 | ||
54 | * If no registered observers, performance is O(1). |
|
54 | * If no registered observers, performance is O(1). | |
55 | * Notificaiton order is undefined. |
|
55 | * Notificaiton order is undefined. | |
56 | * Notifications are posted synchronously. |
|
56 | * Notifications are posted synchronously. | |
@@ -122,4 +122,4 b' class NotificationCenter(object):' | |||||
122 |
|
122 | |||
123 |
|
123 | |||
124 |
|
124 | |||
125 | sharedCenter = NotificationCenter() No newline at end of file |
|
125 | sharedCenter = NotificationCenter() |
@@ -106,6 +106,9 b' def make_quoted_expr(s):' | |||||
106 | def system_shell(cmd, verbose=False, debug=False, header=''): |
|
106 | def system_shell(cmd, verbose=False, debug=False, header=''): | |
107 | """ Execute a command in the system shell; always return None. |
|
107 | """ Execute a command in the system shell; always return None. | |
108 |
|
108 | |||
|
109 | This returns None so it can be conveniently used in interactive loops | |||
|
110 | without getting the return value (typically 0) printed many times. | |||
|
111 | ||||
109 | Parameters |
|
112 | Parameters | |
110 | ---------- |
|
113 | ---------- | |
111 | cmd : str |
|
114 | cmd : str | |
@@ -117,11 +120,6 b" def system_shell(cmd, verbose=False, debug=False, header=''):" | |||||
117 | header : str |
|
120 | header : str | |
118 | Header to print to screen prior to the executed command. No extra |
|
121 | Header to print to screen prior to the executed command. No extra | |
119 | newlines are added. |
|
122 | newlines are added. | |
120 |
|
||||
121 | Description |
|
|||
122 | ----------- |
|
|||
123 | This returns None so it can be conveniently used in interactive loops |
|
|||
124 | without getting the return value (typically 0) printed many times. |
|
|||
125 | """ |
|
123 | """ | |
126 |
|
124 | |||
127 | if verbose or debug: |
|
125 | if verbose or debug: |
@@ -23,6 +23,10 b' method that automatically added methods to engines.' | |||||
23 |
|
23 | |||
24 | __docformat__ = "restructuredtext en" |
|
24 | __docformat__ = "restructuredtext en" | |
25 |
|
25 | |||
|
26 | # Tell nose to skip this module. I don't think we need this as nose | |||
|
27 | # shouldn't ever be run on this! | |||
|
28 | __test__ = {} | |||
|
29 | ||||
26 | #------------------------------------------------------------------------------- |
|
30 | #------------------------------------------------------------------------------- | |
27 | # Copyright (C) 2008 The IPython Development Team |
|
31 | # Copyright (C) 2008 The IPython Development Team | |
28 | # |
|
32 | # | |
@@ -34,12 +38,9 b' __docformat__ = "restructuredtext en"' | |||||
34 | # Imports |
|
38 | # Imports | |
35 | #------------------------------------------------------------------------------- |
|
39 | #------------------------------------------------------------------------------- | |
36 |
|
40 | |||
37 | # Tell nose to skip the testing of this module |
|
41 | import copy | |
38 | __test__ = {} |
|
42 | import sys | |
39 |
|
||||
40 | import os, sys, copy |
|
|||
41 | import cPickle as pickle |
|
43 | import cPickle as pickle | |
42 | from new import instancemethod |
|
|||
43 |
|
44 | |||
44 | from twisted.application import service |
|
45 | from twisted.application import service | |
45 | from twisted.internet import defer, reactor |
|
46 | from twisted.internet import defer, reactor | |
@@ -47,11 +48,7 b' from twisted.python import log, failure, components' | |||||
47 | import zope.interface as zi |
|
48 | import zope.interface as zi | |
48 |
|
49 | |||
49 | from IPython.kernel.core.interpreter import Interpreter |
|
50 | from IPython.kernel.core.interpreter import Interpreter | |
50 |
from IPython.kernel import newserialized, error |
|
51 | from IPython.kernel import newserialized, error | |
51 | from IPython.kernel.util import printer |
|
|||
52 | from IPython.kernel.twistedutil import gatherBoth, DeferredList |
|
|||
53 | from IPython.kernel import codeutil |
|
|||
54 |
|
||||
55 |
|
52 | |||
56 | #------------------------------------------------------------------------------- |
|
53 | #------------------------------------------------------------------------------- | |
57 | # Interface specification for the Engine |
|
54 | # Interface specification for the Engine |
@@ -4,6 +4,9 b'' | |||||
4 |
|
4 | |||
5 | __docformat__ = "restructuredtext en" |
|
5 | __docformat__ = "restructuredtext en" | |
6 |
|
6 | |||
|
7 | # Tell nose to skip this module | |||
|
8 | __test__ = {} | |||
|
9 | ||||
7 | #------------------------------------------------------------------------------- |
|
10 | #------------------------------------------------------------------------------- | |
8 | # Copyright (C) 2008 The IPython Development Team |
|
11 | # Copyright (C) 2008 The IPython Development Team | |
9 | # |
|
12 | # | |
@@ -14,9 +17,9 b' __docformat__ = "restructuredtext en"' | |||||
14 | #------------------------------------------------------------------------------- |
|
17 | #------------------------------------------------------------------------------- | |
15 | # Imports |
|
18 | # Imports | |
16 | #------------------------------------------------------------------------------- |
|
19 | #------------------------------------------------------------------------------- | |
|
20 | from twisted.python import failure | |||
17 |
|
21 | |||
18 | from IPython.kernel.core import error |
|
22 | from IPython.kernel.core import error | |
19 | from twisted.python import failure |
|
|||
20 |
|
23 | |||
21 | #------------------------------------------------------------------------------- |
|
24 | #------------------------------------------------------------------------------- | |
22 | # Error classes |
|
25 | # Error classes |
@@ -86,14 +86,13 b' class PendingResult(object):' | |||||
86 |
|
86 | |||
87 | A user should not create a `PendingResult` instance by hand. |
|
87 | A user should not create a `PendingResult` instance by hand. | |
88 |
|
88 | |||
89 | Methods |
|
89 | Methods: | |
90 | ======= |
|
|||
91 |
|
90 | |||
92 | * `get_result` |
|
91 | * `get_result` | |
93 | * `add_callback` |
|
92 | * `add_callback` | |
94 |
|
93 | |||
95 | Properties |
|
94 | Properties: | |
96 | ========== |
|
95 | ||
97 | * `r` |
|
96 | * `r` | |
98 | """ |
|
97 | """ | |
99 |
|
98 |
@@ -5,6 +5,9 b'' | |||||
5 |
|
5 | |||
6 | __docformat__ = "restructuredtext en" |
|
6 | __docformat__ = "restructuredtext en" | |
7 |
|
7 | |||
|
8 | # Tell nose to skip this module | |||
|
9 | __test__ = {} | |||
|
10 | ||||
8 | #------------------------------------------------------------------------------- |
|
11 | #------------------------------------------------------------------------------- | |
9 | # Copyright (C) 2008 The IPython Development Team |
|
12 | # Copyright (C) 2008 The IPython Development Team | |
10 | # |
|
13 | # | |
@@ -18,8 +21,8 b' __docformat__ = "restructuredtext en"' | |||||
18 |
|
21 | |||
19 | import cPickle as pickle |
|
22 | import cPickle as pickle | |
20 |
|
23 | |||
21 | from zope.interface import Interface, implements |
|
|||
22 | from twisted.python import components |
|
24 | from twisted.python import components | |
|
25 | from zope.interface import Interface, implements | |||
23 |
|
26 | |||
24 | try: |
|
27 | try: | |
25 | import numpy |
|
28 | import numpy | |
@@ -28,6 +31,10 b' except ImportError:' | |||||
28 |
|
31 | |||
29 | from IPython.kernel.error import SerializationError |
|
32 | from IPython.kernel.error import SerializationError | |
30 |
|
33 | |||
|
34 | #----------------------------------------------------------------------------- | |||
|
35 | # Classes and functions | |||
|
36 | #----------------------------------------------------------------------------- | |||
|
37 | ||||
31 | class ISerialized(Interface): |
|
38 | class ISerialized(Interface): | |
32 |
|
39 | |||
33 | def getData(): |
|
40 | def getData(): |
1 | NO CONTENT: modified file chmod 100755 => 100644 |
|
NO CONTENT: modified file chmod 100755 => 100644 |
@@ -414,7 +414,7 b' class ResultNS(object):' | |||||
414 | This can be a bad idea, as it may corrupt standard behavior of the |
|
414 | This can be a bad idea, as it may corrupt standard behavior of the | |
415 | ns object. |
|
415 | ns object. | |
416 |
|
416 | |||
417 | Example |
|
417 | Examples | |
418 | -------- |
|
418 | -------- | |
419 |
|
419 | |||
420 | >>> ns = ResultNS({'a':17,'foo':range(3)}) |
|
420 | >>> ns = ResultNS({'a':17,'foo':range(3)}) |
@@ -111,6 +111,13 b' has a few useful methods for navigation, like again(), edit(), jump(), seek()' | |||||
111 | and back(). It can be reset for a new run via reset() or reloaded from disk |
|
111 | and back(). It can be reset for a new run via reset() or reloaded from disk | |
112 | (in case you've edited the source) via reload(). See their docstrings below. |
|
112 | (in case you've edited the source) via reload(). See their docstrings below. | |
113 |
|
113 | |||
|
114 | Note: To make this simpler to explore, a file called "demo-exercizer.py" has | |||
|
115 | been added to the "docs/examples/core" directory. Just cd to this directory in | |||
|
116 | an IPython session, and type:: | |||
|
117 | ||||
|
118 | %run demo-exercizer.py | |||
|
119 | ||||
|
120 | and then follow the directions. | |||
114 |
|
121 | |||
115 | Example |
|
122 | Example | |
116 | ======= |
|
123 | ======= | |
@@ -125,7 +132,7 b" print 'Hello, welcome to an interactive IPython demo.'" | |||||
125 | # The mark below defines a block boundary, which is a point where IPython will |
|
132 | # The mark below defines a block boundary, which is a point where IPython will | |
126 | # stop execution and return to the interactive prompt. The dashes are actually |
|
133 | # stop execution and return to the interactive prompt. The dashes are actually | |
127 | # optional and used only as a visual aid to clearly separate blocks while |
|
134 | # optional and used only as a visual aid to clearly separate blocks while | |
128 | editing the demo code. |
|
135 | # editing the demo code. | |
129 | # <demo> stop |
|
136 | # <demo> stop | |
130 |
|
137 | |||
131 | x = 1 |
|
138 | x = 1 | |
@@ -169,7 +176,7 b' import shlex' | |||||
169 | import sys |
|
176 | import sys | |
170 |
|
177 | |||
171 | from IPython.utils.PyColorize import Parser |
|
178 | from IPython.utils.PyColorize import Parser | |
172 | from IPython.utils.genutils import marquee, file_read, file_readlines |
|
179 | from IPython.utils.genutils import marquee, file_read, file_readlines, Term | |
173 |
|
180 | |||
174 | __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] |
|
181 | __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] | |
175 |
|
182 | |||
@@ -185,7 +192,7 b' class Demo(object):' | |||||
185 | re_auto = re_mark('auto') |
|
192 | re_auto = re_mark('auto') | |
186 | re_auto_all = re_mark('auto_all') |
|
193 | re_auto_all = re_mark('auto_all') | |
187 |
|
194 | |||
188 |
def __init__(self, |
|
195 | def __init__(self,src,title='',arg_str='',auto_all=None): | |
189 | """Make a new demo object. To run the demo, simply call the object. |
|
196 | """Make a new demo object. To run the demo, simply call the object. | |
190 |
|
197 | |||
191 | See the module docstring for full details and an example (you can use |
|
198 | See the module docstring for full details and an example (you can use | |
@@ -193,9 +200,14 b' class Demo(object):' | |||||
193 |
|
200 | |||
194 | Inputs: |
|
201 | Inputs: | |
195 |
|
202 | |||
196 | - fname = filename. |
|
203 | - src is either a file, or file-like object, or a | |
|
204 | string that can be resolved to a filename. | |||
197 |
|
205 | |||
198 | Optional inputs: |
|
206 | Optional inputs: | |
|
207 | ||||
|
208 | - title: a string to use as the demo name. Of most use when the demo | |||
|
209 | you are making comes from an object that has no filename, or if you | |||
|
210 | want an alternate denotation distinct from the filename. | |||
199 |
|
211 | |||
200 | - arg_str(''): a string of arguments, internally converted to a list |
|
212 | - arg_str(''): a string of arguments, internally converted to a list | |
201 | just like sys.argv, so the demo script can see a similar |
|
213 | just like sys.argv, so the demo script can see a similar | |
@@ -207,9 +219,24 b' class Demo(object):' | |||||
207 | can be changed at runtime simply by reassigning it to a boolean |
|
219 | can be changed at runtime simply by reassigning it to a boolean | |
208 | value. |
|
220 | value. | |
209 | """ |
|
221 | """ | |
210 |
|
222 | if hasattr(src, "read"): | ||
211 | self.fname = fname |
|
223 | # It seems to be a file or a file-like object | |
212 | self.sys_argv = [fname] + shlex.split(arg_str) |
|
224 | self.fobj = src | |
|
225 | self.fname = "from a file-like object" | |||
|
226 | if title == '': | |||
|
227 | self.title = "from a file-like object" | |||
|
228 | else: | |||
|
229 | self.title = title | |||
|
230 | else: | |||
|
231 | # Assume it's a string or something that can be converted to one | |||
|
232 | self.fobj = open(src) | |||
|
233 | self.fname = src | |||
|
234 | if title == '': | |||
|
235 | (filepath, filename) = os.path.split(src) | |||
|
236 | self.title = filename | |||
|
237 | else: | |||
|
238 | self.title = title | |||
|
239 | self.sys_argv = [src] + shlex.split(arg_str) | |||
213 | self.auto_all = auto_all |
|
240 | self.auto_all = auto_all | |
214 |
|
241 | |||
215 | # get a few things from ipython. While it's a bit ugly design-wise, |
|
242 | # get a few things from ipython. While it's a bit ugly design-wise, | |
@@ -228,7 +255,7 b' class Demo(object):' | |||||
228 | def reload(self): |
|
255 | def reload(self): | |
229 | """Reload source from disk and initialize state.""" |
|
256 | """Reload source from disk and initialize state.""" | |
230 | # read data and parse into blocks |
|
257 | # read data and parse into blocks | |
231 |
self.src = |
|
258 | self.src = self.fobj.read() | |
232 | src_b = [b.strip() for b in self.re_stop.split(self.src) if b] |
|
259 | src_b = [b.strip() for b in self.re_stop.split(self.src) if b] | |
233 | self._silent = [bool(self.re_silent.findall(b)) for b in src_b] |
|
260 | self._silent = [bool(self.re_silent.findall(b)) for b in src_b] | |
234 | self._auto = [bool(self.re_auto.findall(b)) for b in src_b] |
|
261 | self._auto = [bool(self.re_auto.findall(b)) for b in src_b] | |
@@ -277,7 +304,7 b' class Demo(object):' | |||||
277 |
|
304 | |||
278 | if index is None: |
|
305 | if index is None: | |
279 | if self.finished: |
|
306 | if self.finished: | |
280 | print 'Demo finished. Use reset() if you want to rerun it.' |
|
307 | print >>Term.cout, 'Demo finished. Use <demo_name>.reset() if you want to rerun it.' | |
281 | return None |
|
308 | return None | |
282 | index = self.block_index |
|
309 | index = self.block_index | |
283 | else: |
|
310 | else: | |
@@ -346,26 +373,27 b' class Demo(object):' | |||||
346 | if index is None: |
|
373 | if index is None: | |
347 | return |
|
374 | return | |
348 |
|
375 | |||
349 | print self.marquee('<%s> block # %s (%s remaining)' % |
|
376 | print >>Term.cout, self.marquee('<%s> block # %s (%s remaining)' % | |
350 |
(self. |
|
377 | (self.title,index,self.nblocks-index-1)) | |
351 |
|
|
378 | print >>Term.cout,(self.src_blocks_colored[index]) | |
352 | sys.stdout.flush() |
|
379 | sys.stdout.flush() | |
353 |
|
380 | |||
354 | def show_all(self): |
|
381 | def show_all(self): | |
355 | """Show entire demo on screen, block by block""" |
|
382 | """Show entire demo on screen, block by block""" | |
356 |
|
383 | |||
357 |
fname = self. |
|
384 | fname = self.title | |
|
385 | title = self.title | |||
358 | nblocks = self.nblocks |
|
386 | nblocks = self.nblocks | |
359 | silent = self._silent |
|
387 | silent = self._silent | |
360 | marquee = self.marquee |
|
388 | marquee = self.marquee | |
361 | for index,block in enumerate(self.src_blocks_colored): |
|
389 | for index,block in enumerate(self.src_blocks_colored): | |
362 | if silent[index]: |
|
390 | if silent[index]: | |
363 | print marquee('<%s> SILENT block # %s (%s remaining)' % |
|
391 | print >>Term.cout, marquee('<%s> SILENT block # %s (%s remaining)' % | |
364 |
( |
|
392 | (title,index,nblocks-index-1)) | |
365 | else: |
|
393 | else: | |
366 | print marquee('<%s> block # %s (%s remaining)' % |
|
394 | print >>Term.cout, marquee('<%s> block # %s (%s remaining)' % | |
367 |
( |
|
395 | (title,index,nblocks-index-1)) | |
368 | print block, |
|
396 | print >>Term.cout, block, | |
369 | sys.stdout.flush() |
|
397 | sys.stdout.flush() | |
370 |
|
398 | |||
371 | def runlines(self,source): |
|
399 | def runlines(self,source): | |
@@ -390,18 +418,18 b' class Demo(object):' | |||||
390 | next_block = self.src_blocks[index] |
|
418 | next_block = self.src_blocks[index] | |
391 | self.block_index += 1 |
|
419 | self.block_index += 1 | |
392 | if self._silent[index]: |
|
420 | if self._silent[index]: | |
393 | print marquee('Executing silent block # %s (%s remaining)' % |
|
421 | print >>Term.cout, marquee('Executing silent block # %s (%s remaining)' % | |
394 | (index,self.nblocks-index-1)) |
|
422 | (index,self.nblocks-index-1)) | |
395 | else: |
|
423 | else: | |
396 | self.pre_cmd() |
|
424 | self.pre_cmd() | |
397 | self.show(index) |
|
425 | self.show(index) | |
398 | if self.auto_all or self._auto[index]: |
|
426 | if self.auto_all or self._auto[index]: | |
399 | print marquee('output:') |
|
427 | print >>Term.cout, marquee('output:') | |
400 | else: |
|
428 | else: | |
401 | print marquee('Press <q> to quit, <Enter> to execute...'), |
|
429 | print >>Term.cout, marquee('Press <q> to quit, <Enter> to execute...'), | |
402 | ans = raw_input().strip() |
|
430 | ans = raw_input().strip() | |
403 | if ans: |
|
431 | if ans: | |
404 | print marquee('Block NOT executed') |
|
432 | print >>Term.cout, marquee('Block NOT executed') | |
405 | return |
|
433 | return | |
406 | try: |
|
434 | try: | |
407 | save_argv = sys.argv |
|
435 | save_argv = sys.argv | |
@@ -419,10 +447,10 b' class Demo(object):' | |||||
419 | if self.block_index == self.nblocks: |
|
447 | if self.block_index == self.nblocks: | |
420 | mq1 = self.marquee('END OF DEMO') |
|
448 | mq1 = self.marquee('END OF DEMO') | |
421 | if mq1: |
|
449 | if mq1: | |
422 | # avoid spurious prints if empty marquees are used |
|
450 | # avoid spurious print >>Term.cout,s if empty marquees are used | |
423 |
|
451 | print >>Term.cout | ||
424 | print mq1 |
|
452 | print >>Term.cout, mq1 | |
425 | print self.marquee('Use reset() if you want to rerun it.') |
|
453 | print >>Term.cout, self.marquee('Use <demo_name>.reset() if you want to rerun it.') | |
426 | self.finished = True |
|
454 | self.finished = True | |
427 |
|
455 | |||
428 | # These methods are meant to be overridden by subclasses who may wish to |
|
456 | # These methods are meant to be overridden by subclasses who may wish to | |
@@ -471,9 +499,9 b' class LineDemo(Demo):' | |||||
471 | def reload(self): |
|
499 | def reload(self): | |
472 | """Reload source from disk and initialize state.""" |
|
500 | """Reload source from disk and initialize state.""" | |
473 | # read data and parse into blocks |
|
501 | # read data and parse into blocks | |
474 |
src_b = [l for l in |
|
502 | src_b = [l for l in self.fobj.readline() if l.strip()] | |
475 | nblocks = len(src_b) |
|
503 | nblocks = len(src_b) | |
476 |
self.src = os.linesep.join( |
|
504 | self.src = os.linesep.join(self.fobj.readlines()) | |
477 | self._silent = [False]*nblocks |
|
505 | self._silent = [False]*nblocks | |
478 | self._auto = [True]*nblocks |
|
506 | self._auto = [True]*nblocks | |
479 | self.auto_all = True |
|
507 | self.auto_all = True | |
@@ -494,29 +522,29 b' class IPythonLineDemo(IPythonDemo,LineDemo):' | |||||
494 |
|
522 | |||
495 | class ClearMixin(object): |
|
523 | class ClearMixin(object): | |
496 | """Use this mixin to make Demo classes with less visual clutter. |
|
524 | """Use this mixin to make Demo classes with less visual clutter. | |
497 |
|
525 | |||
498 | Demos using this mixin will clear the screen before every block and use |
|
526 | Demos using this mixin will clear the screen before every block and use | |
499 | blank marquees. |
|
527 | blank marquees. | |
500 |
|
528 | |||
501 | Note that in order for the methods defined here to actually override those |
|
529 | Note that in order for the methods defined here to actually override those | |
502 | of the classes it's mixed with, it must go /first/ in the inheritance |
|
530 | of the classes it's mixed with, it must go /first/ in the inheritance | |
503 | tree. For example: |
|
531 | tree. For example: | |
504 |
|
532 | |||
505 | class ClearIPDemo(ClearMixin,IPythonDemo): pass |
|
533 | class ClearIPDemo(ClearMixin,IPythonDemo): pass | |
506 |
|
534 | |||
507 | will provide an IPythonDemo class with the mixin's features. |
|
535 | will provide an IPythonDemo class with the mixin's features. | |
508 | """ |
|
536 | """ | |
509 |
|
537 | |||
510 | def marquee(self,txt='',width=78,mark='*'): |
|
538 | def marquee(self,txt='',width=78,mark='*'): | |
511 | """Blank marquee that returns '' no matter what the input.""" |
|
539 | """Blank marquee that returns '' no matter what the input.""" | |
512 | return '' |
|
540 | return '' | |
513 |
|
541 | |||
514 | def pre_cmd(self): |
|
542 | def pre_cmd(self): | |
515 | """Method called before executing each block. |
|
543 | """Method called before executing each block. | |
516 |
|
544 | |||
517 | This one simply clears the screen.""" |
|
545 | This one simply clears the screen.""" | |
518 | os.system('clear') |
|
546 | from IPython.utils.platutils import term_clear | |
519 |
|
547 | term_clear() | ||
520 |
|
548 | |||
521 | class ClearDemo(ClearMixin,Demo): |
|
549 | class ClearDemo(ClearMixin,Demo): | |
522 | pass |
|
550 | pass |
@@ -45,10 +45,10 b' def skipif(skip_condition=True, msg=None):' | |||||
45 | Parameters |
|
45 | Parameters | |
46 | ---------- |
|
46 | ---------- | |
47 | skip_condition : bool or callable. |
|
47 | skip_condition : bool or callable. | |
48 |
|
|
48 | Flag to determine whether to skip test. If the condition is a | |
49 |
|
|
49 | callable, it is used at runtime to dynamically make the decision. This | |
50 |
|
|
50 | is useful for tests that may require costly imports, to delay the cost | |
51 |
|
|
51 | until the test suite is actually executed. | |
52 | msg : string |
|
52 | msg : string | |
53 | Message to give on raising a SkipTest exception |
|
53 | Message to give on raising a SkipTest exception | |
54 |
|
54 |
@@ -24,6 +24,7 b' import os' | |||||
24 | import os.path as path |
|
24 | import os.path as path | |
25 | import sys |
|
25 | import sys | |
26 | import subprocess |
|
26 | import subprocess | |
|
27 | import tempfile | |||
27 | import time |
|
28 | import time | |
28 | import warnings |
|
29 | import warnings | |
29 |
|
30 | |||
@@ -50,6 +51,7 b' def test_for(mod):' | |||||
50 |
|
51 | |||
51 | have_curses = test_for('_curses') |
|
52 | have_curses = test_for('_curses') | |
52 | have_wx = test_for('wx') |
|
53 | have_wx = test_for('wx') | |
|
54 | have_wx_aui = test_for('wx.aui') | |||
53 | have_zi = test_for('zope.interface') |
|
55 | have_zi = test_for('zope.interface') | |
54 | have_twisted = test_for('twisted') |
|
56 | have_twisted = test_for('twisted') | |
55 | have_foolscap = test_for('foolscap') |
|
57 | have_foolscap = test_for('foolscap') | |
@@ -69,8 +71,9 b' def make_exclude():' | |||||
69 | pjoin('IPython', 'frontend', 'process', 'winprocess.py'), |
|
71 | pjoin('IPython', 'frontend', 'process', 'winprocess.py'), | |
70 | pjoin('IPython_doctest_plugin'), |
|
72 | pjoin('IPython_doctest_plugin'), | |
71 | pjoin('IPython', 'extensions', 'ipy_'), |
|
73 | pjoin('IPython', 'extensions', 'ipy_'), | |
72 |
pjoin('IPython', 'extensions', ' |
|
74 | pjoin('IPython', 'extensions', 'PhysicalQInput'), | |
73 | pjoin('IPython', 'extensions', 'PhysicalQInteractive'), |
|
75 | pjoin('IPython', 'extensions', 'PhysicalQInteractive'), | |
|
76 | pjoin('IPython', 'extensions', 'InterpreterPasteInput'), | |||
74 | pjoin('IPython', 'extensions', 'scitedirector'), |
|
77 | pjoin('IPython', 'extensions', 'scitedirector'), | |
75 | pjoin('IPython', 'extensions', 'numeric_formats'), |
|
78 | pjoin('IPython', 'extensions', 'numeric_formats'), | |
76 | pjoin('IPython', 'testing', 'attic'), |
|
79 | pjoin('IPython', 'testing', 'attic'), | |
@@ -88,6 +91,9 b' def make_exclude():' | |||||
88 | if not have_gtk or not have_gobject: |
|
91 | if not have_gtk or not have_gobject: | |
89 | EXCLUDE.append(pjoin('IPython', 'lib', 'inputhookgtk')) |
|
92 | EXCLUDE.append(pjoin('IPython', 'lib', 'inputhookgtk')) | |
90 |
|
93 | |||
|
94 | if not have_wx_aui: | |||
|
95 | EXCLUDE.append(pjoin('IPython', 'gui', 'wx', 'wxIPython')) | |||
|
96 | ||||
91 | if not have_objc: |
|
97 | if not have_objc: | |
92 | EXCLUDE.append(pjoin('IPython', 'frontend', 'cocoa')) |
|
98 | EXCLUDE.append(pjoin('IPython', 'frontend', 'cocoa')) | |
93 |
|
99 | |||
@@ -109,6 +115,27 b' def make_exclude():' | |||||
109 | if not have_pexpect: |
|
115 | if not have_pexpect: | |
110 | EXCLUDE.append(pjoin('IPython', 'scripts', 'irunner')) |
|
116 | EXCLUDE.append(pjoin('IPython', 'scripts', 'irunner')) | |
111 |
|
117 | |||
|
118 | # This is scary. We still have things in frontend and testing that | |||
|
119 | # are being tested by nose that use twisted. We need to rethink | |||
|
120 | # how we are isolating dependencies in testing. | |||
|
121 | if not (have_twisted and have_zi and have_foolscap): | |||
|
122 | EXCLUDE.append(pjoin('IPython', 'frontend', 'asyncfrontendbase')) | |||
|
123 | EXCLUDE.append(pjoin('IPython', 'frontend', 'prefilterfrontend')) | |||
|
124 | EXCLUDE.append(pjoin('IPython', 'frontend', 'frontendbase')) | |||
|
125 | EXCLUDE.append(pjoin('IPython', 'frontend', 'linefrontendbase')) | |||
|
126 | EXCLUDE.append(pjoin('IPython', 'frontend', 'tests', | |||
|
127 | 'test_linefrontend')) | |||
|
128 | EXCLUDE.append(pjoin('IPython', 'frontend', 'tests', | |||
|
129 | 'test_frontendbase')) | |||
|
130 | EXCLUDE.append(pjoin('IPython', 'frontend', 'tests', | |||
|
131 | 'test_prefilterfrontend')) | |||
|
132 | EXCLUDE.append(pjoin('IPython', 'frontend', 'tests', | |||
|
133 | 'test_asyncfrontendbase')), | |||
|
134 | EXCLUDE.append(pjoin('IPython', 'testing', 'parametric')) | |||
|
135 | EXCLUDE.append(pjoin('IPython', 'testing', 'util')) | |||
|
136 | EXCLUDE.append(pjoin('IPython', 'testing', 'tests', | |||
|
137 | 'test_decorators_trial')) | |||
|
138 | ||||
112 | # Skip shell always because of a bug in FakeModule. |
|
139 | # Skip shell always because of a bug in FakeModule. | |
113 | EXCLUDE.append(pjoin('IPython', 'core', 'shell')) |
|
140 | EXCLUDE.append(pjoin('IPython', 'core', 'shell')) | |
114 |
|
141 | |||
@@ -118,6 +145,7 b' def make_exclude():' | |||||
118 |
|
145 | |||
119 | return EXCLUDE |
|
146 | return EXCLUDE | |
120 |
|
147 | |||
|
148 | ||||
121 | #----------------------------------------------------------------------------- |
|
149 | #----------------------------------------------------------------------------- | |
122 | # Functions and classes |
|
150 | # Functions and classes | |
123 | #----------------------------------------------------------------------------- |
|
151 | #----------------------------------------------------------------------------- | |
@@ -196,9 +224,29 b' class IPTester(object):' | |||||
196 | # Assemble call |
|
224 | # Assemble call | |
197 | self.call_args = self.runner+self.params |
|
225 | self.call_args = self.runner+self.params | |
198 |
|
226 | |||
199 | def run(self): |
|
227 | if sys.platform == 'win32': | |
200 | """Run the stored commands""" |
|
228 | def run(self): | |
201 | return subprocess.call(self.call_args) |
|
229 | """Run the stored commands""" | |
|
230 | # On Windows, cd to temporary directory to run tests. Otherwise, | |||
|
231 | # Twisted's trial may not be able to execute 'trial IPython', since | |||
|
232 | # it will confuse the IPython module name with the ipython | |||
|
233 | # execution scripts, because the windows file system isn't case | |||
|
234 | # sensitive. | |||
|
235 | # We also use os.system instead of subprocess.call, because I was | |||
|
236 | # having problems with subprocess and I just don't know enough | |||
|
237 | # about win32 to debug this reliably. Os.system may be the 'old | |||
|
238 | # fashioned' way to do it, but it works just fine. If someone | |||
|
239 | # later can clean this up that's fine, as long as the tests run | |||
|
240 | # reliably in win32. | |||
|
241 | curdir = os.getcwd() | |||
|
242 | os.chdir(tempfile.gettempdir()) | |||
|
243 | stat = os.system(' '.join(self.call_args)) | |||
|
244 | os.chdir(curdir) | |||
|
245 | return stat | |||
|
246 | else: | |||
|
247 | def run(self): | |||
|
248 | """Run the stored commands""" | |||
|
249 | return subprocess.call(self.call_args) | |||
202 |
|
250 | |||
203 |
|
251 | |||
204 | def make_runners(): |
|
252 | def make_runners(): | |
@@ -244,7 +292,7 b' def run_iptestall():' | |||||
244 | t_start = time.time() |
|
292 | t_start = time.time() | |
245 | for name,runner in runners.iteritems(): |
|
293 | for name,runner in runners.iteritems(): | |
246 | print '*'*77 |
|
294 | print '*'*77 | |
247 |
print 'IPython test |
|
295 | print 'IPython test group:',name | |
248 | res = runner.run() |
|
296 | res = runner.run() | |
249 | if res: |
|
297 | if res: | |
250 | failed[name] = res |
|
298 | failed[name] = res | |
@@ -255,14 +303,14 b' def run_iptestall():' | |||||
255 | # summarize results |
|
303 | # summarize results | |
256 |
|
304 | |||
257 | print '*'*77 |
|
305 | print '*'*77 | |
258 |
print 'Ran %s test |
|
306 | print 'Ran %s test groups in %.3fs' % (nrunners, t_tests) | |
259 |
|
307 | |||
260 | if not failed: |
|
308 | if not failed: | |
261 | print 'OK' |
|
309 | print 'OK' | |
262 | else: |
|
310 | else: | |
263 | # If anything went wrong, point out what command to rerun manually to |
|
311 | # If anything went wrong, point out what command to rerun manually to | |
264 | # see the actual errors and individual summary |
|
312 | # see the actual errors and individual summary | |
265 |
print 'ERROR - %s out of %s test |
|
313 | print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners) | |
266 | for name in failed: |
|
314 | for name in failed: | |
267 | failed_runner = runners[name] |
|
315 | failed_runner = runners[name] | |
268 | print '-'*40 |
|
316 | print '-'*40 | |
@@ -283,4 +331,4 b' def main():' | |||||
283 |
|
331 | |||
284 |
|
332 | |||
285 | if __name__ == '__main__': |
|
333 | if __name__ == '__main__': | |
286 | main() No newline at end of file |
|
334 | main() |
@@ -208,6 +208,15 b' def start_ipython():' | |||||
208 | _ip.IP.magic_run_ori = _ip.IP.magic_run |
|
208 | _ip.IP.magic_run_ori = _ip.IP.magic_run | |
209 | _ip.IP.magic_run = im |
|
209 | _ip.IP.magic_run = im | |
210 |
|
210 | |||
|
211 | # XXX - For some very bizarre reason, the loading of %history by default is | |||
|
212 | # failing. This needs to be fixed later, but for now at least this ensures | |||
|
213 | # that tests that use %hist run to completion. | |||
|
214 | from IPython.core import history | |||
|
215 | history.init_ipython(_ip) | |||
|
216 | if not hasattr(_ip.IP,'magic_history'): | |||
|
217 | raise RuntimeError("Can't load magics, aborting") | |||
|
218 | ||||
|
219 | ||||
211 | # The start call MUST be made here. I'm not sure yet why it doesn't work if |
|
220 | # The start call MUST be made here. I'm not sure yet why it doesn't work if | |
212 | # it is made later, at plugin initialization time, but in all my tests, that's |
|
221 | # it is made later, at plugin initialization time, but in all my tests, that's | |
213 | # the case. |
|
222 | # the case. | |
@@ -431,7 +440,29 b' class DocTestCase(doctests.DocTestCase):' | |||||
431 | _ip.IP.user_ns.update(self._dt_test.globs) |
|
440 | _ip.IP.user_ns.update(self._dt_test.globs) | |
432 | self._dt_test.globs = _ip.IP.user_ns |
|
441 | self._dt_test.globs = _ip.IP.user_ns | |
433 |
|
442 | |||
434 |
|
|
443 | super(DocTestCase, self).setUp() | |
|
444 | ||||
|
445 | def tearDown(self): | |||
|
446 | # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but | |||
|
447 | # it does look like one to me: its tearDown method tries to run | |||
|
448 | # | |||
|
449 | # delattr(__builtin__, self._result_var) | |||
|
450 | # | |||
|
451 | # without checking that the attribute really is there; it implicitly | |||
|
452 | # assumes it should have been set via displayhook. But if the | |||
|
453 | # displayhook was never called, this doesn't necessarily happen. I | |||
|
454 | # haven't been able to find a little self-contained example outside of | |||
|
455 | # ipython that would show the problem so I can report it to the nose | |||
|
456 | # team, but it does happen a lot in our code. | |||
|
457 | # | |||
|
458 | # So here, we just protect as narrowly as possible by trapping an | |||
|
459 | # attribute error whose message would be the name of self._result_var, | |||
|
460 | # and letting any other error propagate. | |||
|
461 | try: | |||
|
462 | super(DocTestCase, self).tearDown() | |||
|
463 | except AttributeError, exc: | |||
|
464 | if exc.args[0] != self._result_var: | |||
|
465 | raise | |||
435 |
|
466 | |||
436 |
|
467 | |||
437 | # A simple subclassing of the original with a different class name, so we can |
|
468 | # A simple subclassing of the original with a different class name, so we can |
@@ -10,9 +10,10 b' class C(object):' | |||||
10 | pass |
|
10 | pass | |
11 | #print 'deleting object...' # dbg |
|
11 | #print 'deleting object...' # dbg | |
12 |
|
12 | |||
13 | c = C() |
|
13 | if __name__ == '__main__': | |
|
14 | c = C() | |||
14 |
|
15 | |||
15 | c_refs = gc.get_referrers(c) |
|
16 | c_refs = gc.get_referrers(c) | |
16 | ref_ids = map(id,c_refs) |
|
17 | ref_ids = map(id,c_refs) | |
17 |
|
18 | |||
18 | print 'c referrers:',map(type,c_refs) |
|
19 | print 'c referrers:',map(type,c_refs) |
@@ -21,7 +21,7 b' from twisted.internet import defer' | |||||
21 | class DeferredTestCase(unittest.TestCase): |
|
21 | class DeferredTestCase(unittest.TestCase): | |
22 |
|
22 | |||
23 | def assertDeferredEquals(self, deferred, expectedResult, |
|
23 | def assertDeferredEquals(self, deferred, expectedResult, | |
24 |
|
|
24 | chainDeferred=None): | |
25 | """Calls assertEquals on the result of the deferred and expectedResult. |
|
25 | """Calls assertEquals on the result of the deferred and expectedResult. | |
26 |
|
26 | |||
27 | chainDeferred can be used to pass in previous Deferred objects that |
|
27 | chainDeferred can be used to pass in previous Deferred objects that | |
@@ -32,7 +32,7 b' class DeferredTestCase(unittest.TestCase):' | |||||
32 |
|
32 | |||
33 | if chainDeferred is None: |
|
33 | if chainDeferred is None: | |
34 | chainDeferred = defer.succeed(None) |
|
34 | chainDeferred = defer.succeed(None) | |
35 |
|
|
35 | ||
36 | def gotResult(actualResult): |
|
36 | def gotResult(actualResult): | |
37 | self.assertEquals(actualResult, expectedResult) |
|
37 | self.assertEquals(actualResult, expectedResult) | |
38 |
|
38 | |||
@@ -41,7 +41,7 b' class DeferredTestCase(unittest.TestCase):' | |||||
41 | return chainDeferred.addCallback(lambda _: deferred) |
|
41 | return chainDeferred.addCallback(lambda _: deferred) | |
42 |
|
42 | |||
43 | def assertDeferredRaises(self, deferred, expectedException, |
|
43 | def assertDeferredRaises(self, deferred, expectedException, | |
44 |
|
|
44 | chainDeferred=None): | |
45 | """Calls assertRaises on the Failure of the deferred and expectedException. |
|
45 | """Calls assertRaises on the Failure of the deferred and expectedException. | |
46 |
|
46 | |||
47 | chainDeferred can be used to pass in previous Deferred objects that |
|
47 | chainDeferred can be used to pass in previous Deferred objects that |
@@ -881,7 +881,7 b' def doctest_reload():' | |||||
881 |
|
881 | |||
882 | This routine: |
|
882 | This routine: | |
883 |
|
883 | |||
884 | - reloads doctest |
|
884 | - imports doctest but does NOT reload it (see below). | |
885 |
|
885 | |||
886 | - resets its global 'master' attribute to None, so that multiple uses of |
|
886 | - resets its global 'master' attribute to None, so that multiple uses of | |
887 | the module interactively don't produce cumulative reports. |
|
887 | the module interactively don't produce cumulative reports. | |
@@ -890,20 +890,20 b' def doctest_reload():' | |||||
890 | modified displayhook. Doctest expects the default displayhook behavior |
|
890 | modified displayhook. Doctest expects the default displayhook behavior | |
891 | deep down, so our modification breaks it completely. For this reason, a |
|
891 | deep down, so our modification breaks it completely. For this reason, a | |
892 | hard monkeypatch seems like a reasonable solution rather than asking |
|
892 | hard monkeypatch seems like a reasonable solution rather than asking | |
893 |
users to manually use a different doctest runner when under IPython. |
|
893 | users to manually use a different doctest runner when under IPython. | |
894 |
|
|
894 | ||
895 | import doctest |
|
895 | Notes | |
896 | reload(doctest) |
|
896 | ----- | |
897 | doctest.master=None |
|
|||
898 |
|
|
897 | ||
899 | try: |
|
898 | This function *used to* reload doctest, but this has been disabled because | |
900 | doctest.DocTestRunner |
|
899 | reloading doctest unconditionally can cause massive breakage of other | |
901 | except AttributeError: |
|
900 | doctest-dependent modules already in memory, such as those for IPython's | |
902 | # This is only for python 2.3 compatibility, remove once we move to |
|
901 | own testing system. The name wasn't changed to avoid breaking people's | |
903 | # 2.4 only. |
|
902 | code, but the reload call isn't actually made anymore.""" | |
904 | pass |
|
903 | ||
905 | else: |
|
904 | import doctest | |
906 | doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run) |
|
905 | doctest.master = None | |
|
906 | doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run) | |||
907 |
|
907 | |||
908 | #---------------------------------------------------------------------------- |
|
908 | #---------------------------------------------------------------------------- | |
909 | class HomeDirError(Error): |
|
909 | class HomeDirError(Error): |
@@ -23,11 +23,6 b" elif sys.platform == 'win32':" | |||||
23 | import platutils_win32 as _platutils |
|
23 | import platutils_win32 as _platutils | |
24 | else: |
|
24 | else: | |
25 | import platutils_dummy as _platutils |
|
25 | import platutils_dummy as _platutils | |
26 | import warnings |
|
|||
27 | warnings.warn("Platutils not available for platform '%s', some features may be missing" % |
|
|||
28 | os.name) |
|
|||
29 | del warnings |
|
|||
30 |
|
||||
31 |
|
26 | |||
32 | # Functionality that's logically common to all platforms goes here, each |
|
27 | # Functionality that's logically common to all platforms goes here, each | |
33 | # platform-specific module only provides the bits that are OS-dependent. |
|
28 | # platform-specific module only provides the bits that are OS-dependent. | |
@@ -36,6 +31,9 b' else:' | |||||
36 | # there is a public, cross-platform way of toggling the term title control on |
|
31 | # there is a public, cross-platform way of toggling the term title control on | |
37 | # and off. We should make this a stateful object later on so that each user |
|
32 | # and off. We should make this a stateful object later on so that each user | |
38 | # can have its own instance if needed. |
|
33 | # can have its own instance if needed. | |
|
34 | def term_clear(): | |||
|
35 | _platutils.term_clear() | |||
|
36 | ||||
39 | def toggle_set_term_title(val): |
|
37 | def toggle_set_term_title(val): | |
40 | """Control whether set_term_title is active or not. |
|
38 | """Control whether set_term_title is active or not. | |
41 |
|
39 | |||
@@ -103,4 +101,3 b' def get_long_path_name(path):' | |||||
103 | def freeze_term_title(): |
|
101 | def freeze_term_title(): | |
104 | warnings.warn("This function is deprecated, use toggle_set_term_title()") |
|
102 | warnings.warn("This function is deprecated, use toggle_set_term_title()") | |
105 | _platutils.ignore_termtitle = True |
|
103 | _platutils.ignore_termtitle = True | |
106 |
|
@@ -20,6 +20,7 b' ignore_termtitle = True' | |||||
20 | def _dummy_op(*a, **b): |
|
20 | def _dummy_op(*a, **b): | |
21 | """ A no-op function """ |
|
21 | """ A no-op function """ | |
22 |
|
22 | |||
|
23 | ||||
23 | def _set_term_title_xterm(title): |
|
24 | def _set_term_title_xterm(title): | |
24 | """ Change virtual terminal title in xterm-workalikes """ |
|
25 | """ Change virtual terminal title in xterm-workalikes """ | |
25 |
|
26 | |||
@@ -31,10 +32,16 b" if os.environ.get('TERM','') == 'xterm':" | |||||
31 | else: |
|
32 | else: | |
32 | set_term_title = _dummy_op |
|
33 | set_term_title = _dummy_op | |
33 |
|
34 | |||
|
35 | ||||
34 | def find_cmd(cmd): |
|
36 | def find_cmd(cmd): | |
35 | """Find the full path to a command using which.""" |
|
37 | """Find the full path to a command using which.""" | |
36 | return os.popen('which %s' % cmd).read().strip() |
|
38 | return os.popen('which %s' % cmd).read().strip() | |
37 |
|
39 | |||
|
40 | ||||
38 | def get_long_path_name(path): |
|
41 | def get_long_path_name(path): | |
39 | """Dummy no-op.""" |
|
42 | """Dummy no-op.""" | |
40 | return path |
|
43 | return path | |
|
44 | ||||
|
45 | ||||
|
46 | def term_clear(): | |||
|
47 | os.system('clear') |
@@ -42,18 +42,26 b' except ImportError:' | |||||
42 | # non-zero return code signals error, don't try again |
|
42 | # non-zero return code signals error, don't try again | |
43 | ignore_termtitle = True |
|
43 | ignore_termtitle = True | |
44 |
|
44 | |||
|
45 | ||||
45 | def find_cmd(cmd): |
|
46 | def find_cmd(cmd): | |
46 | """Find the full path to a .bat or .exe using the win32api module.""" |
|
47 | """Find the full path to a .bat or .exe using the win32api module.""" | |
47 | try: |
|
48 | try: | |
48 | import win32api |
|
49 | from win32api import SearchPath | |
49 | except ImportError: |
|
50 | except ImportError: | |
50 | raise ImportError('you need to have pywin32 installed for this to work') |
|
51 | raise ImportError('you need to have pywin32 installed for this to work') | |
51 | else: |
|
52 | else: | |
52 | try: |
|
53 | PATH = os.environ['PATH'] | |
53 | (path, offest) = win32api.SearchPath(os.environ['PATH'],cmd + '.exe') |
|
54 | extensions = ['.exe', '.com', '.bat', '.py'] | |
54 | except: |
|
55 | path = None | |
55 | (path, offset) = win32api.SearchPath(os.environ['PATH'],cmd + '.bat') |
|
56 | for ext in extensions: | |
56 | return path |
|
57 | try: | |
|
58 | path = SearchPath(PATH,cmd + ext)[0] | |||
|
59 | except: | |||
|
60 | pass | |||
|
61 | if path is None: | |||
|
62 | raise OSError("command %r not found" % cmd) | |||
|
63 | else: | |||
|
64 | return path | |||
57 |
|
65 | |||
58 |
|
66 | |||
59 | def get_long_path_name(path): |
|
67 | def get_long_path_name(path): | |
@@ -80,3 +88,7 b' def get_long_path_name(path):' | |||||
80 | return path |
|
88 | return path | |
81 | else: |
|
89 | else: | |
82 | return buf.value |
|
90 | return buf.value | |
|
91 | ||||
|
92 | ||||
|
93 | def term_clear(): | |||
|
94 | os.system('cls') |
@@ -3,6 +3,8 b'' | |||||
3 |
|
3 | |||
4 | from IPython.kernel import client |
|
4 | from IPython.kernel import client | |
5 | import time |
|
5 | import time | |
|
6 | import sys | |||
|
7 | flush = sys.stdout.flush | |||
6 |
|
8 | |||
7 | tc = client.TaskClient() |
|
9 | tc = client.TaskClient() | |
8 | mec = client.MultiEngineClient() |
|
10 | mec = client.MultiEngineClient() | |
@@ -16,6 +18,7 b' for i in range(6):' | |||||
16 | time.sleep(1.0) |
|
18 | time.sleep(1.0) | |
17 | print "Queue status (vebose=False)" |
|
19 | print "Queue status (vebose=False)" | |
18 | print tc.queue_status() |
|
20 | print tc.queue_status() | |
|
21 | flush() | |||
19 |
|
22 | |||
20 | for i in range(24): |
|
23 | for i in range(24): | |
21 | tc.run(client.StringTask('time.sleep(1)')) |
|
24 | tc.run(client.StringTask('time.sleep(1)')) | |
@@ -24,12 +27,14 b' for i in range(6):' | |||||
24 | time.sleep(1.0) |
|
27 | time.sleep(1.0) | |
25 | print "Queue status (vebose=True)" |
|
28 | print "Queue status (vebose=True)" | |
26 | print tc.queue_status(True) |
|
29 | print tc.queue_status(True) | |
|
30 | flush() | |||
27 |
|
31 | |||
28 | for i in range(12): |
|
32 | for i in range(12): | |
29 | tc.run(client.StringTask('time.sleep(2)')) |
|
33 | tc.run(client.StringTask('time.sleep(2)')) | |
30 |
|
34 | |||
31 | print "Queue status (vebose=True)" |
|
35 | print "Queue status (vebose=True)" | |
32 | print tc.queue_status(True) |
|
36 | print tc.queue_status(True) | |
|
37 | flush() | |||
33 |
|
38 | |||
34 | qs = tc.queue_status(True) |
|
39 | qs = tc.queue_status(True) | |
35 | sched = qs['scheduled'] |
|
40 | sched = qs['scheduled'] | |
@@ -41,4 +46,5 b' for i in range(6):' | |||||
41 | time.sleep(1.0) |
|
46 | time.sleep(1.0) | |
42 | print "Queue status (vebose=True)" |
|
47 | print "Queue status (vebose=True)" | |
43 | print tc.queue_status(True) |
|
48 | print tc.queue_status(True) | |
|
49 | flush() | |||
44 |
|
50 |
@@ -1,3 +1,11 b'' | |||||
|
1 | .. Developers should add in this file, during each release cycle, information | |||
|
2 | .. about important changes they've made, in a summary format that's meant for | |||
|
3 | .. end users. For each release we normally have three sections: features, bug | |||
|
4 | .. fixes and api breakage. | |||
|
5 | .. Please remember to credit the authors of the contributions by name, | |||
|
6 | .. especially when they are new users or developers who do not regularly | |||
|
7 | .. participate in IPython's development. | |||
|
8 | ||||
1 | .. _changes: |
|
9 | .. _changes: | |
2 |
|
10 | |||
3 | ========== |
|
11 | ========== | |
@@ -6,19 +14,27 b" What's new" | |||||
6 |
|
14 | |||
7 | .. contents:: |
|
15 | .. contents:: | |
8 | .. |
|
16 | .. | |
9 |
1 Release |
|
17 | 1 Release dev | |
10 | 2 Release 0.9 |
|
18 | 1.1 New features | |
|
19 | 1.2 Bug fixes | |||
|
20 | 1.3 Backwards incompatible changes | |||
|
21 | 2 Release 0.10 | |||
11 | 2.1 New features |
|
22 | 2.1 New features | |
12 | 2.2 Bug fixes |
|
23 | 2.2 Bug fixes | |
13 | 2.3 Backwards incompatible changes |
|
24 | 2.3 Backwards incompatible changes | |
14 | 2.4 Changes merged in from IPython1 |
|
25 | 3 Release 0.9.1 | |
15 | 2.4.1 New features |
|
26 | 4 Release 0.9 | |
16 | 2.4.2 Bug fixes |
|
27 | 4.1 New features | |
17 | 2.4.3 Backwards incompatible changes |
|
28 | 4.2 Bug fixes | |
18 | 3 Release 0.8.4 |
|
29 | 4.3 Backwards incompatible changes | |
19 | 4 Release 0.8.3 |
|
30 | 4.4 Changes merged in from IPython1 | |
20 | 5 Release 0.8.2 |
|
31 | 4.4.1 New features | |
21 | 6 Older releases |
|
32 | 4.4.2 Bug fixes | |
|
33 | 4.4.3 Backwards incompatible changes | |||
|
34 | 5 Release 0.8.4 | |||
|
35 | 6 Release 0.8.3 | |||
|
36 | 7 Release 0.8.2 | |||
|
37 | 8 Older releases | |||
22 | .. |
|
38 | .. | |
23 |
|
39 | |||
24 | Release dev |
|
40 | Release dev | |
@@ -27,25 +43,139 b' Release dev' | |||||
27 | New features |
|
43 | New features | |
28 | ------------ |
|
44 | ------------ | |
29 |
|
45 | |||
|
46 | Bug fixes | |||
|
47 | --------- | |||
|
48 | ||||
|
49 | Backwards incompatible changes | |||
|
50 | ------------------------------ | |||
|
51 | ||||
|
52 | ||||
|
53 | Release 0.10 | |||
|
54 | ============ | |||
|
55 | ||||
|
56 | This release brings months of slow but steady development, and will be the last | |||
|
57 | before a major restructuring and cleanup of IPython's internals that is already | |||
|
58 | under way. For this reason, we hope that 0.10 will be a stable and robust | |||
|
59 | release so that while users adapt to some of the API changes that will come | |||
|
60 | with the refactoring that will become IPython 0.11, they can safely use 0.10 in | |||
|
61 | all existing projects with minimal changes (if any). | |||
|
62 | ||||
|
63 | IPython 0.10 is now a medium-sized project, with roughly (as reported by David | |||
|
64 | Wheeler's :command:`sloccount` utility) 40750 lines of Python code, and a diff | |||
|
65 | between 0.9.1 and this release that contains almost 28000 lines of code and | |||
|
66 | documentation. Our documentation, in PDF format, is a 495-page long PDF | |||
|
67 | document (also available in HTML format, both generated from the same sources). | |||
|
68 | ||||
|
69 | Many users and developers contributed code, features, bug reports and ideas to | |||
|
70 | this release. Please do not hesitate in contacting us if we've failed to | |||
|
71 | acknowledge your contribution here. In particular, for this release we have | |||
|
72 | contribution from the following people, a mix of new and regular names (in | |||
|
73 | alphabetical order by first name): | |||
|
74 | ||||
|
75 | * Alexander Clausen: fix #341726. | |||
|
76 | * Brian Granger: lots of work everywhere (features, bug fixes, etc). | |||
|
77 | * Daniel Ashbrook: bug report on MemoryError during compilation, now fixed. | |||
|
78 | * Darren Dale: improvements to documentation build system, feedback, design | |||
|
79 | ideas. | |||
|
80 | * Fernando Perez: various places. | |||
|
81 | * Gaël Varoquaux: core code, ipythonx GUI, design discussions, etc. Lots... | |||
|
82 | * John Hunter: suggestions, bug fixes, feedback. | |||
|
83 | * Jorgen Stenarson: work on many fronts, tests, fixes, win32 support, etc. | |||
|
84 | * Laurent Dufréchou: many improvements to ipython-wx standalone app. | |||
|
85 | * Lukasz Pankowski: prefilter, `%edit`, demo improvements. | |||
|
86 | * Matt Foster: TextMate support in `%edit`. | |||
|
87 | * Nathaniel Smith: fix #237073. | |||
|
88 | * Pauli Virtanen: fixes and improvements to extensions, documentation. | |||
|
89 | * Prabhu Ramachandran: improvements to `%timeit`. | |||
|
90 | * Robert Kern: several extensions. | |||
|
91 | * Sameer D'Costa: help on critical bug #269966. | |||
|
92 | * Stephan Peijnik: feedback on Debian compliance and many man pages. | |||
|
93 | * Tom Fetherston: many improvements to :mod:`IPython.demo` module. | |||
|
94 | * Ville Vainio: lots of work everywhere (features, bug fixes, etc). | |||
|
95 | * Vishal Vasta: ssh support in ipcluster. | |||
|
96 | * Walter Doerwald: work on the :mod:`IPython.ipipe` system. | |||
|
97 | ||||
|
98 | Below we give an overview of new features, bug fixes and backwards-incompatible | |||
|
99 | changes. For a detailed account of every change made, feel free to view the | |||
|
100 | project log with :command:`bzr log`. | |||
|
101 | ||||
|
102 | New features | |||
|
103 | ------------ | |||
|
104 | ||||
|
105 | * New `%paste` magic automatically extracts current contents of clipboard and | |||
|
106 | pastes it directly, while correctly handling code that is indented or | |||
|
107 | prepended with `>>>` or `...` python prompt markers. A very useful new | |||
|
108 | feature contributed by Robert Kern. | |||
|
109 | ||||
|
110 | * IPython 'demos', created with the :mod:`IPython.demo` module, can now be | |||
|
111 | created from files on disk or strings in memory. Other fixes and | |||
|
112 | improvements to the demo system, by Tom Fetherston. | |||
|
113 | ||||
|
114 | * Added :func:`find_cmd` function to :mod:`IPython.platutils` module, to find | |||
|
115 | commands in a cross-platform manner. | |||
|
116 | ||||
|
117 | * Many improvements and fixes to Gaël Varoquaux's :command:`ipythonx`, a | |||
|
118 | WX-based lightweight IPython instance that can be easily embedded in other WX | |||
|
119 | applications. These improvements have made it possible to now have an | |||
|
120 | embedded IPython in Mayavi and other tools. | |||
|
121 | ||||
|
122 | * :class:`MultiengineClient` objects now have a :meth:`benchmark` method. | |||
|
123 | ||||
|
124 | * The manual now includes a full set of auto-generated API documents from the | |||
|
125 | code sources, using Sphinx and some of our own support code. We are now | |||
|
126 | using the `Numpy Documentation Standard`_ for all docstrings, and we have | |||
|
127 | tried to update as many existing ones as possible to this format. | |||
|
128 | ||||
|
129 | .. _Numpy Documentation Standard: http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard | |||
|
130 | ||||
|
131 | * The new :mod:`IPython.Extensions.ipy_pretty` extension by Robert Kern | |||
|
132 | provides configurable pretty-printing. | |||
|
133 | ||||
|
134 | * Many improvements to the :command:`ipython-wx` standalone WX-based IPython | |||
|
135 | application by Laurent Dufréchou. It can optionally run in a thread, and | |||
|
136 | this can be toggled at runtime (allowing the loading of Matplotlib in a | |||
|
137 | running session without ill effects). | |||
|
138 | ||||
|
139 | * IPython includes a copy of Steven Bethard's argparse_ in the | |||
|
140 | :mod:`IPython.external` package, so we can use it internally and it is also | |||
|
141 | available to any IPython user. By installing it in this manner, we ensure | |||
|
142 | zero conflicts with any system-wide installation you may already have while | |||
|
143 | minimizing external dependencies for new users. | |||
|
144 | ||||
|
145 | * An improved and much more robust test suite, that runs groups of tests in | |||
|
146 | separate subprocesses using either Nose or Twisted's :command:`trial` runner | |||
|
147 | to ensure proper management of Twisted-using code. The test suite degrades | |||
|
148 | gracefully if optional dependencies are not available, so that the | |||
|
149 | :command:`iptest` command can be run with only Nose installed and nothing | |||
|
150 | else. We also have more and cleaner test decorators to better select tests | |||
|
151 | depending on runtime conditions, do setup/teardown, etc. | |||
|
152 | ||||
30 | * The new ipcluster now has a fully working ssh mode that should work on |
|
153 | * The new ipcluster now has a fully working ssh mode that should work on | |
31 | Linux, Unix and OS X. Thanks to Vishal Vatsa for implementing this! |
|
154 | Linux, Unix and OS X. Thanks to Vishal Vatsa for implementing this! | |
32 |
|
155 | |||
33 | * The wonderful TextMate editor can now be used with %edit on OS X. Thanks |
|
156 | * The wonderful TextMate editor can now be used with %edit on OS X. Thanks | |
34 | to Matt Foster for this patch. |
|
157 | to Matt Foster for this patch. | |
35 |
|
158 | |||
|
159 | * The documentation regarding parallel uses of IPython, including MPI and PBS, | |||
|
160 | has been significantly updated and improved. | |||
|
161 | ||||
|
162 | * The developer guidelines in the documentation have been updated to explain | |||
|
163 | our workflow using :command:`bzr` and Launchpad. | |||
|
164 | ||||
36 | * Fully refactored :command:`ipcluster` command line program for starting |
|
165 | * Fully refactored :command:`ipcluster` command line program for starting | |
37 | IPython clusters. This new version is a complete rewrite and 1) is fully |
|
166 | IPython clusters. This new version is a complete rewrite and 1) is fully | |
38 | cross platform (we now use Twisted's process management), 2) has much |
|
167 | cross platform (we now use Twisted's process management), 2) has much | |
39 | improved performance, 3) uses subcommands for different types of clusters, |
|
168 | improved performance, 3) uses subcommands for different types of clusters, 4) | |
40 |
|
|
169 | uses argparse for parsing command line options, 5) has better support for | |
41 |
|
|
170 | starting clusters using :command:`mpirun`, 6) has experimental support for | |
42 | for starting engines using PBS. However, this new version of ipcluster |
|
171 | starting engines using PBS. It can also reuse FURL files, by appropriately | |
43 | should be considered a technology preview. We plan on changing the API |
|
172 | passing options to its subcommands. However, this new version of ipcluster | |
44 | in significant ways before it is final. |
|
173 | should be considered a technology preview. We plan on changing the API in | |
|
174 | significant ways before it is final. | |||
45 |
|
175 | |||
46 | * The :mod:`argparse` module has been added to :mod:`IPython.external`. |
|
176 | * The :mod:`argparse` module has been added to :mod:`IPython.external`. | |
47 |
|
177 | |||
48 |
* Full |
|
178 | * Full description of the security model added to the docs. | |
49 |
|
179 | |||
50 | * cd completer: show bookmarks if no other completions are available. |
|
180 | * cd completer: show bookmarks if no other completions are available. | |
51 |
|
181 | |||
@@ -55,13 +185,45 b' New features' | |||||
55 | [~]|1> _prompt_title = 'sudo!' |
|
185 | [~]|1> _prompt_title = 'sudo!' | |
56 | sudo![~]|2> |
|
186 | sudo![~]|2> | |
57 |
|
187 | |||
58 | * %edit: If you do '%edit pasted_block', pasted_block |
|
188 | * %edit: If you do '%edit pasted_block', pasted_block variable gets updated | |
59 | variable gets updated with new data (so repeated |
|
189 | with new data (so repeated editing makes sense) | |
60 | editing makes sense) |
|
|||
61 |
|
190 | |||
62 | Bug fixes |
|
191 | Bug fixes | |
63 | --------- |
|
192 | --------- | |
64 |
|
193 | |||
|
194 | * Fix #368719, removed top-level debian/ directory to make the job of Debian | |||
|
195 | packagers easier. | |||
|
196 | ||||
|
197 | * Fix #291143 by including man pages contributed by Stephan Peijnik from the | |||
|
198 | Debian project. | |||
|
199 | ||||
|
200 | * Fix #358202, effectively a race condition, by properly synchronizing file | |||
|
201 | creation at cluster startup time. | |||
|
202 | ||||
|
203 | * `%timeit` now handles correctly functions that take a long time to execute | |||
|
204 | even the first time, by not repeating them. | |||
|
205 | ||||
|
206 | * Fix #239054, releasing of references after exiting. | |||
|
207 | ||||
|
208 | * Fix #341726, thanks to Alexander Clausen. | |||
|
209 | ||||
|
210 | * Fix #269966. This long-standing and very difficult bug (which is actually a | |||
|
211 | problem in Python itself) meant long-running sessions would inevitably grow | |||
|
212 | in memory size, often with catastrophic consequences if users had large | |||
|
213 | objects in their scripts. Now, using `%run` repeatedly should not cause any | |||
|
214 | memory leaks. Special thanks to John Hunter and Sameer D'Costa for their | |||
|
215 | help with this bug. | |||
|
216 | ||||
|
217 | * Fix #295371, bug in `%history`. | |||
|
218 | ||||
|
219 | * Improved support for py2exe. | |||
|
220 | ||||
|
221 | * Fix #270856: IPython hangs with PyGTK | |||
|
222 | ||||
|
223 | * Fix #270998: A magic with no docstring breaks the '%magic magic' | |||
|
224 | ||||
|
225 | * fix #271684: -c startup commands screw up raw vs. native history | |||
|
226 | ||||
65 | * Numerous bugs on Windows with the new ipcluster have been fixed. |
|
227 | * Numerous bugs on Windows with the new ipcluster have been fixed. | |
66 |
|
228 | |||
67 | * The ipengine and ipcontroller scripts now handle missing furl files |
|
229 | * The ipengine and ipcontroller scripts now handle missing furl files | |
@@ -81,12 +243,26 b' Bug fixes' | |||||
81 | Backwards incompatible changes |
|
243 | Backwards incompatible changes | |
82 | ------------------------------ |
|
244 | ------------------------------ | |
83 |
|
245 | |||
|
246 | * `ipykit` and related files were unmaintained and have been removed. | |||
|
247 | ||||
|
248 | * The :func:`IPython.genutils.doctest_reload` does not actually call | |||
|
249 | `reload(doctest)` anymore, as this was causing many problems with the test | |||
|
250 | suite. It still resets `doctest.master` to None. | |||
|
251 | ||||
|
252 | * While we have not deliberately broken Python 2.4 compatibility, only minor | |||
|
253 | testing was done with Python 2.4, while 2.5 and 2.6 were fully tested. But | |||
|
254 | if you encounter problems with 2.4, please do report them as bugs. | |||
|
255 | ||||
|
256 | * The :command:`ipcluster` now requires a mode argument; for example to start a | |||
|
257 | cluster on the local machine with 4 engines, you must now type:: | |||
|
258 | ||||
|
259 | $ ipcluster local -n 4 | |||
|
260 | ||||
84 | * The controller now has a ``-r`` flag that needs to be used if you want to |
|
261 | * The controller now has a ``-r`` flag that needs to be used if you want to | |
85 | reuse existing furl files. Otherwise they are deleted (the default). |
|
262 | reuse existing furl files. Otherwise they are deleted (the default). | |
86 |
|
263 | |||
87 |
* Remove ipy_leo.py. |
|
264 | * Remove ipy_leo.py. You can use :command:`easy_install ipython-extension` to | |
88 | (done to decouple it from ipython release cycle) |
|
265 | get it. (done to decouple it from ipython release cycle) | |
89 |
|
||||
90 |
|
266 | |||
91 |
|
267 | |||
92 | Release 0.9.1 |
|
268 | Release 0.9.1 |
@@ -175,11 +175,16 b' In order to configure less as your default pager, do the following:' | |||||
175 | properly interpret control sequences, which is how color |
|
175 | properly interpret control sequences, which is how color | |
176 | information is given to your terminal. |
|
176 | information is given to your terminal. | |
177 |
|
177 | |||
|
178 | For the bash shell, add to your ~/.bashrc file the lines:: | |||
|
179 | ||||
|
180 | export PAGER=less | |||
|
181 | export LESS=-r | |||
|
182 | ||||
178 | For the csh or tcsh shells, add to your ~/.cshrc file the lines:: |
|
183 | For the csh or tcsh shells, add to your ~/.cshrc file the lines:: | |
179 |
|
184 | |||
180 | setenv PAGER less |
|
185 | setenv PAGER less | |
181 | setenv LESS -r |
|
186 | setenv LESS -r | |
182 |
|
187 | |||
183 | There is similar syntax for other Unix shells, look at your system |
|
188 | There is similar syntax for other Unix shells, look at your system | |
184 | documentation for details. |
|
189 | documentation for details. | |
185 |
|
190 |
@@ -476,8 +476,17 b' if we want to have a codebase that works directly on both 2.x and 3.x.' | |||||
476 |
|
476 | |||
477 | 1. The syntax for exceptions changed (PEP 3110). The old |
|
477 | 1. The syntax for exceptions changed (PEP 3110). The old | |
478 | `except exc, var` changed to `except exc as var`. At last |
|
478 | `except exc, var` changed to `except exc as var`. At last | |
479 | count there was 78 occurences of this usage in the codebase |
|
479 | count there was 78 occurences of this usage in the codebase. This | |
480 |
|
480 | is a particularly problematic issue, because it's not easy to | ||
|
481 | implement it in a 2.5-compatible way. | |||
|
482 | ||||
|
483 | Because it is quite difficult to support simultaneously Python 2.5 and 3.x, we | |||
|
484 | will likely at some point put out a release that requires strictly 2.6 and | |||
|
485 | abandons 2.5 compatibility. This will then allow us to port the code to using | |||
|
486 | :func:`print` as a function, `except exc as var` syntax, etc. But as of | |||
|
487 | version 0.11 at least, we will retain Python 2.5 compatibility. | |||
|
488 | ||||
|
489 | ||||
481 | .. [Bazaar] Bazaar. http://bazaar-vcs.org/ |
|
490 | .. [Bazaar] Bazaar. http://bazaar-vcs.org/ | |
482 | .. [Launchpad] Launchpad. http://www.launchpad.net/ipython |
|
491 | .. [Launchpad] Launchpad. http://www.launchpad.net/ipython | |
483 | .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html |
|
492 | .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html |
@@ -9,14 +9,16 b' install all of its dependencies.' | |||||
9 |
|
9 | |||
10 |
|
10 | |||
11 | Please let us know if you have problems installing IPython or any of its |
|
11 | Please let us know if you have problems installing IPython or any of its | |
12 |
dependencies. IPython requires Python version 2. |
|
12 | dependencies. Officially, IPython requires Python version 2.5 or 2.6. We | |
13 | has been done on version 2.6, and so far everything looks fine. We have *not* |
|
13 | have *not* yet started to port IPython to Python 3.0. | |
14 | yet started to port IPython to Python 3.0, where the language changes are much |
|
|||
15 | more significant. |
|
|||
16 |
|
14 | |||
17 | .. warning:: |
|
15 | .. warning:: | |
18 |
|
16 | |||
19 | IPython will not work with Python 2.4 or below. |
|
17 | Officially, IPython supports Python versions 2.5 and 2.6. | |
|
18 | ||||
|
19 | IPython 0.10 has only been well tested with Python 2.5 and 2.6. Parts of | |||
|
20 | it may work with Python 2.4, but we do not officially support Python 2.4 | |||
|
21 | anymore. If you need to use 2.4, you can still run IPython 0.9. | |||
20 |
|
22 | |||
21 | Some of the installation approaches use the :mod:`setuptools` package and its |
|
23 | Some of the installation approaches use the :mod:`setuptools` package and its | |
22 | :command:`easy_install` command line program. In many scenarios, this provides |
|
24 | :command:`easy_install` command line program. In many scenarios, this provides | |
@@ -85,8 +87,8 b' Windows' | |||||
85 |
|
87 | |||
86 | There are a few caveats for Windows users. The main issue is that a basic |
|
88 | There are a few caveats for Windows users. The main issue is that a basic | |
87 | ``python setup.py install`` approach won't create ``.bat`` file or Start Menu |
|
89 | ``python setup.py install`` approach won't create ``.bat`` file or Start Menu | |
88 |
shortcuts, which most users want. To get an installation with these, |
|
90 | shortcuts, which most users want. To get an installation with these, you can | |
89 | two choices: |
|
91 | use any of the following alternatives: | |
90 |
|
92 | |||
91 | 1. Install using :command:`easy_install`. |
|
93 | 1. Install using :command:`easy_install`. | |
92 |
|
94 | |||
@@ -96,6 +98,16 b' two choices:' | |||||
96 | 3. Install from source, but using :mod:`setuptools` (``python setupegg.py |
|
98 | 3. Install from source, but using :mod:`setuptools` (``python setupegg.py | |
97 | install``). |
|
99 | install``). | |
98 |
|
100 | |||
|
101 | IPython by default runs in a termninal window, but the normal terminal | |||
|
102 | application supplied by Microsoft Windows is very primitive. You may want to | |||
|
103 | download the excellent and free Console_ application instead, which is a far | |||
|
104 | superior tool. You can even configure Console to give you by default an | |||
|
105 | IPython tab, which is very convenient to create new IPython sessions directly | |||
|
106 | from the working terminal. | |||
|
107 | ||||
|
108 | .. _Console: http://sourceforge.net/projects/console | |||
|
109 | ||||
|
110 | ||||
99 | Installing the development version |
|
111 | Installing the development version | |
100 | ---------------------------------- |
|
112 | ---------------------------------- | |
101 |
|
113 |
@@ -1329,8 +1329,9 b' For stand-alone use of the feature in your programs which do not use' | |||||
1329 | IPython at all, put the following lines toward the top of your 'main' |
|
1329 | IPython at all, put the following lines toward the top of your 'main' | |
1330 | routine:: |
|
1330 | routine:: | |
1331 |
|
1331 | |||
1332 |
import sys |
|
1332 | import sys | |
1333 | sys.excepthook = IPython.ultraTB.FormattedTB(mode='Verbose', |
|
1333 | from IPython.core import ultratb | |
|
1334 | sys.excepthook = ultratb.FormattedTB(mode='Verbose', | |||
1334 | color_scheme='Linux', call_pdb=1) |
|
1335 | color_scheme='Linux', call_pdb=1) | |
1335 |
|
1336 | |||
1336 | The mode keyword can be either 'Verbose' or 'Plain', giving either very |
|
1337 | The mode keyword can be either 'Verbose' or 'Plain', giving either very |
@@ -38,7 +38,7 b' To use code that calls MPI, there are typically two things that MPI requires.' | |||||
38 | There are a couple of ways that you can start the IPython engines and get these things to happen. |
|
38 | There are a couple of ways that you can start the IPython engines and get these things to happen. | |
39 |
|
39 | |||
40 | Automatic starting using :command:`mpiexec` and :command:`ipcluster` |
|
40 | Automatic starting using :command:`mpiexec` and :command:`ipcluster` | |
41 | ------------------------------------------------------------------- |
|
41 | -------------------------------------------------------------------- | |
42 |
|
42 | |||
43 | The easiest approach is to use the `mpiexec` mode of :command:`ipcluster`, which will first start a controller and then a set of engines using :command:`mpiexec`:: |
|
43 | The easiest approach is to use the `mpiexec` mode of :command:`ipcluster`, which will first start a controller and then a set of engines using :command:`mpiexec`:: | |
44 |
|
44 | |||
@@ -48,7 +48,7 b' This approach is best as interrupting :command:`ipcluster` will automatically' | |||||
48 | stop and clean up the controller and engines. |
|
48 | stop and clean up the controller and engines. | |
49 |
|
49 | |||
50 | Manual starting using :command:`mpiexec` |
|
50 | Manual starting using :command:`mpiexec` | |
51 | --------------------------------------- |
|
51 | ---------------------------------------- | |
52 |
|
52 | |||
53 | If you want to start the IPython engines using the :command:`mpiexec`, just do:: |
|
53 | If you want to start the IPython engines using the :command:`mpiexec`, just do:: | |
54 |
|
54 | |||
@@ -154,4 +154,4 b' compiled C, C++ and Fortran libraries that have been exposed to Python.' | |||||
154 | .. [MPI] Message Passing Interface. http://www-unix.mcs.anl.gov/mpi/ |
|
154 | .. [MPI] Message Passing Interface. http://www-unix.mcs.anl.gov/mpi/ | |
155 | .. [mpi4py] MPI for Python. mpi4py: http://mpi4py.scipy.org/ |
|
155 | .. [mpi4py] MPI for Python. mpi4py: http://mpi4py.scipy.org/ | |
156 | .. [OpenMPI] Open MPI. http://www.open-mpi.org/ |
|
156 | .. [OpenMPI] Open MPI. http://www.open-mpi.org/ | |
157 | .. [PyTrilinos] PyTrilinos. http://trilinos.sandia.gov/packages/pytrilinos/ No newline at end of file |
|
157 | .. [PyTrilinos] PyTrilinos. http://trilinos.sandia.gov/packages/pytrilinos/ |
@@ -65,11 +65,7 b' def install():' | |||||
65 | link = pjoin(ip_start_menu, 'scipy.lnk') |
|
65 | link = pjoin(ip_start_menu, 'scipy.lnk') | |
66 | cmd = '"%s" -p scipy' % ipybase |
|
66 | cmd = '"%s" -p scipy' % ipybase | |
67 | mkshortcut(python,'IPython (scipy profile)',link,cmd) |
|
67 | mkshortcut(python,'IPython (scipy profile)',link,cmd) | |
68 |
|
68 | |||
69 | link = pjoin(ip_start_menu, 'IPython test suite.lnk') |
|
|||
70 | cmd = '"%s" -vv' % pjoin(scripts, 'iptest') |
|
|||
71 | mkshortcut(python,'Run the IPython test suite',link,cmd) |
|
|||
72 |
|
||||
73 | link = pjoin(ip_start_menu, 'ipcontroller.lnk') |
|
69 | link = pjoin(ip_start_menu, 'ipcontroller.lnk') | |
74 | cmd = '"%s" -xy' % pjoin(scripts, 'ipcontroller') |
|
70 | cmd = '"%s" -xy' % pjoin(scripts, 'ipcontroller') | |
75 | mkshortcut(python,'IPython controller',link,cmd) |
|
71 | mkshortcut(python,'IPython controller',link,cmd) |
@@ -78,14 +78,38 b" if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):" | |||||
78 | #('docs/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 | ('docs/man/ipcluster.1.gz', | |||
|
83 | ['docs/man/ipcluster.1'], | |||
|
84 | 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'), | |||
|
85 | ||||
|
86 | ('docs/man/ipcontroller.1.gz', | |||
|
87 | ['docs/man/ipcontroller.1'], | |||
|
88 | 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'), | |||
|
89 | ||||
|
90 | ('docs/man/ipengine.1.gz', | |||
|
91 | ['docs/man/ipengine.1'], | |||
|
92 | 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'), | |||
|
93 | ||||
82 | ('docs/man/ipython.1.gz', |
|
94 | ('docs/man/ipython.1.gz', | |
83 | ['docs/man/ipython.1'], |
|
95 | ['docs/man/ipython.1'], | |
84 |
|
|
96 | 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'), | |
|
97 | ||||
|
98 | ('docs/man/ipython-wx.1.gz', | |||
|
99 | ['docs/man/ipython-wx.1'], | |||
|
100 | 'cd docs/man && gzip -9c ipython-wx.1 > ipython-wx.1.gz'), | |||
|
101 | ||||
|
102 | ('docs/man/ipythonx.1.gz', | |||
|
103 | ['docs/man/ipythonx.1'], | |||
|
104 | 'cd docs/man && gzip -9c ipythonx.1 > ipythonx.1.gz'), | |||
|
105 | ||||
|
106 | ('docs/man/irunner.1.gz', | |||
|
107 | ['docs/man/irunner.1'], | |||
|
108 | 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'), | |||
85 |
|
109 | |||
86 | ('docs/man/pycolor.1.gz', |
|
110 | ('docs/man/pycolor.1.gz', | |
87 | ['docs/man/pycolor.1'], |
|
111 | ['docs/man/pycolor.1'], | |
88 |
|
|
112 | 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'), | |
89 | ] |
|
113 | ] | |
90 |
|
114 | |||
91 | # Only build the docs if sphinx is present |
|
115 | # Only build the docs if sphinx is present |
@@ -57,7 +57,7 b' def file_doesnt_endwith(test,endings):' | |||||
57 | # Basic project information |
|
57 | # Basic project information | |
58 | #--------------------------------------------------------------------------- |
|
58 | #--------------------------------------------------------------------------- | |
59 |
|
59 | |||
60 |
# |
|
60 | # release.py contains version, authors, license, url, keywords, etc. | |
61 | execfile(pjoin('IPython','core','release.py')) |
|
61 | execfile(pjoin('IPython','core','release.py')) | |
62 |
|
62 | |||
63 | # Create a dict with the basic information |
|
63 | # Create a dict with the basic information | |
@@ -227,6 +227,31 b' def find_data_files():' | |||||
227 |
|
227 | |||
228 | return data_files |
|
228 | return data_files | |
229 |
|
229 | |||
|
230 | ||||
|
231 | def make_man_update_target(manpage): | |||
|
232 | """Return a target_update-compliant tuple for the given manpage. | |||
|
233 | ||||
|
234 | Parameters | |||
|
235 | ---------- | |||
|
236 | manpage : string | |||
|
237 | Name of the manpage, must include the section number (trailing number). | |||
|
238 | ||||
|
239 | Example | |||
|
240 | ------- | |||
|
241 | ||||
|
242 | >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE | |||
|
243 | ('docs/man/ipython.1.gz', | |||
|
244 | ['docs/man/ipython.1'], | |||
|
245 | 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz') | |||
|
246 | """ | |||
|
247 | man_dir = pjoin('docs', 'man') | |||
|
248 | manpage_gz = manpage + '.gz' | |||
|
249 | manpath = pjoin(man_dir, manpage) | |||
|
250 | manpath_gz = pjoin(man_dir, manpage_gz) | |||
|
251 | gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" % | |||
|
252 | locals() ) | |||
|
253 | return (manpath_gz, [manpath], gz_cmd) | |||
|
254 | ||||
230 | #--------------------------------------------------------------------------- |
|
255 | #--------------------------------------------------------------------------- | |
231 | # Find scripts |
|
256 | # Find scripts | |
232 | #--------------------------------------------------------------------------- |
|
257 | #--------------------------------------------------------------------------- |
@@ -5,8 +5,6 b' import sys' | |||||
5 |
|
5 | |||
6 | # now, import setuptools and call the actual setup |
|
6 | # now, import setuptools and call the actual setup | |
7 | import setuptools |
|
7 | import setuptools | |
8 | # print sys.argv |
|
|||
9 | #sys.argv=['','bdist_egg'] |
|
|||
10 | execfile('setup.py') |
|
8 | execfile('setup.py') | |
11 |
|
9 | |||
12 | # clean up the junk left around by setuptools |
|
10 | # clean up the junk left around by setuptools |
@@ -1,15 +1,54 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | """Utility to look for hard tabs and \r characters in all sources. | |||
|
3 | ||||
|
4 | Usage: | |||
|
5 | ||||
|
6 | ./check_sources.py | |||
|
7 | ||||
|
8 | It prints summaries and if chosen, line-by-line info of where \\t or \\r | |||
|
9 | characters can be found in our source tree. | |||
|
10 | """ | |||
|
11 | ||||
|
12 | # Config | |||
|
13 | # If true, all lines that have tabs are printed, with line number | |||
|
14 | full_report_tabs = True | |||
|
15 | # If true, all lines that have tabs are printed, with line number | |||
|
16 | full_report_rets = False | |||
|
17 | ||||
|
18 | # Code begins | |||
1 | from IPython.external.path import path |
|
19 | from IPython.external.path import path | |
2 | fs = path('..').walkfiles('*.py') |
|
|||
3 |
|
20 | |||
4 | for f in fs: |
|
21 | rets = [] | |
|
22 | tabs = [] | |||
|
23 | ||||
|
24 | for f in path('..').walkfiles('*.py'): | |||
5 | errs = '' |
|
25 | errs = '' | |
6 | cont = f.bytes() |
|
26 | cont = f.bytes() | |
7 | if '\t' in cont: |
|
27 | if '\t' in cont: | |
8 | errs+='t' |
|
28 | errs+='t' | |
|
29 | tabs.append(f) | |||
9 |
|
30 | |||
10 | if '\r' in cont: |
|
31 | if '\r' in cont: | |
11 | errs+='r' |
|
32 | errs+='r' | |
|
33 | rets.append(f) | |||
12 |
|
34 | |||
13 | if errs: |
|
35 | if errs: | |
14 | print "%3s" % errs, f |
|
36 | print "%3s" % errs, f | |
15 |
|
37 | |||
|
38 | if 't' in errs and full_report_tabs: | |||
|
39 | for ln,line in enumerate(f.lines()): | |||
|
40 | if '\t' in line: | |||
|
41 | print 'TAB:',ln,':',line, | |||
|
42 | ||||
|
43 | if 'r' in errs and full_report_rets: | |||
|
44 | for ln,line in enumerate(open(f.abspath(),'rb')): | |||
|
45 | if '\r' in line: | |||
|
46 | print 'RET:',ln,':',line, | |||
|
47 | ||||
|
48 | # Summary at the end, to call cleanup tools if necessary | |||
|
49 | if tabs: | |||
|
50 | print 'Hard tabs found. These can be cleaned with untabify:' | |||
|
51 | for f in tabs: print f, | |||
|
52 | if rets: | |||
|
53 | print 'Carriage returns (\\r) found in:' | |||
|
54 | for f in rets: print f, |
@@ -1,20 +1,19 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 |
""" |
|
2 | """Script to check that all code in a directory compiles correctly. | |
3 | """ |
|
|||
4 |
|
|
3 | ||
5 | import os |
|
4 | Usage: | |
6 | import sys |
|
|||
7 |
|
|
5 | ||
|
6 | compile.py | |||
8 |
|
|
7 | ||
9 | vstr = '.'.join(map(str,sys.version_info[:2])) |
|
8 | This script verifies that all Python files in the directory where run, and all | |
|
9 | of its subdirectories, compile correctly. | |||
10 |
|
|
10 | ||
11 | stat = os.system('python %s/lib/python%s/compileall.py .' % (sys.prefix,vstr)) |
|
11 | Before a release, call this script from the top-level directory. | |
|
12 | """ | |||
|
13 | ||||
|
14 | import sys | |||
12 |
|
15 | |||
13 |
|
16 | from toollib import compile_tree | ||
14 | if stat: |
|
|||
15 | print '*** THERE WAS AN ERROR! ***' |
|
|||
16 | print 'See messages above for the actual file that produced it.' |
|
|||
17 | else: |
|
|||
18 | print 'OK' |
|
|||
19 |
|
17 | |||
20 | sys.exit(stat) |
|
18 | if __name__ == '__main__': | |
|
19 | compile_tree() |
@@ -2,35 +2,22 b'' | |||||
2 | """Simple script to create a tarball with proper bzr version info. |
|
2 | """Simple script to create a tarball with proper bzr version info. | |
3 | """ |
|
3 | """ | |
4 |
|
4 | |||
5 |
import os |
|
5 | import os | |
|
6 | import sys | |||
|
7 | import shutil | |||
6 |
|
8 | |||
7 | basever = '0.9.0' |
|
9 | from toollib import * | |
8 |
|
10 | |||
9 | def oscmd(c): |
|
11 | c('python update_revnum.py') | |
10 | print ">",c |
|
|||
11 | s = os.system(c) |
|
|||
12 | if s: |
|
|||
13 | print "Error",s |
|
|||
14 | sys.exit(s) |
|
|||
15 |
|
12 | |||
16 | def verinfo(): |
|
13 | execfile('../IPython/core/release.py') # defines version_base | |
17 |
|
||||
18 | out = os.popen('bzr version-info') |
|
|||
19 | pairs = (l.split(':',1) for l in out) |
|
|||
20 | d = dict(((k,v.strip()) for (k,v) in pairs)) |
|
|||
21 | return d |
|
|||
22 |
|
||||
23 | basename = 'ipython' |
|
|||
24 |
|
||||
25 | #tarname = '%s.r%s.tgz' % (basename, ver) |
|
|||
26 | oscmd('python update_revnum.py') |
|
|||
27 |
|
14 | |||
28 | ver = verinfo() |
|
15 | ver = version_info() | |
29 |
|
16 | |||
30 | if ver['branch-nick'] == 'ipython': |
|
17 | if ver['branch-nick'] == 'ipython': | |
31 |
tarname = 'ipython-%s.bzr.r%s.tgz' % (base |
|
18 | tarname = 'ipython-%s.bzr.r%s.tgz' % (version_base, ver['revno']) | |
32 | else: |
|
19 | else: | |
33 |
tarname = 'ipython-%s.bzr.r%s.%s.tgz' % (base |
|
20 | tarname = 'ipython-%s.bzr.r%s.%s.tgz' % (version_base, ver['revno'], | |
34 | ver['branch-nick']) |
|
21 | ver['branch-nick']) | |
35 |
|
22 | |||
36 |
|
|
23 | c('bzr export ' + tarname) |
@@ -1,58 +1,43 b'' | |||||
1 | #!/bin/sh |
|
1 | #!/usr/bin/env python | |
2 |
|
|
2 | """IPython release script. | |
3 |
|
3 | |||
4 | PYVER=`python -V 2>&1 | awk '{print $2}' | awk -F '.' '{print $1$2}' ` |
|
4 | This should only be run at real release time. | |
5 | version=`ipython -Version` |
|
5 | """ | |
6 | ipdir=~/ipython/ipython |
|
|||
7 | ipbackupdir=~/ipython/backup |
|
|||
8 |
|
6 | |||
9 | echo |
|
7 | from toollib import * | |
10 | echo "Releasing IPython version $version" |
|
|||
11 | echo "==================================" |
|
|||
12 |
|
8 | |||
13 | # Perform local backup |
|
9 | # Get main ipython dir, this will raise if it doesn't pass some checks | |
14 | cd $ipdir/tools |
|
10 | ipdir = get_ipdir() | |
15 | ./make_tarball.py |
|
11 | cd(ipdir) | |
16 | mv ipython-*.tgz $ipbackupdir |
|
|||
17 |
|
||||
18 | # Clean up build/dist directories |
|
|||
19 | rm -rf $ipdir/build/* |
|
|||
20 | rm -rf $ipdir/dist/* |
|
|||
21 |
|
12 | |||
22 | # Build source and binary distros |
|
13 | # Load release info | |
23 | cd $ipdir |
|
14 | execfile(pjoin('IPython','core','release.py')) | |
24 | ./setup.py sdist --formats=gztar |
|
|||
25 |
|
15 | |||
26 | # Build version-specific RPMs, where we must use the --python option to ensure |
|
16 | # Where I keep static backups of each release | |
27 | # that the resulting RPM is really built with the requested python version (so |
|
17 | ipbackupdir = os.path.expanduser('~/ipython/backup') | |
28 | # things go to lib/python2.X/...) |
|
|||
29 | #python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4 |
|
|||
30 | #python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5 |
|
|||
31 |
|
18 | |||
32 | # Build eggs |
|
19 | ||
33 | python2.4 ./setup_bdist_egg.py |
|
20 | print "Releasing IPython version $version" | |
34 | python2.5 ./setup_bdist_egg.py |
|
21 | print "==================================" | |
35 |
|
22 | |||
36 | # Call the windows build separately, so that the extra Windows scripts don't |
|
23 | # Perform local backup | |
37 | # get pulled into Unix builds (setup.py has code which checks for |
|
24 | c('./make_tarball.py') | |
38 | # bdist_wininst) |
|
25 | c('mv ipython-*.tgz %s' % ipbackupdir) | |
39 | ./setup.py bdist_wininst --install-script=ipython_win_post_install.py |
|
|||
40 |
|
26 | |||
41 | # Change name so retarded Vista runs the installer correctly |
|
27 | # Build release files | |
42 | rename 's/win32/win32-setup/' $ipdir/dist/*.exe |
|
28 | c('./mkrel.py %s' % ipdir) | |
43 |
|
29 | |||
44 | # Register with the Python Package Index (PyPI) |
|
30 | # Register with the Python Package Index (PyPI) | |
45 |
|
|
31 | print "Registering with PyPI..." | |
46 | cd $ipdir |
|
32 | c('./setup.py register') | |
47 | ./setup.py register |
|
|||
48 |
|
33 | |||
49 | # Upload all files |
|
34 | # Upload all files | |
50 | cd $ipdir/dist |
|
35 | cd('dist') | |
51 |
|
|
36 | print "Uploading distribution files..." | |
52 | scp * ipython@ipython.scipy.org:www/dist/ |
|
37 | c('scp * ipython@ipython.scipy.org:www/dist/') | |
53 |
|
38 | |||
54 |
|
|
39 | print "Uploading backup files..." | |
55 |
cd |
|
40 | cd(ipbackupdir) | |
56 | scp `ls -1tr *tgz | tail -1` ipython@ipython.scipy.org:www/backup/ |
|
41 | c('scp `ls -1tr *tgz | tail -1` ipython@ipython.scipy.org:www/backup/') | |
57 |
|
42 | |||
58 |
|
|
43 | print "Done!" |
@@ -1,3 +1,9 b'' | |||||
|
1 | """XXX - What exactly is the use of this script? | |||
|
2 | ||||
|
3 | I (fperez) tried it quickly and it doesn't work in its current form. Either it | |||
|
4 | needs to be fixed and documented or removed. | |||
|
5 | """ | |||
|
6 | ||||
1 | import cProfile as profile |
|
7 | import cProfile as profile | |
2 | import sys |
|
8 | import sys | |
3 | #import profile |
|
9 | #import profile |
@@ -1,5 +1,5 b'' | |||||
1 | #!/bin/sh |
|
1 | #!/bin/sh | |
2 |
|
2 | # Simple upload script to push up into the testing directory a local build | ||
3 | ipdir=$PWD/.. |
|
3 | ipdir=$PWD/.. | |
4 |
|
4 | |||
5 | cd $ipdir/dist |
|
5 | cd $ipdir/dist |
@@ -1,23 +1,32 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 |
""" |
|
2 | """Change the revision number in release.py | |
|
3 | ||||
|
4 | This edits in-place release.py to update the revision number from bzr info. | |||
|
5 | ||||
|
6 | Usage: | |||
|
7 | ||||
|
8 | ./update_revnum.py""" | |||
3 |
|
9 | |||
4 | import os |
|
10 | import os | |
5 |
import |
|
11 | import pprint | |
|
12 | import re | |||
6 |
|
13 | |||
7 | def verinfo(): |
|
14 | from toollib import * | |
8 |
|
||||
9 | out = os.popen('bzr version-info') |
|
|||
10 | pairs = (l.split(':',1) for l in out) |
|
|||
11 | d = dict(((k,v.strip()) for (k,v) in pairs)) |
|
|||
12 | return d |
|
|||
13 |
|
15 | |||
14 | ver = verinfo() |
|
16 | if __name__ == '__main__': | |
|
17 | ver = version_info() | |||
15 |
|
18 | |||
16 | pprint.pprint(ver) |
|
19 | pprint.pprint(ver) | |
17 |
|
20 | |||
18 | rfile = open('../IPython/core/release.py','rb').read() |
|
21 | rfile = open('../IPython/core/release.py','rb').read() | |
19 |
newcont = re.sub(r'revision\s*=.*', |
|
22 | newcont = re.sub(r'revision\s*=.*', | |
|
23 | "revision = '%s'" % ver['revno'], | |||
|
24 | rfile) | |||
20 |
|
25 | |||
21 | newcont = re.sub(r'^branch\s*=[^=].*', "branch = '%s'" % ver['branch-nick'], newcont ) |
|
26 | newcont = re.sub(r'^branch\s*=[^=].*', | |
|
27 | "branch = '%s'" % ver['branch-nick'], | |||
|
28 | newcont) | |||
22 |
|
29 | |||
23 |
open('../IPython/core/release.py','wb') |
|
30 | f = open('../IPython/core/release.py','wb') | |
|
31 | f.write(newcont) | |||
|
32 | f.close() |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed | ||
This diff has been collapsed as it changes many lines, (1067 lines changed) Show them Hide them |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed | ||
This diff has been collapsed as it changes many lines, (800 lines changed) Show them Hide them |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now