diff --git a/IPython/core/application.py b/IPython/core/application.py index 41fea47..42b2f46 100644 --- a/IPython/core/application.py +++ b/IPython/core/application.py @@ -25,10 +25,12 @@ Notes import logging import os + import sys import traceback from copy import deepcopy +from IPython.core import release from IPython.utils.genutils import get_ipython_dir, filefind from IPython.config.loader import ( PyFileConfigLoader, @@ -42,7 +44,7 @@ from IPython.config.loader import ( #----------------------------------------------------------------------------- -class IPythonArgParseConfigLoader(ArgParseConfigLoader): +class BaseAppArgParseConfigLoader(ArgParseConfigLoader): """Default command line options for IPython based applications.""" def _add_other_arguments(self): @@ -77,6 +79,7 @@ class Application(object): config_file_name = 'ipython_config.py' name = 'ipython' + description = 'IPython: an enhanced interactive Python shell.' default_log_level = logging.WARN @@ -141,6 +144,7 @@ class Application(object): """ self.default_config = Config() self.default_config.Global.ipythondir = get_ipython_dir() + self.default_config.Global.log_level = self.log_level def log_default_config(self): self.log.debug('Default config loaded:') @@ -155,7 +159,10 @@ class Application(object): def create_command_line_config(self): """Create and return a command line config loader.""" - return IPythonArgParseConfigLoader(description=self.name) + return BaseAppArgParseConfigLoader( + description=self.description, + version=release.version + ) def pre_load_command_line_config(self): """Do actions just before loading the command line config.""" @@ -331,4 +338,93 @@ class Application(object): self.abort() elif action == 'exit': self.exit() - \ No newline at end of file + + +class AppWithDirArgParseConfigLoader(ArgParseConfigLoader): + """Default command line options for IPython based applications.""" + + def _add_other_arguments(self): + self.parser.add_argument('-ipythondir', '--ipython-dir', + dest='Global.ipythondir',type=str, + help='Set to override default location of Global.ipythondir.', + default=NoConfigDefault, + metavar='Global.ipythondir') + self.parser.add_argument('-p','-profile', '--profile', + dest='Global.profile',type=str, + help='The string name of the ipython profile to be used.', + default=NoConfigDefault, + metavar='Global.profile') + self.parser.add_argument('-log_level', '--log-level', + dest="Global.log_level",type=int, + help='Set the log level (0,10,20,30,40,50). Default is 30.', + default=NoConfigDefault) + self.parser.add_argument('-app_dir', '--app-dir', + dest='Global.app_dir',type=str, + help='Set the application directory where everything for this ' + 'application will be found (including the config file).', + default=NoConfigDefault, + metavar='Global.app_dir') + + +class ApplicationWithDir(Application): + + name = 'appname' + description = 'Application: foo and bar it.' + config_file_name = 'appname_config.py' + default_log_level = logging.WARN + + def create_default_config(self): + super(ApplicationWithDir, self).create_default_config() + self.default_config.Global.profile = 'default' + self.default_config.Global.app_dir = '' + + def create_command_line_config(self): + """Create and return a command line config loader.""" + return AppWithDirArgParseConfigLoader( + description=self.description, + version=release.version + ) + + def find_config_file_name(self): + """Find the config file name for this application.""" + self.find_app_dir() + self.create_app_dir() + + def find_app_dir(self): + """This resolves into full paths, the app directory. + + This method must set ``self.app_dir`` to the full path of + the directory. + """ + # Instead, first look for an explicit app_dir + try: + self.app_dir = self.command_line_config.Global.app_dir + except AttributeError: + self.app_dir = self.default_config.Global.app_dir + self.app_dir = os.path.expandvars(os.path.expanduser(self.app_dir)) + if not self.app_dir: + # Then look for a profile + try: + self.profile = self.command_line_config.Global.profile + except AttributeError: + self.profile = self.default_config.Global.profile + app_dir_name = 'cluster_' + self.profile + try_this = os.path.join(os.getcwd(), app_dir_name) + if os.path.isdir(try_this): + self.app_dir = try_this + else: + self.app_dir = os.path.join(self.ipythondir, app_dir_name) + # These have to be set because they could be different from the one + # that we just computed. Because command line has the highest + # priority, this will always end up in the master_config. + self.default_config.Global.app_dir = self.app_dir + self.command_line_config.Global.app_dir = self.app_dir + + def create_app_dir(self): + """Make sure that the cluster, security and log dirs exist.""" + if not os.path.isdir(self.app_dir): + os.makedirs(self.app_dir, mode=0777) + + def find_config_file_paths(self): + """Set the search paths for resolving the config file.""" + self.config_file_paths = (self.app_dir,) diff --git a/IPython/core/ipapp.py b/IPython/core/ipapp.py index 7d5d4e1..d64cf6f 100644 --- a/IPython/core/ipapp.py +++ b/IPython/core/ipapp.py @@ -28,7 +28,7 @@ import os import sys import warnings -from IPython.core.application import Application, IPythonArgParseConfigLoader +from IPython.core.application import Application, BaseAppArgParseConfigLoader from IPython.core import release from IPython.core.iplib import InteractiveShell from IPython.config.loader import ( @@ -283,20 +283,23 @@ cl_args = ( # # These are only here to get the proper deprecation warnings (('-pylab',), dict( action='store_true', dest='Global.pylab', default=NoConfigDefault, - help="Disabled. Pylab has been disabled until matplotlib supports this version of IPython.") + help="Disabled. Pylab has been disabled until matplotlib " + "supports this version of IPython.") ) ) -class IPythonAppCLConfigLoader(IPythonArgParseConfigLoader): +class IPythonAppCLConfigLoader(BaseAppArgParseConfigLoader): arguments = cl_args _default_config_file_name = 'ipython_config.py' + class IPythonApp(Application): name = 'ipython' + description = 'IPython: an enhanced interactive Python shell.' config_file_name = _default_config_file_name def create_default_config(self): @@ -313,11 +316,6 @@ class IPythonApp(Application): # By default always interact by starting the IPython mainloop. self.default_config.Global.interact = True - # Let the parent class set the default, but each time log_level - # changes from config, we need to update self.log_level as that is - # what updates the actual log level in self.log. - self.default_config.Global.log_level = self.log_level - # No GUI integration by default self.default_config.Global.wthread = False self.default_config.Global.q4thread = False @@ -326,8 +324,9 @@ class IPythonApp(Application): def create_command_line_config(self): """Create and return a command line config loader.""" return IPythonAppCLConfigLoader( - description=ipython_desc, - version=release.version) + description=self.description, + version=release.version + ) def post_load_command_line_config(self): """Do actions after loading cl config.""" @@ -540,7 +539,7 @@ def load_default_config(ipythondir=None): def launch_new_instance(): - """Create a run a full blown IPython instance""" + """Create and run a full blown IPython instance""" app = IPythonApp() app.start() diff --git a/IPython/kernel/ipcontrollerapp.py b/IPython/kernel/ipcontrollerapp.py index 5f828ba..65abba8 100644 --- a/IPython/kernel/ipcontrollerapp.py +++ b/IPython/kernel/ipcontrollerapp.py @@ -26,7 +26,11 @@ from twisted.python import log from IPython.config.loader import Config, NoConfigDefault -from IPython.core.application import Application, IPythonArgParseConfigLoader +from IPython.core.application import ( + ApplicationWithDir, + BaseAppArgParseConfigLoader +) + from IPython.core import release from IPython.utils.traitlets import Int, Str, Bool, Instance @@ -152,25 +156,22 @@ cl_args = ( (('-r','--reuse-furls'), dict( action='store_true', dest='Global.reuse_furls', default=NoConfigDefault, help='Try to reuse all FURL files.') - ), - (('-cluster_dir', '--cluster-dir',), dict( - type=str, dest='Global.cluster_dir', default=NoConfigDefault, - help='Absolute or relative path to the cluster directory.', - metavar='Global.cluster_dir') - ), + ) ) -class IPControllerAppCLConfigLoader(IPythonArgParseConfigLoader): +class IPControllerAppCLConfigLoader(BaseAppArgParseConfigLoader): arguments = cl_args _default_config_file_name = 'ipcontroller_config.py' -class IPControllerApp(Application): + +class IPControllerApp(ApplicationWithDir): name = 'ipcontroller' + description = 'Start the IPython controller for parallel computing.' config_file_name = _default_config_file_name default_log_level = logging.DEBUG @@ -178,71 +179,16 @@ class IPControllerApp(Application): super(IPControllerApp, self).create_default_config() self.default_config.Global.reuse_furls = False self.default_config.Global.import_statements = [] - self.default_config.Global.profile = 'default' self.default_config.Global.log_dir_name = 'log' self.default_config.Global.security_dir_name = 'security' self.default_config.Global.log_to_file = False - # Resolve the default cluster_dir using the default profile - self.default_config.Global.cluster_dir = '' - - def create_command_line_config(self): - """Create and return a command line config loader.""" - - return IPControllerAppCLConfigLoader( - description="Start an IPython controller", - version=release.version) - - def find_config_file_name(self): - """Find the config file name for this application.""" - self.find_cluster_dir() - self.create_cluster_dir() - - def find_cluster_dir(self): - """This resolves into full paths, the various cluster directories. - - This method must set ``self.cluster_dir`` to the full paths of - the directory. - """ - # Ignore self.command_line_config.Global.config_file - # Instead, first look for an explicit cluster_dir - try: - self.cluster_dir = self.command_line_config.Global.cluster_dir - except AttributeError: - self.cluster_dir = self.default_config.Global.cluster_dir - self.cluster_dir = os.path.expandvars(os.path.expanduser(self.cluster_dir)) - if not self.cluster_dir: - # Then look for a profile - try: - self.profile = self.command_line_config.Global.profile - except AttributeError: - self.profile = self.default_config.Global.profile - cluster_dir_name = 'cluster_' + self.profile - try_this = os.path.join(os.getcwd(), cluster_dir_name) - if os.path.isdir(try_this): - self.cluster_dir = try_this - else: - self.cluster_dir = os.path.join(self.ipythondir, cluster_dir_name) - # These have to be set because they could be different from the one - # that we just computed. Because command line has the highest - # priority, this will always end up in the master_config. - self.default_config.Global.cluster_dir = self.cluster_dir - self.command_line_config.Global.cluster_dir = self.cluster_dir - - def create_cluster_dir(self): - """Make sure that the cluster, security and log dirs exist.""" - if not os.path.isdir(self.cluster_dir): - os.makedirs(self.cluster_dir, mode=0777) - - def find_config_file_paths(self): - """Set the search paths for resolving the config file.""" - self.config_file_paths = (self.cluster_dir,) def pre_construct(self): # Now set the security_dir and log_dir and create them. We use # the names an construct the absolute paths. - security_dir = os.path.join(self.master_config.Global.cluster_dir, + security_dir = os.path.join(self.master_config.Global.app_dir, self.master_config.Global.security_dir_name) - log_dir = os.path.join(self.master_config.Global.cluster_dir, + log_dir = os.path.join(self.master_config.Global.app_dir, self.master_config.Global.log_dir_name) if not os.path.isdir(security_dir): os.mkdir(security_dir, 0700) @@ -255,7 +201,7 @@ class IPControllerApp(Application): self.log_dir = self.master_config.Global.log_dir = log_dir # Now setup reuse_furls - if hasattr(self.master_config.Global.reuse_furls): + if hasattr(self.master_config.Global, 'reuse_furls'): self.master_config.FCClientServiceFactory.reuse_furls = \ self.master_config.Global.reuse_furls self.master_config.FCEngineServiceFactory.reuse_furls = \ @@ -305,6 +251,8 @@ class IPControllerApp(Application): self.main_service.startService() reactor.run() -if __name__ == '__main__': + +def launch_new_instance(): + """Create and run the IPython controller""" app = IPControllerApp() app.start() diff --git a/IPython/kernel/scripts/ipcontroller b/IPython/kernel/scripts/ipcontroller index b4c86a4..5209663 100755 --- a/IPython/kernel/scripts/ipcontroller +++ b/IPython/kernel/scripts/ipcontroller @@ -1,20 +1,18 @@ #!/usr/bin/env python # encoding: utf-8 -__docformat__ = "restructuredtext en" - -#------------------------------------------------------------------------------- -# Copyright (C) 2008 The IPython Development Team +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2009 The IPython Development Team # # Distributed under the terms of the BSD License. The full license is in # the file COPYING, distributed as part of this software. -#------------------------------------------------------------------------------- +#----------------------------------------------------------------------------- -#------------------------------------------------------------------------------- +#----------------------------------------------------------------------------- # Imports -#------------------------------------------------------------------------------- +#----------------------------------------------------------------------------- + -if __name__ == '__main__': - from IPython.kernel.scripts import ipcontroller - ipcontroller.main() +from IPython.kernel.ipcontrollerapp import launch_new_instance +launch_new_instance() diff --git a/setup.py b/setup.py index 0826f67..6170588 100755 --- a/setup.py +++ b/setup.py @@ -169,7 +169,7 @@ if 'setuptools' in sys.modules: 'console_scripts': [ 'ipython = IPython.core.ipapp:launch_new_instance', 'pycolor = IPython.utils.PyColorize:main', - 'ipcontroller = IPython.kernel.scripts.ipcontroller:main', + 'ipcontroller = IPython.kernel.ipcontrollerapp:launch_new_instance', 'ipengine = IPython.kernel.scripts.ipengine:main', 'ipcluster = IPython.kernel.scripts.ipcluster:main', 'ipythonx = IPython.frontend.wx.ipythonx:main',