profileapp.py
313 lines
| 10.6 KiB
| text/x-python
|
PythonLexer
MinRK
|
r4024 | # encoding: utf-8 | ||
""" | ||||
An application for managing IPython profiles. | ||||
To be invoked as the `ipython profile` subcommand. | ||||
Authors: | ||||
* Min RK | ||||
""" | ||||
#----------------------------------------------------------------------------- | ||||
MinRK
|
r12419 | # Copyright (C) 2008 The IPython Development Team | ||
MinRK
|
r4024 | # | ||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#----------------------------------------------------------------------------- | ||||
#----------------------------------------------------------------------------- | ||||
# Imports | ||||
#----------------------------------------------------------------------------- | ||||
import os | ||||
Thomas Kluyver
|
r9399 | from IPython.config.application import Application | ||
MinRK
|
r4024 | from IPython.core.application import ( | ||
Thomas Kluyver
|
r9399 | BaseIPythonApplication, base_flags | ||
MinRK
|
r4024 | ) | ||
from IPython.core.profiledir import ProfileDir | ||||
MinRK
|
r12419 | from IPython.utils.importstring import import_item | ||
MinRK
|
r5769 | from IPython.utils.path import get_ipython_dir, get_ipython_package_dir | ||
MinRK
|
r4024 | from IPython.utils.traitlets import Unicode, Bool, Dict | ||
#----------------------------------------------------------------------------- | ||||
# Constants | ||||
#----------------------------------------------------------------------------- | ||||
MinRK
|
r4038 | create_help = """Create an IPython profile by name | ||
MinRK
|
r4024 | |||
Create an ipython profile directory by its name or | ||||
profile directory path. Profile directories contain | ||||
configuration, log and security related files and are named | ||||
using the convention 'profile_<name>'. By default they are | ||||
located in your ipython directory. Once created, you will | ||||
can edit the configuration files in the profile | ||||
directory to configure IPython. Most users will create a | ||||
MinRK
|
r4038 | profile directory by name, | ||
MinRK
|
r4024 | `ipython profile create myprofile`, which will put the directory | ||
in `<ipython_dir>/profile_myprofile`. | ||||
""" | ||||
list_help = """List available IPython profiles | ||||
List all available profiles, by profile location, that can | ||||
be found in the current working directly or in the ipython | ||||
directory. Profile directories are named using the convention | ||||
'profile_<profile>'. | ||||
""" | ||||
profile_help = """Manage IPython profiles | ||||
Profile directories contain | ||||
configuration, log and security related files and are named | ||||
using the convention 'profile_<name>'. By default they are | ||||
located in your ipython directory. You can create profiles | ||||
with `ipython profile create <name>`, or see the profiles you | ||||
already have with `ipython profile list` | ||||
To get started configuring IPython, simply do: | ||||
$> ipython profile create | ||||
and IPython will create the default profile in <ipython_dir>/profile_default, | ||||
where you can edit ipython_config.py to start configuring IPython. | ||||
""" | ||||
Brian Granger
|
r4216 | _list_examples = "ipython profile list # list all profiles" | ||
_create_examples = """ | ||||
Brian E. Granger
|
r4218 | ipython profile create foo # create profile foo w/ default config files | ||
ipython profile create foo --reset # restage default config files over current | ||||
ipython profile create foo --parallel # also stage parallel config files | ||||
Brian Granger
|
r4216 | """ | ||
_main_examples = """ | ||||
ipython profile create -h # show the help string for the create subcommand | ||||
ipython profile list -h # show the help string for the list subcommand | ||||
MinRK
|
r6901 | |||
Katie Silverio
|
r12954 | ipython locate profile foo # print the path to the directory for profile 'foo' | ||
Brian Granger
|
r4216 | """ | ||
MinRK
|
r4024 | #----------------------------------------------------------------------------- | ||
# Profile Application Class (for `ipython profile` subcommand) | ||||
#----------------------------------------------------------------------------- | ||||
Brian Granger
|
r6191 | def list_profiles_in(path): | ||
"""list profiles in a given root directory""" | ||||
files = os.listdir(path) | ||||
profiles = [] | ||||
for f in files: | ||||
MinRK
|
r12779 | try: | ||
full_path = os.path.join(path, f) | ||||
except UnicodeError: | ||||
continue | ||||
Brian Granger
|
r6191 | if os.path.isdir(full_path) and f.startswith('profile_'): | ||
profiles.append(f.split('_',1)[-1]) | ||||
return profiles | ||||
def list_bundled_profiles(): | ||||
"""list profiles that are bundled with IPython.""" | ||||
path = os.path.join(get_ipython_package_dir(), u'config', u'profile') | ||||
files = os.listdir(path) | ||||
profiles = [] | ||||
for profile in files: | ||||
full_path = os.path.join(path, profile) | ||||
Thomas Kluyver
|
r6491 | if os.path.isdir(full_path) and profile != "__pycache__": | ||
Brian Granger
|
r6191 | profiles.append(profile) | ||
return profiles | ||||
MinRK
|
r6901 | class ProfileLocate(BaseIPythonApplication): | ||
Katie Silverio
|
r12949 | description = """print the path to an IPython profile dir""" | ||
MinRK
|
r6901 | |||
def parse_command_line(self, argv=None): | ||||
super(ProfileLocate, self).parse_command_line(argv) | ||||
if self.extra_args: | ||||
self.profile = self.extra_args[0] | ||||
def start(self): | ||||
print self.profile_dir.location | ||||
MinRK
|
r4024 | class ProfileList(Application): | ||
name = u'ipython-profile' | ||||
description = list_help | ||||
Brian Granger
|
r4216 | examples = _list_examples | ||
MinRK
|
r4214 | aliases = Dict({ | ||
'ipython-dir' : 'ProfileList.ipython_dir', | ||||
'log-level' : 'Application.log_level', | ||||
}) | ||||
MinRK
|
r4024 | flags = Dict(dict( | ||
debug = ({'Application' : {'log_level' : 0}}, | ||||
MinRK
|
r4214 | "Set Application.log_level to 0, maximizing log output." | ||
MinRK
|
r4024 | ) | ||
)) | ||||
Brian Granger
|
r4216 | |||
Bernardo B. Marques
|
r4872 | ipython_dir = Unicode(get_ipython_dir(), config=True, | ||
MinRK
|
r4024 | help=""" | ||
The name of the IPython directory. This directory is used for logging | ||||
configuration (through profiles), history storage, etc. The default | ||||
is usually $HOME/.ipython. This options can also be specified through | ||||
Bradley M. Froehle
|
r6696 | the environment variable IPYTHONDIR. | ||
MinRK
|
r4024 | """ | ||
) | ||||
Brian Granger
|
r6191 | |||
MinRK
|
r5770 | def _print_profiles(self, profiles): | ||
"""print list of profiles, indented.""" | ||||
for profile in profiles: | ||||
print ' %s' % profile | ||||
Brian Granger
|
r6191 | |||
MinRK
|
r4024 | def list_profile_dirs(self): | ||
Brian Granger
|
r6191 | profiles = list_bundled_profiles() | ||
MinRK
|
r5769 | if profiles: | ||
print "Available profiles in IPython:" | ||||
MinRK
|
r5770 | self._print_profiles(profiles) | ||
MinRK
|
r5769 | |||
print " The first request for a bundled profile will copy it" | ||||
print " into your IPython directory (%s)," % self.ipython_dir | ||||
MinRK
|
r5770 | print " where you can customize it." | ||
MinRK
|
r5769 | |||
Brian Granger
|
r6191 | profiles = list_profiles_in(self.ipython_dir) | ||
MinRK
|
r5769 | if profiles: | ||
print "Available profiles in %s:" % self.ipython_dir | ||||
MinRK
|
r5770 | self._print_profiles(profiles) | ||
MinRK
|
r5769 | |||
Brian Granger
|
r6191 | profiles = list_profiles_in(os.getcwdu()) | ||
MinRK
|
r5769 | if profiles: | ||
print "Available profiles in current directory (%s):" % os.getcwdu() | ||||
MinRK
|
r5770 | self._print_profiles(profiles) | ||
print "To use any of the above profiles, start IPython with:" | ||||
print " ipython --profile=<name>" | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4024 | def start(self): | ||
self.list_profile_dirs() | ||||
create_flags = {} | ||||
create_flags.update(base_flags) | ||||
MinRK
|
r4247 | # don't include '--init' flag, which implies running profile create in other apps | ||
create_flags.pop('init') | ||||
create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}}, | ||||
"reset config files in this profile to the defaults.") | ||||
create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}}, | ||||
"Include the config files for parallel " | ||||
"computing apps (ipengine, ipcontroller, etc.)") | ||||
MinRK
|
r4024 | |||
Brian Granger
|
r4215 | |||
MinRK
|
r4024 | class ProfileCreate(BaseIPythonApplication): | ||
name = u'ipython-profile' | ||||
description = create_help | ||||
Brian Granger
|
r4216 | examples = _create_examples | ||
MinRK
|
r4024 | auto_create = Bool(True, config=False) | ||
MinRK
|
r12420 | def _log_format_default(self): | ||
return "[%(name)s] %(message)s" | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4024 | def _copy_config_files_default(self): | ||
return True | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4038 | parallel = Bool(False, config=True, | ||
MinRK
|
r4024 | help="whether to include parallel computing config files") | ||
MinRK
|
r4038 | def _parallel_changed(self, name, old, new): | ||
Bernardo B. Marques
|
r4872 | parallel_files = [ 'ipcontroller_config.py', | ||
'ipengine_config.py', | ||||
MinRK
|
r4024 | 'ipcluster_config.py' | ||
] | ||||
if new: | ||||
MinRK
|
r4038 | for cf in parallel_files: | ||
MinRK
|
r4024 | self.config_files.append(cf) | ||
else: | ||||
MinRK
|
r4038 | for cf in parallel_files: | ||
MinRK
|
r4024 | if cf in self.config_files: | ||
self.config_files.remove(cf) | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4024 | def parse_command_line(self, argv): | ||
super(ProfileCreate, self).parse_command_line(argv) | ||||
# accept positional arg as profile name | ||||
if self.extra_args: | ||||
self.profile = self.extra_args[0] | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4024 | flags = Dict(create_flags) | ||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4024 | classes = [ProfileDir] | ||
MinRK
|
r12419 | |||
def _import_app(self, app_path): | ||||
"""import an app class""" | ||||
app = None | ||||
name = app_path.rsplit('.', 1)[-1] | ||||
try: | ||||
app = import_item(app_path) | ||||
except ImportError as e: | ||||
self.log.info("Couldn't import %s, config file will be excluded", name) | ||||
except Exception: | ||||
self.log.warn('Unexpected error importing %s', name, exc_info=True) | ||||
return app | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4025 | def init_config_files(self): | ||
super(ProfileCreate, self).init_config_files() | ||||
# use local imports, since these classes may import from here | ||||
Fernando Perez
|
r11024 | from IPython.terminal.ipapp import TerminalIPythonApp | ||
MinRK
|
r4025 | apps = [TerminalIPythonApp] | ||
MinRK
|
r12419 | for app_path in ( | ||
'IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp', | ||||
'IPython.html.notebookapp.NotebookApp', | ||||
'IPython.nbconvert.nbconvertapp.NbConvertApp', | ||||
): | ||||
app = self._import_app(app_path) | ||||
if app is not None: | ||||
apps.append(app) | ||||
MinRK
|
r4038 | if self.parallel: | ||
MinRK
|
r4025 | from IPython.parallel.apps.ipcontrollerapp import IPControllerApp | ||
from IPython.parallel.apps.ipengineapp import IPEngineApp | ||||
from IPython.parallel.apps.ipclusterapp import IPClusterStart | ||||
from IPython.parallel.apps.iploggerapp import IPLoggerApp | ||||
apps.extend([ | ||||
IPControllerApp, | ||||
IPEngineApp, | ||||
IPClusterStart, | ||||
IPLoggerApp, | ||||
]) | ||||
for App in apps: | ||||
app = App() | ||||
app.config.update(self.config) | ||||
app.log = self.log | ||||
app.overwrite = self.overwrite | ||||
app.copy_config_files=True | ||||
app.profile = self.profile | ||||
app.init_profile_dir() | ||||
app.init_config_files() | ||||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4025 | def stage_default_config_file(self): | ||
pass | ||||
MinRK
|
r4024 | |||
Brian Granger
|
r4215 | |||
MinRK
|
r4024 | class ProfileApp(Application): | ||
name = u'ipython-profile' | ||||
description = profile_help | ||||
Brian Granger
|
r4216 | examples = _main_examples | ||
Brian Granger
|
r4215 | |||
MinRK
|
r4024 | subcommands = Dict(dict( | ||
MinRK
|
r6901 | create = (ProfileCreate, ProfileCreate.description.splitlines()[0]), | ||
list = (ProfileList, ProfileList.description.splitlines()[0]), | ||||
Katie Silverio
|
r12949 | locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]), | ||
MinRK
|
r4024 | )) | ||
Bernardo B. Marques
|
r4872 | |||
MinRK
|
r4026 | def start(self): | ||
if self.subapp is None: | ||||
print "No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()) | ||||
self.print_description() | ||||
self.print_subcommands() | ||||
self.exit(1) | ||||
else: | ||||
return self.subapp.start() | ||||