From 1d7c11a48ccb48965a7e022272d996073df748fa 2010-01-06 04:54:48 From: Fernando Perez Date: 2010-01-06 04:54:48 Subject: [PATCH] Manage and propagate argv correctly. All Application objects should take argv in their constructor, akin to how the standard signature of C programs is "main(int argc, char *argv)". This makes it possible to initialize them from code with different command-line options (otherwise, they end up directly accessing sys.argv[1:] via argparse). --- diff --git a/IPython/config/loader.py b/IPython/config/loader.py index b3e47fd..5b01462 100644 --- a/IPython/config/loader.py +++ b/IPython/config/loader.py @@ -301,18 +301,39 @@ class ArgParseConfigLoader(CommandLineConfigLoader): # arguments = [(('-f','--file'),dict(type=str,dest='file'))] arguments = () - def __init__(self, *args, **kw): + def __init__(self, argv=None, *args, **kw): """Create a config loader for use with argparse. - The args and kwargs arguments here are passed onto the constructor - of :class:`argparse.ArgumentParser`. + With the exception of argv, other args and kwargs arguments here are + passed onto the constructor of :class:`argparse.ArgumentParser`. + + Parameters + ---------- + + argv : optional, list + If given, used to read command-line arguments from, otherwise + sys.argv[1:] is used. """ super(CommandLineConfigLoader, self).__init__() + if argv == None: + argv = sys.argv[1:] + self.argv = argv self.args = args self.kw = kw def load_config(self, args=None): - """Parse command line arguments and return as a Struct.""" + """Parse command line arguments and return as a Struct. + + Parameters + ---------- + + args : optional, list + If given, a list with the structure of sys.argv[1:] to parse arguments + from. If not given, the instance's self.argv attribute (given at + construction time) is used.""" + + if args is None: + args = self.argv self._create_parser() self._parse_args(args) self._convert_to_config() @@ -337,12 +358,9 @@ class ArgParseConfigLoader(CommandLineConfigLoader): argument[1].setdefault('default', NoConfigDefault) self.parser.add_argument(*argument[0],**argument[1]) - def _parse_args(self, args=None): - """self.parser->self.parsed_data""" - if args is None: - self.parsed_data, self.extra_args = self.parser.parse_known_args() - else: - self.parsed_data, self.extra_args = self.parser.parse_known_args(args) + def _parse_args(self, args): + """self.parser->self.parsed_data""" + self.parsed_data, self.extra_args = self.parser.parse_known_args(args) def _convert_to_config(self): """self.parsed_data->self.config""" diff --git a/IPython/core/application.py b/IPython/core/application.py index 1dae602..a4ae573 100755 --- a/IPython/core/application.py +++ b/IPython/core/application.py @@ -92,11 +92,14 @@ class Application(object): profile_name = None #: User's ipython directory, typically ~/.ipython/ ipython_dir = None + #: A reference to the argv to be used (typically ends up being sys.argv[1:]) + argv = None # Private attributes _exiting = False - def __init__(self): + def __init__(self, argv=None): + self.argv = sys.argv[1:] if argv is None else argv self.init_logger() def init_logger(self): @@ -173,7 +176,7 @@ class Application(object): def create_command_line_config(self): """Create and return a command line config loader.""" - return BaseAppArgParseConfigLoader( + return BaseAppArgParseConfigLoader(self.argv, description=self.description, version=release.version ) diff --git a/IPython/core/ipapp.py b/IPython/core/ipapp.py index aa5fa90..4094085 100755 --- a/IPython/core/ipapp.py +++ b/IPython/core/ipapp.py @@ -344,7 +344,7 @@ class IPythonApp(Application): def create_command_line_config(self): """Create and return a command line config loader.""" - return IPythonAppCLConfigLoader( + return IPythonAppCLConfigLoader(self.argv, description=self.description, version=release.version ) @@ -565,7 +565,8 @@ class IPythonApp(Application): if self.master_config.Global.interact: self.log.debug("Starting IPython's mainloop...") self.shell.mainloop() - + else: + self.log.debug("IPython not interactive, start_app is no-op...") def load_default_config(ipython_dir=None): @@ -584,4 +585,3 @@ def launch_new_instance(): """Create and run a full blown IPython instance""" app = IPythonApp() app.start() -