##// END OF EJS Templates
remove simplegeneric from external...
MinRK -
Show More
@@ -1,707 +1,707 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 ======
3 ======
4 Rmagic
4 Rmagic
5 ======
5 ======
6
6
7 Magic command interface for interactive work with R via rpy2
7 Magic command interface for interactive work with R via rpy2
8
8
9 .. note::
9 .. note::
10
10
11 The ``rpy2`` package needs to be installed separately. It
11 The ``rpy2`` package needs to be installed separately. It
12 can be obtained using ``easy_install`` or ``pip``.
12 can be obtained using ``easy_install`` or ``pip``.
13
13
14 You will also need a working copy of R.
14 You will also need a working copy of R.
15
15
16 Usage
16 Usage
17 =====
17 =====
18
18
19 To enable the magics below, execute ``%load_ext rmagic``.
19 To enable the magics below, execute ``%load_ext rmagic``.
20
20
21 ``%R``
21 ``%R``
22
22
23 {R_DOC}
23 {R_DOC}
24
24
25 ``%Rpush``
25 ``%Rpush``
26
26
27 {RPUSH_DOC}
27 {RPUSH_DOC}
28
28
29 ``%Rpull``
29 ``%Rpull``
30
30
31 {RPULL_DOC}
31 {RPULL_DOC}
32
32
33 ``%Rget``
33 ``%Rget``
34
34
35 {RGET_DOC}
35 {RGET_DOC}
36
36
37 """
37 """
38 from __future__ import print_function
38 from __future__ import print_function
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Copyright (C) 2012 The IPython Development Team
41 # Copyright (C) 2012 The IPython Development Team
42 #
42 #
43 # Distributed under the terms of the BSD License. The full license is in
43 # Distributed under the terms of the BSD License. The full license is in
44 # the file COPYING, distributed as part of this software.
44 # the file COPYING, distributed as part of this software.
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46
46
47 import sys
47 import sys
48 import tempfile
48 import tempfile
49 from glob import glob
49 from glob import glob
50 from shutil import rmtree
50 from shutil import rmtree
51 import warnings
51 import warnings
52
52
53 # numpy and rpy2 imports
53 # numpy and rpy2 imports
54
54
55 import numpy as np
55 import numpy as np
56
56
57 import rpy2.rinterface as ri
57 import rpy2.rinterface as ri
58 import rpy2.robjects as ro
58 import rpy2.robjects as ro
59 try:
59 try:
60 from rpy2.robjects import pandas2ri
60 from rpy2.robjects import pandas2ri
61 pandas2ri.activate()
61 pandas2ri.activate()
62 except ImportError:
62 except ImportError:
63 pandas2ri = None
63 pandas2ri = None
64 from rpy2.robjects import numpy2ri
64 from rpy2.robjects import numpy2ri
65 numpy2ri.activate()
65 numpy2ri.activate()
66
66
67 # IPython imports
67 # IPython imports
68
68
69 from IPython.core.displaypub import publish_display_data
69 from IPython.core.displaypub import publish_display_data
70 from IPython.core.magic import (Magics, magics_class, line_magic,
70 from IPython.core.magic import (Magics, magics_class, line_magic,
71 line_cell_magic, needs_local_scope)
71 line_cell_magic, needs_local_scope)
72 from IPython.testing.skipdoctest import skip_doctest
72 from IPython.testing.skipdoctest import skip_doctest
73 from IPython.core.magic_arguments import (
73 from IPython.core.magic_arguments import (
74 argument, magic_arguments, parse_argstring
74 argument, magic_arguments, parse_argstring
75 )
75 )
76 from IPython.external.simplegeneric import generic
76 from simplegeneric import generic
77 from IPython.utils.py3compat import (str_to_unicode, unicode_to_str, PY3,
77 from IPython.utils.py3compat import (str_to_unicode, unicode_to_str, PY3,
78 unicode_type)
78 unicode_type)
79 from IPython.utils.text import dedent
79 from IPython.utils.text import dedent
80
80
81 class RInterpreterError(ri.RRuntimeError):
81 class RInterpreterError(ri.RRuntimeError):
82 """An error when running R code in a %%R magic cell."""
82 """An error when running R code in a %%R magic cell."""
83 def __init__(self, line, err, stdout):
83 def __init__(self, line, err, stdout):
84 self.line = line
84 self.line = line
85 self.err = err.rstrip()
85 self.err = err.rstrip()
86 self.stdout = stdout.rstrip()
86 self.stdout = stdout.rstrip()
87
87
88 def __unicode__(self):
88 def __unicode__(self):
89 s = 'Failed to parse and evaluate line %r.\nR error message: %r' % \
89 s = 'Failed to parse and evaluate line %r.\nR error message: %r' % \
90 (self.line, self.err)
90 (self.line, self.err)
91 if self.stdout and (self.stdout != self.err):
91 if self.stdout and (self.stdout != self.err):
92 s += '\nR stdout:\n' + self.stdout
92 s += '\nR stdout:\n' + self.stdout
93 return s
93 return s
94
94
95 if PY3:
95 if PY3:
96 __str__ = __unicode__
96 __str__ = __unicode__
97 else:
97 else:
98 def __str__(self):
98 def __str__(self):
99 return unicode_to_str(unicode(self), 'utf-8')
99 return unicode_to_str(unicode(self), 'utf-8')
100
100
101 def Rconverter(Robj, dataframe=False):
101 def Rconverter(Robj, dataframe=False):
102 """
102 """
103 Convert an object in R's namespace to one suitable
103 Convert an object in R's namespace to one suitable
104 for ipython's namespace.
104 for ipython's namespace.
105
105
106 For a data.frame, it tries to return a structured array.
106 For a data.frame, it tries to return a structured array.
107 It first checks for colnames, then names.
107 It first checks for colnames, then names.
108 If all are NULL, it returns np.asarray(Robj), else
108 If all are NULL, it returns np.asarray(Robj), else
109 it tries to construct a recarray
109 it tries to construct a recarray
110
110
111 Parameters
111 Parameters
112 ----------
112 ----------
113
113
114 Robj: an R object returned from rpy2
114 Robj: an R object returned from rpy2
115 """
115 """
116 is_data_frame = ro.r('is.data.frame')
116 is_data_frame = ro.r('is.data.frame')
117 colnames = ro.r('colnames')
117 colnames = ro.r('colnames')
118 rownames = ro.r('rownames') # with pandas, these could be used for the index
118 rownames = ro.r('rownames') # with pandas, these could be used for the index
119 names = ro.r('names')
119 names = ro.r('names')
120
120
121 if dataframe:
121 if dataframe:
122 as_data_frame = ro.r('as.data.frame')
122 as_data_frame = ro.r('as.data.frame')
123 cols = colnames(Robj)
123 cols = colnames(Robj)
124 _names = names(Robj)
124 _names = names(Robj)
125 if cols != ri.NULL:
125 if cols != ri.NULL:
126 Robj = as_data_frame(Robj)
126 Robj = as_data_frame(Robj)
127 names = tuple(np.array(cols))
127 names = tuple(np.array(cols))
128 elif _names != ri.NULL:
128 elif _names != ri.NULL:
129 names = tuple(np.array(_names))
129 names = tuple(np.array(_names))
130 else: # failed to find names
130 else: # failed to find names
131 return np.asarray(Robj)
131 return np.asarray(Robj)
132 Robj = np.rec.fromarrays(Robj, names = names)
132 Robj = np.rec.fromarrays(Robj, names = names)
133 return np.asarray(Robj)
133 return np.asarray(Robj)
134
134
135 @generic
135 @generic
136 def pyconverter(pyobj):
136 def pyconverter(pyobj):
137 """Convert Python objects to R objects. Add types using the decorator:
137 """Convert Python objects to R objects. Add types using the decorator:
138
138
139 @pyconverter.when_type
139 @pyconverter.when_type
140 """
140 """
141 return pyobj
141 return pyobj
142
142
143 # The default conversion for lists seems to make them a nested list. That has
143 # The default conversion for lists seems to make them a nested list. That has
144 # some advantages, but is rarely convenient, so for interactive use, we convert
144 # some advantages, but is rarely convenient, so for interactive use, we convert
145 # lists to a numpy array, which becomes an R vector.
145 # lists to a numpy array, which becomes an R vector.
146 @pyconverter.when_type(list)
146 @pyconverter.when_type(list)
147 def pyconverter_list(pyobj):
147 def pyconverter_list(pyobj):
148 return np.asarray(pyobj)
148 return np.asarray(pyobj)
149
149
150 if pandas2ri is None:
150 if pandas2ri is None:
151 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
151 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
152 # conversion function.
152 # conversion function.
153 try:
153 try:
154 from pandas import DataFrame
154 from pandas import DataFrame
155 from pandas.rpy.common import convert_to_r_dataframe
155 from pandas.rpy.common import convert_to_r_dataframe
156 @pyconverter.when_type(DataFrame)
156 @pyconverter.when_type(DataFrame)
157 def pyconverter_dataframe(pyobj):
157 def pyconverter_dataframe(pyobj):
158 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
158 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
159 except ImportError:
159 except ImportError:
160 pass
160 pass
161
161
162 @magics_class
162 @magics_class
163 class RMagics(Magics):
163 class RMagics(Magics):
164 """A set of magics useful for interactive work with R via rpy2.
164 """A set of magics useful for interactive work with R via rpy2.
165 """
165 """
166
166
167 def __init__(self, shell, Rconverter=Rconverter,
167 def __init__(self, shell, Rconverter=Rconverter,
168 pyconverter=pyconverter,
168 pyconverter=pyconverter,
169 cache_display_data=False):
169 cache_display_data=False):
170 """
170 """
171 Parameters
171 Parameters
172 ----------
172 ----------
173
173
174 shell : IPython shell
174 shell : IPython shell
175
175
176 Rconverter : callable
176 Rconverter : callable
177 To be called on values taken from R before putting them in the
177 To be called on values taken from R before putting them in the
178 IPython namespace.
178 IPython namespace.
179
179
180 pyconverter : callable
180 pyconverter : callable
181 To be called on values in ipython namespace before
181 To be called on values in ipython namespace before
182 assigning to variables in rpy2.
182 assigning to variables in rpy2.
183
183
184 cache_display_data : bool
184 cache_display_data : bool
185 If True, the published results of the final call to R are
185 If True, the published results of the final call to R are
186 cached in the variable 'display_cache'.
186 cached in the variable 'display_cache'.
187
187
188 """
188 """
189 super(RMagics, self).__init__(shell)
189 super(RMagics, self).__init__(shell)
190 self.cache_display_data = cache_display_data
190 self.cache_display_data = cache_display_data
191
191
192 self.r = ro.R()
192 self.r = ro.R()
193
193
194 self.Rstdout_cache = []
194 self.Rstdout_cache = []
195 self.pyconverter = pyconverter
195 self.pyconverter = pyconverter
196 self.Rconverter = Rconverter
196 self.Rconverter = Rconverter
197
197
198 def eval(self, line):
198 def eval(self, line):
199 '''
199 '''
200 Parse and evaluate a line of R code with rpy2.
200 Parse and evaluate a line of R code with rpy2.
201 Returns the output to R's stdout() connection,
201 Returns the output to R's stdout() connection,
202 the value generated by evaluating the code, and a
202 the value generated by evaluating the code, and a
203 boolean indicating whether the return value would be
203 boolean indicating whether the return value would be
204 visible if the line of code were evaluated in an R REPL.
204 visible if the line of code were evaluated in an R REPL.
205
205
206 R Code evaluation and visibility determination are
206 R Code evaluation and visibility determination are
207 done via an R call of the form withVisible({<code>})
207 done via an R call of the form withVisible({<code>})
208
208
209 '''
209 '''
210 old_writeconsole = ri.get_writeconsole()
210 old_writeconsole = ri.get_writeconsole()
211 ri.set_writeconsole(self.write_console)
211 ri.set_writeconsole(self.write_console)
212 try:
212 try:
213 res = ro.r("withVisible({%s\n})" % line)
213 res = ro.r("withVisible({%s\n})" % line)
214 value = res[0] #value (R object)
214 value = res[0] #value (R object)
215 visible = ro.conversion.ri2py(res[1])[0] #visible (boolean)
215 visible = ro.conversion.ri2py(res[1])[0] #visible (boolean)
216 except (ri.RRuntimeError, ValueError) as exception:
216 except (ri.RRuntimeError, ValueError) as exception:
217 warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
217 warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
218 raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
218 raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
219 text_output = self.flush()
219 text_output = self.flush()
220 ri.set_writeconsole(old_writeconsole)
220 ri.set_writeconsole(old_writeconsole)
221 return text_output, value, visible
221 return text_output, value, visible
222
222
223 def write_console(self, output):
223 def write_console(self, output):
224 '''
224 '''
225 A hook to capture R's stdout in a cache.
225 A hook to capture R's stdout in a cache.
226 '''
226 '''
227 self.Rstdout_cache.append(output)
227 self.Rstdout_cache.append(output)
228
228
229 def flush(self):
229 def flush(self):
230 '''
230 '''
231 Flush R's stdout cache to a string, returning the string.
231 Flush R's stdout cache to a string, returning the string.
232 '''
232 '''
233 value = ''.join([str_to_unicode(s, 'utf-8') for s in self.Rstdout_cache])
233 value = ''.join([str_to_unicode(s, 'utf-8') for s in self.Rstdout_cache])
234 self.Rstdout_cache = []
234 self.Rstdout_cache = []
235 return value
235 return value
236
236
237 @skip_doctest
237 @skip_doctest
238 @needs_local_scope
238 @needs_local_scope
239 @line_magic
239 @line_magic
240 def Rpush(self, line, local_ns=None):
240 def Rpush(self, line, local_ns=None):
241 '''
241 '''
242 A line-level magic for R that pushes
242 A line-level magic for R that pushes
243 variables from python to rpy2. The line should be made up
243 variables from python to rpy2. The line should be made up
244 of whitespace separated variable names in the IPython
244 of whitespace separated variable names in the IPython
245 namespace::
245 namespace::
246
246
247 In [7]: import numpy as np
247 In [7]: import numpy as np
248
248
249 In [8]: X = np.array([4.5,6.3,7.9])
249 In [8]: X = np.array([4.5,6.3,7.9])
250
250
251 In [9]: X.mean()
251 In [9]: X.mean()
252 Out[9]: 6.2333333333333343
252 Out[9]: 6.2333333333333343
253
253
254 In [10]: %Rpush X
254 In [10]: %Rpush X
255
255
256 In [11]: %R mean(X)
256 In [11]: %R mean(X)
257 Out[11]: array([ 6.23333333])
257 Out[11]: array([ 6.23333333])
258
258
259 '''
259 '''
260 if local_ns is None:
260 if local_ns is None:
261 local_ns = {}
261 local_ns = {}
262
262
263 inputs = line.split(' ')
263 inputs = line.split(' ')
264 for input in inputs:
264 for input in inputs:
265 try:
265 try:
266 val = local_ns[input]
266 val = local_ns[input]
267 except KeyError:
267 except KeyError:
268 try:
268 try:
269 val = self.shell.user_ns[input]
269 val = self.shell.user_ns[input]
270 except KeyError:
270 except KeyError:
271 # reraise the KeyError as a NameError so that it looks like
271 # reraise the KeyError as a NameError so that it looks like
272 # the standard python behavior when you use an unnamed
272 # the standard python behavior when you use an unnamed
273 # variable
273 # variable
274 raise NameError("name '%s' is not defined" % input)
274 raise NameError("name '%s' is not defined" % input)
275
275
276 self.r.assign(input, self.pyconverter(val))
276 self.r.assign(input, self.pyconverter(val))
277
277
278 @skip_doctest
278 @skip_doctest
279 @magic_arguments()
279 @magic_arguments()
280 @argument(
280 @argument(
281 '-d', '--as_dataframe', action='store_true',
281 '-d', '--as_dataframe', action='store_true',
282 default=False,
282 default=False,
283 help='Convert objects to data.frames before returning to ipython.'
283 help='Convert objects to data.frames before returning to ipython.'
284 )
284 )
285 @argument(
285 @argument(
286 'outputs',
286 'outputs',
287 nargs='*',
287 nargs='*',
288 )
288 )
289 @line_magic
289 @line_magic
290 def Rpull(self, line):
290 def Rpull(self, line):
291 '''
291 '''
292 A line-level magic for R that pulls
292 A line-level magic for R that pulls
293 variables from python to rpy2::
293 variables from python to rpy2::
294
294
295 In [18]: _ = %R x = c(3,4,6.7); y = c(4,6,7); z = c('a',3,4)
295 In [18]: _ = %R x = c(3,4,6.7); y = c(4,6,7); z = c('a',3,4)
296
296
297 In [19]: %Rpull x y z
297 In [19]: %Rpull x y z
298
298
299 In [20]: x
299 In [20]: x
300 Out[20]: array([ 3. , 4. , 6.7])
300 Out[20]: array([ 3. , 4. , 6.7])
301
301
302 In [21]: y
302 In [21]: y
303 Out[21]: array([ 4., 6., 7.])
303 Out[21]: array([ 4., 6., 7.])
304
304
305 In [22]: z
305 In [22]: z
306 Out[22]:
306 Out[22]:
307 array(['a', '3', '4'],
307 array(['a', '3', '4'],
308 dtype='|S1')
308 dtype='|S1')
309
309
310
310
311 If --as_dataframe, then each object is returned as a structured array
311 If --as_dataframe, then each object is returned as a structured array
312 after first passed through "as.data.frame" in R before
312 after first passed through "as.data.frame" in R before
313 being calling self.Rconverter.
313 being calling self.Rconverter.
314 This is useful when a structured array is desired as output, or
314 This is useful when a structured array is desired as output, or
315 when the object in R has mixed data types.
315 when the object in R has mixed data types.
316 See the %%R docstring for more examples.
316 See the %%R docstring for more examples.
317
317
318 Notes
318 Notes
319 -----
319 -----
320
320
321 Beware that R names can have '.' so this is not fool proof.
321 Beware that R names can have '.' so this is not fool proof.
322 To avoid this, don't name your R objects with '.'s...
322 To avoid this, don't name your R objects with '.'s...
323
323
324 '''
324 '''
325 args = parse_argstring(self.Rpull, line)
325 args = parse_argstring(self.Rpull, line)
326 outputs = args.outputs
326 outputs = args.outputs
327 for output in outputs:
327 for output in outputs:
328 self.shell.push({output:self.Rconverter(self.r(output),dataframe=args.as_dataframe)})
328 self.shell.push({output:self.Rconverter(self.r(output),dataframe=args.as_dataframe)})
329
329
330 @skip_doctest
330 @skip_doctest
331 @magic_arguments()
331 @magic_arguments()
332 @argument(
332 @argument(
333 '-d', '--as_dataframe', action='store_true',
333 '-d', '--as_dataframe', action='store_true',
334 default=False,
334 default=False,
335 help='Convert objects to data.frames before returning to ipython.'
335 help='Convert objects to data.frames before returning to ipython.'
336 )
336 )
337 @argument(
337 @argument(
338 'output',
338 'output',
339 nargs=1,
339 nargs=1,
340 type=str,
340 type=str,
341 )
341 )
342 @line_magic
342 @line_magic
343 def Rget(self, line):
343 def Rget(self, line):
344 '''
344 '''
345 Return an object from rpy2, possibly as a structured array (if possible).
345 Return an object from rpy2, possibly as a structured array (if possible).
346 Similar to Rpull except only one argument is accepted and the value is
346 Similar to Rpull except only one argument is accepted and the value is
347 returned rather than pushed to self.shell.user_ns::
347 returned rather than pushed to self.shell.user_ns::
348
348
349 In [3]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
349 In [3]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
350
350
351 In [4]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
351 In [4]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
352
352
353 In [5]: %R -i datapy
353 In [5]: %R -i datapy
354
354
355 In [6]: %Rget datapy
355 In [6]: %Rget datapy
356 Out[6]:
356 Out[6]:
357 array([['1', '2', '3', '4'],
357 array([['1', '2', '3', '4'],
358 ['2', '3', '2', '5'],
358 ['2', '3', '2', '5'],
359 ['a', 'b', 'c', 'e']],
359 ['a', 'b', 'c', 'e']],
360 dtype='|S1')
360 dtype='|S1')
361
361
362 In [7]: %Rget -d datapy
362 In [7]: %Rget -d datapy
363 Out[7]:
363 Out[7]:
364 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
364 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
365 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
365 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
366
366
367 '''
367 '''
368 args = parse_argstring(self.Rget, line)
368 args = parse_argstring(self.Rget, line)
369 output = args.output
369 output = args.output
370 return self.Rconverter(self.r(output[0]),dataframe=args.as_dataframe)
370 return self.Rconverter(self.r(output[0]),dataframe=args.as_dataframe)
371
371
372
372
373 @skip_doctest
373 @skip_doctest
374 @magic_arguments()
374 @magic_arguments()
375 @argument(
375 @argument(
376 '-i', '--input', action='append',
376 '-i', '--input', action='append',
377 help='Names of input variable from shell.user_ns to be assigned to R variables of the same names after calling self.pyconverter. Multiple names can be passed separated only by commas with no whitespace.'
377 help='Names of input variable from shell.user_ns to be assigned to R variables of the same names after calling self.pyconverter. Multiple names can be passed separated only by commas with no whitespace.'
378 )
378 )
379 @argument(
379 @argument(
380 '-o', '--output', action='append',
380 '-o', '--output', action='append',
381 help='Names of variables to be pushed from rpy2 to shell.user_ns after executing cell body and applying self.Rconverter. Multiple names can be passed separated only by commas with no whitespace.'
381 help='Names of variables to be pushed from rpy2 to shell.user_ns after executing cell body and applying self.Rconverter. Multiple names can be passed separated only by commas with no whitespace.'
382 )
382 )
383 @argument(
383 @argument(
384 '-w', '--width', type=int,
384 '-w', '--width', type=int,
385 help='Width of png plotting device sent as an argument to *png* in R.'
385 help='Width of png plotting device sent as an argument to *png* in R.'
386 )
386 )
387 @argument(
387 @argument(
388 '-h', '--height', type=int,
388 '-h', '--height', type=int,
389 help='Height of png plotting device sent as an argument to *png* in R.'
389 help='Height of png plotting device sent as an argument to *png* in R.'
390 )
390 )
391
391
392 @argument(
392 @argument(
393 '-d', '--dataframe', action='append',
393 '-d', '--dataframe', action='append',
394 help='Convert these objects to data.frames and return as structured arrays.'
394 help='Convert these objects to data.frames and return as structured arrays.'
395 )
395 )
396 @argument(
396 @argument(
397 '-u', '--units', type=unicode_type, choices=["px", "in", "cm", "mm"],
397 '-u', '--units', type=unicode_type, choices=["px", "in", "cm", "mm"],
398 help='Units of png plotting device sent as an argument to *png* in R. One of ["px", "in", "cm", "mm"].'
398 help='Units of png plotting device sent as an argument to *png* in R. One of ["px", "in", "cm", "mm"].'
399 )
399 )
400 @argument(
400 @argument(
401 '-r', '--res', type=int,
401 '-r', '--res', type=int,
402 help='Resolution of png plotting device sent as an argument to *png* in R. Defaults to 72 if *units* is one of ["in", "cm", "mm"].'
402 help='Resolution of png plotting device sent as an argument to *png* in R. Defaults to 72 if *units* is one of ["in", "cm", "mm"].'
403 )
403 )
404 @argument(
404 @argument(
405 '-p', '--pointsize', type=int,
405 '-p', '--pointsize', type=int,
406 help='Pointsize of png plotting device sent as an argument to *png* in R.'
406 help='Pointsize of png plotting device sent as an argument to *png* in R.'
407 )
407 )
408 @argument(
408 @argument(
409 '-b', '--bg',
409 '-b', '--bg',
410 help='Background of png plotting device sent as an argument to *png* in R.'
410 help='Background of png plotting device sent as an argument to *png* in R.'
411 )
411 )
412 @argument(
412 @argument(
413 '-n', '--noreturn',
413 '-n', '--noreturn',
414 help='Force the magic to not return anything.',
414 help='Force the magic to not return anything.',
415 action='store_true',
415 action='store_true',
416 default=False
416 default=False
417 )
417 )
418 @argument(
418 @argument(
419 'code',
419 'code',
420 nargs='*',
420 nargs='*',
421 )
421 )
422 @needs_local_scope
422 @needs_local_scope
423 @line_cell_magic
423 @line_cell_magic
424 def R(self, line, cell=None, local_ns=None):
424 def R(self, line, cell=None, local_ns=None):
425 '''
425 '''
426 Execute code in R, and pull some of the results back into the Python namespace.
426 Execute code in R, and pull some of the results back into the Python namespace.
427
427
428 In line mode, this will evaluate an expression and convert the returned value to a Python object.
428 In line mode, this will evaluate an expression and convert the returned value to a Python object.
429 The return value is determined by rpy2's behaviour of returning the result of evaluating the
429 The return value is determined by rpy2's behaviour of returning the result of evaluating the
430 final line.
430 final line.
431
431
432 Multiple R lines can be executed by joining them with semicolons::
432 Multiple R lines can be executed by joining them with semicolons::
433
433
434 In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
434 In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
435 Out[9]: array([ 4.25])
435 Out[9]: array([ 4.25])
436
436
437 In cell mode, this will run a block of R code. The resulting value
437 In cell mode, this will run a block of R code. The resulting value
438 is printed if it would printed be when evaluating the same code
438 is printed if it would printed be when evaluating the same code
439 within a standard R REPL.
439 within a standard R REPL.
440
440
441 Nothing is returned to python by default in cell mode::
441 Nothing is returned to python by default in cell mode::
442
442
443 In [10]: %%R
443 In [10]: %%R
444 ....: Y = c(2,4,3,9)
444 ....: Y = c(2,4,3,9)
445 ....: summary(lm(Y~X))
445 ....: summary(lm(Y~X))
446
446
447 Call:
447 Call:
448 lm(formula = Y ~ X)
448 lm(formula = Y ~ X)
449
449
450 Residuals:
450 Residuals:
451 1 2 3 4
451 1 2 3 4
452 0.88 -0.24 -2.28 1.64
452 0.88 -0.24 -2.28 1.64
453
453
454 Coefficients:
454 Coefficients:
455 Estimate Std. Error t value Pr(>|t|)
455 Estimate Std. Error t value Pr(>|t|)
456 (Intercept) 0.0800 2.3000 0.035 0.975
456 (Intercept) 0.0800 2.3000 0.035 0.975
457 X 1.0400 0.4822 2.157 0.164
457 X 1.0400 0.4822 2.157 0.164
458
458
459 Residual standard error: 2.088 on 2 degrees of freedom
459 Residual standard error: 2.088 on 2 degrees of freedom
460 Multiple R-squared: 0.6993,Adjusted R-squared: 0.549
460 Multiple R-squared: 0.6993,Adjusted R-squared: 0.549
461 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638
461 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638
462
462
463 In the notebook, plots are published as the output of the cell::
463 In the notebook, plots are published as the output of the cell::
464
464
465 %R plot(X, Y)
465 %R plot(X, Y)
466
466
467 will create a scatter plot of X bs Y.
467 will create a scatter plot of X bs Y.
468
468
469 If cell is not None and line has some R code, it is prepended to
469 If cell is not None and line has some R code, it is prepended to
470 the R code in cell.
470 the R code in cell.
471
471
472 Objects can be passed back and forth between rpy2 and python via the -i -o flags in line::
472 Objects can be passed back and forth between rpy2 and python via the -i -o flags in line::
473
473
474 In [14]: Z = np.array([1,4,5,10])
474 In [14]: Z = np.array([1,4,5,10])
475
475
476 In [15]: %R -i Z mean(Z)
476 In [15]: %R -i Z mean(Z)
477 Out[15]: array([ 5.])
477 Out[15]: array([ 5.])
478
478
479
479
480 In [16]: %R -o W W=Z*mean(Z)
480 In [16]: %R -o W W=Z*mean(Z)
481 Out[16]: array([ 5., 20., 25., 50.])
481 Out[16]: array([ 5., 20., 25., 50.])
482
482
483 In [17]: W
483 In [17]: W
484 Out[17]: array([ 5., 20., 25., 50.])
484 Out[17]: array([ 5., 20., 25., 50.])
485
485
486 The return value is determined by these rules:
486 The return value is determined by these rules:
487
487
488 * If the cell is not None, the magic returns None.
488 * If the cell is not None, the magic returns None.
489
489
490 * If the cell evaluates as False, the resulting value is returned
490 * If the cell evaluates as False, the resulting value is returned
491 unless the final line prints something to the console, in
491 unless the final line prints something to the console, in
492 which case None is returned.
492 which case None is returned.
493
493
494 * If the final line results in a NULL value when evaluated
494 * If the final line results in a NULL value when evaluated
495 by rpy2, then None is returned.
495 by rpy2, then None is returned.
496
496
497 * No attempt is made to convert the final value to a structured array.
497 * No attempt is made to convert the final value to a structured array.
498 Use the --dataframe flag or %Rget to push / return a structured array.
498 Use the --dataframe flag or %Rget to push / return a structured array.
499
499
500 * If the -n flag is present, there is no return value.
500 * If the -n flag is present, there is no return value.
501
501
502 * A trailing ';' will also result in no return value as the last
502 * A trailing ';' will also result in no return value as the last
503 value in the line is an empty string.
503 value in the line is an empty string.
504
504
505 The --dataframe argument will attempt to return structured arrays.
505 The --dataframe argument will attempt to return structured arrays.
506 This is useful for dataframes with
506 This is useful for dataframes with
507 mixed data types. Note also that for a data.frame,
507 mixed data types. Note also that for a data.frame,
508 if it is returned as an ndarray, it is transposed::
508 if it is returned as an ndarray, it is transposed::
509
509
510 In [18]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
510 In [18]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
511
511
512 In [19]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
512 In [19]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
513
513
514 In [20]: %%R -o datar
514 In [20]: %%R -o datar
515 datar = datapy
515 datar = datapy
516 ....:
516 ....:
517
517
518 In [21]: datar
518 In [21]: datar
519 Out[21]:
519 Out[21]:
520 array([['1', '2', '3', '4'],
520 array([['1', '2', '3', '4'],
521 ['2', '3', '2', '5'],
521 ['2', '3', '2', '5'],
522 ['a', 'b', 'c', 'e']],
522 ['a', 'b', 'c', 'e']],
523 dtype='|S1')
523 dtype='|S1')
524
524
525 In [22]: %%R -d datar
525 In [22]: %%R -d datar
526 datar = datapy
526 datar = datapy
527 ....:
527 ....:
528
528
529 In [23]: datar
529 In [23]: datar
530 Out[23]:
530 Out[23]:
531 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
531 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
532 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
532 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
533
533
534 The --dataframe argument first tries colnames, then names.
534 The --dataframe argument first tries colnames, then names.
535 If both are NULL, it returns an ndarray (i.e. unstructured)::
535 If both are NULL, it returns an ndarray (i.e. unstructured)::
536
536
537 In [1]: %R mydata=c(4,6,8.3); NULL
537 In [1]: %R mydata=c(4,6,8.3); NULL
538
538
539 In [2]: %R -d mydata
539 In [2]: %R -d mydata
540
540
541 In [3]: mydata
541 In [3]: mydata
542 Out[3]: array([ 4. , 6. , 8.3])
542 Out[3]: array([ 4. , 6. , 8.3])
543
543
544 In [4]: %R names(mydata) = c('a','b','c'); NULL
544 In [4]: %R names(mydata) = c('a','b','c'); NULL
545
545
546 In [5]: %R -d mydata
546 In [5]: %R -d mydata
547
547
548 In [6]: mydata
548 In [6]: mydata
549 Out[6]:
549 Out[6]:
550 array((4.0, 6.0, 8.3),
550 array((4.0, 6.0, 8.3),
551 dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
551 dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
552
552
553 In [7]: %R -o mydata
553 In [7]: %R -o mydata
554
554
555 In [8]: mydata
555 In [8]: mydata
556 Out[8]: array([ 4. , 6. , 8.3])
556 Out[8]: array([ 4. , 6. , 8.3])
557
557
558 '''
558 '''
559
559
560 args = parse_argstring(self.R, line)
560 args = parse_argstring(self.R, line)
561
561
562 # arguments 'code' in line are prepended to
562 # arguments 'code' in line are prepended to
563 # the cell lines
563 # the cell lines
564
564
565 if cell is None:
565 if cell is None:
566 code = ''
566 code = ''
567 return_output = True
567 return_output = True
568 line_mode = True
568 line_mode = True
569 else:
569 else:
570 code = cell
570 code = cell
571 return_output = False
571 return_output = False
572 line_mode = False
572 line_mode = False
573
573
574 code = ' '.join(args.code) + code
574 code = ' '.join(args.code) + code
575
575
576 # if there is no local namespace then default to an empty dict
576 # if there is no local namespace then default to an empty dict
577 if local_ns is None:
577 if local_ns is None:
578 local_ns = {}
578 local_ns = {}
579
579
580 if args.input:
580 if args.input:
581 for input in ','.join(args.input).split(','):
581 for input in ','.join(args.input).split(','):
582 try:
582 try:
583 val = local_ns[input]
583 val = local_ns[input]
584 except KeyError:
584 except KeyError:
585 try:
585 try:
586 val = self.shell.user_ns[input]
586 val = self.shell.user_ns[input]
587 except KeyError:
587 except KeyError:
588 raise NameError("name '%s' is not defined" % input)
588 raise NameError("name '%s' is not defined" % input)
589 self.r.assign(input, self.pyconverter(val))
589 self.r.assign(input, self.pyconverter(val))
590
590
591 if getattr(args, 'units') is not None:
591 if getattr(args, 'units') is not None:
592 if args.units != "px" and getattr(args, 'res') is None:
592 if args.units != "px" and getattr(args, 'res') is None:
593 args.res = 72
593 args.res = 72
594 args.units = '"%s"' % args.units
594 args.units = '"%s"' % args.units
595
595
596 png_argdict = dict([(n, getattr(args, n)) for n in ['units', 'res', 'height', 'width', 'bg', 'pointsize']])
596 png_argdict = dict([(n, getattr(args, n)) for n in ['units', 'res', 'height', 'width', 'bg', 'pointsize']])
597 png_args = ','.join(['%s=%s' % (o,v) for o, v in png_argdict.items() if v is not None])
597 png_args = ','.join(['%s=%s' % (o,v) for o, v in png_argdict.items() if v is not None])
598 # execute the R code in a temporary directory
598 # execute the R code in a temporary directory
599
599
600 tmpd = tempfile.mkdtemp()
600 tmpd = tempfile.mkdtemp()
601 self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd.replace('\\', '/'), png_args))
601 self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd.replace('\\', '/'), png_args))
602
602
603 text_output = ''
603 text_output = ''
604 try:
604 try:
605 if line_mode:
605 if line_mode:
606 for line in code.split(';'):
606 for line in code.split(';'):
607 text_result, result, visible = self.eval(line)
607 text_result, result, visible = self.eval(line)
608 text_output += text_result
608 text_output += text_result
609 if text_result:
609 if text_result:
610 # the last line printed something to the console so we won't return it
610 # the last line printed something to the console so we won't return it
611 return_output = False
611 return_output = False
612 else:
612 else:
613 text_result, result, visible = self.eval(code)
613 text_result, result, visible = self.eval(code)
614 text_output += text_result
614 text_output += text_result
615 if visible:
615 if visible:
616 old_writeconsole = ri.get_writeconsole()
616 old_writeconsole = ri.get_writeconsole()
617 ri.set_writeconsole(self.write_console)
617 ri.set_writeconsole(self.write_console)
618 ro.r.show(result)
618 ro.r.show(result)
619 text_output += self.flush()
619 text_output += self.flush()
620 ri.set_writeconsole(old_writeconsole)
620 ri.set_writeconsole(old_writeconsole)
621
621
622 except RInterpreterError as e:
622 except RInterpreterError as e:
623 print(e.stdout)
623 print(e.stdout)
624 if not e.stdout.endswith(e.err):
624 if not e.stdout.endswith(e.err):
625 print(e.err)
625 print(e.err)
626 rmtree(tmpd)
626 rmtree(tmpd)
627 return
627 return
628 finally:
628 finally:
629 self.r('dev.off()')
629 self.r('dev.off()')
630
630
631 # read out all the saved .png files
631 # read out all the saved .png files
632
632
633 images = [open(imgfile, 'rb').read() for imgfile in glob("%s/Rplots*png" % tmpd)]
633 images = [open(imgfile, 'rb').read() for imgfile in glob("%s/Rplots*png" % tmpd)]
634
634
635 # now publish the images
635 # now publish the images
636 # mimicking IPython/zmq/pylab/backend_inline.py
636 # mimicking IPython/zmq/pylab/backend_inline.py
637 fmt = 'png'
637 fmt = 'png'
638 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
638 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
639 mime = mimetypes[fmt]
639 mime = mimetypes[fmt]
640
640
641 # publish the printed R objects, if any
641 # publish the printed R objects, if any
642
642
643 display_data = []
643 display_data = []
644 if text_output:
644 if text_output:
645 display_data.append(('RMagic.R', {'text/plain':text_output}))
645 display_data.append(('RMagic.R', {'text/plain':text_output}))
646
646
647 # flush text streams before sending figures, helps a little with output
647 # flush text streams before sending figures, helps a little with output
648 for image in images:
648 for image in images:
649 # synchronization in the console (though it's a bandaid, not a real sln)
649 # synchronization in the console (though it's a bandaid, not a real sln)
650 sys.stdout.flush(); sys.stderr.flush()
650 sys.stdout.flush(); sys.stderr.flush()
651 display_data.append(('RMagic.R', {mime: image}))
651 display_data.append(('RMagic.R', {mime: image}))
652
652
653 # kill the temporary directory
653 # kill the temporary directory
654 rmtree(tmpd)
654 rmtree(tmpd)
655
655
656 # try to turn every output into a numpy array
656 # try to turn every output into a numpy array
657 # this means that output are assumed to be castable
657 # this means that output are assumed to be castable
658 # as numpy arrays
658 # as numpy arrays
659
659
660 if args.output:
660 if args.output:
661 for output in ','.join(args.output).split(','):
661 for output in ','.join(args.output).split(','):
662 self.shell.push({output:self.Rconverter(self.r(output), dataframe=False)})
662 self.shell.push({output:self.Rconverter(self.r(output), dataframe=False)})
663
663
664 if args.dataframe:
664 if args.dataframe:
665 for output in ','.join(args.dataframe).split(','):
665 for output in ','.join(args.dataframe).split(','):
666 self.shell.push({output:self.Rconverter(self.r(output), dataframe=True)})
666 self.shell.push({output:self.Rconverter(self.r(output), dataframe=True)})
667
667
668 for tag, disp_d in display_data:
668 for tag, disp_d in display_data:
669 publish_display_data(data=disp_d, source=tag)
669 publish_display_data(data=disp_d, source=tag)
670
670
671 # this will keep a reference to the display_data
671 # this will keep a reference to the display_data
672 # which might be useful to other objects who happen to use
672 # which might be useful to other objects who happen to use
673 # this method
673 # this method
674
674
675 if self.cache_display_data:
675 if self.cache_display_data:
676 self.display_cache = display_data
676 self.display_cache = display_data
677
677
678 # if in line mode and return_output, return the result as an ndarray
678 # if in line mode and return_output, return the result as an ndarray
679 if return_output and not args.noreturn:
679 if return_output and not args.noreturn:
680 if result != ri.NULL:
680 if result != ri.NULL:
681 return self.Rconverter(result, dataframe=False)
681 return self.Rconverter(result, dataframe=False)
682
682
683 __doc__ = __doc__.format(
683 __doc__ = __doc__.format(
684 R_DOC = dedent(RMagics.R.__doc__),
684 R_DOC = dedent(RMagics.R.__doc__),
685 RPUSH_DOC = dedent(RMagics.Rpush.__doc__),
685 RPUSH_DOC = dedent(RMagics.Rpush.__doc__),
686 RPULL_DOC = dedent(RMagics.Rpull.__doc__),
686 RPULL_DOC = dedent(RMagics.Rpull.__doc__),
687 RGET_DOC = dedent(RMagics.Rget.__doc__)
687 RGET_DOC = dedent(RMagics.Rget.__doc__)
688 )
688 )
689
689
690
690
691 def load_ipython_extension(ip):
691 def load_ipython_extension(ip):
692 """Load the extension in IPython."""
692 """Load the extension in IPython."""
693 warnings.warn("The rmagic extension in IPython is deprecated in favour of "
693 warnings.warn("The rmagic extension in IPython is deprecated in favour of "
694 "rpy2.ipython. If available, that will be loaded instead.\n"
694 "rpy2.ipython. If available, that will be loaded instead.\n"
695 "http://rpy.sourceforge.net/")
695 "http://rpy.sourceforge.net/")
696 try:
696 try:
697 import rpy2.ipython
697 import rpy2.ipython
698 except ImportError:
698 except ImportError:
699 pass # Fall back to our own implementation for now
699 pass # Fall back to our own implementation for now
700 else:
700 else:
701 return rpy2.ipython.load_ipython_extension(ip)
701 return rpy2.ipython.load_ipython_extension(ip)
702
702
703 ip.register_magics(RMagics)
703 ip.register_magics(RMagics)
704 # Initialising rpy2 interferes with readline. Since, at this point, we've
704 # Initialising rpy2 interferes with readline. Since, at this point, we've
705 # probably just loaded rpy2, we reset the delimiters. See issue gh-2759.
705 # probably just loaded rpy2, we reset the delimiters. See issue gh-2759.
706 if ip.has_readline:
706 if ip.has_readline:
707 ip.readline.set_completer_delims(ip.readline_delims)
707 ip.readline.set_completer_delims(ip.readline_delims)
@@ -1,49 +1,34 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Generic functions for extending IPython.
2 """Generic functions for extending IPython.
3
3
4 See http://cheeseshop.python.org/pypi/simplegeneric.
4 See http://pypi.python.org/pypi/simplegeneric.
5 """
5 """
6
6
7 #-----------------------------------------------------------------------------
8 # Copyright (C) 2008-2011 The IPython Development Team
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
13
14 #-----------------------------------------------------------------------------
15 # Imports
16 #-----------------------------------------------------------------------------
17
18 from IPython.core.error import TryNext
7 from IPython.core.error import TryNext
19 from IPython.external.simplegeneric import generic
8 from simplegeneric import generic
20
21 #-----------------------------------------------------------------------------
22 # Imports
23 #-----------------------------------------------------------------------------
24
9
25
10
26 @generic
11 @generic
27 def inspect_object(obj):
12 def inspect_object(obj):
28 """Called when you do obj?"""
13 """Called when you do obj?"""
29 raise TryNext
14 raise TryNext
30
15
31
16
32 @generic
17 @generic
33 def complete_object(obj, prev_completions):
18 def complete_object(obj, prev_completions):
34 """Custom completer dispatching for python objects.
19 """Custom completer dispatching for python objects.
35
20
36 Parameters
21 Parameters
37 ----------
22 ----------
38 obj : object
23 obj : object
39 The object to complete.
24 The object to complete.
40 prev_completions : list
25 prev_completions : list
41 List of attributes discovered so far.
26 List of attributes discovered so far.
42
27
43 This should return the list of attributes in obj. If you only wish to
28 This should return the list of attributes in obj. If you only wish to
44 add to the attributes already discovered normally, return
29 add to the attributes already discovered normally, return
45 own_attrs + prev_completions.
30 own_attrs + prev_completions.
46 """
31 """
47 raise TryNext
32 raise TryNext
48
33
49
34
@@ -1,349 +1,350 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 """Setup script for IPython.
3 """Setup script for IPython.
4
4
5 Under Posix environments it works like a typical setup.py script.
5 Under Posix environments it works like a typical setup.py script.
6 Under Windows, the command sdist is not supported, since IPython
6 Under Windows, the command sdist is not supported, since IPython
7 requires utilities which are not available under Windows."""
7 requires utilities which are not available under Windows."""
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (c) 2008-2011, IPython Development Team.
10 # Copyright (c) 2008-2011, IPython Development Team.
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 #
14 #
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16 #
16 #
17 # The full license is in the file COPYING.rst, distributed with this software.
17 # The full license is in the file COPYING.rst, distributed with this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Minimal Python version sanity check
21 # Minimal Python version sanity check
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 from __future__ import print_function
23 from __future__ import print_function
24
24
25 import sys
25 import sys
26
26
27 # This check is also made in IPython/__init__, don't forget to update both when
27 # This check is also made in IPython/__init__, don't forget to update both when
28 # changing Python version requirements.
28 # changing Python version requirements.
29 v = sys.version_info
29 v = sys.version_info
30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
32 print(error, file=sys.stderr)
32 print(error, file=sys.stderr)
33 sys.exit(1)
33 sys.exit(1)
34
34
35 PY3 = (sys.version_info[0] >= 3)
35 PY3 = (sys.version_info[0] >= 3)
36
36
37 # At least we're on the python version we need, move on.
37 # At least we're on the python version we need, move on.
38
38
39 #-------------------------------------------------------------------------------
39 #-------------------------------------------------------------------------------
40 # Imports
40 # Imports
41 #-------------------------------------------------------------------------------
41 #-------------------------------------------------------------------------------
42
42
43 # Stdlib imports
43 # Stdlib imports
44 import os
44 import os
45 import shutil
45 import shutil
46
46
47 from glob import glob
47 from glob import glob
48
48
49 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
49 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
50 # update it when the contents of directories change.
50 # update it when the contents of directories change.
51 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
51 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
52
52
53 from distutils.core import setup
53 from distutils.core import setup
54
54
55 # Our own imports
55 # Our own imports
56 from setupbase import target_update
56 from setupbase import target_update
57
57
58 from setupbase import (
58 from setupbase import (
59 setup_args,
59 setup_args,
60 find_packages,
60 find_packages,
61 find_package_data,
61 find_package_data,
62 check_package_data_first,
62 check_package_data_first,
63 find_entry_points,
63 find_entry_points,
64 build_scripts_entrypt,
64 build_scripts_entrypt,
65 find_data_files,
65 find_data_files,
66 check_for_dependencies,
66 check_for_dependencies,
67 git_prebuild,
67 git_prebuild,
68 check_submodule_status,
68 check_submodule_status,
69 update_submodules,
69 update_submodules,
70 require_submodules,
70 require_submodules,
71 UpdateSubmodules,
71 UpdateSubmodules,
72 get_bdist_wheel,
72 get_bdist_wheel,
73 CompileCSS,
73 CompileCSS,
74 JavascriptVersion,
74 JavascriptVersion,
75 css_js_prerelease,
75 css_js_prerelease,
76 install_symlinked,
76 install_symlinked,
77 install_lib_symlink,
77 install_lib_symlink,
78 install_scripts_for_symlink,
78 install_scripts_for_symlink,
79 unsymlink,
79 unsymlink,
80 )
80 )
81 from setupext import setupext
81 from setupext import setupext
82
82
83 isfile = os.path.isfile
83 isfile = os.path.isfile
84 pjoin = os.path.join
84 pjoin = os.path.join
85
85
86 #-------------------------------------------------------------------------------
86 #-------------------------------------------------------------------------------
87 # Handle OS specific things
87 # Handle OS specific things
88 #-------------------------------------------------------------------------------
88 #-------------------------------------------------------------------------------
89
89
90 if os.name in ('nt','dos'):
90 if os.name in ('nt','dos'):
91 os_name = 'windows'
91 os_name = 'windows'
92 else:
92 else:
93 os_name = os.name
93 os_name = os.name
94
94
95 # Under Windows, 'sdist' has not been supported. Now that the docs build with
95 # Under Windows, 'sdist' has not been supported. Now that the docs build with
96 # Sphinx it might work, but let's not turn it on until someone confirms that it
96 # Sphinx it might work, but let's not turn it on until someone confirms that it
97 # actually works.
97 # actually works.
98 if os_name == 'windows' and 'sdist' in sys.argv:
98 if os_name == 'windows' and 'sdist' in sys.argv:
99 print('The sdist command is not available under Windows. Exiting.')
99 print('The sdist command is not available under Windows. Exiting.')
100 sys.exit(1)
100 sys.exit(1)
101
101
102 #-------------------------------------------------------------------------------
102 #-------------------------------------------------------------------------------
103 # Make sure we aren't trying to run without submodules
103 # Make sure we aren't trying to run without submodules
104 #-------------------------------------------------------------------------------
104 #-------------------------------------------------------------------------------
105 here = os.path.abspath(os.path.dirname(__file__))
105 here = os.path.abspath(os.path.dirname(__file__))
106
106
107 def require_clean_submodules():
107 def require_clean_submodules():
108 """Check on git submodules before distutils can do anything
108 """Check on git submodules before distutils can do anything
109
109
110 Since distutils cannot be trusted to update the tree
110 Since distutils cannot be trusted to update the tree
111 after everything has been set in motion,
111 after everything has been set in motion,
112 this is not a distutils command.
112 this is not a distutils command.
113 """
113 """
114 # PACKAGERS: Add a return here to skip checks for git submodules
114 # PACKAGERS: Add a return here to skip checks for git submodules
115
115
116 # don't do anything if nothing is actually supposed to happen
116 # don't do anything if nothing is actually supposed to happen
117 for do_nothing in ('-h', '--help', '--help-commands', 'clean', 'submodule'):
117 for do_nothing in ('-h', '--help', '--help-commands', 'clean', 'submodule'):
118 if do_nothing in sys.argv:
118 if do_nothing in sys.argv:
119 return
119 return
120
120
121 status = check_submodule_status(here)
121 status = check_submodule_status(here)
122
122
123 if status == "missing":
123 if status == "missing":
124 print("checking out submodules for the first time")
124 print("checking out submodules for the first time")
125 update_submodules(here)
125 update_submodules(here)
126 elif status == "unclean":
126 elif status == "unclean":
127 print('\n'.join([
127 print('\n'.join([
128 "Cannot build / install IPython with unclean submodules",
128 "Cannot build / install IPython with unclean submodules",
129 "Please update submodules with",
129 "Please update submodules with",
130 " python setup.py submodule",
130 " python setup.py submodule",
131 "or",
131 "or",
132 " git submodule update",
132 " git submodule update",
133 "or commit any submodule changes you have made."
133 "or commit any submodule changes you have made."
134 ]))
134 ]))
135 sys.exit(1)
135 sys.exit(1)
136
136
137 require_clean_submodules()
137 require_clean_submodules()
138
138
139 #-------------------------------------------------------------------------------
139 #-------------------------------------------------------------------------------
140 # Things related to the IPython documentation
140 # Things related to the IPython documentation
141 #-------------------------------------------------------------------------------
141 #-------------------------------------------------------------------------------
142
142
143 # update the manuals when building a source dist
143 # update the manuals when building a source dist
144 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
144 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
145
145
146 # List of things to be updated. Each entry is a triplet of args for
146 # List of things to be updated. Each entry is a triplet of args for
147 # target_update()
147 # target_update()
148 to_update = [
148 to_update = [
149 # FIXME - Disabled for now: we need to redo an automatic way
149 # FIXME - Disabled for now: we need to redo an automatic way
150 # of generating the magic info inside the rst.
150 # of generating the magic info inside the rst.
151 #('docs/magic.tex',
151 #('docs/magic.tex',
152 #['IPython/Magic.py'],
152 #['IPython/Magic.py'],
153 #"cd doc && ./update_magic.sh" ),
153 #"cd doc && ./update_magic.sh" ),
154
154
155 ('docs/man/ipcluster.1.gz',
155 ('docs/man/ipcluster.1.gz',
156 ['docs/man/ipcluster.1'],
156 ['docs/man/ipcluster.1'],
157 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
157 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
158
158
159 ('docs/man/ipcontroller.1.gz',
159 ('docs/man/ipcontroller.1.gz',
160 ['docs/man/ipcontroller.1'],
160 ['docs/man/ipcontroller.1'],
161 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
161 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
162
162
163 ('docs/man/ipengine.1.gz',
163 ('docs/man/ipengine.1.gz',
164 ['docs/man/ipengine.1'],
164 ['docs/man/ipengine.1'],
165 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
165 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
166
166
167 ('docs/man/ipython.1.gz',
167 ('docs/man/ipython.1.gz',
168 ['docs/man/ipython.1'],
168 ['docs/man/ipython.1'],
169 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
169 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
170
170
171 ]
171 ]
172
172
173
173
174 [ target_update(*t) for t in to_update ]
174 [ target_update(*t) for t in to_update ]
175
175
176 #---------------------------------------------------------------------------
176 #---------------------------------------------------------------------------
177 # Find all the packages, package data, and data_files
177 # Find all the packages, package data, and data_files
178 #---------------------------------------------------------------------------
178 #---------------------------------------------------------------------------
179
179
180 packages = find_packages()
180 packages = find_packages()
181 package_data = find_package_data()
181 package_data = find_package_data()
182
182
183 data_files = find_data_files()
183 data_files = find_data_files()
184
184
185 setup_args['packages'] = packages
185 setup_args['packages'] = packages
186 setup_args['package_data'] = package_data
186 setup_args['package_data'] = package_data
187 setup_args['data_files'] = data_files
187 setup_args['data_files'] = data_files
188
188
189 #---------------------------------------------------------------------------
189 #---------------------------------------------------------------------------
190 # custom distutils commands
190 # custom distutils commands
191 #---------------------------------------------------------------------------
191 #---------------------------------------------------------------------------
192 # imports here, so they are after setuptools import if there was one
192 # imports here, so they are after setuptools import if there was one
193 from distutils.command.sdist import sdist
193 from distutils.command.sdist import sdist
194 from distutils.command.upload import upload
194 from distutils.command.upload import upload
195
195
196 class UploadWindowsInstallers(upload):
196 class UploadWindowsInstallers(upload):
197
197
198 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
198 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
199 user_options = upload.user_options + [
199 user_options = upload.user_options + [
200 ('files=', 'f', 'exe file (or glob) to upload')
200 ('files=', 'f', 'exe file (or glob) to upload')
201 ]
201 ]
202 def initialize_options(self):
202 def initialize_options(self):
203 upload.initialize_options(self)
203 upload.initialize_options(self)
204 meta = self.distribution.metadata
204 meta = self.distribution.metadata
205 base = '{name}-{version}'.format(
205 base = '{name}-{version}'.format(
206 name=meta.get_name(),
206 name=meta.get_name(),
207 version=meta.get_version()
207 version=meta.get_version()
208 )
208 )
209 self.files = os.path.join('dist', '%s.*.exe' % base)
209 self.files = os.path.join('dist', '%s.*.exe' % base)
210
210
211 def run(self):
211 def run(self):
212 for dist_file in glob(self.files):
212 for dist_file in glob(self.files):
213 self.upload_file('bdist_wininst', 'any', dist_file)
213 self.upload_file('bdist_wininst', 'any', dist_file)
214
214
215 setup_args['cmdclass'] = {
215 setup_args['cmdclass'] = {
216 'build_py': css_js_prerelease(
216 'build_py': css_js_prerelease(
217 check_package_data_first(git_prebuild('IPython'))),
217 check_package_data_first(git_prebuild('IPython'))),
218 'sdist' : css_js_prerelease(git_prebuild('IPython', sdist)),
218 'sdist' : css_js_prerelease(git_prebuild('IPython', sdist)),
219 'upload_wininst' : UploadWindowsInstallers,
219 'upload_wininst' : UploadWindowsInstallers,
220 'submodule' : UpdateSubmodules,
220 'submodule' : UpdateSubmodules,
221 'css' : CompileCSS,
221 'css' : CompileCSS,
222 'symlink': install_symlinked,
222 'symlink': install_symlinked,
223 'install_lib_symlink': install_lib_symlink,
223 'install_lib_symlink': install_lib_symlink,
224 'install_scripts_sym': install_scripts_for_symlink,
224 'install_scripts_sym': install_scripts_for_symlink,
225 'unsymlink': unsymlink,
225 'unsymlink': unsymlink,
226 'jsversion' : JavascriptVersion,
226 'jsversion' : JavascriptVersion,
227 }
227 }
228
228
229 #---------------------------------------------------------------------------
229 #---------------------------------------------------------------------------
230 # Handle scripts, dependencies, and setuptools specific things
230 # Handle scripts, dependencies, and setuptools specific things
231 #---------------------------------------------------------------------------
231 #---------------------------------------------------------------------------
232
232
233 # For some commands, use setuptools. Note that we do NOT list install here!
233 # For some commands, use setuptools. Note that we do NOT list install here!
234 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
234 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
235 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
235 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
236 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
236 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
237 'egg_info', 'easy_install', 'upload', 'install_egg_info',
237 'egg_info', 'easy_install', 'upload', 'install_egg_info',
238 ))
238 ))
239
239
240 if len(needs_setuptools.intersection(sys.argv)) > 0:
240 if len(needs_setuptools.intersection(sys.argv)) > 0:
241 import setuptools
241 import setuptools
242
242
243 # This dict is used for passing extra arguments that are setuptools
243 # This dict is used for passing extra arguments that are setuptools
244 # specific to setup
244 # specific to setup
245 setuptools_extra_args = {}
245 setuptools_extra_args = {}
246
246
247 # setuptools requirements
247 # setuptools requirements
248
248
249 pyzmq = 'pyzmq>=13'
249 pyzmq = 'pyzmq>=13'
250
250
251 extras_require = dict(
251 extras_require = dict(
252 parallel = [pyzmq],
252 parallel = [pyzmq],
253 qtconsole = [pyzmq, 'pygments'],
253 qtconsole = [pyzmq, 'pygments'],
254 doc = ['Sphinx>=1.1', 'numpydoc'],
254 doc = ['Sphinx>=1.1', 'numpydoc'],
255 test = ['nose>=0.10.1', 'requests'],
255 test = ['nose>=0.10.1', 'requests'],
256 terminal = [],
256 terminal = [],
257 nbformat = ['jsonschema>=2.0'],
257 nbformat = ['jsonschema>=2.0'],
258 notebook = ['tornado>=4.0', pyzmq, 'jinja2', 'pygments', 'mistune>=0.5'],
258 notebook = ['tornado>=4.0', pyzmq, 'jinja2', 'pygments', 'mistune>=0.5'],
259 nbconvert = ['pygments', 'jinja2', 'mistune>=0.3.1']
259 nbconvert = ['pygments', 'jinja2', 'mistune>=0.3.1']
260 )
260 )
261
261
262 if not sys.platform.startswith('win'):
262 if not sys.platform.startswith('win'):
263 extras_require['notebook'].append('terminado>=0.3.3')
263 extras_require['notebook'].append('terminado>=0.3.3')
264
264
265 if sys.version_info < (3, 3):
265 if sys.version_info < (3, 3):
266 extras_require['test'].append('mock')
266 extras_require['test'].append('mock')
267
267
268 extras_require['notebook'].extend(extras_require['nbformat'])
268 extras_require['notebook'].extend(extras_require['nbformat'])
269 extras_require['nbconvert'].extend(extras_require['nbformat'])
269 extras_require['nbconvert'].extend(extras_require['nbformat'])
270
270
271 install_requires = [
271 install_requires = [
272 'decorator',
272 'decorator',
273 'path.py', # required by pickleshare, remove when pickleshare is added here
273 'path.py', # required by pickleshare, remove when pickleshare is added here
274 'simplegeneric>0.8',
274 ]
275 ]
275
276
276 # add platform-specific dependencies
277 # add platform-specific dependencies
277 if sys.platform == 'darwin':
278 if sys.platform == 'darwin':
278 install_requires.append('appnope')
279 install_requires.append('appnope')
279 if 'bdist_wheel' in sys.argv[1:] or not setupext.check_for_readline():
280 if 'bdist_wheel' in sys.argv[1:] or not setupext.check_for_readline():
280 install_requires.append('gnureadline')
281 install_requires.append('gnureadline')
281
282
282 if sys.platform.startswith('win'):
283 if sys.platform.startswith('win'):
283 extras_require['terminal'].append('pyreadline>=2.0')
284 extras_require['terminal'].append('pyreadline>=2.0')
284 else:
285 else:
285 install_requires.append('pexpect')
286 install_requires.append('pexpect')
286
287
287 everything = set()
288 everything = set()
288 for deps in extras_require.values():
289 for deps in extras_require.values():
289 everything.update(deps)
290 everything.update(deps)
290 extras_require['all'] = everything
291 extras_require['all'] = everything
291
292
292 if 'setuptools' in sys.modules:
293 if 'setuptools' in sys.modules:
293 # setup.py develop should check for submodules
294 # setup.py develop should check for submodules
294 from setuptools.command.develop import develop
295 from setuptools.command.develop import develop
295 setup_args['cmdclass']['develop'] = require_submodules(develop)
296 setup_args['cmdclass']['develop'] = require_submodules(develop)
296 setup_args['cmdclass']['bdist_wheel'] = css_js_prerelease(get_bdist_wheel())
297 setup_args['cmdclass']['bdist_wheel'] = css_js_prerelease(get_bdist_wheel())
297
298
298 setuptools_extra_args['zip_safe'] = False
299 setuptools_extra_args['zip_safe'] = False
299 setuptools_extra_args['entry_points'] = {
300 setuptools_extra_args['entry_points'] = {
300 'console_scripts': find_entry_points(),
301 'console_scripts': find_entry_points(),
301 'pygments.lexers': [
302 'pygments.lexers': [
302 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
303 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
303 'ipython = IPython.lib.lexers:IPythonLexer',
304 'ipython = IPython.lib.lexers:IPythonLexer',
304 'ipython3 = IPython.lib.lexers:IPython3Lexer',
305 'ipython3 = IPython.lib.lexers:IPython3Lexer',
305 ],
306 ],
306 }
307 }
307 setup_args['extras_require'] = extras_require
308 setup_args['extras_require'] = extras_require
308 requires = setup_args['install_requires'] = install_requires
309 requires = setup_args['install_requires'] = install_requires
309
310
310 # Script to be run by the windows binary installer after the default setup
311 # Script to be run by the windows binary installer after the default setup
311 # routine, to add shortcuts and similar windows-only things. Windows
312 # routine, to add shortcuts and similar windows-only things. Windows
312 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
313 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
313 # doesn't find them.
314 # doesn't find them.
314 if 'bdist_wininst' in sys.argv:
315 if 'bdist_wininst' in sys.argv:
315 if len(sys.argv) > 2 and \
316 if len(sys.argv) > 2 and \
316 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
317 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
317 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
318 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
318 sys.exit(1)
319 sys.exit(1)
319 setup_args['data_files'].append(
320 setup_args['data_files'].append(
320 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
321 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
321 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
322 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
322 setup_args['options'] = {"bdist_wininst":
323 setup_args['options'] = {"bdist_wininst":
323 {"install_script":
324 {"install_script":
324 "ipython_win_post_install.py"}}
325 "ipython_win_post_install.py"}}
325
326
326 else:
327 else:
327 # If we are installing without setuptools, call this function which will
328 # If we are installing without setuptools, call this function which will
328 # check for dependencies an inform the user what is needed. This is
329 # check for dependencies an inform the user what is needed. This is
329 # just to make life easy for users.
330 # just to make life easy for users.
330 for install_cmd in ('install', 'symlink'):
331 for install_cmd in ('install', 'symlink'):
331 if install_cmd in sys.argv:
332 if install_cmd in sys.argv:
332 check_for_dependencies()
333 check_for_dependencies()
333 break
334 break
334 # scripts has to be a non-empty list, or install_scripts isn't called
335 # scripts has to be a non-empty list, or install_scripts isn't called
335 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
336 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
336
337
337 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
338 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
338
339
339 #---------------------------------------------------------------------------
340 #---------------------------------------------------------------------------
340 # Do the actual setup now
341 # Do the actual setup now
341 #---------------------------------------------------------------------------
342 #---------------------------------------------------------------------------
342
343
343 setup_args.update(setuptools_extra_args)
344 setup_args.update(setuptools_extra_args)
344
345
345 def main():
346 def main():
346 setup(**setup_args)
347 setup(**setup_args)
347
348
348 if __name__ == '__main__':
349 if __name__ == '__main__':
349 main()
350 main()
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