##// END OF EJS Templates
Specify unicode type properly in rmagic
Thomas Kluyver -
Show More
@@ -1,693 +1,694 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
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # Copyright (C) 2012 The IPython Development Team
40 # Copyright (C) 2012 The IPython Development Team
41 #
41 #
42 # Distributed under the terms of the BSD License. The full license is in
42 # Distributed under the terms of the BSD License. The full license is in
43 # the file COPYING, distributed as part of this software.
43 # the file COPYING, distributed as part of this software.
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 import sys
46 import sys
47 import tempfile
47 import tempfile
48 from glob import glob
48 from glob import glob
49 from shutil import rmtree
49 from shutil import rmtree
50
50
51 # numpy and rpy2 imports
51 # numpy and rpy2 imports
52
52
53 import numpy as np
53 import numpy as np
54
54
55 import rpy2.rinterface as ri
55 import rpy2.rinterface as ri
56 import rpy2.robjects as ro
56 import rpy2.robjects as ro
57 try:
57 try:
58 from rpy2.robjects import pandas2ri
58 from rpy2.robjects import pandas2ri
59 pandas2ri.activate()
59 pandas2ri.activate()
60 except ImportError:
60 except ImportError:
61 pandas2ri = None
61 pandas2ri = None
62 from rpy2.robjects import numpy2ri
62 from rpy2.robjects import numpy2ri
63 numpy2ri.activate()
63 numpy2ri.activate()
64
64
65 # IPython imports
65 # IPython imports
66
66
67 from IPython.core.displaypub import publish_display_data
67 from IPython.core.displaypub import publish_display_data
68 from IPython.core.magic import (Magics, magics_class, line_magic,
68 from IPython.core.magic import (Magics, magics_class, line_magic,
69 line_cell_magic, needs_local_scope)
69 line_cell_magic, needs_local_scope)
70 from IPython.testing.skipdoctest import skip_doctest
70 from IPython.testing.skipdoctest import skip_doctest
71 from IPython.core.magic_arguments import (
71 from IPython.core.magic_arguments import (
72 argument, magic_arguments, parse_argstring
72 argument, magic_arguments, parse_argstring
73 )
73 )
74 from IPython.external.simplegeneric import generic
74 from IPython.external.simplegeneric import generic
75 from IPython.utils.py3compat import str_to_unicode, unicode_to_str, PY3
75 from IPython.utils.py3compat import (str_to_unicode, unicode_to_str, PY3,
76 unicode_type)
76
77
77 class RInterpreterError(ri.RRuntimeError):
78 class RInterpreterError(ri.RRuntimeError):
78 """An error when running R code in a %%R magic cell."""
79 """An error when running R code in a %%R magic cell."""
79 def __init__(self, line, err, stdout):
80 def __init__(self, line, err, stdout):
80 self.line = line
81 self.line = line
81 self.err = err.rstrip()
82 self.err = err.rstrip()
82 self.stdout = stdout.rstrip()
83 self.stdout = stdout.rstrip()
83
84
84 def __unicode__(self):
85 def __unicode__(self):
85 s = 'Failed to parse and evaluate line %r.\nR error message: %r' % \
86 s = 'Failed to parse and evaluate line %r.\nR error message: %r' % \
86 (self.line, self.err)
87 (self.line, self.err)
87 if self.stdout and (self.stdout != self.err):
88 if self.stdout and (self.stdout != self.err):
88 s += '\nR stdout:\n' + self.stdout
89 s += '\nR stdout:\n' + self.stdout
89 return s
90 return s
90
91
91 if PY3:
92 if PY3:
92 __str__ = __unicode__
93 __str__ = __unicode__
93 else:
94 else:
94 def __str__(self):
95 def __str__(self):
95 return unicode_to_str(unicode(self), 'utf-8')
96 return unicode_to_str(unicode(self), 'utf-8')
96
97
97 def Rconverter(Robj, dataframe=False):
98 def Rconverter(Robj, dataframe=False):
98 """
99 """
99 Convert an object in R's namespace to one suitable
100 Convert an object in R's namespace to one suitable
100 for ipython's namespace.
101 for ipython's namespace.
101
102
102 For a data.frame, it tries to return a structured array.
103 For a data.frame, it tries to return a structured array.
103 It first checks for colnames, then names.
104 It first checks for colnames, then names.
104 If all are NULL, it returns np.asarray(Robj), else
105 If all are NULL, it returns np.asarray(Robj), else
105 it tries to construct a recarray
106 it tries to construct a recarray
106
107
107 Parameters
108 Parameters
108 ----------
109 ----------
109
110
110 Robj: an R object returned from rpy2
111 Robj: an R object returned from rpy2
111 """
112 """
112 is_data_frame = ro.r('is.data.frame')
113 is_data_frame = ro.r('is.data.frame')
113 colnames = ro.r('colnames')
114 colnames = ro.r('colnames')
114 rownames = ro.r('rownames') # with pandas, these could be used for the index
115 rownames = ro.r('rownames') # with pandas, these could be used for the index
115 names = ro.r('names')
116 names = ro.r('names')
116
117
117 if dataframe:
118 if dataframe:
118 as_data_frame = ro.r('as.data.frame')
119 as_data_frame = ro.r('as.data.frame')
119 cols = colnames(Robj)
120 cols = colnames(Robj)
120 _names = names(Robj)
121 _names = names(Robj)
121 if cols != ri.NULL:
122 if cols != ri.NULL:
122 Robj = as_data_frame(Robj)
123 Robj = as_data_frame(Robj)
123 names = tuple(np.array(cols))
124 names = tuple(np.array(cols))
124 elif _names != ri.NULL:
125 elif _names != ri.NULL:
125 names = tuple(np.array(_names))
126 names = tuple(np.array(_names))
126 else: # failed to find names
127 else: # failed to find names
127 return np.asarray(Robj)
128 return np.asarray(Robj)
128 Robj = np.rec.fromarrays(Robj, names = names)
129 Robj = np.rec.fromarrays(Robj, names = names)
129 return np.asarray(Robj)
130 return np.asarray(Robj)
130
131
131 @generic
132 @generic
132 def pyconverter(pyobj):
133 def pyconverter(pyobj):
133 """Convert Python objects to R objects. Add types using the decorator:
134 """Convert Python objects to R objects. Add types using the decorator:
134
135
135 @pyconverter.when_type
136 @pyconverter.when_type
136 """
137 """
137 return pyobj
138 return pyobj
138
139
139 # The default conversion for lists seems to make them a nested list. That has
140 # The default conversion for lists seems to make them a nested list. That has
140 # some advantages, but is rarely convenient, so for interactive use, we convert
141 # some advantages, but is rarely convenient, so for interactive use, we convert
141 # lists to a numpy array, which becomes an R vector.
142 # lists to a numpy array, which becomes an R vector.
142 @pyconverter.when_type(list)
143 @pyconverter.when_type(list)
143 def pyconverter_list(pyobj):
144 def pyconverter_list(pyobj):
144 return np.asarray(pyobj)
145 return np.asarray(pyobj)
145
146
146 if pandas2ri is None:
147 if pandas2ri is None:
147 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
148 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
148 # conversion function.
149 # conversion function.
149 try:
150 try:
150 from pandas import DataFrame
151 from pandas import DataFrame
151 from pandas.rpy.common import convert_to_r_dataframe
152 from pandas.rpy.common import convert_to_r_dataframe
152 @pyconverter.when_type(DataFrame)
153 @pyconverter.when_type(DataFrame)
153 def pyconverter_dataframe(pyobj):
154 def pyconverter_dataframe(pyobj):
154 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
155 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
155 except ImportError:
156 except ImportError:
156 pass
157 pass
157
158
158 @magics_class
159 @magics_class
159 class RMagics(Magics):
160 class RMagics(Magics):
160 """A set of magics useful for interactive work with R via rpy2.
161 """A set of magics useful for interactive work with R via rpy2.
161 """
162 """
162
163
163 def __init__(self, shell, Rconverter=Rconverter,
164 def __init__(self, shell, Rconverter=Rconverter,
164 pyconverter=pyconverter,
165 pyconverter=pyconverter,
165 cache_display_data=False):
166 cache_display_data=False):
166 """
167 """
167 Parameters
168 Parameters
168 ----------
169 ----------
169
170
170 shell : IPython shell
171 shell : IPython shell
171
172
172 Rconverter : callable
173 Rconverter : callable
173 To be called on values taken from R before putting them in the
174 To be called on values taken from R before putting them in the
174 IPython namespace.
175 IPython namespace.
175
176
176 pyconverter : callable
177 pyconverter : callable
177 To be called on values in ipython namespace before
178 To be called on values in ipython namespace before
178 assigning to variables in rpy2.
179 assigning to variables in rpy2.
179
180
180 cache_display_data : bool
181 cache_display_data : bool
181 If True, the published results of the final call to R are
182 If True, the published results of the final call to R are
182 cached in the variable 'display_cache'.
183 cached in the variable 'display_cache'.
183
184
184 """
185 """
185 super(RMagics, self).__init__(shell)
186 super(RMagics, self).__init__(shell)
186 self.cache_display_data = cache_display_data
187 self.cache_display_data = cache_display_data
187
188
188 self.r = ro.R()
189 self.r = ro.R()
189
190
190 self.Rstdout_cache = []
191 self.Rstdout_cache = []
191 self.pyconverter = pyconverter
192 self.pyconverter = pyconverter
192 self.Rconverter = Rconverter
193 self.Rconverter = Rconverter
193
194
194 def eval(self, line):
195 def eval(self, line):
195 '''
196 '''
196 Parse and evaluate a line of R code with rpy2.
197 Parse and evaluate a line of R code with rpy2.
197 Returns the output to R's stdout() connection,
198 Returns the output to R's stdout() connection,
198 the value generated by evaluating the code, and a
199 the value generated by evaluating the code, and a
199 boolean indicating whether the return value would be
200 boolean indicating whether the return value would be
200 visible if the line of code were evaluated in an R REPL.
201 visible if the line of code were evaluated in an R REPL.
201
202
202 R Code evaluation and visibility determination are
203 R Code evaluation and visibility determination are
203 done via an R call of the form withVisible({<code>})
204 done via an R call of the form withVisible({<code>})
204
205
205 '''
206 '''
206 old_writeconsole = ri.get_writeconsole()
207 old_writeconsole = ri.get_writeconsole()
207 ri.set_writeconsole(self.write_console)
208 ri.set_writeconsole(self.write_console)
208 try:
209 try:
209 res = ro.r("withVisible({%s})" % line)
210 res = ro.r("withVisible({%s})" % line)
210 value = res[0] #value (R object)
211 value = res[0] #value (R object)
211 visible = ro.conversion.ri2py(res[1])[0] #visible (boolean)
212 visible = ro.conversion.ri2py(res[1])[0] #visible (boolean)
212 except (ri.RRuntimeError, ValueError) as exception:
213 except (ri.RRuntimeError, ValueError) as exception:
213 warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
214 warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
214 raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
215 raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
215 text_output = self.flush()
216 text_output = self.flush()
216 ri.set_writeconsole(old_writeconsole)
217 ri.set_writeconsole(old_writeconsole)
217 return text_output, value, visible
218 return text_output, value, visible
218
219
219 def write_console(self, output):
220 def write_console(self, output):
220 '''
221 '''
221 A hook to capture R's stdout in a cache.
222 A hook to capture R's stdout in a cache.
222 '''
223 '''
223 self.Rstdout_cache.append(output)
224 self.Rstdout_cache.append(output)
224
225
225 def flush(self):
226 def flush(self):
226 '''
227 '''
227 Flush R's stdout cache to a string, returning the string.
228 Flush R's stdout cache to a string, returning the string.
228 '''
229 '''
229 value = ''.join([str_to_unicode(s, 'utf-8') for s in self.Rstdout_cache])
230 value = ''.join([str_to_unicode(s, 'utf-8') for s in self.Rstdout_cache])
230 self.Rstdout_cache = []
231 self.Rstdout_cache = []
231 return value
232 return value
232
233
233 @skip_doctest
234 @skip_doctest
234 @needs_local_scope
235 @needs_local_scope
235 @line_magic
236 @line_magic
236 def Rpush(self, line, local_ns=None):
237 def Rpush(self, line, local_ns=None):
237 '''
238 '''
238 A line-level magic for R that pushes
239 A line-level magic for R that pushes
239 variables from python to rpy2. The line should be made up
240 variables from python to rpy2. The line should be made up
240 of whitespace separated variable names in the IPython
241 of whitespace separated variable names in the IPython
241 namespace::
242 namespace::
242
243
243 In [7]: import numpy as np
244 In [7]: import numpy as np
244
245
245 In [8]: X = np.array([4.5,6.3,7.9])
246 In [8]: X = np.array([4.5,6.3,7.9])
246
247
247 In [9]: X.mean()
248 In [9]: X.mean()
248 Out[9]: 6.2333333333333343
249 Out[9]: 6.2333333333333343
249
250
250 In [10]: %Rpush X
251 In [10]: %Rpush X
251
252
252 In [11]: %R mean(X)
253 In [11]: %R mean(X)
253 Out[11]: array([ 6.23333333])
254 Out[11]: array([ 6.23333333])
254
255
255 '''
256 '''
256 if local_ns is None:
257 if local_ns is None:
257 local_ns = {}
258 local_ns = {}
258
259
259 inputs = line.split(' ')
260 inputs = line.split(' ')
260 for input in inputs:
261 for input in inputs:
261 try:
262 try:
262 val = local_ns[input]
263 val = local_ns[input]
263 except KeyError:
264 except KeyError:
264 try:
265 try:
265 val = self.shell.user_ns[input]
266 val = self.shell.user_ns[input]
266 except KeyError:
267 except KeyError:
267 # reraise the KeyError as a NameError so that it looks like
268 # reraise the KeyError as a NameError so that it looks like
268 # the standard python behavior when you use an unnamed
269 # the standard python behavior when you use an unnamed
269 # variable
270 # variable
270 raise NameError("name '%s' is not defined" % input)
271 raise NameError("name '%s' is not defined" % input)
271
272
272 self.r.assign(input, self.pyconverter(val))
273 self.r.assign(input, self.pyconverter(val))
273
274
274 @skip_doctest
275 @skip_doctest
275 @magic_arguments()
276 @magic_arguments()
276 @argument(
277 @argument(
277 '-d', '--as_dataframe', action='store_true',
278 '-d', '--as_dataframe', action='store_true',
278 default=False,
279 default=False,
279 help='Convert objects to data.frames before returning to ipython.'
280 help='Convert objects to data.frames before returning to ipython.'
280 )
281 )
281 @argument(
282 @argument(
282 'outputs',
283 'outputs',
283 nargs='*',
284 nargs='*',
284 )
285 )
285 @line_magic
286 @line_magic
286 def Rpull(self, line):
287 def Rpull(self, line):
287 '''
288 '''
288 A line-level magic for R that pulls
289 A line-level magic for R that pulls
289 variables from python to rpy2::
290 variables from python to rpy2::
290
291
291 In [18]: _ = %R x = c(3,4,6.7); y = c(4,6,7); z = c('a',3,4)
292 In [18]: _ = %R x = c(3,4,6.7); y = c(4,6,7); z = c('a',3,4)
292
293
293 In [19]: %Rpull x y z
294 In [19]: %Rpull x y z
294
295
295 In [20]: x
296 In [20]: x
296 Out[20]: array([ 3. , 4. , 6.7])
297 Out[20]: array([ 3. , 4. , 6.7])
297
298
298 In [21]: y
299 In [21]: y
299 Out[21]: array([ 4., 6., 7.])
300 Out[21]: array([ 4., 6., 7.])
300
301
301 In [22]: z
302 In [22]: z
302 Out[22]:
303 Out[22]:
303 array(['a', '3', '4'],
304 array(['a', '3', '4'],
304 dtype='|S1')
305 dtype='|S1')
305
306
306
307
307 If --as_dataframe, then each object is returned as a structured array
308 If --as_dataframe, then each object is returned as a structured array
308 after first passed through "as.data.frame" in R before
309 after first passed through "as.data.frame" in R before
309 being calling self.Rconverter.
310 being calling self.Rconverter.
310 This is useful when a structured array is desired as output, or
311 This is useful when a structured array is desired as output, or
311 when the object in R has mixed data types.
312 when the object in R has mixed data types.
312 See the %%R docstring for more examples.
313 See the %%R docstring for more examples.
313
314
314 Notes
315 Notes
315 -----
316 -----
316
317
317 Beware that R names can have '.' so this is not fool proof.
318 Beware that R names can have '.' so this is not fool proof.
318 To avoid this, don't name your R objects with '.'s...
319 To avoid this, don't name your R objects with '.'s...
319
320
320 '''
321 '''
321 args = parse_argstring(self.Rpull, line)
322 args = parse_argstring(self.Rpull, line)
322 outputs = args.outputs
323 outputs = args.outputs
323 for output in outputs:
324 for output in outputs:
324 self.shell.push({output:self.Rconverter(self.r(output),dataframe=args.as_dataframe)})
325 self.shell.push({output:self.Rconverter(self.r(output),dataframe=args.as_dataframe)})
325
326
326 @skip_doctest
327 @skip_doctest
327 @magic_arguments()
328 @magic_arguments()
328 @argument(
329 @argument(
329 '-d', '--as_dataframe', action='store_true',
330 '-d', '--as_dataframe', action='store_true',
330 default=False,
331 default=False,
331 help='Convert objects to data.frames before returning to ipython.'
332 help='Convert objects to data.frames before returning to ipython.'
332 )
333 )
333 @argument(
334 @argument(
334 'output',
335 'output',
335 nargs=1,
336 nargs=1,
336 type=str,
337 type=str,
337 )
338 )
338 @line_magic
339 @line_magic
339 def Rget(self, line):
340 def Rget(self, line):
340 '''
341 '''
341 Return an object from rpy2, possibly as a structured array (if possible).
342 Return an object from rpy2, possibly as a structured array (if possible).
342 Similar to Rpull except only one argument is accepted and the value is
343 Similar to Rpull except only one argument is accepted and the value is
343 returned rather than pushed to self.shell.user_ns::
344 returned rather than pushed to self.shell.user_ns::
344
345
345 In [3]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
346 In [3]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
346
347
347 In [4]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
348 In [4]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
348
349
349 In [5]: %R -i datapy
350 In [5]: %R -i datapy
350
351
351 In [6]: %Rget datapy
352 In [6]: %Rget datapy
352 Out[6]:
353 Out[6]:
353 array([['1', '2', '3', '4'],
354 array([['1', '2', '3', '4'],
354 ['2', '3', '2', '5'],
355 ['2', '3', '2', '5'],
355 ['a', 'b', 'c', 'e']],
356 ['a', 'b', 'c', 'e']],
356 dtype='|S1')
357 dtype='|S1')
357
358
358 In [7]: %Rget -d datapy
359 In [7]: %Rget -d datapy
359 Out[7]:
360 Out[7]:
360 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
361 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
361 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
362 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
362
363
363 '''
364 '''
364 args = parse_argstring(self.Rget, line)
365 args = parse_argstring(self.Rget, line)
365 output = args.output
366 output = args.output
366 return self.Rconverter(self.r(output[0]),dataframe=args.as_dataframe)
367 return self.Rconverter(self.r(output[0]),dataframe=args.as_dataframe)
367
368
368
369
369 @skip_doctest
370 @skip_doctest
370 @magic_arguments()
371 @magic_arguments()
371 @argument(
372 @argument(
372 '-i', '--input', action='append',
373 '-i', '--input', action='append',
373 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.'
374 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.'
374 )
375 )
375 @argument(
376 @argument(
376 '-o', '--output', action='append',
377 '-o', '--output', action='append',
377 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.'
378 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.'
378 )
379 )
379 @argument(
380 @argument(
380 '-w', '--width', type=int,
381 '-w', '--width', type=int,
381 help='Width of png plotting device sent as an argument to *png* in R.'
382 help='Width of png plotting device sent as an argument to *png* in R.'
382 )
383 )
383 @argument(
384 @argument(
384 '-h', '--height', type=int,
385 '-h', '--height', type=int,
385 help='Height of png plotting device sent as an argument to *png* in R.'
386 help='Height of png plotting device sent as an argument to *png* in R.'
386 )
387 )
387
388
388 @argument(
389 @argument(
389 '-d', '--dataframe', action='append',
390 '-d', '--dataframe', action='append',
390 help='Convert these objects to data.frames and return as structured arrays.'
391 help='Convert these objects to data.frames and return as structured arrays.'
391 )
392 )
392 @argument(
393 @argument(
393 '-u', '--units', type=unicode, choices=["px", "in", "cm", "mm"],
394 '-u', '--units', type=unicode_type, choices=["px", "in", "cm", "mm"],
394 help='Units of png plotting device sent as an argument to *png* in R. One of ["px", "in", "cm", "mm"].'
395 help='Units of png plotting device sent as an argument to *png* in R. One of ["px", "in", "cm", "mm"].'
395 )
396 )
396 @argument(
397 @argument(
397 '-r', '--res', type=int,
398 '-r', '--res', type=int,
398 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"].'
399 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"].'
399 )
400 )
400 @argument(
401 @argument(
401 '-p', '--pointsize', type=int,
402 '-p', '--pointsize', type=int,
402 help='Pointsize of png plotting device sent as an argument to *png* in R.'
403 help='Pointsize of png plotting device sent as an argument to *png* in R.'
403 )
404 )
404 @argument(
405 @argument(
405 '-b', '--bg',
406 '-b', '--bg',
406 help='Background of png plotting device sent as an argument to *png* in R.'
407 help='Background of png plotting device sent as an argument to *png* in R.'
407 )
408 )
408 @argument(
409 @argument(
409 '-n', '--noreturn',
410 '-n', '--noreturn',
410 help='Force the magic to not return anything.',
411 help='Force the magic to not return anything.',
411 action='store_true',
412 action='store_true',
412 default=False
413 default=False
413 )
414 )
414 @argument(
415 @argument(
415 'code',
416 'code',
416 nargs='*',
417 nargs='*',
417 )
418 )
418 @needs_local_scope
419 @needs_local_scope
419 @line_cell_magic
420 @line_cell_magic
420 def R(self, line, cell=None, local_ns=None):
421 def R(self, line, cell=None, local_ns=None):
421 '''
422 '''
422 Execute code in R, and pull some of the results back into the Python namespace.
423 Execute code in R, and pull some of the results back into the Python namespace.
423
424
424 In line mode, this will evaluate an expression and convert the returned value to a Python object.
425 In line mode, this will evaluate an expression and convert the returned value to a Python object.
425 The return value is determined by rpy2's behaviour of returning the result of evaluating the
426 The return value is determined by rpy2's behaviour of returning the result of evaluating the
426 final line.
427 final line.
427
428
428 Multiple R lines can be executed by joining them with semicolons::
429 Multiple R lines can be executed by joining them with semicolons::
429
430
430 In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
431 In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
431 Out[9]: array([ 4.25])
432 Out[9]: array([ 4.25])
432
433
433 In cell mode, this will run a block of R code. The resulting value
434 In cell mode, this will run a block of R code. The resulting value
434 is printed if it would printed be when evaluating the same code
435 is printed if it would printed be when evaluating the same code
435 within a standard R REPL.
436 within a standard R REPL.
436
437
437 Nothing is returned to python by default in cell mode::
438 Nothing is returned to python by default in cell mode::
438
439
439 In [10]: %%R
440 In [10]: %%R
440 ....: Y = c(2,4,3,9)
441 ....: Y = c(2,4,3,9)
441 ....: summary(lm(Y~X))
442 ....: summary(lm(Y~X))
442
443
443 Call:
444 Call:
444 lm(formula = Y ~ X)
445 lm(formula = Y ~ X)
445
446
446 Residuals:
447 Residuals:
447 1 2 3 4
448 1 2 3 4
448 0.88 -0.24 -2.28 1.64
449 0.88 -0.24 -2.28 1.64
449
450
450 Coefficients:
451 Coefficients:
451 Estimate Std. Error t value Pr(>|t|)
452 Estimate Std. Error t value Pr(>|t|)
452 (Intercept) 0.0800 2.3000 0.035 0.975
453 (Intercept) 0.0800 2.3000 0.035 0.975
453 X 1.0400 0.4822 2.157 0.164
454 X 1.0400 0.4822 2.157 0.164
454
455
455 Residual standard error: 2.088 on 2 degrees of freedom
456 Residual standard error: 2.088 on 2 degrees of freedom
456 Multiple R-squared: 0.6993,Adjusted R-squared: 0.549
457 Multiple R-squared: 0.6993,Adjusted R-squared: 0.549
457 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638
458 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638
458
459
459 In the notebook, plots are published as the output of the cell::
460 In the notebook, plots are published as the output of the cell::
460
461
461 %R plot(X, Y)
462 %R plot(X, Y)
462
463
463 will create a scatter plot of X bs Y.
464 will create a scatter plot of X bs Y.
464
465
465 If cell is not None and line has some R code, it is prepended to
466 If cell is not None and line has some R code, it is prepended to
466 the R code in cell.
467 the R code in cell.
467
468
468 Objects can be passed back and forth between rpy2 and python via the -i -o flags in line::
469 Objects can be passed back and forth between rpy2 and python via the -i -o flags in line::
469
470
470 In [14]: Z = np.array([1,4,5,10])
471 In [14]: Z = np.array([1,4,5,10])
471
472
472 In [15]: %R -i Z mean(Z)
473 In [15]: %R -i Z mean(Z)
473 Out[15]: array([ 5.])
474 Out[15]: array([ 5.])
474
475
475
476
476 In [16]: %R -o W W=Z*mean(Z)
477 In [16]: %R -o W W=Z*mean(Z)
477 Out[16]: array([ 5., 20., 25., 50.])
478 Out[16]: array([ 5., 20., 25., 50.])
478
479
479 In [17]: W
480 In [17]: W
480 Out[17]: array([ 5., 20., 25., 50.])
481 Out[17]: array([ 5., 20., 25., 50.])
481
482
482 The return value is determined by these rules:
483 The return value is determined by these rules:
483
484
484 * If the cell is not None, the magic returns None.
485 * If the cell is not None, the magic returns None.
485
486
486 * If the cell evaluates as False, the resulting value is returned
487 * If the cell evaluates as False, the resulting value is returned
487 unless the final line prints something to the console, in
488 unless the final line prints something to the console, in
488 which case None is returned.
489 which case None is returned.
489
490
490 * If the final line results in a NULL value when evaluated
491 * If the final line results in a NULL value when evaluated
491 by rpy2, then None is returned.
492 by rpy2, then None is returned.
492
493
493 * No attempt is made to convert the final value to a structured array.
494 * No attempt is made to convert the final value to a structured array.
494 Use the --dataframe flag or %Rget to push / return a structured array.
495 Use the --dataframe flag or %Rget to push / return a structured array.
495
496
496 * If the -n flag is present, there is no return value.
497 * If the -n flag is present, there is no return value.
497
498
498 * A trailing ';' will also result in no return value as the last
499 * A trailing ';' will also result in no return value as the last
499 value in the line is an empty string.
500 value in the line is an empty string.
500
501
501 The --dataframe argument will attempt to return structured arrays.
502 The --dataframe argument will attempt to return structured arrays.
502 This is useful for dataframes with
503 This is useful for dataframes with
503 mixed data types. Note also that for a data.frame,
504 mixed data types. Note also that for a data.frame,
504 if it is returned as an ndarray, it is transposed::
505 if it is returned as an ndarray, it is transposed::
505
506
506 In [18]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
507 In [18]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
507
508
508 In [19]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
509 In [19]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
509
510
510 In [20]: %%R -o datar
511 In [20]: %%R -o datar
511 datar = datapy
512 datar = datapy
512 ....:
513 ....:
513
514
514 In [21]: datar
515 In [21]: datar
515 Out[21]:
516 Out[21]:
516 array([['1', '2', '3', '4'],
517 array([['1', '2', '3', '4'],
517 ['2', '3', '2', '5'],
518 ['2', '3', '2', '5'],
518 ['a', 'b', 'c', 'e']],
519 ['a', 'b', 'c', 'e']],
519 dtype='|S1')
520 dtype='|S1')
520
521
521 In [22]: %%R -d datar
522 In [22]: %%R -d datar
522 datar = datapy
523 datar = datapy
523 ....:
524 ....:
524
525
525 In [23]: datar
526 In [23]: datar
526 Out[23]:
527 Out[23]:
527 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
528 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
528 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
529 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
529
530
530 The --dataframe argument first tries colnames, then names.
531 The --dataframe argument first tries colnames, then names.
531 If both are NULL, it returns an ndarray (i.e. unstructured)::
532 If both are NULL, it returns an ndarray (i.e. unstructured)::
532
533
533 In [1]: %R mydata=c(4,6,8.3); NULL
534 In [1]: %R mydata=c(4,6,8.3); NULL
534
535
535 In [2]: %R -d mydata
536 In [2]: %R -d mydata
536
537
537 In [3]: mydata
538 In [3]: mydata
538 Out[3]: array([ 4. , 6. , 8.3])
539 Out[3]: array([ 4. , 6. , 8.3])
539
540
540 In [4]: %R names(mydata) = c('a','b','c'); NULL
541 In [4]: %R names(mydata) = c('a','b','c'); NULL
541
542
542 In [5]: %R -d mydata
543 In [5]: %R -d mydata
543
544
544 In [6]: mydata
545 In [6]: mydata
545 Out[6]:
546 Out[6]:
546 array((4.0, 6.0, 8.3),
547 array((4.0, 6.0, 8.3),
547 dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
548 dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
548
549
549 In [7]: %R -o mydata
550 In [7]: %R -o mydata
550
551
551 In [8]: mydata
552 In [8]: mydata
552 Out[8]: array([ 4. , 6. , 8.3])
553 Out[8]: array([ 4. , 6. , 8.3])
553
554
554 '''
555 '''
555
556
556 args = parse_argstring(self.R, line)
557 args = parse_argstring(self.R, line)
557
558
558 # arguments 'code' in line are prepended to
559 # arguments 'code' in line are prepended to
559 # the cell lines
560 # the cell lines
560
561
561 if cell is None:
562 if cell is None:
562 code = ''
563 code = ''
563 return_output = True
564 return_output = True
564 line_mode = True
565 line_mode = True
565 else:
566 else:
566 code = cell
567 code = cell
567 return_output = False
568 return_output = False
568 line_mode = False
569 line_mode = False
569
570
570 code = ' '.join(args.code) + code
571 code = ' '.join(args.code) + code
571
572
572 # if there is no local namespace then default to an empty dict
573 # if there is no local namespace then default to an empty dict
573 if local_ns is None:
574 if local_ns is None:
574 local_ns = {}
575 local_ns = {}
575
576
576 if args.input:
577 if args.input:
577 for input in ','.join(args.input).split(','):
578 for input in ','.join(args.input).split(','):
578 try:
579 try:
579 val = local_ns[input]
580 val = local_ns[input]
580 except KeyError:
581 except KeyError:
581 try:
582 try:
582 val = self.shell.user_ns[input]
583 val = self.shell.user_ns[input]
583 except KeyError:
584 except KeyError:
584 raise NameError("name '%s' is not defined" % input)
585 raise NameError("name '%s' is not defined" % input)
585 self.r.assign(input, self.pyconverter(val))
586 self.r.assign(input, self.pyconverter(val))
586
587
587 if getattr(args, 'units') is not None:
588 if getattr(args, 'units') is not None:
588 if args.units != "px" and getattr(args, 'res') is None:
589 if args.units != "px" and getattr(args, 'res') is None:
589 args.res = 72
590 args.res = 72
590 args.units = '"%s"' % args.units
591 args.units = '"%s"' % args.units
591
592
592 png_argdict = dict([(n, getattr(args, n)) for n in ['units', 'res', 'height', 'width', 'bg', 'pointsize']])
593 png_argdict = dict([(n, getattr(args, n)) for n in ['units', 'res', 'height', 'width', 'bg', 'pointsize']])
593 png_args = ','.join(['%s=%s' % (o,v) for o, v in png_argdict.items() if v is not None])
594 png_args = ','.join(['%s=%s' % (o,v) for o, v in png_argdict.items() if v is not None])
594 # execute the R code in a temporary directory
595 # execute the R code in a temporary directory
595
596
596 tmpd = tempfile.mkdtemp()
597 tmpd = tempfile.mkdtemp()
597 self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd.replace('\\', '/'), png_args))
598 self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd.replace('\\', '/'), png_args))
598
599
599 text_output = ''
600 text_output = ''
600 try:
601 try:
601 if line_mode:
602 if line_mode:
602 for line in code.split(';'):
603 for line in code.split(';'):
603 text_result, result, visible = self.eval(line)
604 text_result, result, visible = self.eval(line)
604 text_output += text_result
605 text_output += text_result
605 if text_result:
606 if text_result:
606 # the last line printed something to the console so we won't return it
607 # the last line printed something to the console so we won't return it
607 return_output = False
608 return_output = False
608 else:
609 else:
609 text_result, result, visible = self.eval(code)
610 text_result, result, visible = self.eval(code)
610 text_output += text_result
611 text_output += text_result
611 if visible:
612 if visible:
612 old_writeconsole = ri.get_writeconsole()
613 old_writeconsole = ri.get_writeconsole()
613 ri.set_writeconsole(self.write_console)
614 ri.set_writeconsole(self.write_console)
614 ro.r.show(result)
615 ro.r.show(result)
615 text_output += self.flush()
616 text_output += self.flush()
616 ri.set_writeconsole(old_writeconsole)
617 ri.set_writeconsole(old_writeconsole)
617
618
618 except RInterpreterError as e:
619 except RInterpreterError as e:
619 print(e.stdout)
620 print(e.stdout)
620 if not e.stdout.endswith(e.err):
621 if not e.stdout.endswith(e.err):
621 print(e.err)
622 print(e.err)
622 rmtree(tmpd)
623 rmtree(tmpd)
623 return
624 return
624
625
625 self.r('dev.off()')
626 self.r('dev.off()')
626
627
627 # read out all the saved .png files
628 # read out all the saved .png files
628
629
629 images = [open(imgfile, 'rb').read() for imgfile in glob("%s/Rplots*png" % tmpd)]
630 images = [open(imgfile, 'rb').read() for imgfile in glob("%s/Rplots*png" % tmpd)]
630
631
631 # now publish the images
632 # now publish the images
632 # mimicking IPython/zmq/pylab/backend_inline.py
633 # mimicking IPython/zmq/pylab/backend_inline.py
633 fmt = 'png'
634 fmt = 'png'
634 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
635 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
635 mime = mimetypes[fmt]
636 mime = mimetypes[fmt]
636
637
637 # publish the printed R objects, if any
638 # publish the printed R objects, if any
638
639
639 display_data = []
640 display_data = []
640 if text_output:
641 if text_output:
641 display_data.append(('RMagic.R', {'text/plain':text_output}))
642 display_data.append(('RMagic.R', {'text/plain':text_output}))
642
643
643 # flush text streams before sending figures, helps a little with output
644 # flush text streams before sending figures, helps a little with output
644 for image in images:
645 for image in images:
645 # synchronization in the console (though it's a bandaid, not a real sln)
646 # synchronization in the console (though it's a bandaid, not a real sln)
646 sys.stdout.flush(); sys.stderr.flush()
647 sys.stdout.flush(); sys.stderr.flush()
647 display_data.append(('RMagic.R', {mime: image}))
648 display_data.append(('RMagic.R', {mime: image}))
648
649
649 # kill the temporary directory
650 # kill the temporary directory
650 rmtree(tmpd)
651 rmtree(tmpd)
651
652
652 # try to turn every output into a numpy array
653 # try to turn every output into a numpy array
653 # this means that output are assumed to be castable
654 # this means that output are assumed to be castable
654 # as numpy arrays
655 # as numpy arrays
655
656
656 if args.output:
657 if args.output:
657 for output in ','.join(args.output).split(','):
658 for output in ','.join(args.output).split(','):
658 self.shell.push({output:self.Rconverter(self.r(output), dataframe=False)})
659 self.shell.push({output:self.Rconverter(self.r(output), dataframe=False)})
659
660
660 if args.dataframe:
661 if args.dataframe:
661 for output in ','.join(args.dataframe).split(','):
662 for output in ','.join(args.dataframe).split(','):
662 self.shell.push({output:self.Rconverter(self.r(output), dataframe=True)})
663 self.shell.push({output:self.Rconverter(self.r(output), dataframe=True)})
663
664
664 for tag, disp_d in display_data:
665 for tag, disp_d in display_data:
665 publish_display_data(tag, disp_d)
666 publish_display_data(tag, disp_d)
666
667
667 # this will keep a reference to the display_data
668 # this will keep a reference to the display_data
668 # which might be useful to other objects who happen to use
669 # which might be useful to other objects who happen to use
669 # this method
670 # this method
670
671
671 if self.cache_display_data:
672 if self.cache_display_data:
672 self.display_cache = display_data
673 self.display_cache = display_data
673
674
674 # if in line mode and return_output, return the result as an ndarray
675 # if in line mode and return_output, return the result as an ndarray
675 if return_output and not args.noreturn:
676 if return_output and not args.noreturn:
676 if result != ri.NULL:
677 if result != ri.NULL:
677 return self.Rconverter(result, dataframe=False)
678 return self.Rconverter(result, dataframe=False)
678
679
679 __doc__ = __doc__.format(
680 __doc__ = __doc__.format(
680 R_DOC = ' '*8 + RMagics.R.__doc__,
681 R_DOC = ' '*8 + RMagics.R.__doc__,
681 RPUSH_DOC = ' '*8 + RMagics.Rpush.__doc__,
682 RPUSH_DOC = ' '*8 + RMagics.Rpush.__doc__,
682 RPULL_DOC = ' '*8 + RMagics.Rpull.__doc__,
683 RPULL_DOC = ' '*8 + RMagics.Rpull.__doc__,
683 RGET_DOC = ' '*8 + RMagics.Rget.__doc__
684 RGET_DOC = ' '*8 + RMagics.Rget.__doc__
684 )
685 )
685
686
686
687
687 def load_ipython_extension(ip):
688 def load_ipython_extension(ip):
688 """Load the extension in IPython."""
689 """Load the extension in IPython."""
689 ip.register_magics(RMagics)
690 ip.register_magics(RMagics)
690 # Initialising rpy2 interferes with readline. Since, at this point, we've
691 # Initialising rpy2 interferes with readline. Since, at this point, we've
691 # probably just loaded rpy2, we reset the delimiters. See issue gh-2759.
692 # probably just loaded rpy2, we reset the delimiters. See issue gh-2759.
692 if ip.has_readline:
693 if ip.has_readline:
693 ip.readline.set_completer_delims(ip.readline_delims)
694 ip.readline.set_completer_delims(ip.readline_delims)
@@ -1,204 +1,206 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
3 import __builtin__
3 import __builtin__
4 import functools
4 import functools
5 import sys
5 import sys
6 import re
6 import re
7 import types
7 import types
8
8
9 from .encoding import DEFAULT_ENCODING
9 from .encoding import DEFAULT_ENCODING
10
10
11 orig_open = open
11 orig_open = open
12
12
13 def no_code(x, encoding=None):
13 def no_code(x, encoding=None):
14 return x
14 return x
15
15
16 def decode(s, encoding=None):
16 def decode(s, encoding=None):
17 encoding = encoding or DEFAULT_ENCODING
17 encoding = encoding or DEFAULT_ENCODING
18 return s.decode(encoding, "replace")
18 return s.decode(encoding, "replace")
19
19
20 def encode(u, encoding=None):
20 def encode(u, encoding=None):
21 encoding = encoding or DEFAULT_ENCODING
21 encoding = encoding or DEFAULT_ENCODING
22 return u.encode(encoding, "replace")
22 return u.encode(encoding, "replace")
23
23
24
24
25 def cast_unicode(s, encoding=None):
25 def cast_unicode(s, encoding=None):
26 if isinstance(s, bytes):
26 if isinstance(s, bytes):
27 return decode(s, encoding)
27 return decode(s, encoding)
28 return s
28 return s
29
29
30 def cast_bytes(s, encoding=None):
30 def cast_bytes(s, encoding=None):
31 if not isinstance(s, bytes):
31 if not isinstance(s, bytes):
32 return encode(s, encoding)
32 return encode(s, encoding)
33 return s
33 return s
34
34
35 def _modify_str_or_docstring(str_change_func):
35 def _modify_str_or_docstring(str_change_func):
36 @functools.wraps(str_change_func)
36 @functools.wraps(str_change_func)
37 def wrapper(func_or_str):
37 def wrapper(func_or_str):
38 if isinstance(func_or_str, basestring):
38 if isinstance(func_or_str, basestring):
39 func = None
39 func = None
40 doc = func_or_str
40 doc = func_or_str
41 else:
41 else:
42 func = func_or_str
42 func = func_or_str
43 doc = func.__doc__
43 doc = func.__doc__
44
44
45 doc = str_change_func(doc)
45 doc = str_change_func(doc)
46
46
47 if func:
47 if func:
48 func.__doc__ = doc
48 func.__doc__ = doc
49 return func
49 return func
50 return doc
50 return doc
51 return wrapper
51 return wrapper
52
52
53 def safe_unicode(e):
53 def safe_unicode(e):
54 """unicode(e) with various fallbacks. Used for exceptions, which may not be
54 """unicode(e) with various fallbacks. Used for exceptions, which may not be
55 safe to call unicode() on.
55 safe to call unicode() on.
56 """
56 """
57 try:
57 try:
58 return unicode(e)
58 return unicode(e)
59 except UnicodeError:
59 except UnicodeError:
60 pass
60 pass
61
61
62 try:
62 try:
63 return str_to_unicode(str(e))
63 return str_to_unicode(str(e))
64 except UnicodeError:
64 except UnicodeError:
65 pass
65 pass
66
66
67 try:
67 try:
68 return str_to_unicode(repr(e))
68 return str_to_unicode(repr(e))
69 except UnicodeError:
69 except UnicodeError:
70 pass
70 pass
71
71
72 return u'Unrecoverably corrupt evalue'
72 return u'Unrecoverably corrupt evalue'
73
73
74 if sys.version_info[0] >= 3:
74 if sys.version_info[0] >= 3:
75 PY3 = True
75 PY3 = True
76
76
77 input = input
77 input = input
78 builtin_mod_name = "builtins"
78 builtin_mod_name = "builtins"
79
79
80 str_to_unicode = no_code
80 str_to_unicode = no_code
81 unicode_to_str = no_code
81 unicode_to_str = no_code
82 str_to_bytes = encode
82 str_to_bytes = encode
83 bytes_to_str = decode
83 bytes_to_str = decode
84 cast_bytes_py2 = no_code
84 cast_bytes_py2 = no_code
85
85
86 string_types = (str,)
86 string_types = (str,)
87 unicode_type = str
87
88
88 def isidentifier(s, dotted=False):
89 def isidentifier(s, dotted=False):
89 if dotted:
90 if dotted:
90 return all(isidentifier(a) for a in s.split("."))
91 return all(isidentifier(a) for a in s.split("."))
91 return s.isidentifier()
92 return s.isidentifier()
92
93
93 open = orig_open
94 open = orig_open
94
95
95 MethodType = types.MethodType
96 MethodType = types.MethodType
96
97
97 def execfile(fname, glob, loc=None):
98 def execfile(fname, glob, loc=None):
98 loc = loc if (loc is not None) else glob
99 loc = loc if (loc is not None) else glob
99 with open(fname, 'rb') as f:
100 with open(fname, 'rb') as f:
100 exec compile(f.read(), fname, 'exec') in glob, loc
101 exec compile(f.read(), fname, 'exec') in glob, loc
101
102
102 # Refactor print statements in doctests.
103 # Refactor print statements in doctests.
103 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
104 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
104 def _print_statement_sub(match):
105 def _print_statement_sub(match):
105 expr = match.groups('expr')
106 expr = match.groups('expr')
106 return "print(%s)" % expr
107 return "print(%s)" % expr
107
108
108 @_modify_str_or_docstring
109 @_modify_str_or_docstring
109 def doctest_refactor_print(doc):
110 def doctest_refactor_print(doc):
110 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
111 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
111 unfortunately doesn't pick up on our doctests.
112 unfortunately doesn't pick up on our doctests.
112
113
113 Can accept a string or a function, so it can be used as a decorator."""
114 Can accept a string or a function, so it can be used as a decorator."""
114 return _print_statement_re.sub(_print_statement_sub, doc)
115 return _print_statement_re.sub(_print_statement_sub, doc)
115
116
116 # Abstract u'abc' syntax:
117 # Abstract u'abc' syntax:
117 @_modify_str_or_docstring
118 @_modify_str_or_docstring
118 def u_format(s):
119 def u_format(s):
119 """"{u}'abc'" --> "'abc'" (Python 3)
120 """"{u}'abc'" --> "'abc'" (Python 3)
120
121
121 Accepts a string or a function, so it can be used as a decorator."""
122 Accepts a string or a function, so it can be used as a decorator."""
122 return s.format(u='')
123 return s.format(u='')
123
124
124 else:
125 else:
125 PY3 = False
126 PY3 = False
126
127
127 input = raw_input
128 input = raw_input
128 builtin_mod_name = "__builtin__"
129 builtin_mod_name = "__builtin__"
129
130
130 str_to_unicode = decode
131 str_to_unicode = decode
131 unicode_to_str = encode
132 unicode_to_str = encode
132 str_to_bytes = no_code
133 str_to_bytes = no_code
133 bytes_to_str = no_code
134 bytes_to_str = no_code
134 cast_bytes_py2 = cast_bytes
135 cast_bytes_py2 = cast_bytes
135
136
136 string_types = (str, unicode)
137 string_types = (str, unicode)
138 unicode_type = unicode
137
139
138 import re
140 import re
139 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
141 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
140 def isidentifier(s, dotted=False):
142 def isidentifier(s, dotted=False):
141 if dotted:
143 if dotted:
142 return all(isidentifier(a) for a in s.split("."))
144 return all(isidentifier(a) for a in s.split("."))
143 return bool(_name_re.match(s))
145 return bool(_name_re.match(s))
144
146
145 class open(object):
147 class open(object):
146 """Wrapper providing key part of Python 3 open() interface."""
148 """Wrapper providing key part of Python 3 open() interface."""
147 def __init__(self, fname, mode="r", encoding="utf-8"):
149 def __init__(self, fname, mode="r", encoding="utf-8"):
148 self.f = orig_open(fname, mode)
150 self.f = orig_open(fname, mode)
149 self.enc = encoding
151 self.enc = encoding
150
152
151 def write(self, s):
153 def write(self, s):
152 return self.f.write(s.encode(self.enc))
154 return self.f.write(s.encode(self.enc))
153
155
154 def read(self, size=-1):
156 def read(self, size=-1):
155 return self.f.read(size).decode(self.enc)
157 return self.f.read(size).decode(self.enc)
156
158
157 def close(self):
159 def close(self):
158 return self.f.close()
160 return self.f.close()
159
161
160 def __enter__(self):
162 def __enter__(self):
161 return self
163 return self
162
164
163 def __exit__(self, etype, value, traceback):
165 def __exit__(self, etype, value, traceback):
164 self.f.close()
166 self.f.close()
165
167
166 def MethodType(func, instance):
168 def MethodType(func, instance):
167 return types.MethodType(func, instance, type(instance))
169 return types.MethodType(func, instance, type(instance))
168
170
169 # don't override system execfile on 2.x:
171 # don't override system execfile on 2.x:
170 execfile = execfile
172 execfile = execfile
171
173
172 def doctest_refactor_print(func_or_str):
174 def doctest_refactor_print(func_or_str):
173 return func_or_str
175 return func_or_str
174
176
175
177
176 # Abstract u'abc' syntax:
178 # Abstract u'abc' syntax:
177 @_modify_str_or_docstring
179 @_modify_str_or_docstring
178 def u_format(s):
180 def u_format(s):
179 """"{u}'abc'" --> "u'abc'" (Python 2)
181 """"{u}'abc'" --> "u'abc'" (Python 2)
180
182
181 Accepts a string or a function, so it can be used as a decorator."""
183 Accepts a string or a function, so it can be used as a decorator."""
182 return s.format(u='u')
184 return s.format(u='u')
183
185
184 if sys.platform == 'win32':
186 if sys.platform == 'win32':
185 def execfile(fname, glob=None, loc=None):
187 def execfile(fname, glob=None, loc=None):
186 loc = loc if (loc is not None) else glob
188 loc = loc if (loc is not None) else glob
187 # The rstrip() is necessary b/c trailing whitespace in files will
189 # The rstrip() is necessary b/c trailing whitespace in files will
188 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
190 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
189 # but we still support 2.6). See issue 1027.
191 # but we still support 2.6). See issue 1027.
190 scripttext = __builtin__.open(fname).read().rstrip() + '\n'
192 scripttext = __builtin__.open(fname).read().rstrip() + '\n'
191 # compile converts unicode filename to str assuming
193 # compile converts unicode filename to str assuming
192 # ascii. Let's do the conversion before calling compile
194 # ascii. Let's do the conversion before calling compile
193 if isinstance(fname, unicode):
195 if isinstance(fname, unicode):
194 filename = unicode_to_str(fname)
196 filename = unicode_to_str(fname)
195 else:
197 else:
196 filename = fname
198 filename = fname
197 exec compile(scripttext, filename, 'exec') in glob, loc
199 exec compile(scripttext, filename, 'exec') in glob, loc
198 else:
200 else:
199 def execfile(fname, *where):
201 def execfile(fname, *where):
200 if isinstance(fname, unicode):
202 if isinstance(fname, unicode):
201 filename = fname.encode(sys.getfilesystemencoding())
203 filename = fname.encode(sys.getfilesystemencoding())
202 else:
204 else:
203 filename = fname
205 filename = fname
204 __builtin__.execfile(filename, *where)
206 __builtin__.execfile(filename, *where)
General Comments 0
You need to be logged in to leave comments. Login now