##// END OF EJS Templates
Merge pull request #4151 from takluyver/drop-alias...
Thomas Kluyver -
r12759:b1100aa2 merge
parent child Browse files
Show More
@@ -0,0 +1,41 b''
1 from IPython.utils.capture import capture_output
2
3 import nose.tools as nt
4
5 def test_alias_lifecycle():
6 name = 'test_alias1'
7 cmd = 'echo "Hello"'
8 am = _ip.alias_manager
9 am.clear_aliases()
10 am.define_alias(name, cmd)
11 assert am.is_alias(name)
12 nt.assert_equal(am.retrieve_alias(name), cmd)
13 nt.assert_in((name, cmd), am.aliases)
14
15 # Test running the alias
16 orig_system = _ip.system
17 result = []
18 _ip.system = result.append
19 try:
20 _ip.run_cell('%{}'.format(name))
21 result = [c.strip() for c in result]
22 nt.assert_equal(result, [cmd])
23 finally:
24 _ip.system = orig_system
25
26 # Test removing the alias
27 am.undefine_alias(name)
28 assert not am.is_alias(name)
29 with nt.assert_raises(ValueError):
30 am.retrieve_alias(name)
31 nt.assert_not_in((name, cmd), am.aliases)
32
33
34 def test_alias_args_error():
35 """Error expanding with wrong number of arguments"""
36 _ip.alias_manager.define_alias('parts', 'echo first %s second %s')
37 # capture stderr:
38 with capture_output() as cap:
39 _ip.run_cell('parts 1')
40
41 nt.assert_equal(cap.stderr.split(':')[0], 'UsageError') No newline at end of file
@@ -0,0 +1,3 b''
1 - The alias system has been reimplemented to use magic functions. There should be little
2 visible difference while automagics are enabled, as they are by default, but parts of the
3 :class:`~IPython.core.alias.AliasManager` API have been removed.
@@ -20,17 +20,15 b' Authors:'
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import __builtin__
24 import keyword
25 import os
23 import os
26 import re
24 import re
27 import sys
25 import sys
28
26
29 from IPython.config.configurable import Configurable
27 from IPython.config.configurable import Configurable
30 from IPython.core.splitinput import split_user_input
28 from IPython.core.error import UsageError
31
29
32 from IPython.utils.traitlets import List, Instance
30 from IPython.utils.traitlets import List, Instance
33 from IPython.utils.warn import warn, error
31 from IPython.utils.warn import error
34
32
35 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
36 # Utilities
34 # Utilities
@@ -104,97 +102,53 b' class AliasError(Exception):'
104 class InvalidAliasError(AliasError):
102 class InvalidAliasError(AliasError):
105 pass
103 pass
106
104
107 #-----------------------------------------------------------------------------
105 class Alias(object):
108 # Main AliasManager class
106 """Callable object storing the details of one alias.
109 #-----------------------------------------------------------------------------
110
111 class AliasManager(Configurable):
112
113 default_aliases = List(default_aliases(), config=True)
114 user_aliases = List(default_value=[], config=True)
115 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
116
117 def __init__(self, shell=None, **kwargs):
118 super(AliasManager, self).__init__(shell=shell, **kwargs)
119 self.alias_table = {}
120 self.exclude_aliases()
121 self.init_aliases()
122
123 def __contains__(self, name):
124 return name in self.alias_table
125
126 @property
127 def aliases(self):
128 return [(item[0], item[1][1]) for item in self.alias_table.iteritems()]
129
130 def exclude_aliases(self):
131 # set of things NOT to alias (keywords, builtins and some magics)
132 no_alias = set(['cd','popd','pushd','dhist','alias','unalias'])
133 no_alias.update(set(keyword.kwlist))
134 no_alias.update(set(__builtin__.__dict__.keys()))
135 self.no_alias = no_alias
136
107
137 def init_aliases(self):
108 Instances are registered as magic functions to allow use of aliases.
138 # Load default aliases
109 """
139 for name, cmd in self.default_aliases:
140 self.soft_define_alias(name, cmd)
141
110
142 # Load user aliases
111 # Prepare blacklist
143 for name, cmd in self.user_aliases:
112 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
144 self.soft_define_alias(name, cmd)
145
113
146 def clear_aliases(self):
114 def __init__(self, shell, name, cmd):
147 self.alias_table.clear()
115 self.shell = shell
116 self.name = name
117 self.cmd = cmd
118 self.nargs = self.validate()
148
119
149 def soft_define_alias(self, name, cmd):
120 def validate(self):
150 """Define an alias, but don't raise on an AliasError."""
121 """Validate the alias, and return the number of arguments."""
122 if self.name in self.blacklist:
123 raise InvalidAliasError("The name %s can't be aliased "
124 "because it is a keyword or builtin." % self.name)
151 try:
125 try:
152 self.define_alias(name, cmd)
126 caller = self.shell.magics_manager.magics['line'][self.name]
153 except AliasError as e:
127 except KeyError:
154 error("Invalid alias: %s" % e)
128 pass
155
129 else:
156 def define_alias(self, name, cmd):
130 if not isinstance(caller, Alias):
157 """Define a new alias after validating it.
131 raise InvalidAliasError("The name %s can't be aliased "
132 "because it is another magic command." % self.name)
158
133
159 This will raise an :exc:`AliasError` if there are validation
134 if not (isinstance(self.cmd, basestring)):
160 problems.
135 raise InvalidAliasError("An alias command must be a string, "
161 """
136 "got: %r" % self.cmd)
162 nargs = self.validate_alias(name, cmd)
163 self.alias_table[name] = (nargs, cmd)
164
137
165 def undefine_alias(self, name):
138 nargs = self.cmd.count('%s')
166 if name in self.alias_table:
167 del self.alias_table[name]
168
139
169 def validate_alias(self, name, cmd):
140 if (nargs > 0) and (self.cmd.find('%l') >= 0):
170 """Validate an alias and return the its number of arguments."""
171 if name in self.no_alias:
172 raise InvalidAliasError("The name %s can't be aliased "
173 "because it is a keyword or builtin." % name)
174 if not (isinstance(cmd, basestring)):
175 raise InvalidAliasError("An alias command must be a string, "
176 "got: %r" % cmd)
177 nargs = cmd.count('%s')
178 if nargs>0 and cmd.find('%l')>=0:
179 raise InvalidAliasError('The %s and %l specifiers are mutually '
141 raise InvalidAliasError('The %s and %l specifiers are mutually '
180 'exclusive in alias definitions.')
142 'exclusive in alias definitions.')
181 return nargs
182
183 def call_alias(self, alias, rest=''):
184 """Call an alias given its name and the rest of the line."""
185 cmd = self.transform_alias(alias, rest)
186 try:
187 self.shell.system(cmd)
188 except:
189 self.shell.showtraceback()
190
143
191 def transform_alias(self, alias,rest=''):
144 return nargs
192 """Transform alias to system command string."""
193 nargs, cmd = self.alias_table[alias]
194
145
195 if ' ' in cmd and os.path.isfile(cmd):
146 def __repr__(self):
196 cmd = '"%s"' % cmd
147 return "<alias {} for {!r}>".format(self.name, self.cmd)
197
148
149 def __call__(self, rest=''):
150 cmd = self.cmd
151 nargs = self.nargs
198 # Expand the %l special to be the user's input line
152 # Expand the %l special to be the user's input line
199 if cmd.find('%l') >= 0:
153 if cmd.find('%l') >= 0:
200 cmd = cmd.replace('%l', rest)
154 cmd = cmd.replace('%l', rest)
@@ -206,57 +160,78 b' class AliasManager(Configurable):'
206 # Handle aliases with positional arguments
160 # Handle aliases with positional arguments
207 args = rest.split(None, nargs)
161 args = rest.split(None, nargs)
208 if len(args) < nargs:
162 if len(args) < nargs:
209 raise AliasError('Alias <%s> requires %s arguments, %s given.' %
163 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
210 (alias, nargs, len(args)))
164 (self.name, nargs, len(args)))
211 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
165 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
212 return cmd
213
166
214 def expand_alias(self, line):
167 self.shell.system(cmd)
215 """ Expand an alias in the command line
168
169 #-----------------------------------------------------------------------------
170 # Main AliasManager class
171 #-----------------------------------------------------------------------------
216
172
217 Returns the provided command line, possibly with the first word
173 class AliasManager(Configurable):
218 (command) translated according to alias expansion rules.
219
174
220 [ipython]|16> _ip.expand_aliases("np myfile.txt")
175 default_aliases = List(default_aliases(), config=True)
221 <16> 'q:/opt/np/notepad++.exe myfile.txt'
176 user_aliases = List(default_value=[], config=True)
222 """
177 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
223
178
224 pre,_,fn,rest = split_user_input(line)
179 def __init__(self, shell=None, **kwargs):
225 res = pre + self.expand_aliases(fn, rest)
180 super(AliasManager, self).__init__(shell=shell, **kwargs)
226 return res
181 # For convenient access
182 self.linemagics = self.shell.magics_manager.magics['line']
183 self.init_aliases()
227
184
228 def expand_aliases(self, fn, rest):
185 def init_aliases(self):
229 """Expand multiple levels of aliases:
186 # Load default & user aliases
187 for name, cmd in self.default_aliases + self.user_aliases:
188 self.soft_define_alias(name, cmd)
230
189
231 if:
190 @property
191 def aliases(self):
192 return [(n, func.cmd) for (n, func) in self.linemagics.items()
193 if isinstance(func, Alias)]
232
194
233 alias foo bar /tmp
195 def soft_define_alias(self, name, cmd):
234 alias baz foo
196 """Define an alias, but don't raise on an AliasError."""
197 try:
198 self.define_alias(name, cmd)
199 except AliasError as e:
200 error("Invalid alias: %s" % e)
235
201
236 then:
202 def define_alias(self, name, cmd):
203 """Define a new alias after validating it.
237
204
238 baz huhhahhei -> bar /tmp huhhahhei
205 This will raise an :exc:`AliasError` if there are validation
206 problems.
239 """
207 """
240 line = fn + " " + rest
208 caller = Alias(shell=self.shell, name=name, cmd=cmd)
241
209 self.shell.magics_manager.register_function(caller, magic_kind='line',
242 done = set()
210 magic_name=name)
243 while 1:
211
244 pre,_,fn,rest = split_user_input(line, shell_line_split)
212 def get_alias(self, name):
245 if fn in self.alias_table:
213 """Return an alias, or None if no alias by that name exists."""
246 if fn in done:
214 aname = self.linemagics.get(name, None)
247 warn("Cyclic alias definition, repeated '%s'" % fn)
215 return aname if isinstance(aname, Alias) else None
248 return ""
216
249 done.add(fn)
217 def is_alias(self, name):
250
218 """Return whether or not a given name has been defined as an alias"""
251 l2 = self.transform_alias(fn, rest)
219 return self.get_alias(name) is not None
252 if l2 == line:
220
253 break
221 def undefine_alias(self, name):
254 # ls -> ls -F should not recurse forever
222 if self.is_alias(name):
255 if l2.split(None,1)[0] == line.split(None,1)[0]:
223 del self.linemagics[name]
256 line = l2
257 break
258 line = l2
259 else:
224 else:
260 break
225 raise ValueError('%s is not an alias' % name)
261
226
262 return line
227 def clear_aliases(self):
228 for name, cmd in self.aliases:
229 self.undefine_alias(name)
230
231 def retrieve_alias(self, name):
232 """Retrieve the command to which an alias expands."""
233 caller = self.get_alias(name)
234 if caller:
235 return caller.cmd
236 else:
237 raise ValueError('%s is not an alias' % name)
@@ -431,8 +431,7 b' class IPCompleter(Completer):'
431 )
431 )
432
432
433 def __init__(self, shell=None, namespace=None, global_namespace=None,
433 def __init__(self, shell=None, namespace=None, global_namespace=None,
434 alias_table=None, use_readline=True,
434 use_readline=True, config=None, **kwargs):
435 config=None, **kwargs):
436 """IPCompleter() -> completer
435 """IPCompleter() -> completer
437
436
438 Return a completer object suitable for use by the readline library
437 Return a completer object suitable for use by the readline library
@@ -450,9 +449,6 b' class IPCompleter(Completer):'
450 handle cases (such as IPython embedded inside functions) where
449 handle cases (such as IPython embedded inside functions) where
451 both Python scopes are visible.
450 both Python scopes are visible.
452
451
453 - If alias_table is supplied, it should be a dictionary of aliases
454 to complete.
455
456 use_readline : bool, optional
452 use_readline : bool, optional
457 If true, use the readline library. This completer can still function
453 If true, use the readline library. This completer can still function
458 without readline, though in that case callers must provide some extra
454 without readline, though in that case callers must provide some extra
@@ -476,9 +472,6 b' class IPCompleter(Completer):'
476 # List where completion matches will be stored
472 # List where completion matches will be stored
477 self.matches = []
473 self.matches = []
478 self.shell = shell
474 self.shell = shell
479 if alias_table is None:
480 alias_table = {}
481 self.alias_table = alias_table
482 # Regexp to split filenames with spaces in them
475 # Regexp to split filenames with spaces in them
483 self.space_name_re = re.compile(r'([^\\] )')
476 self.space_name_re = re.compile(r'([^\\] )')
484 # Hold a local ref. to glob.glob for speed
477 # Hold a local ref. to glob.glob for speed
@@ -505,7 +498,6 b' class IPCompleter(Completer):'
505 self.matchers = [self.python_matches,
498 self.matchers = [self.python_matches,
506 self.file_matches,
499 self.file_matches,
507 self.magic_matches,
500 self.magic_matches,
508 self.alias_matches,
509 self.python_func_kw_matches,
501 self.python_func_kw_matches,
510 ]
502 ]
511
503
@@ -628,22 +620,6 b' class IPCompleter(Completer):'
628 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
620 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
629 return comp
621 return comp
630
622
631 def alias_matches(self, text):
632 """Match internal system aliases"""
633 #print 'Completer->alias_matches:',text,'lb',self.text_until_cursor # dbg
634
635 # if we are not in the first 'item', alias matching
636 # doesn't make sense - unless we are starting with 'sudo' command.
637 main_text = self.text_until_cursor.lstrip()
638 if ' ' in main_text and not main_text.startswith('sudo'):
639 return []
640 text = os.path.expanduser(text)
641 aliases = self.alias_table.keys()
642 if text == '':
643 return aliases
644 else:
645 return [a for a in aliases if a.startswith(text)]
646
647 def python_matches(self,text):
623 def python_matches(self,text):
648 """Match attributes or global python names"""
624 """Match attributes or global python names"""
649
625
@@ -470,7 +470,6 b' class InteractiveShell(SingletonConfigurable):'
470 # because it and init_io have to come after init_readline.
470 # because it and init_io have to come after init_readline.
471 self.init_user_ns()
471 self.init_user_ns()
472 self.init_logger()
472 self.init_logger()
473 self.init_alias()
474 self.init_builtins()
473 self.init_builtins()
475
474
476 # The following was in post_config_initialization
475 # The following was in post_config_initialization
@@ -502,6 +501,7 b' class InteractiveShell(SingletonConfigurable):'
502 self.init_displayhook()
501 self.init_displayhook()
503 self.init_latextool()
502 self.init_latextool()
504 self.init_magics()
503 self.init_magics()
504 self.init_alias()
505 self.init_logstart()
505 self.init_logstart()
506 self.init_pdb()
506 self.init_pdb()
507 self.init_extension_manager()
507 self.init_extension_manager()
@@ -1363,9 +1363,7 b' class InteractiveShell(SingletonConfigurable):'
1363 namespaces = [ ('Interactive', self.user_ns),
1363 namespaces = [ ('Interactive', self.user_ns),
1364 ('Interactive (global)', self.user_global_ns),
1364 ('Interactive (global)', self.user_global_ns),
1365 ('Python builtin', builtin_mod.__dict__),
1365 ('Python builtin', builtin_mod.__dict__),
1366 ('Alias', self.alias_manager.alias_table),
1367 ]
1366 ]
1368 alias_ns = self.alias_manager.alias_table
1369
1367
1370 # initialize results to 'null'
1368 # initialize results to 'null'
1371 found = False; obj = None; ospace = None; ds = None;
1369 found = False; obj = None; ospace = None; ds = None;
@@ -1404,8 +1402,6 b' class InteractiveShell(SingletonConfigurable):'
1404 # If we finish the for loop (no break), we got all members
1402 # If we finish the for loop (no break), we got all members
1405 found = True
1403 found = True
1406 ospace = nsname
1404 ospace = nsname
1407 if ns == alias_ns:
1408 isalias = True
1409 break # namespace loop
1405 break # namespace loop
1410
1406
1411 # Try to see if it's magic
1407 # Try to see if it's magic
@@ -1940,7 +1936,6 b' class InteractiveShell(SingletonConfigurable):'
1940 self.Completer = IPCompleter(shell=self,
1936 self.Completer = IPCompleter(shell=self,
1941 namespace=self.user_ns,
1937 namespace=self.user_ns,
1942 global_namespace=self.user_global_ns,
1938 global_namespace=self.user_global_ns,
1943 alias_table=self.alias_manager.alias_table,
1944 use_readline=self.has_readline,
1939 use_readline=self.has_readline,
1945 parent=self,
1940 parent=self,
1946 )
1941 )
@@ -2305,7 +2300,6 b' class InteractiveShell(SingletonConfigurable):'
2305 def init_alias(self):
2300 def init_alias(self):
2306 self.alias_manager = AliasManager(shell=self, parent=self)
2301 self.alias_manager = AliasManager(shell=self, parent=self)
2307 self.configurables.append(self.alias_manager)
2302 self.configurables.append(self.alias_manager)
2308 self.ns_table['alias'] = self.alias_manager.alias_table,
2309
2303
2310 #-------------------------------------------------------------------------
2304 #-------------------------------------------------------------------------
2311 # Things related to extensions
2305 # Things related to extensions
@@ -26,6 +26,7 b' from pprint import pformat'
26 from IPython.core import magic_arguments
26 from IPython.core import magic_arguments
27 from IPython.core import oinspect
27 from IPython.core import oinspect
28 from IPython.core import page
28 from IPython.core import page
29 from IPython.core.alias import AliasError, Alias
29 from IPython.core.error import UsageError
30 from IPython.core.error import UsageError
30 from IPython.core.magic import (
31 from IPython.core.magic import (
31 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
32 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
@@ -113,10 +114,14 b' class OSMagics(Magics):'
113 # Now try to define a new one
114 # Now try to define a new one
114 try:
115 try:
115 alias,cmd = par.split(None, 1)
116 alias,cmd = par.split(None, 1)
116 except:
117 except TypeError:
117 print oinspect.getdoc(self.alias)
118 print(oinspect.getdoc(self.alias))
118 else:
119 return
119 self.shell.alias_manager.soft_define_alias(alias, cmd)
120
121 try:
122 self.shell.alias_manager.define_alias(alias, cmd)
123 except AliasError as e:
124 print(e)
120 # end magic_alias
125 # end magic_alias
121
126
122 @line_magic
127 @line_magic
@@ -124,7 +129,12 b' class OSMagics(Magics):'
124 """Remove an alias"""
129 """Remove an alias"""
125
130
126 aname = parameter_s.strip()
131 aname = parameter_s.strip()
132 try:
127 self.shell.alias_manager.undefine_alias(aname)
133 self.shell.alias_manager.undefine_alias(aname)
134 except ValueError as e:
135 print(e)
136 return
137
128 stored = self.shell.db.get('stored_aliases', {} )
138 stored = self.shell.db.get('stored_aliases', {} )
129 if aname in stored:
139 if aname in stored:
130 print "Removing %stored alias",aname
140 print "Removing %stored alias",aname
@@ -182,7 +192,7 b' class OSMagics(Magics):'
182 try:
192 try:
183 # Removes dots from the name since ipython
193 # Removes dots from the name since ipython
184 # will assume names with dots to be python.
194 # will assume names with dots to be python.
185 if ff not in self.shell.alias_manager:
195 if not self.shell.alias_manager.is_alias(ff):
186 self.shell.alias_manager.define_alias(
196 self.shell.alias_manager.define_alias(
187 ff.replace('.',''), ff)
197 ff.replace('.',''), ff)
188 except InvalidAliasError:
198 except InvalidAliasError:
@@ -190,7 +200,7 b' class OSMagics(Magics):'
190 else:
200 else:
191 syscmdlist.append(ff)
201 syscmdlist.append(ff)
192 else:
202 else:
193 no_alias = self.shell.alias_manager.no_alias
203 no_alias = Alias.blacklist
194 for pdir in path:
204 for pdir in path:
195 os.chdir(pdir)
205 os.chdir(pdir)
196 for ff in os.listdir(pdir):
206 for ff in os.listdir(pdir):
@@ -488,22 +488,6 b' class AutoMagicChecker(PrefilterChecker):'
488 return self.prefilter_manager.get_handler_by_name('magic')
488 return self.prefilter_manager.get_handler_by_name('magic')
489
489
490
490
491 class AliasChecker(PrefilterChecker):
492
493 priority = Integer(800, config=True)
494
495 def check(self, line_info):
496 "Check if the initital identifier on the line is an alias."
497 # Note: aliases can not contain '.'
498 head = line_info.ifun.split('.',1)[0]
499 if line_info.ifun not in self.shell.alias_manager \
500 or head not in self.shell.alias_manager \
501 or is_shadowed(head, self.shell):
502 return None
503
504 return self.prefilter_manager.get_handler_by_name('alias')
505
506
507 class PythonOpsChecker(PrefilterChecker):
491 class PythonOpsChecker(PrefilterChecker):
508
492
509 priority = Integer(900, config=True)
493 priority = Integer(900, config=True)
@@ -591,20 +575,6 b' class PrefilterHandler(Configurable):'
591 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
575 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
592
576
593
577
594 class AliasHandler(PrefilterHandler):
595
596 handler_name = Unicode('alias')
597
598 def handle(self, line_info):
599 """Handle alias input lines. """
600 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
601 # pre is needed, because it carries the leading whitespace. Otherwise
602 # aliases won't work in indented sections.
603 line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed)
604
605 return line_out
606
607
608 class MacroHandler(PrefilterHandler):
578 class MacroHandler(PrefilterHandler):
609 handler_name = Unicode("macro")
579 handler_name = Unicode("macro")
610
580
@@ -730,14 +700,12 b' _default_checkers = ['
730 IPyAutocallChecker,
700 IPyAutocallChecker,
731 AssignmentChecker,
701 AssignmentChecker,
732 AutoMagicChecker,
702 AutoMagicChecker,
733 AliasChecker,
734 PythonOpsChecker,
703 PythonOpsChecker,
735 AutocallChecker
704 AutocallChecker
736 ]
705 ]
737
706
738 _default_handlers = [
707 _default_handlers = [
739 PrefilterHandler,
708 PrefilterHandler,
740 AliasHandler,
741 MacroHandler,
709 MacroHandler,
742 MagicHandler,
710 MagicHandler,
743 AutoHandler,
711 AutoHandler,
@@ -45,28 +45,6 b' def run(tests):'
45
45
46
46
47 def test_handlers():
47 def test_handlers():
48 # alias expansion
49
50 # We're using 'true' as our syscall of choice because it doesn't
51 # write anything to stdout.
52
53 # Turn off actual execution of aliases, because it's noisy
54 old_system_cmd = ip.system
55 ip.system = lambda cmd: None
56
57
58 ip.alias_manager.alias_table['an_alias'] = (0, 'true')
59 # These are useful for checking a particular recursive alias issue
60 ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
61 ip.alias_manager.alias_table['d'] = (0, 'true')
62 run([(i,py3compat.u_format(o)) for i,o in \
63 [("an_alias", "get_ipython().system({u}'true ')"), # alias
64 # Below: recursive aliases should expand whitespace-surrounded
65 # chars, *not* initial chars which happen to be aliases:
66 ("top", "get_ipython().system({u}'d:/cygwin/top ')"),
67 ]])
68 ip.system = old_system_cmd
69
70 call_idx = CallableIndexable()
48 call_idx = CallableIndexable()
71 ip.user_ns['call_idx'] = call_idx
49 ip.user_ns['call_idx'] = call_idx
72
50
@@ -106,17 +106,6 b' class InteractiveShellTestCase(unittest.TestCase):'
106 ip.run_cell('a = """\n%exit\n"""')
106 ip.run_cell('a = """\n%exit\n"""')
107 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
107 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
108
108
109 def test_alias_crash(self):
110 """Errors in prefilter can't crash IPython"""
111 ip.run_cell('%alias parts echo first %s second %s')
112 # capture stderr:
113 save_err = io.stderr
114 io.stderr = StringIO()
115 ip.run_cell('parts 1')
116 err = io.stderr.getvalue()
117 io.stderr = save_err
118 self.assertEqual(err.split(':')[0], 'ERROR')
119
120 def test_trailing_newline(self):
109 def test_trailing_newline(self):
121 """test that running !(command) does not raise a SyntaxError"""
110 """test that running !(command) does not raise a SyntaxError"""
122 ip.run_cell('!(true)\n', False)
111 ip.run_cell('!(true)\n', False)
@@ -48,16 +48,16 b' class DummyMagics(magic.Magics): pass'
48 def test_rehashx():
48 def test_rehashx():
49 # clear up everything
49 # clear up everything
50 _ip = get_ipython()
50 _ip = get_ipython()
51 _ip.alias_manager.alias_table.clear()
51 _ip.alias_manager.clear_aliases()
52 del _ip.db['syscmdlist']
52 del _ip.db['syscmdlist']
53
53
54 _ip.magic('rehashx')
54 _ip.magic('rehashx')
55 # Practically ALL ipython development systems will have more than 10 aliases
55 # Practically ALL ipython development systems will have more than 10 aliases
56
56
57 nt.assert_true(len(_ip.alias_manager.alias_table) > 10)
57 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
58 for key, val in _ip.alias_manager.alias_table.iteritems():
58 for name, cmd in _ip.alias_manager.aliases:
59 # we must strip dots from alias names
59 # we must strip dots from alias names
60 nt.assert_not_in('.', key)
60 nt.assert_not_in('.', name)
61
61
62 # rehashx must fill up syscmdlist
62 # rehashx must fill up syscmdlist
63 scoms = _ip.db['syscmdlist']
63 scoms = _ip.db['syscmdlist']
@@ -210,17 +210,17 b' class StoreMagics(Magics, Configurable):'
210 obj = ip.user_ns[args[0]]
210 obj = ip.user_ns[args[0]]
211 except KeyError:
211 except KeyError:
212 # it might be an alias
212 # it might be an alias
213 # This needs to be refactored to use the new AliasManager stuff.
214 if args[0] in ip.alias_manager:
215 name = args[0]
213 name = args[0]
216 nargs, cmd = ip.alias_manager.alias_table[ name ]
214 try:
215 cmd = ip.alias_manager.retrieve_alias(name)
216 except ValueError:
217 raise UsageError("Unknown variable '%s'" % name)
218
217 staliases = db.get('stored_aliases',{})
219 staliases = db.get('stored_aliases',{})
218 staliases[ name ] = cmd
220 staliases[name] = cmd
219 db['stored_aliases'] = staliases
221 db['stored_aliases'] = staliases
220 print "Alias stored: %s (%s)" % (name, cmd)
222 print "Alias stored: %s (%s)" % (name, cmd)
221 return
223 return
222 else:
223 raise UsageError("Unknown variable '%s'" % args[0])
224
224
225 else:
225 else:
226 modname = getattr(inspect.getmodule(obj), '__name__', '')
226 modname = getattr(inspect.getmodule(obj), '__name__', '')
@@ -27,7 +27,7 b' def test_store_restore():'
27 # Check restoring
27 # Check restoring
28 ip.magic('store -r')
28 ip.magic('store -r')
29 nt.assert_equal(ip.user_ns['foo'], 78)
29 nt.assert_equal(ip.user_ns['foo'], 78)
30 nt.assert_in('bar', ip.alias_manager.alias_table)
30 assert ip.alias_manager.is_alias('bar')
31 nt.assert_in(os.path.realpath(tmpd), ip.user_ns['_dh'])
31 nt.assert_in(os.path.realpath(tmpd), ip.user_ns['_dh'])
32
32
33 os.rmdir(tmpd)
33 os.rmdir(tmpd)
@@ -369,7 +369,7 b' class TerminalInteractiveShell(InteractiveShell):'
369
369
370
370
371 for name, cmd in aliases:
371 for name, cmd in aliases:
372 self.alias_manager.define_alias(name, cmd)
372 self.alias_manager.soft_define_alias(name, cmd)
373
373
374 #-------------------------------------------------------------------------
374 #-------------------------------------------------------------------------
375 # Things related to the banner and usage
375 # Things related to the banner and usage
General Comments 0
You need to be logged in to leave comments. Login now