Show More
@@ -27,7 +27,7 b' from copy import deepcopy' | |||
|
27 | 27 | |
|
28 | 28 | from IPython.config.configurable import SingletonConfigurable |
|
29 | 29 | from IPython.config.loader import ( |
|
30 |
K |
|
|
30 | KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError | |
|
31 | 31 | ) |
|
32 | 32 | |
|
33 | 33 | from IPython.utils.traitlets import ( |
@@ -46,8 +46,6 b' from IPython.utils.text import indent, wrap_paragraphs, dedent' | |||
|
46 | 46 | |
|
47 | 47 | # merge flags&aliases into options |
|
48 | 48 | option_description = """ |
|
49 | IPython command-line arguments are passed as '--<flag>', or '--<name>=<value>'. | |
|
50 | ||
|
51 | 49 | Arguments that take values are actually convenience aliases to full |
|
52 | 50 | Configurables, whose aliases are listed on the help line. For more information |
|
53 | 51 | on full configurables, see '--help-all'. |
@@ -210,6 +208,8 b' class Application(SingletonConfigurable):' | |||
|
210 | 208 | help = cls.class_get_trait_help(trait).splitlines() |
|
211 | 209 | # reformat first line |
|
212 | 210 | help[0] = help[0].replace(longname, alias) + ' (%s)'%longname |
|
211 | if len(alias) == 1: | |
|
212 | help[0] = help[0].replace('--%s='%alias, '-%s '%alias) | |
|
213 | 213 | lines.extend(help) |
|
214 | 214 | # lines.append('') |
|
215 | 215 | print os.linesep.join(lines) |
@@ -221,7 +221,8 b' class Application(SingletonConfigurable):' | |||
|
221 | 221 | |
|
222 | 222 | lines = [] |
|
223 | 223 | for m, (cfg,help) in self.flags.iteritems(): |
|
224 | lines.append('--'+m) | |
|
224 | prefix = '--' if len(m) > 1 else '-' | |
|
225 | lines.append(prefix+m) | |
|
225 | 226 | lines.append(indent(dedent(help.strip()))) |
|
226 | 227 | # lines.append('') |
|
227 | 228 | print os.linesep.join(lines) |
@@ -350,7 +351,7 b' class Application(SingletonConfigurable):' | |||
|
350 | 351 | self.print_version() |
|
351 | 352 | self.exit(0) |
|
352 | 353 | |
|
353 |
loader = K |
|
|
354 | loader = KVArgParseConfigLoader(argv=argv, aliases=self.aliases, | |
|
354 | 355 | flags=self.flags) |
|
355 | 356 | try: |
|
356 | 357 | config = loader.load_config() |
@@ -326,6 +326,31 b' class CommandLineConfigLoader(ConfigLoader):' | |||
|
326 | 326 | here. |
|
327 | 327 | """ |
|
328 | 328 | |
|
329 | def _exec_config_str(self, lhs, rhs): | |
|
330 | exec_str = 'self.config.' + lhs + '=' + rhs | |
|
331 | try: | |
|
332 | # Try to see if regular Python syntax will work. This | |
|
333 | # won't handle strings as the quote marks are removed | |
|
334 | # by the system shell. | |
|
335 | exec exec_str in locals(), globals() | |
|
336 | except (NameError, SyntaxError): | |
|
337 | # This case happens if the rhs is a string but without | |
|
338 | # the quote marks. Use repr, to get quote marks, and | |
|
339 | # 'u' prefix and see if | |
|
340 | # it succeeds. If it still fails, we let it raise. | |
|
341 | exec_str = u'self.config.' + lhs + '=' + repr(rhs) | |
|
342 | exec exec_str in locals(), globals() | |
|
343 | ||
|
344 | def _load_flag(self, cfg): | |
|
345 | """update self.config from a flag, which can be a dict or Config""" | |
|
346 | if isinstance(cfg, (dict, Config)): | |
|
347 | # don't clobber whole config sections, update | |
|
348 | # each section from config: | |
|
349 | for sec,c in cfg.iteritems(): | |
|
350 | self.config[sec].update(c) | |
|
351 | else: | |
|
352 | raise ValueError("Invalid flag: '%s'"%raw) | |
|
353 | ||
|
329 | 354 | # raw --identifier=value pattern |
|
330 | 355 | # but *also* accept '-' as wordsep, for aliases |
|
331 | 356 | # accepts: --foo=a |
@@ -463,29 +488,12 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||
|
463 | 488 | if '.' not in lhs: |
|
464 | 489 | # probably a mistyped alias, but not technically illegal |
|
465 | 490 | warn.warn("Unrecognized alias: '%s', it will probably have no effect."%lhs) |
|
466 |
|
|
|
467 |
|
|
|
468 | # Try to see if regular Python syntax will work. This | |
|
469 | # won't handle strings as the quote marks are removed | |
|
470 | # by the system shell. | |
|
471 | exec exec_str in locals(), globals() | |
|
472 | except (NameError, SyntaxError): | |
|
473 | # This case happens if the rhs is a string but without | |
|
474 | # the quote marks. Use repr, to get quote marks, and | |
|
475 | # 'u' prefix and see if | |
|
476 | # it succeeds. If it still fails, we let it raise. | |
|
477 | exec_str = u'self.config.' + lhs + '=' + repr(rhs) | |
|
478 | exec exec_str in locals(), globals() | |
|
491 | self._exec_config_str(lhs, rhs) | |
|
492 | ||
|
479 | 493 | elif flag_pattern.match(raw): |
|
480 | 494 | if item in flags: |
|
481 | 495 | cfg,help = flags[item] |
|
482 | if isinstance(cfg, (dict, Config)): | |
|
483 | # don't clobber whole config sections, update | |
|
484 | # each section from config: | |
|
485 | for sec,c in cfg.iteritems(): | |
|
486 | self.config[sec].update(c) | |
|
487 | else: | |
|
488 | raise ValueError("Invalid flag: '%s'"%raw) | |
|
496 | self._load_flag(cfg) | |
|
489 | 497 | else: |
|
490 | 498 | raise ArgumentError("Unrecognized flag: '%s'"%raw) |
|
491 | 499 | elif raw.startswith('-'): |
@@ -503,7 +511,7 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||
|
503 | 511 | class ArgParseConfigLoader(CommandLineConfigLoader): |
|
504 | 512 | """A loader that uses the argparse module to load from the command line.""" |
|
505 | 513 | |
|
506 | def __init__(self, argv=None, *parser_args, **parser_kw): | |
|
514 | def __init__(self, argv=None, aliases=None, flags=None, *parser_args, **parser_kw): | |
|
507 | 515 | """Create a config loader for use with argparse. |
|
508 | 516 | |
|
509 | 517 | Parameters |
@@ -527,16 +535,20 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||
|
527 | 535 | The resulting Config object. |
|
528 | 536 | """ |
|
529 | 537 | super(CommandLineConfigLoader, self).__init__() |
|
530 | if argv == None: | |
|
538 | self.clear() | |
|
539 | if argv is None: | |
|
531 | 540 | argv = sys.argv[1:] |
|
532 | 541 | self.argv = argv |
|
542 | self.aliases = aliases or {} | |
|
543 | self.flags = flags or {} | |
|
544 | ||
|
533 | 545 | self.parser_args = parser_args |
|
534 | 546 | self.version = parser_kw.pop("version", None) |
|
535 | 547 | kwargs = dict(argument_default=argparse.SUPPRESS) |
|
536 | 548 | kwargs.update(parser_kw) |
|
537 | 549 | self.parser_kw = kwargs |
|
538 | 550 | |
|
539 | def load_config(self, argv=None): | |
|
551 | def load_config(self, argv=None, aliases=None, flags=None): | |
|
540 | 552 | """Parse command line arguments and return as a Config object. |
|
541 | 553 | |
|
542 | 554 | Parameters |
@@ -549,7 +561,11 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||
|
549 | 561 | self.clear() |
|
550 | 562 | if argv is None: |
|
551 | 563 | argv = self.argv |
|
552 | self._create_parser() | |
|
564 | if aliases is None: | |
|
565 | aliases = self.aliases | |
|
566 | if flags is None: | |
|
567 | flags = self.flags | |
|
568 | self._create_parser(aliases, flags) | |
|
553 | 569 | self._parse_args(argv) |
|
554 | 570 | self._convert_to_config() |
|
555 | 571 | return self.config |
@@ -560,11 +576,11 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||
|
560 | 576 | else: |
|
561 | 577 | return [] |
|
562 | 578 | |
|
563 | def _create_parser(self): | |
|
579 | def _create_parser(self, aliases=None, flags=None): | |
|
564 | 580 | self.parser = ArgumentParser(*self.parser_args, **self.parser_kw) |
|
565 | self._add_arguments() | |
|
581 | self._add_arguments(aliases, flags) | |
|
566 | 582 | |
|
567 | def _add_arguments(self): | |
|
583 | def _add_arguments(self, aliases=None, flags=None): | |
|
568 | 584 | raise NotImplementedError("subclasses must implement _add_arguments") |
|
569 | 585 | |
|
570 | 586 | def _parse_args(self, args): |
@@ -582,7 +598,69 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||
|
582 | 598 | def _convert_to_config(self): |
|
583 | 599 | """self.parsed_data->self.config""" |
|
584 | 600 | for k, v in vars(self.parsed_data).iteritems(): |
|
585 | exec_str = 'self.config.' + k + '= v' | |
|
586 | exec exec_str in locals(), globals() | |
|
601 | exec "self.config.%s = v"%k in locals(), globals() | |
|
602 | ||
|
603 | class KVArgParseConfigLoader(ArgParseConfigLoader): | |
|
604 | """A config loader that loads aliases and flags with argparse, | |
|
605 | but will use KVLoader for the rest. This allows better parsing | |
|
606 | of common args, such as `ipython -c 'print 5'`, but still gets | |
|
607 | arbitrary config with `ipython --InteractiveShell.use_readline=False`""" | |
|
608 | ||
|
609 | def _convert_to_config(self): | |
|
610 | """self.parsed_data->self.config""" | |
|
611 | for k, v in vars(self.parsed_data).iteritems(): | |
|
612 | self._exec_config_str(k, v) | |
|
613 | ||
|
614 | def _add_arguments(self, aliases=None, flags=None): | |
|
615 | self.alias_flags = {} | |
|
616 | # print aliases, flags | |
|
617 | if aliases is None: | |
|
618 | aliases = self.aliases | |
|
619 | if flags is None: | |
|
620 | flags = self.flags | |
|
621 | paa = self.parser.add_argument | |
|
622 | for key,value in aliases.iteritems(): | |
|
623 | if key in flags: | |
|
624 | # flags | |
|
625 | nargs = '?' | |
|
626 | else: | |
|
627 | nargs = None | |
|
628 | if len(key) is 1: | |
|
629 | paa('-'+key, '--'+key, type=str, dest=value, nargs=nargs) | |
|
630 | else: | |
|
631 | paa('--'+key, type=str, dest=value, nargs=nargs) | |
|
632 | for key, (value, help) in flags.iteritems(): | |
|
633 | if key in self.aliases: | |
|
634 | # | |
|
635 | self.alias_flags[self.aliases[key]] = value | |
|
636 | continue | |
|
637 | if len(key) is 1: | |
|
638 | paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value) | |
|
639 | else: | |
|
640 | paa('--'+key, action='append_const', dest='_flags', const=value) | |
|
641 | ||
|
642 | def _convert_to_config(self): | |
|
643 | """self.parsed_data->self.config, parse unrecognized extra args via KVLoader.""" | |
|
644 | # remove subconfigs list from namespace before transforming the Namespace | |
|
645 | if '_flags' in self.parsed_data: | |
|
646 | subcs = self.parsed_data._flags | |
|
647 | del self.parsed_data._flags | |
|
648 | else: | |
|
649 | subcs = [] | |
|
650 | ||
|
651 | for k, v in vars(self.parsed_data).iteritems(): | |
|
652 | if v is None: | |
|
653 | # it was a flag that shares the name of an alias | |
|
654 | subcs.append(self.alias_flags[k]) | |
|
655 | else: | |
|
656 | # eval the KV assignment | |
|
657 | self._exec_config_str(k, v) | |
|
587 | 658 | |
|
659 | for subc in subcs: | |
|
660 | self._load_flag(subc) | |
|
588 | 661 | |
|
662 | if self.extra_args: | |
|
663 | sub_parser = KeyValueConfigLoader() | |
|
664 | sub_parser.load_config(self.extra_args) | |
|
665 | self.config._merge(sub_parser.config) | |
|
666 | self.extra_args = sub_parser.extra_args |
@@ -69,7 +69,7 b' class TestPyFileCL(TestCase):' | |||
|
69 | 69 | self.assertEquals(config.D.C.value, 'hi there') |
|
70 | 70 | |
|
71 | 71 | class MyLoader1(ArgParseConfigLoader): |
|
72 | def _add_arguments(self): | |
|
72 | def _add_arguments(self, aliases=None, flags=None): | |
|
73 | 73 | p = self.parser |
|
74 | 74 | p.add_argument('-f', '--foo', dest='Global.foo', type=str) |
|
75 | 75 | p.add_argument('-b', dest='MyClass.bar', type=int) |
@@ -77,7 +77,7 b' class MyLoader1(ArgParseConfigLoader):' | |||
|
77 | 77 | p.add_argument('Global.bam', type=str) |
|
78 | 78 | |
|
79 | 79 | class MyLoader2(ArgParseConfigLoader): |
|
80 | def _add_arguments(self): | |
|
80 | def _add_arguments(self, aliases=None, flags=None): | |
|
81 | 81 | subparsers = self.parser.add_subparsers(dest='subparser_name') |
|
82 | 82 | subparser1 = subparsers.add_parser('1') |
|
83 | 83 | subparser1.add_argument('-x',dest='Global.x') |
@@ -386,23 +386,39 b' Is the same as adding:' | |||
|
386 | 386 | to your config file. Key/Value arguments *always* take a value, separated by '=' |
|
387 | 387 | and no spaces. |
|
388 | 388 | |
|
389 | Common Arguments | |
|
390 | **************** | |
|
391 | ||
|
392 | Since the strictness and verbosity of the KVLoader above are not ideal for everyday | |
|
393 | use, common arguments can be specified as flags_ or aliases_. | |
|
394 | ||
|
395 | Flags and Aliases are handled by :mod:`argparse` instead, allowing for more flexible | |
|
396 | parsing. In general, flags and aliases are prefixed by ``--``, except for those | |
|
397 | that are single characters, in which case they can be specified with a single ``-``, e.g.: | |
|
398 | ||
|
399 | .. code-block:: bash | |
|
400 | ||
|
401 | $> ipython -i -c "import numpy; x=numpy.linspace(0,1)" --profile testing --colors=lightbg | |
|
402 | ||
|
389 | 403 | Aliases |
|
390 | 404 | ------- |
|
391 | 405 | |
|
392 | For convenience, applications have a mapping of commonly | |
|
393 | used traits, so you don't have to specify the whole class name. For these **aliases**, the class need not be specified: | |
|
406 | For convenience, applications have a mapping of commonly used traits, so you don't have | |
|
407 | to specify the whole class name: | |
|
394 | 408 | |
|
395 | 409 | .. code-block:: bash |
|
396 | 410 | |
|
411 | $> ipython --profile myprofile | |
|
412 | # and | |
|
397 | 413 | $> ipython --profile='myprofile' |
|
398 |
# |
|
|
414 | # are equivalent to | |
|
399 | 415 | $> ipython --BaseIPythonApplication.profile='myprofile' |
|
400 | 416 | |
|
401 | 417 | Flags |
|
402 | 418 | ----- |
|
403 | 419 | |
|
404 | 420 | Applications can also be passed **flags**. Flags are options that take no |
|
405 |
arguments |
|
|
421 | arguments. They are simply wrappers for | |
|
406 | 422 | setting one or more configurables with predefined values, often True/False. |
|
407 | 423 | |
|
408 | 424 | For instance: |
@@ -416,9 +432,13 b' For instance:' | |||
|
416 | 432 | $> ipython --pylab |
|
417 | 433 | # is equivalent to |
|
418 | 434 | $> ipython --pylab=auto |
|
435 | # or | |
|
436 | $> ipython --no-banner | |
|
437 | # is equivalent to | |
|
438 | $> ipython --TerminalIPythonApp.display_banner=False | |
|
419 | 439 | |
|
420 | 440 | Subcommands |
|
421 | ----------- | |
|
441 | *********** | |
|
422 | 442 | |
|
423 | 443 | |
|
424 | 444 | Some IPython applications have **subcommands**. Subcommands are modeled after |
@@ -83,7 +83,7 b' All options with a [no] prepended can be specified in negated form' | |||
|
83 | 83 | ``--[no-]banner`` |
|
84 | 84 | Print the initial information banner (default on). |
|
85 | 85 | |
|
86 |
``- |
|
|
86 | ``-c <command>`` | |
|
87 | 87 | execute the given command string. This is similar to the -c |
|
88 | 88 | option in the normal Python interpreter. |
|
89 | 89 | |
@@ -158,7 +158,7 b' All options with a [no] prepended can be specified in negated form' | |||
|
158 | 158 | ipython_log.py in your current directory (which prevents logs |
|
159 | 159 | from multiple IPython sessions from trampling each other). You |
|
160 | 160 | can use this to later restore a session by loading your |
|
161 |
logfile with ``ipython - |
|
|
161 | logfile with ``ipython -i ipython_log.py`` | |
|
162 | 162 | |
|
163 | 163 | ``--logplay=<name>`` |
|
164 | 164 |
@@ -205,7 +205,7 b' simply start a controller and engines on a single host using the' | |||
|
205 | 205 | :command:`ipcluster` command. To start a controller and 4 engines on your |
|
206 | 206 | localhost, just do:: |
|
207 | 207 | |
|
208 |
$ ipcluster start - |
|
|
208 | $ ipcluster start -n 4 | |
|
209 | 209 | |
|
210 | 210 | More details about starting the IPython controller and engines can be found |
|
211 | 211 | :ref:`here <parallel_process>` |
@@ -52,7 +52,7 b' The easiest approach is to use the `MPIExec` Launchers in :command:`ipcluster`,' | |||
|
52 | 52 | which will first start a controller and then a set of engines using |
|
53 | 53 | :command:`mpiexec`:: |
|
54 | 54 | |
|
55 |
$ ipcluster start - |
|
|
55 | $ ipcluster start -n 4 --elauncher=MPIExecEngineSetLauncher | |
|
56 | 56 | |
|
57 | 57 | This approach is best as interrupting :command:`ipcluster` will automatically |
|
58 | 58 | stop and clean up the controller and engines. |
@@ -105,7 +105,7 b' distributed array. Save the following text in a file called :file:`psum.py`:' | |||
|
105 | 105 | |
|
106 | 106 | Now, start an IPython cluster:: |
|
107 | 107 | |
|
108 |
$ ipcluster start --profile=mpi - |
|
|
108 | $ ipcluster start --profile=mpi -n 4 | |
|
109 | 109 | |
|
110 | 110 | .. note:: |
|
111 | 111 |
@@ -19,7 +19,7 b' To follow along with this tutorial, you will need to start the IPython' | |||
|
19 | 19 | controller and four IPython engines. The simplest way of doing this is to use |
|
20 | 20 | the :command:`ipcluster` command:: |
|
21 | 21 | |
|
22 |
$ ipcluster start - |
|
|
22 | $ ipcluster start -n 4 | |
|
23 | 23 | |
|
24 | 24 | For more detailed information about starting the controller and engines, see |
|
25 | 25 | our :ref:`introduction <parallel_overview>` to using IPython for parallel computing. |
@@ -109,7 +109,7 b' The simplest way to use ipcluster requires no configuration, and will' | |||
|
109 | 109 | launch a controller and a number of engines on the local machine. For instance, |
|
110 | 110 | to start one controller and 4 engines on localhost, just do:: |
|
111 | 111 | |
|
112 |
$ ipcluster start - |
|
|
112 | $ ipcluster start -n 4 | |
|
113 | 113 | |
|
114 | 114 | To see other command line options, do:: |
|
115 | 115 | |
@@ -174,7 +174,7 b' There, instruct ipcluster to use the MPIExec launchers by adding the lines:' | |||
|
174 | 174 | |
|
175 | 175 | If the default MPI configuration is correct, then you can now start your cluster, with:: |
|
176 | 176 | |
|
177 |
$ ipcluster start - |
|
|
177 | $ ipcluster start -n 4 --profile=mpi | |
|
178 | 178 | |
|
179 | 179 | This does the following: |
|
180 | 180 | |
@@ -324,7 +324,7 b' connections on all its interfaces, by adding in :file:`ipcontroller_config`:' | |||
|
324 | 324 | |
|
325 | 325 | You can now run the cluster with:: |
|
326 | 326 | |
|
327 |
$ ipcluster start --profile=pbs - |
|
|
327 | $ ipcluster start --profile=pbs -n 128 | |
|
328 | 328 | |
|
329 | 329 | Additional configuration options can be found in the PBS section of :file:`ipcluster_config`. |
|
330 | 330 |
@@ -24,7 +24,7 b' To follow along with this tutorial, you will need to start the IPython' | |||
|
24 | 24 | controller and four IPython engines. The simplest way of doing this is to use |
|
25 | 25 | the :command:`ipcluster` command:: |
|
26 | 26 | |
|
27 |
$ ipcluster start - |
|
|
27 | $ ipcluster start -n 4 | |
|
28 | 28 | |
|
29 | 29 | For more detailed information about starting the controller and engines, see |
|
30 | 30 | our :ref:`introduction <parallel_overview>` to using IPython for parallel computing. |
@@ -257,7 +257,7 b' Starting the cluster profile' | |||
|
257 | 257 | Once a cluster profile has been configured, starting an IPython cluster using |
|
258 | 258 | the profile is simple:: |
|
259 | 259 | |
|
260 |
ipcluster start --profile=mycluster - |
|
|
260 | ipcluster start --profile=mycluster -n 32 | |
|
261 | 261 | |
|
262 | 262 | The ``-n`` option tells :command:`ipcluster` how many engines to start (in |
|
263 | 263 | this case 32). Stopping the cluster is as simple as typing Control-C. |
General Comments 0
You need to be logged in to leave comments.
Login now