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