##// END OF EJS Templates
Modify tests to expect unicode. Now all tests pass again.
Thomas Kluyver -
Show More
@@ -1,383 +1,384 b''
1 1 # -*- coding: utf-8 -*-
2 2 # coding: utf-8
3 3 """A simple configuration system.
4 4
5 5 Authors
6 6 -------
7 7 * Brian Granger
8 8 * Fernando Perez
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2009 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import __builtin__
23 23 import os
24 24 import sys
25 25
26 26 from IPython.external import argparse
27 27 from IPython.utils.path import filefind
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Exceptions
31 31 #-----------------------------------------------------------------------------
32 32
33 33
34 34 class ConfigError(Exception):
35 35 pass
36 36
37 37
38 38 class ConfigLoaderError(ConfigError):
39 39 pass
40 40
41 41 #-----------------------------------------------------------------------------
42 42 # Argparse fix
43 43 #-----------------------------------------------------------------------------
44 44
45 45 # Unfortunately argparse by default prints help messages to stderr instead of
46 46 # stdout. This makes it annoying to capture long help screens at the command
47 47 # line, since one must know how to pipe stderr, which many users don't know how
48 48 # to do. So we override the print_help method with one that defaults to
49 49 # stdout and use our class instead.
50 50
51 51 class ArgumentParser(argparse.ArgumentParser):
52 52 """Simple argparse subclass that prints help to stdout by default."""
53 53
54 54 def print_help(self, file=None):
55 55 if file is None:
56 56 file = sys.stdout
57 57 return super(ArgumentParser, self).print_help(file)
58 58
59 59 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
60 60
61 61 #-----------------------------------------------------------------------------
62 62 # Config class for holding config information
63 63 #-----------------------------------------------------------------------------
64 64
65 65
66 66 class Config(dict):
67 67 """An attribute based dict that can do smart merges."""
68 68
69 69 def __init__(self, *args, **kwds):
70 70 dict.__init__(self, *args, **kwds)
71 71 # This sets self.__dict__ = self, but it has to be done this way
72 72 # because we are also overriding __setattr__.
73 73 dict.__setattr__(self, '__dict__', self)
74 74
75 75 def _merge(self, other):
76 76 to_update = {}
77 77 for k, v in other.iteritems():
78 78 if not self.has_key(k):
79 79 to_update[k] = v
80 80 else: # I have this key
81 81 if isinstance(v, Config):
82 82 # Recursively merge common sub Configs
83 83 self[k]._merge(v)
84 84 else:
85 85 # Plain updates for non-Configs
86 86 to_update[k] = v
87 87
88 88 self.update(to_update)
89 89
90 90 def _is_section_key(self, key):
91 91 if key[0].upper()==key[0] and not key.startswith('_'):
92 92 return True
93 93 else:
94 94 return False
95 95
96 96 def __contains__(self, key):
97 97 if self._is_section_key(key):
98 98 return True
99 99 else:
100 100 return super(Config, self).__contains__(key)
101 101 # .has_key is deprecated for dictionaries.
102 102 has_key = __contains__
103 103
104 104 def _has_section(self, key):
105 105 if self._is_section_key(key):
106 106 if super(Config, self).__contains__(key):
107 107 return True
108 108 return False
109 109
110 110 def copy(self):
111 111 return type(self)(dict.copy(self))
112 112
113 113 def __copy__(self):
114 114 return self.copy()
115 115
116 116 def __deepcopy__(self, memo):
117 117 import copy
118 118 return type(self)(copy.deepcopy(self.items()))
119 119
120 120 def __getitem__(self, key):
121 121 # Because we use this for an exec namespace, we need to delegate
122 122 # the lookup of names in __builtin__ to itself. This means
123 123 # that you can't have section or attribute names that are
124 124 # builtins.
125 125 try:
126 126 return getattr(__builtin__, key)
127 127 except AttributeError:
128 128 pass
129 129 if self._is_section_key(key):
130 130 try:
131 131 return dict.__getitem__(self, key)
132 132 except KeyError:
133 133 c = Config()
134 134 dict.__setitem__(self, key, c)
135 135 return c
136 136 else:
137 137 return dict.__getitem__(self, key)
138 138
139 139 def __setitem__(self, key, value):
140 140 # Don't allow names in __builtin__ to be modified.
141 141 if hasattr(__builtin__, key):
142 142 raise ConfigError('Config variable names cannot have the same name '
143 143 'as a Python builtin: %s' % key)
144 144 if self._is_section_key(key):
145 145 if not isinstance(value, Config):
146 146 raise ValueError('values whose keys begin with an uppercase '
147 147 'char must be Config instances: %r, %r' % (key, value))
148 148 else:
149 149 dict.__setitem__(self, key, value)
150 150
151 151 def __getattr__(self, key):
152 152 try:
153 153 return self.__getitem__(key)
154 154 except KeyError, e:
155 155 raise AttributeError(e)
156 156
157 157 def __setattr__(self, key, value):
158 158 try:
159 159 self.__setitem__(key, value)
160 160 except KeyError, e:
161 161 raise AttributeError(e)
162 162
163 163 def __delattr__(self, key):
164 164 try:
165 165 dict.__delitem__(self, key)
166 166 except KeyError, e:
167 167 raise AttributeError(e)
168 168
169 169
170 170 #-----------------------------------------------------------------------------
171 171 # Config loading classes
172 172 #-----------------------------------------------------------------------------
173 173
174 174
175 175 class ConfigLoader(object):
176 176 """A object for loading configurations from just about anywhere.
177 177
178 178 The resulting configuration is packaged as a :class:`Struct`.
179 179
180 180 Notes
181 181 -----
182 182 A :class:`ConfigLoader` does one thing: load a config from a source
183 183 (file, command line arguments) and returns the data as a :class:`Struct`.
184 184 There are lots of things that :class:`ConfigLoader` does not do. It does
185 185 not implement complex logic for finding config files. It does not handle
186 186 default values or merge multiple configs. These things need to be
187 187 handled elsewhere.
188 188 """
189 189
190 190 def __init__(self):
191 191 """A base class for config loaders.
192 192
193 193 Examples
194 194 --------
195 195
196 196 >>> cl = ConfigLoader()
197 197 >>> config = cl.load_config()
198 198 >>> config
199 199 {}
200 200 """
201 201 self.clear()
202 202
203 203 def clear(self):
204 204 self.config = Config()
205 205
206 206 def load_config(self):
207 207 """Load a config from somewhere, return a :class:`Config` instance.
208 208
209 209 Usually, this will cause self.config to be set and then returned.
210 210 However, in most cases, :meth:`ConfigLoader.clear` should be called
211 211 to erase any previous state.
212 212 """
213 213 self.clear()
214 214 return self.config
215 215
216 216
217 217 class FileConfigLoader(ConfigLoader):
218 218 """A base class for file based configurations.
219 219
220 220 As we add more file based config loaders, the common logic should go
221 221 here.
222 222 """
223 223 pass
224 224
225 225
226 226 class PyFileConfigLoader(FileConfigLoader):
227 227 """A config loader for pure python files.
228 228
229 229 This calls execfile on a plain python file and looks for attributes
230 230 that are all caps. These attribute are added to the config Struct.
231 231 """
232 232
233 233 def __init__(self, filename, path=None):
234 234 """Build a config loader for a filename and path.
235 235
236 236 Parameters
237 237 ----------
238 238 filename : str
239 239 The file name of the config file.
240 240 path : str, list, tuple
241 241 The path to search for the config file on, or a sequence of
242 242 paths to try in order.
243 243 """
244 244 super(PyFileConfigLoader, self).__init__()
245 245 self.filename = filename
246 246 self.path = path
247 247 self.full_filename = ''
248 248 self.data = None
249 249
250 250 def load_config(self):
251 251 """Load the config from a file and return it as a Struct."""
252 252 self.clear()
253 253 self._find_file()
254 254 self._read_file_as_dict()
255 255 self._convert_to_config()
256 256 return self.config
257 257
258 258 def _find_file(self):
259 259 """Try to find the file by searching the paths."""
260 260 self.full_filename = filefind(self.filename, self.path)
261 261
262 262 def _read_file_as_dict(self):
263 263 """Load the config file into self.config, with recursive loading."""
264 264 # This closure is made available in the namespace that is used
265 265 # to exec the config file. This allows users to call
266 266 # load_subconfig('myconfig.py') to load config files recursively.
267 267 # It needs to be a closure because it has references to self.path
268 268 # and self.config. The sub-config is loaded with the same path
269 269 # as the parent, but it uses an empty config which is then merged
270 270 # with the parents.
271 271 def load_subconfig(fname):
272 272 loader = PyFileConfigLoader(fname, self.path)
273 273 try:
274 274 sub_config = loader.load_config()
275 275 except IOError:
276 276 # Pass silently if the sub config is not there. This happens
277 277 # when a user us using a profile, but not the default config.
278 278 pass
279 279 else:
280 280 self.config._merge(sub_config)
281 281
282 282 # Again, this needs to be a closure and should be used in config
283 283 # files to get the config being loaded.
284 284 def get_config():
285 285 return self.config
286 286
287 287 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
288 288 fs_encoding = sys.getfilesystemencoding() or 'ascii'
289 289 conf_filename = self.full_filename.encode(fs_encoding)
290 290 execfile(conf_filename, namespace)
291 291
292 292 def _convert_to_config(self):
293 293 if self.data is None:
294 294 ConfigLoaderError('self.data does not exist')
295 295
296 296
297 297 class CommandLineConfigLoader(ConfigLoader):
298 298 """A config loader for command line arguments.
299 299
300 300 As we add more command line based loaders, the common logic should go
301 301 here.
302 302 """
303 303
304 304
305 305 class ArgParseConfigLoader(CommandLineConfigLoader):
306 306
307 307 def __init__(self, argv=None, *parser_args, **parser_kw):
308 308 """Create a config loader for use with argparse.
309 309
310 310 Parameters
311 311 ----------
312 312
313 313 argv : optional, list
314 314 If given, used to read command-line arguments from, otherwise
315 315 sys.argv[1:] is used.
316 316
317 317 parser_args : tuple
318 318 A tuple of positional arguments that will be passed to the
319 319 constructor of :class:`argparse.ArgumentParser`.
320 320
321 321 parser_kw : dict
322 322 A tuple of keyword arguments that will be passed to the
323 323 constructor of :class:`argparse.ArgumentParser`.
324 324 """
325 325 super(CommandLineConfigLoader, self).__init__()
326 326 if argv == None:
327 327 argv = sys.argv[1:]
328 328 self.argv = argv
329 329 self.parser_args = parser_args
330 330 self.version = parser_kw.pop("version", None)
331 331 kwargs = dict(argument_default=argparse.SUPPRESS)
332 332 kwargs.update(parser_kw)
333 333 self.parser_kw = kwargs
334 334
335 335 def load_config(self, args=None):
336 336 """Parse command line arguments and return as a Struct.
337 337
338 338 Parameters
339 339 ----------
340 340
341 341 args : optional, list
342 342 If given, a list with the structure of sys.argv[1:] to parse
343 343 arguments from. If not given, the instance's self.argv attribute
344 344 (given at construction time) is used."""
345 345 self.clear()
346 346 if args is None:
347 347 args = self.argv
348 348 self._create_parser()
349 349 self._parse_args(args)
350 350 self._convert_to_config()
351 351 return self.config
352 352
353 353 def get_extra_args(self):
354 354 if hasattr(self, 'extra_args'):
355 355 return self.extra_args
356 356 else:
357 357 return []
358 358
359 359 def _create_parser(self):
360 360 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
361 361 self._add_arguments()
362 362
363 363 def _add_arguments(self):
364 364 raise NotImplementedError("subclasses must implement _add_arguments")
365 365
366 366 def _parse_args(self, args):
367 367 """self.parser->self.parsed_data"""
368 368 # decode sys.argv to support unicode command-line options
369 369 uargs = []
370 370 for a in args:
371 371 if isinstance(a, str):
372 372 # don't decode if we already got unicode
373 a = a.decode(sys.stdin.encoding)
373 a = a.decode(sys.stdin.encoding or
374 sys.getdefaultencoding())
374 375 uargs.append(a)
375 376 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
376 377
377 378 def _convert_to_config(self):
378 379 """self.parsed_data->self.config"""
379 380 for k, v in vars(self.parsed_data).iteritems():
380 381 exec_str = 'self.config.' + k + '= v'
381 382 exec exec_str in locals(), globals()
382 383
383 384
@@ -1,1009 +1,1009 b''
1 1 """Analysis of text input into executable blocks.
2 2
3 3 The main class in this module, :class:`InputSplitter`, is designed to break
4 4 input from either interactive, line-by-line environments or block-based ones,
5 5 into standalone blocks that can be executed by Python as 'single' statements
6 6 (thus triggering sys.displayhook).
7 7
8 8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
9 9 with full support for the extended IPython syntax (magics, system calls, etc).
10 10
11 11 For more details, see the class docstring below.
12 12
13 13 Syntax Transformations
14 14 ----------------------
15 15
16 16 One of the main jobs of the code in this file is to apply all syntax
17 17 transformations that make up 'the IPython language', i.e. magics, shell
18 18 escapes, etc. All transformations should be implemented as *fully stateless*
19 19 entities, that simply take one line as their input and return a line.
20 20 Internally for implementation purposes they may be a normal function or a
21 21 callable object, but the only input they receive will be a single line and they
22 22 should only return a line, without holding any data-dependent state between
23 23 calls.
24 24
25 25 As an example, the EscapedTransformer is a class so we can more clearly group
26 26 together the functionality of dispatching to individual functions based on the
27 27 starting escape character, but the only method for public use is its call
28 28 method.
29 29
30 30
31 31 ToDo
32 32 ----
33 33
34 34 - Should we make push() actually raise an exception once push_accepts_more()
35 35 returns False?
36 36
37 37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
38 38 at least just attributes of a class so not really very exposed.
39 39
40 40 - Think about the best way to support dynamic things: automagic, autocall,
41 41 macros, etc.
42 42
43 43 - Think of a better heuristic for the application of the transforms in
44 44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
45 45 track indentation change events (indent, dedent, nothing) and apply them only
46 46 if the indentation went up, but not otherwise.
47 47
48 48 - Think of the cleanest way for supporting user-specified transformations (the
49 49 user prefilters we had before).
50 50
51 51 Authors
52 52 -------
53 53
54 54 * Fernando Perez
55 55 * Brian Granger
56 56 """
57 57 #-----------------------------------------------------------------------------
58 58 # Copyright (C) 2010 The IPython Development Team
59 59 #
60 60 # Distributed under the terms of the BSD License. The full license is in
61 61 # the file COPYING, distributed as part of this software.
62 62 #-----------------------------------------------------------------------------
63 63 from __future__ import print_function
64 64
65 65 #-----------------------------------------------------------------------------
66 66 # Imports
67 67 #-----------------------------------------------------------------------------
68 68 # stdlib
69 69 import ast
70 70 import codeop
71 71 import re
72 72 import sys
73 73
74 74 # IPython modules
75 75 from IPython.utils.text import make_quoted_expr
76 76
77 77 #-----------------------------------------------------------------------------
78 78 # Globals
79 79 #-----------------------------------------------------------------------------
80 80
81 81 # The escape sequences that define the syntax transformations IPython will
82 82 # apply to user input. These can NOT be just changed here: many regular
83 83 # expressions and other parts of the code may use their hardcoded values, and
84 84 # for all intents and purposes they constitute the 'IPython syntax', so they
85 85 # should be considered fixed.
86 86
87 87 ESC_SHELL = '!' # Send line to underlying system shell
88 88 ESC_SH_CAP = '!!' # Send line to system shell and capture output
89 89 ESC_HELP = '?' # Find information about object
90 90 ESC_HELP2 = '??' # Find extra-detailed information about object
91 91 ESC_MAGIC = '%' # Call magic function
92 92 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
93 93 ESC_QUOTE2 = ';' # Quote all args as a single string, call
94 94 ESC_PAREN = '/' # Call first argument with rest of line as arguments
95 95
96 96 #-----------------------------------------------------------------------------
97 97 # Utilities
98 98 #-----------------------------------------------------------------------------
99 99
100 100 # FIXME: These are general-purpose utilities that later can be moved to the
101 101 # general ward. Kept here for now because we're being very strict about test
102 102 # coverage with this code, and this lets us ensure that we keep 100% coverage
103 103 # while developing.
104 104
105 105 # compiled regexps for autoindent management
106 106 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
107 107 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
108 108
109 109 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
110 110 # before pure comments
111 111 comment_line_re = re.compile('^\s*\#')
112 112
113 113
114 114 def num_ini_spaces(s):
115 115 """Return the number of initial spaces in a string.
116 116
117 117 Note that tabs are counted as a single space. For now, we do *not* support
118 118 mixing of tabs and spaces in the user's input.
119 119
120 120 Parameters
121 121 ----------
122 122 s : string
123 123
124 124 Returns
125 125 -------
126 126 n : int
127 127 """
128 128
129 129 ini_spaces = ini_spaces_re.match(s)
130 130 if ini_spaces:
131 131 return ini_spaces.end()
132 132 else:
133 133 return 0
134 134
135 135
136 136 def remove_comments(src):
137 137 """Remove all comments from input source.
138 138
139 139 Note: comments are NOT recognized inside of strings!
140 140
141 141 Parameters
142 142 ----------
143 143 src : string
144 144 A single or multiline input string.
145 145
146 146 Returns
147 147 -------
148 148 String with all Python comments removed.
149 149 """
150 150
151 151 return re.sub('#.*', '', src)
152 152
153 153
154 154 def get_input_encoding():
155 155 """Return the default standard input encoding.
156 156
157 157 If sys.stdin has no encoding, 'ascii' is returned."""
158 158 # There are strange environments for which sys.stdin.encoding is None. We
159 159 # ensure that a valid encoding is returned.
160 160 encoding = getattr(sys.stdin, 'encoding', None)
161 161 if encoding is None:
162 162 encoding = 'ascii'
163 163 return encoding
164 164
165 165 #-----------------------------------------------------------------------------
166 166 # Classes and functions for normal Python syntax handling
167 167 #-----------------------------------------------------------------------------
168 168
169 169 # HACK! This implementation, written by Robert K a while ago using the
170 170 # compiler module, is more robust than the other one below, but it expects its
171 171 # input to be pure python (no ipython syntax). For now we're using it as a
172 172 # second-pass splitter after the first pass transforms the input to pure
173 173 # python.
174 174
175 175 def split_blocks(python):
176 176 """ Split multiple lines of code into discrete commands that can be
177 177 executed singly.
178 178
179 179 Parameters
180 180 ----------
181 181 python : str
182 182 Pure, exec'able Python code.
183 183
184 184 Returns
185 185 -------
186 186 commands : list of str
187 187 Separate commands that can be exec'ed independently.
188 188 """
189 189 # compiler.parse treats trailing spaces after a newline as a
190 190 # SyntaxError. This is different than codeop.CommandCompiler, which
191 191 # will compile the trailng spaces just fine. We simply strip any
192 192 # trailing whitespace off. Passing a string with trailing whitespace
193 193 # to exec will fail however. There seems to be some inconsistency in
194 194 # how trailing whitespace is handled, but this seems to work.
195 195 python_ori = python # save original in case we bail on error
196 196 python = python.strip()
197 197
198 198 # The compiler module will parse the code into an abstract syntax tree.
199 199 # This has a bug with str("a\nb"), but not str("""a\nb""")!!!
200 200 try:
201 201 code_ast = ast.parse(python)
202 202 except:
203 203 return [python_ori]
204 204
205 205 # Uncomment to help debug the ast tree
206 206 # for n in code_ast.body:
207 207 # print n.lineno,'->',n
208 208
209 209 # Each separate command is available by iterating over ast.node. The
210 210 # lineno attribute is the line number (1-indexed) beginning the commands
211 211 # suite.
212 212 # lines ending with ";" yield a Discard Node that doesn't have a lineno
213 213 # attribute. These nodes can and should be discarded. But there are
214 214 # other situations that cause Discard nodes that shouldn't be discarded.
215 215 # We might eventually discover other cases where lineno is None and have
216 216 # to put in a more sophisticated test.
217 217 linenos = [x.lineno-1 for x in code_ast.body if x.lineno is not None]
218 218
219 219 # When we finally get the slices, we will need to slice all the way to
220 220 # the end even though we don't have a line number for it. Fortunately,
221 221 # None does the job nicely.
222 222 linenos.append(None)
223 223
224 224 # Same problem at the other end: sometimes the ast tree has its
225 225 # first complete statement not starting on line 0. In this case
226 226 # we might miss part of it. This fixes ticket 266993. Thanks Gael!
227 227 linenos[0] = 0
228 228
229 229 lines = python.splitlines()
230 230
231 231 # Create a list of atomic commands.
232 232 cmds = []
233 233 for i, j in zip(linenos[:-1], linenos[1:]):
234 234 cmd = lines[i:j]
235 235 if cmd:
236 236 cmds.append('\n'.join(cmd)+'\n')
237 237
238 238 return cmds
239 239
240 240
241 241 class InputSplitter(object):
242 242 """An object that can split Python source input in executable blocks.
243 243
244 244 This object is designed to be used in one of two basic modes:
245 245
246 246 1. By feeding it python source line-by-line, using :meth:`push`. In this
247 247 mode, it will return on each push whether the currently pushed code
248 248 could be executed already. In addition, it provides a method called
249 249 :meth:`push_accepts_more` that can be used to query whether more input
250 250 can be pushed into a single interactive block.
251 251
252 252 2. By calling :meth:`split_blocks` with a single, multiline Python string,
253 253 that is then split into blocks each of which can be executed
254 254 interactively as a single statement.
255 255
256 256 This is a simple example of how an interactive terminal-based client can use
257 257 this tool::
258 258
259 259 isp = InputSplitter()
260 260 while isp.push_accepts_more():
261 261 indent = ' '*isp.indent_spaces
262 262 prompt = '>>> ' + indent
263 263 line = indent + raw_input(prompt)
264 264 isp.push(line)
265 265 print 'Input source was:\n', isp.source_reset(),
266 266 """
267 267 # Number of spaces of indentation computed from input that has been pushed
268 268 # so far. This is the attributes callers should query to get the current
269 269 # indentation level, in order to provide auto-indent facilities.
270 270 indent_spaces = 0
271 271 # String, indicating the default input encoding. It is computed by default
272 272 # at initialization time via get_input_encoding(), but it can be reset by a
273 273 # client with specific knowledge of the encoding.
274 274 encoding = ''
275 275 # String where the current full source input is stored, properly encoded.
276 276 # Reading this attribute is the normal way of querying the currently pushed
277 277 # source code, that has been properly encoded.
278 278 source = ''
279 279 # Code object corresponding to the current source. It is automatically
280 280 # synced to the source, so it can be queried at any time to obtain the code
281 281 # object; it will be None if the source doesn't compile to valid Python.
282 282 code = None
283 283 # Input mode
284 284 input_mode = 'line'
285 285
286 286 # Private attributes
287 287
288 288 # List with lines of input accumulated so far
289 289 _buffer = None
290 290 # Command compiler
291 291 _compile = None
292 292 # Mark when input has changed indentation all the way back to flush-left
293 293 _full_dedent = False
294 294 # Boolean indicating whether the current block is complete
295 295 _is_complete = None
296 296
297 297 def __init__(self, input_mode=None):
298 298 """Create a new InputSplitter instance.
299 299
300 300 Parameters
301 301 ----------
302 302 input_mode : str
303 303
304 304 One of ['line', 'cell']; default is 'line'.
305 305
306 306 The input_mode parameter controls how new inputs are used when fed via
307 307 the :meth:`push` method:
308 308
309 309 - 'line': meant for line-oriented clients, inputs are appended one at a
310 310 time to the internal buffer and the whole buffer is compiled.
311 311
312 312 - 'cell': meant for clients that can edit multi-line 'cells' of text at
313 313 a time. A cell can contain one or more blocks that can be compile in
314 314 'single' mode by Python. In this mode, each new input new input
315 315 completely replaces all prior inputs. Cell mode is thus equivalent
316 316 to prepending a full reset() to every push() call.
317 317 """
318 318 self._buffer = []
319 319 self._compile = codeop.CommandCompiler()
320 320 self.encoding = get_input_encoding()
321 321 self.input_mode = InputSplitter.input_mode if input_mode is None \
322 322 else input_mode
323 323
324 324 def reset(self):
325 325 """Reset the input buffer and associated state."""
326 326 self.indent_spaces = 0
327 327 self._buffer[:] = []
328 328 self.source = ''
329 329 self.code = None
330 330 self._is_complete = False
331 331 self._full_dedent = False
332 332
333 333 def source_reset(self):
334 334 """Return the input source and perform a full reset.
335 335 """
336 336 out = self.source
337 337 self.reset()
338 338 return out
339 339
340 340 def push(self, lines):
341 341 """Push one or more lines of input.
342 342
343 343 This stores the given lines and returns a status code indicating
344 344 whether the code forms a complete Python block or not.
345 345
346 346 Any exceptions generated in compilation are swallowed, but if an
347 347 exception was produced, the method returns True.
348 348
349 349 Parameters
350 350 ----------
351 351 lines : string
352 352 One or more lines of Python input.
353 353
354 354 Returns
355 355 -------
356 356 is_complete : boolean
357 357 True if the current input source (the result of the current input
358 358 plus prior inputs) forms a complete Python execution block. Note that
359 359 this value is also stored as a private attribute (_is_complete), so it
360 360 can be queried at any time.
361 361 """
362 362 if self.input_mode == 'cell':
363 363 self.reset()
364 364
365 365 self._store(lines)
366 366 source = self.source
367 367
368 368 # Before calling _compile(), reset the code object to None so that if an
369 369 # exception is raised in compilation, we don't mislead by having
370 370 # inconsistent code/source attributes.
371 371 self.code, self._is_complete = None, None
372 372
373 373 # Honor termination lines properly
374 374 if source.rstrip().endswith('\\'):
375 375 return False
376 376
377 377 self._update_indent(lines)
378 378 try:
379 379 self.code = self._compile(source)
380 380 # Invalid syntax can produce any of a number of different errors from
381 381 # inside the compiler, so we have to catch them all. Syntax errors
382 382 # immediately produce a 'ready' block, so the invalid Python can be
383 383 # sent to the kernel for evaluation with possible ipython
384 384 # special-syntax conversion.
385 385 except (SyntaxError, OverflowError, ValueError, TypeError,
386 386 MemoryError):
387 387 self._is_complete = True
388 388 else:
389 389 # Compilation didn't produce any exceptions (though it may not have
390 390 # given a complete code object)
391 391 self._is_complete = self.code is not None
392 392
393 393 return self._is_complete
394 394
395 395 def push_accepts_more(self):
396 396 """Return whether a block of interactive input can accept more input.
397 397
398 398 This method is meant to be used by line-oriented frontends, who need to
399 399 guess whether a block is complete or not based solely on prior and
400 400 current input lines. The InputSplitter considers it has a complete
401 401 interactive block and will not accept more input only when either a
402 402 SyntaxError is raised, or *all* of the following are true:
403 403
404 404 1. The input compiles to a complete statement.
405 405
406 406 2. The indentation level is flush-left (because if we are indented,
407 407 like inside a function definition or for loop, we need to keep
408 408 reading new input).
409 409
410 410 3. There is one extra line consisting only of whitespace.
411 411
412 412 Because of condition #3, this method should be used only by
413 413 *line-oriented* frontends, since it means that intermediate blank lines
414 414 are not allowed in function definitions (or any other indented block).
415 415
416 416 Block-oriented frontends that have a separate keyboard event to
417 417 indicate execution should use the :meth:`split_blocks` method instead.
418 418
419 419 If the current input produces a syntax error, this method immediately
420 420 returns False but does *not* raise the syntax error exception, as
421 421 typically clients will want to send invalid syntax to an execution
422 422 backend which might convert the invalid syntax into valid Python via
423 423 one of the dynamic IPython mechanisms.
424 424 """
425 425
426 426 # With incomplete input, unconditionally accept more
427 427 if not self._is_complete:
428 428 return True
429 429
430 430 # If we already have complete input and we're flush left, the answer
431 431 # depends. In line mode, if there hasn't been any indentation,
432 432 # that's it. If we've come back from some indentation, we need
433 433 # the blank final line to finish.
434 434 # In cell mode, we need to check how many blocks the input so far
435 435 # compiles into, because if there's already more than one full
436 436 # independent block of input, then the client has entered full
437 437 # 'cell' mode and is feeding lines that each is complete. In this
438 438 # case we should then keep accepting. The Qt terminal-like console
439 439 # does precisely this, to provide the convenience of terminal-like
440 440 # input of single expressions, but allowing the user (with a
441 441 # separate keystroke) to switch to 'cell' mode and type multiple
442 442 # expressions in one shot.
443 443 if self.indent_spaces==0:
444 444 if self.input_mode=='line':
445 445 if not self._full_dedent:
446 446 return False
447 447 else:
448 448 nblocks = len(split_blocks(''.join(self._buffer)))
449 449 if nblocks==1:
450 450 return False
451 451
452 452 # When input is complete, then termination is marked by an extra blank
453 453 # line at the end.
454 454 last_line = self.source.splitlines()[-1]
455 455 return bool(last_line and not last_line.isspace())
456 456
457 457 def split_blocks(self, lines):
458 458 """Split a multiline string into multiple input blocks.
459 459
460 460 Note: this method starts by performing a full reset().
461 461
462 462 Parameters
463 463 ----------
464 464 lines : str
465 465 A possibly multiline string.
466 466
467 467 Returns
468 468 -------
469 469 blocks : list
470 470 A list of strings, each possibly multiline. Each string corresponds
471 471 to a single block that can be compiled in 'single' mode (unless it
472 472 has a syntax error)."""
473 473
474 474 # This code is fairly delicate. If you make any changes here, make
475 475 # absolutely sure that you do run the full test suite and ALL tests
476 476 # pass.
477 477
478 478 self.reset()
479 479 blocks = []
480 480
481 481 # Reversed copy so we can use pop() efficiently and consume the input
482 482 # as a stack
483 483 lines = lines.splitlines()[::-1]
484 484 # Outer loop over all input
485 485 while lines:
486 486 #print 'Current lines:', lines # dbg
487 487 # Inner loop to build each block
488 488 while True:
489 489 # Safety exit from inner loop
490 490 if not lines:
491 491 break
492 492 # Grab next line but don't push it yet
493 493 next_line = lines.pop()
494 494 # Blank/empty lines are pushed as-is
495 495 if not next_line or next_line.isspace():
496 496 self.push(next_line)
497 497 continue
498 498
499 499 # Check indentation changes caused by the *next* line
500 500 indent_spaces, _full_dedent = self._find_indent(next_line)
501 501
502 502 # If the next line causes a dedent, it can be for two differnt
503 503 # reasons: either an explicit de-dent by the user or a
504 504 # return/raise/pass statement. These MUST be handled
505 505 # separately:
506 506 #
507 507 # 1. the first case is only detected when the actual explicit
508 508 # dedent happens, and that would be the *first* line of a *new*
509 509 # block. Thus, we must put the line back into the input buffer
510 510 # so that it starts a new block on the next pass.
511 511 #
512 512 # 2. the second case is detected in the line before the actual
513 513 # dedent happens, so , we consume the line and we can break out
514 514 # to start a new block.
515 515
516 516 # Case 1, explicit dedent causes a break.
517 517 # Note: check that we weren't on the very last line, else we'll
518 518 # enter an infinite loop adding/removing the last line.
519 519 if _full_dedent and lines and not next_line.startswith(' '):
520 520 lines.append(next_line)
521 521 break
522 522
523 523 # Otherwise any line is pushed
524 524 self.push(next_line)
525 525
526 526 # Case 2, full dedent with full block ready:
527 527 if _full_dedent or \
528 528 self.indent_spaces==0 and not self.push_accepts_more():
529 529 break
530 530 # Form the new block with the current source input
531 531 blocks.append(self.source_reset())
532 532
533 533 #return blocks
534 534 # HACK!!! Now that our input is in blocks but guaranteed to be pure
535 535 # python syntax, feed it back a second time through the AST-based
536 536 # splitter, which is more accurate than ours.
537 537 return split_blocks(''.join(blocks))
538 538
539 539 #------------------------------------------------------------------------
540 540 # Private interface
541 541 #------------------------------------------------------------------------
542 542
543 543 def _find_indent(self, line):
544 544 """Compute the new indentation level for a single line.
545 545
546 546 Parameters
547 547 ----------
548 548 line : str
549 549 A single new line of non-whitespace, non-comment Python input.
550 550
551 551 Returns
552 552 -------
553 553 indent_spaces : int
554 554 New value for the indent level (it may be equal to self.indent_spaces
555 555 if indentation doesn't change.
556 556
557 557 full_dedent : boolean
558 558 Whether the new line causes a full flush-left dedent.
559 559 """
560 560 indent_spaces = self.indent_spaces
561 561 full_dedent = self._full_dedent
562 562
563 563 inisp = num_ini_spaces(line)
564 564 if inisp < indent_spaces:
565 565 indent_spaces = inisp
566 566 if indent_spaces <= 0:
567 567 #print 'Full dedent in text',self.source # dbg
568 568 full_dedent = True
569 569
570 570 if line[-1] == ':':
571 571 indent_spaces += 4
572 572 elif dedent_re.match(line):
573 573 indent_spaces -= 4
574 574 if indent_spaces <= 0:
575 575 full_dedent = True
576 576
577 577 # Safety
578 578 if indent_spaces < 0:
579 579 indent_spaces = 0
580 580 #print 'safety' # dbg
581 581
582 582 return indent_spaces, full_dedent
583 583
584 584 def _update_indent(self, lines):
585 585 for line in remove_comments(lines).splitlines():
586 586 if line and not line.isspace():
587 587 self.indent_spaces, self._full_dedent = self._find_indent(line)
588 588
589 589 def _store(self, lines, buffer=None, store='source'):
590 590 """Store one or more lines of input.
591 591
592 592 If input lines are not newline-terminated, a newline is automatically
593 593 appended."""
594 594
595 595 if buffer is None:
596 596 buffer = self._buffer
597 597
598 598 if lines.endswith('\n'):
599 599 buffer.append(lines)
600 600 else:
601 601 buffer.append(lines+'\n')
602 602 setattr(self, store, self._set_source(buffer))
603 603
604 604 def _set_source(self, buffer):
605 605 return u''.join(buffer)
606 606
607 607
608 608 #-----------------------------------------------------------------------------
609 609 # Functions and classes for IPython-specific syntactic support
610 610 #-----------------------------------------------------------------------------
611 611
612 612 # RegExp for splitting line contents into pre-char//first word-method//rest.
613 613 # For clarity, each group in on one line.
614 614
615 615 line_split = re.compile("""
616 616 ^(\s*) # any leading space
617 617 ([,;/%]|!!?|\?\??) # escape character or characters
618 618 \s*(%?[\w\.\*]*) # function/method, possibly with leading %
619 619 # to correctly treat things like '?%magic'
620 620 (\s+.*$|$) # rest of line
621 621 """, re.VERBOSE)
622 622
623 623
624 624 def split_user_input(line):
625 625 """Split user input into early whitespace, esc-char, function part and rest.
626 626
627 627 This is currently handles lines with '=' in them in a very inconsistent
628 628 manner.
629 629
630 630 Examples
631 631 ========
632 632 >>> split_user_input('x=1')
633 633 ('', '', 'x=1', '')
634 634 >>> split_user_input('?')
635 635 ('', '?', '', '')
636 636 >>> split_user_input('??')
637 637 ('', '??', '', '')
638 638 >>> split_user_input(' ?')
639 639 (' ', '?', '', '')
640 640 >>> split_user_input(' ??')
641 641 (' ', '??', '', '')
642 642 >>> split_user_input('??x')
643 643 ('', '??', 'x', '')
644 644 >>> split_user_input('?x=1')
645 645 ('', '', '?x=1', '')
646 646 >>> split_user_input('!ls')
647 647 ('', '!', 'ls', '')
648 648 >>> split_user_input(' !ls')
649 649 (' ', '!', 'ls', '')
650 650 >>> split_user_input('!!ls')
651 651 ('', '!!', 'ls', '')
652 652 >>> split_user_input(' !!ls')
653 653 (' ', '!!', 'ls', '')
654 654 >>> split_user_input(',ls')
655 655 ('', ',', 'ls', '')
656 656 >>> split_user_input(';ls')
657 657 ('', ';', 'ls', '')
658 658 >>> split_user_input(' ;ls')
659 659 (' ', ';', 'ls', '')
660 660 >>> split_user_input('f.g(x)')
661 661 ('', '', 'f.g(x)', '')
662 662 >>> split_user_input('f.g (x)')
663 663 ('', '', 'f.g', '(x)')
664 664 >>> split_user_input('?%hist')
665 665 ('', '?', '%hist', '')
666 666 >>> split_user_input('?x*')
667 667 ('', '?', 'x*', '')
668 668 """
669 669 match = line_split.match(line)
670 670 if match:
671 671 lspace, esc, fpart, rest = match.groups()
672 672 else:
673 673 # print "match failed for line '%s'" % line
674 674 try:
675 675 fpart, rest = line.split(None, 1)
676 676 except ValueError:
677 677 # print "split failed for line '%s'" % line
678 678 fpart, rest = line,''
679 679 lspace = re.match('^(\s*)(.*)', line).groups()[0]
680 680 esc = ''
681 681
682 682 # fpart has to be a valid python identifier, so it better be only pure
683 683 # ascii, no unicode:
684 684 try:
685 685 fpart = fpart.encode('ascii')
686 686 except UnicodeEncodeError:
687 687 lspace = unicode(lspace)
688 688 rest = fpart + u' ' + rest
689 689 fpart = u''
690 690
691 691 #print 'line:<%s>' % line # dbg
692 692 #print 'esc <%s> fpart <%s> rest <%s>' % (esc,fpart.strip(),rest) # dbg
693 693 return lspace, esc, fpart.strip(), rest.lstrip()
694 694
695 695
696 696 # The escaped translators ALL receive a line where their own escape has been
697 697 # stripped. Only '?' is valid at the end of the line, all others can only be
698 698 # placed at the start.
699 699
700 700 class LineInfo(object):
701 701 """A single line of input and associated info.
702 702
703 703 This is a utility class that mostly wraps the output of
704 704 :func:`split_user_input` into a convenient object to be passed around
705 705 during input transformations.
706 706
707 707 Includes the following as properties:
708 708
709 709 line
710 710 The original, raw line
711 711
712 712 lspace
713 713 Any early whitespace before actual text starts.
714 714
715 715 esc
716 716 The initial esc character (or characters, for double-char escapes like
717 717 '??' or '!!').
718 718
719 719 fpart
720 720 The 'function part', which is basically the maximal initial sequence
721 721 of valid python identifiers and the '.' character. This is what is
722 722 checked for alias and magic transformations, used for auto-calling,
723 723 etc.
724 724
725 725 rest
726 726 Everything else on the line.
727 727 """
728 728 def __init__(self, line):
729 729 self.line = line
730 730 self.lspace, self.esc, self.fpart, self.rest = \
731 731 split_user_input(line)
732 732
733 733 def __str__(self):
734 734 return "LineInfo [%s|%s|%s|%s]" % (self.lspace, self.esc,
735 735 self.fpart, self.rest)
736 736
737 737
738 738 # Transformations of the special syntaxes that don't rely on an explicit escape
739 739 # character but instead on patterns on the input line
740 740
741 741 # The core transformations are implemented as standalone functions that can be
742 742 # tested and validated in isolation. Each of these uses a regexp, we
743 743 # pre-compile these and keep them close to each function definition for clarity
744 744
745 745 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
746 746 r'\s*=\s*!\s*(?P<cmd>.*)')
747 747
748 748 def transform_assign_system(line):
749 749 """Handle the `files = !ls` syntax."""
750 750 m = _assign_system_re.match(line)
751 751 if m is not None:
752 752 cmd = m.group('cmd')
753 753 lhs = m.group('lhs')
754 754 expr = make_quoted_expr(cmd)
755 755 new_line = '%s = get_ipython().getoutput(%s)' % (lhs, expr)
756 756 return new_line
757 757 return line
758 758
759 759
760 760 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
761 761 r'\s*=\s*%\s*(?P<cmd>.*)')
762 762
763 763 def transform_assign_magic(line):
764 764 """Handle the `a = %who` syntax."""
765 765 m = _assign_magic_re.match(line)
766 766 if m is not None:
767 767 cmd = m.group('cmd')
768 768 lhs = m.group('lhs')
769 769 expr = make_quoted_expr(cmd)
770 770 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
771 771 return new_line
772 772 return line
773 773
774 774
775 775 _classic_prompt_re = re.compile(r'^([ \t]*>>> |^[ \t]*\.\.\. )')
776 776
777 777 def transform_classic_prompt(line):
778 778 """Handle inputs that start with '>>> ' syntax."""
779 779
780 780 if not line or line.isspace():
781 781 return line
782 782 m = _classic_prompt_re.match(line)
783 783 if m:
784 784 return line[len(m.group(0)):]
785 785 else:
786 786 return line
787 787
788 788
789 789 _ipy_prompt_re = re.compile(r'^([ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
790 790
791 791 def transform_ipy_prompt(line):
792 792 """Handle inputs that start classic IPython prompt syntax."""
793 793
794 794 if not line or line.isspace():
795 795 return line
796 796 #print 'LINE: %r' % line # dbg
797 797 m = _ipy_prompt_re.match(line)
798 798 if m:
799 799 #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg
800 800 return line[len(m.group(0)):]
801 801 else:
802 802 return line
803 803
804 804
805 805 class EscapedTransformer(object):
806 806 """Class to transform lines that are explicitly escaped out."""
807 807
808 808 def __init__(self):
809 809 tr = { ESC_SHELL : self._tr_system,
810 810 ESC_SH_CAP : self._tr_system2,
811 811 ESC_HELP : self._tr_help,
812 812 ESC_HELP2 : self._tr_help,
813 813 ESC_MAGIC : self._tr_magic,
814 814 ESC_QUOTE : self._tr_quote,
815 815 ESC_QUOTE2 : self._tr_quote2,
816 816 ESC_PAREN : self._tr_paren }
817 817 self.tr = tr
818 818
819 819 # Support for syntax transformations that use explicit escapes typed by the
820 820 # user at the beginning of a line
821 821 @staticmethod
822 822 def _tr_system(line_info):
823 823 "Translate lines escaped with: !"
824 824 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
825 825 return '%sget_ipython().system(%s)' % (line_info.lspace,
826 826 make_quoted_expr(cmd))
827 827
828 828 @staticmethod
829 829 def _tr_system2(line_info):
830 830 "Translate lines escaped with: !!"
831 831 cmd = line_info.line.lstrip()[2:]
832 832 return '%sget_ipython().getoutput(%s)' % (line_info.lspace,
833 833 make_quoted_expr(cmd))
834 834
835 835 @staticmethod
836 836 def _tr_help(line_info):
837 837 "Translate lines escaped with: ?/??"
838 838 # A naked help line should just fire the intro help screen
839 839 if not line_info.line[1:]:
840 840 return 'get_ipython().show_usage()'
841 841
842 842 # There may be one or two '?' at the end, move them to the front so that
843 843 # the rest of the logic can assume escapes are at the start
844 844 l_ori = line_info
845 845 line = line_info.line
846 846 if line.endswith('?'):
847 847 line = line[-1] + line[:-1]
848 848 if line.endswith('?'):
849 849 line = line[-1] + line[:-1]
850 850 line_info = LineInfo(line)
851 851
852 852 # From here on, simply choose which level of detail to get, and
853 853 # special-case the psearch syntax
854 854 pinfo = 'pinfo' # default
855 855 if '*' in line_info.line:
856 856 pinfo = 'psearch'
857 857 elif line_info.esc == '??':
858 858 pinfo = 'pinfo2'
859 859
860 tpl = '%sget_ipython().magic("%s %s")'
860 tpl = '%sget_ipython().magic(u"%s %s")'
861 861 return tpl % (line_info.lspace, pinfo,
862 862 ' '.join([line_info.fpart, line_info.rest]).strip())
863 863
864 864 @staticmethod
865 865 def _tr_magic(line_info):
866 866 "Translate lines escaped with: %"
867 867 tpl = '%sget_ipython().magic(%s)'
868 868 cmd = make_quoted_expr(' '.join([line_info.fpart,
869 869 line_info.rest]).strip())
870 870 return tpl % (line_info.lspace, cmd)
871 871
872 872 @staticmethod
873 873 def _tr_quote(line_info):
874 874 "Translate lines escaped with: ,"
875 875 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
876 876 '", "'.join(line_info.rest.split()) )
877 877
878 878 @staticmethod
879 879 def _tr_quote2(line_info):
880 880 "Translate lines escaped with: ;"
881 881 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
882 882 line_info.rest)
883 883
884 884 @staticmethod
885 885 def _tr_paren(line_info):
886 886 "Translate lines escaped with: /"
887 887 return '%s%s(%s)' % (line_info.lspace, line_info.fpart,
888 888 ", ".join(line_info.rest.split()))
889 889
890 890 def __call__(self, line):
891 891 """Class to transform lines that are explicitly escaped out.
892 892
893 893 This calls the above _tr_* static methods for the actual line
894 894 translations."""
895 895
896 896 # Empty lines just get returned unmodified
897 897 if not line or line.isspace():
898 898 return line
899 899
900 900 # Get line endpoints, where the escapes can be
901 901 line_info = LineInfo(line)
902 902
903 903 # If the escape is not at the start, only '?' needs to be special-cased.
904 904 # All other escapes are only valid at the start
905 905 if not line_info.esc in self.tr:
906 906 if line.endswith(ESC_HELP):
907 907 return self._tr_help(line_info)
908 908 else:
909 909 # If we don't recognize the escape, don't modify the line
910 910 return line
911 911
912 912 return self.tr[line_info.esc](line_info)
913 913
914 914
915 915 # A function-looking object to be used by the rest of the code. The purpose of
916 916 # the class in this case is to organize related functionality, more than to
917 917 # manage state.
918 918 transform_escaped = EscapedTransformer()
919 919
920 920
921 921 class IPythonInputSplitter(InputSplitter):
922 922 """An input splitter that recognizes all of IPython's special syntax."""
923 923
924 924 # String with raw, untransformed input.
925 925 source_raw = ''
926 926
927 927 # Private attributes
928 928
929 929 # List with lines of raw input accumulated so far.
930 930 _buffer_raw = None
931 931
932 932 def __init__(self, input_mode=None):
933 933 InputSplitter.__init__(self, input_mode)
934 934 self._buffer_raw = []
935 935
936 936 def reset(self):
937 937 """Reset the input buffer and associated state."""
938 938 InputSplitter.reset(self)
939 939 self._buffer_raw[:] = []
940 940 self.source_raw = ''
941 941
942 942 def source_raw_reset(self):
943 943 """Return input and raw source and perform a full reset.
944 944 """
945 945 out = self.source
946 946 out_r = self.source_raw
947 947 self.reset()
948 948 return out, out_r
949 949
950 950 def push(self, lines):
951 951 """Push one or more lines of IPython input.
952 952 """
953 953 if not lines:
954 954 return super(IPythonInputSplitter, self).push(lines)
955 955
956 956 # We must ensure all input is pure unicode
957 957 if type(lines)==str:
958 958 lines = lines.decode(self.encoding)
959 959
960 960 lines_list = lines.splitlines()
961 961
962 962 transforms = [transform_escaped, transform_assign_system,
963 963 transform_assign_magic, transform_ipy_prompt,
964 964 transform_classic_prompt]
965 965
966 966 # Transform logic
967 967 #
968 968 # We only apply the line transformers to the input if we have either no
969 969 # input yet, or complete input, or if the last line of the buffer ends
970 970 # with ':' (opening an indented block). This prevents the accidental
971 971 # transformation of escapes inside multiline expressions like
972 972 # triple-quoted strings or parenthesized expressions.
973 973 #
974 974 # The last heuristic, while ugly, ensures that the first line of an
975 975 # indented block is correctly transformed.
976 976 #
977 977 # FIXME: try to find a cleaner approach for this last bit.
978 978
979 979 # If we were in 'block' mode, since we're going to pump the parent
980 980 # class by hand line by line, we need to temporarily switch out to
981 981 # 'line' mode, do a single manual reset and then feed the lines one
982 982 # by one. Note that this only matters if the input has more than one
983 983 # line.
984 984 changed_input_mode = False
985 985
986 986 if self.input_mode == 'cell':
987 987 self.reset()
988 988 changed_input_mode = True
989 989 saved_input_mode = 'cell'
990 990 self.input_mode = 'line'
991 991
992 992 # Store raw source before applying any transformations to it. Note
993 993 # that this must be done *after* the reset() call that would otherwise
994 994 # flush the buffer.
995 995 self._store(lines, self._buffer_raw, 'source_raw')
996 996
997 997 try:
998 998 push = super(IPythonInputSplitter, self).push
999 999 for line in lines_list:
1000 1000 if self._is_complete or not self._buffer or \
1001 1001 (self._buffer and self._buffer[-1].rstrip().endswith(':')):
1002 1002 for f in transforms:
1003 1003 line = f(line)
1004 1004
1005 1005 out = push(line)
1006 1006 finally:
1007 1007 if changed_input_mode:
1008 1008 self.input_mode = saved_input_mode
1009 1009 return out
@@ -1,174 +1,174 b''
1 1 """Tests for input handlers.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Module imports
5 5 #-----------------------------------------------------------------------------
6 6
7 7 # third party
8 8 import nose.tools as nt
9 9
10 10 # our own packages
11 11 from IPython.core import autocall
12 12 from IPython.testing import decorators as dec
13 13 from IPython.testing.globalipapp import get_ipython
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Globals
17 17 #-----------------------------------------------------------------------------
18 18
19 19 # Get the public instance of IPython
20 20 ip = get_ipython()
21 21
22 22 failures = []
23 23 num_tests = 0
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Test functions
27 27 #-----------------------------------------------------------------------------
28 28
29 29 class CallableIndexable(object):
30 30 def __getitem__(self, idx): return True
31 31 def __call__(self, *args, **kws): return True
32 32
33 33
34 34 class Autocallable(autocall.IPyAutocall):
35 35 def __call__(self):
36 36 return "called"
37 37
38 38
39 39 def run(tests):
40 40 """Loop through a list of (pre, post) inputs, where pre is the string
41 41 handed to ipython, and post is how that string looks after it's been
42 42 transformed (i.e. ipython's notion of _i)"""
43 43 for pre, post in tests:
44 44 global num_tests
45 45 num_tests += 1
46 46 ip.runlines(pre)
47 47 ip.runlines('_i') # Not sure why I need this...
48 48 actual = ip.user_ns['_i']
49 49 if actual != None:
50 50 actual = actual.rstrip('\n')
51 51 if actual != post:
52 52 failures.append('Expected %r to become %r, found %r' % (
53 53 pre, post, actual))
54 54
55 55
56 56 def test_handlers():
57 57 # alias expansion
58 58
59 59 # We're using 'true' as our syscall of choice because it doesn't
60 60 # write anything to stdout.
61 61
62 62 # Turn off actual execution of aliases, because it's noisy
63 63 old_system_cmd = ip.system
64 64 ip.system = lambda cmd: None
65 65
66 66
67 67 ip.alias_manager.alias_table['an_alias'] = (0, 'true')
68 68 # These are useful for checking a particular recursive alias issue
69 69 ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
70 70 ip.alias_manager.alias_table['d'] = (0, 'true')
71 run([("an_alias", 'get_ipython().system("true ")'), # alias
71 run([("an_alias", 'get_ipython().system(u"true ")'), # alias
72 72 # Below: recursive aliases should expand whitespace-surrounded
73 73 # chars, *not* initial chars which happen to be aliases:
74 ("top", 'get_ipython().system("d:/cygwin/top ")'),
74 ("top", 'get_ipython().system(u"d:/cygwin/top ")'),
75 75 ])
76 76 ip.system = old_system_cmd
77 77
78 78 call_idx = CallableIndexable()
79 79 ip.user_ns['call_idx'] = call_idx
80 80
81 81 # For many of the below, we're also checking that leading whitespace
82 82 # turns off the esc char, which it should unless there is a continuation
83 83 # line.
84 84 run([('"no change"', '"no change"'), # normal
85 ("!true", 'get_ipython().system("true")'), # shell_escapes
86 ("!! true", 'get_ipython().magic("sx true")'), # shell_escapes + magic
87 ("!!true", 'get_ipython().magic("sx true")'), # shell_escapes + magic
88 ("%lsmagic", 'get_ipython().magic("lsmagic ")'), # magic
89 ("lsmagic", 'get_ipython().magic("lsmagic ")'), # magic
85 ("!true", 'get_ipython().system(u"true")'), # shell_escapes
86 ("!! true", 'get_ipython().magic(u"sx true")'), # shell_escapes + magic
87 ("!!true", 'get_ipython().magic(u"sx true")'), # shell_escapes + magic
88 ("%lsmagic", 'get_ipython().magic(u"lsmagic ")'), # magic
89 ("lsmagic", 'get_ipython().magic(u"lsmagic ")'), # magic
90 90 #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
91 91
92 92 # post-esc-char whitespace goes inside
93 ("! true", 'get_ipython().system(" true")'),
93 ("! true", 'get_ipython().system(u" true")'),
94 94
95 95 # handle_help
96 96
97 97 # These are weak tests -- just looking at what the help handlers
98 98 # logs, which is not how it really does its work. But it still
99 99 # lets us check the key paths through the handler.
100 100
101 101 ("x=1 # what?", "x=1 # what?"), # no help if valid python
102 102 ])
103 103
104 104 # multi_line_specials
105 105 ip.prefilter_manager.multi_line_specials = False
106 106 # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion
107 107 run([
108 108 ('if 1:\n !true', 'if 1:\n !true'),
109 109 ('if 1:\n lsmagic', 'if 1:\n lsmagic'),
110 110 ('if 1:\n an_alias', 'if 1:\n an_alias'),
111 111 ])
112 112
113 113 ip.prefilter_manager.multi_line_specials = True
114 114 # initial indents must be preserved.
115 115 run([
116 ('if 1:\n !true', 'if 1:\n get_ipython().system("true")'),
117 ('if 2:\n lsmagic', 'if 2:\n get_ipython().magic("lsmagic ")'),
118 ('if 1:\n an_alias', 'if 1:\n get_ipython().system("true ")'),
116 ('if 1:\n !true', 'if 1:\n get_ipython().system(u"true")'),
117 ('if 2:\n lsmagic', 'if 2:\n get_ipython().magic(u"lsmagic ")'),
118 ('if 1:\n an_alias', 'if 1:\n get_ipython().system(u"true ")'),
119 119 # Weird one
120 ('if 1:\n !!true', 'if 1:\n get_ipython().magic("sx true")'),
120 ('if 1:\n !!true', 'if 1:\n get_ipython().magic(u"sx true")'),
121 121
122 122 # Even with m_l_s on, autocall is off even with special chars
123 123 ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'),
124 124 ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'),
125 125 ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'),
126 126 ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'),
127 127 # What about !!
128 128 ])
129 129
130 130 # Objects which are instances of IPyAutocall are *always* autocalled
131 131 autocallable = Autocallable()
132 132 ip.user_ns['autocallable'] = autocallable
133 133
134 134 # auto
135 135 ip.magic('autocall 0')
136 136 # Only explicit escapes or instances of IPyAutocallable should get
137 137 # expanded
138 138 run([
139 139 ('len "abc"', 'len "abc"'),
140 140 ('autocallable', 'autocallable()'),
141 141 (",list 1 2 3", 'list("1", "2", "3")'),
142 142 (";list 1 2 3", 'list("1 2 3")'),
143 143 ("/len range(1,4)", 'len(range(1,4))'),
144 144 ])
145 145 ip.magic('autocall 1')
146 146 run([
147 147 (",list 1 2 3", 'list("1", "2", "3")'),
148 148 (";list 1 2 3", 'list("1 2 3")'),
149 149 ("/len range(1,4)", 'len(range(1,4))'),
150 150 ('len "abc"', 'len("abc")'),
151 151 ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
152 152 # Autocall is turned off if first arg is [] and the object
153 153 # is both callable and indexable. Like so:
154 154 ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__...
155 155 ('call_idx [1]', 'call_idx [1]'), # call_idx *does*..
156 156 ('call_idx 1', 'call_idx(1)'),
157 157 ('len', 'len '), # only at 2 does it auto-call on single args
158 158 ])
159 159 ip.magic('autocall 2')
160 160 run([
161 161 (",list 1 2 3", 'list("1", "2", "3")'),
162 162 (";list 1 2 3", 'list("1 2 3")'),
163 163 ("/len range(1,4)", 'len(range(1,4))'),
164 164 ('len "abc"', 'len("abc")'),
165 165 ('len "abc";', 'len("abc");'),
166 166 ('len [1,2]', 'len([1,2])'),
167 167 ('call_idx [1]', 'call_idx [1]'),
168 168 ('call_idx 1', 'call_idx(1)'),
169 169 # This is what's different:
170 170 ('len', 'len()'), # only at 2 does it auto-call on single args
171 171 ])
172 172 ip.magic('autocall 1')
173 173
174 174 nt.assert_equals(failures, [])
@@ -1,704 +1,704 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the inputsplitter module.
3 3
4 4 Authors
5 5 -------
6 6 * Fernando Perez
7 7 * Robert Kern
8 8 """
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2010 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19 # stdlib
20 20 import unittest
21 21 import sys
22 22
23 23 # Third party
24 24 import nose.tools as nt
25 25
26 26 # Our own
27 27 from IPython.core import inputsplitter as isp
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Semi-complete examples (also used as tests)
31 31 #-----------------------------------------------------------------------------
32 32
33 33 # Note: at the bottom, there's a slightly more complete version of this that
34 34 # can be useful during development of code here.
35 35
36 36 def mini_interactive_loop(input_func):
37 37 """Minimal example of the logic of an interactive interpreter loop.
38 38
39 39 This serves as an example, and it is used by the test system with a fake
40 40 raw_input that simulates interactive input."""
41 41
42 42 from IPython.core.inputsplitter import InputSplitter
43 43
44 44 isp = InputSplitter()
45 45 # In practice, this input loop would be wrapped in an outside loop to read
46 46 # input indefinitely, until some exit/quit command was issued. Here we
47 47 # only illustrate the basic inner loop.
48 48 while isp.push_accepts_more():
49 49 indent = ' '*isp.indent_spaces
50 50 prompt = '>>> ' + indent
51 51 line = indent + input_func(prompt)
52 52 isp.push(line)
53 53
54 54 # Here we just return input so we can use it in a test suite, but a real
55 55 # interpreter would instead send it for execution somewhere.
56 56 src = isp.source_reset()
57 57 #print 'Input source was:\n', src # dbg
58 58 return src
59 59
60 60 #-----------------------------------------------------------------------------
61 61 # Test utilities, just for local use
62 62 #-----------------------------------------------------------------------------
63 63
64 64 def assemble(block):
65 65 """Assemble a block into multi-line sub-blocks."""
66 66 return ['\n'.join(sub_block)+'\n' for sub_block in block]
67 67
68 68
69 69 def pseudo_input(lines):
70 70 """Return a function that acts like raw_input but feeds the input list."""
71 71 ilines = iter(lines)
72 72 def raw_in(prompt):
73 73 try:
74 74 return next(ilines)
75 75 except StopIteration:
76 76 return ''
77 77 return raw_in
78 78
79 79 #-----------------------------------------------------------------------------
80 80 # Tests
81 81 #-----------------------------------------------------------------------------
82 82 def test_spaces():
83 83 tests = [('', 0),
84 84 (' ', 1),
85 85 ('\n', 0),
86 86 (' \n', 1),
87 87 ('x', 0),
88 88 (' x', 1),
89 89 (' x',2),
90 90 (' x',4),
91 91 # Note: tabs are counted as a single whitespace!
92 92 ('\tx', 1),
93 93 ('\t x', 2),
94 94 ]
95 95
96 96 for s, nsp in tests:
97 97 nt.assert_equal(isp.num_ini_spaces(s), nsp)
98 98
99 99
100 100 def test_remove_comments():
101 101 tests = [('text', 'text'),
102 102 ('text # comment', 'text '),
103 103 ('text # comment\n', 'text \n'),
104 104 ('text # comment \n', 'text \n'),
105 105 ('line # c \nline\n','line \nline\n'),
106 106 ('line # c \nline#c2 \nline\nline #c\n\n',
107 107 'line \nline\nline\nline \n\n'),
108 108 ]
109 109
110 110 for inp, out in tests:
111 111 nt.assert_equal(isp.remove_comments(inp), out)
112 112
113 113
114 114 def test_get_input_encoding():
115 115 encoding = isp.get_input_encoding()
116 116 nt.assert_true(isinstance(encoding, basestring))
117 117 # simple-minded check that at least encoding a simple string works with the
118 118 # encoding we got.
119 119 nt.assert_equal('test'.encode(encoding), 'test')
120 120
121 121
122 122 class NoInputEncodingTestCase(unittest.TestCase):
123 123 def setUp(self):
124 124 self.old_stdin = sys.stdin
125 125 class X: pass
126 126 fake_stdin = X()
127 127 sys.stdin = fake_stdin
128 128
129 129 def test(self):
130 130 # Verify that if sys.stdin has no 'encoding' attribute we do the right
131 131 # thing
132 132 enc = isp.get_input_encoding()
133 133 self.assertEqual(enc, 'ascii')
134 134
135 135 def tearDown(self):
136 136 sys.stdin = self.old_stdin
137 137
138 138
139 139 class InputSplitterTestCase(unittest.TestCase):
140 140 def setUp(self):
141 141 self.isp = isp.InputSplitter()
142 142
143 143 def test_reset(self):
144 144 isp = self.isp
145 145 isp.push('x=1')
146 146 isp.reset()
147 147 self.assertEqual(isp._buffer, [])
148 148 self.assertEqual(isp.indent_spaces, 0)
149 149 self.assertEqual(isp.source, '')
150 150 self.assertEqual(isp.code, None)
151 151 self.assertEqual(isp._is_complete, False)
152 152
153 153 def test_source(self):
154 154 self.isp._store('1')
155 155 self.isp._store('2')
156 156 self.assertEqual(self.isp.source, '1\n2\n')
157 157 self.assertTrue(len(self.isp._buffer)>0)
158 158 self.assertEqual(self.isp.source_reset(), '1\n2\n')
159 159 self.assertEqual(self.isp._buffer, [])
160 160 self.assertEqual(self.isp.source, '')
161 161
162 162 def test_indent(self):
163 163 isp = self.isp # shorthand
164 164 isp.push('x=1')
165 165 self.assertEqual(isp.indent_spaces, 0)
166 166 isp.push('if 1:\n x=1')
167 167 self.assertEqual(isp.indent_spaces, 4)
168 168 isp.push('y=2\n')
169 169 self.assertEqual(isp.indent_spaces, 0)
170 170
171 171 def test_indent2(self):
172 172 # In cell mode, inputs must be fed in whole blocks, so skip this test
173 173 if self.isp.input_mode == 'cell': return
174 174
175 175 isp = self.isp
176 176 isp.push('if 1:')
177 177 self.assertEqual(isp.indent_spaces, 4)
178 178 isp.push(' x=1')
179 179 self.assertEqual(isp.indent_spaces, 4)
180 180 # Blank lines shouldn't change the indent level
181 181 isp.push(' '*2)
182 182 self.assertEqual(isp.indent_spaces, 4)
183 183
184 184 def test_indent3(self):
185 185 # In cell mode, inputs must be fed in whole blocks, so skip this test
186 186 if self.isp.input_mode == 'cell': return
187 187
188 188 isp = self.isp
189 189 # When a multiline statement contains parens or multiline strings, we
190 190 # shouldn't get confused.
191 191 isp.push("if 1:")
192 192 isp.push(" x = (1+\n 2)")
193 193 self.assertEqual(isp.indent_spaces, 4)
194 194
195 195 def test_dedent(self):
196 196 isp = self.isp # shorthand
197 197 isp.push('if 1:')
198 198 self.assertEqual(isp.indent_spaces, 4)
199 199 isp.push(' pass')
200 200 self.assertEqual(isp.indent_spaces, 0)
201 201
202 202 def test_push(self):
203 203 isp = self.isp
204 204 self.assertTrue(isp.push('x=1'))
205 205
206 206 def test_push2(self):
207 207 isp = self.isp
208 208 self.assertFalse(isp.push('if 1:'))
209 209 for line in [' x=1', '# a comment', ' y=2']:
210 210 self.assertTrue(isp.push(line))
211 211
212 212 def test_replace_mode(self):
213 213 isp = self.isp
214 214 isp.input_mode = 'cell'
215 215 isp.push('x=1')
216 216 self.assertEqual(isp.source, 'x=1\n')
217 217 isp.push('x=2')
218 218 self.assertEqual(isp.source, 'x=2\n')
219 219
220 220 def test_push_accepts_more(self):
221 221 isp = self.isp
222 222 isp.push('x=1')
223 223 self.assertFalse(isp.push_accepts_more())
224 224
225 225 def test_push_accepts_more2(self):
226 226 # In cell mode, inputs must be fed in whole blocks, so skip this test
227 227 if self.isp.input_mode == 'cell': return
228 228
229 229 isp = self.isp
230 230 isp.push('if 1:')
231 231 self.assertTrue(isp.push_accepts_more())
232 232 isp.push(' x=1')
233 233 self.assertTrue(isp.push_accepts_more())
234 234 isp.push('')
235 235 self.assertFalse(isp.push_accepts_more())
236 236
237 237 def test_push_accepts_more3(self):
238 238 isp = self.isp
239 239 isp.push("x = (2+\n3)")
240 240 self.assertFalse(isp.push_accepts_more())
241 241
242 242 def test_push_accepts_more4(self):
243 243 # In cell mode, inputs must be fed in whole blocks, so skip this test
244 244 if self.isp.input_mode == 'cell': return
245 245
246 246 isp = self.isp
247 247 # When a multiline statement contains parens or multiline strings, we
248 248 # shouldn't get confused.
249 249 # FIXME: we should be able to better handle de-dents in statements like
250 250 # multiline strings and multiline expressions (continued with \ or
251 251 # parens). Right now we aren't handling the indentation tracking quite
252 252 # correctly with this, though in practice it may not be too much of a
253 253 # problem. We'll need to see.
254 254 isp.push("if 1:")
255 255 isp.push(" x = (2+")
256 256 isp.push(" 3)")
257 257 self.assertTrue(isp.push_accepts_more())
258 258 isp.push(" y = 3")
259 259 self.assertTrue(isp.push_accepts_more())
260 260 isp.push('')
261 261 self.assertFalse(isp.push_accepts_more())
262 262
263 263 def test_push_accepts_more5(self):
264 264 # In cell mode, inputs must be fed in whole blocks, so skip this test
265 265 if self.isp.input_mode == 'cell': return
266 266
267 267 isp = self.isp
268 268 isp.push('try:')
269 269 isp.push(' a = 5')
270 270 isp.push('except:')
271 271 isp.push(' raise')
272 272 self.assertTrue(isp.push_accepts_more())
273 273
274 274 def test_continuation(self):
275 275 isp = self.isp
276 276 isp.push("import os, \\")
277 277 self.assertTrue(isp.push_accepts_more())
278 278 isp.push("sys")
279 279 self.assertFalse(isp.push_accepts_more())
280 280
281 281 def test_syntax_error(self):
282 282 isp = self.isp
283 283 # Syntax errors immediately produce a 'ready' block, so the invalid
284 284 # Python can be sent to the kernel for evaluation with possible ipython
285 285 # special-syntax conversion.
286 286 isp.push('run foo')
287 287 self.assertFalse(isp.push_accepts_more())
288 288
289 289 def check_split(self, block_lines, compile=True):
290 290 blocks = assemble(block_lines)
291 291 lines = ''.join(blocks)
292 292 oblock = self.isp.split_blocks(lines)
293 293 self.assertEqual(oblock, blocks)
294 294 if compile:
295 295 for block in blocks:
296 296 self.isp._compile(block)
297 297
298 298 def test_split(self):
299 299 # All blocks of input we want to test in a list. The format for each
300 300 # block is a list of lists, with each inner lists consisting of all the
301 301 # lines (as single-lines) that should make up a sub-block.
302 302
303 303 # Note: do NOT put here sub-blocks that don't compile, as the
304 304 # check_split() routine makes a final verification pass to check that
305 305 # each sub_block, as returned by split_blocks(), does compile
306 306 # correctly.
307 307 all_blocks = [ [['x=1']],
308 308
309 309 [['x=1'],
310 310 ['y=2']],
311 311
312 312 [['x=1',
313 313 '# a comment'],
314 314 ['y=11']],
315 315
316 316 [['if 1:',
317 317 ' x=1'],
318 318 ['y=3']],
319 319
320 320 [['def f(x):',
321 321 ' return x'],
322 322 ['x=1']],
323 323
324 324 [['def f(x):',
325 325 ' x+=1',
326 326 ' ',
327 327 ' return x'],
328 328 ['x=1']],
329 329
330 330 [['def f(x):',
331 331 ' if x>0:',
332 332 ' y=1',
333 333 ' # a comment',
334 334 ' else:',
335 335 ' y=4',
336 336 ' ',
337 337 ' return y'],
338 338 ['x=1'],
339 339 ['if 1:',
340 340 ' y=11'] ],
341 341
342 342 [['for i in range(10):'
343 343 ' x=i**2']],
344 344
345 345 [['for i in range(10):'
346 346 ' x=i**2'],
347 347 ['z = 1']],
348 348
349 349 [['"asdf"']],
350 350
351 351 [['"asdf"'],
352 352 ['10'],
353 353 ],
354 354
355 355 [['"""foo',
356 356 'bar"""']],
357 357 ]
358 358 for block_lines in all_blocks:
359 359 self.check_split(block_lines)
360 360
361 361 def test_split_syntax_errors(self):
362 362 # Block splitting with invalid syntax
363 363 all_blocks = [ [['a syntax error']],
364 364
365 365 [['x=1',
366 366 'another syntax error']],
367 367
368 368 [['for i in range(10):'
369 369 ' yet another error']],
370 370
371 371 ]
372 372 for block_lines in all_blocks:
373 373 self.check_split(block_lines, compile=False)
374 374
375 375 def test_unicode(self):
376 376 self.isp.push(u"PΓ©rez")
377 377 self.isp.push(u'\xc3\xa9')
378 378 self.isp.push(u"u'\xc3\xa9'")
379 379
380 380 class InteractiveLoopTestCase(unittest.TestCase):
381 381 """Tests for an interactive loop like a python shell.
382 382 """
383 383 def check_ns(self, lines, ns):
384 384 """Validate that the given input lines produce the resulting namespace.
385 385
386 386 Note: the input lines are given exactly as they would be typed in an
387 387 auto-indenting environment, as mini_interactive_loop above already does
388 388 auto-indenting and prepends spaces to the input.
389 389 """
390 390 src = mini_interactive_loop(pseudo_input(lines))
391 391 test_ns = {}
392 392 exec src in test_ns
393 393 # We can't check that the provided ns is identical to the test_ns,
394 394 # because Python fills test_ns with extra keys (copyright, etc). But
395 395 # we can check that the given dict is *contained* in test_ns
396 396 for k,v in ns.iteritems():
397 397 self.assertEqual(test_ns[k], v)
398 398
399 399 def test_simple(self):
400 400 self.check_ns(['x=1'], dict(x=1))
401 401
402 402 def test_simple2(self):
403 403 self.check_ns(['if 1:', 'x=2'], dict(x=2))
404 404
405 405 def test_xy(self):
406 406 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
407 407
408 408 def test_abc(self):
409 409 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
410 410
411 411 def test_multi(self):
412 412 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
413 413
414 414
415 415 def test_LineInfo():
416 416 """Simple test for LineInfo construction and str()"""
417 417 linfo = isp.LineInfo(' %cd /home')
418 418 nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]')
419 419
420 420
421 421 def test_split_user_input():
422 422 """Unicode test - split_user_input already has good doctests"""
423 423 line = u"PΓ©rez Fernando"
424 424 parts = isp.split_user_input(line)
425 425 parts_expected = (u'', u'', u'', line)
426 426 nt.assert_equal(parts, parts_expected)
427 427
428 428
429 429 # Transformer tests
430 430 def transform_checker(tests, func):
431 431 """Utility to loop over test inputs"""
432 432 for inp, tr in tests:
433 433 nt.assert_equals(func(inp), tr)
434 434
435 435 # Data for all the syntax tests in the form of lists of pairs of
436 436 # raw/transformed input. We store it here as a global dict so that we can use
437 437 # it both within single-function tests and also to validate the behavior of the
438 438 # larger objects
439 439
440 440 syntax = \
441 441 dict(assign_system =
442 [('a =! ls', 'a = get_ipython().getoutput("ls")'),
443 ('b = !ls', 'b = get_ipython().getoutput("ls")'),
442 [('a =! ls', 'a = get_ipython().getoutput(u"ls")'),
443 ('b = !ls', 'b = get_ipython().getoutput(u"ls")'),
444 444 ('x=1', 'x=1'), # normal input is unmodified
445 445 (' ',' '), # blank lines are kept intact
446 446 ],
447 447
448 448 assign_magic =
449 [('a =% who', 'a = get_ipython().magic("who")'),
450 ('b = %who', 'b = get_ipython().magic("who")'),
449 [('a =% who', 'a = get_ipython().magic(u"who")'),
450 ('b = %who', 'b = get_ipython().magic(u"who")'),
451 451 ('x=1', 'x=1'), # normal input is unmodified
452 452 (' ',' '), # blank lines are kept intact
453 453 ],
454 454
455 455 classic_prompt =
456 456 [('>>> x=1', 'x=1'),
457 457 ('x=1', 'x=1'), # normal input is unmodified
458 458 (' ', ' '), # blank lines are kept intact
459 459 ('... ', ''), # continuation prompts
460 460 ],
461 461
462 462 ipy_prompt =
463 463 [('In [1]: x=1', 'x=1'),
464 464 ('x=1', 'x=1'), # normal input is unmodified
465 465 (' ',' '), # blank lines are kept intact
466 466 (' ....: ', ''), # continuation prompts
467 467 ],
468 468
469 469 # Tests for the escape transformer to leave normal code alone
470 470 escaped_noesc =
471 471 [ (' ', ' '),
472 472 ('x=1', 'x=1'),
473 473 ],
474 474
475 475 # System calls
476 476 escaped_shell =
477 [ ('!ls', 'get_ipython().system("ls")'),
477 [ ('!ls', 'get_ipython().system(u"ls")'),
478 478 # Double-escape shell, this means to capture the output of the
479 479 # subprocess and return it
480 ('!!ls', 'get_ipython().getoutput("ls")'),
480 ('!!ls', 'get_ipython().getoutput(u"ls")'),
481 481 ],
482 482
483 483 # Help/object info
484 484 escaped_help =
485 485 [ ('?', 'get_ipython().show_usage()'),
486 ('?x1', 'get_ipython().magic("pinfo x1")'),
487 ('??x2', 'get_ipython().magic("pinfo2 x2")'),
488 ('x3?', 'get_ipython().magic("pinfo x3")'),
489 ('x4??', 'get_ipython().magic("pinfo2 x4")'),
490 ('%hist?', 'get_ipython().magic("pinfo %hist")'),
491 ('f*?', 'get_ipython().magic("psearch f*")'),
492 ('ax.*aspe*?', 'get_ipython().magic("psearch ax.*aspe*")'),
486 ('?x1', 'get_ipython().magic(u"pinfo x1")'),
487 ('??x2', 'get_ipython().magic(u"pinfo2 x2")'),
488 ('x3?', 'get_ipython().magic(u"pinfo x3")'),
489 ('x4??', 'get_ipython().magic(u"pinfo2 x4")'),
490 ('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
491 ('f*?', 'get_ipython().magic(u"psearch f*")'),
492 ('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
493 493 ],
494 494
495 495 # Explicit magic calls
496 496 escaped_magic =
497 [ ('%cd', 'get_ipython().magic("cd")'),
498 ('%cd /home', 'get_ipython().magic("cd /home")'),
499 (' %magic', ' get_ipython().magic("magic")'),
497 [ ('%cd', 'get_ipython().magic(u"cd")'),
498 ('%cd /home', 'get_ipython().magic(u"cd /home")'),
499 (' %magic', ' get_ipython().magic(u"magic")'),
500 500 ],
501 501
502 502 # Quoting with separate arguments
503 503 escaped_quote =
504 504 [ (',f', 'f("")'),
505 505 (',f x', 'f("x")'),
506 506 (' ,f y', ' f("y")'),
507 507 (',f a b', 'f("a", "b")'),
508 508 ],
509 509
510 510 # Quoting with single argument
511 511 escaped_quote2 =
512 512 [ (';f', 'f("")'),
513 513 (';f x', 'f("x")'),
514 514 (' ;f y', ' f("y")'),
515 515 (';f a b', 'f("a b")'),
516 516 ],
517 517
518 518 # Simply apply parens
519 519 escaped_paren =
520 520 [ ('/f', 'f()'),
521 521 ('/f x', 'f(x)'),
522 522 (' /f y', ' f(y)'),
523 523 ('/f a b', 'f(a, b)'),
524 524 ],
525 525
526 526 )
527 527
528 528 # multiline syntax examples. Each of these should be a list of lists, with
529 529 # each entry itself having pairs of raw/transformed input. The union (with
530 530 # '\n'.join() of the transformed inputs is what the splitter should produce
531 531 # when fed the raw lines one at a time via push.
532 532 syntax_ml = \
533 533 dict(classic_prompt =
534 534 [ [('>>> for i in range(10):','for i in range(10):'),
535 535 ('... print i',' print i'),
536 536 ('... ', ''),
537 537 ],
538 538 ],
539 539
540 540 ipy_prompt =
541 541 [ [('In [24]: for i in range(10):','for i in range(10):'),
542 542 (' ....: print i',' print i'),
543 543 (' ....: ', ''),
544 544 ],
545 545 ],
546 546 )
547 547
548 548
549 549 def test_assign_system():
550 550 transform_checker(syntax['assign_system'], isp.transform_assign_system)
551 551
552 552
553 553 def test_assign_magic():
554 554 transform_checker(syntax['assign_magic'], isp.transform_assign_magic)
555 555
556 556
557 557 def test_classic_prompt():
558 558 transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt)
559 559 for example in syntax_ml['classic_prompt']:
560 560 transform_checker(example, isp.transform_classic_prompt)
561 561
562 562
563 563 def test_ipy_prompt():
564 564 transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt)
565 565 for example in syntax_ml['ipy_prompt']:
566 566 transform_checker(example, isp.transform_ipy_prompt)
567 567
568 568
569 569 def test_escaped_noesc():
570 570 transform_checker(syntax['escaped_noesc'], isp.transform_escaped)
571 571
572 572
573 573 def test_escaped_shell():
574 574 transform_checker(syntax['escaped_shell'], isp.transform_escaped)
575 575
576 576
577 577 def test_escaped_help():
578 578 transform_checker(syntax['escaped_help'], isp.transform_escaped)
579 579
580 580
581 581 def test_escaped_magic():
582 582 transform_checker(syntax['escaped_magic'], isp.transform_escaped)
583 583
584 584
585 585 def test_escaped_quote():
586 586 transform_checker(syntax['escaped_quote'], isp.transform_escaped)
587 587
588 588
589 589 def test_escaped_quote2():
590 590 transform_checker(syntax['escaped_quote2'], isp.transform_escaped)
591 591
592 592
593 593 def test_escaped_paren():
594 594 transform_checker(syntax['escaped_paren'], isp.transform_escaped)
595 595
596 596
597 597 class IPythonInputTestCase(InputSplitterTestCase):
598 598 """By just creating a new class whose .isp is a different instance, we
599 599 re-run the same test battery on the new input splitter.
600 600
601 601 In addition, this runs the tests over the syntax and syntax_ml dicts that
602 602 were tested by individual functions, as part of the OO interface.
603 603
604 604 It also makes some checks on the raw buffer storage.
605 605 """
606 606
607 607 def setUp(self):
608 608 self.isp = isp.IPythonInputSplitter(input_mode='line')
609 609
610 610 def test_syntax(self):
611 611 """Call all single-line syntax tests from the main object"""
612 612 isp = self.isp
613 613 for example in syntax.itervalues():
614 614 for raw, out_t in example:
615 615 if raw.startswith(' '):
616 616 continue
617 617
618 618 isp.push(raw)
619 619 out, out_raw = isp.source_raw_reset()
620 620 self.assertEqual(out.rstrip(), out_t)
621 621 self.assertEqual(out_raw.rstrip(), raw.rstrip())
622 622
623 623 def test_syntax_multiline(self):
624 624 isp = self.isp
625 625 for example in syntax_ml.itervalues():
626 626 out_t_parts = []
627 627 raw_parts = []
628 628 for line_pairs in example:
629 629 for lraw, out_t_part in line_pairs:
630 630 isp.push(lraw)
631 631 out_t_parts.append(out_t_part)
632 632 raw_parts.append(lraw)
633 633
634 634 out, out_raw = isp.source_raw_reset()
635 635 out_t = '\n'.join(out_t_parts).rstrip()
636 636 raw = '\n'.join(raw_parts).rstrip()
637 637 self.assertEqual(out.rstrip(), out_t)
638 638 self.assertEqual(out_raw.rstrip(), raw)
639 639
640 640
641 641 class BlockIPythonInputTestCase(IPythonInputTestCase):
642 642
643 643 # Deactivate tests that don't make sense for the block mode
644 644 test_push3 = test_split = lambda s: None
645 645
646 646 def setUp(self):
647 647 self.isp = isp.IPythonInputSplitter(input_mode='cell')
648 648
649 649 def test_syntax_multiline(self):
650 650 isp = self.isp
651 651 for example in syntax_ml.itervalues():
652 652 raw_parts = []
653 653 out_t_parts = []
654 654 for line_pairs in example:
655 655 for raw, out_t_part in line_pairs:
656 656 raw_parts.append(raw)
657 657 out_t_parts.append(out_t_part)
658 658
659 659 raw = '\n'.join(raw_parts)
660 660 out_t = '\n'.join(out_t_parts)
661 661
662 662 isp.push(raw)
663 663 out, out_raw = isp.source_raw_reset()
664 664 # Match ignoring trailing whitespace
665 665 self.assertEqual(out.rstrip(), out_t.rstrip())
666 666 self.assertEqual(out_raw.rstrip(), raw.rstrip())
667 667
668 668
669 669 #-----------------------------------------------------------------------------
670 670 # Main - use as a script, mostly for developer experiments
671 671 #-----------------------------------------------------------------------------
672 672
673 673 if __name__ == '__main__':
674 674 # A simple demo for interactive experimentation. This code will not get
675 675 # picked up by any test suite.
676 676 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
677 677
678 678 # configure here the syntax to use, prompt and whether to autoindent
679 679 #isp, start_prompt = InputSplitter(), '>>> '
680 680 isp, start_prompt = IPythonInputSplitter(), 'In> '
681 681
682 682 autoindent = True
683 683 #autoindent = False
684 684
685 685 try:
686 686 while True:
687 687 prompt = start_prompt
688 688 while isp.push_accepts_more():
689 689 indent = ' '*isp.indent_spaces
690 690 if autoindent:
691 691 line = indent + raw_input(prompt+indent)
692 692 else:
693 693 line = raw_input(prompt)
694 694 isp.push(line)
695 695 prompt = '... '
696 696
697 697 # Here we just return input so we can use it in a test suite, but a
698 698 # real interpreter would instead send it for execution somewhere.
699 699 #src = isp.source; raise EOFError # dbg
700 700 src, raw = isp.source_raw_reset()
701 701 print 'Input source was:\n', src
702 702 print 'Raw source was:\n', raw
703 703 except EOFError:
704 704 print 'Bye'
@@ -1,271 +1,271 b''
1 1 """Tests for the key interactiveshell module, where the main ipython class is defined.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Module imports
5 5 #-----------------------------------------------------------------------------
6 6
7 7 # stdlib
8 8 import os
9 9 import shutil
10 10 import tempfile
11 11
12 12 # third party
13 13 import nose.tools as nt
14 14
15 15 # our own packages
16 16 from IPython.testing import decorators as dec
17 17 from IPython.testing.globalipapp import get_ipython
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Globals
21 21 #-----------------------------------------------------------------------------
22 22
23 23 # Get the public instance of IPython
24 24 ip = get_ipython()
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Test functions
28 28 #-----------------------------------------------------------------------------
29 29
30 30 @dec.parametric
31 31 def test_reset():
32 32 """reset must clear most namespaces."""
33 33 # The number of variables in the private user_ns_hidden is not zero, but it
34 34 # should be constant regardless of what we do
35 35 nvars_config_ns = len(ip.user_ns_hidden)
36 36
37 37 # Check that reset runs without error
38 38 ip.reset()
39 39
40 40 # Once we've reset it (to clear of any junk that might have been there from
41 41 # other tests, we can count how many variables are in the user's namespace
42 42 nvars_user_ns = len(ip.user_ns)
43 43
44 44 # Now add a few variables to user_ns, and check that reset clears them
45 45 ip.user_ns['x'] = 1
46 46 ip.user_ns['y'] = 1
47 47 ip.reset()
48 48
49 49 # Finally, check that all namespaces have only as many variables as we
50 50 # expect to find in them:
51 51 for ns in ip.ns_refs_table:
52 52 if ns is ip.user_ns:
53 53 nvars_expected = nvars_user_ns
54 54 elif ns is ip.user_ns_hidden:
55 55 nvars_expected = nvars_config_ns
56 56 else:
57 57 nvars_expected = 0
58 58
59 59 yield nt.assert_equals(len(ns), nvars_expected)
60 60
61 61
62 62 # Tests for reporting of exceptions in various modes, handling of SystemExit,
63 63 # and %tb functionality. This is really a mix of testing ultraTB and interactiveshell.
64 64
65 65 def doctest_tb_plain():
66 66 """
67 67 In [18]: xmode plain
68 68 Exception reporting mode: Plain
69 69
70 70 In [19]: run simpleerr.py
71 71 Traceback (most recent call last):
72 72 ...line 32, in <module>
73 73 bar(mode)
74 74 ...line 16, in bar
75 75 div0()
76 76 ...line 8, in div0
77 77 x/y
78 78 ZeroDivisionError: integer division or modulo by zero
79 79 """
80 80
81 81
82 82 def doctest_tb_context():
83 83 """
84 84 In [3]: xmode context
85 85 Exception reporting mode: Context
86 86
87 87 In [4]: run simpleerr.py
88 88 ---------------------------------------------------------------------------
89 89 ZeroDivisionError Traceback (most recent call last)
90 90 <BLANKLINE>
91 91 ... in <module>()
92 92 30 mode = 'div'
93 93 31
94 94 ---> 32 bar(mode)
95 95 <BLANKLINE>
96 96 ... in bar(mode)
97 97 14 "bar"
98 98 15 if mode=='div':
99 99 ---> 16 div0()
100 100 17 elif mode=='exit':
101 101 18 try:
102 102 <BLANKLINE>
103 103 ... in div0()
104 104 6 x = 1
105 105 7 y = 0
106 106 ----> 8 x/y
107 107 9
108 108 10 def sysexit(stat, mode):
109 109 <BLANKLINE>
110 110 ZeroDivisionError: integer division or modulo by zero
111 111 """
112 112
113 113
114 114 def doctest_tb_verbose():
115 115 """
116 116 In [5]: xmode verbose
117 117 Exception reporting mode: Verbose
118 118
119 119 In [6]: run simpleerr.py
120 120 ---------------------------------------------------------------------------
121 121 ZeroDivisionError Traceback (most recent call last)
122 122 <BLANKLINE>
123 123 ... in <module>()
124 124 30 mode = 'div'
125 125 31
126 126 ---> 32 bar(mode)
127 127 global bar = <function bar at ...>
128 128 global mode = 'div'
129 129 <BLANKLINE>
130 130 ... in bar(mode='div')
131 131 14 "bar"
132 132 15 if mode=='div':
133 133 ---> 16 div0()
134 134 global div0 = <function div0 at ...>
135 135 17 elif mode=='exit':
136 136 18 try:
137 137 <BLANKLINE>
138 138 ... in div0()
139 139 6 x = 1
140 140 7 y = 0
141 141 ----> 8 x/y
142 142 x = 1
143 143 y = 0
144 144 9
145 145 10 def sysexit(stat, mode):
146 146 <BLANKLINE>
147 147 ZeroDivisionError: integer division or modulo by zero
148 148 """
149 149
150 150
151 151 def doctest_tb_sysexit():
152 152 """
153 153 In [17]: %xmode plain
154 154 Exception reporting mode: Plain
155 155
156 156 In [18]: %run simpleerr.py exit
157 157 An exception has occurred, use %tb to see the full traceback.
158 SystemExit: (1, 'Mode = exit')
158 SystemExit: (1, u'Mode = exit')
159 159
160 160 In [19]: %run simpleerr.py exit 2
161 161 An exception has occurred, use %tb to see the full traceback.
162 SystemExit: (2, 'Mode = exit')
162 SystemExit: (2, u'Mode = exit')
163 163
164 164 In [20]: %tb
165 165 Traceback (most recent call last):
166 166 File ... in <module>
167 167 bar(mode)
168 168 File ... line 22, in bar
169 169 sysexit(stat, mode)
170 170 File ... line 11, in sysexit
171 171 raise SystemExit(stat, 'Mode = %s' % mode)
172 SystemExit: (2, 'Mode = exit')
172 SystemExit: (2, u'Mode = exit')
173 173
174 174 In [21]: %xmode context
175 175 Exception reporting mode: Context
176 176
177 177 In [22]: %tb
178 178 ---------------------------------------------------------------------------
179 179 SystemExit Traceback (most recent call last)
180 180 <BLANKLINE>
181 181 ...<module>()
182 182 30 mode = 'div'
183 183 31
184 184 ---> 32 bar(mode)
185 185 <BLANKLINE>
186 186 ...bar(mode)
187 187 20 except:
188 188 21 stat = 1
189 189 ---> 22 sysexit(stat, mode)
190 190 23 else:
191 191 24 raise ValueError('Unknown mode')
192 192 <BLANKLINE>
193 193 ...sysexit(stat, mode)
194 194 9
195 195 10 def sysexit(stat, mode):
196 196 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
197 197 12
198 198 13 def bar(mode):
199 199 <BLANKLINE>
200 SystemExit: (2, 'Mode = exit')
200 SystemExit: (2, u'Mode = exit')
201 201
202 202 In [23]: %xmode verbose
203 203 Exception reporting mode: Verbose
204 204
205 205 In [24]: %tb
206 206 ---------------------------------------------------------------------------
207 207 SystemExit Traceback (most recent call last)
208 208 <BLANKLINE>
209 209 ... in <module>()
210 210 30 mode = 'div'
211 211 31
212 212 ---> 32 bar(mode)
213 213 global bar = <function bar at ...>
214 global mode = 'exit'
214 global mode = u'exit'
215 215 <BLANKLINE>
216 ... in bar(mode='exit')
216 ... in bar(mode=u'exit')
217 217 20 except:
218 218 21 stat = 1
219 219 ---> 22 sysexit(stat, mode)
220 220 global sysexit = <function sysexit at ...>
221 221 stat = 2
222 mode = 'exit'
222 mode = u'exit'
223 223 23 else:
224 224 24 raise ValueError('Unknown mode')
225 225 <BLANKLINE>
226 ... in sysexit(stat=2, mode='exit')
226 ... in sysexit(stat=2, mode=u'exit')
227 227 9
228 228 10 def sysexit(stat, mode):
229 229 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
230 230 global SystemExit = undefined
231 231 stat = 2
232 mode = 'exit'
232 mode = u'exit'
233 233 12
234 234 13 def bar(mode):
235 235 <BLANKLINE>
236 SystemExit: (2, 'Mode = exit')
236 SystemExit: (2, u'Mode = exit')
237 237 """
238 238
239 239
240 240 def test_runlines():
241 241 import textwrap
242 242 ip.runlines(['a = 10', 'a+=1'])
243 243 ip.runlines('assert a == 11\nassert 1')
244 244
245 245 nt.assert_equals(ip.user_ns['a'], 11)
246 246 complex = textwrap.dedent("""
247 247 if 1:
248 248 print "hello"
249 249 if 1:
250 250 print "world"
251 251
252 252 if 2:
253 253 print "foo"
254 254
255 255 if 3:
256 256 print "bar"
257 257
258 258 if 4:
259 259 print "bar"
260 260
261 261 """)
262 262 # Simply verifies that this kind of input is run
263 263 ip.runlines(complex)
264 264
265 265
266 266 def test_db():
267 267 """Test the internal database used for variable persistence."""
268 268 ip.db['__unittest_'] = 12
269 269 nt.assert_equals(ip.db['__unittest_'], 12)
270 270 del ip.db['__unittest_']
271 271 assert '__unittest_' not in ip.db
@@ -1,186 +1,186 b''
1 1 """Tests for code execution (%run and related), which is particularly tricky.
2 2
3 3 Because of how %run manages namespaces, and the fact that we are trying here to
4 4 verify subtle object deletion and reference counting issues, the %run tests
5 5 will be kept in this separate file. This makes it easier to aggregate in one
6 6 place the tricks needed to handle it; most other magics are much easier to test
7 7 and we do so in a common test_magic file.
8 8 """
9 9 from __future__ import absolute_import
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 import os
16 16 import sys
17 17 import tempfile
18 18
19 19 import nose.tools as nt
20 20
21 21 from IPython.testing import decorators as dec
22 22 from IPython.testing import tools as tt
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Test functions begin
26 26 #-----------------------------------------------------------------------------
27 27
28 28 def doctest_refbug():
29 29 """Very nasty problem with references held by multiple runs of a script.
30 30 See: https://bugs.launchpad.net/ipython/+bug/269966
31 31
32 32 In [1]: _ip.clear_main_mod_cache()
33 33 # random
34 34
35 35 In [2]: %run refbug
36 36
37 37 In [3]: call_f()
38 38 lowercased: hello
39 39
40 40 In [4]: %run refbug
41 41
42 42 In [5]: call_f()
43 43 lowercased: hello
44 44 lowercased: hello
45 45 """
46 46
47 47
48 48 def doctest_run_builtins():
49 49 r"""Check that %run doesn't damage __builtins__.
50 50
51 51 In [1]: import tempfile
52 52
53 53 In [2]: bid1 = id(__builtins__)
54 54
55 55 In [3]: fname = tempfile.mkstemp('.py')[1]
56 56
57 57 In [3]: f = open(fname,'w')
58 58
59 59 In [4]: f.write('pass\n')
60 60
61 61 In [5]: f.flush()
62 62
63 63 In [6]: t1 = type(__builtins__)
64 64
65 65 In [7]: %run $fname
66 66
67 67 In [7]: f.close()
68 68
69 69 In [8]: bid2 = id(__builtins__)
70 70
71 71 In [9]: t2 = type(__builtins__)
72 72
73 73 In [10]: t1 == t2
74 74 Out[10]: True
75 75
76 76 In [10]: bid1 == bid2
77 77 Out[10]: True
78 78
79 79 In [12]: try:
80 80 ....: os.unlink(fname)
81 81 ....: except:
82 82 ....: pass
83 83 ....:
84 84 """
85 85
86 86 def doctest_reset_del():
87 87 """Test that resetting doesn't cause errors in __del__ methods.
88 88
89 89 In [2]: class A(object):
90 90 ...: def __del__(self):
91 91 ...: print str("Hi")
92 92 ...:
93 93
94 94 In [3]: a = A()
95 95
96 96 In [4]: get_ipython().reset()
97 97 Hi
98 98
99 99 In [5]: 1+1
100 100 Out[5]: 2
101 101 """
102 102
103 103 # For some tests, it will be handy to organize them in a class with a common
104 104 # setup that makes a temp file
105 105
106 106 class TestMagicRunPass(tt.TempFileMixin):
107 107
108 108 def setup(self):
109 109 """Make a valid python temp file."""
110 110 self.mktmp('pass\n')
111 111
112 112 def run_tmpfile(self):
113 113 _ip = get_ipython()
114 114 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
115 115 # See below and ticket https://bugs.launchpad.net/bugs/366353
116 116 _ip.magic('run %s' % self.fname)
117 117
118 118 def test_builtins_id(self):
119 119 """Check that %run doesn't damage __builtins__ """
120 120 _ip = get_ipython()
121 121 # Test that the id of __builtins__ is not modified by %run
122 122 bid1 = id(_ip.user_ns['__builtins__'])
123 123 self.run_tmpfile()
124 124 bid2 = id(_ip.user_ns['__builtins__'])
125 125 tt.assert_equals(bid1, bid2)
126 126
127 127 def test_builtins_type(self):
128 128 """Check that the type of __builtins__ doesn't change with %run.
129 129
130 130 However, the above could pass if __builtins__ was already modified to
131 131 be a dict (it should be a module) by a previous use of %run. So we
132 132 also check explicitly that it really is a module:
133 133 """
134 134 _ip = get_ipython()
135 135 self.run_tmpfile()
136 136 tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys))
137 137
138 138 def test_prompts(self):
139 139 """Test that prompts correctly generate after %run"""
140 140 self.run_tmpfile()
141 141 _ip = get_ipython()
142 142 p2 = str(_ip.displayhook.prompt2).strip()
143 143 nt.assert_equals(p2[:3], '...')
144 144
145 145
146 146 class TestMagicRunSimple(tt.TempFileMixin):
147 147
148 148 def test_simpledef(self):
149 149 """Test that simple class definitions work."""
150 150 src = ("class foo: pass\n"
151 151 "def f(): return foo()")
152 152 self.mktmp(src)
153 153 _ip.magic('run %s' % self.fname)
154 154 _ip.runlines('t = isinstance(f(), foo)')
155 155 nt.assert_true(_ip.user_ns['t'])
156 156
157 157 # We have to skip these in win32 because getoutputerr() crashes,
158 158 # due to the fact that subprocess does not support close_fds when
159 159 # redirecting stdout/err. So unless someone who knows more tells us how to
160 160 # implement getoutputerr() in win32, we're stuck avoiding these.
161 161 @dec.skip_win32
162 162 def test_obj_del(self):
163 163 """Test that object's __del__ methods are called on exit."""
164 164
165 165 # This test is known to fail on win32.
166 166 # See ticket https://bugs.launchpad.net/bugs/366334
167 167 src = ("class A(object):\n"
168 168 " def __del__(self):\n"
169 169 " print 'object A deleted'\n"
170 170 "a = A()\n")
171 171 self.mktmp(src)
172 172 tt.ipexec_validate(self.fname, 'object A deleted')
173 173
174 174 @dec.skip_win32
175 175 def test_tclass(self):
176 176 mydir = os.path.dirname(__file__)
177 177 tc = os.path.join(mydir, 'tclass')
178 178 src = ("%%run '%s' C-first\n"
179 179 "%%run '%s' C-second\n") % (tc, tc)
180 180 self.mktmp(src, '.ipy')
181 181 out = """\
182 ARGV 1-: ['C-first']
183 ARGV 1-: ['C-second']
182 ARGV 1-: [u'C-first']
183 ARGV 1-: [u'C-second']
184 184 tclass.py: deleting object: C-first
185 185 """
186 186 tt.ipexec_validate(self.fname, out)
General Comments 0
You need to be logged in to leave comments. Login now