##// END OF EJS Templates
Work on ipcontroller....
Brian Granger -
Show More
@@ -1,334 +1,430 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 An application for IPython
4 An application for IPython
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez
9 * Fernando Perez
10
10
11 Notes
11 Notes
12 -----
12 -----
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2009 The IPython Development Team
16 # Copyright (C) 2008-2009 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 import logging
26 import logging
27 import os
27 import os
28
28 import sys
29 import sys
29 import traceback
30 import traceback
30 from copy import deepcopy
31 from copy import deepcopy
31
32
33 from IPython.core import release
32 from IPython.utils.genutils import get_ipython_dir, filefind
34 from IPython.utils.genutils import get_ipython_dir, filefind
33 from IPython.config.loader import (
35 from IPython.config.loader import (
34 PyFileConfigLoader,
36 PyFileConfigLoader,
35 ArgParseConfigLoader,
37 ArgParseConfigLoader,
36 Config,
38 Config,
37 NoConfigDefault
39 NoConfigDefault
38 )
40 )
39
41
40 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
41 # Classes and functions
43 # Classes and functions
42 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
43
45
44
46
45 class IPythonArgParseConfigLoader(ArgParseConfigLoader):
47 class BaseAppArgParseConfigLoader(ArgParseConfigLoader):
46 """Default command line options for IPython based applications."""
48 """Default command line options for IPython based applications."""
47
49
48 def _add_other_arguments(self):
50 def _add_other_arguments(self):
49 self.parser.add_argument('-ipythondir', '--ipython-dir',
51 self.parser.add_argument('-ipythondir', '--ipython-dir',
50 dest='Global.ipythondir',type=str,
52 dest='Global.ipythondir',type=str,
51 help='Set to override default location of Global.ipythondir.',
53 help='Set to override default location of Global.ipythondir.',
52 default=NoConfigDefault,
54 default=NoConfigDefault,
53 metavar='Global.ipythondir')
55 metavar='Global.ipythondir')
54 self.parser.add_argument('-p','-profile', '--profile',
56 self.parser.add_argument('-p','-profile', '--profile',
55 dest='Global.profile',type=str,
57 dest='Global.profile',type=str,
56 help='The string name of the ipython profile to be used.',
58 help='The string name of the ipython profile to be used.',
57 default=NoConfigDefault,
59 default=NoConfigDefault,
58 metavar='Global.profile')
60 metavar='Global.profile')
59 self.parser.add_argument('-log_level', '--log-level',
61 self.parser.add_argument('-log_level', '--log-level',
60 dest="Global.log_level",type=int,
62 dest="Global.log_level",type=int,
61 help='Set the log level (0,10,20,30,40,50). Default is 30.',
63 help='Set the log level (0,10,20,30,40,50). Default is 30.',
62 default=NoConfigDefault)
64 default=NoConfigDefault)
63 self.parser.add_argument('-config_file', '--config-file',
65 self.parser.add_argument('-config_file', '--config-file',
64 dest='Global.config_file',type=str,
66 dest='Global.config_file',type=str,
65 help='Set the config file name to override default.',
67 help='Set the config file name to override default.',
66 default=NoConfigDefault,
68 default=NoConfigDefault,
67 metavar='Global.config_file')
69 metavar='Global.config_file')
68
70
69
71
70 class ApplicationError(Exception):
72 class ApplicationError(Exception):
71 pass
73 pass
72
74
73
75
74 class Application(object):
76 class Application(object):
75 """Load a config, construct an app and run it.
77 """Load a config, construct an app and run it.
76 """
78 """
77
79
78 config_file_name = 'ipython_config.py'
80 config_file_name = 'ipython_config.py'
79 name = 'ipython'
81 name = 'ipython'
82 description = 'IPython: an enhanced interactive Python shell.'
80 default_log_level = logging.WARN
83 default_log_level = logging.WARN
81
84
82
85
83 def __init__(self):
86 def __init__(self):
84 self.init_logger()
87 self.init_logger()
85 self.default_config_file_name = self.config_file_name
88 self.default_config_file_name = self.config_file_name
86
89
87 def init_logger(self):
90 def init_logger(self):
88 self.log = logging.getLogger(self.__class__.__name__)
91 self.log = logging.getLogger(self.__class__.__name__)
89 # This is used as the default until the command line arguments are read.
92 # This is used as the default until the command line arguments are read.
90 self.log.setLevel(self.default_log_level)
93 self.log.setLevel(self.default_log_level)
91 self._log_handler = logging.StreamHandler()
94 self._log_handler = logging.StreamHandler()
92 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
95 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
93 self._log_handler.setFormatter(self._log_formatter)
96 self._log_handler.setFormatter(self._log_formatter)
94 self.log.addHandler(self._log_handler)
97 self.log.addHandler(self._log_handler)
95
98
96 def _set_log_level(self, level):
99 def _set_log_level(self, level):
97 self.log.setLevel(level)
100 self.log.setLevel(level)
98
101
99 def _get_log_level(self):
102 def _get_log_level(self):
100 return self.log.level
103 return self.log.level
101
104
102 log_level = property(_get_log_level, _set_log_level)
105 log_level = property(_get_log_level, _set_log_level)
103
106
104 def start(self):
107 def start(self):
105 """Start the application."""
108 """Start the application."""
106 self.attempt(self.create_default_config)
109 self.attempt(self.create_default_config)
107 self.log_default_config()
110 self.log_default_config()
108 self.set_default_config_log_level()
111 self.set_default_config_log_level()
109 self.attempt(self.pre_load_command_line_config)
112 self.attempt(self.pre_load_command_line_config)
110 self.attempt(self.load_command_line_config, action='abort')
113 self.attempt(self.load_command_line_config, action='abort')
111 self.set_command_line_config_log_level()
114 self.set_command_line_config_log_level()
112 self.attempt(self.post_load_command_line_config)
115 self.attempt(self.post_load_command_line_config)
113 self.log_command_line_config()
116 self.log_command_line_config()
114 self.attempt(self.find_ipythondir)
117 self.attempt(self.find_ipythondir)
115 self.attempt(self.find_config_file_name)
118 self.attempt(self.find_config_file_name)
116 self.attempt(self.find_config_file_paths)
119 self.attempt(self.find_config_file_paths)
117 self.attempt(self.pre_load_file_config)
120 self.attempt(self.pre_load_file_config)
118 self.attempt(self.load_file_config)
121 self.attempt(self.load_file_config)
119 self.set_file_config_log_level()
122 self.set_file_config_log_level()
120 self.attempt(self.post_load_file_config)
123 self.attempt(self.post_load_file_config)
121 self.log_file_config()
124 self.log_file_config()
122 self.attempt(self.merge_configs)
125 self.attempt(self.merge_configs)
123 self.log_master_config()
126 self.log_master_config()
124 self.attempt(self.pre_construct)
127 self.attempt(self.pre_construct)
125 self.attempt(self.construct)
128 self.attempt(self.construct)
126 self.attempt(self.post_construct)
129 self.attempt(self.post_construct)
127 self.attempt(self.start_app)
130 self.attempt(self.start_app)
128
131
129 #-------------------------------------------------------------------------
132 #-------------------------------------------------------------------------
130 # Various stages of Application creation
133 # Various stages of Application creation
131 #-------------------------------------------------------------------------
134 #-------------------------------------------------------------------------
132
135
133 def create_default_config(self):
136 def create_default_config(self):
134 """Create defaults that can't be set elsewhere.
137 """Create defaults that can't be set elsewhere.
135
138
136 For the most part, we try to set default in the class attributes
139 For the most part, we try to set default in the class attributes
137 of Components. But, defaults the top-level Application (which is
140 of Components. But, defaults the top-level Application (which is
138 not a HasTraitlets or Component) are not set in this way. Instead
141 not a HasTraitlets or Component) are not set in this way. Instead
139 we set them here. The Global section is for variables like this that
142 we set them here. The Global section is for variables like this that
140 don't belong to a particular component.
143 don't belong to a particular component.
141 """
144 """
142 self.default_config = Config()
145 self.default_config = Config()
143 self.default_config.Global.ipythondir = get_ipython_dir()
146 self.default_config.Global.ipythondir = get_ipython_dir()
147 self.default_config.Global.log_level = self.log_level
144
148
145 def log_default_config(self):
149 def log_default_config(self):
146 self.log.debug('Default config loaded:')
150 self.log.debug('Default config loaded:')
147 self.log.debug(repr(self.default_config))
151 self.log.debug(repr(self.default_config))
148
152
149 def set_default_config_log_level(self):
153 def set_default_config_log_level(self):
150 try:
154 try:
151 self.log_level = self.default_config.Global.log_level
155 self.log_level = self.default_config.Global.log_level
152 except AttributeError:
156 except AttributeError:
153 # Fallback to the default_log_level class attribute
157 # Fallback to the default_log_level class attribute
154 pass
158 pass
155
159
156 def create_command_line_config(self):
160 def create_command_line_config(self):
157 """Create and return a command line config loader."""
161 """Create and return a command line config loader."""
158 return IPythonArgParseConfigLoader(description=self.name)
162 return BaseAppArgParseConfigLoader(
163 description=self.description,
164 version=release.version
165 )
159
166
160 def pre_load_command_line_config(self):
167 def pre_load_command_line_config(self):
161 """Do actions just before loading the command line config."""
168 """Do actions just before loading the command line config."""
162 pass
169 pass
163
170
164 def load_command_line_config(self):
171 def load_command_line_config(self):
165 """Load the command line config."""
172 """Load the command line config."""
166 loader = self.create_command_line_config()
173 loader = self.create_command_line_config()
167 self.command_line_config = loader.load_config()
174 self.command_line_config = loader.load_config()
168 self.extra_args = loader.get_extra_args()
175 self.extra_args = loader.get_extra_args()
169
176
170 def set_command_line_config_log_level(self):
177 def set_command_line_config_log_level(self):
171 try:
178 try:
172 self.log_level = self.command_line_config.Global.log_level
179 self.log_level = self.command_line_config.Global.log_level
173 except AttributeError:
180 except AttributeError:
174 pass
181 pass
175
182
176 def post_load_command_line_config(self):
183 def post_load_command_line_config(self):
177 """Do actions just after loading the command line config."""
184 """Do actions just after loading the command line config."""
178 pass
185 pass
179
186
180 def log_command_line_config(self):
187 def log_command_line_config(self):
181 self.log.debug("Command line config loaded:")
188 self.log.debug("Command line config loaded:")
182 self.log.debug(repr(self.command_line_config))
189 self.log.debug(repr(self.command_line_config))
183
190
184 def find_ipythondir(self):
191 def find_ipythondir(self):
185 """Set the IPython directory.
192 """Set the IPython directory.
186
193
187 This sets ``self.ipythondir``, but the actual value that is passed
194 This sets ``self.ipythondir``, but the actual value that is passed
188 to the application is kept in either ``self.default_config`` or
195 to the application is kept in either ``self.default_config`` or
189 ``self.command_line_config``. This also added ``self.ipythondir`` to
196 ``self.command_line_config``. This also added ``self.ipythondir`` to
190 ``sys.path`` so config files there can be references by other config
197 ``sys.path`` so config files there can be references by other config
191 files.
198 files.
192 """
199 """
193
200
194 try:
201 try:
195 self.ipythondir = self.command_line_config.Global.ipythondir
202 self.ipythondir = self.command_line_config.Global.ipythondir
196 except AttributeError:
203 except AttributeError:
197 self.ipythondir = self.default_config.Global.ipythondir
204 self.ipythondir = self.default_config.Global.ipythondir
198 sys.path.append(os.path.abspath(self.ipythondir))
205 sys.path.append(os.path.abspath(self.ipythondir))
199 if not os.path.isdir(self.ipythondir):
206 if not os.path.isdir(self.ipythondir):
200 os.makedirs(self.ipythondir, mode=0777)
207 os.makedirs(self.ipythondir, mode=0777)
201 self.log.debug("IPYTHONDIR set to: %s" % self.ipythondir)
208 self.log.debug("IPYTHONDIR set to: %s" % self.ipythondir)
202
209
203 def find_config_file_name(self):
210 def find_config_file_name(self):
204 """Find the config file name for this application.
211 """Find the config file name for this application.
205
212
206 This must set ``self.config_file_name`` to the filename of the
213 This must set ``self.config_file_name`` to the filename of the
207 config file to use (just the filename). The search paths for the
214 config file to use (just the filename). The search paths for the
208 config file are set in :meth:`find_config_file_paths` and then passed
215 config file are set in :meth:`find_config_file_paths` and then passed
209 to the config file loader where they are resolved to an absolute path.
216 to the config file loader where they are resolved to an absolute path.
210
217
211 If a profile has been set at the command line, this will resolve
218 If a profile has been set at the command line, this will resolve
212 it.
219 it.
213 """
220 """
214
221
215 try:
222 try:
216 self.config_file_name = self.command_line_config.Global.config_file
223 self.config_file_name = self.command_line_config.Global.config_file
217 except AttributeError:
224 except AttributeError:
218 pass
225 pass
219
226
220 try:
227 try:
221 self.profile_name = self.command_line_config.Global.profile
228 self.profile_name = self.command_line_config.Global.profile
222 name_parts = self.config_file_name.split('.')
229 name_parts = self.config_file_name.split('.')
223 name_parts.insert(1, '_' + self.profile_name + '.')
230 name_parts.insert(1, '_' + self.profile_name + '.')
224 self.config_file_name = ''.join(name_parts)
231 self.config_file_name = ''.join(name_parts)
225 except AttributeError:
232 except AttributeError:
226 pass
233 pass
227
234
228 def find_config_file_paths(self):
235 def find_config_file_paths(self):
229 """Set the search paths for resolving the config file.
236 """Set the search paths for resolving the config file.
230
237
231 This must set ``self.config_file_paths`` to a sequence of search
238 This must set ``self.config_file_paths`` to a sequence of search
232 paths to pass to the config file loader.
239 paths to pass to the config file loader.
233 """
240 """
234 self.config_file_paths = (os.getcwd(), self.ipythondir)
241 self.config_file_paths = (os.getcwd(), self.ipythondir)
235
242
236 def pre_load_file_config(self):
243 def pre_load_file_config(self):
237 """Do actions before the config file is loaded."""
244 """Do actions before the config file is loaded."""
238 pass
245 pass
239
246
240 def load_file_config(self):
247 def load_file_config(self):
241 """Load the config file.
248 """Load the config file.
242
249
243 This tries to load the config file from disk. If successful, the
250 This tries to load the config file from disk. If successful, the
244 ``CONFIG_FILE`` config variable is set to the resolved config file
251 ``CONFIG_FILE`` config variable is set to the resolved config file
245 location. If not successful, an empty config is used.
252 location. If not successful, an empty config is used.
246 """
253 """
247 self.log.debug("Attempting to load config file: <%s>" % self.config_file_name)
254 self.log.debug("Attempting to load config file: <%s>" % self.config_file_name)
248 loader = PyFileConfigLoader(self.config_file_name,
255 loader = PyFileConfigLoader(self.config_file_name,
249 path=self.config_file_paths)
256 path=self.config_file_paths)
250 try:
257 try:
251 self.file_config = loader.load_config()
258 self.file_config = loader.load_config()
252 self.file_config.Global.config_file = loader.full_filename
259 self.file_config.Global.config_file = loader.full_filename
253 except IOError:
260 except IOError:
254 # Only warn if the default config file was NOT being used.
261 # Only warn if the default config file was NOT being used.
255 if not self.config_file_name==self.default_config_file_name:
262 if not self.config_file_name==self.default_config_file_name:
256 self.log.warn("Config file not found, skipping: <%s>" % \
263 self.log.warn("Config file not found, skipping: <%s>" % \
257 self.config_file_name, exc_info=True)
264 self.config_file_name, exc_info=True)
258 self.file_config = Config()
265 self.file_config = Config()
259 except:
266 except:
260 self.log.warn("Error loading config file: <%s>" % \
267 self.log.warn("Error loading config file: <%s>" % \
261 self.config_file_name, exc_info=True)
268 self.config_file_name, exc_info=True)
262 self.file_config = Config()
269 self.file_config = Config()
263
270
264 def set_file_config_log_level(self):
271 def set_file_config_log_level(self):
265 # We need to keeep self.log_level updated. But we only use the value
272 # We need to keeep self.log_level updated. But we only use the value
266 # of the file_config if a value was not specified at the command
273 # of the file_config if a value was not specified at the command
267 # line, because the command line overrides everything.
274 # line, because the command line overrides everything.
268 if not hasattr(self.command_line_config.Global, 'log_level'):
275 if not hasattr(self.command_line_config.Global, 'log_level'):
269 try:
276 try:
270 self.log_level = self.file_config.Global.log_level
277 self.log_level = self.file_config.Global.log_level
271 except AttributeError:
278 except AttributeError:
272 pass # Use existing value
279 pass # Use existing value
273
280
274 def post_load_file_config(self):
281 def post_load_file_config(self):
275 """Do actions after the config file is loaded."""
282 """Do actions after the config file is loaded."""
276 pass
283 pass
277
284
278 def log_file_config(self):
285 def log_file_config(self):
279 if hasattr(self.file_config.Global, 'config_file'):
286 if hasattr(self.file_config.Global, 'config_file'):
280 self.log.debug("Config file loaded: <%s>" % self.file_config.Global.config_file)
287 self.log.debug("Config file loaded: <%s>" % self.file_config.Global.config_file)
281 self.log.debug(repr(self.file_config))
288 self.log.debug(repr(self.file_config))
282
289
283 def merge_configs(self):
290 def merge_configs(self):
284 """Merge the default, command line and file config objects."""
291 """Merge the default, command line and file config objects."""
285 config = Config()
292 config = Config()
286 config._merge(self.default_config)
293 config._merge(self.default_config)
287 config._merge(self.file_config)
294 config._merge(self.file_config)
288 config._merge(self.command_line_config)
295 config._merge(self.command_line_config)
289 self.master_config = config
296 self.master_config = config
290
297
291 def log_master_config(self):
298 def log_master_config(self):
292 self.log.debug("Master config created:")
299 self.log.debug("Master config created:")
293 self.log.debug(repr(self.master_config))
300 self.log.debug(repr(self.master_config))
294
301
295 def pre_construct(self):
302 def pre_construct(self):
296 """Do actions after the config has been built, but before construct."""
303 """Do actions after the config has been built, but before construct."""
297 pass
304 pass
298
305
299 def construct(self):
306 def construct(self):
300 """Construct the main components that make up this app."""
307 """Construct the main components that make up this app."""
301 self.log.debug("Constructing components for application")
308 self.log.debug("Constructing components for application")
302
309
303 def post_construct(self):
310 def post_construct(self):
304 """Do actions after construct, but before starting the app."""
311 """Do actions after construct, but before starting the app."""
305 pass
312 pass
306
313
307 def start_app(self):
314 def start_app(self):
308 """Actually start the app."""
315 """Actually start the app."""
309 self.log.debug("Starting application")
316 self.log.debug("Starting application")
310
317
311 #-------------------------------------------------------------------------
318 #-------------------------------------------------------------------------
312 # Utility methods
319 # Utility methods
313 #-------------------------------------------------------------------------
320 #-------------------------------------------------------------------------
314
321
315 def abort(self):
322 def abort(self):
316 """Abort the starting of the application."""
323 """Abort the starting of the application."""
317 self.log.critical("Aborting application: %s" % self.name, exc_info=True)
324 self.log.critical("Aborting application: %s" % self.name, exc_info=True)
318 sys.exit(1)
325 sys.exit(1)
319
326
320 def exit(self):
327 def exit(self):
321 self.log.critical("Aborting application: %s" % self.name)
328 self.log.critical("Aborting application: %s" % self.name)
322 sys.exit(1)
329 sys.exit(1)
323
330
324 def attempt(self, func, action='abort'):
331 def attempt(self, func, action='abort'):
325 try:
332 try:
326 func()
333 func()
327 except SystemExit:
334 except SystemExit:
328 self.exit()
335 self.exit()
329 except:
336 except:
330 if action == 'abort':
337 if action == 'abort':
331 self.abort()
338 self.abort()
332 elif action == 'exit':
339 elif action == 'exit':
333 self.exit()
340 self.exit()
334 No newline at end of file
341
342
343 class AppWithDirArgParseConfigLoader(ArgParseConfigLoader):
344 """Default command line options for IPython based applications."""
345
346 def _add_other_arguments(self):
347 self.parser.add_argument('-ipythondir', '--ipython-dir',
348 dest='Global.ipythondir',type=str,
349 help='Set to override default location of Global.ipythondir.',
350 default=NoConfigDefault,
351 metavar='Global.ipythondir')
352 self.parser.add_argument('-p','-profile', '--profile',
353 dest='Global.profile',type=str,
354 help='The string name of the ipython profile to be used.',
355 default=NoConfigDefault,
356 metavar='Global.profile')
357 self.parser.add_argument('-log_level', '--log-level',
358 dest="Global.log_level",type=int,
359 help='Set the log level (0,10,20,30,40,50). Default is 30.',
360 default=NoConfigDefault)
361 self.parser.add_argument('-app_dir', '--app-dir',
362 dest='Global.app_dir',type=str,
363 help='Set the application directory where everything for this '
364 'application will be found (including the config file).',
365 default=NoConfigDefault,
366 metavar='Global.app_dir')
367
368
369 class ApplicationWithDir(Application):
370
371 name = 'appname'
372 description = 'Application: foo and bar it.'
373 config_file_name = 'appname_config.py'
374 default_log_level = logging.WARN
375
376 def create_default_config(self):
377 super(ApplicationWithDir, self).create_default_config()
378 self.default_config.Global.profile = 'default'
379 self.default_config.Global.app_dir = ''
380
381 def create_command_line_config(self):
382 """Create and return a command line config loader."""
383 return AppWithDirArgParseConfigLoader(
384 description=self.description,
385 version=release.version
386 )
387
388 def find_config_file_name(self):
389 """Find the config file name for this application."""
390 self.find_app_dir()
391 self.create_app_dir()
392
393 def find_app_dir(self):
394 """This resolves into full paths, the app directory.
395
396 This method must set ``self.app_dir`` to the full path of
397 the directory.
398 """
399 # Instead, first look for an explicit app_dir
400 try:
401 self.app_dir = self.command_line_config.Global.app_dir
402 except AttributeError:
403 self.app_dir = self.default_config.Global.app_dir
404 self.app_dir = os.path.expandvars(os.path.expanduser(self.app_dir))
405 if not self.app_dir:
406 # Then look for a profile
407 try:
408 self.profile = self.command_line_config.Global.profile
409 except AttributeError:
410 self.profile = self.default_config.Global.profile
411 app_dir_name = 'cluster_' + self.profile
412 try_this = os.path.join(os.getcwd(), app_dir_name)
413 if os.path.isdir(try_this):
414 self.app_dir = try_this
415 else:
416 self.app_dir = os.path.join(self.ipythondir, app_dir_name)
417 # These have to be set because they could be different from the one
418 # that we just computed. Because command line has the highest
419 # priority, this will always end up in the master_config.
420 self.default_config.Global.app_dir = self.app_dir
421 self.command_line_config.Global.app_dir = self.app_dir
422
423 def create_app_dir(self):
424 """Make sure that the cluster, security and log dirs exist."""
425 if not os.path.isdir(self.app_dir):
426 os.makedirs(self.app_dir, mode=0777)
427
428 def find_config_file_paths(self):
429 """Set the search paths for resolving the config file."""
430 self.config_file_paths = (self.app_dir,)
@@ -1,546 +1,545 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The main IPython application object
4 The main IPython application object
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez
9 * Fernando Perez
10
10
11 Notes
11 Notes
12 -----
12 -----
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2009 The IPython Development Team
16 # Copyright (C) 2008-2009 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 import logging
26 import logging
27 import os
27 import os
28 import sys
28 import sys
29 import warnings
29 import warnings
30
30
31 from IPython.core.application import Application, IPythonArgParseConfigLoader
31 from IPython.core.application import Application, BaseAppArgParseConfigLoader
32 from IPython.core import release
32 from IPython.core import release
33 from IPython.core.iplib import InteractiveShell
33 from IPython.core.iplib import InteractiveShell
34 from IPython.config.loader import (
34 from IPython.config.loader import (
35 NoConfigDefault,
35 NoConfigDefault,
36 Config,
36 Config,
37 ConfigError,
37 ConfigError,
38 PyFileConfigLoader
38 PyFileConfigLoader
39 )
39 )
40
40
41 from IPython.lib import inputhook
41 from IPython.lib import inputhook
42
42
43 from IPython.utils.ipstruct import Struct
43 from IPython.utils.ipstruct import Struct
44 from IPython.utils.genutils import filefind, get_ipython_dir
44 from IPython.utils.genutils import filefind, get_ipython_dir
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Utilities and helpers
47 # Utilities and helpers
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50
50
51 ipython_desc = """
51 ipython_desc = """
52 A Python shell with automatic history (input and output), dynamic object
52 A Python shell with automatic history (input and output), dynamic object
53 introspection, easier configuration, command completion, access to the system
53 introspection, easier configuration, command completion, access to the system
54 shell and more.
54 shell and more.
55 """
55 """
56
56
57 def pylab_warning():
57 def pylab_warning():
58 msg = """
58 msg = """
59
59
60 IPython's -pylab mode has been disabled until matplotlib supports this version
60 IPython's -pylab mode has been disabled until matplotlib supports this version
61 of IPython. This version of IPython has greatly improved GUI integration that
61 of IPython. This version of IPython has greatly improved GUI integration that
62 matplotlib will soon be able to take advantage of. This will eventually
62 matplotlib will soon be able to take advantage of. This will eventually
63 result in greater stability and a richer API for matplotlib under IPython.
63 result in greater stability and a richer API for matplotlib under IPython.
64 However during this transition, you will either need to use an older version
64 However during this transition, you will either need to use an older version
65 of IPython, or do the following to use matplotlib interactively::
65 of IPython, or do the following to use matplotlib interactively::
66
66
67 import matplotlib
67 import matplotlib
68 matplotlib.interactive(True)
68 matplotlib.interactive(True)
69 matplotlib.use('wxagg') # adjust for your backend
69 matplotlib.use('wxagg') # adjust for your backend
70 %gui -a wx # adjust for your GUI
70 %gui -a wx # adjust for your GUI
71 from matplotlib import pyplot as plt
71 from matplotlib import pyplot as plt
72
72
73 See the %gui magic for information on the new interface.
73 See the %gui magic for information on the new interface.
74 """
74 """
75 warnings.warn(msg, category=DeprecationWarning, stacklevel=1)
75 warnings.warn(msg, category=DeprecationWarning, stacklevel=1)
76
76
77
77
78 #-----------------------------------------------------------------------------
78 #-----------------------------------------------------------------------------
79 # Main classes and functions
79 # Main classes and functions
80 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
81
81
82 cl_args = (
82 cl_args = (
83 (('-autocall',), dict(
83 (('-autocall',), dict(
84 type=int, dest='InteractiveShell.autocall', default=NoConfigDefault,
84 type=int, dest='InteractiveShell.autocall', default=NoConfigDefault,
85 help='Set the autocall value (0,1,2).',
85 help='Set the autocall value (0,1,2).',
86 metavar='InteractiveShell.autocall')
86 metavar='InteractiveShell.autocall')
87 ),
87 ),
88 (('-autoindent',), dict(
88 (('-autoindent',), dict(
89 action='store_true', dest='InteractiveShell.autoindent', default=NoConfigDefault,
89 action='store_true', dest='InteractiveShell.autoindent', default=NoConfigDefault,
90 help='Turn on autoindenting.')
90 help='Turn on autoindenting.')
91 ),
91 ),
92 (('-noautoindent',), dict(
92 (('-noautoindent',), dict(
93 action='store_false', dest='InteractiveShell.autoindent', default=NoConfigDefault,
93 action='store_false', dest='InteractiveShell.autoindent', default=NoConfigDefault,
94 help='Turn off autoindenting.')
94 help='Turn off autoindenting.')
95 ),
95 ),
96 (('-automagic',), dict(
96 (('-automagic',), dict(
97 action='store_true', dest='InteractiveShell.automagic', default=NoConfigDefault,
97 action='store_true', dest='InteractiveShell.automagic', default=NoConfigDefault,
98 help='Turn on the auto calling of magic commands.')
98 help='Turn on the auto calling of magic commands.')
99 ),
99 ),
100 (('-noautomagic',), dict(
100 (('-noautomagic',), dict(
101 action='store_false', dest='InteractiveShell.automagic', default=NoConfigDefault,
101 action='store_false', dest='InteractiveShell.automagic', default=NoConfigDefault,
102 help='Turn off the auto calling of magic commands.')
102 help='Turn off the auto calling of magic commands.')
103 ),
103 ),
104 (('-autoedit_syntax',), dict(
104 (('-autoedit_syntax',), dict(
105 action='store_true', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault,
105 action='store_true', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault,
106 help='Turn on auto editing of files with syntax errors.')
106 help='Turn on auto editing of files with syntax errors.')
107 ),
107 ),
108 (('-noautoedit_syntax',), dict(
108 (('-noautoedit_syntax',), dict(
109 action='store_false', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault,
109 action='store_false', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault,
110 help='Turn off auto editing of files with syntax errors.')
110 help='Turn off auto editing of files with syntax errors.')
111 ),
111 ),
112 (('-banner',), dict(
112 (('-banner',), dict(
113 action='store_true', dest='Global.display_banner', default=NoConfigDefault,
113 action='store_true', dest='Global.display_banner', default=NoConfigDefault,
114 help='Display a banner upon starting IPython.')
114 help='Display a banner upon starting IPython.')
115 ),
115 ),
116 (('-nobanner',), dict(
116 (('-nobanner',), dict(
117 action='store_false', dest='Global.display_banner', default=NoConfigDefault,
117 action='store_false', dest='Global.display_banner', default=NoConfigDefault,
118 help="Don't display a banner upon starting IPython.")
118 help="Don't display a banner upon starting IPython.")
119 ),
119 ),
120 (('-cache_size',), dict(
120 (('-cache_size',), dict(
121 type=int, dest='InteractiveShell.cache_size', default=NoConfigDefault,
121 type=int, dest='InteractiveShell.cache_size', default=NoConfigDefault,
122 help="Set the size of the output cache.",
122 help="Set the size of the output cache.",
123 metavar='InteractiveShell.cache_size')
123 metavar='InteractiveShell.cache_size')
124 ),
124 ),
125 (('-classic',), dict(
125 (('-classic',), dict(
126 action='store_true', dest='Global.classic', default=NoConfigDefault,
126 action='store_true', dest='Global.classic', default=NoConfigDefault,
127 help="Gives IPython a similar feel to the classic Python prompt.")
127 help="Gives IPython a similar feel to the classic Python prompt.")
128 ),
128 ),
129 (('-colors',), dict(
129 (('-colors',), dict(
130 type=str, dest='InteractiveShell.colors', default=NoConfigDefault,
130 type=str, dest='InteractiveShell.colors', default=NoConfigDefault,
131 help="Set the color scheme (NoColor, Linux, and LightBG).",
131 help="Set the color scheme (NoColor, Linux, and LightBG).",
132 metavar='InteractiveShell.colors')
132 metavar='InteractiveShell.colors')
133 ),
133 ),
134 (('-color_info',), dict(
134 (('-color_info',), dict(
135 action='store_true', dest='InteractiveShell.color_info', default=NoConfigDefault,
135 action='store_true', dest='InteractiveShell.color_info', default=NoConfigDefault,
136 help="Enable using colors for info related things.")
136 help="Enable using colors for info related things.")
137 ),
137 ),
138 (('-nocolor_info',), dict(
138 (('-nocolor_info',), dict(
139 action='store_false', dest='InteractiveShell.color_info', default=NoConfigDefault,
139 action='store_false', dest='InteractiveShell.color_info', default=NoConfigDefault,
140 help="Disable using colors for info related things.")
140 help="Disable using colors for info related things.")
141 ),
141 ),
142 (('-confirm_exit',), dict(
142 (('-confirm_exit',), dict(
143 action='store_true', dest='InteractiveShell.confirm_exit', default=NoConfigDefault,
143 action='store_true', dest='InteractiveShell.confirm_exit', default=NoConfigDefault,
144 help="Prompt the user when existing.")
144 help="Prompt the user when existing.")
145 ),
145 ),
146 (('-noconfirm_exit',), dict(
146 (('-noconfirm_exit',), dict(
147 action='store_false', dest='InteractiveShell.confirm_exit', default=NoConfigDefault,
147 action='store_false', dest='InteractiveShell.confirm_exit', default=NoConfigDefault,
148 help="Don't prompt the user when existing.")
148 help="Don't prompt the user when existing.")
149 ),
149 ),
150 (('-deep_reload',), dict(
150 (('-deep_reload',), dict(
151 action='store_true', dest='InteractiveShell.deep_reload', default=NoConfigDefault,
151 action='store_true', dest='InteractiveShell.deep_reload', default=NoConfigDefault,
152 help="Enable deep (recursive) reloading by default.")
152 help="Enable deep (recursive) reloading by default.")
153 ),
153 ),
154 (('-nodeep_reload',), dict(
154 (('-nodeep_reload',), dict(
155 action='store_false', dest='InteractiveShell.deep_reload', default=NoConfigDefault,
155 action='store_false', dest='InteractiveShell.deep_reload', default=NoConfigDefault,
156 help="Disable deep (recursive) reloading by default.")
156 help="Disable deep (recursive) reloading by default.")
157 ),
157 ),
158 (('-editor',), dict(
158 (('-editor',), dict(
159 type=str, dest='InteractiveShell.editor', default=NoConfigDefault,
159 type=str, dest='InteractiveShell.editor', default=NoConfigDefault,
160 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
160 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
161 metavar='InteractiveShell.editor')
161 metavar='InteractiveShell.editor')
162 ),
162 ),
163 (('-log','-l'), dict(
163 (('-log','-l'), dict(
164 action='store_true', dest='InteractiveShell.logstart', default=NoConfigDefault,
164 action='store_true', dest='InteractiveShell.logstart', default=NoConfigDefault,
165 help="Start logging to the default file (./ipython_log.py).")
165 help="Start logging to the default file (./ipython_log.py).")
166 ),
166 ),
167 (('-logfile','-lf'), dict(
167 (('-logfile','-lf'), dict(
168 type=str, dest='InteractiveShell.logfile', default=NoConfigDefault,
168 type=str, dest='InteractiveShell.logfile', default=NoConfigDefault,
169 help="Start logging to logfile.",
169 help="Start logging to logfile.",
170 metavar='InteractiveShell.logfile')
170 metavar='InteractiveShell.logfile')
171 ),
171 ),
172 (('-logappend','-la'), dict(
172 (('-logappend','-la'), dict(
173 type=str, dest='InteractiveShell.logappend', default=NoConfigDefault,
173 type=str, dest='InteractiveShell.logappend', default=NoConfigDefault,
174 help="Start logging to logappend in append mode.",
174 help="Start logging to logappend in append mode.",
175 metavar='InteractiveShell.logfile')
175 metavar='InteractiveShell.logfile')
176 ),
176 ),
177 (('-pdb',), dict(
177 (('-pdb',), dict(
178 action='store_true', dest='InteractiveShell.pdb', default=NoConfigDefault,
178 action='store_true', dest='InteractiveShell.pdb', default=NoConfigDefault,
179 help="Enable auto calling the pdb debugger after every exception.")
179 help="Enable auto calling the pdb debugger after every exception.")
180 ),
180 ),
181 (('-nopdb',), dict(
181 (('-nopdb',), dict(
182 action='store_false', dest='InteractiveShell.pdb', default=NoConfigDefault,
182 action='store_false', dest='InteractiveShell.pdb', default=NoConfigDefault,
183 help="Disable auto calling the pdb debugger after every exception.")
183 help="Disable auto calling the pdb debugger after every exception.")
184 ),
184 ),
185 (('-pprint',), dict(
185 (('-pprint',), dict(
186 action='store_true', dest='InteractiveShell.pprint', default=NoConfigDefault,
186 action='store_true', dest='InteractiveShell.pprint', default=NoConfigDefault,
187 help="Enable auto pretty printing of results.")
187 help="Enable auto pretty printing of results.")
188 ),
188 ),
189 (('-nopprint',), dict(
189 (('-nopprint',), dict(
190 action='store_false', dest='InteractiveShell.pprint', default=NoConfigDefault,
190 action='store_false', dest='InteractiveShell.pprint', default=NoConfigDefault,
191 help="Disable auto auto pretty printing of results.")
191 help="Disable auto auto pretty printing of results.")
192 ),
192 ),
193 (('-prompt_in1','-pi1'), dict(
193 (('-prompt_in1','-pi1'), dict(
194 type=str, dest='InteractiveShell.prompt_in1', default=NoConfigDefault,
194 type=str, dest='InteractiveShell.prompt_in1', default=NoConfigDefault,
195 help="Set the main input prompt ('In [\#]: ')",
195 help="Set the main input prompt ('In [\#]: ')",
196 metavar='InteractiveShell.prompt_in1')
196 metavar='InteractiveShell.prompt_in1')
197 ),
197 ),
198 (('-prompt_in2','-pi2'), dict(
198 (('-prompt_in2','-pi2'), dict(
199 type=str, dest='InteractiveShell.prompt_in2', default=NoConfigDefault,
199 type=str, dest='InteractiveShell.prompt_in2', default=NoConfigDefault,
200 help="Set the secondary input prompt (' .\D.: ')",
200 help="Set the secondary input prompt (' .\D.: ')",
201 metavar='InteractiveShell.prompt_in2')
201 metavar='InteractiveShell.prompt_in2')
202 ),
202 ),
203 (('-prompt_out','-po'), dict(
203 (('-prompt_out','-po'), dict(
204 type=str, dest='InteractiveShell.prompt_out', default=NoConfigDefault,
204 type=str, dest='InteractiveShell.prompt_out', default=NoConfigDefault,
205 help="Set the output prompt ('Out[\#]:')",
205 help="Set the output prompt ('Out[\#]:')",
206 metavar='InteractiveShell.prompt_out')
206 metavar='InteractiveShell.prompt_out')
207 ),
207 ),
208 (('-quick',), dict(
208 (('-quick',), dict(
209 action='store_true', dest='Global.quick', default=NoConfigDefault,
209 action='store_true', dest='Global.quick', default=NoConfigDefault,
210 help="Enable quick startup with no config files.")
210 help="Enable quick startup with no config files.")
211 ),
211 ),
212 (('-readline',), dict(
212 (('-readline',), dict(
213 action='store_true', dest='InteractiveShell.readline_use', default=NoConfigDefault,
213 action='store_true', dest='InteractiveShell.readline_use', default=NoConfigDefault,
214 help="Enable readline for command line usage.")
214 help="Enable readline for command line usage.")
215 ),
215 ),
216 (('-noreadline',), dict(
216 (('-noreadline',), dict(
217 action='store_false', dest='InteractiveShell.readline_use', default=NoConfigDefault,
217 action='store_false', dest='InteractiveShell.readline_use', default=NoConfigDefault,
218 help="Disable readline for command line usage.")
218 help="Disable readline for command line usage.")
219 ),
219 ),
220 (('-screen_length','-sl'), dict(
220 (('-screen_length','-sl'), dict(
221 type=int, dest='InteractiveShell.screen_length', default=NoConfigDefault,
221 type=int, dest='InteractiveShell.screen_length', default=NoConfigDefault,
222 help='Number of lines on screen, used to control printing of long strings.',
222 help='Number of lines on screen, used to control printing of long strings.',
223 metavar='InteractiveShell.screen_length')
223 metavar='InteractiveShell.screen_length')
224 ),
224 ),
225 (('-separate_in','-si'), dict(
225 (('-separate_in','-si'), dict(
226 type=str, dest='InteractiveShell.separate_in', default=NoConfigDefault,
226 type=str, dest='InteractiveShell.separate_in', default=NoConfigDefault,
227 help="Separator before input prompts. Default '\n'.",
227 help="Separator before input prompts. Default '\n'.",
228 metavar='InteractiveShell.separate_in')
228 metavar='InteractiveShell.separate_in')
229 ),
229 ),
230 (('-separate_out','-so'), dict(
230 (('-separate_out','-so'), dict(
231 type=str, dest='InteractiveShell.separate_out', default=NoConfigDefault,
231 type=str, dest='InteractiveShell.separate_out', default=NoConfigDefault,
232 help="Separator before output prompts. Default 0 (nothing).",
232 help="Separator before output prompts. Default 0 (nothing).",
233 metavar='InteractiveShell.separate_out')
233 metavar='InteractiveShell.separate_out')
234 ),
234 ),
235 (('-separate_out2','-so2'), dict(
235 (('-separate_out2','-so2'), dict(
236 type=str, dest='InteractiveShell.separate_out2', default=NoConfigDefault,
236 type=str, dest='InteractiveShell.separate_out2', default=NoConfigDefault,
237 help="Separator after output prompts. Default 0 (nonight).",
237 help="Separator after output prompts. Default 0 (nonight).",
238 metavar='InteractiveShell.separate_out2')
238 metavar='InteractiveShell.separate_out2')
239 ),
239 ),
240 (('-nosep',), dict(
240 (('-nosep',), dict(
241 action='store_true', dest='Global.nosep', default=NoConfigDefault,
241 action='store_true', dest='Global.nosep', default=NoConfigDefault,
242 help="Eliminate all spacing between prompts.")
242 help="Eliminate all spacing between prompts.")
243 ),
243 ),
244 (('-term_title',), dict(
244 (('-term_title',), dict(
245 action='store_true', dest='InteractiveShell.term_title', default=NoConfigDefault,
245 action='store_true', dest='InteractiveShell.term_title', default=NoConfigDefault,
246 help="Enable auto setting the terminal title.")
246 help="Enable auto setting the terminal title.")
247 ),
247 ),
248 (('-noterm_title',), dict(
248 (('-noterm_title',), dict(
249 action='store_false', dest='InteractiveShell.term_title', default=NoConfigDefault,
249 action='store_false', dest='InteractiveShell.term_title', default=NoConfigDefault,
250 help="Disable auto setting the terminal title.")
250 help="Disable auto setting the terminal title.")
251 ),
251 ),
252 (('-xmode',), dict(
252 (('-xmode',), dict(
253 type=str, dest='InteractiveShell.xmode', default=NoConfigDefault,
253 type=str, dest='InteractiveShell.xmode', default=NoConfigDefault,
254 help="Exception mode ('Plain','Context','Verbose')",
254 help="Exception mode ('Plain','Context','Verbose')",
255 metavar='InteractiveShell.xmode')
255 metavar='InteractiveShell.xmode')
256 ),
256 ),
257 (('-ext',), dict(
257 (('-ext',), dict(
258 type=str, dest='Global.extra_extension', default=NoConfigDefault,
258 type=str, dest='Global.extra_extension', default=NoConfigDefault,
259 help="The dotted module name of an IPython extension to load.",
259 help="The dotted module name of an IPython extension to load.",
260 metavar='Global.extra_extension')
260 metavar='Global.extra_extension')
261 ),
261 ),
262 (('-c',), dict(
262 (('-c',), dict(
263 type=str, dest='Global.code_to_run', default=NoConfigDefault,
263 type=str, dest='Global.code_to_run', default=NoConfigDefault,
264 help="Execute the given command string.",
264 help="Execute the given command string.",
265 metavar='Global.code_to_run')
265 metavar='Global.code_to_run')
266 ),
266 ),
267 (('-i',), dict(
267 (('-i',), dict(
268 action='store_true', dest='Global.force_interact', default=NoConfigDefault,
268 action='store_true', dest='Global.force_interact', default=NoConfigDefault,
269 help="If running code from the command line, become interactive afterwards.")
269 help="If running code from the command line, become interactive afterwards.")
270 ),
270 ),
271 (('-wthread',), dict(
271 (('-wthread',), dict(
272 action='store_true', dest='Global.wthread', default=NoConfigDefault,
272 action='store_true', dest='Global.wthread', default=NoConfigDefault,
273 help="Enable wxPython event loop integration.")
273 help="Enable wxPython event loop integration.")
274 ),
274 ),
275 (('-q4thread','-qthread'), dict(
275 (('-q4thread','-qthread'), dict(
276 action='store_true', dest='Global.q4thread', default=NoConfigDefault,
276 action='store_true', dest='Global.q4thread', default=NoConfigDefault,
277 help="Enable Qt4 event loop integration. Qt3 is no longer supported.")
277 help="Enable Qt4 event loop integration. Qt3 is no longer supported.")
278 ),
278 ),
279 (('-gthread',), dict(
279 (('-gthread',), dict(
280 action='store_true', dest='Global.gthread', default=NoConfigDefault,
280 action='store_true', dest='Global.gthread', default=NoConfigDefault,
281 help="Enable GTK event loop integration.")
281 help="Enable GTK event loop integration.")
282 ),
282 ),
283 # # These are only here to get the proper deprecation warnings
283 # # These are only here to get the proper deprecation warnings
284 (('-pylab',), dict(
284 (('-pylab',), dict(
285 action='store_true', dest='Global.pylab', default=NoConfigDefault,
285 action='store_true', dest='Global.pylab', default=NoConfigDefault,
286 help="Disabled. Pylab has been disabled until matplotlib supports this version of IPython.")
286 help="Disabled. Pylab has been disabled until matplotlib "
287 "supports this version of IPython.")
287 )
288 )
288 )
289 )
289
290
290
291
291 class IPythonAppCLConfigLoader(IPythonArgParseConfigLoader):
292 class IPythonAppCLConfigLoader(BaseAppArgParseConfigLoader):
292
293
293 arguments = cl_args
294 arguments = cl_args
294
295
295
296
296 _default_config_file_name = 'ipython_config.py'
297 _default_config_file_name = 'ipython_config.py'
297
298
299
298 class IPythonApp(Application):
300 class IPythonApp(Application):
299 name = 'ipython'
301 name = 'ipython'
302 description = 'IPython: an enhanced interactive Python shell.'
300 config_file_name = _default_config_file_name
303 config_file_name = _default_config_file_name
301
304
302 def create_default_config(self):
305 def create_default_config(self):
303 super(IPythonApp, self).create_default_config()
306 super(IPythonApp, self).create_default_config()
304 self.default_config.Global.display_banner = True
307 self.default_config.Global.display_banner = True
305
308
306 # If the -c flag is given or a file is given to run at the cmd line
309 # If the -c flag is given or a file is given to run at the cmd line
307 # like "ipython foo.py", normally we exit without starting the main
310 # like "ipython foo.py", normally we exit without starting the main
308 # loop. The force_interact config variable allows a user to override
311 # loop. The force_interact config variable allows a user to override
309 # this and interact. It is also set by the -i cmd line flag, just
312 # this and interact. It is also set by the -i cmd line flag, just
310 # like Python.
313 # like Python.
311 self.default_config.Global.force_interact = False
314 self.default_config.Global.force_interact = False
312
315
313 # By default always interact by starting the IPython mainloop.
316 # By default always interact by starting the IPython mainloop.
314 self.default_config.Global.interact = True
317 self.default_config.Global.interact = True
315
318
316 # Let the parent class set the default, but each time log_level
317 # changes from config, we need to update self.log_level as that is
318 # what updates the actual log level in self.log.
319 self.default_config.Global.log_level = self.log_level
320
321 # No GUI integration by default
319 # No GUI integration by default
322 self.default_config.Global.wthread = False
320 self.default_config.Global.wthread = False
323 self.default_config.Global.q4thread = False
321 self.default_config.Global.q4thread = False
324 self.default_config.Global.gthread = False
322 self.default_config.Global.gthread = False
325
323
326 def create_command_line_config(self):
324 def create_command_line_config(self):
327 """Create and return a command line config loader."""
325 """Create and return a command line config loader."""
328 return IPythonAppCLConfigLoader(
326 return IPythonAppCLConfigLoader(
329 description=ipython_desc,
327 description=self.description,
330 version=release.version)
328 version=release.version
329 )
331
330
332 def post_load_command_line_config(self):
331 def post_load_command_line_config(self):
333 """Do actions after loading cl config."""
332 """Do actions after loading cl config."""
334 clc = self.command_line_config
333 clc = self.command_line_config
335
334
336 # Display the deprecation warnings about threaded shells
335 # Display the deprecation warnings about threaded shells
337 if hasattr(clc.Global, 'pylab'):
336 if hasattr(clc.Global, 'pylab'):
338 pylab_warning()
337 pylab_warning()
339 del clc.Global['pylab']
338 del clc.Global['pylab']
340
339
341 def load_file_config(self):
340 def load_file_config(self):
342 if hasattr(self.command_line_config.Global, 'quick'):
341 if hasattr(self.command_line_config.Global, 'quick'):
343 if self.command_line_config.Global.quick:
342 if self.command_line_config.Global.quick:
344 self.file_config = Config()
343 self.file_config = Config()
345 return
344 return
346 super(IPythonApp, self).load_file_config()
345 super(IPythonApp, self).load_file_config()
347
346
348 def post_load_file_config(self):
347 def post_load_file_config(self):
349 if hasattr(self.command_line_config.Global, 'extra_extension'):
348 if hasattr(self.command_line_config.Global, 'extra_extension'):
350 if not hasattr(self.file_config.Global, 'extensions'):
349 if not hasattr(self.file_config.Global, 'extensions'):
351 self.file_config.Global.extensions = []
350 self.file_config.Global.extensions = []
352 self.file_config.Global.extensions.append(
351 self.file_config.Global.extensions.append(
353 self.command_line_config.Global.extra_extension)
352 self.command_line_config.Global.extra_extension)
354 del self.command_line_config.Global.extra_extension
353 del self.command_line_config.Global.extra_extension
355
354
356 def pre_construct(self):
355 def pre_construct(self):
357 config = self.master_config
356 config = self.master_config
358
357
359 if hasattr(config.Global, 'classic'):
358 if hasattr(config.Global, 'classic'):
360 if config.Global.classic:
359 if config.Global.classic:
361 config.InteractiveShell.cache_size = 0
360 config.InteractiveShell.cache_size = 0
362 config.InteractiveShell.pprint = 0
361 config.InteractiveShell.pprint = 0
363 config.InteractiveShell.prompt_in1 = '>>> '
362 config.InteractiveShell.prompt_in1 = '>>> '
364 config.InteractiveShell.prompt_in2 = '... '
363 config.InteractiveShell.prompt_in2 = '... '
365 config.InteractiveShell.prompt_out = ''
364 config.InteractiveShell.prompt_out = ''
366 config.InteractiveShell.separate_in = \
365 config.InteractiveShell.separate_in = \
367 config.InteractiveShell.separate_out = \
366 config.InteractiveShell.separate_out = \
368 config.InteractiveShell.separate_out2 = ''
367 config.InteractiveShell.separate_out2 = ''
369 config.InteractiveShell.colors = 'NoColor'
368 config.InteractiveShell.colors = 'NoColor'
370 config.InteractiveShell.xmode = 'Plain'
369 config.InteractiveShell.xmode = 'Plain'
371
370
372 if hasattr(config.Global, 'nosep'):
371 if hasattr(config.Global, 'nosep'):
373 if config.Global.nosep:
372 if config.Global.nosep:
374 config.InteractiveShell.separate_in = \
373 config.InteractiveShell.separate_in = \
375 config.InteractiveShell.separate_out = \
374 config.InteractiveShell.separate_out = \
376 config.InteractiveShell.separate_out2 = ''
375 config.InteractiveShell.separate_out2 = ''
377
376
378 # if there is code of files to run from the cmd line, don't interact
377 # if there is code of files to run from the cmd line, don't interact
379 # unless the -i flag (Global.force_interact) is true.
378 # unless the -i flag (Global.force_interact) is true.
380 code_to_run = config.Global.get('code_to_run','')
379 code_to_run = config.Global.get('code_to_run','')
381 file_to_run = False
380 file_to_run = False
382 if len(self.extra_args)>=1:
381 if len(self.extra_args)>=1:
383 if self.extra_args[0]:
382 if self.extra_args[0]:
384 file_to_run = True
383 file_to_run = True
385 if file_to_run or code_to_run:
384 if file_to_run or code_to_run:
386 if not config.Global.force_interact:
385 if not config.Global.force_interact:
387 config.Global.interact = False
386 config.Global.interact = False
388
387
389 def construct(self):
388 def construct(self):
390 # I am a little hesitant to put these into InteractiveShell itself.
389 # I am a little hesitant to put these into InteractiveShell itself.
391 # But that might be the place for them
390 # But that might be the place for them
392 sys.path.insert(0, '')
391 sys.path.insert(0, '')
393
392
394 # Create an InteractiveShell instance
393 # Create an InteractiveShell instance
395 self.shell = InteractiveShell(
394 self.shell = InteractiveShell(
396 parent=None,
395 parent=None,
397 config=self.master_config
396 config=self.master_config
398 )
397 )
399
398
400 def post_construct(self):
399 def post_construct(self):
401 """Do actions after construct, but before starting the app."""
400 """Do actions after construct, but before starting the app."""
402 config = self.master_config
401 config = self.master_config
403
402
404 # shell.display_banner should always be False for the terminal
403 # shell.display_banner should always be False for the terminal
405 # based app, because we call shell.show_banner() by hand below
404 # based app, because we call shell.show_banner() by hand below
406 # so the banner shows *before* all extension loading stuff.
405 # so the banner shows *before* all extension loading stuff.
407 self.shell.display_banner = False
406 self.shell.display_banner = False
408
407
409 if config.Global.display_banner and \
408 if config.Global.display_banner and \
410 config.Global.interact:
409 config.Global.interact:
411 self.shell.show_banner()
410 self.shell.show_banner()
412
411
413 # Make sure there is a space below the banner.
412 # Make sure there is a space below the banner.
414 if self.log_level <= logging.INFO: print
413 if self.log_level <= logging.INFO: print
415
414
416 # Now a variety of things that happen after the banner is printed.
415 # Now a variety of things that happen after the banner is printed.
417 self._enable_gui()
416 self._enable_gui()
418 self._load_extensions()
417 self._load_extensions()
419 self._run_exec_lines()
418 self._run_exec_lines()
420 self._run_exec_files()
419 self._run_exec_files()
421 self._run_cmd_line_code()
420 self._run_cmd_line_code()
422
421
423 def _enable_gui(self):
422 def _enable_gui(self):
424 """Enable GUI event loop integration."""
423 """Enable GUI event loop integration."""
425 config = self.master_config
424 config = self.master_config
426 try:
425 try:
427 # Enable GUI integration
426 # Enable GUI integration
428 if config.Global.wthread:
427 if config.Global.wthread:
429 self.log.info("Enabling wx GUI event loop integration")
428 self.log.info("Enabling wx GUI event loop integration")
430 inputhook.enable_wx(app=True)
429 inputhook.enable_wx(app=True)
431 elif config.Global.q4thread:
430 elif config.Global.q4thread:
432 self.log.info("Enabling Qt4 GUI event loop integration")
431 self.log.info("Enabling Qt4 GUI event loop integration")
433 inputhook.enable_qt4(app=True)
432 inputhook.enable_qt4(app=True)
434 elif config.Global.gthread:
433 elif config.Global.gthread:
435 self.log.info("Enabling GTK GUI event loop integration")
434 self.log.info("Enabling GTK GUI event loop integration")
436 inputhook.enable_gtk(app=True)
435 inputhook.enable_gtk(app=True)
437 except:
436 except:
438 self.log.warn("Error in enabling GUI event loop integration:")
437 self.log.warn("Error in enabling GUI event loop integration:")
439 self.shell.showtraceback()
438 self.shell.showtraceback()
440
439
441 def _load_extensions(self):
440 def _load_extensions(self):
442 """Load all IPython extensions in Global.extensions.
441 """Load all IPython extensions in Global.extensions.
443
442
444 This uses the :meth:`InteractiveShell.load_extensions` to load all
443 This uses the :meth:`InteractiveShell.load_extensions` to load all
445 the extensions listed in ``self.master_config.Global.extensions``.
444 the extensions listed in ``self.master_config.Global.extensions``.
446 """
445 """
447 try:
446 try:
448 if hasattr(self.master_config.Global, 'extensions'):
447 if hasattr(self.master_config.Global, 'extensions'):
449 self.log.debug("Loading IPython extensions...")
448 self.log.debug("Loading IPython extensions...")
450 extensions = self.master_config.Global.extensions
449 extensions = self.master_config.Global.extensions
451 for ext in extensions:
450 for ext in extensions:
452 try:
451 try:
453 self.log.info("Loading IPython extension: %s" % ext)
452 self.log.info("Loading IPython extension: %s" % ext)
454 self.shell.load_extension(ext)
453 self.shell.load_extension(ext)
455 except:
454 except:
456 self.log.warn("Error in loading extension: %s" % ext)
455 self.log.warn("Error in loading extension: %s" % ext)
457 self.shell.showtraceback()
456 self.shell.showtraceback()
458 except:
457 except:
459 self.log.warn("Unknown error in loading extensions:")
458 self.log.warn("Unknown error in loading extensions:")
460 self.shell.showtraceback()
459 self.shell.showtraceback()
461
460
462 def _run_exec_lines(self):
461 def _run_exec_lines(self):
463 """Run lines of code in Global.exec_lines in the user's namespace."""
462 """Run lines of code in Global.exec_lines in the user's namespace."""
464 try:
463 try:
465 if hasattr(self.master_config.Global, 'exec_lines'):
464 if hasattr(self.master_config.Global, 'exec_lines'):
466 self.log.debug("Running code from Global.exec_lines...")
465 self.log.debug("Running code from Global.exec_lines...")
467 exec_lines = self.master_config.Global.exec_lines
466 exec_lines = self.master_config.Global.exec_lines
468 for line in exec_lines:
467 for line in exec_lines:
469 try:
468 try:
470 self.log.info("Running code in user namespace: %s" % line)
469 self.log.info("Running code in user namespace: %s" % line)
471 self.shell.runlines(line)
470 self.shell.runlines(line)
472 except:
471 except:
473 self.log.warn("Error in executing line in user namespace: %s" % line)
472 self.log.warn("Error in executing line in user namespace: %s" % line)
474 self.shell.showtraceback()
473 self.shell.showtraceback()
475 except:
474 except:
476 self.log.warn("Unknown error in handling Global.exec_lines:")
475 self.log.warn("Unknown error in handling Global.exec_lines:")
477 self.shell.showtraceback()
476 self.shell.showtraceback()
478
477
479 def _exec_file(self, fname):
478 def _exec_file(self, fname):
480 full_filename = filefind(fname, ['.', self.ipythondir])
479 full_filename = filefind(fname, ['.', self.ipythondir])
481 if os.path.isfile(full_filename):
480 if os.path.isfile(full_filename):
482 if full_filename.endswith('.py'):
481 if full_filename.endswith('.py'):
483 self.log.info("Running file in user namespace: %s" % full_filename)
482 self.log.info("Running file in user namespace: %s" % full_filename)
484 self.shell.safe_execfile(full_filename, self.shell.user_ns)
483 self.shell.safe_execfile(full_filename, self.shell.user_ns)
485 elif full_filename.endswith('.ipy'):
484 elif full_filename.endswith('.ipy'):
486 self.log.info("Running file in user namespace: %s" % full_filename)
485 self.log.info("Running file in user namespace: %s" % full_filename)
487 self.shell.safe_execfile_ipy(full_filename)
486 self.shell.safe_execfile_ipy(full_filename)
488 else:
487 else:
489 self.log.warn("File does not have a .py or .ipy extension: <%s>" % full_filename)
488 self.log.warn("File does not have a .py or .ipy extension: <%s>" % full_filename)
490
489
491 def _run_exec_files(self):
490 def _run_exec_files(self):
492 try:
491 try:
493 if hasattr(self.master_config.Global, 'exec_files'):
492 if hasattr(self.master_config.Global, 'exec_files'):
494 self.log.debug("Running files in Global.exec_files...")
493 self.log.debug("Running files in Global.exec_files...")
495 exec_files = self.master_config.Global.exec_files
494 exec_files = self.master_config.Global.exec_files
496 for fname in exec_files:
495 for fname in exec_files:
497 self._exec_file(fname)
496 self._exec_file(fname)
498 except:
497 except:
499 self.log.warn("Unknown error in handling Global.exec_files:")
498 self.log.warn("Unknown error in handling Global.exec_files:")
500 self.shell.showtraceback()
499 self.shell.showtraceback()
501
500
502 def _run_cmd_line_code(self):
501 def _run_cmd_line_code(self):
503 if hasattr(self.master_config.Global, 'code_to_run'):
502 if hasattr(self.master_config.Global, 'code_to_run'):
504 line = self.master_config.Global.code_to_run
503 line = self.master_config.Global.code_to_run
505 try:
504 try:
506 self.log.info("Running code given at command line (-c): %s" % line)
505 self.log.info("Running code given at command line (-c): %s" % line)
507 self.shell.runlines(line)
506 self.shell.runlines(line)
508 except:
507 except:
509 self.log.warn("Error in executing line in user namespace: %s" % line)
508 self.log.warn("Error in executing line in user namespace: %s" % line)
510 self.shell.showtraceback()
509 self.shell.showtraceback()
511 return
510 return
512 # Like Python itself, ignore the second if the first of these is present
511 # Like Python itself, ignore the second if the first of these is present
513 try:
512 try:
514 fname = self.extra_args[0]
513 fname = self.extra_args[0]
515 except:
514 except:
516 pass
515 pass
517 else:
516 else:
518 try:
517 try:
519 self._exec_file(fname)
518 self._exec_file(fname)
520 except:
519 except:
521 self.log.warn("Error in executing file in user namespace: %s" % fname)
520 self.log.warn("Error in executing file in user namespace: %s" % fname)
522 self.shell.showtraceback()
521 self.shell.showtraceback()
523
522
524 def start_app(self):
523 def start_app(self):
525 if self.master_config.Global.interact:
524 if self.master_config.Global.interact:
526 self.log.debug("Starting IPython's mainloop...")
525 self.log.debug("Starting IPython's mainloop...")
527 self.shell.mainloop()
526 self.shell.mainloop()
528
527
529
528
530 def load_default_config(ipythondir=None):
529 def load_default_config(ipythondir=None):
531 """Load the default config file from the default ipythondir.
530 """Load the default config file from the default ipythondir.
532
531
533 This is useful for embedded shells.
532 This is useful for embedded shells.
534 """
533 """
535 if ipythondir is None:
534 if ipythondir is None:
536 ipythondir = get_ipython_dir()
535 ipythondir = get_ipython_dir()
537 cl = PyFileConfigLoader(_default_config_file_name, ipythondir)
536 cl = PyFileConfigLoader(_default_config_file_name, ipythondir)
538 config = cl.load_config()
537 config = cl.load_config()
539 return config
538 return config
540
539
541
540
542 def launch_new_instance():
541 def launch_new_instance():
543 """Create a run a full blown IPython instance"""
542 """Create and run a full blown IPython instance"""
544 app = IPythonApp()
543 app = IPythonApp()
545 app.start()
544 app.start()
546
545
@@ -1,310 +1,258 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The IPython controller application
4 The IPython controller application
5 """
5 """
6
6
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (C) 2008-2009 The IPython Development Team
8 # Copyright (C) 2008-2009 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 import copy
18 import copy
19 import logging
19 import logging
20 import os
20 import os
21 import sys
21 import sys
22
22
23 from twisted.application import service
23 from twisted.application import service
24 from twisted.internet import reactor, defer
24 from twisted.internet import reactor, defer
25 from twisted.python import log
25 from twisted.python import log
26
26
27 from IPython.config.loader import Config, NoConfigDefault
27 from IPython.config.loader import Config, NoConfigDefault
28
28
29 from IPython.core.application import Application, IPythonArgParseConfigLoader
29 from IPython.core.application import (
30 ApplicationWithDir,
31 BaseAppArgParseConfigLoader
32 )
33
30 from IPython.core import release
34 from IPython.core import release
31
35
32 from IPython.utils.traitlets import Int, Str, Bool, Instance
36 from IPython.utils.traitlets import Int, Str, Bool, Instance
33 from IPython.utils.importstring import import_item
37 from IPython.utils.importstring import import_item
34
38
35 from IPython.kernel import controllerservice
39 from IPython.kernel import controllerservice
36 from IPython.kernel.configobjfactory import (
40 from IPython.kernel.configobjfactory import (
37 ConfiguredObjectFactory,
41 ConfiguredObjectFactory,
38 AdaptedConfiguredObjectFactory
42 AdaptedConfiguredObjectFactory
39 )
43 )
40
44
41 from IPython.kernel.fcutil import FCServiceFactory
45 from IPython.kernel.fcutil import FCServiceFactory
42
46
43 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
44 # Default interfaces
48 # Default interfaces
45 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
46
50
47
51
48 # The default client interfaces for FCClientServiceFactory.Interfaces
52 # The default client interfaces for FCClientServiceFactory.Interfaces
49 default_client_interfaces = Config()
53 default_client_interfaces = Config()
50 default_client_interfaces.Task.interface_chain = [
54 default_client_interfaces.Task.interface_chain = [
51 'IPython.kernel.task.ITaskController',
55 'IPython.kernel.task.ITaskController',
52 'IPython.kernel.taskfc.IFCTaskController'
56 'IPython.kernel.taskfc.IFCTaskController'
53 ]
57 ]
54
58
55 default_client_interfaces.Task.furl_file = 'ipcontroller-tc.furl'
59 default_client_interfaces.Task.furl_file = 'ipcontroller-tc.furl'
56 default_client_interfaces.MultiEngine.interface_chain = [
60 default_client_interfaces.MultiEngine.interface_chain = [
57 'IPython.kernel.multiengine.IMultiEngine',
61 'IPython.kernel.multiengine.IMultiEngine',
58 'IPython.kernel.multienginefc.IFCSynchronousMultiEngine'
62 'IPython.kernel.multienginefc.IFCSynchronousMultiEngine'
59 ]
63 ]
60
64
61 default_client_interfaces.MultiEngine.furl_file = 'ipcontroller-mec.furl'
65 default_client_interfaces.MultiEngine.furl_file = 'ipcontroller-mec.furl'
62
66
63 # Make this a dict we can pass to Config.__init__ for the default
67 # Make this a dict we can pass to Config.__init__ for the default
64 default_client_interfaces = dict(copy.deepcopy(default_client_interfaces.items()))
68 default_client_interfaces = dict(copy.deepcopy(default_client_interfaces.items()))
65
69
66
70
67
71
68 # The default engine interfaces for FCEngineServiceFactory.Interfaces
72 # The default engine interfaces for FCEngineServiceFactory.Interfaces
69 default_engine_interfaces = Config()
73 default_engine_interfaces = Config()
70 default_engine_interfaces.Default.interface_chain = [
74 default_engine_interfaces.Default.interface_chain = [
71 'IPython.kernel.enginefc.IFCControllerBase'
75 'IPython.kernel.enginefc.IFCControllerBase'
72 ]
76 ]
73
77
74 default_engine_interfaces.Default.furl_file = 'ipcontroller-engine.furl'
78 default_engine_interfaces.Default.furl_file = 'ipcontroller-engine.furl'
75
79
76 # Make this a dict we can pass to Config.__init__ for the default
80 # Make this a dict we can pass to Config.__init__ for the default
77 default_engine_interfaces = dict(copy.deepcopy(default_engine_interfaces.items()))
81 default_engine_interfaces = dict(copy.deepcopy(default_engine_interfaces.items()))
78
82
79
83
80 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
81 # Service factories
85 # Service factories
82 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
83
87
84
88
85 class FCClientServiceFactory(FCServiceFactory):
89 class FCClientServiceFactory(FCServiceFactory):
86 """A Foolscap implementation of the client services."""
90 """A Foolscap implementation of the client services."""
87
91
88 cert_file = Str('ipcontroller-client.pem', config=True)
92 cert_file = Str('ipcontroller-client.pem', config=True)
89 Interfaces = Instance(klass=Config, kw=default_client_interfaces,
93 Interfaces = Instance(klass=Config, kw=default_client_interfaces,
90 allow_none=False, config=True)
94 allow_none=False, config=True)
91
95
92
96
93 class FCEngineServiceFactory(FCServiceFactory):
97 class FCEngineServiceFactory(FCServiceFactory):
94 """A Foolscap implementation of the engine services."""
98 """A Foolscap implementation of the engine services."""
95
99
96 cert_file = Str('ipcontroller-engine.pem', config=True)
100 cert_file = Str('ipcontroller-engine.pem', config=True)
97 Interfaces = Instance(klass=dict, kw=default_engine_interfaces,
101 Interfaces = Instance(klass=dict, kw=default_engine_interfaces,
98 allow_none=False, config=True)
102 allow_none=False, config=True)
99
103
100
104
101 #-----------------------------------------------------------------------------
105 #-----------------------------------------------------------------------------
102 # The main application
106 # The main application
103 #-----------------------------------------------------------------------------
107 #-----------------------------------------------------------------------------
104
108
105
109
106 cl_args = (
110 cl_args = (
107 # Client config
111 # Client config
108 (('--client-ip',), dict(
112 (('--client-ip',), dict(
109 type=str, dest='FCClientServiceFactory.ip', default=NoConfigDefault,
113 type=str, dest='FCClientServiceFactory.ip', default=NoConfigDefault,
110 help='The IP address or hostname the controller will listen on for client connections.',
114 help='The IP address or hostname the controller will listen on for client connections.',
111 metavar='FCClientServiceFactory.ip')
115 metavar='FCClientServiceFactory.ip')
112 ),
116 ),
113 (('--client-port',), dict(
117 (('--client-port',), dict(
114 type=int, dest='FCClientServiceFactory.port', default=NoConfigDefault,
118 type=int, dest='FCClientServiceFactory.port', default=NoConfigDefault,
115 help='The port the controller will listen on for client connections.',
119 help='The port the controller will listen on for client connections.',
116 metavar='FCClientServiceFactory.port')
120 metavar='FCClientServiceFactory.port')
117 ),
121 ),
118 (('--client-location',), dict(
122 (('--client-location',), dict(
119 type=str, dest='FCClientServiceFactory.location', default=NoConfigDefault,
123 type=str, dest='FCClientServiceFactory.location', default=NoConfigDefault,
120 help='The hostname or ip that clients should connect to.',
124 help='The hostname or ip that clients should connect to.',
121 metavar='FCClientServiceFactory.location')
125 metavar='FCClientServiceFactory.location')
122 ),
126 ),
123 (('-x',), dict(
127 (('-x',), dict(
124 action='store_false', dest='FCClientServiceFactory.secure', default=NoConfigDefault,
128 action='store_false', dest='FCClientServiceFactory.secure', default=NoConfigDefault,
125 help='Turn off all client security.')
129 help='Turn off all client security.')
126 ),
130 ),
127 # Engine config
131 # Engine config
128 (('--engine-ip',), dict(
132 (('--engine-ip',), dict(
129 type=str, dest='FCEngineServiceFactory.ip', default=NoConfigDefault,
133 type=str, dest='FCEngineServiceFactory.ip', default=NoConfigDefault,
130 help='The IP address or hostname the controller will listen on for engine connections.',
134 help='The IP address or hostname the controller will listen on for engine connections.',
131 metavar='FCEngineServiceFactory.ip')
135 metavar='FCEngineServiceFactory.ip')
132 ),
136 ),
133 (('--engine-port',), dict(
137 (('--engine-port',), dict(
134 type=int, dest='FCEngineServiceFactory.port', default=NoConfigDefault,
138 type=int, dest='FCEngineServiceFactory.port', default=NoConfigDefault,
135 help='The port the controller will listen on for engine connections.',
139 help='The port the controller will listen on for engine connections.',
136 metavar='FCEngineServiceFactory.port')
140 metavar='FCEngineServiceFactory.port')
137 ),
141 ),
138 (('--engine-location',), dict(
142 (('--engine-location',), dict(
139 type=str, dest='FCEngineServiceFactory.location', default=NoConfigDefault,
143 type=str, dest='FCEngineServiceFactory.location', default=NoConfigDefault,
140 help='The hostname or ip that engines should connect to.',
144 help='The hostname or ip that engines should connect to.',
141 metavar='FCEngineServiceFactory.location')
145 metavar='FCEngineServiceFactory.location')
142 ),
146 ),
143 (('-y',), dict(
147 (('-y',), dict(
144 action='store_false', dest='FCEngineServiceFactory.secure', default=NoConfigDefault,
148 action='store_false', dest='FCEngineServiceFactory.secure', default=NoConfigDefault,
145 help='Turn off all engine security.')
149 help='Turn off all engine security.')
146 ),
150 ),
147 # Global config
151 # Global config
148 (('--log-to-file',), dict(
152 (('--log-to-file',), dict(
149 action='store_true', dest='Global.log_to_file', default=NoConfigDefault,
153 action='store_true', dest='Global.log_to_file', default=NoConfigDefault,
150 help='Log to a file in the log directory (default is stdout)')
154 help='Log to a file in the log directory (default is stdout)')
151 ),
155 ),
152 (('-r','--reuse-furls'), dict(
156 (('-r','--reuse-furls'), dict(
153 action='store_true', dest='Global.reuse_furls', default=NoConfigDefault,
157 action='store_true', dest='Global.reuse_furls', default=NoConfigDefault,
154 help='Try to reuse all FURL files.')
158 help='Try to reuse all FURL files.')
155 ),
159 )
156 (('-cluster_dir', '--cluster-dir',), dict(
157 type=str, dest='Global.cluster_dir', default=NoConfigDefault,
158 help='Absolute or relative path to the cluster directory.',
159 metavar='Global.cluster_dir')
160 ),
161 )
160 )
162
161
163
162
164 class IPControllerAppCLConfigLoader(IPythonArgParseConfigLoader):
163 class IPControllerAppCLConfigLoader(BaseAppArgParseConfigLoader):
165
164
166 arguments = cl_args
165 arguments = cl_args
167
166
168
167
169 _default_config_file_name = 'ipcontroller_config.py'
168 _default_config_file_name = 'ipcontroller_config.py'
170
169
171 class IPControllerApp(Application):
170
171 class IPControllerApp(ApplicationWithDir):
172
172
173 name = 'ipcontroller'
173 name = 'ipcontroller'
174 description = 'Start the IPython controller for parallel computing.'
174 config_file_name = _default_config_file_name
175 config_file_name = _default_config_file_name
175 default_log_level = logging.DEBUG
176 default_log_level = logging.DEBUG
176
177
177 def create_default_config(self):
178 def create_default_config(self):
178 super(IPControllerApp, self).create_default_config()
179 super(IPControllerApp, self).create_default_config()
179 self.default_config.Global.reuse_furls = False
180 self.default_config.Global.reuse_furls = False
180 self.default_config.Global.import_statements = []
181 self.default_config.Global.import_statements = []
181 self.default_config.Global.profile = 'default'
182 self.default_config.Global.log_dir_name = 'log'
182 self.default_config.Global.log_dir_name = 'log'
183 self.default_config.Global.security_dir_name = 'security'
183 self.default_config.Global.security_dir_name = 'security'
184 self.default_config.Global.log_to_file = False
184 self.default_config.Global.log_to_file = False
185 # Resolve the default cluster_dir using the default profile
186 self.default_config.Global.cluster_dir = ''
187
188 def create_command_line_config(self):
189 """Create and return a command line config loader."""
190
191 return IPControllerAppCLConfigLoader(
192 description="Start an IPython controller",
193 version=release.version)
194
195 def find_config_file_name(self):
196 """Find the config file name for this application."""
197 self.find_cluster_dir()
198 self.create_cluster_dir()
199
200 def find_cluster_dir(self):
201 """This resolves into full paths, the various cluster directories.
202
203 This method must set ``self.cluster_dir`` to the full paths of
204 the directory.
205 """
206 # Ignore self.command_line_config.Global.config_file
207 # Instead, first look for an explicit cluster_dir
208 try:
209 self.cluster_dir = self.command_line_config.Global.cluster_dir
210 except AttributeError:
211 self.cluster_dir = self.default_config.Global.cluster_dir
212 self.cluster_dir = os.path.expandvars(os.path.expanduser(self.cluster_dir))
213 if not self.cluster_dir:
214 # Then look for a profile
215 try:
216 self.profile = self.command_line_config.Global.profile
217 except AttributeError:
218 self.profile = self.default_config.Global.profile
219 cluster_dir_name = 'cluster_' + self.profile
220 try_this = os.path.join(os.getcwd(), cluster_dir_name)
221 if os.path.isdir(try_this):
222 self.cluster_dir = try_this
223 else:
224 self.cluster_dir = os.path.join(self.ipythondir, cluster_dir_name)
225 # These have to be set because they could be different from the one
226 # that we just computed. Because command line has the highest
227 # priority, this will always end up in the master_config.
228 self.default_config.Global.cluster_dir = self.cluster_dir
229 self.command_line_config.Global.cluster_dir = self.cluster_dir
230
231 def create_cluster_dir(self):
232 """Make sure that the cluster, security and log dirs exist."""
233 if not os.path.isdir(self.cluster_dir):
234 os.makedirs(self.cluster_dir, mode=0777)
235
236 def find_config_file_paths(self):
237 """Set the search paths for resolving the config file."""
238 self.config_file_paths = (self.cluster_dir,)
239
185
240 def pre_construct(self):
186 def pre_construct(self):
241 # Now set the security_dir and log_dir and create them. We use
187 # Now set the security_dir and log_dir and create them. We use
242 # the names an construct the absolute paths.
188 # the names an construct the absolute paths.
243 security_dir = os.path.join(self.master_config.Global.cluster_dir,
189 security_dir = os.path.join(self.master_config.Global.app_dir,
244 self.master_config.Global.security_dir_name)
190 self.master_config.Global.security_dir_name)
245 log_dir = os.path.join(self.master_config.Global.cluster_dir,
191 log_dir = os.path.join(self.master_config.Global.app_dir,
246 self.master_config.Global.log_dir_name)
192 self.master_config.Global.log_dir_name)
247 if not os.path.isdir(security_dir):
193 if not os.path.isdir(security_dir):
248 os.mkdir(security_dir, 0700)
194 os.mkdir(security_dir, 0700)
249 else:
195 else:
250 os.chmod(security_dir, 0700)
196 os.chmod(security_dir, 0700)
251 if not os.path.isdir(log_dir):
197 if not os.path.isdir(log_dir):
252 os.mkdir(log_dir, 0777)
198 os.mkdir(log_dir, 0777)
253
199
254 self.security_dir = self.master_config.Global.security_dir = security_dir
200 self.security_dir = self.master_config.Global.security_dir = security_dir
255 self.log_dir = self.master_config.Global.log_dir = log_dir
201 self.log_dir = self.master_config.Global.log_dir = log_dir
256
202
257 # Now setup reuse_furls
203 # Now setup reuse_furls
258 if hasattr(self.master_config.Global.reuse_furls):
204 if hasattr(self.master_config.Global, 'reuse_furls'):
259 self.master_config.FCClientServiceFactory.reuse_furls = \
205 self.master_config.FCClientServiceFactory.reuse_furls = \
260 self.master_config.Global.reuse_furls
206 self.master_config.Global.reuse_furls
261 self.master_config.FCEngineServiceFactory.reuse_furls = \
207 self.master_config.FCEngineServiceFactory.reuse_furls = \
262 self.master_config.Global.reuse_furls
208 self.master_config.Global.reuse_furls
263
209
264 def construct(self):
210 def construct(self):
265 # I am a little hesitant to put these into InteractiveShell itself.
211 # I am a little hesitant to put these into InteractiveShell itself.
266 # But that might be the place for them
212 # But that might be the place for them
267 sys.path.insert(0, '')
213 sys.path.insert(0, '')
268
214
269 self.start_logging()
215 self.start_logging()
270 self.import_statements()
216 self.import_statements()
271
217
272 # Create the service hierarchy
218 # Create the service hierarchy
273 self.main_service = service.MultiService()
219 self.main_service = service.MultiService()
274 # The controller service
220 # The controller service
275 controller_service = controllerservice.ControllerService()
221 controller_service = controllerservice.ControllerService()
276 controller_service.setServiceParent(self.main_service)
222 controller_service.setServiceParent(self.main_service)
277 # The client tub and all its refereceables
223 # The client tub and all its refereceables
278 csfactory = FCClientServiceFactory(self.master_config, controller_service)
224 csfactory = FCClientServiceFactory(self.master_config, controller_service)
279 client_service = csfactory.create()
225 client_service = csfactory.create()
280 client_service.setServiceParent(self.main_service)
226 client_service.setServiceParent(self.main_service)
281 # The engine tub
227 # The engine tub
282 esfactory = FCEngineServiceFactory(self.master_config, controller_service)
228 esfactory = FCEngineServiceFactory(self.master_config, controller_service)
283 engine_service = esfactory.create()
229 engine_service = esfactory.create()
284 engine_service.setServiceParent(self.main_service)
230 engine_service.setServiceParent(self.main_service)
285
231
286 def start_logging(self):
232 def start_logging(self):
287 if self.master_config.Global.log_to_file:
233 if self.master_config.Global.log_to_file:
288 log_filename = self.name + '-' + str(os.getpid()) + '.log'
234 log_filename = self.name + '-' + str(os.getpid()) + '.log'
289 logfile = os.path.join(self.log_dir, log_filename)
235 logfile = os.path.join(self.log_dir, log_filename)
290 open_log_file = open(logfile, 'w')
236 open_log_file = open(logfile, 'w')
291 else:
237 else:
292 open_log_file = sys.stdout
238 open_log_file = sys.stdout
293 log.startLogging(open_log_file)
239 log.startLogging(open_log_file)
294
240
295 def import_statements(self):
241 def import_statements(self):
296 statements = self.master_config.Global.import_statements
242 statements = self.master_config.Global.import_statements
297 for s in statements:
243 for s in statements:
298 try:
244 try:
299 exec s in globals(), locals()
245 exec s in globals(), locals()
300 except:
246 except:
301 log.msg("Error running import statement: %s" % s)
247 log.msg("Error running import statement: %s" % s)
302
248
303 def start_app(self):
249 def start_app(self):
304 # Start the controller service and set things running
250 # Start the controller service and set things running
305 self.main_service.startService()
251 self.main_service.startService()
306 reactor.run()
252 reactor.run()
307
253
308 if __name__ == '__main__':
254
255 def launch_new_instance():
256 """Create and run the IPython controller"""
309 app = IPControllerApp()
257 app = IPControllerApp()
310 app.start()
258 app.start()
@@ -1,20 +1,18 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3
3
4 __docformat__ = "restructuredtext en"
4 #-----------------------------------------------------------------------------
5
5 # Copyright (C) 2008-2009 The IPython Development Team
6 #-------------------------------------------------------------------------------
7 # Copyright (C) 2008 The IPython Development Team
8 #
6 #
9 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
11 #-------------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
12
10
13 #-------------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
14 # Imports
12 # Imports
15 #-------------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
16
15
17 if __name__ == '__main__':
16 from IPython.kernel.ipcontrollerapp import launch_new_instance
18 from IPython.kernel.scripts import ipcontroller
19 ipcontroller.main()
20
17
18 launch_new_instance()
@@ -1,210 +1,210 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 """Setup script for IPython.
3 """Setup script for IPython.
4
4
5 Under Posix environments it works like a typical setup.py script.
5 Under Posix environments it works like a typical setup.py script.
6 Under Windows, the command sdist is not supported, since IPython
6 Under Windows, the command sdist is not supported, since IPython
7 requires utilities which are not available under Windows."""
7 requires utilities which are not available under Windows."""
8
8
9 #-------------------------------------------------------------------------------
9 #-------------------------------------------------------------------------------
10 # Copyright (C) 2008 The IPython Development Team
10 # Copyright (C) 2008 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15
15
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19
19
20 # Stdlib imports
20 # Stdlib imports
21 import os
21 import os
22 import sys
22 import sys
23
23
24 from glob import glob
24 from glob import glob
25
25
26 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
26 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
27 # update it when the contents of directories change.
27 # update it when the contents of directories change.
28 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
28 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
29
29
30 from distutils.core import setup
30 from distutils.core import setup
31
31
32 from IPython.utils.genutils import target_update
32 from IPython.utils.genutils import target_update
33
33
34 from setupbase import (
34 from setupbase import (
35 setup_args,
35 setup_args,
36 find_packages,
36 find_packages,
37 find_package_data,
37 find_package_data,
38 find_scripts,
38 find_scripts,
39 find_data_files,
39 find_data_files,
40 check_for_dependencies
40 check_for_dependencies
41 )
41 )
42
42
43 isfile = os.path.isfile
43 isfile = os.path.isfile
44 pjoin = os.path.join
44 pjoin = os.path.join
45
45
46 #-------------------------------------------------------------------------------
46 #-------------------------------------------------------------------------------
47 # Handle OS specific things
47 # Handle OS specific things
48 #-------------------------------------------------------------------------------
48 #-------------------------------------------------------------------------------
49
49
50 if os.name == 'posix':
50 if os.name == 'posix':
51 os_name = 'posix'
51 os_name = 'posix'
52 elif os.name in ['nt','dos']:
52 elif os.name in ['nt','dos']:
53 os_name = 'windows'
53 os_name = 'windows'
54 else:
54 else:
55 print 'Unsupported operating system:',os.name
55 print 'Unsupported operating system:',os.name
56 sys.exit(1)
56 sys.exit(1)
57
57
58 # Under Windows, 'sdist' has not been supported. Now that the docs build with
58 # Under Windows, 'sdist' has not been supported. Now that the docs build with
59 # Sphinx it might work, but let's not turn it on until someone confirms that it
59 # Sphinx it might work, but let's not turn it on until someone confirms that it
60 # actually works.
60 # actually works.
61 if os_name == 'windows' and 'sdist' in sys.argv:
61 if os_name == 'windows' and 'sdist' in sys.argv:
62 print 'The sdist command is not available under Windows. Exiting.'
62 print 'The sdist command is not available under Windows. Exiting.'
63 sys.exit(1)
63 sys.exit(1)
64
64
65 #-------------------------------------------------------------------------------
65 #-------------------------------------------------------------------------------
66 # Things related to the IPython documentation
66 # Things related to the IPython documentation
67 #-------------------------------------------------------------------------------
67 #-------------------------------------------------------------------------------
68
68
69 # update the manuals when building a source dist
69 # update the manuals when building a source dist
70 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
70 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
71 import textwrap
71 import textwrap
72
72
73 # List of things to be updated. Each entry is a triplet of args for
73 # List of things to be updated. Each entry is a triplet of args for
74 # target_update()
74 # target_update()
75 to_update = [
75 to_update = [
76 # FIXME - Disabled for now: we need to redo an automatic way
76 # FIXME - Disabled for now: we need to redo an automatic way
77 # of generating the magic info inside the rst.
77 # of generating the magic info inside the rst.
78 #('docs/magic.tex',
78 #('docs/magic.tex',
79 #['IPython/Magic.py'],
79 #['IPython/Magic.py'],
80 #"cd doc && ./update_magic.sh" ),
80 #"cd doc && ./update_magic.sh" ),
81
81
82 ('docs/man/ipcluster.1.gz',
82 ('docs/man/ipcluster.1.gz',
83 ['docs/man/ipcluster.1'],
83 ['docs/man/ipcluster.1'],
84 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
84 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
85
85
86 ('docs/man/ipcontroller.1.gz',
86 ('docs/man/ipcontroller.1.gz',
87 ['docs/man/ipcontroller.1'],
87 ['docs/man/ipcontroller.1'],
88 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
88 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
89
89
90 ('docs/man/ipengine.1.gz',
90 ('docs/man/ipengine.1.gz',
91 ['docs/man/ipengine.1'],
91 ['docs/man/ipengine.1'],
92 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
92 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
93
93
94 ('docs/man/ipython.1.gz',
94 ('docs/man/ipython.1.gz',
95 ['docs/man/ipython.1'],
95 ['docs/man/ipython.1'],
96 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
96 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
97
97
98 ('docs/man/ipython-wx.1.gz',
98 ('docs/man/ipython-wx.1.gz',
99 ['docs/man/ipython-wx.1'],
99 ['docs/man/ipython-wx.1'],
100 'cd docs/man && gzip -9c ipython-wx.1 > ipython-wx.1.gz'),
100 'cd docs/man && gzip -9c ipython-wx.1 > ipython-wx.1.gz'),
101
101
102 ('docs/man/ipythonx.1.gz',
102 ('docs/man/ipythonx.1.gz',
103 ['docs/man/ipythonx.1'],
103 ['docs/man/ipythonx.1'],
104 'cd docs/man && gzip -9c ipythonx.1 > ipythonx.1.gz'),
104 'cd docs/man && gzip -9c ipythonx.1 > ipythonx.1.gz'),
105
105
106 ('docs/man/irunner.1.gz',
106 ('docs/man/irunner.1.gz',
107 ['docs/man/irunner.1'],
107 ['docs/man/irunner.1'],
108 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
108 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
109
109
110 ('docs/man/pycolor.1.gz',
110 ('docs/man/pycolor.1.gz',
111 ['docs/man/pycolor.1'],
111 ['docs/man/pycolor.1'],
112 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
112 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
113 ]
113 ]
114
114
115 # Only build the docs if sphinx is present
115 # Only build the docs if sphinx is present
116 try:
116 try:
117 import sphinx
117 import sphinx
118 except ImportError:
118 except ImportError:
119 pass
119 pass
120 else:
120 else:
121 # The Makefile calls the do_sphinx scripts to build html and pdf, so
121 # The Makefile calls the do_sphinx scripts to build html and pdf, so
122 # just one target is enough to cover all manual generation
122 # just one target is enough to cover all manual generation
123
123
124 # First, compute all the dependencies that can force us to rebuild the
124 # First, compute all the dependencies that can force us to rebuild the
125 # docs. Start with the main release file that contains metadata
125 # docs. Start with the main release file that contains metadata
126 docdeps = ['IPython/core/release.py']
126 docdeps = ['IPython/core/release.py']
127 # Inculde all the reST sources
127 # Inculde all the reST sources
128 pjoin = os.path.join
128 pjoin = os.path.join
129 for dirpath,dirnames,filenames in os.walk('docs/source'):
129 for dirpath,dirnames,filenames in os.walk('docs/source'):
130 if dirpath in ['_static','_templates']:
130 if dirpath in ['_static','_templates']:
131 continue
131 continue
132 docdeps += [ pjoin(dirpath,f) for f in filenames
132 docdeps += [ pjoin(dirpath,f) for f in filenames
133 if f.endswith('.txt') ]
133 if f.endswith('.txt') ]
134 # and the examples
134 # and the examples
135 for dirpath,dirnames,filenames in os.walk('docs/example'):
135 for dirpath,dirnames,filenames in os.walk('docs/example'):
136 docdeps += [ pjoin(dirpath,f) for f in filenames
136 docdeps += [ pjoin(dirpath,f) for f in filenames
137 if not f.endswith('~') ]
137 if not f.endswith('~') ]
138 # then, make them all dependencies for the main PDF (the html will get
138 # then, make them all dependencies for the main PDF (the html will get
139 # auto-generated as well).
139 # auto-generated as well).
140 to_update.append(
140 to_update.append(
141 ('docs/dist/ipython.pdf',
141 ('docs/dist/ipython.pdf',
142 docdeps,
142 docdeps,
143 "cd docs && make dist")
143 "cd docs && make dist")
144 )
144 )
145
145
146 [ target_update(*t) for t in to_update ]
146 [ target_update(*t) for t in to_update ]
147
147
148
148
149 #---------------------------------------------------------------------------
149 #---------------------------------------------------------------------------
150 # Find all the packages, package data, scripts and data_files
150 # Find all the packages, package data, scripts and data_files
151 #---------------------------------------------------------------------------
151 #---------------------------------------------------------------------------
152
152
153 packages = find_packages()
153 packages = find_packages()
154 package_data = find_package_data()
154 package_data = find_package_data()
155 scripts = find_scripts()
155 scripts = find_scripts()
156 data_files = find_data_files()
156 data_files = find_data_files()
157
157
158 #---------------------------------------------------------------------------
158 #---------------------------------------------------------------------------
159 # Handle dependencies and setuptools specific things
159 # Handle dependencies and setuptools specific things
160 #---------------------------------------------------------------------------
160 #---------------------------------------------------------------------------
161
161
162 # This dict is used for passing extra arguments that are setuptools
162 # This dict is used for passing extra arguments that are setuptools
163 # specific to setup
163 # specific to setup
164 setuptools_extra_args = {}
164 setuptools_extra_args = {}
165
165
166 if 'setuptools' in sys.modules:
166 if 'setuptools' in sys.modules:
167 setuptools_extra_args['zip_safe'] = False
167 setuptools_extra_args['zip_safe'] = False
168 setuptools_extra_args['entry_points'] = {
168 setuptools_extra_args['entry_points'] = {
169 'console_scripts': [
169 'console_scripts': [
170 'ipython = IPython.core.ipapp:launch_new_instance',
170 'ipython = IPython.core.ipapp:launch_new_instance',
171 'pycolor = IPython.utils.PyColorize:main',
171 'pycolor = IPython.utils.PyColorize:main',
172 'ipcontroller = IPython.kernel.scripts.ipcontroller:main',
172 'ipcontroller = IPython.kernel.ipcontrollerapp:launch_new_instance',
173 'ipengine = IPython.kernel.scripts.ipengine:main',
173 'ipengine = IPython.kernel.scripts.ipengine:main',
174 'ipcluster = IPython.kernel.scripts.ipcluster:main',
174 'ipcluster = IPython.kernel.scripts.ipcluster:main',
175 'ipythonx = IPython.frontend.wx.ipythonx:main',
175 'ipythonx = IPython.frontend.wx.ipythonx:main',
176 'iptest = IPython.testing.iptest:main',
176 'iptest = IPython.testing.iptest:main',
177 'irunner = IPython.lib.irunner:main'
177 'irunner = IPython.lib.irunner:main'
178 ]
178 ]
179 }
179 }
180 setup_args['extras_require'] = dict(
180 setup_args['extras_require'] = dict(
181 kernel = [
181 kernel = [
182 'zope.interface>=3.4.1',
182 'zope.interface>=3.4.1',
183 'Twisted>=8.0.1',
183 'Twisted>=8.0.1',
184 'foolscap>=0.2.6'
184 'foolscap>=0.2.6'
185 ],
185 ],
186 doc='Sphinx>=0.3',
186 doc='Sphinx>=0.3',
187 test='nose>=0.10.1',
187 test='nose>=0.10.1',
188 security='pyOpenSSL>=0.6'
188 security='pyOpenSSL>=0.6'
189 )
189 )
190 # Allow setuptools to handle the scripts
190 # Allow setuptools to handle the scripts
191 scripts = []
191 scripts = []
192 else:
192 else:
193 # If we are running without setuptools, call this function which will
193 # If we are running without setuptools, call this function which will
194 # check for dependencies an inform the user what is needed. This is
194 # check for dependencies an inform the user what is needed. This is
195 # just to make life easy for users.
195 # just to make life easy for users.
196 check_for_dependencies()
196 check_for_dependencies()
197
197
198
198
199 #---------------------------------------------------------------------------
199 #---------------------------------------------------------------------------
200 # Do the actual setup now
200 # Do the actual setup now
201 #---------------------------------------------------------------------------
201 #---------------------------------------------------------------------------
202
202
203 setup_args['packages'] = packages
203 setup_args['packages'] = packages
204 setup_args['package_data'] = package_data
204 setup_args['package_data'] = package_data
205 setup_args['scripts'] = scripts
205 setup_args['scripts'] = scripts
206 setup_args['data_files'] = data_files
206 setup_args['data_files'] = data_files
207 setup_args.update(setuptools_extra_args)
207 setup_args.update(setuptools_extra_args)
208
208
209 if __name__ == '__main__':
209 if __name__ == '__main__':
210 setup(**setup_args)
210 setup(**setup_args)
General Comments 0
You need to be logged in to leave comments. Login now