From b6b911674356c4f58f4230f0d9577e5b43836360 2009-11-12 01:52:47 From: Brian Granger Date: 2009-11-12 01:52:47 Subject: [PATCH] The cluster applications now have a working directory option.. The ipcontroller, ipengine and ipcluster application now have a working directory that is os.chdir'd to in the pre_construct stage. There is a corresponding --working-dir command line flag and Global.working_dir config attribute. --- diff --git a/IPython/config/default/ipcluster_config.py b/IPython/config/default/ipcluster_config.py index b9f1831..b7ff08e 100644 --- a/IPython/config/default/ipcluster_config.py +++ b/IPython/config/default/ipcluster_config.py @@ -37,6 +37,10 @@ c = get_config() # Remove old logs from cluster_dir/log before starting. # c.Global.clean_logs = True +# The working directory for the process. The application will use os.chdir +# to change to this directory before starting. +# c.Global.working_dir = os.getcwd() + #----------------------------------------------------------------------------- # Controller launcher configuration #----------------------------------------------------------------------------- diff --git a/IPython/config/default/ipcontroller_config.py b/IPython/config/default/ipcontroller_config.py index 03bae62..5ecd2aa 100644 --- a/IPython/config/default/ipcontroller_config.py +++ b/IPython/config/default/ipcontroller_config.py @@ -35,6 +35,10 @@ c = get_config() # will override the values set for the client and engine connections below. # c.Global.secure = True +# The working directory for the process. The application will use os.chdir +# to change to this directory before starting. +# c.Global.working_dir = os.getcwd() + #----------------------------------------------------------------------------- # Configure the client services #----------------------------------------------------------------------------- diff --git a/IPython/config/default/ipengine_config.py b/IPython/config/default/ipengine_config.py index 8db1949..08d4206 100644 --- a/IPython/config/default/ipengine_config.py +++ b/IPython/config/default/ipengine_config.py @@ -34,6 +34,10 @@ c = get_config() # attribute can be set to the full path of the FURL file. # c.Global.furl_file = u'' +# The working directory for the process. The application will use os.chdir +# to change to this directory before starting. +# c.Global.working_dir = os.getcwd() + #----------------------------------------------------------------------------- # MPI configuration #----------------------------------------------------------------------------- diff --git a/IPython/kernel/clusterdir.py b/IPython/kernel/clusterdir.py index fcf4068..8b4ace4 100644 --- a/IPython/kernel/clusterdir.py +++ b/IPython/kernel/clusterdir.py @@ -256,6 +256,12 @@ class AppWithClusterDirArgParseConfigLoader(ArgParseConfigLoader): '--profile option.', default=NoConfigDefault, metavar='Global.cluster_dir' + ), + self.parser.add_argument('--working-dir', + dest='Global.working_dir',type=unicode, + help='Set the working dir for the process.', + default=NoConfigDefault, + metavar='Global.working_dir' ) self.parser.add_argument('--clean-logs', dest='Global.clean_logs', action='store_true', @@ -293,6 +299,7 @@ class ApplicationWithClusterDir(Application): super(ApplicationWithClusterDir, self).create_default_config() self.default_config.Global.profile = u'default' self.default_config.Global.cluster_dir = u'' + self.default_config.Global.working_dir = os.getcwd() self.default_config.Global.log_to_file = False self.default_config.Global.clean_logs = False @@ -398,6 +405,16 @@ class ApplicationWithClusterDir(Application): pdir = self.cluster_dir_obj.pid_dir self.pid_dir = config.Global.pid_dir = pdir self.log.info("Cluster directory set to: %s" % self.cluster_dir) + config.Global.working_dir = unicode(genutils.expand_path(config.Global.working_dir)) + # Change to the working directory. We do this just before construct + # is called so all the components there have the right working dir. + self.to_working_dir() + + def to_working_dir(self): + wd = self.master_config.Global.working_dir + if unicode(wd) != unicode(os.getcwd()): + os.chdir(wd) + self.log.info("Changing to working dir: %s" % wd) def start_logging(self): # Remove old log files diff --git a/IPython/kernel/ipclusterapp.py b/IPython/kernel/ipclusterapp.py index 4816916..fcbe29e 100644 --- a/IPython/kernel/ipclusterapp.py +++ b/IPython/kernel/ipclusterapp.py @@ -85,7 +85,12 @@ class IPClusterCLLoader(ArgParseConfigLoader): help='Set the cluster dir. This overrides the logic used by the ' '--profile option.', default=NoConfigDefault, - metavar='Global.cluster_dir') + metavar='Global.cluster_dir'), + parent_parser2.add_argument('--working-dir', + dest='Global.working_dir',type=unicode, + help='Set the working dir for the process.', + default=NoConfigDefault, + metavar='Global.working_dir') parent_parser2.add_argument('--log-to-file', action='store_true', dest='Global.log_to_file', default=NoConfigDefault, @@ -242,6 +247,7 @@ class IPClusterApp(ApplicationWithClusterDir): print start_cmd + " ==> " + full_path def pre_construct(self): + # This is where we cd to the working directory. super(IPClusterApp, self).pre_construct() config = self.master_config try: @@ -367,8 +373,6 @@ class IPClusterApp(ApplicationWithClusterDir): # Now write the new pid file AFTER our new forked pid is active. self.write_pid_file() - # cd to the cluster_dir as our working directory. - os.chdir(config.Global.cluster_dir) reactor.addSystemEventTrigger('during','shutdown', self.remove_pid_file) reactor.run() diff --git a/IPython/kernel/ipcontrollerapp.py b/IPython/kernel/ipcontrollerapp.py index 4b7dbeb..02cc1e6 100644 --- a/IPython/kernel/ipcontrollerapp.py +++ b/IPython/kernel/ipcontrollerapp.py @@ -213,8 +213,7 @@ class IPControllerApp(ApplicationWithClusterDir): del c.Global.secure def construct(self): - # I am a little hesitant to put these into InteractiveShell itself. - # But that might be the place for them + # This is the working dir by now. sys.path.insert(0, '') self.start_logging() @@ -250,8 +249,6 @@ class IPControllerApp(ApplicationWithClusterDir): # controllers to clober each other. But Windows is not cleaning # these up properly. self.write_pid_file(overwrite=True) - # cd to the cluster_dir as our working directory. - os.chdir(self.master_config.Global.cluster_dir) # Add a trigger to delete the .pid file upon shutting down. reactor.addSystemEventTrigger('during','shutdown', self.remove_pid_file) reactor.run() diff --git a/IPython/kernel/ipengineapp.py b/IPython/kernel/ipengineapp.py index 513d3fb..4a2a879 100644 --- a/IPython/kernel/ipengineapp.py +++ b/IPython/kernel/ipengineapp.py @@ -154,8 +154,7 @@ class IPEngineApp(ApplicationWithClusterDir): config.Global.furl_file = try_this def construct(self): - # I am a little hesitant to put these into InteractiveShell itself. - # But that might be the place for them + # This is the working dir by now. sys.path.insert(0, '') self.start_mpi() @@ -224,8 +223,6 @@ class IPEngineApp(ApplicationWithClusterDir): log.msg("Error executing statement: %s" % line) def start_app(self): - # cd to the cluster_dir as our working directory. - os.chdir(self.master_config.Global.cluster_dir) reactor.run() diff --git a/IPython/kernel/launcher.py b/IPython/kernel/launcher.py index e90be3a..2d2e4ef 100644 --- a/IPython/kernel/launcher.py +++ b/IPython/kernel/launcher.py @@ -222,7 +222,11 @@ class LocalProcessLauncherProtocol(ProcessProtocol): class LocalProcessLauncher(BaseLauncher): - """Start and stop an external process in an asynchronous manner.""" + """Start and stop an external process in an asynchronous manner. + + This will launch the external process with a working directory of + ``self.working_dir``. + """ # This is used to to construct self.args, which is passed to # spawnProcess. @@ -246,7 +250,8 @@ class LocalProcessLauncher(BaseLauncher): self.process_protocol, str(self.args[0]), # twisted expects these to be str, not unicode [str(a) for a in self.args], # str expected, not unicode - env=os.environ + env=os.environ, + path=self.working_dir # start in the working_dir ) return self.start_deferred else: