Show More
@@ -40,6 +40,7 b' class ConfigLoaderError(ConfigError):' | |||
|
40 | 40 | #----------------------------------------------------------------------------- |
|
41 | 41 | # Argparse fix |
|
42 | 42 | #----------------------------------------------------------------------------- |
|
43 | ||
|
43 | 44 | # Unfortunately argparse by default prints help messages to stderr instead of |
|
44 | 45 | # stdout. This makes it annoying to capture long help screens at the command |
|
45 | 46 | # line, since one must know how to pipe stderr, which many users don't know how |
@@ -200,10 +201,13 b' class ConfigLoader(object):' | |||
|
200 | 201 | self.config = Config() |
|
201 | 202 | |
|
202 | 203 | def load_config(self): |
|
203 |
"""Load a config from somewhere, return a |
|
|
204 | """Load a config from somewhere, return a :class:`Config` instance. | |
|
204 | 205 | |
|
205 | 206 | Usually, this will cause self.config to be set and then returned. |
|
207 | However, in most cases, :meth:`ConfigLoader.clear` should be called | |
|
208 | to erase any previous state. | |
|
206 | 209 | """ |
|
210 | self.clear() | |
|
207 | 211 | return self.config |
|
208 | 212 | |
|
209 | 213 | |
@@ -242,6 +246,7 b' class PyFileConfigLoader(FileConfigLoader):' | |||
|
242 | 246 | |
|
243 | 247 | def load_config(self): |
|
244 | 248 | """Load the config from a file and return it as a Struct.""" |
|
249 | self.clear() | |
|
245 | 250 | self._find_file() |
|
246 | 251 | self._read_file_as_dict() |
|
247 | 252 | self._convert_to_config() |
@@ -292,21 +297,11 b' class CommandLineConfigLoader(ConfigLoader):' | |||
|
292 | 297 | """ |
|
293 | 298 | |
|
294 | 299 | |
|
295 | class __NoConfigDefault(object): pass | |
|
296 | NoConfigDefault = __NoConfigDefault() | |
|
297 | ||
|
298 | ||
|
299 | 300 | class ArgParseConfigLoader(CommandLineConfigLoader): |
|
300 | #: Global default for arguments (see argparse docs for details) | |
|
301 | argument_default = NoConfigDefault | |
|
302 | 301 | |
|
303 | def __init__(self, argv=None, arguments=(), *args, **kw): | |
|
302 | def __init__(self, argv=None, arguments=(), *parser_args, **parser_kw): | |
|
304 | 303 | """Create a config loader for use with argparse. |
|
305 | 304 | |
|
306 | With the exception of ``argv`` and ``arguments``, other args and kwargs | |
|
307 | arguments here are passed onto the constructor of | |
|
308 | :class:`argparse.ArgumentParser`. | |
|
309 | ||
|
310 | 305 | Parameters |
|
311 | 306 | ---------- |
|
312 | 307 | |
@@ -315,18 +310,27 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||
|
315 | 310 | sys.argv[1:] is used. |
|
316 | 311 | |
|
317 | 312 | arguments : optional, tuple |
|
318 | Description of valid command-line arguments, to be called in sequence | |
|
319 | with parser.add_argument() to configure the parser. | |
|
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 | parser_args : tuple | |
|
318 | A tuple of positional arguments that will be passed to the | |
|
319 | constructor of :class:`argparse.ArgumentParser`. | |
|
320 | ||
|
321 | parser_kw : dict | |
|
322 | A tuple of keyword arguments that will be passed to the | |
|
323 | constructor of :class:`argparse.ArgumentParser`. | |
|
320 | 324 | """ |
|
321 | 325 | super(CommandLineConfigLoader, self).__init__() |
|
322 | 326 | if argv == None: |
|
323 | 327 | argv = sys.argv[1:] |
|
324 | 328 | self.argv = argv |
|
325 | 329 | self.arguments = arguments |
|
326 | self.args = args | |
|
327 |
kwargs = dict(argument_default=se |
|
|
328 | kwargs.update(kw) | |
|
329 | self.kw = kwargs | |
|
330 | self.parser_args = parser_args | |
|
331 | kwargs = dict(argument_default=argparse.SUPPRESS) | |
|
332 | kwargs.update(parser_kw) | |
|
333 | self.parser_kw = kwargs | |
|
330 | 334 | |
|
331 | 335 | def load_config(self, args=None): |
|
332 | 336 | """Parse command line arguments and return as a Struct. |
@@ -335,10 +339,10 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||
|
335 | 339 | ---------- |
|
336 | 340 | |
|
337 | 341 | args : optional, list |
|
338 |
If given, a list with the structure of sys.argv[1:] to parse |
|
|
339 |
from. |
|
|
340 | construction time) is used.""" | |
|
341 | ||
|
342 | If given, a list with the structure of sys.argv[1:] to parse | |
|
343 | arguments from. If not given, the instance's self.argv attribute | |
|
344 | (given at construction time) is used.""" | |
|
345 | self.clear() | |
|
342 | 346 | if args is None: |
|
343 | 347 | args = self.argv |
|
344 | 348 | self._create_parser() |
@@ -353,12 +357,16 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||
|
353 | 357 | return [] |
|
354 | 358 | |
|
355 | 359 | def _create_parser(self): |
|
356 | self.parser = ArgumentParser(*self.args, **self.kw) | |
|
360 | self.parser = ArgumentParser(*self.parser_args, **self.parser_kw) | |
|
357 | 361 | self._add_arguments() |
|
358 | 362 | self._add_other_arguments() |
|
359 | 363 | |
|
360 | 364 | def _add_arguments(self): |
|
361 | 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) | |
|
362 | 370 | self.parser.add_argument(*argument[0],**argument[1]) |
|
363 | 371 | |
|
364 | 372 | def _add_other_arguments(self): |
@@ -372,6 +380,7 b' class ArgParseConfigLoader(CommandLineConfigLoader):' | |||
|
372 | 380 | def _convert_to_config(self): |
|
373 | 381 | """self.parsed_data->self.config""" |
|
374 | 382 | for k, v in vars(self.parsed_data).items(): |
|
375 | if v is not NoConfigDefault: | |
|
376 | 383 |
|
|
377 | 384 |
|
|
385 | ||
|
386 |
@@ -62,22 +62,26 b' class TestPyFileCL(TestCase):' | |||
|
62 | 62 | self.assertEquals(config.D.C.value, 'hi there') |
|
63 | 63 | |
|
64 | 64 | |
|
65 | class TestArgParseCL(TestCase): | |
|
66 | ||
|
67 | def test_basic(self): | |
|
68 | ||
|
69 | 65 |
|
|
70 | 66 |
|
|
71 | 67 |
|
|
72 | 68 |
|
|
73 | 69 |
|
|
74 | 70 | ) |
|
71 | ||
|
72 | class TestArgParseCL(TestCase): | |
|
73 | ||
|
74 | def test_basic(self): | |
|
75 | 75 | cl = ArgParseConfigLoader(arguments=arguments) |
|
76 | 76 | config = cl.load_config('-f hi -b 10 -n wow'.split()) |
|
77 | 77 | self.assertEquals(config.Global.foo, 'hi') |
|
78 | 78 | self.assertEquals(config.MyClass.bar, 10) |
|
79 | 79 | self.assertEquals(config.n, True) |
|
80 | 80 | self.assertEquals(config.Global.bam, 'wow') |
|
81 | config = cl.load_config(['wow']) | |
|
82 | self.assertEquals(config.keys(), ['Global']) | |
|
83 | self.assertEquals(config.Global.keys(), ['bam']) | |
|
84 | self.assertEquals(config.Global.bam, 'wow') | |
|
81 | 85 | |
|
82 | 86 | def test_add_arguments(self): |
|
83 | 87 | |
@@ -97,6 +101,18 b' class TestArgParseCL(TestCase):' | |||
|
97 | 101 | self.assertEquals(config.subparser_name, '1') |
|
98 | 102 | self.assertEquals(config.Global.x, 'frobble') |
|
99 | 103 | |
|
104 | def test_argv(self): | |
|
105 | cl = ArgParseConfigLoader( | |
|
106 | argv='-f hi -b 10 -n wow'.split(), | |
|
107 | arguments=arguments | |
|
108 | ) | |
|
109 | config = cl.load_config() | |
|
110 | self.assertEquals(config.Global.foo, 'hi') | |
|
111 | self.assertEquals(config.MyClass.bar, 10) | |
|
112 | self.assertEquals(config.n, True) | |
|
113 | self.assertEquals(config.Global.bam, 'wow') | |
|
114 | ||
|
115 | ||
|
100 | 116 | class TestConfig(TestCase): |
|
101 | 117 | |
|
102 | 118 | def test_setget(self): |
@@ -32,8 +32,7 b' from IPython.core.application import Application' | |||
|
32 | 32 | from IPython.core.iplib import InteractiveShell |
|
33 | 33 | from IPython.config.loader import ( |
|
34 | 34 | Config, |
|
35 |
PyFileConfigLoader |
|
|
36 | # NoConfigDefault, | |
|
35 | PyFileConfigLoader | |
|
37 | 36 | ) |
|
38 | 37 | from IPython.lib import inputhook |
|
39 | 38 | from IPython.utils.path import filefind, get_ipython_dir |
@@ -23,8 +23,8 b" if os.name=='posix':" | |||
|
23 | 23 | from twisted.scripts._twistd_unix import daemonize |
|
24 | 24 | |
|
25 | 25 | from IPython.core import release |
|
26 | from IPython.external.argparse import ArgumentParser | |
|
27 |
from IPython.config.loader import ArgParseConfigLoader |
|
|
26 | from IPython.external.argparse import ArgumentParser, SUPPRESS | |
|
27 | from IPython.config.loader import ArgParseConfigLoader | |
|
28 | 28 | from IPython.utils.importstring import import_item |
|
29 | 29 | |
|
30 | 30 | from IPython.kernel.clusterdir import ( |
@@ -56,7 +56,7 b' class IPClusterCLLoader(ArgParseConfigLoader):' | |||
|
56 | 56 | def _add_other_arguments(self): |
|
57 | 57 | # This has all the common options that all subcommands use |
|
58 | 58 | parent_parser1 = ArgumentParser(add_help=False, |
|
59 |
argument_default= |
|
|
59 | argument_default=SUPPRESS) | |
|
60 | 60 | parent_parser1.add_argument('--ipython-dir', |
|
61 | 61 | dest='Global.ipython_dir',type=unicode, |
|
62 | 62 | help='Set to override default location of Global.ipython_dir.', |
@@ -68,7 +68,7 b' class IPClusterCLLoader(ArgParseConfigLoader):' | |||
|
68 | 68 | |
|
69 | 69 | # This has all the common options that other subcommands use |
|
70 | 70 | parent_parser2 = ArgumentParser(add_help=False, |
|
71 |
argument_default= |
|
|
71 | argument_default=SUPPRESS) | |
|
72 | 72 | parent_parser2.add_argument('-p','--profile', |
|
73 | 73 | dest='Global.profile',type=unicode, |
|
74 | 74 | help='The string name of the profile to be used. This determines ' |
@@ -112,7 +112,6 b' class IPClusterCLLoader(ArgParseConfigLoader):' | |||
|
112 | 112 | parser_create.add_argument( |
|
113 | 113 | '--reset-config', |
|
114 | 114 | dest='Global.reset_config', action='store_true', |
|
115 | default=NoConfigDefault, | |
|
116 | 115 | help='Recopy the default config files to the cluster directory. ' |
|
117 | 116 | 'You will loose any modifications you have made to these files.' |
|
118 | 117 | ) |
General Comments 0
You need to be logged in to leave comments.
Login now