##// END OF EJS Templates
Refactored the command line config system and other aspects of config....
Brian Granger -
Show More
@@ -299,7 +299,7 b' class CommandLineConfigLoader(ConfigLoader):'
299 299
300 300 class ArgParseConfigLoader(CommandLineConfigLoader):
301 301
302 def __init__(self, argv=None, arguments=(), *parser_args, **parser_kw):
302 def __init__(self, argv=None, *parser_args, **parser_kw):
303 303 """Create a config loader for use with argparse.
304 304
305 305 Parameters
@@ -309,11 +309,6 b' class ArgParseConfigLoader(CommandLineConfigLoader):'
309 309 If given, used to read command-line arguments from, otherwise
310 310 sys.argv[1:] is used.
311 311
312 arguments : optional, tuple
313 A tuple of two element tuples each having the form (args, kwargs).
314 Each such pair is passed to parser.add_argument(*args, **kwargs)
315 in sequence to configure the parser.
316
317 312 parser_args : tuple
318 313 A tuple of positional arguments that will be passed to the
319 314 constructor of :class:`argparse.ArgumentParser`.
@@ -326,7 +321,6 b' class ArgParseConfigLoader(CommandLineConfigLoader):'
326 321 if argv == None:
327 322 argv = sys.argv[1:]
328 323 self.argv = argv
329 self.arguments = arguments
330 324 self.parser_args = parser_args
331 325 kwargs = dict(argument_default=argparse.SUPPRESS)
332 326 kwargs.update(parser_kw)
@@ -359,19 +353,9 b' class ArgParseConfigLoader(CommandLineConfigLoader):'
359 353 def _create_parser(self):
360 354 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
361 355 self._add_arguments()
362 self._add_other_arguments()
363 356
364 357 def _add_arguments(self):
365 for argument in self.arguments:
366 # Remove any defaults in case people add them. We can't have
367 # command line default because all default are determined by
368 # traited class attributes.
369 argument[1].pop('default', None)
370 self.parser.add_argument(*argument[0], **argument[1])
371
372 def _add_other_arguments(self):
373 """Meant for subclasses to add their own arguments."""
374 pass
358 raise NotImplementedError("subclasses must implement _add_arguments")
375 359
376 360 def _parse_args(self, args):
377 361 """self.parser->self.parsed_data"""
@@ -61,18 +61,26 b' class TestPyFileCL(TestCase):'
61 61 self.assertEquals(config.Foo.Bam.value, range(10))
62 62 self.assertEquals(config.D.C.value, 'hi there')
63 63
64 class MyLoader1(ArgParseConfigLoader):
65 def _add_arguments(self):
66 p = self.parser
67 p.add_argument('-f', '--foo', dest='Global.foo', type=str)
68 p.add_argument('-b', dest='MyClass.bar', type=int)
69 p.add_argument('-n', dest='n', action='store_true')
70 p.add_argument('Global.bam', type=str)
64 71
65 arguments = (
66 (('-f','--foo'), dict(dest='Global.foo', type=str)),
67 (('-b',), dict(dest='MyClass.bar', type=int)),
68 (('-n',), dict(dest='n', action='store_true')),
69 (('Global.bam',), dict(type=str))
70 )
72 class MyLoader2(ArgParseConfigLoader):
73 def _add_arguments(self):
74 subparsers = self.parser.add_subparsers(dest='subparser_name')
75 subparser1 = subparsers.add_parser('1')
76 subparser1.add_argument('-x',dest='Global.x')
77 subparser2 = subparsers.add_parser('2')
78 subparser2.add_argument('y')
71 79
72 80 class TestArgParseCL(TestCase):
73 81
74 82 def test_basic(self):
75 cl = ArgParseConfigLoader(arguments=arguments)
83 cl = MyLoader1()
76 84 config = cl.load_config('-f hi -b 10 -n wow'.split())
77 85 self.assertEquals(config.Global.foo, 'hi')
78 86 self.assertEquals(config.MyClass.bar, 10)
@@ -84,16 +92,7 b' class TestArgParseCL(TestCase):'
84 92 self.assertEquals(config.Global.bam, 'wow')
85 93
86 94 def test_add_arguments(self):
87
88 class MyLoader(ArgParseConfigLoader):
89 def _add_arguments(self):
90 subparsers = self.parser.add_subparsers(dest='subparser_name')
91 subparser1 = subparsers.add_parser('1')
92 subparser1.add_argument('-x',dest='Global.x')
93 subparser2 = subparsers.add_parser('2')
94 subparser2.add_argument('y')
95
96 cl = MyLoader()
95 cl = MyLoader2()
97 96 config = cl.load_config('2 frobble'.split())
98 97 self.assertEquals(config.subparser_name, '2')
99 98 self.assertEquals(config.y, 'frobble')
@@ -102,10 +101,7 b' class TestArgParseCL(TestCase):'
102 101 self.assertEquals(config.Global.x, 'frobble')
103 102
104 103 def test_argv(self):
105 cl = ArgParseConfigLoader(
106 argv='-f hi -b 10 -n wow'.split(),
107 arguments=arguments
108 )
104 cl = MyLoader1(argv='-f hi -b 10 -n wow'.split())
109 105 config = cl.load_config()
110 106 self.assertEquals(config.Global.foo, 'hi')
111 107 self.assertEquals(config.MyClass.bar, 10)
@@ -48,94 +48,75 b' class ApplicationError(Exception):'
48 48 pass
49 49
50 50
51 app_cl_args = (
52 (('--ipython-dir', ), dict(
51 class BaseAppConfigLoader(ArgParseConfigLoader):
52 """Default command line options for IPython based applications."""
53
54 def _add_ipython_dir(self, parser):
55 """Add the --ipython-dir option to the parser."""
56 paa = parser.add_argument
57 paa('--ipython-dir',
53 58 dest='Global.ipython_dir',type=unicode,
54 59 help=
55 60 """Set to override default location of the IPython directory
56 IPYTHON_DIR, stored as Global.ipython_dir. This can also be specified
57 through the environment variable IPYTHON_DIR.""",
58 metavar='Global.ipython_dir') ),
59 (('-p', '--profile',), dict(
60 dest='Global.profile',type=unicode,
61 help=
62 """The string name of the ipython profile to be used. Assume that your
63 config file is ipython_config-<name>.py (looks in current dir first,
64 then in IPYTHON_DIR). This is a quick way to keep and load multiple
65 config files for different tasks, especially if include your basic one
66 in your more specialized ones. You can keep a basic
67 IPYTHON_DIR/ipython_config.py file and then have other 'profiles' which
68 include this one and load extra things for particular tasks.""",
69 metavar='Global.profile') ),
70 (('--log-level',), dict(
61 IPYTHON_DIR, stored as Global.ipython_dir. This can also be
62 specified through the environment variable IPYTHON_DIR.""",
63 metavar='Global.ipython_dir')
64
65 def _add_log_level(self, parser):
66 """Add the --log-level option to the parser."""
67 paa = parser.add_argument
68 paa('--log-level',
71 69 dest="Global.log_level",type=int,
72 70 help='Set the log level (0,10,20,30,40,50). Default is 30.',
73 metavar='Global.log_level')),
74 (('--config-file',), dict(
75 dest='Global.config_file',type=unicode,
76 help=
77 """Set the config file name to override default. Normally IPython
78 loads ipython_config.py (from current directory) or
79 IPYTHON_DIR/ipython_config.py. If the loading of your config file
80 fails, IPython starts with a bare bones configuration (no modules
81 loaded at all).""",
82 metavar='Global.config_file')),
83 )
71 metavar='Global.log_level')
72
73 def _add_arguments(self):
74 self._add_ipython_dir(self.parser)
75 self._add_log_level(self.parser)
76
84 77
85 78 class Application(object):
86 79 """Load a config, construct components and set them running.
87 80
88 The configuration of an application can be done via four different Config
89 objects, which are loaded and ultimately merged into a single one used from
90 that point on by the app. These are:
81 The configuration of an application can be done via three different Config
82 objects, which are loaded and ultimately merged into a single one used
83 from that point on by the app. These are:
91 84
92 85 1. default_config: internal defaults, implemented in code.
93 86 2. file_config: read from the filesystem.
94 87 3. command_line_config: read from the system's command line flags.
95 4. constructor_config: passed parametrically to the constructor.
96 88
97 89 During initialization, 3 is actually read before 2, since at the
98 90 command-line one may override the location of the file to be read. But the
99 91 above is the order in which the merge is made.
100
101 There is a final config object can be created and passed to the
102 constructor: override_config. If it exists, this completely overrides the
103 configs 2-4 above (the default is still used to ensure that all needed
104 fields at least are created). This makes it easier to create
105 parametrically (e.g. in testing or sphinx plugins) objects with a known
106 configuration, that are unaffected by whatever arguments may be present in
107 sys.argv or files in the user's various directories.
108 92 """
109 93
110 94 name = u'ipython'
111 95 description = 'IPython: an enhanced interactive Python shell.'
112 #: usage message printed by argparse. If None, auto-generate
96 #: Usage message printed by argparse. If None, auto-generate
113 97 usage = None
98 #: The command line config loader. Subclass of ArgParseConfigLoader.
99 command_line_loader = BaseAppConfigLoader
100 #: The name of the config file to load.
114 101 config_file_name = u'ipython_config.py'
115 #: Track the default and actual separately because some messages are
116 #: only printed if we aren't using the default.
102 #: The name of the default config file. Track separately from the actual
103 #: name because some logic happens only if we aren't using the default.
117 104 default_config_file_name = config_file_name
118 105 default_log_level = logging.WARN
119 106 #: Set by --profile option
120 107 profile_name = None
121 108 #: User's ipython directory, typically ~/.ipython/
122 109 ipython_dir = None
123 #: internal defaults, implemented in code.
110 #: Internal defaults, implemented in code.
124 111 default_config = None
125 #: read from the filesystem
112 #: Read from the filesystem.
126 113 file_config = None
127 #: read from the system's command line flags
114 #: Read from the system's command line flags.
128 115 command_line_config = None
129 #: passed parametrically to the constructor.
130 constructor_config = None
131 #: final override, if given supercedes file/command/constructor configs
132 override_config = None
116 #: The final config that will be passed to the component.
117 master_config = None
133 118 #: A reference to the argv to be used (typically ends up being sys.argv[1:])
134 119 argv = None
135 #: Default command line arguments. Subclasses should create a new tuple
136 #: that *includes* these.
137 cl_arguments = app_cl_args
138
139 120 #: extra arguments computed by the command-line loader
140 121 extra_args = None
141 122
@@ -146,10 +127,8 b' class Application(object):'
146 127 # Class choices for things that will be instantiated at runtime.
147 128 _CrashHandler = crashhandler.CrashHandler
148 129
149 def __init__(self, argv=None, constructor_config=None, override_config=None):
130 def __init__(self, argv=None):
150 131 self.argv = sys.argv[1:] if argv is None else argv
151 self.constructor_config = constructor_config
152 self.override_config = override_config
153 132 self.init_logger()
154 133
155 134 def init_logger(self):
@@ -194,7 +173,6 b' class Application(object):'
194 173 self.log_default_config()
195 174 self.set_default_config_log_level()
196 175
197 if self.override_config is None:
198 176 # Command-line config
199 177 self.pre_load_command_line_config()
200 178 self.load_command_line_config()
@@ -209,7 +187,6 b' class Application(object):'
209 187 self.find_config_file_name()
210 188 self.find_config_file_paths()
211 189
212 if self.override_config is None:
213 190 # File-based config
214 191 self.pre_load_file_config()
215 192 self.load_file_config()
@@ -270,10 +247,11 b' class Application(object):'
270 247
271 248 def create_command_line_config(self):
272 249 """Create and return a command line config loader."""
273 return ArgParseConfigLoader(self.argv, self.cl_arguments,
250 return self.command_line_loader(
251 self.argv,
274 252 description=self.description,
275 253 version=release.version,
276 usage=self.usage,
254 usage=self.usage
277 255 )
278 256
279 257 def pre_load_command_line_config(self):
@@ -418,13 +396,9 b' class Application(object):'
418 396 """Merge the default, command line and file config objects."""
419 397 config = Config()
420 398 config._merge(self.default_config)
421 if self.override_config is None:
422 399 config._merge(self.file_config)
423 400 config._merge(self.command_line_config)
424 if self.constructor_config is not None:
425 config._merge(self.constructor_config)
426 else:
427 config._merge(self.override_config)
401
428 402 # XXX fperez - propose to Brian we rename master_config to simply
429 403 # config, I think this is going to be heavily used in examples and
430 404 # application code and the name is shorter/easier to find/remember.
@@ -221,3 +221,4 b' class IPythonCrashHandler(CrashHandler):'
221 221 pass
222 222
223 223 return ''.join(report)
224
@@ -28,7 +28,7 b' import os'
28 28 import sys
29 29
30 30 from IPython.core import crashhandler
31 from IPython.core.application import Application
31 from IPython.core.application import Application, BaseAppConfigLoader
32 32 from IPython.core.iplib import InteractiveShell
33 33 from IPython.config.loader import (
34 34 Config,
@@ -42,11 +42,37 b' from . import usage'
42 42 # Globals, utilities and helpers
43 43 #-----------------------------------------------------------------------------
44 44
45 #: The default config file name for this application.
45 46 default_config_file_name = u'ipython_config.py'
46 47
47 cl_args = (
48 (('--autocall',), dict(
49 type=int, dest='InteractiveShell.autocall',
48
49 class IPAppConfigLoader(BaseAppConfigLoader):
50
51 def _add_arguments(self):
52 super(IPAppConfigLoader, self)._add_arguments()
53 paa = self.parser.add_argument
54 paa('-p',
55 '--profile', dest='Global.profile', type=unicode,
56 help=
57 """The string name of the ipython profile to be used. Assume that your
58 config file is ipython_config-<name>.py (looks in current dir first,
59 then in IPYTHON_DIR). This is a quick way to keep and load multiple
60 config files for different tasks, especially if include your basic one
61 in your more specialized ones. You can keep a basic
62 IPYTHON_DIR/ipython_config.py file and then have other 'profiles' which
63 include this one and load extra things for particular tasks.""",
64 metavar='Global.profile')
65 paa('--config-file',
66 dest='Global.config_file', type=unicode,
67 help=
68 """Set the config file name to override default. Normally IPython
69 loads ipython_config.py (from current directory) or
70 IPYTHON_DIR/ipython_config.py. If the loading of your config file
71 fails, IPython starts with a bare bones configuration (no modules
72 loaded at all).""",
73 metavar='Global.config_file')
74 paa('--autocall',
75 dest='InteractiveShell.autocall', type=int,
50 76 help=
51 77 """Make IPython automatically call any callable object even if you
52 78 didn't type explicit parentheses. For example, 'str 43' becomes
@@ -56,41 +82,33 b' cl_args = ('
56 82 objects are automatically called (even if no arguments are present).
57 83 The default is '1'.""",
58 84 metavar='InteractiveShell.autocall')
59 ),
60 (('--autoindent',), dict(
85 paa('--autoindent',
61 86 action='store_true', dest='InteractiveShell.autoindent',
62 87 help='Turn on autoindenting.')
63 ),
64 (('--no-autoindent',), dict(
88 paa('--no-autoindent',
65 89 action='store_false', dest='InteractiveShell.autoindent',
66 90 help='Turn off autoindenting.')
67 ),
68 (('--automagic',), dict(
91 paa('--automagic',
69 92 action='store_true', dest='InteractiveShell.automagic',
70 help='Turn on the auto calling of magic commands.'
71 'Type %%magic at the IPython prompt for more information.')
72 ),
73 (('--no-automagic',), dict(
93 help=
94 """Turn on the auto calling of magic commands. Type %%magic at the
95 IPython prompt for more information.""")
96 paa('--no-automagic',
74 97 action='store_false', dest='InteractiveShell.automagic',
75 98 help='Turn off the auto calling of magic commands.')
76 ),
77 (('--autoedit-syntax',), dict(
99 paa('--autoedit-syntax',
78 100 action='store_true', dest='InteractiveShell.autoedit_syntax',
79 101 help='Turn on auto editing of files with syntax errors.')
80 ),
81 (('--no-autoedit-syntax',), dict(
102 paa('--no-autoedit-syntax',
82 103 action='store_false', dest='InteractiveShell.autoedit_syntax',
83 104 help='Turn off auto editing of files with syntax errors.')
84 ),
85 (('--banner',), dict(
105 paa('--banner',
86 106 action='store_true', dest='Global.display_banner',
87 107 help='Display a banner upon starting IPython.')
88 ),
89 (('--no-banner',), dict(
108 paa('--no-banner',
90 109 action='store_false', dest='Global.display_banner',
91 110 help="Don't display a banner upon starting IPython.")
92 ),
93 (('--cache-size',), dict(
111 paa('--cache-size',
94 112 type=int, dest='InteractiveShell.cache_size',
95 113 help=
96 114 """Set the size of the output cache. The default is 1000, you can
@@ -98,20 +116,16 b' cl_args = ('
98 116 disables the caching system, and the minimum value accepted is 20 (if
99 117 you provide a value less than 20, it is reset to 0 and a warning is
100 118 issued). This limit is defined because otherwise you'll spend more
101 time re-flushing a too small cache than working.
102 """,
119 time re-flushing a too small cache than working""",
103 120 metavar='InteractiveShell.cache_size')
104 ),
105 (('--classic',), dict(
121 paa('--classic',
106 122 action='store_true', dest='Global.classic',
107 123 help="Gives IPython a similar feel to the classic Python prompt.")
108 ),
109 (('--colors',), dict(
124 paa('--colors',
110 125 type=str, dest='InteractiveShell.colors',
111 126 help="Set the color scheme (NoColor, Linux, and LightBG).",
112 127 metavar='InteractiveShell.colors')
113 ),
114 (('--color-info',), dict(
128 paa('--color-info',
115 129 action='store_true', dest='InteractiveShell.color_info',
116 130 help=
117 131 """IPython can display information about objects via a set of func-
@@ -122,27 +136,20 b' cl_args = ('
122 136 it and turn it on permanently in your ipython_config.py file if it
123 137 works for you. Test it and turn it on permanently if it works with
124 138 your system. The magic function %%color_info allows you to toggle this
125 inter- actively for testing."""
126 )
127 ),
128 (('--no-color-info',), dict(
139 inter- actively for testing.""")
140 paa('--no-color-info',
129 141 action='store_false', dest='InteractiveShell.color_info',
130 142 help="Disable using colors for info related things.")
131 ),
132 (('--confirm-exit',), dict(
143 paa('--confirm-exit',
133 144 action='store_true', dest='InteractiveShell.confirm_exit',
134 145 help=
135 146 """Set to confirm when you try to exit IPython with an EOF (Control-D
136 147 in Unix, Control-Z/Enter in Windows). By typing 'exit', 'quit' or
137 '%%Exit', you can force a direct exit without any confirmation.
138 """
139 )
140 ),
141 (('--no-confirm-exit',), dict(
148 '%%Exit', you can force a direct exit without any confirmation.""")
149 paa('--no-confirm-exit',
142 150 action='store_false', dest='InteractiveShell.confirm_exit',
143 151 help="Don't prompt the user when exiting.")
144 ),
145 (('--deep-reload',), dict(
152 paa('--deep-reload',
146 153 action='store_true', dest='InteractiveShell.deep_reload',
147 154 help=
148 155 """Enable deep (recursive) reloading by default. IPython can use the
@@ -154,47 +161,37 b' cl_args = ('
154 161 deep_reload will still be available as dreload(). This fea- ture is off
155 162 by default [which means that you have both normal reload() and
156 163 dreload()].""")
157 ),
158 (('--no-deep-reload',), dict(
164 paa('--no-deep-reload',
159 165 action='store_false', dest='InteractiveShell.deep_reload',
160 166 help="Disable deep (recursive) reloading by default.")
161 ),
162 (('--editor',), dict(
167 paa('--editor',
163 168 type=str, dest='InteractiveShell.editor',
164 169 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
165 170 metavar='InteractiveShell.editor')
166 ),
167 (('--log','-l'), dict(
171 paa('--log','-l',
168 172 action='store_true', dest='InteractiveShell.logstart',
169 173 help="Start logging to the default log file (./ipython_log.py).")
170 ),
171 (('--logfile','-lf'), dict(
174 paa('--logfile','-lf',
172 175 type=unicode, dest='InteractiveShell.logfile',
173 176 help="Start logging to logfile with this name.",
174 177 metavar='InteractiveShell.logfile')
175 ),
176 (('--log-append','-la'), dict(
178 paa('--log-append','-la',
177 179 type=unicode, dest='InteractiveShell.logappend',
178 180 help="Start logging to the given file in append mode.",
179 181 metavar='InteractiveShell.logfile')
180 ),
181 (('--pdb',), dict(
182 paa('--pdb',
182 183 action='store_true', dest='InteractiveShell.pdb',
183 184 help="Enable auto calling the pdb debugger after every exception.")
184 ),
185 (('--no-pdb',), dict(
185 paa('--no-pdb',
186 186 action='store_false', dest='InteractiveShell.pdb',
187 187 help="Disable auto calling the pdb debugger after every exception.")
188 ),
189 (('--pprint',), dict(
188 paa('--pprint',
190 189 action='store_true', dest='InteractiveShell.pprint',
191 190 help="Enable auto pretty printing of results.")
192 ),
193 (('--no-pprint',), dict(
191 paa('--no-pprint',
194 192 action='store_false', dest='InteractiveShell.pprint',
195 193 help="Disable auto auto pretty printing of results.")
196 ),
197 (('--prompt-in1','-pi1'), dict(
194 paa('--prompt-in1','-pi1',
198 195 type=str, dest='InteractiveShell.prompt_in1',
199 196 help=
200 197 """Set the main input prompt ('In [\#]: '). Note that if you are using
@@ -205,8 +202,7 b' cl_args = ('
205 202 prompt escapes are described in detail in the Customization section of
206 203 the IPython manual.""",
207 204 metavar='InteractiveShell.prompt_in1')
208 ),
209 (('--prompt-in2','-pi2'), dict(
205 paa('--prompt-in2','-pi2',
210 206 type=str, dest='InteractiveShell.prompt_in2',
211 207 help=
212 208 """Set the secondary input prompt (' .\D.: '). Similar to the previous
@@ -216,25 +212,20 b' cl_args = ('
216 212 Default: ' .\D.: ' (note three spaces at the start for alignment with
217 213 'In [\#]')""",
218 214 metavar='InteractiveShell.prompt_in2')
219 ),
220 (('--prompt-out','-po'), dict(
215 paa('--prompt-out','-po',
221 216 type=str, dest='InteractiveShell.prompt_out',
222 217 help="Set the output prompt ('Out[\#]:')",
223 218 metavar='InteractiveShell.prompt_out')
224 ),
225 (('--quick',), dict(
219 paa('--quick',
226 220 action='store_true', dest='Global.quick',
227 221 help="Enable quick startup with no config files.")
228 ),
229 (('--readline',), dict(
222 paa('--readline',
230 223 action='store_true', dest='InteractiveShell.readline_use',
231 224 help="Enable readline for command line usage.")
232 ),
233 (('--no-readline',), dict(
225 paa('--no-readline',
234 226 action='store_false', dest='InteractiveShell.readline_use',
235 227 help="Disable readline for command line usage.")
236 ),
237 (('--screen-length','-sl'), dict(
228 paa('--screen-length','-sl',
238 229 type=int, dest='InteractiveShell.screen_length',
239 230 help=
240 231 """Number of lines of your screen, used to control printing of very
@@ -247,35 +238,28 b' cl_args = ('
247 238 curses support), specify it yourself. Otherwise don't change the
248 239 default.""",
249 240 metavar='InteractiveShell.screen_length')
250 ),
251 (('--separate-in','-si'), dict(
241 paa('--separate-in','-si',
252 242 type=str, dest='InteractiveShell.separate_in',
253 243 help="Separator before input prompts. Default '\\n'.",
254 244 metavar='InteractiveShell.separate_in')
255 ),
256 (('--separate-out','-so'), dict(
245 paa('--separate-out','-so',
257 246 type=str, dest='InteractiveShell.separate_out',
258 247 help="Separator before output prompts. Default 0 (nothing).",
259 248 metavar='InteractiveShell.separate_out')
260 ),
261 (('--separate-out2','-so2'), dict(
249 paa('--separate-out2','-so2',
262 250 type=str, dest='InteractiveShell.separate_out2',
263 251 help="Separator after output prompts. Default 0 (nonight).",
264 252 metavar='InteractiveShell.separate_out2')
265 ),
266 (('-no-sep',), dict(
253 paa('-no-sep',
267 254 action='store_true', dest='Global.nosep',
268 255 help="Eliminate all spacing between prompts.")
269 ),
270 (('--term-title',), dict(
256 paa('--term-title',
271 257 action='store_true', dest='InteractiveShell.term_title',
272 258 help="Enable auto setting the terminal title.")
273 ),
274 (('--no-term-title',), dict(
259 paa('--no-term-title',
275 260 action='store_false', dest='InteractiveShell.term_title',
276 261 help="Disable auto setting the terminal title.")
277 ),
278 (('--xmode',), dict(
262 paa('--xmode',
279 263 type=str, dest='InteractiveShell.xmode',
280 264 help=
281 265 """Exception reporting mode ('Plain','Context','Verbose'). Plain:
@@ -290,57 +274,47 b' cl_args = ('
290 274 it more than once).
291 275 """,
292 276 metavar='InteractiveShell.xmode')
293 ),
294 (('--ext',), dict(
277 paa('--ext',
295 278 type=str, dest='Global.extra_extension',
296 279 help="The dotted module name of an IPython extension to load.",
297 280 metavar='Global.extra_extension')
298 ),
299 (('-c',), dict(
281 paa('-c',
300 282 type=str, dest='Global.code_to_run',
301 283 help="Execute the given command string.",
302 284 metavar='Global.code_to_run')
303 ),
304 (('-i',), dict(
285 paa('-i',
305 286 action='store_true', dest='Global.force_interact',
306 287 help=
307 "If running code from the command line, become interactive afterwards."
308 )
309 ),
288 "If running code from the command line, become interactive afterwards.")
310 289
311 290 # Options to start with GUI control enabled from the beginning
312 (('--gui',), dict(
291 paa('--gui',
313 292 type=str, dest='Global.gui',
314 293 help="Enable GUI event loop integration ('qt', 'wx', 'gtk').",
315 294 metavar='gui-mode')
316 ),
317
318 (('--pylab','-pylab'), dict(
295 paa('--pylab','-pylab',
319 296 type=str, dest='Global.pylab',
320 297 nargs='?', const='auto', metavar='gui-mode',
321 298 help="Pre-load matplotlib and numpy for interactive use. "+
322 299 "If no value is given, the gui backend is matplotlib's, else use "+
323 300 "one of: ['tk', 'qt', 'wx', 'gtk'].")
324 ),
325 301
326 302 # Legacy GUI options. Leave them in for backwards compatibility, but the
327 303 # 'thread' names are really a misnomer now.
328 (('--wthread','-wthread'), dict(
304 paa('--wthread', '-wthread',
329 305 action='store_true', dest='Global.wthread',
330 help="Enable wxPython event loop integration "+
331 "(DEPRECATED, use --gui wx)")
332 ),
333 (('--q4thread','--qthread','-q4thread','-qthread'), dict(
306 help=
307 """Enable wxPython event loop integration. (DEPRECATED, use --gui wx)""")
308 paa('--q4thread', '--qthread', '-q4thread', '-qthread',
334 309 action='store_true', dest='Global.q4thread',
335 help="Enable Qt4 event loop integration. Qt3 is no longer supported. "+
336 "(DEPRECATED, use --gui qt)")
337 ),
338 (('--gthread','-gthread'), dict(
310 help=
311 """Enable Qt4 event loop integration. Qt3 is no longer supported.
312 (DEPRECATED, use --gui qt)""")
313 paa('--gthread', '-gthread',
339 314 action='store_true', dest='Global.gthread',
340 help="Enable GTK event loop integration. "+
341 "(DEPRECATED, use --gui gtk)")
342 ),
343 )
315 help=
316 """Enable GTK event loop integration. (DEPRECATED, use --gui gtk)""")
317
344 318
345 319 #-----------------------------------------------------------------------------
346 320 # Main classes and functions
@@ -350,45 +324,13 b' class IPythonApp(Application):'
350 324 name = u'ipython'
351 325 #: argparse formats better the 'usage' than the 'description' field
352 326 description = None
353 #: usage message printed by argparse. If None, auto-generate
354 327 usage = usage.cl_usage
355
328 command_line_loader = IPAppConfigLoader
356 329 config_file_name = default_config_file_name
357 330
358 cl_arguments = Application.cl_arguments + cl_args
359
360 331 # Private and configuration attributes
361 332 _CrashHandler = crashhandler.IPythonCrashHandler
362 333
363 def __init__(self, argv=None,
364 constructor_config=None, override_config=None,
365 **shell_params):
366 """Create a new IPythonApp.
367
368 See the parent class for details on how configuration is handled.
369
370 Parameters
371 ----------
372 argv : optional, list
373 If given, used as the command-line argv environment to read arguments
374 from.
375
376 constructor_config : optional, Config
377 If given, additional config that is merged last, after internal
378 defaults, command-line and file-based configs.
379
380 override_config : optional, Config
381 If given, config that overrides all others unconditionally (except
382 for internal defaults, which ensure that all parameters exist).
383
384 shell_params : optional, dict
385 All other keywords are passed to the :class:`iplib.InteractiveShell`
386 constructor.
387 """
388 super(IPythonApp, self).__init__(argv, constructor_config,
389 override_config)
390 self.shell_params = shell_params
391
392 334 def create_default_config(self):
393 335 super(IPythonApp, self).create_default_config()
394 336 # Eliminate multiple lookups
@@ -473,8 +415,7 b' class IPythonApp(Application):'
473 415 sys.path.insert(0, '')
474 416
475 417 # Create an InteractiveShell instance
476 self.shell = InteractiveShell(None, self.master_config,
477 **self.shell_params )
418 self.shell = InteractiveShell(None, self.master_config)
478 419
479 420 def post_construct(self):
480 421 """Do actions after construct, but before starting the app."""
@@ -646,3 +587,4 b' def launch_new_instance():'
646 587 """Create and run a full blown IPython instance"""
647 588 app = IPythonApp()
648 589 app.start()
590
@@ -25,7 +25,7 b' import warnings'
25 25 from twisted.python import log
26 26
27 27 from IPython.config.loader import PyFileConfigLoader
28 from IPython.core.application import Application
28 from IPython.core.application import Application, BaseAppConfigLoader
29 29 from IPython.core.component import Component
30 30 from IPython.utils.path import (
31 31 get_ipython_package_dir,
@@ -46,7 +46,7 b" warnings.filterwarnings('ignore', 'the sha module is deprecated',"
46 46 DeprecationWarning)
47 47
48 48 #-----------------------------------------------------------------------------
49 # Classes and functions
49 # Module errors
50 50 #-----------------------------------------------------------------------------
51 51
52 52 class ClusterDirError(Exception):
@@ -57,6 +57,10 b' class PIDFileError(Exception):'
57 57 pass
58 58
59 59
60 #-----------------------------------------------------------------------------
61 # Class for managing cluster directories
62 #-----------------------------------------------------------------------------
63
60 64 class ClusterDir(Component):
61 65 """An object to manage the cluster directory and its resources.
62 66
@@ -232,37 +236,62 b' class ClusterDir(Component):'
232 236 return ClusterDir(cluster_dir)
233 237
234 238
235 # Default command line options for IPython cluster applications.
236 cl_args = (
237 (('--ipython-dir',), dict(
238 dest='Global.ipython_dir',type=unicode,
239 help='Set to override default location of Global.ipython_dir.',
240 metavar='Global.ipython_dir') ),
241 (('-p', '--profile',), dict(
239 #-----------------------------------------------------------------------------
240 # Command line options
241 #-----------------------------------------------------------------------------
242
243 class ClusterDirConfigLoader(BaseAppConfigLoader):
244
245 def _add_cluster_profile(self, parser):
246 paa = parser.add_argument
247 paa('-p', '--profile',
242 248 dest='Global.profile',type=unicode,
243 249 help=
244 250 """The string name of the profile to be used. This determines the name
245 251 of the cluster dir as: cluster_<profile>. The default profile is named
246 252 'default'. The cluster directory is resolve this way if the
247 253 --cluster-dir option is not used.""",
248 metavar='Global.profile') ),
249 (('--cluster-dir',), dict(
254 metavar='Global.profile')
255
256 def _add_cluster_dir(self, parser):
257 paa = parser.add_argument
258 paa('--cluster-dir',
250 259 dest='Global.cluster_dir',type=unicode,
251 260 help="""Set the cluster dir. This overrides the logic used by the
252 261 --profile option.""",
253 metavar='Global.cluster_dir') ),
254 (('--work-dir',), dict(
262 metavar='Global.cluster_dir')
263
264 def _add_work_dir(self, parser):
265 paa = parser.add_argument
266 paa('--work-dir',
255 267 dest='Global.work_dir',type=unicode,
256 268 help='Set the working dir for the process.',
257 metavar='Global.work_dir') ),
258 (('--clean-logs',), dict(
269 metavar='Global.work_dir')
270
271 def _add_clean_logs(self, parser):
272 paa = parser.add_argument
273 paa('--clean-logs',
259 274 dest='Global.clean_logs', action='store_true',
260 help='Delete old log flies before starting.') ),
261 (('--no-clean-logs',), dict(
275 help='Delete old log flies before starting.')
276
277 def _add_no_clean_logs(self, parser):
278 paa = parser.add_argument
279 paa('--no-clean-logs',
262 280 dest='Global.clean_logs', action='store_false',
263 help="Don't Delete old log flies before starting.") ),
264 )
281 help="Don't Delete old log flies before starting.")
265 282
283 def _add_arguments(self):
284 super(ClusterDirConfigLoader, self)._add_arguments()
285 self._add_cluster_profile(self.parser)
286 self._add_cluster_dir(self.parser)
287 self._add_work_dir(self.parser)
288 self._add_clean_logs(self.parser)
289 self._add_no_clean_logs(self.parser)
290
291
292 #-----------------------------------------------------------------------------
293 # Main application
294 #-----------------------------------------------------------------------------
266 295
267 296 class ApplicationWithClusterDir(Application):
268 297 """An application that puts everything into a cluster directory.
@@ -283,10 +312,9 b' class ApplicationWithClusterDir(Application):'
283 312 dir and named the value of the ``config_file_name`` class attribute.
284 313 """
285 314
315 command_line_loader = ClusterDirConfigLoader
286 316 auto_create_cluster_dir = True
287 317
288 cl_arguments = Application.cl_arguments + cl_args
289
290 318 def create_default_config(self):
291 319 super(ApplicationWithClusterDir, self).create_default_config()
292 320 self.default_config.Global.profile = u'default'
@@ -462,3 +490,4 b' class ApplicationWithClusterDir(Application):'
462 490 return pid
463 491 else:
464 492 raise PIDFileError('pid file not found: %s' % pid_file)
493
@@ -22,159 +22,162 b' import signal'
22 22 if os.name=='posix':
23 23 from twisted.scripts._twistd_unix import daemonize
24 24
25 from IPython.core import release
25 from twisted.internet import reactor, defer
26 from twisted.python import log, failure
27
28
26 29 from IPython.external.argparse import ArgumentParser, SUPPRESS
27 from IPython.config.loader import ArgParseConfigLoader
28 30 from IPython.utils.importstring import import_item
29
30 31 from IPython.kernel.clusterdir import (
31 ApplicationWithClusterDir, ClusterDirError, PIDFileError
32 ApplicationWithClusterDir, ClusterDirConfigLoader,
33 ClusterDirError, PIDFileError
32 34 )
33 35
34 from twisted.internet import reactor, defer
35 from twisted.python import log, failure
36
37 36
38 37 #-----------------------------------------------------------------------------
39 # The ipcluster application
38 # Module level variables
40 39 #-----------------------------------------------------------------------------
41 40
42 41
42 default_config_file_name = u'ipcluster_config.py'
43
44
45 _description = """\
46 Start an IPython cluster for parallel computing.\n\n
47
48 An IPython cluster consists of 1 controller and 1 or more engines.
49 This command automates the startup of these processes using a wide
50 range of startup methods (SSH, local processes, PBS, mpiexec,
51 Windows HPC Server 2008). To start a cluster with 4 engines on your
52 local host simply do "ipcluster start -n 4". For more complex usage
53 you will typically do "ipcluster create -p mycluster", then edit
54 configuration files, followed by "ipcluster start -p mycluster -n 4".
55 """
56
57
43 58 # Exit codes for ipcluster
44 59
45 60 # This will be the exit code if the ipcluster appears to be running because
46 61 # a .pid file exists
47 62 ALREADY_STARTED = 10
48 63
64
49 65 # This will be the exit code if ipcluster stop is run, but there is not .pid
50 66 # file to be found.
51 67 ALREADY_STOPPED = 11
52 68
53 69
54 class IPClusterCLLoader(ArgParseConfigLoader):
70 #-----------------------------------------------------------------------------
71 # Command line options
72 #-----------------------------------------------------------------------------
73
74
75 class IPClusterAppConfigLoader(ClusterDirConfigLoader):
76
77 def _add_arguments(self):
78 # Don't call ClusterDirConfigLoader._add_arguments as we don't want
79 # its defaults on self.parser. Instead, we will put those on
80 # default options on our subparsers.
55 81
56 def _add_other_arguments(self):
57 82 # This has all the common options that all subcommands use
58 parent_parser1 = ArgumentParser(add_help=False,
59 argument_default=SUPPRESS)
60 parent_parser1.add_argument('--ipython-dir',
61 dest='Global.ipython_dir',type=unicode,
62 help='Set to override default location of Global.ipython_dir.',
63 metavar='Global.ipython_dir')
64 parent_parser1.add_argument('--log-level',
65 dest="Global.log_level",type=int,
66 help='Set the log level (0,10,20,30,40,50). Default is 30.',
67 metavar='Global.log_level')
83 parent_parser1 = ArgumentParser(
84 add_help=False,
85 argument_default=SUPPRESS
86 )
87 self._add_ipython_dir(parent_parser1)
88 self._add_log_level(parent_parser1)
68 89
69 90 # This has all the common options that other subcommands use
70 parent_parser2 = ArgumentParser(add_help=False,
71 argument_default=SUPPRESS)
72 parent_parser2.add_argument('-p','--profile',
73 dest='Global.profile',type=unicode,
74 help='The string name of the profile to be used. This determines '
75 'the name of the cluster dir as: cluster_<profile>. The default profile '
76 'is named "default". The cluster directory is resolve this way '
77 'if the --cluster-dir option is not used.',
78 metavar='Global.profile')
79 parent_parser2.add_argument('--cluster-dir',
80 dest='Global.cluster_dir',type=unicode,
81 help='Set the cluster dir. This overrides the logic used by the '
82 '--profile option.',
83 metavar='Global.cluster_dir'),
84 parent_parser2.add_argument('--work-dir',
85 dest='Global.work_dir',type=unicode,
86 help='Set the working dir for the process.',
87 metavar='Global.work_dir')
88 parent_parser2.add_argument('--log-to-file',
89 action='store_true', dest='Global.log_to_file',
90 help='Log to a file in the log directory (default is stdout)'
91 parent_parser2 = ArgumentParser(
92 add_help=False,
93 argument_default=SUPPRESS
91 94 )
95 self._add_cluster_profile(parent_parser2)
96 self._add_cluster_dir(parent_parser2)
97 self._add_work_dir(parent_parser2)
98 paa = parent_parser2.add_argument
99 paa('--log-to-file',
100 action='store_true', dest='Global.log_to_file',
101 help='Log to a file in the log directory (default is stdout)')
92 102
103 # Create the object used to create the subparsers.
93 104 subparsers = self.parser.add_subparsers(
94 105 dest='Global.subcommand',
95 106 title='ipcluster subcommands',
96 description='ipcluster has a variety of subcommands. '
97 'The general way of running ipcluster is "ipcluster <cmd> '
98 ' [options]""',
99 help='For more help, type "ipcluster <cmd> -h"')
107 description=
108 """ipcluster has a variety of subcommands. The general way of
109 running ipcluster is 'ipcluster <cmd> [options]'""",
110 help="For more help, type 'ipcluster <cmd> -h'"
111 )
100 112
113 # The "list" subcommand parser
101 114 parser_list = subparsers.add_parser(
102 115 'list',
103 116 help='List all clusters in cwd and ipython_dir.',
104 117 parents=[parent_parser1]
105 118 )
106 119
120 # The "create" subcommand parser
107 121 parser_create = subparsers.add_parser(
108 122 'create',
109 123 help='Create a new cluster directory.',
110 124 parents=[parent_parser1, parent_parser2]
111 125 )
112 parser_create.add_argument(
113 '--reset-config',
126 paa = parser_create.add_argument
127 paa('--reset-config',
114 128 dest='Global.reset_config', action='store_true',
115 help='Recopy the default config files to the cluster directory. '
116 'You will loose any modifications you have made to these files.'
117 )
129 help=
130 """Recopy the default config files to the cluster directory.
131 You will loose any modifications you have made to these files.""")
118 132
133 # The "start" subcommand parser
119 134 parser_start = subparsers.add_parser(
120 135 'start',
121 136 help='Start a cluster.',
122 137 parents=[parent_parser1, parent_parser2]
123 138 )
124 parser_start.add_argument(
125 '-n', '--number',
139 paa = parser_start.add_argument
140 paa('-n', '--number',
126 141 type=int, dest='Global.n',
127 142 help='The number of engines to start.',
128 metavar='Global.n'
129 )
130 parser_start.add_argument('--clean-logs',
143 metavar='Global.n')
144 paa('--clean-logs',
131 145 dest='Global.clean_logs', action='store_true',
132 help='Delete old log flies before starting.',
133 )
134 parser_start.add_argument('--no-clean-logs',
146 help='Delete old log flies before starting.')
147 paa('--no-clean-logs',
135 148 dest='Global.clean_logs', action='store_false',
136 help="Don't delete old log flies before starting.",
137 )
138 parser_start.add_argument('--daemon',
149 help="Don't delete old log flies before starting.")
150 paa('--daemon',
139 151 dest='Global.daemonize', action='store_true',
140 help='Daemonize the ipcluster program. This implies --log-to-file',
141 )
142 parser_start.add_argument('--no-daemon',
152 help='Daemonize the ipcluster program. This implies --log-to-file')
153 paa('--no-daemon',
143 154 dest='Global.daemonize', action='store_false',
144 help="Dont't daemonize the ipcluster program.",
145 )
155 help="Dont't daemonize the ipcluster program.")
146 156
147 parser_start = subparsers.add_parser(
157 # The "stop" subcommand parser
158 parser_stop = subparsers.add_parser(
148 159 'stop',
149 160 help='Stop a cluster.',
150 161 parents=[parent_parser1, parent_parser2]
151 162 )
152 parser_start.add_argument('--signal',
163 paa = parser_stop.add_argument
164 paa('--signal',
153 165 dest='Global.signal', type=int,
154 166 help="The signal number to use in stopping the cluster (default=2).",
155 metavar="Global.signal",
156 )
157
158
159 default_config_file_name = u'ipcluster_config.py'
167 metavar="Global.signal")
160 168
161 169
162 _description = """Start an IPython cluster for parallel computing.\n\n
163
164 An IPython cluster consists of 1 controller and 1 or more engines.
165 This command automates the startup of these processes using a wide
166 range of startup methods (SSH, local processes, PBS, mpiexec,
167 Windows HPC Server 2008). To start a cluster with 4 engines on your
168 local host simply do "ipcluster start -n 4". For more complex usage
169 you will typically do "ipcluster create -p mycluster", then edit
170 configuration files, followed by "ipcluster start -p mycluster -n 4".
171 """
170 #-----------------------------------------------------------------------------
171 # Main application
172 #-----------------------------------------------------------------------------
172 173
173 174
174 175 class IPClusterApp(ApplicationWithClusterDir):
175 176
176 177 name = u'ipcluster'
177 178 description = _description
179 usage = None
180 command_line_loader = IPClusterAppConfigLoader
178 181 config_file_name = default_config_file_name
179 182 default_log_level = logging.INFO
180 183 auto_create_cluster_dir = False
@@ -191,13 +194,6 b' class IPClusterApp(ApplicationWithClusterDir):'
191 194 self.default_config.Global.signal = 2
192 195 self.default_config.Global.daemonize = False
193 196
194 def create_command_line_config(self):
195 """Create and return a command line config loader."""
196 return IPClusterCLLoader(
197 description=self.description,
198 version=release.version
199 )
200
201 197 def find_resources(self):
202 198 subcommand = self.command_line_config.Global.subcommand
203 199 if subcommand=='list':
@@ -451,6 +447,7 b' class IPClusterApp(ApplicationWithClusterDir):'
451 447 # old .pid files.
452 448 self.remove_pid_file()
453 449
450
454 451 def launch_new_instance():
455 452 """Create and run the IPython cluster."""
456 453 app = IPClusterApp()
@@ -25,12 +25,34 b' from twisted.internet import reactor'
25 25 from twisted.python import log
26 26
27 27 from IPython.config.loader import Config
28 from IPython.core.application import Application
29 28 from IPython.kernel import controllerservice
30 from IPython.kernel.clusterdir import ApplicationWithClusterDir
29 from IPython.kernel.clusterdir import (
30 ApplicationWithClusterDir,
31 ClusterDirConfigLoader
32 )
31 33 from IPython.kernel.fcutil import FCServiceFactory
32 34 from IPython.utils.traitlets import Instance, Unicode
33 35
36
37 #-----------------------------------------------------------------------------
38 # Module level variables
39 #-----------------------------------------------------------------------------
40
41
42 #: The default config file name for this application
43 default_config_file_name = u'ipcontroller_config.py'
44
45
46 _description = """Start the IPython controller for parallel computing.
47
48 The IPython controller provides a gateway between the IPython engines and
49 clients. The controller needs to be started before the engines and can be
50 configured using command line options or using a cluster directory. Cluster
51 directories contain config, log and security files and are usually located in
52 your .ipython directory and named as "cluster_<profile>". See the --profile
53 and --cluster-dir options for details.
54 """
55
34 56 #-----------------------------------------------------------------------------
35 57 # Default interfaces
36 58 #-----------------------------------------------------------------------------
@@ -90,25 +112,27 b' class FCEngineServiceFactory(FCServiceFactory):'
90 112
91 113
92 114 #-----------------------------------------------------------------------------
93 # The main application
115 # Command line options
94 116 #-----------------------------------------------------------------------------
95 117
96 118
97 cl_args = (
119 class IPControllerAppConfigLoader(ClusterDirConfigLoader):
120
121 def _add_arguments(self):
122 super(IPControllerAppConfigLoader, self)._add_arguments()
123 paa = self.parser.add_argument
98 124 # Client config
99 (('--client-ip',), dict(
125 paa('--client-ip',
100 126 type=str, dest='FCClientServiceFactory.ip',
101 127 help='The IP address or hostname the controller will listen on for '
102 128 'client connections.',
103 129 metavar='FCClientServiceFactory.ip')
104 ),
105 (('--client-port',), dict(
130 paa('--client-port',
106 131 type=int, dest='FCClientServiceFactory.port',
107 132 help='The port the controller will listen on for client connections. '
108 133 'The default is to use 0, which will autoselect an open port.',
109 134 metavar='FCClientServiceFactory.port')
110 ),
111 (('--client-location',), dict(
135 paa('--client-location',), dict(
112 136 type=str, dest='FCClientServiceFactory.location',
113 137 help='The hostname or IP that clients should connect to. This does '
114 138 'not control which interface the controller listens on. Instead, this '
@@ -116,21 +140,18 b' cl_args = ('
116 140 'clients know where to connect. Useful if the controller is listening '
117 141 'on multiple interfaces.',
118 142 metavar='FCClientServiceFactory.location')
119 ),
120 143 # Engine config
121 (('--engine-ip',), dict(
144 paa('--engine-ip',
122 145 type=str, dest='FCEngineServiceFactory.ip',
123 146 help='The IP address or hostname the controller will listen on for '
124 147 'engine connections.',
125 148 metavar='FCEngineServiceFactory.ip')
126 ),
127 (('--engine-port',), dict(
149 paa('--engine-port',
128 150 type=int, dest='FCEngineServiceFactory.port',
129 151 help='The port the controller will listen on for engine connections. '
130 152 'The default is to use 0, which will autoselect an open port.',
131 153 metavar='FCEngineServiceFactory.port')
132 ),
133 (('--engine-location',), dict(
154 paa('--engine-location',
134 155 type=str, dest='FCEngineServiceFactory.location',
135 156 help='The hostname or IP that engines should connect to. This does '
136 157 'not control which interface the controller listens on. Instead, this '
@@ -138,49 +159,35 b' cl_args = ('
138 159 'engines know where to connect. Useful if the controller is listening '
139 160 'on multiple interfaces.',
140 161 metavar='FCEngineServiceFactory.location')
141 ),
142 162 # Global config
143 (('--log-to-file',), dict(
163 paa('--log-to-file',
144 164 action='store_true', dest='Global.log_to_file',
145 165 help='Log to a file in the log directory (default is stdout)')
146 ),
147 (('-r','--reuse-furls'), dict(
166 paa('-r','--reuse-furls',
148 167 action='store_true', dest='Global.reuse_furls',
149 168 help='Try to reuse all FURL files. If this is not set all FURL files '
150 169 'are deleted before the controller starts. This must be set if '
151 170 'specific ports are specified by --engine-port or --client-port.')
152 ),
153 (('--no-secure',), dict(
171 paa('--no-secure',
154 172 action='store_false', dest='Global.secure',
155 173 help='Turn off SSL encryption for all connections.')
156 ),
157 (('--secure',), dict(
174 paa('--secure',
158 175 action='store_true', dest='Global.secure',
159 176 help='Turn off SSL encryption for all connections.')
160 )
161 )
162
163 177
164 _description = """Start the IPython controller for parallel computing.
165
166 The IPython controller provides a gateway between the IPython engines and
167 clients. The controller needs to be started before the engines and can be
168 configured using command line options or using a cluster directory. Cluster
169 directories contain config, log and security files and are usually located in
170 your .ipython directory and named as "cluster_<profile>". See the --profile
171 and --cluster-dir options for details.
172 """
173 178
174 default_config_file_name = u'ipcontroller_config.py'
179 #-----------------------------------------------------------------------------
180 # The main application
181 #-----------------------------------------------------------------------------
175 182
176 183
177 184 class IPControllerApp(ApplicationWithClusterDir):
178 185
179 186 name = u'ipcontroller'
180 187 description = _description
188 command_line_loader = IPControllerAppConfigLoader
181 189 config_file_name = default_config_file_name
182 190 auto_create_cluster_dir = True
183 cl_arguments = Application.cl_arguments + cl_args
184 191
185 192 def create_default_config(self):
186 193 super(IPControllerApp, self).create_default_config()
@@ -22,39 +22,21 b' from twisted.application import service'
22 22 from twisted.internet import reactor
23 23 from twisted.python import log
24 24
25 from IPython.core.application import Application
26 from IPython.kernel.clusterdir import ApplicationWithClusterDir
25 from IPython.kernel.clusterdir import (
26 ApplicationWithClusterDir,
27 ClusterDirConfigLoader
28 )
27 29 from IPython.kernel.engineconnector import EngineConnector
28 30 from IPython.kernel.engineservice import EngineService
29 31 from IPython.kernel.fcutil import Tub
30 32 from IPython.utils.importstring import import_item
31 33
32 34 #-----------------------------------------------------------------------------
33 # The main application
35 # Module level variables
34 36 #-----------------------------------------------------------------------------
35 37
36 cl_args = (
37 # Controller config
38 (('--furl-file',), dict(
39 type=unicode, dest='Global.furl_file',
40 help='The full location of the file containing the FURL of the '
41 'controller. If this is not given, the FURL file must be in the '
42 'security directory of the cluster directory. This location is '
43 'resolved using the --profile and --app-dir options.',
44 metavar='Global.furl_file')
45 ),
46 # MPI
47 (('--mpi',), dict(
48 type=str, dest='MPI.use',
49 help='How to enable MPI (mpi4py, pytrilinos, or empty string to disable).',
50 metavar='MPI.use')
51 ),
52 # Global config
53 (('--log-to-file',), dict(
54 action='store_true', dest='Global.log_to_file',
55 help='Log to a file in the log directory (default is stdout)')
56 )
57 )
38 #: The default config file name for this application
39 default_config_file_name = u'ipengine_config.py'
58 40
59 41
60 42 mpi4py_init = """from mpi4py import MPI as mpi
@@ -62,6 +44,7 b' mpi.size = mpi.COMM_WORLD.Get_size()'
62 44 mpi.rank = mpi.COMM_WORLD.Get_rank()
63 45 """
64 46
47
65 48 pytrilinos_init = """from PyTrilinos import Epetra
66 49 class SimpleStruct:
67 50 pass
@@ -71,9 +54,6 b' mpi.size = 0'
71 54 """
72 55
73 56
74 default_config_file_name = u'ipengine_config.py'
75
76
77 57 _description = """Start an IPython engine for parallel computing.\n\n
78 58
79 59 IPython engines run in parallel and perform computations on behalf of a client
@@ -84,14 +64,47 b' usually located in your .ipython directory and named as "cluster_<profile>".'
84 64 See the --profile and --cluster-dir options for details.
85 65 """
86 66
67 #-----------------------------------------------------------------------------
68 # Command line options
69 #-----------------------------------------------------------------------------
70
71
72 class IPEngineAppConfigLoader(ClusterDirConfigLoader):
73
74 def _add_arguments(self):
75 super(IPEngineAppConfigLoader, self)._add_arguments()
76 paa = self.parser.add_argument
77 # Controller config
78 paa('--furl-file',
79 type=unicode, dest='Global.furl_file',
80 help='The full location of the file containing the FURL of the '
81 'controller. If this is not given, the FURL file must be in the '
82 'security directory of the cluster directory. This location is '
83 'resolved using the --profile and --app-dir options.',
84 metavar='Global.furl_file')
85 # MPI
86 paa('--mpi',
87 type=str, dest='MPI.use',
88 help='How to enable MPI (mpi4py, pytrilinos, or empty string to disable).',
89 metavar='MPI.use')
90 # Global config
91 paa('--log-to-file',
92 action='store_true', dest='Global.log_to_file',
93 help='Log to a file in the log directory (default is stdout)')
94
95
96 #-----------------------------------------------------------------------------
97 # Main application
98 #-----------------------------------------------------------------------------
99
87 100
88 101 class IPEngineApp(ApplicationWithClusterDir):
89 102
90 103 name = u'ipengine'
91 104 description = _description
105 command_line_loader = IPEngineAppConfigLoader
92 106 config_file_name = default_config_file_name
93 107 auto_create_cluster_dir = True
94 cl_arguments = Application.cl_arguments + cl_args
95 108
96 109 def create_default_config(self):
97 110 super(IPEngineApp, self).create_default_config()
General Comments 0
You need to be logged in to leave comments. Login now