Show More
@@ -20,18 +20,15 b' Authors:' | |||
|
20 | 20 | # Imports |
|
21 | 21 | #----------------------------------------------------------------------------- |
|
22 | 22 | |
|
23 | import __builtin__ | |
|
24 | import keyword | |
|
25 | 23 | import os |
|
26 | 24 | import re |
|
27 | 25 | import sys |
|
28 | 26 | |
|
29 | 27 | from IPython.config.configurable import Configurable |
|
30 | 28 | from IPython.core.error import UsageError |
|
31 | from IPython.core.splitinput import split_user_input | |
|
32 | 29 | |
|
33 | 30 | from IPython.utils.traitlets import List, Instance |
|
34 |
from IPython.utils.warn import |
|
|
31 | from IPython.utils.warn import error | |
|
35 | 32 | |
|
36 | 33 | #----------------------------------------------------------------------------- |
|
37 | 34 | # Utilities |
@@ -105,19 +102,50 b' class AliasError(Exception):' | |||
|
105 | 102 | class InvalidAliasError(AliasError): |
|
106 | 103 | pass |
|
107 | 104 | |
|
108 |
class Alias |
|
|
105 | class Alias(object): | |
|
106 | """Callable object storing the details of one alias. | |
|
107 | ||
|
108 | Instances are registered as magic functions to allow use of aliases. | |
|
109 | """ | |
|
110 | ||
|
111 | # Prepare blacklist | |
|
112 | blacklist = {'cd','popd','pushd','dhist','alias','unalias'} | |
|
113 | ||
|
109 | 114 | def __init__(self, shell, name, cmd): |
|
110 | 115 | self.shell = shell |
|
111 | 116 | self.name = name |
|
112 | 117 | self.cmd = cmd |
|
113 |
self.nargs = |
|
|
114 | if (self.nargs > 0) and (cmd.find('%l') >= 0): | |
|
118 | self.nargs = self.validate() | |
|
119 | ||
|
120 | def validate(self): | |
|
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) | |
|
125 | try: | |
|
126 | caller = self.shell.magics_manager.magics['line'][self.name] | |
|
127 | except KeyError: | |
|
128 | pass | |
|
129 | else: | |
|
130 | if not isinstance(caller, Alias): | |
|
131 | raise InvalidAliasError("The name %s can't be aliased " | |
|
132 | "because it is another magic command." % self.name) | |
|
133 | ||
|
134 | if not (isinstance(self.cmd, basestring)): | |
|
135 | raise InvalidAliasError("An alias command must be a string, " | |
|
136 | "got: %r" % self.cmd) | |
|
137 | ||
|
138 | nargs = self.cmd.count('%s') | |
|
139 | ||
|
140 | if (nargs > 0) and (self.cmd.find('%l') >= 0): | |
|
115 | 141 | raise InvalidAliasError('The %s and %l specifiers are mutually ' |
|
116 |
'exclusive in alias definitions.') |
|
|
117 | ||
|
142 | 'exclusive in alias definitions.') | |
|
143 | ||
|
144 | return nargs | |
|
145 | ||
|
118 | 146 | def __repr__(self): |
|
119 | 147 | return "<alias {} for {!r}>".format(self.name, self.cmd) |
|
120 | ||
|
148 | ||
|
121 | 149 | def __call__(self, rest=''): |
|
122 | 150 | cmd = self.cmd |
|
123 | 151 | nargs = self.nargs |
@@ -135,7 +163,7 b' class AliasCaller(object):' | |||
|
135 | 163 | raise UsageError('Alias <%s> requires %s arguments, %s given.' % |
|
136 | 164 | (self.name, nargs, len(args))) |
|
137 | 165 | cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:])) |
|
138 | ||
|
166 | ||
|
139 | 167 | self.shell.system(cmd) |
|
140 | 168 | |
|
141 | 169 | #----------------------------------------------------------------------------- |
@@ -150,34 +178,19 b' class AliasManager(Configurable):' | |||
|
150 | 178 | |
|
151 | 179 | def __init__(self, shell=None, **kwargs): |
|
152 | 180 | super(AliasManager, self).__init__(shell=shell, **kwargs) |
|
153 | self.init_exclusions() | |
|
181 | # For convenient access | |
|
182 | self.linemagics = self.shell.magics_manager.magics['line'] | |
|
154 | 183 | self.init_aliases() |
|
155 | 184 | |
|
156 | @property | |
|
157 | def aliases(self): | |
|
158 | linemagics = self.shell.magics_manager.magics['line'] | |
|
159 | return [(n, func.cmd) for (n, func) in linemagics.items() | |
|
160 | if isinstance(func, AliasCaller)] | |
|
161 | ||
|
162 | def init_exclusions(self): | |
|
163 | # set of things NOT to alias (keywords, builtins and some magics) | |
|
164 | no_alias = {'cd','popd','pushd','dhist','alias','unalias'} | |
|
165 | no_alias.update(set(keyword.kwlist)) | |
|
166 | no_alias.update(set(__builtin__.__dict__.keys())) | |
|
167 | self.no_alias = no_alias | |
|
168 | ||
|
169 | 185 | def init_aliases(self): |
|
170 | # Load default aliases | |
|
171 | for name, cmd in self.default_aliases: | |
|
186 | # Load default & user aliases | |
|
187 | for name, cmd in self.default_aliases + self.user_aliases: | |
|
172 | 188 | self.soft_define_alias(name, cmd) |
|
173 | 189 | |
|
174 | # Load user aliases | |
|
175 | for name, cmd in self.user_aliases: | |
|
176 | self.soft_define_alias(name, cmd) | |
|
177 | ||
|
178 | def clear_aliases(self): | |
|
179 | for name, cmd in self.aliases: | |
|
180 | self.undefine_alias(name) | |
|
190 | @property | |
|
191 | def aliases(self): | |
|
192 | return [(n, func.cmd) for (n, func) in self.linemagics.items() | |
|
193 | if isinstance(func, Alias)] | |
|
181 | 194 | |
|
182 | 195 | def soft_define_alias(self, name, cmd): |
|
183 | 196 | """Define an alias, but don't raise on an AliasError.""" |
@@ -192,46 +205,33 b' class AliasManager(Configurable):' | |||
|
192 | 205 | This will raise an :exc:`AliasError` if there are validation |
|
193 | 206 | problems. |
|
194 | 207 | """ |
|
195 | self.validate_alias(name, cmd) | |
|
196 | caller = AliasCaller(shell=self.shell, name=name, cmd=cmd) | |
|
208 | caller = Alias(shell=self.shell, name=name, cmd=cmd) | |
|
197 | 209 | self.shell.magics_manager.register_function(caller, magic_kind='line', |
|
198 | 210 | magic_name=name) |
|
199 | 211 | |
|
212 | def get_alias(self, name): | |
|
213 | """Return an alias, or None if no alias by that name exists.""" | |
|
214 | aname = self.linemagics.get(name, None) | |
|
215 | return aname if isinstance(aname, Alias) else None | |
|
216 | ||
|
217 | def is_alias(self, name): | |
|
218 | """Return whether or not a given name has been defined as an alias""" | |
|
219 | return self.get_alias(name) is not None | |
|
220 | ||
|
200 | 221 | def undefine_alias(self, name): |
|
201 | linemagics = self.shell.magics_manager.magics['line'] | |
|
202 |
|
|
|
203 | if isinstance(caller, AliasCaller): | |
|
204 | del linemagics[name] | |
|
222 | if self.is_alias(name): | |
|
223 | del self.linemagics[name] | |
|
205 | 224 | else: |
|
206 | 225 | raise ValueError('%s is not an alias' % name) |
|
207 | 226 | |
|
208 |
def |
|
|
209 | """Validate an alias and return the its number of arguments.""" | |
|
210 |
|
|
|
211 | raise InvalidAliasError("The name %s can't be aliased " | |
|
212 | "because it is a keyword or builtin." % name) | |
|
213 | try: | |
|
214 | caller = self.shell.magics_manager.magics['line'][name] | |
|
215 | except KeyError: | |
|
216 | pass | |
|
217 | else: | |
|
218 | if not isinstance(caller, AliasCaller): | |
|
219 | raise InvalidAliasError("The name %s can't be aliased " | |
|
220 | "because it is another magic command." % name) | |
|
221 | if not (isinstance(cmd, basestring)): | |
|
222 | raise InvalidAliasError("An alias command must be a string, " | |
|
223 | "got: %r" % cmd) | |
|
224 | return True | |
|
225 | ||
|
227 | def clear_aliases(self): | |
|
228 | for name, cmd in self.aliases: | |
|
229 | self.undefine_alias(name) | |
|
230 | ||
|
226 | 231 | def retrieve_alias(self, name): |
|
227 | 232 | """Retrieve the command to which an alias expands.""" |
|
228 | caller = self.shell.magics_manager.magics['line'].get(name, None) | |
|
229 | if isinstance(caller, AliasCaller): | |
|
233 | caller = self.get_alias(name) | |
|
234 | if caller: | |
|
230 | 235 | return caller.cmd |
|
231 | 236 | else: |
|
232 | 237 | raise ValueError('%s is not an alias' % name) |
|
233 | ||
|
234 | def is_alias(self, name): | |
|
235 | """Return whether or not a given name has been defined as an alias""" | |
|
236 | caller = self.shell.magics_manager.magics['line'].get(name, None) | |
|
237 | return isinstance(caller, AliasCaller) |
@@ -26,7 +26,7 b' from pprint import pformat' | |||
|
26 | 26 | from IPython.core import magic_arguments |
|
27 | 27 | from IPython.core import oinspect |
|
28 | 28 | from IPython.core import page |
|
29 | from IPython.core.alias import AliasError | |
|
29 | from IPython.core.alias import AliasError, Alias | |
|
30 | 30 | from IPython.core.error import UsageError |
|
31 | 31 | from IPython.core.magic import ( |
|
32 | 32 | Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic |
@@ -200,7 +200,7 b' class OSMagics(Magics):' | |||
|
200 | 200 | else: |
|
201 | 201 | syscmdlist.append(ff) |
|
202 | 202 | else: |
|
203 |
no_alias = s |
|
|
203 | no_alias = Alias.blacklist | |
|
204 | 204 | for pdir in path: |
|
205 | 205 | os.chdir(pdir) |
|
206 | 206 | for ff in os.listdir(pdir): |
@@ -210,7 +210,6 b' class StoreMagics(Magics, Configurable):' | |||
|
210 | 210 | obj = ip.user_ns[args[0]] |
|
211 | 211 | except KeyError: |
|
212 | 212 | # it might be an alias |
|
213 | # This needs to be refactored to use the new AliasManager stuff. | |
|
214 | 213 | name = args[0] |
|
215 | 214 | try: |
|
216 | 215 | cmd = ip.alias_manager.retrieve_alias(name) |
General Comments 0
You need to be logged in to leave comments.
Login now