##// END OF EJS Templates
catch unicode error listing profiles...
MinRK -
Show More
@@ -1,310 +1,313 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for managing IPython profiles.
3 An application for managing IPython profiles.
4
4
5 To be invoked as the `ipython profile` subcommand.
5 To be invoked as the `ipython profile` subcommand.
6
6
7 Authors:
7 Authors:
8
8
9 * Min RK
9 * Min RK
10
10
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import os
24 import os
25
25
26 from IPython.config.application import Application
26 from IPython.config.application import Application
27 from IPython.core.application import (
27 from IPython.core.application import (
28 BaseIPythonApplication, base_flags
28 BaseIPythonApplication, base_flags
29 )
29 )
30 from IPython.core.profiledir import ProfileDir
30 from IPython.core.profiledir import ProfileDir
31 from IPython.utils.importstring import import_item
31 from IPython.utils.importstring import import_item
32 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
32 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
33 from IPython.utils.traitlets import Unicode, Bool, Dict
33 from IPython.utils.traitlets import Unicode, Bool, Dict
34
34
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # Constants
36 # Constants
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38
38
39 create_help = """Create an IPython profile by name
39 create_help = """Create an IPython profile by name
40
40
41 Create an ipython profile directory by its name or
41 Create an ipython profile directory by its name or
42 profile directory path. Profile directories contain
42 profile directory path. Profile directories contain
43 configuration, log and security related files and are named
43 configuration, log and security related files and are named
44 using the convention 'profile_<name>'. By default they are
44 using the convention 'profile_<name>'. By default they are
45 located in your ipython directory. Once created, you will
45 located in your ipython directory. Once created, you will
46 can edit the configuration files in the profile
46 can edit the configuration files in the profile
47 directory to configure IPython. Most users will create a
47 directory to configure IPython. Most users will create a
48 profile directory by name,
48 profile directory by name,
49 `ipython profile create myprofile`, which will put the directory
49 `ipython profile create myprofile`, which will put the directory
50 in `<ipython_dir>/profile_myprofile`.
50 in `<ipython_dir>/profile_myprofile`.
51 """
51 """
52 list_help = """List available IPython profiles
52 list_help = """List available IPython profiles
53
53
54 List all available profiles, by profile location, that can
54 List all available profiles, by profile location, that can
55 be found in the current working directly or in the ipython
55 be found in the current working directly or in the ipython
56 directory. Profile directories are named using the convention
56 directory. Profile directories are named using the convention
57 'profile_<profile>'.
57 'profile_<profile>'.
58 """
58 """
59 profile_help = """Manage IPython profiles
59 profile_help = """Manage IPython profiles
60
60
61 Profile directories contain
61 Profile directories contain
62 configuration, log and security related files and are named
62 configuration, log and security related files and are named
63 using the convention 'profile_<name>'. By default they are
63 using the convention 'profile_<name>'. By default they are
64 located in your ipython directory. You can create profiles
64 located in your ipython directory. You can create profiles
65 with `ipython profile create <name>`, or see the profiles you
65 with `ipython profile create <name>`, or see the profiles you
66 already have with `ipython profile list`
66 already have with `ipython profile list`
67
67
68 To get started configuring IPython, simply do:
68 To get started configuring IPython, simply do:
69
69
70 $> ipython profile create
70 $> ipython profile create
71
71
72 and IPython will create the default profile in <ipython_dir>/profile_default,
72 and IPython will create the default profile in <ipython_dir>/profile_default,
73 where you can edit ipython_config.py to start configuring IPython.
73 where you can edit ipython_config.py to start configuring IPython.
74
74
75 """
75 """
76
76
77 _list_examples = "ipython profile list # list all profiles"
77 _list_examples = "ipython profile list # list all profiles"
78
78
79 _create_examples = """
79 _create_examples = """
80 ipython profile create foo # create profile foo w/ default config files
80 ipython profile create foo # create profile foo w/ default config files
81 ipython profile create foo --reset # restage default config files over current
81 ipython profile create foo --reset # restage default config files over current
82 ipython profile create foo --parallel # also stage parallel config files
82 ipython profile create foo --parallel # also stage parallel config files
83 """
83 """
84
84
85 _main_examples = """
85 _main_examples = """
86 ipython profile create -h # show the help string for the create subcommand
86 ipython profile create -h # show the help string for the create subcommand
87 ipython profile list -h # show the help string for the list subcommand
87 ipython profile list -h # show the help string for the list subcommand
88
88
89 ipython locate profile foo # print the path to the directory for profile 'foo'
89 ipython locate profile foo # print the path to the directory for profile 'foo'
90 """
90 """
91
91
92 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
93 # Profile Application Class (for `ipython profile` subcommand)
93 # Profile Application Class (for `ipython profile` subcommand)
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95
95
96
96
97 def list_profiles_in(path):
97 def list_profiles_in(path):
98 """list profiles in a given root directory"""
98 """list profiles in a given root directory"""
99 files = os.listdir(path)
99 files = os.listdir(path)
100 profiles = []
100 profiles = []
101 for f in files:
101 for f in files:
102 full_path = os.path.join(path, f)
102 try:
103 full_path = os.path.join(path, f)
104 except UnicodeError:
105 continue
103 if os.path.isdir(full_path) and f.startswith('profile_'):
106 if os.path.isdir(full_path) and f.startswith('profile_'):
104 profiles.append(f.split('_',1)[-1])
107 profiles.append(f.split('_',1)[-1])
105 return profiles
108 return profiles
106
109
107
110
108 def list_bundled_profiles():
111 def list_bundled_profiles():
109 """list profiles that are bundled with IPython."""
112 """list profiles that are bundled with IPython."""
110 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
113 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
111 files = os.listdir(path)
114 files = os.listdir(path)
112 profiles = []
115 profiles = []
113 for profile in files:
116 for profile in files:
114 full_path = os.path.join(path, profile)
117 full_path = os.path.join(path, profile)
115 if os.path.isdir(full_path) and profile != "__pycache__":
118 if os.path.isdir(full_path) and profile != "__pycache__":
116 profiles.append(profile)
119 profiles.append(profile)
117 return profiles
120 return profiles
118
121
119
122
120 class ProfileLocate(BaseIPythonApplication):
123 class ProfileLocate(BaseIPythonApplication):
121 description = """print the path an IPython profile dir"""
124 description = """print the path an IPython profile dir"""
122
125
123 def parse_command_line(self, argv=None):
126 def parse_command_line(self, argv=None):
124 super(ProfileLocate, self).parse_command_line(argv)
127 super(ProfileLocate, self).parse_command_line(argv)
125 if self.extra_args:
128 if self.extra_args:
126 self.profile = self.extra_args[0]
129 self.profile = self.extra_args[0]
127
130
128 def start(self):
131 def start(self):
129 print self.profile_dir.location
132 print self.profile_dir.location
130
133
131
134
132 class ProfileList(Application):
135 class ProfileList(Application):
133 name = u'ipython-profile'
136 name = u'ipython-profile'
134 description = list_help
137 description = list_help
135 examples = _list_examples
138 examples = _list_examples
136
139
137 aliases = Dict({
140 aliases = Dict({
138 'ipython-dir' : 'ProfileList.ipython_dir',
141 'ipython-dir' : 'ProfileList.ipython_dir',
139 'log-level' : 'Application.log_level',
142 'log-level' : 'Application.log_level',
140 })
143 })
141 flags = Dict(dict(
144 flags = Dict(dict(
142 debug = ({'Application' : {'log_level' : 0}},
145 debug = ({'Application' : {'log_level' : 0}},
143 "Set Application.log_level to 0, maximizing log output."
146 "Set Application.log_level to 0, maximizing log output."
144 )
147 )
145 ))
148 ))
146
149
147 ipython_dir = Unicode(get_ipython_dir(), config=True,
150 ipython_dir = Unicode(get_ipython_dir(), config=True,
148 help="""
151 help="""
149 The name of the IPython directory. This directory is used for logging
152 The name of the IPython directory. This directory is used for logging
150 configuration (through profiles), history storage, etc. The default
153 configuration (through profiles), history storage, etc. The default
151 is usually $HOME/.ipython. This options can also be specified through
154 is usually $HOME/.ipython. This options can also be specified through
152 the environment variable IPYTHONDIR.
155 the environment variable IPYTHONDIR.
153 """
156 """
154 )
157 )
155
158
156
159
157 def _print_profiles(self, profiles):
160 def _print_profiles(self, profiles):
158 """print list of profiles, indented."""
161 """print list of profiles, indented."""
159 for profile in profiles:
162 for profile in profiles:
160 print ' %s' % profile
163 print ' %s' % profile
161
164
162 def list_profile_dirs(self):
165 def list_profile_dirs(self):
163 profiles = list_bundled_profiles()
166 profiles = list_bundled_profiles()
164 if profiles:
167 if profiles:
165 print
168 print
166 print "Available profiles in IPython:"
169 print "Available profiles in IPython:"
167 self._print_profiles(profiles)
170 self._print_profiles(profiles)
168 print
171 print
169 print " The first request for a bundled profile will copy it"
172 print " The first request for a bundled profile will copy it"
170 print " into your IPython directory (%s)," % self.ipython_dir
173 print " into your IPython directory (%s)," % self.ipython_dir
171 print " where you can customize it."
174 print " where you can customize it."
172
175
173 profiles = list_profiles_in(self.ipython_dir)
176 profiles = list_profiles_in(self.ipython_dir)
174 if profiles:
177 if profiles:
175 print
178 print
176 print "Available profiles in %s:" % self.ipython_dir
179 print "Available profiles in %s:" % self.ipython_dir
177 self._print_profiles(profiles)
180 self._print_profiles(profiles)
178
181
179 profiles = list_profiles_in(os.getcwdu())
182 profiles = list_profiles_in(os.getcwdu())
180 if profiles:
183 if profiles:
181 print
184 print
182 print "Available profiles in current directory (%s):" % os.getcwdu()
185 print "Available profiles in current directory (%s):" % os.getcwdu()
183 self._print_profiles(profiles)
186 self._print_profiles(profiles)
184
187
185 print
188 print
186 print "To use any of the above profiles, start IPython with:"
189 print "To use any of the above profiles, start IPython with:"
187 print " ipython --profile=<name>"
190 print " ipython --profile=<name>"
188 print
191 print
189
192
190 def start(self):
193 def start(self):
191 self.list_profile_dirs()
194 self.list_profile_dirs()
192
195
193
196
194 create_flags = {}
197 create_flags = {}
195 create_flags.update(base_flags)
198 create_flags.update(base_flags)
196 # don't include '--init' flag, which implies running profile create in other apps
199 # don't include '--init' flag, which implies running profile create in other apps
197 create_flags.pop('init')
200 create_flags.pop('init')
198 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
201 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
199 "reset config files in this profile to the defaults.")
202 "reset config files in this profile to the defaults.")
200 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
203 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
201 "Include the config files for parallel "
204 "Include the config files for parallel "
202 "computing apps (ipengine, ipcontroller, etc.)")
205 "computing apps (ipengine, ipcontroller, etc.)")
203
206
204
207
205 class ProfileCreate(BaseIPythonApplication):
208 class ProfileCreate(BaseIPythonApplication):
206 name = u'ipython-profile'
209 name = u'ipython-profile'
207 description = create_help
210 description = create_help
208 examples = _create_examples
211 examples = _create_examples
209 auto_create = Bool(True, config=False)
212 auto_create = Bool(True, config=False)
210 def _log_format_default(self):
213 def _log_format_default(self):
211 return "[%(name)s] %(message)s"
214 return "[%(name)s] %(message)s"
212
215
213 def _copy_config_files_default(self):
216 def _copy_config_files_default(self):
214 return True
217 return True
215
218
216 parallel = Bool(False, config=True,
219 parallel = Bool(False, config=True,
217 help="whether to include parallel computing config files")
220 help="whether to include parallel computing config files")
218 def _parallel_changed(self, name, old, new):
221 def _parallel_changed(self, name, old, new):
219 parallel_files = [ 'ipcontroller_config.py',
222 parallel_files = [ 'ipcontroller_config.py',
220 'ipengine_config.py',
223 'ipengine_config.py',
221 'ipcluster_config.py'
224 'ipcluster_config.py'
222 ]
225 ]
223 if new:
226 if new:
224 for cf in parallel_files:
227 for cf in parallel_files:
225 self.config_files.append(cf)
228 self.config_files.append(cf)
226 else:
229 else:
227 for cf in parallel_files:
230 for cf in parallel_files:
228 if cf in self.config_files:
231 if cf in self.config_files:
229 self.config_files.remove(cf)
232 self.config_files.remove(cf)
230
233
231 def parse_command_line(self, argv):
234 def parse_command_line(self, argv):
232 super(ProfileCreate, self).parse_command_line(argv)
235 super(ProfileCreate, self).parse_command_line(argv)
233 # accept positional arg as profile name
236 # accept positional arg as profile name
234 if self.extra_args:
237 if self.extra_args:
235 self.profile = self.extra_args[0]
238 self.profile = self.extra_args[0]
236
239
237 flags = Dict(create_flags)
240 flags = Dict(create_flags)
238
241
239 classes = [ProfileDir]
242 classes = [ProfileDir]
240
243
241 def _import_app(self, app_path):
244 def _import_app(self, app_path):
242 """import an app class"""
245 """import an app class"""
243 app = None
246 app = None
244 name = app_path.rsplit('.', 1)[-1]
247 name = app_path.rsplit('.', 1)[-1]
245 try:
248 try:
246 app = import_item(app_path)
249 app = import_item(app_path)
247 except ImportError as e:
250 except ImportError as e:
248 self.log.info("Couldn't import %s, config file will be excluded", name)
251 self.log.info("Couldn't import %s, config file will be excluded", name)
249 except Exception:
252 except Exception:
250 self.log.warn('Unexpected error importing %s', name, exc_info=True)
253 self.log.warn('Unexpected error importing %s', name, exc_info=True)
251 return app
254 return app
252
255
253 def init_config_files(self):
256 def init_config_files(self):
254 super(ProfileCreate, self).init_config_files()
257 super(ProfileCreate, self).init_config_files()
255 # use local imports, since these classes may import from here
258 # use local imports, since these classes may import from here
256 from IPython.terminal.ipapp import TerminalIPythonApp
259 from IPython.terminal.ipapp import TerminalIPythonApp
257 apps = [TerminalIPythonApp]
260 apps = [TerminalIPythonApp]
258 for app_path in (
261 for app_path in (
259 'IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
262 'IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
260 'IPython.html.notebookapp.NotebookApp',
263 'IPython.html.notebookapp.NotebookApp',
261 'IPython.nbconvert.nbconvertapp.NbConvertApp',
264 'IPython.nbconvert.nbconvertapp.NbConvertApp',
262 ):
265 ):
263 app = self._import_app(app_path)
266 app = self._import_app(app_path)
264 if app is not None:
267 if app is not None:
265 apps.append(app)
268 apps.append(app)
266 if self.parallel:
269 if self.parallel:
267 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
270 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
268 from IPython.parallel.apps.ipengineapp import IPEngineApp
271 from IPython.parallel.apps.ipengineapp import IPEngineApp
269 from IPython.parallel.apps.ipclusterapp import IPClusterStart
272 from IPython.parallel.apps.ipclusterapp import IPClusterStart
270 from IPython.parallel.apps.iploggerapp import IPLoggerApp
273 from IPython.parallel.apps.iploggerapp import IPLoggerApp
271 apps.extend([
274 apps.extend([
272 IPControllerApp,
275 IPControllerApp,
273 IPEngineApp,
276 IPEngineApp,
274 IPClusterStart,
277 IPClusterStart,
275 IPLoggerApp,
278 IPLoggerApp,
276 ])
279 ])
277 for App in apps:
280 for App in apps:
278 app = App()
281 app = App()
279 app.config.update(self.config)
282 app.config.update(self.config)
280 app.log = self.log
283 app.log = self.log
281 app.overwrite = self.overwrite
284 app.overwrite = self.overwrite
282 app.copy_config_files=True
285 app.copy_config_files=True
283 app.profile = self.profile
286 app.profile = self.profile
284 app.init_profile_dir()
287 app.init_profile_dir()
285 app.init_config_files()
288 app.init_config_files()
286
289
287 def stage_default_config_file(self):
290 def stage_default_config_file(self):
288 pass
291 pass
289
292
290
293
291 class ProfileApp(Application):
294 class ProfileApp(Application):
292 name = u'ipython-profile'
295 name = u'ipython-profile'
293 description = profile_help
296 description = profile_help
294 examples = _main_examples
297 examples = _main_examples
295
298
296 subcommands = Dict(dict(
299 subcommands = Dict(dict(
297 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
300 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
298 list = (ProfileList, ProfileList.description.splitlines()[0]),
301 list = (ProfileList, ProfileList.description.splitlines()[0]),
299 ))
302 ))
300
303
301 def start(self):
304 def start(self):
302 if self.subapp is None:
305 if self.subapp is None:
303 print "No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())
306 print "No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())
304 print
307 print
305 self.print_description()
308 self.print_description()
306 self.print_subcommands()
309 self.print_subcommands()
307 self.exit(1)
310 self.exit(1)
308 else:
311 else:
309 return self.subapp.start()
312 return self.subapp.start()
310
313
General Comments 0
You need to be logged in to leave comments. Login now