Show More
@@ -20,18 +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.error import UsageError |
|
28 | from IPython.core.error import UsageError | |
31 | from IPython.core.splitinput import split_user_input |
|
|||
32 |
|
29 | |||
33 | from IPython.utils.traitlets import List, Instance |
|
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 | # Utilities |
|
34 | # Utilities | |
@@ -105,19 +102,50 b' class AliasError(Exception):' | |||||
105 | class InvalidAliasError(AliasError): |
|
102 | class InvalidAliasError(AliasError): | |
106 | pass |
|
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 | def __init__(self, shell, name, cmd): |
|
114 | def __init__(self, shell, name, cmd): | |
110 | self.shell = shell |
|
115 | self.shell = shell | |
111 | self.name = name |
|
116 | self.name = name | |
112 | self.cmd = cmd |
|
117 | self.cmd = cmd | |
113 |
self.nargs = |
|
118 | self.nargs = self.validate() | |
114 | if (self.nargs > 0) and (cmd.find('%l') >= 0): |
|
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 | raise InvalidAliasError('The %s and %l specifiers are mutually ' |
|
141 | raise InvalidAliasError('The %s and %l specifiers are mutually ' | |
116 |
'exclusive in alias definitions.') |
|
142 | 'exclusive in alias definitions.') | |
117 |
|
143 | |||
|
144 | return nargs | |||
|
145 | ||||
118 | def __repr__(self): |
|
146 | def __repr__(self): | |
119 | return "<alias {} for {!r}>".format(self.name, self.cmd) |
|
147 | return "<alias {} for {!r}>".format(self.name, self.cmd) | |
120 |
|
148 | |||
121 | def __call__(self, rest=''): |
|
149 | def __call__(self, rest=''): | |
122 | cmd = self.cmd |
|
150 | cmd = self.cmd | |
123 | nargs = self.nargs |
|
151 | nargs = self.nargs | |
@@ -135,7 +163,7 b' class AliasCaller(object):' | |||||
135 | raise UsageError('Alias <%s> requires %s arguments, %s given.' % |
|
163 | raise UsageError('Alias <%s> requires %s arguments, %s given.' % | |
136 | (self.name, nargs, len(args))) |
|
164 | (self.name, nargs, len(args))) | |
137 | cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:])) |
|
165 | cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:])) | |
138 |
|
166 | |||
139 | self.shell.system(cmd) |
|
167 | self.shell.system(cmd) | |
140 |
|
168 | |||
141 | #----------------------------------------------------------------------------- |
|
169 | #----------------------------------------------------------------------------- | |
@@ -150,34 +178,19 b' class AliasManager(Configurable):' | |||||
150 |
|
178 | |||
151 | def __init__(self, shell=None, **kwargs): |
|
179 | def __init__(self, shell=None, **kwargs): | |
152 | super(AliasManager, self).__init__(shell=shell, **kwargs) |
|
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 | self.init_aliases() |
|
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 | def init_aliases(self): |
|
185 | def init_aliases(self): | |
170 | # Load default aliases |
|
186 | # Load default & user aliases | |
171 | for name, cmd in self.default_aliases: |
|
187 | for name, cmd in self.default_aliases + self.user_aliases: | |
172 | self.soft_define_alias(name, cmd) |
|
188 | self.soft_define_alias(name, cmd) | |
173 |
|
189 | |||
174 | # Load user aliases |
|
190 | @property | |
175 | for name, cmd in self.user_aliases: |
|
191 | def aliases(self): | |
176 | self.soft_define_alias(name, cmd) |
|
192 | return [(n, func.cmd) for (n, func) in self.linemagics.items() | |
177 |
|
193 | if isinstance(func, Alias)] | ||
178 | def clear_aliases(self): |
|
|||
179 | for name, cmd in self.aliases: |
|
|||
180 | self.undefine_alias(name) |
|
|||
181 |
|
194 | |||
182 | def soft_define_alias(self, name, cmd): |
|
195 | def soft_define_alias(self, name, cmd): | |
183 | """Define an alias, but don't raise on an AliasError.""" |
|
196 | """Define an alias, but don't raise on an AliasError.""" | |
@@ -192,46 +205,33 b' class AliasManager(Configurable):' | |||||
192 | This will raise an :exc:`AliasError` if there are validation |
|
205 | This will raise an :exc:`AliasError` if there are validation | |
193 | problems. |
|
206 | problems. | |
194 | """ |
|
207 | """ | |
195 | self.validate_alias(name, cmd) |
|
208 | caller = Alias(shell=self.shell, name=name, cmd=cmd) | |
196 | caller = AliasCaller(shell=self.shell, name=name, cmd=cmd) |
|
|||
197 | self.shell.magics_manager.register_function(caller, magic_kind='line', |
|
209 | self.shell.magics_manager.register_function(caller, magic_kind='line', | |
198 | magic_name=name) |
|
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 | def undefine_alias(self, name): |
|
221 | def undefine_alias(self, name): | |
201 | linemagics = self.shell.magics_manager.magics['line'] |
|
222 | if self.is_alias(name): | |
202 |
|
|
223 | del self.linemagics[name] | |
203 | if isinstance(caller, AliasCaller): |
|
|||
204 | del linemagics[name] |
|
|||
205 | else: |
|
224 | else: | |
206 | raise ValueError('%s is not an alias' % name) |
|
225 | raise ValueError('%s is not an alias' % name) | |
207 |
|
226 | |||
208 |
def |
|
227 | def clear_aliases(self): | |
209 | """Validate an alias and return the its number of arguments.""" |
|
228 | for name, cmd in self.aliases: | |
210 |
|
|
229 | self.undefine_alias(name) | |
211 | raise InvalidAliasError("The name %s can't be aliased " |
|
230 | ||
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 |
|
||||
226 | def retrieve_alias(self, name): |
|
231 | def retrieve_alias(self, name): | |
227 | """Retrieve the command to which an alias expands.""" |
|
232 | """Retrieve the command to which an alias expands.""" | |
228 | caller = self.shell.magics_manager.magics['line'].get(name, None) |
|
233 | caller = self.get_alias(name) | |
229 | if isinstance(caller, AliasCaller): |
|
234 | if caller: | |
230 | return caller.cmd |
|
235 | return caller.cmd | |
231 | else: |
|
236 | else: | |
232 | raise ValueError('%s is not an alias' % name) |
|
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 | 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 |
|
29 | from IPython.core.alias import AliasError, Alias | |
30 | from IPython.core.error import UsageError |
|
30 | from IPython.core.error import UsageError | |
31 | from IPython.core.magic import ( |
|
31 | from IPython.core.magic import ( | |
32 | 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 | |
@@ -200,7 +200,7 b' class OSMagics(Magics):' | |||||
200 | else: |
|
200 | else: | |
201 | syscmdlist.append(ff) |
|
201 | syscmdlist.append(ff) | |
202 | else: |
|
202 | else: | |
203 |
no_alias = s |
|
203 | no_alias = Alias.blacklist | |
204 | for pdir in path: |
|
204 | for pdir in path: | |
205 | os.chdir(pdir) |
|
205 | os.chdir(pdir) | |
206 | for ff in os.listdir(pdir): |
|
206 | for ff in os.listdir(pdir): |
@@ -210,7 +210,6 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 | name = args[0] |
|
213 | name = args[0] | |
215 | try: |
|
214 | try: | |
216 | cmd = ip.alias_manager.retrieve_alias(name) |
|
215 | cmd = ip.alias_manager.retrieve_alias(name) |
General Comments 0
You need to be logged in to leave comments.
Login now