Show More
@@ -1,81 +1,66 b'' | |||||
1 | #----------------------------------------------------------------------------- |
|
1 | #----------------------------------------------------------------------------- | |
2 | # IPython Shell Configuration Defaults |
|
2 | # Global options | |
3 | #----------------------------------------------------------------------------- |
|
3 | #----------------------------------------------------------------------------- | |
4 |
|
4 | |||
|
5 | Global.classic = False | |||
|
6 | Global.nosep = False | |||
|
7 | ||||
5 | #----------------------------------------------------------------------------- |
|
8 | #----------------------------------------------------------------------------- | |
6 | # Startup |
|
9 | # InteractiveShell options | |
7 | #----------------------------------------------------------------------------- |
|
10 | #----------------------------------------------------------------------------- | |
8 |
|
11 | |||
9 | AUTOCALL = True |
|
|||
10 |
|
||||
11 | AUTOEDIT_SYNTAX = False |
|
|||
12 |
|
||||
13 | AUTOINDENT = True |
|
|||
14 |
|
||||
15 | AUTOMAGIC = True |
|
|||
16 |
|
||||
17 | CACHE_SIZE = 1000 |
|
|||
18 |
|
12 | |||
19 | CLASSIC = False |
|
13 | InteractiveShell.autocall = 1 | |
20 |
|
14 | |||
21 | COLORS = 'Linux' |
|
15 | InteractiveShell.autoedit_syntax = False | |
22 |
|
16 | |||
23 | COLOR_INFO = True |
|
17 | InteractiveShell.autoindent = True | |
24 |
|
18 | |||
25 | CONFIRM_EXIT = True |
|
19 | InteractiveShell.automagic = False | |
26 |
|
20 | |||
27 | DEEP_RELOAD = False |
|
21 | InteractiveShell.banner1 = 'This if for overriding the default IPython banner' | |
28 |
|
22 | |||
29 | EDITOR = 0 |
|
23 | InteractiveShell.banner2 = "This is for extra banner text" | |
30 |
|
24 | |||
31 | LOG = True |
|
25 | InteractiveShell.cache_size = 1000 | |
32 |
|
26 | |||
33 | LOGFILE = '' |
|
27 | InteractiveShell.colors = 'LightBG' | |
34 |
|
28 | |||
35 | BANNER = True |
|
29 | InteractiveShell.color_info = True | |
36 |
|
30 | |||
37 | MESSAGES = True |
|
31 | InteractiveShell.confirm_exit = True | |
38 |
|
32 | |||
39 | PDB = False |
|
33 | InteractiveShell.deep_reload = False | |
40 |
|
34 | |||
41 | PPRINT = True |
|
35 | InteractiveShell.display_banner = True | |
42 |
|
36 | |||
43 | PROMPT_IN1 = 'In [\#]: ' |
|
37 | InteractiveShell.editor = 'nano' | |
44 |
|
38 | |||
45 | PROMPT_IN2 = ' .\D.: ' |
|
39 | InteractiveShell.logstart = True | |
46 |
|
40 | |||
47 | PROMPT_OUT = 'Out[\#]: ' |
|
41 | InteractiveShell.logfile = 'ipython_log.py' | |
48 |
|
42 | |||
49 | PROMPTS_PAD_LEFT = True |
|
43 | InteractiveShell.logplay = 'mylog.py' | |
50 |
|
44 | |||
51 | QUICK = False |
|
45 | InteractiveShell.object_info_string_level = 0 | |
52 |
|
46 | |||
53 | SCREEN_LENGTH = 0 |
|
47 | InteractiveShell.pager = 'less' | |
54 |
|
48 | |||
55 | SEPARATE_IN = '\n' |
|
49 | InteractiveShell.pdb = False | |
56 | SEPARATE_OUT = '' |
|
|||
57 | SEPARATE_OUT2 = '' |
|
|||
58 | NOSEP = False |
|
|||
59 |
|
50 | |||
60 | WILDCARDS_CASE_SENSITIVE = True |
|
51 | InteractiveShell.pprint = True | |
61 |
|
52 | |||
62 | OBJECT_INFO_STRING_LEVEL = 0 |
|
53 | InteractiveShell.prompt_in1 = 'In [\#]: ' | |
|
54 | InteractiveShell.prompt_in2 = ' .\D.: ' | |||
|
55 | InteractiveShell.prompt_out = 'Out[\#]: ' | |||
|
56 | InteractiveShell.prompts_pad_left = True | |||
63 |
|
57 | |||
64 | XMODE = 'Context' |
|
58 | InteractiveShell.quiet = False | |
65 |
|
59 | |||
66 | MULTI_LINE_SPECIALS = True |
|
|||
67 |
|
||||
68 | SYSTEM_HEADER = "IPython system call: " |
|
|||
69 |
|
||||
70 | SYSTEM_VERBOSE = True |
|
|||
71 |
|
||||
72 | #----------------------------------------------------------------------------- |
|
|||
73 | # Readline |
|
60 | # Readline | |
74 | #----------------------------------------------------------------------------- |
|
61 | InteractiveShell.readline_use = False | |
75 |
|
||||
76 | READLINE = True |
|
|||
77 |
|
62 | |||
78 | READLINE_PARSE_AND_BIND = [ |
|
63 | InteractiveShell.readline_parse_and_bind = [ | |
79 | 'tab: complete', |
|
64 | 'tab: complete', | |
80 | '"\C-l": possible-completions', |
|
65 | '"\C-l": possible-completions', | |
81 | 'set show-all-if-ambiguous on', |
|
66 | 'set show-all-if-ambiguous on', | |
@@ -92,29 +77,39 b' READLINE_PARSE_AND_BIND = [' | |||||
92 | '"\C-k": kill-line', |
|
77 | '"\C-k": kill-line', | |
93 | '"\C-u": unix-line-discard', |
|
78 | '"\C-u": unix-line-discard', | |
94 | ] |
|
79 | ] | |
|
80 | InteractiveShell.readline_remove_delims = '-/~' | |||
|
81 | InteractiveShell.readline_merge_completions = True | |||
|
82 | InteractiveShell.readline_omit_names = 0 | |||
|
83 | ||||
|
84 | InteractiveShell.screen_length = 0 | |||
|
85 | ||||
|
86 | InteractiveShell.separate_in = '\n' | |||
|
87 | InteractiveShell.separate_out = '' | |||
|
88 | InteractiveShell.separate_out2 = '' | |||
|
89 | ||||
|
90 | InteractiveShell.system_header = "IPython system call: " | |||
95 |
|
91 | |||
96 | READLINE_REMOVE_DELIMS = '-/~' |
|
92 | InteractiveShell.system_verbose = True | |
97 |
|
93 | |||
98 | READLINE_MERGE_COMPLETIONS = True |
|
94 | InteractiveShell.term_title = False | |
99 |
|
95 | |||
100 | READLINE_OMIT_NAMES = 0 |
|
96 | InteractiveShell.wildcards_case_sensitive = True | |
|
97 | ||||
|
98 | InteractiveShell.xmode = 'Context' | |||
101 |
|
99 | |||
102 | #----------------------------------------------------------------------------- |
|
100 | #----------------------------------------------------------------------------- | |
103 | # Code to execute |
|
101 | # PrefilterManager options | |
104 | #----------------------------------------------------------------------------- |
|
102 | #----------------------------------------------------------------------------- | |
105 |
|
103 | |||
106 | EXECUTE = [ |
|
104 | PrefilterManager.multi_line_specials = True | |
107 | 'import numpy as np', |
|
|||
108 | 'import sympy', |
|
|||
109 | 'a = 10' |
|
|||
110 | ] |
|
|||
111 |
|
||||
112 | EXECFILE = [] |
|
|||
113 |
|
105 | |||
114 | #----------------------------------------------------------------------------- |
|
106 | #----------------------------------------------------------------------------- | |
115 | # Alias |
|
107 | # AliasManager options | |
116 | #----------------------------------------------------------------------------- |
|
108 | #----------------------------------------------------------------------------- | |
117 |
|
109 | |||
118 | ALIAS = [ |
|
110 | # Do this to enable all defaults | |
119 | ('myls', 'ls -la') |
|
111 | # AliasManager.default_aliases = [] | |
|
112 | ||||
|
113 | AliasManger.user_aliases = [ | |||
|
114 | ('foo', 'echo Hi') | |||
120 | ] No newline at end of file |
|
115 | ] |
@@ -1,6 +1,10 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # encoding: utf-8 |
|
2 | # encoding: utf-8 | |
3 | """A factory for creating configuration objects. |
|
3 | """A simple configuration system. | |
|
4 | ||||
|
5 | Authors: | |||
|
6 | ||||
|
7 | * Brian Granger | |||
4 | """ |
|
8 | """ | |
5 |
|
9 | |||
6 | #----------------------------------------------------------------------------- |
|
10 | #----------------------------------------------------------------------------- | |
@@ -14,22 +18,138 b'' | |||||
14 | # Imports |
|
18 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
16 |
|
20 | |||
|
21 | import __builtin__ | |||
17 | import os |
|
22 | import os | |
18 | import sys |
|
23 | import sys | |
19 |
|
24 | |||
20 | from IPython.external import argparse |
|
25 | from IPython.external import argparse | |
21 | from IPython.utils.ipstruct import Struct |
|
|||
22 | from IPython.utils.genutils import filefind |
|
26 | from IPython.utils.genutils import filefind | |
23 |
|
27 | |||
24 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- | |
25 | # Code |
|
29 | # Exceptions | |
26 | #----------------------------------------------------------------------------- |
|
30 | #----------------------------------------------------------------------------- | |
27 |
|
31 | |||
28 |
|
32 | |||
29 |
class Config |
|
33 | class ConfigError(Exception): | |
|
34 | pass | |||
|
35 | ||||
|
36 | ||||
|
37 | class ConfigLoaderError(ConfigError): | |||
30 | pass |
|
38 | pass | |
31 |
|
39 | |||
32 |
|
40 | |||
|
41 | #----------------------------------------------------------------------------- | |||
|
42 | # Config class for holding config information | |||
|
43 | #----------------------------------------------------------------------------- | |||
|
44 | ||||
|
45 | ||||
|
46 | class Config(dict): | |||
|
47 | """An attribute based dict that can do smart merges.""" | |||
|
48 | ||||
|
49 | def __init__(self, *args, **kwds): | |||
|
50 | dict.__init__(self, *args, **kwds) | |||
|
51 | # This sets self.__dict__ = self, but it has to be done this way | |||
|
52 | # because we are also overriding __setattr__. | |||
|
53 | dict.__setattr__(self, '__dict__', self) | |||
|
54 | ||||
|
55 | def _merge(self, other): | |||
|
56 | to_update = {} | |||
|
57 | for k, v in other.items(): | |||
|
58 | if not self.has_key(k): | |||
|
59 | to_update[k] = v | |||
|
60 | else: # I have this key | |||
|
61 | if isinstance(v, Config): | |||
|
62 | # Recursively merge common sub Configs | |||
|
63 | self[k]._merge(v) | |||
|
64 | else: | |||
|
65 | # Plain updates for non-Configs | |||
|
66 | to_update[k] = v | |||
|
67 | ||||
|
68 | self.update(to_update) | |||
|
69 | ||||
|
70 | def _is_section_key(self, key): | |||
|
71 | if key[0].upper()==key[0] and not key.startswith('_'): | |||
|
72 | return True | |||
|
73 | else: | |||
|
74 | return False | |||
|
75 | ||||
|
76 | def has_key(self, key): | |||
|
77 | if self._is_section_key(key): | |||
|
78 | return True | |||
|
79 | else: | |||
|
80 | return dict.has_key(self, key) | |||
|
81 | ||||
|
82 | def _has_section(self, key): | |||
|
83 | if self._is_section_key(key): | |||
|
84 | if dict.has_key(self, key): | |||
|
85 | return True | |||
|
86 | return False | |||
|
87 | ||||
|
88 | def copy(self): | |||
|
89 | return type(self)(dict.copy(self)) | |||
|
90 | ||||
|
91 | def __copy__(self): | |||
|
92 | return self.copy() | |||
|
93 | ||||
|
94 | def __deepcopy__(self, memo): | |||
|
95 | import copy | |||
|
96 | return type(self)(copy.deepcopy(self.items())) | |||
|
97 | ||||
|
98 | def __getitem__(self, key): | |||
|
99 | # Because we use this for an exec namespace, we need to delegate | |||
|
100 | # the lookup of names in __builtin__ to itself. This means | |||
|
101 | # that you can't have section or attribute names that are | |||
|
102 | # builtins. | |||
|
103 | try: | |||
|
104 | return getattr(__builtin__, key) | |||
|
105 | except AttributeError: | |||
|
106 | pass | |||
|
107 | if self._is_section_key(key): | |||
|
108 | try: | |||
|
109 | return dict.__getitem__(self, key) | |||
|
110 | except KeyError: | |||
|
111 | c = Config() | |||
|
112 | dict.__setitem__(self, key, c) | |||
|
113 | return c | |||
|
114 | else: | |||
|
115 | return dict.__getitem__(self, key) | |||
|
116 | ||||
|
117 | def __setitem__(self, key, value): | |||
|
118 | # Don't allow names in __builtin__ to be modified. | |||
|
119 | if hasattr(__builtin__, key): | |||
|
120 | raise ConfigError('Config variable names cannot have the same name ' | |||
|
121 | 'as a Python builtin: %s' % key) | |||
|
122 | if self._is_section_key(key): | |||
|
123 | if not isinstance(value, Config): | |||
|
124 | raise ValueError('values whose keys begin with an uppercase ' | |||
|
125 | 'char must be Config instances: %r, %r' % (key, value)) | |||
|
126 | else: | |||
|
127 | dict.__setitem__(self, key, value) | |||
|
128 | ||||
|
129 | def __getattr__(self, key): | |||
|
130 | try: | |||
|
131 | return self.__getitem__(key) | |||
|
132 | except KeyError, e: | |||
|
133 | raise AttributeError(e) | |||
|
134 | ||||
|
135 | def __setattr__(self, key, value): | |||
|
136 | try: | |||
|
137 | self.__setitem__(key, value) | |||
|
138 | except KeyError, e: | |||
|
139 | raise AttributeError(e) | |||
|
140 | ||||
|
141 | def __delattr__(self, key): | |||
|
142 | try: | |||
|
143 | dict.__delitem__(self, key) | |||
|
144 | except KeyError, e: | |||
|
145 | raise AttributeError(e) | |||
|
146 | ||||
|
147 | ||||
|
148 | #----------------------------------------------------------------------------- | |||
|
149 | # Config loading classes | |||
|
150 | #----------------------------------------------------------------------------- | |||
|
151 | ||||
|
152 | ||||
33 | class ConfigLoader(object): |
|
153 | class ConfigLoader(object): | |
34 | """A object for loading configurations from just about anywhere. |
|
154 | """A object for loading configurations from just about anywhere. | |
35 |
|
155 | |||
@@ -59,7 +179,7 b' class ConfigLoader(object):' | |||||
59 | self.clear() |
|
179 | self.clear() | |
60 |
|
180 | |||
61 | def clear(self): |
|
181 | def clear(self): | |
62 |
self.config = |
|
182 | self.config = Config() | |
63 |
|
183 | |||
64 | def load_config(self): |
|
184 | def load_config(self): | |
65 | """Load a config from somewhere, return a Struct. |
|
185 | """Load a config from somewhere, return a Struct. | |
@@ -106,7 +226,7 b' class PyFileConfigLoader(FileConfigLoader):' | |||||
106 | """Load the config from a file and return it as a Struct.""" |
|
226 | """Load the config from a file and return it as a Struct.""" | |
107 | self._find_file() |
|
227 | self._find_file() | |
108 | self._read_file_as_dict() |
|
228 | self._read_file_as_dict() | |
109 |
self._convert_to_ |
|
229 | self._convert_to_config() | |
110 | return self.config |
|
230 | return self.config | |
111 |
|
231 | |||
112 | def _find_file(self): |
|
232 | def _find_file(self): | |
@@ -114,15 +234,12 b' class PyFileConfigLoader(FileConfigLoader):' | |||||
114 | self.full_filename = filefind(self.filename, self.path) |
|
234 | self.full_filename = filefind(self.filename, self.path) | |
115 |
|
235 | |||
116 | def _read_file_as_dict(self): |
|
236 | def _read_file_as_dict(self): | |
117 | self.data = {} |
|
237 | execfile(self.full_filename, self.config) | |
118 | execfile(self.full_filename, self.data) |
|
|||
119 |
|
238 | |||
120 |
def _convert_to_ |
|
239 | def _convert_to_config(self): | |
121 | if self.data is None: |
|
240 | if self.data is None: | |
122 | ConfigLoaderError('self.data does not exist') |
|
241 | ConfigLoaderError('self.data does not exist') | |
123 | for k, v in self.data.iteritems(): |
|
242 | del self.config['__builtins__'] | |
124 | if k == k.upper(): |
|
|||
125 | self.config[k] = v |
|
|||
126 |
|
243 | |||
127 |
|
244 | |||
128 | class CommandLineConfigLoader(ConfigLoader): |
|
245 | class CommandLineConfigLoader(ConfigLoader): | |
@@ -133,8 +250,8 b' class CommandLineConfigLoader(ConfigLoader):' | |||||
133 | """ |
|
250 | """ | |
134 |
|
251 | |||
135 |
|
252 | |||
136 | class NoDefault(object): pass |
|
253 | class NoConfigDefault(object): pass | |
137 | NoDefault = NoDefault() |
|
254 | NoConfigDefault = NoConfigDefault() | |
138 |
|
255 | |||
139 | class ArgParseConfigLoader(CommandLineConfigLoader): |
|
256 | class ArgParseConfigLoader(CommandLineConfigLoader): | |
140 |
|
257 | |||
@@ -155,7 +272,7 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||||
155 | """Parse command line arguments and return as a Struct.""" |
|
272 | """Parse command line arguments and return as a Struct.""" | |
156 | self._create_parser() |
|
273 | self._create_parser() | |
157 | self._parse_args(args) |
|
274 | self._parse_args(args) | |
158 |
self._convert_to_ |
|
275 | self._convert_to_config() | |
159 | return self.config |
|
276 | return self.config | |
160 |
|
277 | |||
161 | def _create_parser(self): |
|
278 | def _create_parser(self): | |
@@ -169,7 +286,7 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||||
169 | def _add_arguments(self): |
|
286 | def _add_arguments(self): | |
170 | for argument in self.arguments: |
|
287 | for argument in self.arguments: | |
171 | if not argument[1].has_key('default'): |
|
288 | if not argument[1].has_key('default'): | |
172 | argument[1]['default'] = NoDefault |
|
289 | argument[1]['default'] = NoConfigDefault | |
173 | self.parser.add_argument(*argument[0],**argument[1]) |
|
290 | self.parser.add_argument(*argument[0],**argument[1]) | |
174 |
|
291 | |||
175 | def _parse_args(self, args=None): |
|
292 | def _parse_args(self, args=None): | |
@@ -179,25 +296,10 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||||
179 | else: |
|
296 | else: | |
180 | self.parsed_data = self.parser.parse_args(args) |
|
297 | self.parsed_data = self.parser.parse_args(args) | |
181 |
|
298 | |||
182 |
def _convert_to_ |
|
299 | def _convert_to_config(self): | |
183 | """self.parsed_data->self.config""" |
|
300 | """self.parsed_data->self.config""" | |
184 | self.config = Struct() |
|
|||
185 | for k, v in vars(self.parsed_data).items(): |
|
301 | for k, v in vars(self.parsed_data).items(): | |
186 | if v is not NoDefault: |
|
302 | if v is not NoConfigDefault: | |
187 |
|
|
303 | exec_str = 'self.config.' + k + '= v' | |
188 |
|
304 | exec exec_str in locals(), globals() | ||
189 | class IPythonArgParseConfigLoader(ArgParseConfigLoader): |
|
|||
190 |
|
305 | |||
191 | def _add_other_arguments(self): |
|
|||
192 | self.parser.add_argument('-ipythondir',dest='IPYTHONDIR',type=str, |
|
|||
193 | help='Set to override default location of IPYTHONDIR.', |
|
|||
194 | default=NoDefault) |
|
|||
195 | self.parser.add_argument('-p','-profile',dest='PROFILE',type=str, |
|
|||
196 | help='The string name of the ipython profile to be used.', |
|
|||
197 | default=NoDefault) |
|
|||
198 | self.parser.add_argument('-debug',dest="DEBUG",action='store_true', |
|
|||
199 | help='Debug the application startup process.', |
|
|||
200 | default=NoDefault) |
|
|||
201 | self.parser.add_argument('-config_file',dest='CONFIG_FILE',type=str, |
|
|||
202 | help='Set the config file name to override default.', |
|
|||
203 | default=NoDefault) |
|
@@ -24,7 +24,12 b' import os' | |||||
24 | from tempfile import mkstemp |
|
24 | from tempfile import mkstemp | |
25 | from unittest import TestCase |
|
25 | from unittest import TestCase | |
26 |
|
26 | |||
27 |
from IPython.config.loader import |
|
27 | from IPython.config.loader import ( | |
|
28 | Config, | |||
|
29 | PyFileConfigLoader, | |||
|
30 | ArgParseConfigLoader, | |||
|
31 | ConfigError | |||
|
32 | ) | |||
28 |
|
33 | |||
29 | #----------------------------------------------------------------------------- |
|
34 | #----------------------------------------------------------------------------- | |
30 | # Actual tests |
|
35 | # Actual tests | |
@@ -32,10 +37,11 b' from IPython.config.loader import PyFileConfigLoader, ArgParseConfigLoader' | |||||
32 |
|
37 | |||
33 |
|
38 | |||
34 | pyfile = """ |
|
39 | pyfile = """ | |
35 |
|
|
40 | a = 10 | |
36 | B = range(10) |
|
41 | b = 20 | |
37 | C = True |
|
42 | Foo.Bar.value = 10 | |
38 | D = 'hi there' |
|
43 | Foo.Bam.value = range(10) | |
|
44 | D.C.value = 'hi there' | |||
39 | """ |
|
45 | """ | |
40 |
|
46 | |||
41 | class TestPyFileCL(TestCase): |
|
47 | class TestPyFileCL(TestCase): | |
@@ -48,10 +54,11 b' class TestPyFileCL(TestCase):' | |||||
48 | # Unlink the file |
|
54 | # Unlink the file | |
49 | cl = PyFileConfigLoader(fname) |
|
55 | cl = PyFileConfigLoader(fname) | |
50 | config = cl.load_config() |
|
56 | config = cl.load_config() | |
51 |
self.assertEquals(config. |
|
57 | self.assertEquals(config.a, 10) | |
52 |
self.assertEquals(config. |
|
58 | self.assertEquals(config.b, 20) | |
53 |
self.assertEquals(config. |
|
59 | self.assertEquals(config.Foo.Bar.value, 10) | |
54 |
self.assertEquals(config. |
|
60 | self.assertEquals(config.Foo.Bam.value, range(10)) | |
|
61 | self.assertEquals(config.D.C.value, 'hi there') | |||
55 |
|
62 | |||
56 |
|
63 | |||
57 | class TestArgParseCL(TestCase): |
|
64 | class TestArgParseCL(TestCase): | |
@@ -60,18 +67,18 b' class TestArgParseCL(TestCase):' | |||||
60 |
|
67 | |||
61 | class MyLoader(ArgParseConfigLoader): |
|
68 | class MyLoader(ArgParseConfigLoader): | |
62 | arguments = ( |
|
69 | arguments = ( | |
63 |
(('-f','--foo'), dict(dest=' |
|
70 | (('-f','--foo'), dict(dest='Global.foo', type=str)), | |
64 |
(('-b',), dict(dest=' |
|
71 | (('-b',), dict(dest='MyClass.bar', type=int)), | |
65 |
(('-n',), dict(dest=' |
|
72 | (('-n',), dict(dest='n', action='store_true')), | |
66 |
((' |
|
73 | (('Global.bam',), dict(type=str)) | |
67 | ) |
|
74 | ) | |
68 |
|
75 | |||
69 | cl = MyLoader() |
|
76 | cl = MyLoader() | |
70 | config = cl.load_config('-f hi -b 10 -n wow'.split()) |
|
77 | config = cl.load_config('-f hi -b 10 -n wow'.split()) | |
71 |
self.assertEquals(config. |
|
78 | self.assertEquals(config.Global.foo, 'hi') | |
72 |
self.assertEquals(config. |
|
79 | self.assertEquals(config.MyClass.bar, 10) | |
73 |
self.assertEquals(config. |
|
80 | self.assertEquals(config.n, True) | |
74 |
self.assertEquals(config. |
|
81 | self.assertEquals(config.Global.bam, 'wow') | |
75 |
|
82 | |||
76 | def test_add_arguments(self): |
|
83 | def test_add_arguments(self): | |
77 |
|
84 | |||
@@ -79,7 +86,7 b' class TestArgParseCL(TestCase):' | |||||
79 | def _add_arguments(self): |
|
86 | def _add_arguments(self): | |
80 | subparsers = self.parser.add_subparsers(dest='subparser_name') |
|
87 | subparsers = self.parser.add_subparsers(dest='subparser_name') | |
81 | subparser1 = subparsers.add_parser('1') |
|
88 | subparser1 = subparsers.add_parser('1') | |
82 | subparser1.add_argument('-x') |
|
89 | subparser1.add_argument('-x',dest='Global.x') | |
83 | subparser2 = subparsers.add_parser('2') |
|
90 | subparser2 = subparsers.add_parser('2') | |
84 | subparser2.add_argument('y') |
|
91 | subparser2.add_argument('y') | |
85 |
|
92 | |||
@@ -89,5 +96,68 b' class TestArgParseCL(TestCase):' | |||||
89 | self.assertEquals(config.y, 'frobble') |
|
96 | self.assertEquals(config.y, 'frobble') | |
90 | config = cl.load_config('1 -x frobble'.split()) |
|
97 | config = cl.load_config('1 -x frobble'.split()) | |
91 | self.assertEquals(config.subparser_name, '1') |
|
98 | self.assertEquals(config.subparser_name, '1') | |
92 | self.assertEquals(config.x, 'frobble') |
|
99 | self.assertEquals(config.Global.x, 'frobble') | |
93 |
|
100 | |||
|
101 | class TestConfig(TestCase): | |||
|
102 | ||||
|
103 | def test_setget(self): | |||
|
104 | c = Config() | |||
|
105 | c.a = 10 | |||
|
106 | self.assertEquals(c.a, 10) | |||
|
107 | self.assertEquals(c.has_key('b'), False) | |||
|
108 | ||||
|
109 | def test_auto_section(self): | |||
|
110 | c = Config() | |||
|
111 | self.assertEquals(c.has_key('A'), True) | |||
|
112 | self.assertEquals(c._has_section('A'), False) | |||
|
113 | A = c.A | |||
|
114 | A.foo = 'hi there' | |||
|
115 | self.assertEquals(c._has_section('A'), True) | |||
|
116 | self.assertEquals(c.A.foo, 'hi there') | |||
|
117 | del c.A | |||
|
118 | self.assertEquals(len(c.A.keys()),0) | |||
|
119 | ||||
|
120 | def test_merge_doesnt_exist(self): | |||
|
121 | c1 = Config() | |||
|
122 | c2 = Config() | |||
|
123 | c2.bar = 10 | |||
|
124 | c2.Foo.bar = 10 | |||
|
125 | c1._merge(c2) | |||
|
126 | self.assertEquals(c1.Foo.bar, 10) | |||
|
127 | self.assertEquals(c1.bar, 10) | |||
|
128 | c2.Bar.bar = 10 | |||
|
129 | c1._merge(c2) | |||
|
130 | self.assertEquals(c1.Bar.bar, 10) | |||
|
131 | ||||
|
132 | def test_merge_exists(self): | |||
|
133 | c1 = Config() | |||
|
134 | c2 = Config() | |||
|
135 | c1.Foo.bar = 10 | |||
|
136 | c1.Foo.bam = 30 | |||
|
137 | c2.Foo.bar = 20 | |||
|
138 | c2.Foo.wow = 40 | |||
|
139 | c1._merge(c2) | |||
|
140 | self.assertEquals(c1.Foo.bam, 30) | |||
|
141 | self.assertEquals(c1.Foo.bar, 20) | |||
|
142 | self.assertEquals(c1.Foo.wow, 40) | |||
|
143 | c2.Foo.Bam.bam = 10 | |||
|
144 | c1._merge(c2) | |||
|
145 | self.assertEquals(c1.Foo.Bam.bam, 10) | |||
|
146 | ||||
|
147 | def test_deepcopy(self): | |||
|
148 | c1 = Config() | |||
|
149 | c1.Foo.bar = 10 | |||
|
150 | c1.Foo.bam = 30 | |||
|
151 | c1.a = 'asdf' | |||
|
152 | c1.b = range(10) | |||
|
153 | import copy | |||
|
154 | c2 = copy.deepcopy(c1) | |||
|
155 | self.assertEquals(c1, c2) | |||
|
156 | self.assert_(c1 is not c2) | |||
|
157 | self.assert_(c1.Foo is not c2.Foo) | |||
|
158 | ||||
|
159 | def test_builtin(self): | |||
|
160 | c1 = Config() | |||
|
161 | exec 'foo = True' in c1 | |||
|
162 | self.assertEquals(c1.foo, True) | |||
|
163 | self.assertRaises(ConfigError, setattr, c1, 'ValueError', 10) |
@@ -43,7 +43,7 b' def default_aliases():' | |||||
43 | # Make some aliases automatically |
|
43 | # Make some aliases automatically | |
44 | # Prepare list of shell aliases to auto-define |
|
44 | # Prepare list of shell aliases to auto-define | |
45 | if os.name == 'posix': |
|
45 | if os.name == 'posix': | |
46 |
aut |
|
46 | default_aliases = ('mkdir mkdir', 'rmdir rmdir', | |
47 | 'mv mv -i','rm rm -i','cp cp -i', |
|
47 | 'mv mv -i','rm rm -i','cp cp -i', | |
48 | 'cat cat','less less','clear clear', |
|
48 | 'cat cat','less less','clear clear', | |
49 | # a better ls |
|
49 | # a better ls | |
@@ -75,15 +75,15 b' def default_aliases():' | |||||
75 | # things which are executable |
|
75 | # things which are executable | |
76 | 'lx ls -lF | grep ^-..x', |
|
76 | 'lx ls -lF | grep ^-..x', | |
77 | ) |
|
77 | ) | |
78 |
aut |
|
78 | default_aliases = default_aliases + ls_extra | |
79 | elif os.name in ['nt','dos']: |
|
79 | elif os.name in ['nt','dos']: | |
80 |
aut |
|
80 | default_aliases = ('ls dir /on', | |
81 | 'ddir dir /ad /on', 'ldir dir /ad /on', |
|
81 | 'ddir dir /ad /on', 'ldir dir /ad /on', | |
82 | 'mkdir mkdir','rmdir rmdir','echo echo', |
|
82 | 'mkdir mkdir','rmdir rmdir','echo echo', | |
83 | 'ren ren','cls cls','copy copy') |
|
83 | 'ren ren','cls cls','copy copy') | |
84 | else: |
|
84 | else: | |
85 |
aut |
|
85 | default_aliases = () | |
86 |
return [s.split(None,1) for s in aut |
|
86 | return [s.split(None,1) for s in default_aliases] | |
87 |
|
87 | |||
88 |
|
88 | |||
89 | class AliasError(Exception): |
|
89 | class AliasError(Exception): | |
@@ -101,8 +101,8 b' class InvalidAliasError(AliasError):' | |||||
101 |
|
101 | |||
102 | class AliasManager(Component): |
|
102 | class AliasManager(Component): | |
103 |
|
103 | |||
104 |
aut |
|
104 | default_aliases = List(default_aliases(), config=True) | |
105 |
user_alias = List(default_value=[], config |
|
105 | user_aliases = List(default_value=[], config=True) | |
106 |
|
106 | |||
107 | def __init__(self, parent, config=None): |
|
107 | def __init__(self, parent, config=None): | |
108 | super(AliasManager, self).__init__(parent, config=config) |
|
108 | super(AliasManager, self).__init__(parent, config=config) | |
@@ -137,13 +137,16 b' class AliasManager(Component):' | |||||
137 |
|
137 | |||
138 | def init_aliases(self): |
|
138 | def init_aliases(self): | |
139 | # Load default aliases |
|
139 | # Load default aliases | |
140 |
for name, cmd in self.aut |
|
140 | for name, cmd in self.default_aliases: | |
141 | self.soft_define_alias(name, cmd) |
|
141 | self.soft_define_alias(name, cmd) | |
142 |
|
142 | |||
143 | # Load user aliases |
|
143 | # Load user aliases | |
144 | for name, cmd in self.user_alias: |
|
144 | for name, cmd in self.user_aliases: | |
145 | self.soft_define_alias(name, cmd) |
|
145 | self.soft_define_alias(name, cmd) | |
146 |
|
146 | |||
|
147 | def clear_aliases(self): | |||
|
148 | self.alias_table.clear() | |||
|
149 | ||||
147 | def soft_define_alias(self, name, cmd): |
|
150 | def soft_define_alias(self, name, cmd): | |
148 | """Define an alias, but don't raise on an AliasError.""" |
|
151 | """Define an alias, but don't raise on an AliasError.""" | |
149 | try: |
|
152 | try: | |
@@ -160,6 +163,10 b' class AliasManager(Component):' | |||||
160 | nargs = self.validate_alias(name, cmd) |
|
163 | nargs = self.validate_alias(name, cmd) | |
161 | self.alias_table[name] = (nargs, cmd) |
|
164 | self.alias_table[name] = (nargs, cmd) | |
162 |
|
165 | |||
|
166 | def undefine_alias(self, name): | |||
|
167 | if self.alias_table.has_key(name): | |||
|
168 | del self.alias_table[name] | |||
|
169 | ||||
163 | def validate_alias(self, name, cmd): |
|
170 | def validate_alias(self, name, cmd): | |
164 | """Validate an alias and return the its number of arguments.""" |
|
171 | """Validate an alias and return the its number of arguments.""" | |
165 | if name in self.no_alias: |
|
172 | if name in self.no_alias: |
@@ -26,13 +26,14 b' Notes' | |||||
26 | import os |
|
26 | import os | |
27 | import sys |
|
27 | import sys | |
28 | import traceback |
|
28 | import traceback | |
29 |
|
||||
30 | from copy import deepcopy |
|
29 | from copy import deepcopy | |
31 | from IPython.utils.ipstruct import Struct |
|
30 | ||
32 | from IPython.utils.genutils import get_ipython_dir, filefind |
|
31 | from IPython.utils.genutils import get_ipython_dir, filefind | |
33 | from IPython.config.loader import ( |
|
32 | from IPython.config.loader import ( | |
34 |
|
|
33 | PyFileConfigLoader, | |
35 |
|
|
34 | ArgParseConfigLoader, | |
|
35 | Config, | |||
|
36 | NoConfigDefault | |||
36 | ) |
|
37 | ) | |
37 |
|
38 | |||
38 | #----------------------------------------------------------------------------- |
|
39 | #----------------------------------------------------------------------------- | |
@@ -40,6 +41,27 b' from IPython.config.loader import (' | |||||
40 | #----------------------------------------------------------------------------- |
|
41 | #----------------------------------------------------------------------------- | |
41 |
|
42 | |||
42 |
|
43 | |||
|
44 | class IPythonArgParseConfigLoader(ArgParseConfigLoader): | |||
|
45 | """Default command line options for IPython based applications.""" | |||
|
46 | ||||
|
47 | def _add_other_arguments(self): | |||
|
48 | self.parser.add_argument('-ipythondir',dest='Global.ipythondir',type=str, | |||
|
49 | help='Set to override default location of Global.ipythondir.', | |||
|
50 | default=NoConfigDefault, | |||
|
51 | metavar='Global.ipythondir') | |||
|
52 | self.parser.add_argument('-p','-profile',dest='Global.profile',type=str, | |||
|
53 | help='The string name of the ipython profile to be used.', | |||
|
54 | default=NoConfigDefault, | |||
|
55 | metavar='Global.profile') | |||
|
56 | self.parser.add_argument('-debug',dest="Global.debug",action='store_true', | |||
|
57 | help='Debug the application startup process.', | |||
|
58 | default=NoConfigDefault) | |||
|
59 | self.parser.add_argument('-config_file',dest='Global.config_file',type=str, | |||
|
60 | help='Set the config file name to override default.', | |||
|
61 | default=NoConfigDefault, | |||
|
62 | metavar='Global.config_file') | |||
|
63 | ||||
|
64 | ||||
43 | class ApplicationError(Exception): |
|
65 | class ApplicationError(Exception): | |
44 | pass |
|
66 | pass | |
45 |
|
67 | |||
@@ -79,8 +101,8 b' class Application(object):' | |||||
79 |
|
101 | |||
80 | def create_default_config(self): |
|
102 | def create_default_config(self): | |
81 | """Create defaults that can't be set elsewhere.""" |
|
103 | """Create defaults that can't be set elsewhere.""" | |
82 |
self.default_config = |
|
104 | self.default_config = Config() | |
83 |
self.default_config. |
|
105 | self.default_config.Global.ipythondir = get_ipython_dir() | |
84 |
|
106 | |||
85 | def create_command_line_config(self): |
|
107 | def create_command_line_config(self): | |
86 | """Create and return a command line config loader.""" |
|
108 | """Create and return a command line config loader.""" | |
@@ -99,7 +121,7 b' class Application(object):' | |||||
99 | loader = self.create_command_line_config() |
|
121 | loader = self.create_command_line_config() | |
100 | self.command_line_config = loader.load_config() |
|
122 | self.command_line_config = loader.load_config() | |
101 | try: |
|
123 | try: | |
102 |
self.debug = self.command_line_config. |
|
124 | self.debug = self.command_line_config.Global.debug | |
103 | except AttributeError: |
|
125 | except AttributeError: | |
104 | pass # use class default |
|
126 | pass # use class default | |
105 | self.log("Default config loaded:", self.default_config) |
|
127 | self.log("Default config loaded:", self.default_config) | |
@@ -120,9 +142,9 b' class Application(object):' | |||||
120 | """ |
|
142 | """ | |
121 |
|
143 | |||
122 | try: |
|
144 | try: | |
123 |
self.ipythondir = self.command_line_config. |
|
145 | self.ipythondir = self.command_line_config.Global.ipythondir | |
124 | except AttributeError: |
|
146 | except AttributeError: | |
125 |
self.ipythondir = self.default_config. |
|
147 | self.ipythondir = self.default_config.Global.ipythondir | |
126 | sys.path.append(os.path.abspath(self.ipythondir)) |
|
148 | sys.path.append(os.path.abspath(self.ipythondir)) | |
127 | if not os.path.isdir(self.ipythondir): |
|
149 | if not os.path.isdir(self.ipythondir): | |
128 | os.makedirs(self.ipythondir, mode = 0777) |
|
150 | os.makedirs(self.ipythondir, mode = 0777) | |
@@ -138,12 +160,12 b' class Application(object):' | |||||
138 | """ |
|
160 | """ | |
139 |
|
161 | |||
140 | try: |
|
162 | try: | |
141 |
self.config_file_name = self.command_line_config. |
|
163 | self.config_file_name = self.command_line_config.Global.config_file | |
142 | except AttributeError: |
|
164 | except AttributeError: | |
143 | pass |
|
165 | pass | |
144 |
|
166 | |||
145 | try: |
|
167 | try: | |
146 |
self.profile_name = self.command_line_config. |
|
168 | self.profile_name = self.command_line_config.Global.profile | |
147 | name_parts = self.config_file_name.split('.') |
|
169 | name_parts = self.config_file_name.split('.') | |
148 | name_parts.insert(1, '_' + self.profile_name + '.') |
|
170 | name_parts.insert(1, '_' + self.profile_name + '.') | |
149 | self.config_file_name = ''.join(name_parts) |
|
171 | self.config_file_name = ''.join(name_parts) | |
@@ -166,14 +188,14 b' class Application(object):' | |||||
166 | location. If not successful, an empty config is used. |
|
188 | location. If not successful, an empty config is used. | |
167 | """ |
|
189 | """ | |
168 |
loader = PyFileConfigLoader(self.config_file_name, |
|
190 | loader = PyFileConfigLoader(self.config_file_name, | |
169 | self.config_file_paths) |
|
191 | path=self.config_file_paths) | |
170 | try: |
|
192 | try: | |
171 | self.file_config = loader.load_config() |
|
193 | self.file_config = loader.load_config() | |
172 |
self.file_config. |
|
194 | self.file_config.Global.config_file = loader.full_filename | |
173 | except IOError: |
|
195 | except IOError: | |
174 | self.log("Config file not found, skipping: %s" % \ |
|
196 | self.log("Config file not found, skipping: %s" % \ | |
175 | self.config_file_name) |
|
197 | self.config_file_name) | |
176 |
self.file_config = |
|
198 | self.file_config = Config() | |
177 | else: |
|
199 | else: | |
178 | self.log("Config file loaded: %s" % loader.full_filename, |
|
200 | self.log("Config file loaded: %s" % loader.full_filename, | |
179 | self.file_config) |
|
201 | self.file_config) | |
@@ -184,10 +206,10 b' class Application(object):' | |||||
184 |
|
206 | |||
185 | def merge_configs(self): |
|
207 | def merge_configs(self): | |
186 | """Merge the default, command line and file config objects.""" |
|
208 | """Merge the default, command line and file config objects.""" | |
187 |
config = |
|
209 | config = Config() | |
188 |
config. |
|
210 | config._merge(self.default_config) | |
189 |
config. |
|
211 | config._merge(self.file_config) | |
190 |
config. |
|
212 | config._merge(self.command_line_config) | |
191 | self.master_config = config |
|
213 | self.master_config = config | |
192 | self.log("Master config created:", self.master_config) |
|
214 | self.log("Master config created:", self.master_config) | |
193 |
|
215 | |||
@@ -223,12 +245,13 b' class Application(object):' | |||||
223 | def attempt(self, func, action='abort'): |
|
245 | def attempt(self, func, action='abort'): | |
224 | try: |
|
246 | try: | |
225 | func() |
|
247 | func() | |
|
248 | except SystemExit: | |||
|
249 | self.exit() | |||
226 | except: |
|
250 | except: | |
227 | if action == 'abort': |
|
251 | if action == 'abort': | |
228 | self.print_traceback() |
|
252 | self.print_traceback() | |
229 | self.abort() |
|
253 | self.abort() | |
230 | elif action == 'exit': |
|
254 | elif action == 'exit': | |
231 | self.print_traceback() |
|
|||
232 | self.exit() |
|
255 | self.exit() | |
233 |
|
256 | |||
234 | def print_traceback(self): |
|
257 | def print_traceback(self): |
@@ -40,6 +40,9 b' class BuiltinTrap(Component):' | |||||
40 | def __init__(self, parent): |
|
40 | def __init__(self, parent): | |
41 | super(BuiltinTrap, self).__init__(parent, None, None) |
|
41 | super(BuiltinTrap, self).__init__(parent, None, None) | |
42 | self._orig_builtins = {} |
|
42 | self._orig_builtins = {} | |
|
43 | # We define this to track if a single BuiltinTrap is nested. | |||
|
44 | # Only turn off the trap when the outermost call to __exit__ is made. | |||
|
45 | self._nested_level = 0 | |||
43 |
|
46 | |||
44 | @auto_attr |
|
47 | @auto_attr | |
45 | def shell(self): |
|
48 | def shell(self): | |
@@ -50,12 +53,16 b' class BuiltinTrap(Component):' | |||||
50 | return shell |
|
53 | return shell | |
51 |
|
54 | |||
52 | def __enter__(self): |
|
55 | def __enter__(self): | |
|
56 | if self._nested_level == 0: | |||
53 | self.set() |
|
57 | self.set() | |
|
58 | self._nested_level += 1 | |||
54 | # I return self, so callers can use add_builtin in a with clause. |
|
59 | # I return self, so callers can use add_builtin in a with clause. | |
55 | return self |
|
60 | return self | |
56 |
|
61 | |||
57 | def __exit__(self, type, value, traceback): |
|
62 | def __exit__(self, type, value, traceback): | |
|
63 | if self._nested_level == 1: | |||
58 | self.unset() |
|
64 | self.unset() | |
|
65 | self._nested_level -= 1 | |||
59 | return True |
|
66 | return True | |
60 |
|
67 | |||
61 | def add_builtin(self, key, value): |
|
68 | def add_builtin(self, key, value): |
@@ -25,7 +25,7 b' import datetime' | |||||
25 | from weakref import WeakValueDictionary |
|
25 | from weakref import WeakValueDictionary | |
26 |
|
26 | |||
27 | from IPython.utils.importstring import import_item |
|
27 | from IPython.utils.importstring import import_item | |
28 | from IPython.utils.ipstruct import Struct |
|
28 | from IPython.config.loader import Config | |
29 | from IPython.utils.traitlets import ( |
|
29 | from IPython.utils.traitlets import ( | |
30 | HasTraitlets, TraitletError, MetaHasTraitlets, Instance, This |
|
30 | HasTraitlets, TraitletError, MetaHasTraitlets, Instance, This | |
31 | ) |
|
31 | ) | |
@@ -187,7 +187,7 b' class Component(HasTraitlets):' | |||||
187 | __metaclass__ = MetaComponent |
|
187 | __metaclass__ = MetaComponent | |
188 |
|
188 | |||
189 | # Traitlets are fun! |
|
189 | # Traitlets are fun! | |
190 |
config = Instance( |
|
190 | config = Instance(Config,(),{}) | |
191 | parent = This() |
|
191 | parent = This() | |
192 | root = This() |
|
192 | root = This() | |
193 | created = None |
|
193 | created = None | |
@@ -203,7 +203,7 b' class Component(HasTraitlets):' | |||||
203 | name : str |
|
203 | name : str | |
204 | The unique name of the component. If empty, then a unique |
|
204 | The unique name of the component. If empty, then a unique | |
205 | one will be autogenerated. |
|
205 | one will be autogenerated. | |
206 |
config : |
|
206 | config : Config | |
207 | If this is empty, self.config = parent.config, otherwise |
|
207 | If this is empty, self.config = parent.config, otherwise | |
208 | self.config = config and root.config is ignored. This argument |
|
208 | self.config = config and root.config is ignored. This argument | |
209 | should only be used to *override* the automatic inheritance of |
|
209 | should only be used to *override* the automatic inheritance of | |
@@ -274,11 +274,16 b' class Component(HasTraitlets):' | |||||
274 | In the future, we might want to do a pop here so stale config info |
|
274 | In the future, we might want to do a pop here so stale config info | |
275 | is not passed onto children. |
|
275 | is not passed onto children. | |
276 | """ |
|
276 | """ | |
277 |
# Get all traitlets with a config |
|
277 | # Get all traitlets with a config metadata entry that is True | |
278 |
traitlets = self.traitlets( |
|
278 | traitlets = self.traitlets(config=True) | |
|
279 | ||||
|
280 | # Don't do a blind getattr as that would cause the config to | |||
|
281 | # dynamically create the section with name self.__class__.__name__. | |||
|
282 | if new._has_section(self.__class__.__name__): | |||
|
283 | my_config = new[self.__class__.__name__] | |||
279 | for k, v in traitlets.items(): |
|
284 | for k, v in traitlets.items(): | |
280 | try: |
|
285 | try: | |
281 |
config_value = |
|
286 | config_value = my_config[k] | |
282 | except KeyError: |
|
287 | except KeyError: | |
283 | pass |
|
288 | pass | |
284 | else: |
|
289 | else: |
@@ -40,9 +40,11 b' class DisplayTrap(Component):' | |||||
40 |
|
40 | |||
41 | def __init__(self, parent, hook): |
|
41 | def __init__(self, parent, hook): | |
42 | super(DisplayTrap, self).__init__(parent, None, None) |
|
42 | super(DisplayTrap, self).__init__(parent, None, None) | |
43 |
|
||||
44 | self.hook = hook |
|
43 | self.hook = hook | |
45 | self.old_hook = None |
|
44 | self.old_hook = None | |
|
45 | # We define this to track if a single BuiltinTrap is nested. | |||
|
46 | # Only turn off the trap when the outermost call to __exit__ is made. | |||
|
47 | self._nested_level = 0 | |||
46 |
|
48 | |||
47 | @auto_attr |
|
49 | @auto_attr | |
48 | def shell(self): |
|
50 | def shell(self): | |
@@ -53,11 +55,15 b' class DisplayTrap(Component):' | |||||
53 | return shell |
|
55 | return shell | |
54 |
|
56 | |||
55 | def __enter__(self): |
|
57 | def __enter__(self): | |
|
58 | if self._nested_level == 0: | |||
56 | self.set() |
|
59 | self.set() | |
|
60 | self._nested_level += 1 | |||
57 | return self |
|
61 | return self | |
58 |
|
62 | |||
59 | def __exit__(self, type, value, traceback): |
|
63 | def __exit__(self, type, value, traceback): | |
|
64 | if self._nested_level == 1: | |||
60 | self.unset() |
|
65 | self.unset() | |
|
66 | self._nested_level -= 1 | |||
61 | return True |
|
67 | return True | |
62 |
|
68 | |||
63 | def set(self): |
|
69 | def set(self): |
@@ -30,10 +30,12 b' from contextlib import nested' | |||||
30 |
|
30 | |||
31 | from IPython.core import ultratb |
|
31 | from IPython.core import ultratb | |
32 | from IPython.core.iplib import InteractiveShell |
|
32 | from IPython.core.iplib import InteractiveShell | |
|
33 | from IPython.core.ipapp import load_default_config | |||
33 |
|
34 | |||
34 | from IPython.utils.traitlets import Bool, Str, CBool |
|
35 | from IPython.utils.traitlets import Bool, Str, CBool | |
35 | from IPython.utils.genutils import ask_yes_no |
|
36 | from IPython.utils.genutils import ask_yes_no | |
36 |
|
37 | |||
|
38 | ||||
37 | #----------------------------------------------------------------------------- |
|
39 | #----------------------------------------------------------------------------- | |
38 | # Classes and functions |
|
40 | # Classes and functions | |
39 | #----------------------------------------------------------------------------- |
|
41 | #----------------------------------------------------------------------------- | |
@@ -260,6 +262,8 b" def embed(header='', config=None, usage=None, banner1=None, banner2=None," | |||||
260 | Full customization can be done by passing a :class:`Struct` in as the |
|
262 | Full customization can be done by passing a :class:`Struct` in as the | |
261 | config argument. |
|
263 | config argument. | |
262 | """ |
|
264 | """ | |
|
265 | if config is None: | |||
|
266 | config = load_default_config() | |||
263 | global _embedded_shell |
|
267 | global _embedded_shell | |
264 | if _embedded_shell is None: |
|
268 | if _embedded_shell is None: | |
265 | _embedded_shell = InteractiveShellEmbed(config=config, |
|
269 | _embedded_shell = InteractiveShellEmbed(config=config, |
@@ -27,13 +27,17 b' import os' | |||||
27 | import sys |
|
27 | import sys | |
28 | import warnings |
|
28 | import warnings | |
29 |
|
29 | |||
30 | from IPython.core.application import Application |
|
30 | from IPython.core.application import Application, IPythonArgParseConfigLoader | |
31 | from IPython.core import release |
|
31 | from IPython.core import release | |
32 | from IPython.core.iplib import InteractiveShell |
|
32 | from IPython.core.iplib import InteractiveShell | |
33 |
from IPython.config.loader import |
|
33 | from IPython.config.loader import ( | |
|
34 | NoConfigDefault, | |||
|
35 | Config, | |||
|
36 | PyFileConfigLoader | |||
|
37 | ) | |||
34 |
|
38 | |||
35 | from IPython.utils.ipstruct import Struct |
|
39 | from IPython.utils.ipstruct import Struct | |
36 |
|
40 | from IPython.utils.genutils import get_ipython_dir | ||
37 |
|
41 | |||
38 | #----------------------------------------------------------------------------- |
|
42 | #----------------------------------------------------------------------------- | |
39 | # Utilities and helpers |
|
43 | # Utilities and helpers | |
@@ -62,172 +66,187 b' deprecated. See the %gui magic for information on the new interface.' | |||||
62 |
|
66 | |||
63 | cl_args = ( |
|
67 | cl_args = ( | |
64 | (('-autocall',), dict( |
|
68 | (('-autocall',), dict( | |
65 |
type=int, dest=' |
|
69 | type=int, dest='InteractiveShell.autocall', default=NoConfigDefault, | |
66 |
help='Set the autocall value (0,1,2).' |
|
70 | help='Set the autocall value (0,1,2).', | |
|
71 | metavar='InteractiveShell.autocall') | |||
67 | ), |
|
72 | ), | |
68 | (('-autoindent',), dict( |
|
73 | (('-autoindent',), dict( | |
69 |
action='store_true', dest=' |
|
74 | action='store_true', dest='InteractiveShell.autoindent', default=NoConfigDefault, | |
70 | help='Turn on autoindenting.') |
|
75 | help='Turn on autoindenting.') | |
71 | ), |
|
76 | ), | |
72 | (('-noautoindent',), dict( |
|
77 | (('-noautoindent',), dict( | |
73 |
action='store_false', dest=' |
|
78 | action='store_false', dest='InteractiveShell.autoindent', default=NoConfigDefault, | |
74 | help='Turn off autoindenting.') |
|
79 | help='Turn off autoindenting.') | |
75 | ), |
|
80 | ), | |
76 | (('-automagic',), dict( |
|
81 | (('-automagic',), dict( | |
77 |
action='store_true', dest=' |
|
82 | action='store_true', dest='InteractiveShell.automagic', default=NoConfigDefault, | |
78 | help='Turn on the auto calling of magic commands.') |
|
83 | help='Turn on the auto calling of magic commands.') | |
79 | ), |
|
84 | ), | |
80 | (('-noautomagic',), dict( |
|
85 | (('-noautomagic',), dict( | |
81 |
action='store_false', dest=' |
|
86 | action='store_false', dest='InteractiveShell.automagic', default=NoConfigDefault, | |
82 | help='Turn off the auto calling of magic commands.') |
|
87 | help='Turn off the auto calling of magic commands.') | |
83 | ), |
|
88 | ), | |
84 | (('-autoedit_syntax',), dict( |
|
89 | (('-autoedit_syntax',), dict( | |
85 |
action='store_true', dest=' |
|
90 | action='store_true', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault, | |
86 | help='Turn on auto editing of files with syntax errors.') |
|
91 | help='Turn on auto editing of files with syntax errors.') | |
87 | ), |
|
92 | ), | |
88 | (('-noautoedit_syntax',), dict( |
|
93 | (('-noautoedit_syntax',), dict( | |
89 |
action='store_false', dest=' |
|
94 | action='store_false', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault, | |
90 | help='Turn off auto editing of files with syntax errors.') |
|
95 | help='Turn off auto editing of files with syntax errors.') | |
91 | ), |
|
96 | ), | |
92 | (('-banner',), dict( |
|
97 | (('-banner',), dict( | |
93 |
action='store_true', dest=' |
|
98 | action='store_true', dest='InteractiveShell.display_banner', default=NoConfigDefault, | |
94 | help='Display a banner upon starting IPython.') |
|
99 | help='Display a banner upon starting IPython.') | |
95 | ), |
|
100 | ), | |
96 | (('-nobanner',), dict( |
|
101 | (('-nobanner',), dict( | |
97 |
action='store_false', dest=' |
|
102 | action='store_false', dest='InteractiveShell.display_banner', default=NoConfigDefault, | |
98 | help="Don't display a banner upon starting IPython.") |
|
103 | help="Don't display a banner upon starting IPython.") | |
99 | ), |
|
104 | ), | |
100 | (('-c',), dict( |
|
105 | (('-c',), dict( | |
101 |
type=str, dest=' |
|
106 | type=str, dest='InteractiveShell.c', default=NoConfigDefault, | |
102 |
help="Execute |
|
107 | help="Execute the given command string.", | |
|
108 | metavar='InteractiveShell.c') | |||
103 | ), |
|
109 | ), | |
104 | (('-cache_size',), dict( |
|
110 | (('-cache_size',), dict( | |
105 |
type=int, dest=' |
|
111 | type=int, dest='InteractiveShell.cache_size', default=NoConfigDefault, | |
106 |
help="Set the size of the output cache." |
|
112 | help="Set the size of the output cache.", | |
|
113 | metavar='InteractiveShell.cache_size') | |||
107 | ), |
|
114 | ), | |
108 | (('-classic',), dict( |
|
115 | (('-classic',), dict( | |
109 |
action='store_true', dest=' |
|
116 | action='store_true', dest='Global.classic', default=NoConfigDefault, | |
110 | help="Gives IPython a similar feel to the classic Python prompt.") |
|
117 | help="Gives IPython a similar feel to the classic Python prompt.") | |
111 | ), |
|
118 | ), | |
112 | (('-colors',), dict( |
|
119 | (('-colors',), dict( | |
113 |
type=str, dest=' |
|
120 | type=str, dest='InteractiveShell.colors', default=NoConfigDefault, | |
114 |
help="Set the color scheme (NoColor, Linux, and LightBG)." |
|
121 | help="Set the color scheme (NoColor, Linux, and LightBG).", | |
|
122 | metavar='InteractiveShell.colors') | |||
115 | ), |
|
123 | ), | |
116 | (('-color_info',), dict( |
|
124 | (('-color_info',), dict( | |
117 |
action='store_true', dest=' |
|
125 | action='store_true', dest='InteractiveShell.color_info', default=NoConfigDefault, | |
118 | help="Enable using colors for info related things.") |
|
126 | help="Enable using colors for info related things.") | |
119 | ), |
|
127 | ), | |
120 | (('-nocolor_info',), dict( |
|
128 | (('-nocolor_info',), dict( | |
121 |
action='store_false', dest=' |
|
129 | action='store_false', dest='InteractiveShell.color_info', default=NoConfigDefault, | |
122 | help="Disable using colors for info related things.") |
|
130 | help="Disable using colors for info related things.") | |
123 | ), |
|
131 | ), | |
124 | (('-confirm_exit',), dict( |
|
132 | (('-confirm_exit',), dict( | |
125 |
action='store_true', dest=' |
|
133 | action='store_true', dest='InteractiveShell.confirm_exit', default=NoConfigDefault, | |
126 | help="Prompt the user when existing.") |
|
134 | help="Prompt the user when existing.") | |
127 | ), |
|
135 | ), | |
128 | (('-noconfirm_exit',), dict( |
|
136 | (('-noconfirm_exit',), dict( | |
129 |
action='store_false', dest=' |
|
137 | action='store_false', dest='InteractiveShell.confirm_exit', default=NoConfigDefault, | |
130 | help="Don't prompt the user when existing.") |
|
138 | help="Don't prompt the user when existing.") | |
131 | ), |
|
139 | ), | |
132 | (('-deep_reload',), dict( |
|
140 | (('-deep_reload',), dict( | |
133 |
action='store_true', dest=' |
|
141 | action='store_true', dest='InteractiveShell.deep_reload', default=NoConfigDefault, | |
134 | help="Enable deep (recursive) reloading by default.") |
|
142 | help="Enable deep (recursive) reloading by default.") | |
135 | ), |
|
143 | ), | |
136 | (('-nodeep_reload',), dict( |
|
144 | (('-nodeep_reload',), dict( | |
137 |
action='store_false', dest=' |
|
145 | action='store_false', dest='InteractiveShell.deep_reload', default=NoConfigDefault, | |
138 | help="Disable deep (recursive) reloading by default.") |
|
146 | help="Disable deep (recursive) reloading by default.") | |
139 | ), |
|
147 | ), | |
140 | (('-editor',), dict( |
|
148 | (('-editor',), dict( | |
141 |
type=str, dest=' |
|
149 | type=str, dest='InteractiveShell.editor', default=NoConfigDefault, | |
142 |
help="Set the editor used by IPython (default to $EDITOR/vi/notepad)." |
|
150 | help="Set the editor used by IPython (default to $EDITOR/vi/notepad).", | |
|
151 | metavar='InteractiveShell.editor') | |||
143 | ), |
|
152 | ), | |
144 | (('-log','-l'), dict( |
|
153 | (('-log','-l'), dict( | |
145 |
action='store_true', dest=' |
|
154 | action='store_true', dest='InteractiveShell.logstart', default=NoConfigDefault, | |
146 | help="Start logging to the default file (./ipython_log.py).") |
|
155 | help="Start logging to the default file (./ipython_log.py).") | |
147 | ), |
|
156 | ), | |
148 | (('-logfile','-lf'), dict( |
|
157 | (('-logfile','-lf'), dict( | |
149 |
type=str, dest=' |
|
158 | type=str, dest='InteractiveShell.logfile', default=NoConfigDefault, | |
150 |
help="Specify the name of your logfile." |
|
159 | help="Specify the name of your logfile.", | |
|
160 | metavar='InteractiveShell.logfile') | |||
151 | ), |
|
161 | ), | |
152 | (('-logplay','-lp'), dict( |
|
162 | (('-logplay','-lp'), dict( | |
153 |
type=str, dest=' |
|
163 | type=str, dest='InteractiveShell.logplay', default=NoConfigDefault, | |
154 |
help="Re-play a log file and then append to it." |
|
164 | help="Re-play a log file and then append to it.", | |
|
165 | metavar='InteractiveShell.logplay') | |||
155 | ), |
|
166 | ), | |
156 | (('-pdb',), dict( |
|
167 | (('-pdb',), dict( | |
157 |
action='store_true', dest=' |
|
168 | action='store_true', dest='InteractiveShell.pdb', default=NoConfigDefault, | |
158 | help="Enable auto calling the pdb debugger after every exception.") |
|
169 | help="Enable auto calling the pdb debugger after every exception.") | |
159 | ), |
|
170 | ), | |
160 | (('-nopdb',), dict( |
|
171 | (('-nopdb',), dict( | |
161 |
action='store_false', dest=' |
|
172 | action='store_false', dest='InteractiveShell.pdb', default=NoConfigDefault, | |
162 | help="Disable auto calling the pdb debugger after every exception.") |
|
173 | help="Disable auto calling the pdb debugger after every exception.") | |
163 | ), |
|
174 | ), | |
164 | (('-pprint',), dict( |
|
175 | (('-pprint',), dict( | |
165 |
action='store_true', dest=' |
|
176 | action='store_true', dest='InteractiveShell.pprint', default=NoConfigDefault, | |
166 | help="Enable auto pretty printing of results.") |
|
177 | help="Enable auto pretty printing of results.") | |
167 | ), |
|
178 | ), | |
168 | (('-nopprint',), dict( |
|
179 | (('-nopprint',), dict( | |
169 |
action='store_false', dest=' |
|
180 | action='store_false', dest='InteractiveShell.pprint', default=NoConfigDefault, | |
170 | help="Disable auto auto pretty printing of results.") |
|
181 | help="Disable auto auto pretty printing of results.") | |
171 | ), |
|
182 | ), | |
172 | (('-prompt_in1','-pi1'), dict( |
|
183 | (('-prompt_in1','-pi1'), dict( | |
173 |
type=str, dest=' |
|
184 | type=str, dest='InteractiveShell.prompt_in1', default=NoConfigDefault, | |
174 |
help="Set the main input prompt ('In [\#]: ')" |
|
185 | help="Set the main input prompt ('In [\#]: ')", | |
|
186 | metavar='InteractiveShell.prompt_in1') | |||
175 | ), |
|
187 | ), | |
176 | (('-prompt_in2','-pi2'), dict( |
|
188 | (('-prompt_in2','-pi2'), dict( | |
177 |
type=str, dest=' |
|
189 | type=str, dest='InteractiveShell.prompt_in2', default=NoConfigDefault, | |
178 |
help="Set the secondary input prompt (' .\D.: ')" |
|
190 | help="Set the secondary input prompt (' .\D.: ')", | |
|
191 | metavar='InteractiveShell.prompt_in2') | |||
179 | ), |
|
192 | ), | |
180 | (('-prompt_out','-po'), dict( |
|
193 | (('-prompt_out','-po'), dict( | |
181 |
type=str, dest=' |
|
194 | type=str, dest='InteractiveShell.prompt_out', default=NoConfigDefault, | |
182 |
help="Set the output prompt ('Out[\#]:')" |
|
195 | help="Set the output prompt ('Out[\#]:')", | |
|
196 | metavar='InteractiveShell.prompt_out') | |||
183 | ), |
|
197 | ), | |
184 | (('-quick',), dict( |
|
198 | (('-quick',), dict( | |
185 |
action='store_true', dest=' |
|
199 | action='store_true', dest='Global.quick', default=NoConfigDefault, | |
186 | help="Enable quick startup with no config files.") |
|
200 | help="Enable quick startup with no config files.") | |
187 | ), |
|
201 | ), | |
188 | (('-readline',), dict( |
|
202 | (('-readline',), dict( | |
189 |
action='store_true', dest=' |
|
203 | action='store_true', dest='InteractiveShell.readline_use', default=NoConfigDefault, | |
190 | help="Enable readline for command line usage.") |
|
204 | help="Enable readline for command line usage.") | |
191 | ), |
|
205 | ), | |
192 | (('-noreadline',), dict( |
|
206 | (('-noreadline',), dict( | |
193 |
action='store_false', dest=' |
|
207 | action='store_false', dest='InteractiveShell.readline_use', default=NoConfigDefault, | |
194 | help="Disable readline for command line usage.") |
|
208 | help="Disable readline for command line usage.") | |
195 | ), |
|
209 | ), | |
196 | (('-screen_length','-sl'), dict( |
|
210 | (('-screen_length','-sl'), dict( | |
197 |
type=int, dest=' |
|
211 | type=int, dest='InteractiveShell.screen_length', default=NoConfigDefault, | |
198 |
help='Number of lines on screen, used to control printing of long strings.' |
|
212 | help='Number of lines on screen, used to control printing of long strings.', | |
|
213 | metavar='InteractiveShell.screen_length') | |||
199 | ), |
|
214 | ), | |
200 | (('-separate_in','-si'), dict( |
|
215 | (('-separate_in','-si'), dict( | |
201 |
type=str, dest=' |
|
216 | type=str, dest='InteractiveShell.separate_in', default=NoConfigDefault, | |
202 |
help="Separator before input prompts. Default '\n'." |
|
217 | help="Separator before input prompts. Default '\n'.", | |
|
218 | metavar='InteractiveShell.separate_in') | |||
203 | ), |
|
219 | ), | |
204 | (('-separate_out','-so'), dict( |
|
220 | (('-separate_out','-so'), dict( | |
205 |
type=str, dest=' |
|
221 | type=str, dest='InteractiveShell.separate_out', default=NoConfigDefault, | |
206 |
help="Separator before output prompts. Default 0 (nothing)." |
|
222 | help="Separator before output prompts. Default 0 (nothing).", | |
|
223 | metavar='InteractiveShell.separate_out') | |||
207 | ), |
|
224 | ), | |
208 | (('-separate_out2','-so2'), dict( |
|
225 | (('-separate_out2','-so2'), dict( | |
209 |
type=str, dest=' |
|
226 | type=str, dest='InteractiveShell.separate_out2', default=NoConfigDefault, | |
210 |
help="Separator after output prompts. Default 0 (nonight)." |
|
227 | help="Separator after output prompts. Default 0 (nonight).", | |
|
228 | metavar='InteractiveShell.separate_out2') | |||
211 | ), |
|
229 | ), | |
212 | (('-nosep',), dict( |
|
230 | (('-nosep',), dict( | |
213 |
action='store_true', dest=' |
|
231 | action='store_true', dest='Global.nosep', default=NoConfigDefault, | |
214 | help="Eliminate all spacing between prompts.") |
|
232 | help="Eliminate all spacing between prompts.") | |
215 | ), |
|
233 | ), | |
216 | (('-term_title',), dict( |
|
234 | (('-term_title',), dict( | |
217 |
action='store_true', dest=' |
|
235 | action='store_true', dest='InteractiveShell.term_title', default=NoConfigDefault, | |
218 | help="Enable auto setting the terminal title.") |
|
236 | help="Enable auto setting the terminal title.") | |
219 | ), |
|
237 | ), | |
220 | (('-noterm_title',), dict( |
|
238 | (('-noterm_title',), dict( | |
221 |
action='store_false', dest=' |
|
239 | action='store_false', dest='InteractiveShell.term_title', default=NoConfigDefault, | |
222 | help="Disable auto setting the terminal title.") |
|
240 | help="Disable auto setting the terminal title.") | |
223 | ), |
|
241 | ), | |
224 | (('-xmode',), dict( |
|
242 | (('-xmode',), dict( | |
225 |
type=str, dest=' |
|
243 | type=str, dest='InteractiveShell.xmode', default=NoConfigDefault, | |
226 |
help="Exception mode ('Plain','Context','Verbose')" |
|
244 | help="Exception mode ('Plain','Context','Verbose')", | |
|
245 | metavar='InteractiveShell.xmode') | |||
227 | ), |
|
246 | ), | |
228 | # These are only here to get the proper deprecation warnings |
|
247 | # These are only here to get the proper deprecation warnings | |
229 | (('-pylab','-wthread','-qthread','-q4thread','-gthread'), dict( |
|
248 | (('-pylab','-wthread','-qthread','-q4thread','-gthread'), dict( | |
230 |
action='store_true', dest=' |
|
249 | action='store_true', dest='Global.threaded_shell', default=NoConfigDefault, | |
231 | help="These command line flags are deprecated, see the 'gui' magic.") |
|
250 | help="These command line flags are deprecated, see the 'gui' magic.") | |
232 | ), |
|
251 | ), | |
233 | ) |
|
252 | ) | |
@@ -238,9 +257,11 b' class IPythonAppCLConfigLoader(IPythonArgParseConfigLoader):' | |||||
238 | arguments = cl_args |
|
257 | arguments = cl_args | |
239 |
|
258 | |||
240 |
|
259 | |||
|
260 | _default_config_file_name = 'ipython_config.py' | |||
|
261 | ||||
241 | class IPythonApp(Application): |
|
262 | class IPythonApp(Application): | |
242 | name = 'ipython' |
|
263 | name = 'ipython' | |
243 |
config_file_name = |
|
264 | config_file_name = _default_config_file_name | |
244 |
|
265 | |||
245 | def create_command_line_config(self): |
|
266 | def create_command_line_config(self): | |
246 | """Create and return a command line config loader.""" |
|
267 | """Create and return a command line config loader.""" | |
@@ -252,19 +273,15 b' class IPythonApp(Application):' | |||||
252 | """Do actions after loading cl config.""" |
|
273 | """Do actions after loading cl config.""" | |
253 | clc = self.command_line_config |
|
274 | clc = self.command_line_config | |
254 |
|
275 | |||
255 | # This needs to be set here, the rest are set in pre_construct. |
|
|||
256 | if hasattr(clc, 'CLASSIC'): |
|
|||
257 | if clc.CLASSIC: clc.QUICK = 1 |
|
|||
258 |
|
||||
259 | # Display the deprecation warnings about threaded shells |
|
276 | # Display the deprecation warnings about threaded shells | |
260 |
if hasattr(clc, ' |
|
277 | if hasattr(clc.Global, 'threaded_shell'): | |
261 | threaded_shell_warning() |
|
278 | threaded_shell_warning() | |
262 | del clc['THREADED_SHELL'] |
|
279 | del clc.Global['threaded_shell'] | |
263 |
|
280 | |||
264 | def load_file_config(self): |
|
281 | def load_file_config(self): | |
265 |
if hasattr(self.command_line_config, ' |
|
282 | if hasattr(self.command_line_config.Global, 'quick'): | |
266 |
if self.command_line_config. |
|
283 | if self.command_line_config.Global.quick: | |
267 |
self.file_config = |
|
284 | self.file_config = Config() | |
268 | return |
|
285 | return | |
269 | super(IPythonApp, self).load_file_config() |
|
286 | super(IPythonApp, self).load_file_config() | |
270 |
|
287 | |||
@@ -274,25 +291,28 b' class IPythonApp(Application):' | |||||
274 | def pre_construct(self): |
|
291 | def pre_construct(self): | |
275 | config = self.master_config |
|
292 | config = self.master_config | |
276 |
|
293 | |||
277 |
if hasattr(config, ' |
|
294 | if hasattr(config.Global, 'classic'): | |
278 |
if config. |
|
295 | if config.Global.classic: | |
279 |
config. |
|
296 | config.InteractiveShell.cache_size = 0 | |
280 |
config. |
|
297 | config.InteractiveShell.pprint = 0 | |
281 | config.PPRINT = 0 |
|
298 | config.InteractiveShell.prompt_in1 = '>>> ' | |
282 | config.PROMPT_IN1 = '>>> ' |
|
299 | config.InteractiveShell.prompt_in2 = '... ' | |
283 | config.PROMPT_IN2 = '... ' |
|
300 | config.InteractiveShell.prompt_out = '' | |
284 | config.PROMPT_OUT = '' |
|
301 | config.InteractiveShell.separate_in = \ | |
285 | config.SEPARATE_IN = config.SEPARATE_OUT = config.SEPARATE_OUT2 = '' |
|
302 | config.InteractiveShell.separate_out = \ | |
286 | config.COLORS = 'NoColor' |
|
303 | config.InteractiveShell.separate_out2 = '' | |
287 |
config. |
|
304 | config.InteractiveShell.colors = 'NoColor' | |
|
305 | config.InteractiveShell.xmode = 'Plain' | |||
288 |
|
306 | |||
289 | # All this should be moved to traitlet handlers in InteractiveShell |
|
307 | # All this should be moved to traitlet handlers in InteractiveShell | |
290 | # But, currently InteractiveShell doesn't have support for changing |
|
308 | # But, currently InteractiveShell doesn't have support for changing | |
291 | # these values at runtime. Once we support that, this should |
|
309 | # these values at runtime. Once we support that, this should | |
292 | # be moved there!!! |
|
310 | # be moved there!!! | |
293 |
if hasattr(config, ' |
|
311 | if hasattr(config.Global, 'nosep'): | |
294 |
if config. |
|
312 | if config.Global.nosep: | |
295 | config.SEPARATE_IN = config.SEPARATE_OUT = config.SEPARATE_OUT2 = '0' |
|
313 | config.InteractiveShell.separate_in = \ | |
|
314 | config.InteractiveShell.separate_out = \ | |||
|
315 | config.InteractiveShell.separate_out2 = '0' | |||
296 |
|
316 | |||
297 | def construct(self): |
|
317 | def construct(self): | |
298 | # I am a little hesitant to put these into InteractiveShell itself. |
|
318 | # I am a little hesitant to put these into InteractiveShell itself. | |
@@ -307,12 +327,23 b' class IPythonApp(Application):' | |||||
307 | parent=None, |
|
327 | parent=None, | |
308 | config=self.master_config |
|
328 | config=self.master_config | |
309 | ) |
|
329 | ) | |
310 | print self.shell |
|
|||
311 |
|
330 | |||
312 | def start_app(self): |
|
331 | def start_app(self): | |
313 | self.shell.mainloop() |
|
332 | self.shell.mainloop() | |
314 |
|
333 | |||
315 |
|
334 | |||
|
335 | def load_default_config(ipythondir=None): | |||
|
336 | """Load the default config file from the default ipythondir. | |||
|
337 | ||||
|
338 | This is useful for embedded shells. | |||
|
339 | """ | |||
|
340 | if ipythondir is None: | |||
|
341 | ipythondir = get_ipython_dir() | |||
|
342 | cl = PyFileConfigLoader(_default_config_file_name, ipythondir) | |||
|
343 | config = cl.load_config() | |||
|
344 | return config | |||
|
345 | ||||
|
346 | ||||
316 | if __name__ == '__main__': |
|
347 | if __name__ == '__main__': | |
317 | app = IPythonApp() |
|
348 | app = IPythonApp() | |
318 | app.start() No newline at end of file |
|
349 | app.start() |
@@ -62,6 +62,7 b' from IPython.lib.backgroundjobs import BackgroundJobManager' | |||||
62 | from IPython.utils.ipstruct import Struct |
|
62 | from IPython.utils.ipstruct import Struct | |
63 | from IPython.utils import PyColorize |
|
63 | from IPython.utils import PyColorize | |
64 | from IPython.utils.genutils import * |
|
64 | from IPython.utils.genutils import * | |
|
65 | from IPython.utils.genutils import get_ipython_dir | |||
65 | from IPython.utils.strdispatch import StrDispatch |
|
66 | from IPython.utils.strdispatch import StrDispatch | |
66 | from IPython.utils.platutils import toggle_set_term_title, set_term_title |
|
67 | from IPython.utils.platutils import toggle_set_term_title, set_term_title | |
67 |
|
68 | |||
@@ -188,50 +189,47 b' class SeparateStr(Str):' | |||||
188 | class InteractiveShell(Component, Magic): |
|
189 | class InteractiveShell(Component, Magic): | |
189 | """An enhanced, interactive shell for Python.""" |
|
190 | """An enhanced, interactive shell for Python.""" | |
190 |
|
191 | |||
191 |
autocall = Enum((0,1,2), config |
|
192 | autocall = Enum((0,1,2), config=True) | |
192 |
autoedit_syntax = CBool(False, config |
|
193 | autoedit_syntax = CBool(False, config=True) | |
193 |
autoindent = CBool(True, config |
|
194 | autoindent = CBool(True, config=True) | |
194 |
automagic = CBool(True, config |
|
195 | automagic = CBool(True, config=True) | |
195 |
display_banner = CBool(True, config |
|
196 | display_banner = CBool(True, config=True) | |
196 | banner = Str('') |
|
197 | banner = Str('') | |
197 |
banner1 = Str(default_banner, config |
|
198 | banner1 = Str(default_banner, config=True) | |
198 |
banner2 = Str('', config |
|
199 | banner2 = Str('', config=True) | |
199 |
c = Str('', config |
|
200 | c = Str('', config=True) | |
200 |
cache_size = Int(1000, config |
|
201 | cache_size = Int(1000, config=True) | |
201 |
c |
|
202 | color_info = CBool(True, config=True) | |
202 | color_info = CBool(True, config_key='COLOR_INFO') |
|
|||
203 | colors = CaselessStrEnum(('NoColor','LightBG','Linux'), |
|
203 | colors = CaselessStrEnum(('NoColor','LightBG','Linux'), | |
204 |
default_value='LightBG', config |
|
204 | default_value='LightBG', config=True) | |
205 |
confirm_exit = CBool(True, config |
|
205 | confirm_exit = CBool(True, config=True) | |
206 |
debug = CBool(False, config |
|
206 | debug = CBool(False, config=True) | |
207 |
deep_reload = CBool(False, config |
|
207 | deep_reload = CBool(False, config=True) | |
208 | embedded = CBool(False) |
|
208 | embedded = CBool(False) | |
209 | embedded_active = CBool(False) |
|
209 | embedded_active = CBool(False) | |
210 |
editor = Str(get_default_editor(), config |
|
210 | editor = Str(get_default_editor(), config=True) | |
211 | filename = Str("<ipython console>") |
|
211 | filename = Str("<ipython console>") | |
212 |
interactive = CBool(False, config |
|
212 | interactive = CBool(False, config=True) | |
213 |
ipythondir= Unicode('', config |
|
213 | ipythondir= Unicode('', config=True) # Set to get_ipython_dir() in __init__ | |
214 |
logstart = CBool(False, config |
|
214 | logstart = CBool(False, config=True) | |
215 |
logfile = Str('', config |
|
215 | logfile = Str('', config=True) | |
216 |
logplay = Str('', config |
|
216 | logplay = Str('', config=True) | |
217 | object_info_string_level = Enum((0,1,2), default_value=0, |
|
217 | object_info_string_level = Enum((0,1,2), default_value=0, | |
218 |
config |
|
218 | config=True) | |
219 |
pager = Str('less', config |
|
219 | pager = Str('less', config=True) | |
220 |
pdb = CBool(False, config |
|
220 | pdb = CBool(False, config=True) | |
221 |
pprint = CBool(True, config |
|
221 | pprint = CBool(True, config=True) | |
222 |
profile = Str('', config |
|
222 | profile = Str('', config=True) | |
223 |
prompt_in1 = Str('In [\\#]: ', config |
|
223 | prompt_in1 = Str('In [\\#]: ', config=True) | |
224 |
prompt_in2 = Str(' .\\D.: ', config |
|
224 | prompt_in2 = Str(' .\\D.: ', config=True) | |
225 |
prompt_out = Str('Out[\\#]: ', config |
|
225 | prompt_out = Str('Out[\\#]: ', config=True) | |
226 |
prompts_pad_left = CBool(True, config |
|
226 | prompts_pad_left = CBool(True, config=True) | |
227 |
quiet = CBool(False, config |
|
227 | quiet = CBool(False, config=True) | |
228 |
|
228 | |||
229 |
readline_use = CBool(True, config |
|
229 | readline_use = CBool(True, config=True) | |
230 | readline_merge_completions = CBool(True, |
|
230 | readline_merge_completions = CBool(True, config=True) | |
231 | config_key='READLINE_MERGE_COMPLETIONS') |
|
231 | readline_omit__names = Enum((0,1,2), default_value=0, config=True) | |
232 | readline_omit__names = Enum((0,1,2), default_value=0, |
|
232 | readline_remove_delims = Str('-/~', config=True) | |
233 | config_key='READLINE_OMIT_NAMES') |
|
|||
234 | readline_remove_delims = Str('-/~', config_key='READLINE_REMOVE_DELIMS') |
|
|||
235 | readline_parse_and_bind = List([ |
|
233 | readline_parse_and_bind = List([ | |
236 | 'tab: complete', |
|
234 | 'tab: complete', | |
237 | '"\C-l": possible-completions', |
|
235 | '"\C-l": possible-completions', | |
@@ -248,24 +246,22 b' class InteractiveShell(Component, Magic):' | |||||
248 | '"\e[B": history-search-forward', |
|
246 | '"\e[B": history-search-forward', | |
249 | '"\C-k": kill-line', |
|
247 | '"\C-k": kill-line', | |
250 | '"\C-u": unix-line-discard', |
|
248 | '"\C-u": unix-line-discard', | |
251 |
], allow_none=False, config |
|
249 | ], allow_none=False, config=True) | |
252 | ) |
|
|||
253 |
|
250 | |||
254 |
screen_length = Int(0, config |
|
251 | screen_length = Int(0, config=True) | |
255 |
|
252 | |||
256 | # Use custom TraitletTypes that convert '0'->'' and '\\n'->'\n' |
|
253 | # Use custom TraitletTypes that convert '0'->'' and '\\n'->'\n' | |
257 |
separate_in = SeparateStr('\n', config |
|
254 | separate_in = SeparateStr('\n', config=True) | |
258 |
separate_out = SeparateStr('', config |
|
255 | separate_out = SeparateStr('', config=True) | |
259 |
separate_out2 = SeparateStr('', config |
|
256 | separate_out2 = SeparateStr('', config=True) | |
260 |
|
257 | |||
261 |
system_header = Str('IPython system call: ', config |
|
258 | system_header = Str('IPython system call: ', config=True) | |
262 |
system_verbose = CBool(False, config |
|
259 | system_verbose = CBool(False, config=True) | |
263 |
term_title = CBool(False, config |
|
260 | term_title = CBool(False, config=True) | |
264 |
wildcards_case_sensitive = CBool(True, config |
|
261 | wildcards_case_sensitive = CBool(True, config=True) | |
265 | xmode = CaselessStrEnum(('Context','Plain', 'Verbose'), |
|
262 | xmode = CaselessStrEnum(('Context','Plain', 'Verbose'), | |
266 |
default_value='Context', config |
|
263 | default_value='Context', config=True) | |
267 |
|
264 | |||
268 | alias = List(allow_none=False, config_key='ALIAS') |
|
|||
269 | autoexec = List(allow_none=False) |
|
265 | autoexec = List(allow_none=False) | |
270 |
|
266 | |||
271 | # class attribute to indicate whether the class supports threads or not. |
|
267 | # class attribute to indicate whether the class supports threads or not. | |
@@ -279,7 +275,7 b' class InteractiveShell(Component, Magic):' | |||||
279 |
|
275 | |||
280 | # This is where traitlets with a config_key argument are updated |
|
276 | # This is where traitlets with a config_key argument are updated | |
281 | # from the values on config. |
|
277 | # from the values on config. | |
282 |
super(InteractiveShell, self).__init__(parent, config=config |
|
278 | super(InteractiveShell, self).__init__(parent, config=config) | |
283 |
|
279 | |||
284 | # These are relatively independent and stateless |
|
280 | # These are relatively independent and stateless | |
285 | self.init_ipythondir(ipythondir) |
|
281 | self.init_ipythondir(ipythondir) | |
@@ -288,7 +284,7 b' class InteractiveShell(Component, Magic):' | |||||
288 | self.init_usage(usage) |
|
284 | self.init_usage(usage) | |
289 | self.init_banner(banner1, banner2) |
|
285 | self.init_banner(banner1, banner2) | |
290 |
|
286 | |||
291 |
# Create namespaces (user_ns, user_global_ns, |
|
287 | # Create namespaces (user_ns, user_global_ns, etc.) | |
292 | self.init_create_namespaces(user_ns, user_global_ns) |
|
288 | self.init_create_namespaces(user_ns, user_global_ns) | |
293 | # This has to be done after init_create_namespaces because it uses |
|
289 | # This has to be done after init_create_namespaces because it uses | |
294 | # something in self.user_ns, but before init_sys_modules, which |
|
290 | # something in self.user_ns, but before init_sys_modules, which | |
@@ -327,6 +323,9 b' class InteractiveShell(Component, Magic):' | |||||
327 | self.init_pdb() |
|
323 | self.init_pdb() | |
328 | self.hooks.late_startup_hook() |
|
324 | self.hooks.late_startup_hook() | |
329 |
|
325 | |||
|
326 | def get_ipython(self): | |||
|
327 | return self | |||
|
328 | ||||
330 | #------------------------------------------------------------------------- |
|
329 | #------------------------------------------------------------------------- | |
331 | # Traitlet changed handlers |
|
330 | # Traitlet changed handlers | |
332 | #------------------------------------------------------------------------- |
|
331 | #------------------------------------------------------------------------- | |
@@ -337,6 +336,10 b' class InteractiveShell(Component, Magic):' | |||||
337 | def _banner2_changed(self): |
|
336 | def _banner2_changed(self): | |
338 | self.compute_banner() |
|
337 | self.compute_banner() | |
339 |
|
338 | |||
|
339 | def _ipythondir_changed(self, name, new): | |||
|
340 | if not os.path.isdir(new): | |||
|
341 | os.makedirs(new, mode = 0777) | |||
|
342 | ||||
340 | @property |
|
343 | @property | |
341 | def usable_screen_length(self): |
|
344 | def usable_screen_length(self): | |
342 | if self.screen_length == 0: |
|
345 | if self.screen_length == 0: | |
@@ -370,22 +373,16 b' class InteractiveShell(Component, Magic):' | |||||
370 | def init_ipythondir(self, ipythondir): |
|
373 | def init_ipythondir(self, ipythondir): | |
371 | if ipythondir is not None: |
|
374 | if ipythondir is not None: | |
372 | self.ipythondir = ipythondir |
|
375 | self.ipythondir = ipythondir | |
373 |
self.config. |
|
376 | self.config.Global.ipythondir = self.ipythondir | |
374 | return |
|
377 | return | |
375 |
|
378 | |||
376 |
if hasattr(self.config, ' |
|
379 | if hasattr(self.config.Global, 'ipythondir'): | |
377 |
self.ipythondir = self.config. |
|
380 | self.ipythondir = self.config.Global.ipythondir | |
378 | if not hasattr(self.config, 'IPYTHONDIR'): |
|
381 | else: | |
379 | # cdw is always defined |
|
382 | self.ipythondir = get_ipython_dir() | |
380 | self.ipythondir = os.getcwd() |
|
|||
381 |
|
||||
382 | # The caller must make sure that ipythondir exists. We should |
|
|||
383 | # probably handle this using a Dir traitlet. |
|
|||
384 | if not os.path.isdir(self.ipythondir): |
|
|||
385 | raise IOError('IPython dir does not exist: %s' % self.ipythondir) |
|
|||
386 |
|
383 | |||
387 | # All children can just read this |
|
384 | # All children can just read this | |
388 |
self.config. |
|
385 | self.config.Global.ipythondir = self.ipythondir | |
389 |
|
386 | |||
390 | def init_instance_attrs(self): |
|
387 | def init_instance_attrs(self): | |
391 | self.jobs = BackgroundJobManager() |
|
388 | self.jobs = BackgroundJobManager() | |
@@ -825,11 +822,6 b' class InteractiveShell(Component, Magic):' | |||||
825 | # them from cluttering user-visible stuff. Will be updated later |
|
822 | # them from cluttering user-visible stuff. Will be updated later | |
826 | self.internal_ns = {} |
|
823 | self.internal_ns = {} | |
827 |
|
824 | |||
828 | # Namespace of system aliases. Each entry in the alias |
|
|||
829 | # table must be a 2-tuple of the form (N,name), where N is the number |
|
|||
830 | # of positional arguments of the alias. |
|
|||
831 | self.alias_table = {} |
|
|||
832 |
|
||||
833 | # Now that FakeModule produces a real module, we've run into a nasty |
|
825 | # Now that FakeModule produces a real module, we've run into a nasty | |
834 | # problem: after script execution (via %run), the module where the user |
|
826 | # problem: after script execution (via %run), the module where the user | |
835 | # code ran is deleted. Now that this object is a true module (needed |
|
827 | # code ran is deleted. Now that this object is a true module (needed | |
@@ -863,7 +855,6 b' class InteractiveShell(Component, Magic):' | |||||
863 | # introspection facilities can search easily. |
|
855 | # introspection facilities can search easily. | |
864 | self.ns_table = {'user':user_ns, |
|
856 | self.ns_table = {'user':user_ns, | |
865 | 'user_global':user_global_ns, |
|
857 | 'user_global':user_global_ns, | |
866 | 'alias':self.alias_table, |
|
|||
867 | 'internal':self.internal_ns, |
|
858 | 'internal':self.internal_ns, | |
868 | 'builtin':__builtin__.__dict__ |
|
859 | 'builtin':__builtin__.__dict__ | |
869 | } |
|
860 | } | |
@@ -872,8 +863,7 b' class InteractiveShell(Component, Magic):' | |||||
872 | # we can safely clear (so it can NOT include builtin). This one can be |
|
863 | # we can safely clear (so it can NOT include builtin). This one can be | |
873 | # a simple list. |
|
864 | # a simple list. | |
874 | self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns, |
|
865 | self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns, | |
875 |
self. |
|
866 | self.internal_ns, self._main_ns_cache ] | |
876 | self._main_ns_cache ] |
|
|||
877 |
|
867 | |||
878 | def init_sys_modules(self): |
|
868 | def init_sys_modules(self): | |
879 | # We need to insert into sys.modules something that looks like a |
|
869 | # We need to insert into sys.modules something that looks like a | |
@@ -961,11 +951,8 b' class InteractiveShell(Component, Magic):' | |||||
961 | method. If they were not empty before, data will simply be added to |
|
951 | method. If they were not empty before, data will simply be added to | |
962 | therm. |
|
952 | therm. | |
963 | """ |
|
953 | """ | |
964 | # The user namespace MUST have a pointer to the shell itself. |
|
|||
965 | self.user_ns[self.name] = self |
|
|||
966 |
|
||||
967 | # Store myself as the public api!!! |
|
954 | # Store myself as the public api!!! | |
968 | self.user_ns['_ip'] = self |
|
955 | self.user_ns['get_ipython'] = self.get_ipython | |
969 |
|
956 | |||
970 | # make global variables for user access to the histories |
|
957 | # make global variables for user access to the histories | |
971 | self.user_ns['_ih'] = self.input_hist |
|
958 | self.user_ns['_ih'] = self.input_hist | |
@@ -994,13 +981,19 b' class InteractiveShell(Component, Magic):' | |||||
994 | for ns in self.ns_refs_table: |
|
981 | for ns in self.ns_refs_table: | |
995 | ns.clear() |
|
982 | ns.clear() | |
996 |
|
983 | |||
|
984 | self.alias_manager.clear_aliases() | |||
|
985 | ||||
997 | # Clear input and output histories |
|
986 | # Clear input and output histories | |
998 | self.input_hist[:] = [] |
|
987 | self.input_hist[:] = [] | |
999 | self.input_hist_raw[:] = [] |
|
988 | self.input_hist_raw[:] = [] | |
1000 | self.output_hist.clear() |
|
989 | self.output_hist.clear() | |
|
990 | ||||
1001 | # Restore the user namespaces to minimal usability |
|
991 | # Restore the user namespaces to minimal usability | |
1002 | self.init_user_ns() |
|
992 | self.init_user_ns() | |
1003 |
|
993 | |||
|
994 | # Restore the default and user aliases | |||
|
995 | self.alias_manager.init_aliases() | |||
|
996 | ||||
1004 | def push(self, variables, interactive=True): |
|
997 | def push(self, variables, interactive=True): | |
1005 | """Inject a group of variables into the IPython user namespace. |
|
998 | """Inject a group of variables into the IPython user namespace. | |
1006 |
|
999 | |||
@@ -1076,7 +1069,7 b' class InteractiveShell(Component, Magic):' | |||||
1076 | histfname = 'history-%s' % self.profile |
|
1069 | histfname = 'history-%s' % self.profile | |
1077 | except AttributeError: |
|
1070 | except AttributeError: | |
1078 | histfname = 'history' |
|
1071 | histfname = 'history' | |
1079 |
self.histfile = os.path.join(self. |
|
1072 | self.histfile = os.path.join(self.ipythondir, histfname) | |
1080 |
|
1073 | |||
1081 | # Fill the history zero entry, user counter starts at 1 |
|
1074 | # Fill the history zero entry, user counter starts at 1 | |
1082 | self.input_hist.append('\n') |
|
1075 | self.input_hist.append('\n') | |
@@ -1084,12 +1077,12 b' class InteractiveShell(Component, Magic):' | |||||
1084 |
|
1077 | |||
1085 | def init_shadow_hist(self): |
|
1078 | def init_shadow_hist(self): | |
1086 | try: |
|
1079 | try: | |
1087 |
self.db = pickleshare.PickleShareDB(self. |
|
1080 | self.db = pickleshare.PickleShareDB(self.ipythondir + "/db") | |
1088 | except exceptions.UnicodeDecodeError: |
|
1081 | except exceptions.UnicodeDecodeError: | |
1089 | print "Your ipythondir can't be decoded to unicode!" |
|
1082 | print "Your ipythondir can't be decoded to unicode!" | |
1090 | print "Please set HOME environment variable to something that" |
|
1083 | print "Please set HOME environment variable to something that" | |
1091 | print r"only has ASCII characters, e.g. c:\home" |
|
1084 | print r"only has ASCII characters, e.g. c:\home" | |
1092 |
print "Now it is", self. |
|
1085 | print "Now it is", self.ipythondir | |
1093 | sys.exit() |
|
1086 | sys.exit() | |
1094 | self.shadowhist = ipcorehist.ShadowHist(self.db) |
|
1087 | self.shadowhist = ipcorehist.ShadowHist(self.db) | |
1095 |
|
1088 | |||
@@ -1475,7 +1468,7 b' class InteractiveShell(Component, Magic):' | |||||
1475 |
|
|
1468 | self.user_ns, | |
1476 |
|
|
1469 | self.user_global_ns, | |
1477 |
|
|
1470 | self.readline_omit__names, | |
1478 |
|
|
1471 | self.alias_manager.alias_table) | |
1479 | sdisp = self.strdispatchers.get('complete_command', StrDispatch()) |
|
1472 | sdisp = self.strdispatchers.get('complete_command', StrDispatch()) | |
1480 | self.strdispatchers['complete_command'] = sdisp |
|
1473 | self.strdispatchers['complete_command'] = sdisp | |
1481 | self.Completer.custom_completers = sdisp |
|
1474 | self.Completer.custom_completers = sdisp | |
@@ -1607,8 +1600,11 b' class InteractiveShell(Component, Magic):' | |||||
1607 | error("Magic function `%s` not found." % magic_name) |
|
1600 | error("Magic function `%s` not found." % magic_name) | |
1608 | else: |
|
1601 | else: | |
1609 | magic_args = self.var_expand(magic_args,1) |
|
1602 | magic_args = self.var_expand(magic_args,1) | |
1610 |
with nested(self.builtin_trap, |
|
1603 | with nested(self.builtin_trap,): | |
1611 |
re |
|
1604 | result = fn(magic_args) | |
|
1605 | # Unfortunately, the return statement is what will trigger | |||
|
1606 | # the displayhook, but it is no longer set! | |||
|
1607 | return result | |||
1612 |
|
1608 | |||
1613 | def define_magic(self, magicname, func): |
|
1609 | def define_magic(self, magicname, func): | |
1614 | """Expose own function as magic function for ipython |
|
1610 | """Expose own function as magic function for ipython | |
@@ -1666,6 +1662,7 b' class InteractiveShell(Component, Magic):' | |||||
1666 |
|
1662 | |||
1667 | def init_alias(self): |
|
1663 | def init_alias(self): | |
1668 | self.alias_manager = AliasManager(self, config=self.config) |
|
1664 | self.alias_manager = AliasManager(self, config=self.config) | |
|
1665 | self.ns_table['alias'] = self.alias_manager.alias_table, | |||
1669 |
|
1666 | |||
1670 | #------------------------------------------------------------------------- |
|
1667 | #------------------------------------------------------------------------- | |
1671 | # Things related to the running of code |
|
1668 | # Things related to the running of code | |
@@ -1673,7 +1670,7 b' class InteractiveShell(Component, Magic):' | |||||
1673 |
|
1670 | |||
1674 | def ex(self, cmd): |
|
1671 | def ex(self, cmd): | |
1675 | """Execute a normal python statement in user namespace.""" |
|
1672 | """Execute a normal python statement in user namespace.""" | |
1676 |
with nested(self.builtin_trap, |
|
1673 | with nested(self.builtin_trap,): | |
1677 | exec cmd in self.user_global_ns, self.user_ns |
|
1674 | exec cmd in self.user_global_ns, self.user_ns | |
1678 |
|
1675 | |||
1679 | def ev(self, expr): |
|
1676 | def ev(self, expr): | |
@@ -1681,7 +1678,7 b' class InteractiveShell(Component, Magic):' | |||||
1681 |
|
1678 | |||
1682 | Returns the result of evaluation |
|
1679 | Returns the result of evaluation | |
1683 | """ |
|
1680 | """ | |
1684 |
with nested(self.builtin_trap, |
|
1681 | with nested(self.builtin_trap,): | |
1685 | return eval(expr, self.user_global_ns, self.user_ns) |
|
1682 | return eval(expr, self.user_global_ns, self.user_ns) | |
1686 |
|
1683 | |||
1687 | def mainloop(self, banner=None): |
|
1684 | def mainloop(self, banner=None): |
@@ -47,6 +47,7 b' from IPython.utils import wildcard' | |||||
47 | from IPython.core import debugger, oinspect |
|
47 | from IPython.core import debugger, oinspect | |
48 | from IPython.core.error import TryNext |
|
48 | from IPython.core.error import TryNext | |
49 | from IPython.core.fakemodule import FakeModule |
|
49 | from IPython.core.fakemodule import FakeModule | |
|
50 | from IPython.core.prefilter import ESC_MAGIC | |||
50 | from IPython.external.Itpl import Itpl, itpl, printpl,itplns |
|
51 | from IPython.external.Itpl import Itpl, itpl, printpl,itplns | |
51 | from IPython.utils.PyColorize import Parser |
|
52 | from IPython.utils.PyColorize import Parser | |
52 | from IPython.utils.ipstruct import Struct |
|
53 | from IPython.utils.ipstruct import Struct | |
@@ -205,9 +206,9 b' python-profiler package from non-free.""")' | |||||
205 | namespaces = [ ('Interactive', self.shell.user_ns), |
|
206 | namespaces = [ ('Interactive', self.shell.user_ns), | |
206 | ('IPython internal', self.shell.internal_ns), |
|
207 | ('IPython internal', self.shell.internal_ns), | |
207 | ('Python builtin', __builtin__.__dict__), |
|
208 | ('Python builtin', __builtin__.__dict__), | |
208 | ('Alias', self.shell.alias_table), |
|
209 | ('Alias', self.shell.alias_manager.alias_table), | |
209 | ] |
|
210 | ] | |
210 | alias_ns = self.shell.alias_table |
|
211 | alias_ns = self.shell.alias_manager.alias_table | |
211 |
|
212 | |||
212 | # initialize results to 'null' |
|
213 | # initialize results to 'null' | |
213 | found = 0; obj = None; ospace = None; ds = None; |
|
214 | found = 0; obj = None; ospace = None; ds = None; | |
@@ -244,7 +245,7 b' python-profiler package from non-free.""")' | |||||
244 |
|
245 | |||
245 | # Try to see if it's magic |
|
246 | # Try to see if it's magic | |
246 | if not found: |
|
247 | if not found: | |
247 |
if oname.startswith( |
|
248 | if oname.startswith(ESC_MAGIC): | |
248 | oname = oname[1:] |
|
249 | oname = oname[1:] | |
249 | obj = getattr(self,'magic_'+oname,None) |
|
250 | obj = getattr(self,'magic_'+oname,None) | |
250 | if obj is not None: |
|
251 | if obj is not None: | |
@@ -272,10 +273,10 b' python-profiler package from non-free.""")' | |||||
272 | # Characters that need to be escaped for latex: |
|
273 | # Characters that need to be escaped for latex: | |
273 | escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE) |
|
274 | escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE) | |
274 | # Magic command names as headers: |
|
275 | # Magic command names as headers: | |
275 |
cmd_name_re = re.compile(r'^(%s.*?):' % |
|
276 | cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC, | |
276 | re.MULTILINE) |
|
277 | re.MULTILINE) | |
277 | # Magic commands |
|
278 | # Magic commands | |
278 |
cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % |
|
279 | cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC, | |
279 | re.MULTILINE) |
|
280 | re.MULTILINE) | |
280 | # Paragraph continue |
|
281 | # Paragraph continue | |
281 | par_re = re.compile(r'\\$',re.MULTILINE) |
|
282 | par_re = re.compile(r'\\$',re.MULTILINE) | |
@@ -376,7 +377,7 b' python-profiler package from non-free.""")' | |||||
376 | # Functions for IPython shell work (vars,funcs, config, etc) |
|
377 | # Functions for IPython shell work (vars,funcs, config, etc) | |
377 | def magic_lsmagic(self, parameter_s = ''): |
|
378 | def magic_lsmagic(self, parameter_s = ''): | |
378 | """List currently available magic functions.""" |
|
379 | """List currently available magic functions.""" | |
379 |
mesc = |
|
380 | mesc = ESC_MAGIC | |
380 | print 'Available magic functions:\n'+mesc+\ |
|
381 | print 'Available magic functions:\n'+mesc+\ | |
381 | (' '+mesc).join(self.lsmagic()) |
|
382 | (' '+mesc).join(self.lsmagic()) | |
382 | print '\n' + Magic.auto_status[self.shell.automagic] |
|
383 | print '\n' + Magic.auto_status[self.shell.automagic] | |
@@ -424,11 +425,11 b' python-profiler package from non-free.""")' | |||||
424 |
|
425 | |||
425 |
|
426 | |||
426 | if mode == 'rest': |
|
427 | if mode == 'rest': | |
427 |
rest_docs.append('**%s%s**::\n\n\t%s\n\n' %( |
|
428 | rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(ESC_MAGIC, | |
428 | fname,fndoc)) |
|
429 | fname,fndoc)) | |
429 |
|
430 | |||
430 | else: |
|
431 | else: | |
431 |
magic_docs.append('%s%s:\n\t%s\n' %( |
|
432 | magic_docs.append('%s%s:\n\t%s\n' %(ESC_MAGIC, | |
432 | fname,fndoc)) |
|
433 | fname,fndoc)) | |
433 |
|
434 | |||
434 | magic_docs = ''.join(magic_docs) |
|
435 | magic_docs = ''.join(magic_docs) | |
@@ -479,7 +480,7 b" of any of them, type %magic_name?, e.g. '%cd?'." | |||||
479 |
|
480 | |||
480 | Currently the magic system has the following functions:\n""" |
|
481 | Currently the magic system has the following functions:\n""" | |
481 |
|
482 | |||
482 |
mesc = |
|
483 | mesc = ESC_MAGIC | |
483 | outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):" |
|
484 | outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):" | |
484 | "\n\n%s%s\n\n%s" % (outmsg, |
|
485 | "\n\n%s%s\n\n%s" % (outmsg, | |
485 | magic_docs,mesc,mesc, |
|
486 | magic_docs,mesc,mesc, | |
@@ -2620,52 +2621,27 b' Defaulting color scheme to \'NoColor\'"""' | |||||
2620 | par = parameter_s.strip() |
|
2621 | par = parameter_s.strip() | |
2621 | if not par: |
|
2622 | if not par: | |
2622 | stored = self.db.get('stored_aliases', {} ) |
|
2623 | stored = self.db.get('stored_aliases', {} ) | |
2623 |
a |
|
2624 | aliases = sorted(self.shell.alias_manager.aliases) | |
2624 | aliases = atab.keys() |
|
2625 | # for k, v in stored: | |
2625 | aliases.sort() |
|
2626 | # atab.append(k, v[0]) | |
2626 | res = [] |
|
2627 | ||
2627 | showlast = [] |
|
|||
2628 | for alias in aliases: |
|
|||
2629 | special = False |
|
|||
2630 | try: |
|
|||
2631 | tgt = atab[alias][1] |
|
|||
2632 | except (TypeError, AttributeError): |
|
|||
2633 | # unsubscriptable? probably a callable |
|
|||
2634 | tgt = atab[alias] |
|
|||
2635 | special = True |
|
|||
2636 | # 'interesting' aliases |
|
|||
2637 | if (alias in stored or |
|
|||
2638 | special or |
|
|||
2639 | alias.lower() != os.path.splitext(tgt)[0].lower() or |
|
|||
2640 | ' ' in tgt): |
|
|||
2641 | showlast.append((alias, tgt)) |
|
|||
2642 | else: |
|
|||
2643 | res.append((alias, tgt )) |
|
|||
2644 |
|
||||
2645 | # show most interesting aliases last |
|
|||
2646 | res.extend(showlast) |
|
|||
2647 | print "Total number of aliases:",len(aliases) |
|
2628 | print "Total number of aliases:", len(aliases) | |
2648 |
return |
|
2629 | return aliases | |
|
2630 | ||||
|
2631 | # Now try to define a new one | |||
2649 | try: |
|
2632 | try: | |
2650 | alias,cmd = par.split(None,1) |
|
2633 | alias,cmd = par.split(None, 1) | |
2651 | except: |
|
2634 | except: | |
2652 | print oinspect.getdoc(self.magic_alias) |
|
2635 | print oinspect.getdoc(self.magic_alias) | |
2653 | else: |
|
2636 | else: | |
2654 | nargs = cmd.count('%s') |
|
2637 | self.shell.alias_manager.soft_define_alias(alias, cmd) | |
2655 | if nargs>0 and cmd.find('%l')>=0: |
|
|||
2656 | error('The %s and %l specifiers are mutually exclusive ' |
|
|||
2657 | 'in alias definitions.') |
|
|||
2658 | else: # all looks OK |
|
|||
2659 | self.shell.alias_table[alias] = (nargs,cmd) |
|
|||
2660 | self.shell.alias_table_validate(verbose=0) |
|
|||
2661 | # end magic_alias |
|
2638 | # end magic_alias | |
2662 |
|
2639 | |||
2663 | def magic_unalias(self, parameter_s = ''): |
|
2640 | def magic_unalias(self, parameter_s = ''): | |
2664 | """Remove an alias""" |
|
2641 | """Remove an alias""" | |
2665 |
|
2642 | |||
2666 | aname = parameter_s.strip() |
|
2643 | aname = parameter_s.strip() | |
2667 | if aname in self.shell.alias_table: |
|
2644 | self.shell.alias_manager.undefine_alias(aname) | |
2668 | del self.shell.alias_table[aname] |
|
|||
2669 | stored = self.db.get('stored_aliases', {} ) |
|
2645 | stored = self.db.get('stored_aliases', {} ) | |
2670 | if aname in stored: |
|
2646 | if aname in stored: | |
2671 | print "Removing %stored alias",aname |
|
2647 | print "Removing %stored alias",aname | |
@@ -2686,6 +2662,7 b' Defaulting color scheme to \'NoColor\'"""' | |||||
2686 | This function also resets the root module cache of module completer, |
|
2662 | This function also resets the root module cache of module completer, | |
2687 | used on slow filesystems. |
|
2663 | used on slow filesystems. | |
2688 | """ |
|
2664 | """ | |
|
2665 | from IPython.core.alias import InvalidAliasError | |||
2689 |
|
2666 | |||
2690 | # for the benefit of module completer in ipy_completers.py |
|
2667 | # for the benefit of module completer in ipy_completers.py | |
2691 | del self.db['rootmodules'] |
|
2668 | del self.db['rootmodules'] | |
@@ -2694,13 +2671,12 b' Defaulting color scheme to \'NoColor\'"""' | |||||
2694 | os.environ.get('PATH','').split(os.pathsep)] |
|
2671 | os.environ.get('PATH','').split(os.pathsep)] | |
2695 | path = filter(os.path.isdir,path) |
|
2672 | path = filter(os.path.isdir,path) | |
2696 |
|
2673 | |||
2697 | alias_table = self.shell.alias_table |
|
|||
2698 | syscmdlist = [] |
|
2674 | syscmdlist = [] | |
|
2675 | # Now define isexec in a cross platform manner. | |||
2699 | if os.name == 'posix': |
|
2676 | if os.name == 'posix': | |
2700 | isexec = lambda fname:os.path.isfile(fname) and \ |
|
2677 | isexec = lambda fname:os.path.isfile(fname) and \ | |
2701 | os.access(fname,os.X_OK) |
|
2678 | os.access(fname,os.X_OK) | |
2702 | else: |
|
2679 | else: | |
2703 |
|
||||
2704 | try: |
|
2680 | try: | |
2705 | winext = os.environ['pathext'].replace(';','|').replace('.','') |
|
2681 | winext = os.environ['pathext'].replace(';','|').replace('.','') | |
2706 | except KeyError: |
|
2682 | except KeyError: | |
@@ -2710,6 +2686,8 b' Defaulting color scheme to \'NoColor\'"""' | |||||
2710 | execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) |
|
2686 | execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) | |
2711 | isexec = lambda fname:os.path.isfile(fname) and execre.match(fname) |
|
2687 | isexec = lambda fname:os.path.isfile(fname) and execre.match(fname) | |
2712 | savedir = os.getcwd() |
|
2688 | savedir = os.getcwd() | |
|
2689 | ||||
|
2690 | # Now walk the paths looking for executables to alias. | |||
2713 | try: |
|
2691 | try: | |
2714 | # write the whole loop for posix/Windows so we don't have an if in |
|
2692 | # write the whole loop for posix/Windows so we don't have an if in | |
2715 | # the innermost part |
|
2693 | # the innermost part | |
@@ -2717,13 +2695,15 b' Defaulting color scheme to \'NoColor\'"""' | |||||
2717 | for pdir in path: |
|
2695 | for pdir in path: | |
2718 | os.chdir(pdir) |
|
2696 | os.chdir(pdir) | |
2719 | for ff in os.listdir(pdir): |
|
2697 | for ff in os.listdir(pdir): | |
2720 |
if isexec(ff) |
|
2698 | if isexec(ff): | |
2721 | # each entry in the alias table must be (N,name), |
|
2699 | try: | |
2722 | # where N is the number of positional arguments of the |
|
2700 | # Removes dots from the name since ipython | |
2723 | # alias. |
|
2701 | # will assume names with dots to be python. | |
2724 | # Dots will be removed from alias names, since ipython |
|
2702 | self.shell.alias_manager.define_alias( | |
2725 | # assumes names with dots to be python code |
|
2703 | ff.replace('.',''), ff) | |
2726 | alias_table[ff.replace('.','')] = (0,ff) |
|
2704 | except InvalidAliasError: | |
|
2705 | pass | |||
|
2706 | else: | |||
2727 | syscmdlist.append(ff) |
|
2707 | syscmdlist.append(ff) | |
2728 | else: |
|
2708 | else: | |
2729 | for pdir in path: |
|
2709 | for pdir in path: | |
@@ -2733,16 +2713,14 b' Defaulting color scheme to \'NoColor\'"""' | |||||
2733 | if isexec(ff) and base.lower() not in self.shell.no_alias: |
|
2713 | if isexec(ff) and base.lower() not in self.shell.no_alias: | |
2734 | if ext.lower() == '.exe': |
|
2714 | if ext.lower() == '.exe': | |
2735 | ff = base |
|
2715 | ff = base | |
2736 | alias_table[base.lower().replace('.','')] = (0,ff) |
|
2716 | try: | |
|
2717 | # Removes dots from the name since ipython | |||
|
2718 | # will assume names with dots to be python. | |||
|
2719 | self.shell.alias_manager.define_alias( | |||
|
2720 | base.lower().replace('.',''), ff) | |||
|
2721 | except InvalidAliasError: | |||
|
2722 | pass | |||
2737 | syscmdlist.append(ff) |
|
2723 | syscmdlist.append(ff) | |
2738 | # Make sure the alias table doesn't contain keywords or builtins |
|
|||
2739 | self.shell.alias_table_validate() |
|
|||
2740 | # Call again init_auto_alias() so we get 'rm -i' and other |
|
|||
2741 | # modified aliases since %rehashx will probably clobber them |
|
|||
2742 |
|
||||
2743 | # no, we don't want them. if %rehashx clobbers them, good, |
|
|||
2744 | # we'll probably get better versions |
|
|||
2745 | # self.shell.init_auto_alias() |
|
|||
2746 | db = self.db |
|
2724 | db = self.db | |
2747 | db['syscmdlist'] = syscmdlist |
|
2725 | db['syscmdlist'] = syscmdlist | |
2748 | finally: |
|
2726 | finally: | |
@@ -3167,7 +3145,7 b' Defaulting color scheme to \'NoColor\'"""' | |||||
3167 | """ |
|
3145 | """ | |
3168 |
|
3146 | |||
3169 | start = parameter_s.strip() |
|
3147 | start = parameter_s.strip() | |
3170 |
esc_magic = |
|
3148 | esc_magic = ESC_MAGIC | |
3171 | # Identify magic commands even if automagic is on (which means |
|
3149 | # Identify magic commands even if automagic is on (which means | |
3172 | # the in-memory version is different from that typed by the user). |
|
3150 | # the in-memory version is different from that typed by the user). | |
3173 | if self.shell.automagic: |
|
3151 | if self.shell.automagic: |
@@ -174,7 +174,7 b' class PrefilterManager(Component):' | |||||
174 | to transform the input line. |
|
174 | to transform the input line. | |
175 | """ |
|
175 | """ | |
176 |
|
176 | |||
177 |
multi_line_specials = CBool(True, config |
|
177 | multi_line_specials = CBool(True, config=True) | |
178 |
|
178 | |||
179 | def __init__(self, parent, config=None): |
|
179 | def __init__(self, parent, config=None): | |
180 | super(PrefilterManager, self).__init__(parent, config=config) |
|
180 | super(PrefilterManager, self).__init__(parent, config=config) | |
@@ -274,16 +274,16 b' class PrefilterManager(Component):' | |||||
274 | # the input history needs to track even empty lines |
|
274 | # the input history needs to track even empty lines | |
275 | stripped = line.strip() |
|
275 | stripped = line.strip() | |
276 |
|
276 | |||
277 |
handle |
|
277 | normal_handler = self.get_handler_by_name('normal') | |
278 | if not stripped: |
|
278 | if not stripped: | |
279 | if not continue_prompt: |
|
279 | if not continue_prompt: | |
280 | self.shell.outputcache.prompt_count -= 1 |
|
280 | self.shell.outputcache.prompt_count -= 1 | |
281 |
|
281 | |||
282 |
return handle |
|
282 | return normal_handler.handle(line_info) | |
283 |
|
283 | |||
284 | # special handlers are only allowed for single line statements |
|
284 | # special handlers are only allowed for single line statements | |
285 | if continue_prompt and not self.multi_line_specials: |
|
285 | if continue_prompt and not self.multi_line_specials: | |
286 |
return handle |
|
286 | return normal_handler.handle(line_info) | |
287 |
|
287 | |||
288 | return self.prefilter_line_info(line_info) |
|
288 | return self.prefilter_line_info(line_info) | |
289 |
|
289 | |||
@@ -310,7 +310,7 b' class PrefilterManager(Component):' | |||||
310 | class PrefilterChecker(Component): |
|
310 | class PrefilterChecker(Component): | |
311 | """Inspect an input line and return a handler for that line.""" |
|
311 | """Inspect an input line and return a handler for that line.""" | |
312 |
|
312 | |||
313 | priority = Int(100) |
|
313 | priority = Int(100, config=True) | |
314 | shell = Any |
|
314 | shell = Any | |
315 | prefilter_manager = Any |
|
315 | prefilter_manager = Any | |
316 |
|
316 | |||
@@ -336,7 +336,7 b' class PrefilterChecker(Component):' | |||||
336 |
|
336 | |||
337 | class EmacsChecker(PrefilterChecker): |
|
337 | class EmacsChecker(PrefilterChecker): | |
338 |
|
338 | |||
339 | priority = Int(100) |
|
339 | priority = Int(100, config=True) | |
340 |
|
340 | |||
341 | def check(self, line_info): |
|
341 | def check(self, line_info): | |
342 | "Emacs ipython-mode tags certain input lines." |
|
342 | "Emacs ipython-mode tags certain input lines." | |
@@ -348,7 +348,7 b' class EmacsChecker(PrefilterChecker):' | |||||
348 |
|
348 | |||
349 | class ShellEscapeChecker(PrefilterChecker): |
|
349 | class ShellEscapeChecker(PrefilterChecker): | |
350 |
|
350 | |||
351 | priority = Int(200) |
|
351 | priority = Int(200, config=True) | |
352 |
|
352 | |||
353 | def check(self, line_info): |
|
353 | def check(self, line_info): | |
354 | if line_info.line.lstrip().startswith(ESC_SHELL): |
|
354 | if line_info.line.lstrip().startswith(ESC_SHELL): | |
@@ -357,7 +357,7 b' class ShellEscapeChecker(PrefilterChecker):' | |||||
357 |
|
357 | |||
358 | class IPyAutocallChecker(PrefilterChecker): |
|
358 | class IPyAutocallChecker(PrefilterChecker): | |
359 |
|
359 | |||
360 | priority = Int(300) |
|
360 | priority = Int(300, config=True) | |
361 |
|
361 | |||
362 | def check(self, line_info): |
|
362 | def check(self, line_info): | |
363 | "Instances of IPyAutocall in user_ns get autocalled immediately" |
|
363 | "Instances of IPyAutocall in user_ns get autocalled immediately" | |
@@ -371,7 +371,7 b' class IPyAutocallChecker(PrefilterChecker):' | |||||
371 |
|
371 | |||
372 | class MultiLineMagicChecker(PrefilterChecker): |
|
372 | class MultiLineMagicChecker(PrefilterChecker): | |
373 |
|
373 | |||
374 | priority = Int(400) |
|
374 | priority = Int(400, config=True) | |
375 |
|
375 | |||
376 | def check(self, line_info): |
|
376 | def check(self, line_info): | |
377 | "Allow ! and !! in multi-line statements if multi_line_specials is on" |
|
377 | "Allow ! and !! in multi-line statements if multi_line_specials is on" | |
@@ -388,7 +388,7 b' class MultiLineMagicChecker(PrefilterChecker):' | |||||
388 |
|
388 | |||
389 | class EscCharsChecker(PrefilterChecker): |
|
389 | class EscCharsChecker(PrefilterChecker): | |
390 |
|
390 | |||
391 | priority = Int(500) |
|
391 | priority = Int(500, config=True) | |
392 |
|
392 | |||
393 | def check(self, line_info): |
|
393 | def check(self, line_info): | |
394 | """Check for escape character and return either a handler to handle it, |
|
394 | """Check for escape character and return either a handler to handle it, | |
@@ -406,7 +406,7 b' class EscCharsChecker(PrefilterChecker):' | |||||
406 |
|
406 | |||
407 | class AssignmentChecker(PrefilterChecker): |
|
407 | class AssignmentChecker(PrefilterChecker): | |
408 |
|
408 | |||
409 | priority = Int(600) |
|
409 | priority = Int(600, config=True) | |
410 |
|
410 | |||
411 | def check(self, line_info): |
|
411 | def check(self, line_info): | |
412 | """Check to see if user is assigning to a var for the first time, in |
|
412 | """Check to see if user is assigning to a var for the first time, in | |
@@ -423,7 +423,7 b' class AssignmentChecker(PrefilterChecker):' | |||||
423 |
|
423 | |||
424 | class AutoMagicChecker(PrefilterChecker): |
|
424 | class AutoMagicChecker(PrefilterChecker): | |
425 |
|
425 | |||
426 | priority = Int(700) |
|
426 | priority = Int(700, config=True) | |
427 |
|
427 | |||
428 | def check(self, line_info): |
|
428 | def check(self, line_info): | |
429 | """If the ifun is magic, and automagic is on, run it. Note: normal, |
|
429 | """If the ifun is magic, and automagic is on, run it. Note: normal, | |
@@ -447,7 +447,7 b' class AutoMagicChecker(PrefilterChecker):' | |||||
447 |
|
447 | |||
448 | class AliasChecker(PrefilterChecker): |
|
448 | class AliasChecker(PrefilterChecker): | |
449 |
|
449 | |||
450 | priority = Int(800) |
|
450 | priority = Int(800, config=True) | |
451 |
|
451 | |||
452 | @auto_attr |
|
452 | @auto_attr | |
453 | def alias_manager(self): |
|
453 | def alias_manager(self): | |
@@ -467,7 +467,7 b' class AliasChecker(PrefilterChecker):' | |||||
467 |
|
467 | |||
468 | class PythonOpsChecker(PrefilterChecker): |
|
468 | class PythonOpsChecker(PrefilterChecker): | |
469 |
|
469 | |||
470 | priority = Int(900) |
|
470 | priority = Int(900, config=True) | |
471 |
|
471 | |||
472 | def check(self, line_info): |
|
472 | def check(self, line_info): | |
473 | """If the 'rest' of the line begins with a function call or pretty much |
|
473 | """If the 'rest' of the line begins with a function call or pretty much | |
@@ -482,7 +482,7 b' class PythonOpsChecker(PrefilterChecker):' | |||||
482 |
|
482 | |||
483 | class AutocallChecker(PrefilterChecker): |
|
483 | class AutocallChecker(PrefilterChecker): | |
484 |
|
484 | |||
485 | priority = Int(1000) |
|
485 | priority = Int(1000, config=True) | |
486 |
|
486 | |||
487 | def check(self, line_info): |
|
487 | def check(self, line_info): | |
488 | "Check if the initial word/function is callable and autocall is on." |
|
488 | "Check if the initial word/function is callable and autocall is on." | |
@@ -567,7 +567,7 b' class AliasHandler(PrefilterHandler):' | |||||
567 | transformed = self.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest) |
|
567 | transformed = self.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest) | |
568 | # pre is needed, because it carries the leading whitespace. Otherwise |
|
568 | # pre is needed, because it carries the leading whitespace. Otherwise | |
569 | # aliases won't work in indented sections. |
|
569 | # aliases won't work in indented sections. | |
570 | line_out = '%s_ip.system(%s)' % (line_info.pre_whitespace, |
|
570 | line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace, | |
571 | make_quoted_expr(transformed)) |
|
571 | make_quoted_expr(transformed)) | |
572 |
|
572 | |||
573 | self.shell.log(line_info.line, line_out, line_info.continue_prompt) |
|
573 | self.shell.log(line_info.line, line_out, line_info.continue_prompt) | |
@@ -597,7 +597,7 b' class ShellEscapeHandler(PrefilterHandler):' | |||||
597 | return magic_handler.handle(line_info) |
|
597 | return magic_handler.handle(line_info) | |
598 | else: |
|
598 | else: | |
599 | cmd = line.lstrip().lstrip(ESC_SHELL) |
|
599 | cmd = line.lstrip().lstrip(ESC_SHELL) | |
600 | line_out = '%s_ip.system(%s)' % (line_info.pre_whitespace, |
|
600 | line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace, | |
601 | make_quoted_expr(cmd)) |
|
601 | make_quoted_expr(cmd)) | |
602 | # update cache/log and return |
|
602 | # update cache/log and return | |
603 | self.shell.log(line, line_out, line_info.continue_prompt) |
|
603 | self.shell.log(line, line_out, line_info.continue_prompt) | |
@@ -607,13 +607,13 b' class ShellEscapeHandler(PrefilterHandler):' | |||||
607 | class MagicHandler(PrefilterHandler): |
|
607 | class MagicHandler(PrefilterHandler): | |
608 |
|
608 | |||
609 | handler_name = Str('magic') |
|
609 | handler_name = Str('magic') | |
610 |
esc_strings = List([ |
|
610 | esc_strings = List([ESC_MAGIC]) | |
611 |
|
611 | |||
612 | def handle(self, line_info): |
|
612 | def handle(self, line_info): | |
613 | """Execute magic functions.""" |
|
613 | """Execute magic functions.""" | |
614 | ifun = line_info.ifun |
|
614 | ifun = line_info.ifun | |
615 | the_rest = line_info.the_rest |
|
615 | the_rest = line_info.the_rest | |
616 | cmd = '%s_ip.magic(%s)' % (line_info.pre_whitespace, |
|
616 | cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace, | |
617 | make_quoted_expr(ifun + " " + the_rest)) |
|
617 | make_quoted_expr(ifun + " " + the_rest)) | |
618 | self.shell.log(line_info.line, cmd, line_info.continue_prompt) |
|
618 | self.shell.log(line_info.line, cmd, line_info.continue_prompt) | |
619 | return cmd |
|
619 | return cmd | |
@@ -656,7 +656,7 b' class AutoHandler(PrefilterHandler):' | |||||
656 | # We only apply it to argument-less calls if the autocall |
|
656 | # We only apply it to argument-less calls if the autocall | |
657 | # parameter is set to 2. We only need to check that autocall is < |
|
657 | # parameter is set to 2. We only need to check that autocall is < | |
658 | # 2, since this function isn't called unless it's at least 1. |
|
658 | # 2, since this function isn't called unless it's at least 1. | |
659 | if not the_rest and (self.autocall < 2) and not force_auto: |
|
659 | if not the_rest and (self.shell.autocall < 2) and not force_auto: | |
660 | newcmd = '%s %s' % (ifun,the_rest) |
|
660 | newcmd = '%s %s' % (ifun,the_rest) | |
661 | auto_rewrite = False |
|
661 | auto_rewrite = False | |
662 | else: |
|
662 | else: |
@@ -546,8 +546,11 b' class CachedOutput:' | |||||
546 | # don't use print, puts an extra space |
|
546 | # don't use print, puts an extra space | |
547 | cout_write(self.output_sep) |
|
547 | cout_write(self.output_sep) | |
548 | outprompt = self.shell.hooks.generate_output_prompt() |
|
548 | outprompt = self.shell.hooks.generate_output_prompt() | |
|
549 | # print "Got prompt: ", outprompt | |||
549 | if self.do_full_cache: |
|
550 | if self.do_full_cache: | |
550 | cout_write(outprompt) |
|
551 | cout_write(outprompt) | |
|
552 | else: | |||
|
553 | print "self.do_full_cache = False" | |||
551 |
|
554 | |||
552 | # and now call a possibly user-defined print mechanism |
|
555 | # and now call a possibly user-defined print mechanism | |
553 | manipulated_val = self.display(arg) |
|
556 | manipulated_val = self.display(arg) |
@@ -31,4 +31,5 b' class A(object):' | |||||
31 | a = A() |
|
31 | a = A() | |
32 |
|
32 | |||
33 | # Now, we force an exit, the caller will check that the del printout was given |
|
33 | # Now, we force an exit, the caller will check that the del printout was given | |
|
34 | _ip = get_ipython() | |||
34 | _ip.ask_exit() |
|
35 | _ip.ask_exit() |
@@ -26,7 +26,7 b' from IPython.core.component import Component, ComponentError' | |||||
26 | from IPython.utils.traitlets import ( |
|
26 | from IPython.utils.traitlets import ( | |
27 | TraitletError, Int, Float, Str |
|
27 | TraitletError, Int, Float, Str | |
28 | ) |
|
28 | ) | |
29 | from IPython.utils.ipstruct import Struct |
|
29 | from IPython.config.loader import Config | |
30 |
|
30 | |||
31 |
|
31 | |||
32 | #----------------------------------------------------------------------------- |
|
32 | #----------------------------------------------------------------------------- | |
@@ -138,9 +138,9 b' class TestComponentConfig(TestCase):' | |||||
138 | self.assertEquals(c2.config, c3.config) |
|
138 | self.assertEquals(c2.config, c3.config) | |
139 |
|
139 | |||
140 | def test_custom(self): |
|
140 | def test_custom(self): | |
141 |
config = |
|
141 | config = Config() | |
142 |
config. |
|
142 | config.foo = 'foo' | |
143 |
config. |
|
143 | config.bar = 'bar' | |
144 | c1 = Component(None, config=config) |
|
144 | c1 = Component(None, config=config) | |
145 | c2 = Component(c1) |
|
145 | c2 = Component(c1) | |
146 | c3 = Component(c2) |
|
146 | c3 = Component(c2) | |
@@ -156,19 +156,19 b' class TestComponentConfig(TestCase):' | |||||
156 |
|
156 | |||
157 | def test_inheritance(self): |
|
157 | def test_inheritance(self): | |
158 | class MyComponent(Component): |
|
158 | class MyComponent(Component): | |
159 |
a = Int(1, config |
|
159 | a = Int(1, config=True) | |
160 |
b = Float(1.0, config |
|
160 | b = Float(1.0, config=True) | |
161 | c = Str('no config') |
|
161 | c = Str('no config') | |
162 |
config = |
|
162 | config = Config() | |
163 |
config. |
|
163 | config.MyComponent.a = 2 | |
164 |
config. |
|
164 | config.MyComponent.b = 2.0 | |
165 | c1 = MyComponent(None, config=config) |
|
165 | c1 = MyComponent(None, config=config) | |
166 | c2 = MyComponent(c1) |
|
166 | c2 = MyComponent(c1) | |
167 |
self.assertEquals(c1.a, config. |
|
167 | self.assertEquals(c1.a, config.MyComponent.a) | |
168 |
self.assertEquals(c1.b, config. |
|
168 | self.assertEquals(c1.b, config.MyComponent.b) | |
169 |
self.assertEquals(c2.a, config. |
|
169 | self.assertEquals(c2.a, config.MyComponent.a) | |
170 |
self.assertEquals(c2.b, config. |
|
170 | self.assertEquals(c2.b, config.MyComponent.b) | |
171 |
c4 = MyComponent(c2, config= |
|
171 | c4 = MyComponent(c2, config=Config()) | |
172 | self.assertEquals(c4.a, 1) |
|
172 | self.assertEquals(c4.a, 1) | |
173 | self.assertEquals(c4.b, 1.0) |
|
173 | self.assertEquals(c4.b, 1.0) | |
174 |
|
174 |
@@ -20,14 +20,15 b' from IPython.testing import tools as tt' | |||||
20 |
|
20 | |||
21 | def test_rehashx(): |
|
21 | def test_rehashx(): | |
22 | # clear up everything |
|
22 | # clear up everything | |
23 | _ip.alias_table.clear() |
|
23 | _ip = get_ipython() | |
|
24 | _ip.alias_manager.alias_table.clear() | |||
24 | del _ip.db['syscmdlist'] |
|
25 | del _ip.db['syscmdlist'] | |
25 |
|
26 | |||
26 | _ip.magic('rehashx') |
|
27 | _ip.magic('rehashx') | |
27 | # Practically ALL ipython development systems will have more than 10 aliases |
|
28 | # Practically ALL ipython development systems will have more than 10 aliases | |
28 |
|
29 | |||
29 | yield (nt.assert_true, len(_ip.alias_table) > 10) |
|
30 | yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10) | |
30 | for key, val in _ip.alias_table.items(): |
|
31 | for key, val in _ip.alias_manager.alias_table.items(): | |
31 | # we must strip dots from alias names |
|
32 | # we must strip dots from alias names | |
32 | nt.assert_true('.' not in key) |
|
33 | nt.assert_true('.' not in key) | |
33 |
|
34 | |||
@@ -65,6 +66,7 b' def doctest_hist_r():' | |||||
65 | # This test is known to fail on win32. |
|
66 | # This test is known to fail on win32. | |
66 | # See ticket https://bugs.launchpad.net/bugs/366334 |
|
67 | # See ticket https://bugs.launchpad.net/bugs/366334 | |
67 | def test_obj_del(): |
|
68 | def test_obj_del(): | |
|
69 | _ip = get_ipython() | |||
68 | """Test that object's __del__ methods are called on exit.""" |
|
70 | """Test that object's __del__ methods are called on exit.""" | |
69 | test_dir = os.path.dirname(__file__) |
|
71 | test_dir = os.path.dirname(__file__) | |
70 | del_file = os.path.join(test_dir,'obj_del.py') |
|
72 | del_file = os.path.join(test_dir,'obj_del.py') | |
@@ -221,13 +223,14 b' class TestMagicRun(object):' | |||||
221 | self.fname = fname |
|
223 | self.fname = fname | |
222 |
|
224 | |||
223 | def run_tmpfile(self): |
|
225 | def run_tmpfile(self): | |
|
226 | _ip = get_ipython() | |||
224 | # This fails on Windows if self.tmpfile.name has spaces or "~" in it. |
|
227 | # This fails on Windows if self.tmpfile.name has spaces or "~" in it. | |
225 | # See below and ticket https://bugs.launchpad.net/bugs/366353 |
|
228 | # See below and ticket https://bugs.launchpad.net/bugs/366353 | |
226 | _ip.magic('run "%s"' % self.fname) |
|
229 | _ip.magic('run "%s"' % self.fname) | |
227 |
|
230 | |||
228 | def test_builtins_id(self): |
|
231 | def test_builtins_id(self): | |
229 | """Check that %run doesn't damage __builtins__ """ |
|
232 | """Check that %run doesn't damage __builtins__ """ | |
230 |
|
233 | _ip = get_ipython() | ||
231 | # Test that the id of __builtins__ is not modified by %run |
|
234 | # Test that the id of __builtins__ is not modified by %run | |
232 | bid1 = id(_ip.user_ns['__builtins__']) |
|
235 | bid1 = id(_ip.user_ns['__builtins__']) | |
233 | self.run_tmpfile() |
|
236 | self.run_tmpfile() | |
@@ -241,12 +244,14 b' class TestMagicRun(object):' | |||||
241 | be a dict (it should be a module) by a previous use of %run. So we |
|
244 | be a dict (it should be a module) by a previous use of %run. So we | |
242 | also check explicitly that it really is a module: |
|
245 | also check explicitly that it really is a module: | |
243 | """ |
|
246 | """ | |
|
247 | _ip = get_ipython() | |||
244 | self.run_tmpfile() |
|
248 | self.run_tmpfile() | |
245 | tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys)) |
|
249 | tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys)) | |
246 |
|
250 | |||
247 | def test_prompts(self): |
|
251 | def test_prompts(self): | |
248 | """Test that prompts correctly generate after %run""" |
|
252 | """Test that prompts correctly generate after %run""" | |
249 | self.run_tmpfile() |
|
253 | self.run_tmpfile() | |
|
254 | _ip = get_ipython() | |||
250 | p2 = str(_ip.outputcache.prompt2).strip() |
|
255 | p2 = str(_ip.outputcache.prompt2).strip() | |
251 | nt.assert_equals(p2[:3], '...') |
|
256 | nt.assert_equals(p2[:3], '...') | |
252 |
|
257 | |||
@@ -261,7 +266,7 b' class TestMagicRun(object):' | |||||
261 |
|
266 | |||
262 | # Multiple tests for clipboard pasting |
|
267 | # Multiple tests for clipboard pasting | |
263 | def test_paste(): |
|
268 | def test_paste(): | |
264 |
|
269 | _ip = get_ipython() | ||
265 | def paste(txt, flags='-q'): |
|
270 | def paste(txt, flags='-q'): | |
266 | """Paste input text, by default in quiet mode""" |
|
271 | """Paste input text, by default in quiet mode""" | |
267 | hooks.clipboard_get = lambda : txt |
|
272 | hooks.clipboard_get = lambda : txt |
@@ -21,14 +21,14 b' def hnd_magic(line,mo):' | |||||
21 | var = mo.group('varname') |
|
21 | var = mo.group('varname') | |
22 | cmd = mo.group('cmd') |
|
22 | cmd = mo.group('cmd') | |
23 | expr = make_quoted_expr(cmd) |
|
23 | expr = make_quoted_expr(cmd) | |
24 | return itpl('$var = _ip.magic($expr)') |
|
24 | return itpl('$var = get_ipython().magic($expr)') | |
25 |
|
25 | |||
26 | def hnd_syscmd(line,mo): |
|
26 | def hnd_syscmd(line,mo): | |
27 | """ Handle a = !ls """ |
|
27 | """ Handle a = !ls """ | |
28 | var = mo.group('varname') |
|
28 | var = mo.group('varname') | |
29 | cmd = mo.group('cmd') |
|
29 | cmd = mo.group('cmd') | |
30 | expr = make_quoted_expr(itpl("sc -l =$cmd")) |
|
30 | expr = make_quoted_expr(itpl("sc -l =$cmd")) | |
31 | return itpl('$var = _ip.magic($expr)') |
|
31 | return itpl('$var = get_ipython().magic($expr)') | |
32 |
|
32 | |||
33 | def install_re_handler(pat, hnd): |
|
33 | def install_re_handler(pat, hnd): | |
34 | ip.meta.re_prefilters.append((re.compile(pat), hnd)) |
|
34 | ip.meta.re_prefilters.append((re.compile(pat), hnd)) |
@@ -1644,7 +1644,7 b' class ialias(Table):' | |||||
1644 | def __iter__(self): |
|
1644 | def __iter__(self): | |
1645 | api = ipapi.get() |
|
1645 | api = ipapi.get() | |
1646 |
|
1646 | |||
1647 | for (name, (args, command)) in api.alias_table.iteritems(): |
|
1647 | for (name, (args, command)) in api.alias_manager.alias_table.iteritems(): | |
1648 | yield Alias(name, args, command) |
|
1648 | yield Alias(name, args, command) | |
1649 |
|
1649 | |||
1650 |
|
1650 |
@@ -109,7 +109,7 b' def main():' | |||||
109 | cmd = noext |
|
109 | cmd = noext | |
110 |
|
110 | |||
111 | key = mapper(cmd) |
|
111 | key = mapper(cmd) | |
112 | if key not in ip.alias_table: |
|
112 | if key not in ip.alias_manager.alias_table: | |
113 | # Dots will be removed from alias names, since ipython |
|
113 | # Dots will be removed from alias names, since ipython | |
114 | # assumes names with dots to be python code |
|
114 | # assumes names with dots to be python code | |
115 |
|
115 | |||
@@ -159,7 +159,7 b' def slash_prefilter_f(self,line):' | |||||
159 | """ |
|
159 | """ | |
160 | from IPython.utils import genutils |
|
160 | from IPython.utils import genutils | |
161 | if re.match('(?:[.~]|/[a-zA-Z_0-9]+)/', line): |
|
161 | if re.match('(?:[.~]|/[a-zA-Z_0-9]+)/', line): | |
162 | return "_ip.system(" + genutils.make_quoted_expr(line)+")" |
|
162 | return "get_ipython().system(" + genutils.make_quoted_expr(line)+")" | |
163 | raise TryNext |
|
163 | raise TryNext | |
164 |
|
164 | |||
165 | # XXX You do not need to understand the next function! |
|
165 | # XXX You do not need to understand the next function! |
@@ -88,7 +88,7 b' def rehashdir_f(self,arg):' | |||||
88 | if not arg: |
|
88 | if not arg: | |
89 | arg = '.' |
|
89 | arg = '.' | |
90 | path = map(os.path.abspath,arg.split(';')) |
|
90 | path = map(os.path.abspath,arg.split(';')) | |
91 | alias_table = self.shell.alias_table |
|
91 | alias_table = self.shell.alias_manager.alias_table | |
92 |
|
92 | |||
93 | if os.name == 'posix': |
|
93 | if os.name == 'posix': | |
94 | isexec = lambda fname:os.path.isfile(fname) and \ |
|
94 | isexec = lambda fname:os.path.isfile(fname) and \ |
@@ -126,8 +126,8 b' def jobctrl_prefilter_f(self,line):' | |||||
126 |
|
126 | |||
127 | line = ip.expand_aliases(fn,rest) |
|
127 | line = ip.expand_aliases(fn,rest) | |
128 | if not _jobq: |
|
128 | if not _jobq: | |
129 | return '_ip.startjob(%s)' % genutils.make_quoted_expr(line) |
|
129 | return 'get_ipython().startjob(%s)' % genutils.make_quoted_expr(line) | |
130 | return '_ip.jobq(%s)' % genutils.make_quoted_expr(line) |
|
130 | return 'get_ipython().jobq(%s)' % genutils.make_quoted_expr(line) | |
131 |
|
131 | |||
132 | raise TryNext |
|
132 | raise TryNext | |
133 |
|
133 |
@@ -157,6 +157,7 b" def magic_store(self, parameter_s=''):" | |||||
157 | obj = ip.user_ns[args[0]] |
|
157 | obj = ip.user_ns[args[0]] | |
158 | except KeyError: |
|
158 | except KeyError: | |
159 | # it might be an alias |
|
159 | # it might be an alias | |
|
160 | # This needs to be refactored to use the new AliasManager stuff. | |||
160 | if args[0] in self.alias_table: |
|
161 | if args[0] in self.alias_table: | |
161 | staliases = db.get('stored_aliases',{}) |
|
162 | staliases = db.get('stored_aliases',{}) | |
162 | staliases[ args[0] ] = self.alias_table[ args[0] ] |
|
163 | staliases[ args[0] ] = self.alias_table[ args[0] ] |
@@ -99,7 +99,7 b' def pxrunsource(self, source, filename="<input>", symbol="single"):' | |||||
99 | # Case 3 |
|
99 | # Case 3 | |
100 | # Because autopx is enabled, we now call executeAll or disable autopx if |
|
100 | # Because autopx is enabled, we now call executeAll or disable autopx if | |
101 | # %autopx or autopx has been called |
|
101 | # %autopx or autopx has been called | |
102 | if '_ip.magic("%autopx' in source or '_ip.magic("autopx' in source: |
|
102 | if 'get_ipython().magic("%autopx' in source or 'get_ipython().magic("autopx' in source: | |
103 | _disable_autopx(self) |
|
103 | _disable_autopx(self) | |
104 | return False |
|
104 | return False | |
105 | else: |
|
105 | else: |
@@ -353,14 +353,17 b' class TestHasTraitlets(TestCase):' | |||||
353 | class A(HasTraitlets): |
|
353 | class A(HasTraitlets): | |
354 | i = Int(config_key='VALUE1', other_thing='VALUE2') |
|
354 | i = Int(config_key='VALUE1', other_thing='VALUE2') | |
355 | f = Float(config_key='VALUE3', other_thing='VALUE2') |
|
355 | f = Float(config_key='VALUE3', other_thing='VALUE2') | |
|
356 | j = Int(0) | |||
356 | a = A() |
|
357 | a = A() | |
357 | self.assertEquals(a.traitlets(), dict(i=A.i, f=A.f)) |
|
358 | self.assertEquals(a.traitlets(), dict(i=A.i, f=A.f, j=A.j)) | |
358 | traitlets = a.traitlets(config_key=lambda v: True) |
|
|||
359 | self.assertEquals(traitlets, dict(i=A.i, f=A.f)) |
|
|||
360 | traitlets = a.traitlets(config_key='VALUE1', other_thing='VALUE2') |
|
359 | traitlets = a.traitlets(config_key='VALUE1', other_thing='VALUE2') | |
361 | self.assertEquals(traitlets, dict(i=A.i)) |
|
360 | self.assertEquals(traitlets, dict(i=A.i)) | |
362 | traitlets = a.traitlets('config_key') |
|
361 | ||
363 | self.assertEquals(traitlets, dict(i=A.i, f=A.f)) |
|
362 | # This passes, but it shouldn't because I am replicating a bug in | |
|
363 | # traits. | |||
|
364 | traitlets = a.traitlets(config_key=lambda v: True) | |||
|
365 | self.assertEquals(traitlets, dict(i=A.i, f=A.f, j=A.j)) | |||
|
366 | ||||
364 |
|
367 | |||
365 | #----------------------------------------------------------------------------- |
|
368 | #----------------------------------------------------------------------------- | |
366 | # Tests for specific traitlet types |
|
369 | # Tests for specific traitlet types |
@@ -458,19 +458,22 b' class HasTraitlets(object):' | |||||
458 | """Get a list of all the names of this classes traitlets.""" |
|
458 | """Get a list of all the names of this classes traitlets.""" | |
459 | return self.traitlets(**metadata).keys() |
|
459 | return self.traitlets(**metadata).keys() | |
460 |
|
460 | |||
461 |
def traitlets(self, * |
|
461 | def traitlets(self, **metadata): | |
462 | """Get a list of all the traitlets of this class. |
|
462 | """Get a list of all the traitlets of this class. | |
463 |
|
463 | |||
464 | The TraitletTypes returned don't know anything about the values |
|
464 | The TraitletTypes returned don't know anything about the values | |
465 | that the various HasTraitlet's instances are holding. |
|
465 | that the various HasTraitlet's instances are holding. | |
|
466 | ||||
|
467 | This follows the same algorithm as traits does and does not allow | |||
|
468 | for any simple way of specifying merely that a metadata name | |||
|
469 | exists, but has any value. This is because get_metadata returns | |||
|
470 | None if a metadata key doesn't exist. | |||
466 | """ |
|
471 | """ | |
467 | traitlets = dict([memb for memb in inspect.getmembers(self.__class__) if \ |
|
472 | traitlets = dict([memb for memb in inspect.getmembers(self.__class__) if \ | |
468 | isinstance(memb[1], TraitletType)]) |
|
473 | isinstance(memb[1], TraitletType)]) | |
469 | if len(metadata) == 0 and len(args) == 0: |
|
|||
470 | return traitlets |
|
|||
471 |
|
474 | |||
472 |
f |
|
475 | if len(metadata) == 0: | |
473 | metadata[meta_name] = lambda _: True |
|
476 | return traitlets | |
474 |
|
477 | |||
475 | for meta_name, meta_eval in metadata.items(): |
|
478 | for meta_name, meta_eval in metadata.items(): | |
476 | if type(meta_eval) is not FunctionType: |
|
479 | if type(meta_eval) is not FunctionType: |
General Comments 0
You need to be logged in to leave comments.
Login now