##// END OF EJS Templates
add locate subcommands for IPython
MinRK -
Show More
@@ -1,293 +1,308 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-2011 The IPython Development Team
14 # Copyright (C) 2008-2011 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 logging
24 import logging
25 import os
25 import os
26
26
27 from IPython.config.application import Application, boolean_flag
27 from IPython.config.application import Application, boolean_flag
28 from IPython.core.application import (
28 from IPython.core.application import (
29 BaseIPythonApplication, base_flags, base_aliases
29 BaseIPythonApplication, base_flags, base_aliases
30 )
30 )
31 from IPython.core.profiledir import ProfileDir
31 from IPython.core.profiledir import ProfileDir
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
89 ipython profile locate foo # print the path to the directory for profile 'foo'
88 """
90 """
89
91
90 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
91 # Profile Application Class (for `ipython profile` subcommand)
93 # Profile Application Class (for `ipython profile` subcommand)
92 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
93
95
94
96
95 def list_profiles_in(path):
97 def list_profiles_in(path):
96 """list profiles in a given root directory"""
98 """list profiles in a given root directory"""
97 files = os.listdir(path)
99 files = os.listdir(path)
98 profiles = []
100 profiles = []
99 for f in files:
101 for f in files:
100 full_path = os.path.join(path, f)
102 full_path = os.path.join(path, f)
101 if os.path.isdir(full_path) and f.startswith('profile_'):
103 if os.path.isdir(full_path) and f.startswith('profile_'):
102 profiles.append(f.split('_',1)[-1])
104 profiles.append(f.split('_',1)[-1])
103 return profiles
105 return profiles
104
106
105
107
106 def list_bundled_profiles():
108 def list_bundled_profiles():
107 """list profiles that are bundled with IPython."""
109 """list profiles that are bundled with IPython."""
108 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
110 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
109 files = os.listdir(path)
111 files = os.listdir(path)
110 profiles = []
112 profiles = []
111 for profile in files:
113 for profile in files:
112 full_path = os.path.join(path, profile)
114 full_path = os.path.join(path, profile)
113 if os.path.isdir(full_path) and profile != "__pycache__":
115 if os.path.isdir(full_path) and profile != "__pycache__":
114 profiles.append(profile)
116 profiles.append(profile)
115 return profiles
117 return profiles
116
118
117
119
120 class ProfileLocate(BaseIPythonApplication):
121 description = """print the path an IPython profile dir"""
122
123 def parse_command_line(self, argv=None):
124 super(ProfileLocate, self).parse_command_line(argv)
125 if self.extra_args:
126 self.profile = self.extra_args[0]
127
128 def start(self):
129 print self.profile_dir.location
130
131
118 class ProfileList(Application):
132 class ProfileList(Application):
119 name = u'ipython-profile'
133 name = u'ipython-profile'
120 description = list_help
134 description = list_help
121 examples = _list_examples
135 examples = _list_examples
122
136
123 aliases = Dict({
137 aliases = Dict({
124 'ipython-dir' : 'ProfileList.ipython_dir',
138 'ipython-dir' : 'ProfileList.ipython_dir',
125 'log-level' : 'Application.log_level',
139 'log-level' : 'Application.log_level',
126 })
140 })
127 flags = Dict(dict(
141 flags = Dict(dict(
128 debug = ({'Application' : {'log_level' : 0}},
142 debug = ({'Application' : {'log_level' : 0}},
129 "Set Application.log_level to 0, maximizing log output."
143 "Set Application.log_level to 0, maximizing log output."
130 )
144 )
131 ))
145 ))
132
146
133 ipython_dir = Unicode(get_ipython_dir(), config=True,
147 ipython_dir = Unicode(get_ipython_dir(), config=True,
134 help="""
148 help="""
135 The name of the IPython directory. This directory is used for logging
149 The name of the IPython directory. This directory is used for logging
136 configuration (through profiles), history storage, etc. The default
150 configuration (through profiles), history storage, etc. The default
137 is usually $HOME/.ipython. This options can also be specified through
151 is usually $HOME/.ipython. This options can also be specified through
138 the environment variable IPYTHONDIR.
152 the environment variable IPYTHONDIR.
139 """
153 """
140 )
154 )
141
155
142
156
143 def _print_profiles(self, profiles):
157 def _print_profiles(self, profiles):
144 """print list of profiles, indented."""
158 """print list of profiles, indented."""
145 for profile in profiles:
159 for profile in profiles:
146 print ' %s' % profile
160 print ' %s' % profile
147
161
148 def list_profile_dirs(self):
162 def list_profile_dirs(self):
149 profiles = list_bundled_profiles()
163 profiles = list_bundled_profiles()
150 if profiles:
164 if profiles:
151 print
165 print
152 print "Available profiles in IPython:"
166 print "Available profiles in IPython:"
153 self._print_profiles(profiles)
167 self._print_profiles(profiles)
154 print
168 print
155 print " The first request for a bundled profile will copy it"
169 print " The first request for a bundled profile will copy it"
156 print " into your IPython directory (%s)," % self.ipython_dir
170 print " into your IPython directory (%s)," % self.ipython_dir
157 print " where you can customize it."
171 print " where you can customize it."
158
172
159 profiles = list_profiles_in(self.ipython_dir)
173 profiles = list_profiles_in(self.ipython_dir)
160 if profiles:
174 if profiles:
161 print
175 print
162 print "Available profiles in %s:" % self.ipython_dir
176 print "Available profiles in %s:" % self.ipython_dir
163 self._print_profiles(profiles)
177 self._print_profiles(profiles)
164
178
165 profiles = list_profiles_in(os.getcwdu())
179 profiles = list_profiles_in(os.getcwdu())
166 if profiles:
180 if profiles:
167 print
181 print
168 print "Available profiles in current directory (%s):" % os.getcwdu()
182 print "Available profiles in current directory (%s):" % os.getcwdu()
169 self._print_profiles(profiles)
183 self._print_profiles(profiles)
170
184
171 print
185 print
172 print "To use any of the above profiles, start IPython with:"
186 print "To use any of the above profiles, start IPython with:"
173 print " ipython --profile=<name>"
187 print " ipython --profile=<name>"
174 print
188 print
175
189
176 def start(self):
190 def start(self):
177 self.list_profile_dirs()
191 self.list_profile_dirs()
178
192
179
193
180 create_flags = {}
194 create_flags = {}
181 create_flags.update(base_flags)
195 create_flags.update(base_flags)
182 # don't include '--init' flag, which implies running profile create in other apps
196 # don't include '--init' flag, which implies running profile create in other apps
183 create_flags.pop('init')
197 create_flags.pop('init')
184 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
198 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
185 "reset config files in this profile to the defaults.")
199 "reset config files in this profile to the defaults.")
186 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
200 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
187 "Include the config files for parallel "
201 "Include the config files for parallel "
188 "computing apps (ipengine, ipcontroller, etc.)")
202 "computing apps (ipengine, ipcontroller, etc.)")
189
203
190
204
191 class ProfileCreate(BaseIPythonApplication):
205 class ProfileCreate(BaseIPythonApplication):
192 name = u'ipython-profile'
206 name = u'ipython-profile'
193 description = create_help
207 description = create_help
194 examples = _create_examples
208 examples = _create_examples
195 auto_create = Bool(True, config=False)
209 auto_create = Bool(True, config=False)
196
210
197 def _copy_config_files_default(self):
211 def _copy_config_files_default(self):
198 return True
212 return True
199
213
200 parallel = Bool(False, config=True,
214 parallel = Bool(False, config=True,
201 help="whether to include parallel computing config files")
215 help="whether to include parallel computing config files")
202 def _parallel_changed(self, name, old, new):
216 def _parallel_changed(self, name, old, new):
203 parallel_files = [ 'ipcontroller_config.py',
217 parallel_files = [ 'ipcontroller_config.py',
204 'ipengine_config.py',
218 'ipengine_config.py',
205 'ipcluster_config.py'
219 'ipcluster_config.py'
206 ]
220 ]
207 if new:
221 if new:
208 for cf in parallel_files:
222 for cf in parallel_files:
209 self.config_files.append(cf)
223 self.config_files.append(cf)
210 else:
224 else:
211 for cf in parallel_files:
225 for cf in parallel_files:
212 if cf in self.config_files:
226 if cf in self.config_files:
213 self.config_files.remove(cf)
227 self.config_files.remove(cf)
214
228
215 def parse_command_line(self, argv):
229 def parse_command_line(self, argv):
216 super(ProfileCreate, self).parse_command_line(argv)
230 super(ProfileCreate, self).parse_command_line(argv)
217 # accept positional arg as profile name
231 # accept positional arg as profile name
218 if self.extra_args:
232 if self.extra_args:
219 self.profile = self.extra_args[0]
233 self.profile = self.extra_args[0]
220
234
221 flags = Dict(create_flags)
235 flags = Dict(create_flags)
222
236
223 classes = [ProfileDir]
237 classes = [ProfileDir]
224
238
225 def init_config_files(self):
239 def init_config_files(self):
226 super(ProfileCreate, self).init_config_files()
240 super(ProfileCreate, self).init_config_files()
227 # use local imports, since these classes may import from here
241 # use local imports, since these classes may import from here
228 from IPython.frontend.terminal.ipapp import TerminalIPythonApp
242 from IPython.frontend.terminal.ipapp import TerminalIPythonApp
229 apps = [TerminalIPythonApp]
243 apps = [TerminalIPythonApp]
230 try:
244 try:
231 from IPython.frontend.qt.console.qtconsoleapp import IPythonQtConsoleApp
245 from IPython.frontend.qt.console.qtconsoleapp import IPythonQtConsoleApp
232 except Exception:
246 except Exception:
233 # this should be ImportError, but under weird circumstances
247 # this should be ImportError, but under weird circumstances
234 # this might be an AttributeError, or possibly others
248 # this might be an AttributeError, or possibly others
235 # in any case, nothing should cause the profile creation to crash.
249 # in any case, nothing should cause the profile creation to crash.
236 pass
250 pass
237 else:
251 else:
238 apps.append(IPythonQtConsoleApp)
252 apps.append(IPythonQtConsoleApp)
239 try:
253 try:
240 from IPython.frontend.html.notebook.notebookapp import NotebookApp
254 from IPython.frontend.html.notebook.notebookapp import NotebookApp
241 except ImportError:
255 except ImportError:
242 pass
256 pass
243 except Exception:
257 except Exception:
244 self.log.debug('Unexpected error when importing NotebookApp',
258 self.log.debug('Unexpected error when importing NotebookApp',
245 exc_info=True
259 exc_info=True
246 )
260 )
247 else:
261 else:
248 apps.append(NotebookApp)
262 apps.append(NotebookApp)
249 if self.parallel:
263 if self.parallel:
250 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
264 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
251 from IPython.parallel.apps.ipengineapp import IPEngineApp
265 from IPython.parallel.apps.ipengineapp import IPEngineApp
252 from IPython.parallel.apps.ipclusterapp import IPClusterStart
266 from IPython.parallel.apps.ipclusterapp import IPClusterStart
253 from IPython.parallel.apps.iploggerapp import IPLoggerApp
267 from IPython.parallel.apps.iploggerapp import IPLoggerApp
254 apps.extend([
268 apps.extend([
255 IPControllerApp,
269 IPControllerApp,
256 IPEngineApp,
270 IPEngineApp,
257 IPClusterStart,
271 IPClusterStart,
258 IPLoggerApp,
272 IPLoggerApp,
259 ])
273 ])
260 for App in apps:
274 for App in apps:
261 app = App()
275 app = App()
262 app.config.update(self.config)
276 app.config.update(self.config)
263 app.log = self.log
277 app.log = self.log
264 app.overwrite = self.overwrite
278 app.overwrite = self.overwrite
265 app.copy_config_files=True
279 app.copy_config_files=True
266 app.profile = self.profile
280 app.profile = self.profile
267 app.init_profile_dir()
281 app.init_profile_dir()
268 app.init_config_files()
282 app.init_config_files()
269
283
270 def stage_default_config_file(self):
284 def stage_default_config_file(self):
271 pass
285 pass
272
286
273
287
274 class ProfileApp(Application):
288 class ProfileApp(Application):
275 name = u'ipython-profile'
289 name = u'ipython-profile'
276 description = profile_help
290 description = profile_help
277 examples = _main_examples
291 examples = _main_examples
278
292
279 subcommands = Dict(dict(
293 subcommands = Dict(dict(
280 create = (ProfileCreate, "Create a new profile dir with default config files"),
294 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
281 list = (ProfileList, "List existing profiles")
295 list = (ProfileList, ProfileList.description.splitlines()[0]),
296 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
282 ))
297 ))
283
298
284 def start(self):
299 def start(self):
285 if self.subapp is None:
300 if self.subapp is None:
286 print "No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())
301 print "No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())
287 print
302 print
288 self.print_description()
303 self.print_description()
289 self.print_subcommands()
304 self.print_subcommands()
290 self.exit(1)
305 self.exit(1)
291 else:
306 else:
292 return self.subapp.start()
307 return self.subapp.start()
293
308
@@ -1,412 +1,433 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6
6
7 Authors
7 Authors
8 -------
8 -------
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Min Ragan-Kelley
12 * Min Ragan-Kelley
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2011 The IPython Development Team
16 # Copyright (C) 2008-2011 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 from __future__ import absolute_import
26 from __future__ import absolute_import
27
27
28 import logging
28 import logging
29 import os
29 import os
30 import sys
30 import sys
31
31
32 from IPython.config.loader import (
32 from IPython.config.loader import (
33 Config, PyFileConfigLoader, ConfigFileNotFound
33 Config, PyFileConfigLoader, ConfigFileNotFound
34 )
34 )
35 from IPython.config.application import boolean_flag, catch_config_error
35 from IPython.config.application import boolean_flag, catch_config_error
36 from IPython.core import release
36 from IPython.core import release
37 from IPython.core import usage
37 from IPython.core import usage
38 from IPython.core.completer import IPCompleter
38 from IPython.core.completer import IPCompleter
39 from IPython.core.crashhandler import CrashHandler
39 from IPython.core.crashhandler import CrashHandler
40 from IPython.core.formatters import PlainTextFormatter
40 from IPython.core.formatters import PlainTextFormatter
41 from IPython.core.history import HistoryManager
41 from IPython.core.history import HistoryManager
42 from IPython.core.prompts import PromptManager
42 from IPython.core.prompts import PromptManager
43 from IPython.core.application import (
43 from IPython.core.application import (
44 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
44 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
45 )
45 )
46 from IPython.core.shellapp import (
46 from IPython.core.shellapp import (
47 InteractiveShellApp, shell_flags, shell_aliases
47 InteractiveShellApp, shell_flags, shell_aliases
48 )
48 )
49 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
49 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
50 from IPython.lib import inputhook
50 from IPython.lib import inputhook
51 from IPython.utils import warn
51 from IPython.utils import warn
52 from IPython.utils.path import get_ipython_dir, check_for_old_config
52 from IPython.utils.path import get_ipython_dir, check_for_old_config
53 from IPython.utils.traitlets import (
53 from IPython.utils.traitlets import (
54 Bool, List, Dict, CaselessStrEnum
54 Bool, List, Dict, CaselessStrEnum
55 )
55 )
56
56
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 # Globals, utilities and helpers
58 # Globals, utilities and helpers
59 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
60
60
61 #: The default config file name for this application.
61 #: The default config file name for this application.
62 default_config_file_name = u'ipython_config.py'
62 default_config_file_name = u'ipython_config.py'
63
63
64 _examples = """
64 _examples = """
65 ipython --pylab # start in pylab mode
65 ipython --pylab # start in pylab mode
66 ipython --pylab=qt # start in pylab mode with the qt4 backend
66 ipython --pylab=qt # start in pylab mode with the qt4 backend
67 ipython --log-level=DEBUG # set logging to DEBUG
67 ipython --log-level=DEBUG # set logging to DEBUG
68 ipython --profile=foo # start with profile foo
68 ipython --profile=foo # start with profile foo
69
69
70 ipython qtconsole # start the qtconsole GUI application
70 ipython qtconsole # start the qtconsole GUI application
71 ipython help qtconsole # show the help for the qtconsole subcmd
71 ipython help qtconsole # show the help for the qtconsole subcmd
72
72
73 ipython console # start the terminal-based console application
73 ipython console # start the terminal-based console application
74 ipython help console # show the help for the console subcmd
74 ipython help console # show the help for the console subcmd
75
75
76 ipython notebook # start the IPython notebook
76 ipython notebook # start the IPython notebook
77 ipython help notebook # show the help for the notebook subcmd
77 ipython help notebook # show the help for the notebook subcmd
78
78
79 ipython profile create foo # create profile foo w/ default config files
79 ipython profile create foo # create profile foo w/ default config files
80 ipython help profile # show the help for the profile subcmd
80 ipython help profile # show the help for the profile subcmd
81
82 ipython locate # print the path to the IPython directory
83 ipython locate profile foo # print the path to the directory for profile `foo`
81 """
84 """
82
85
83 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
84 # Crash handler for this application
87 # Crash handler for this application
85 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
86
89
87 class IPAppCrashHandler(CrashHandler):
90 class IPAppCrashHandler(CrashHandler):
88 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
91 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
89
92
90 def __init__(self, app):
93 def __init__(self, app):
91 contact_name = release.authors['Fernando'][0]
94 contact_name = release.authors['Fernando'][0]
92 contact_email = release.author_email
95 contact_email = release.author_email
93 bug_tracker = 'https://github.com/ipython/ipython/issues'
96 bug_tracker = 'https://github.com/ipython/ipython/issues'
94 super(IPAppCrashHandler,self).__init__(
97 super(IPAppCrashHandler,self).__init__(
95 app, contact_name, contact_email, bug_tracker
98 app, contact_name, contact_email, bug_tracker
96 )
99 )
97
100
98 def make_report(self,traceback):
101 def make_report(self,traceback):
99 """Return a string containing a crash report."""
102 """Return a string containing a crash report."""
100
103
101 sec_sep = self.section_sep
104 sec_sep = self.section_sep
102 # Start with parent report
105 # Start with parent report
103 report = [super(IPAppCrashHandler, self).make_report(traceback)]
106 report = [super(IPAppCrashHandler, self).make_report(traceback)]
104 # Add interactive-specific info we may have
107 # Add interactive-specific info we may have
105 rpt_add = report.append
108 rpt_add = report.append
106 try:
109 try:
107 rpt_add(sec_sep+"History of session input:")
110 rpt_add(sec_sep+"History of session input:")
108 for line in self.app.shell.user_ns['_ih']:
111 for line in self.app.shell.user_ns['_ih']:
109 rpt_add(line)
112 rpt_add(line)
110 rpt_add('\n*** Last line of input (may not be in above history):\n')
113 rpt_add('\n*** Last line of input (may not be in above history):\n')
111 rpt_add(self.app.shell._last_input_line+'\n')
114 rpt_add(self.app.shell._last_input_line+'\n')
112 except:
115 except:
113 pass
116 pass
114
117
115 return ''.join(report)
118 return ''.join(report)
116
119
117 #-----------------------------------------------------------------------------
120 #-----------------------------------------------------------------------------
118 # Aliases and Flags
121 # Aliases and Flags
119 #-----------------------------------------------------------------------------
122 #-----------------------------------------------------------------------------
120 flags = dict(base_flags)
123 flags = dict(base_flags)
121 flags.update(shell_flags)
124 flags.update(shell_flags)
122 frontend_flags = {}
125 frontend_flags = {}
123 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
126 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
124 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
127 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
125 'Turn on auto editing of files with syntax errors.',
128 'Turn on auto editing of files with syntax errors.',
126 'Turn off auto editing of files with syntax errors.'
129 'Turn off auto editing of files with syntax errors.'
127 )
130 )
128 addflag('banner', 'TerminalIPythonApp.display_banner',
131 addflag('banner', 'TerminalIPythonApp.display_banner',
129 "Display a banner upon starting IPython.",
132 "Display a banner upon starting IPython.",
130 "Don't display a banner upon starting IPython."
133 "Don't display a banner upon starting IPython."
131 )
134 )
132 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
135 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
133 """Set to confirm when you try to exit IPython with an EOF (Control-D
136 """Set to confirm when you try to exit IPython with an EOF (Control-D
134 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
137 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
135 you can force a direct exit without any confirmation.""",
138 you can force a direct exit without any confirmation.""",
136 "Don't prompt the user when exiting."
139 "Don't prompt the user when exiting."
137 )
140 )
138 addflag('term-title', 'TerminalInteractiveShell.term_title',
141 addflag('term-title', 'TerminalInteractiveShell.term_title',
139 "Enable auto setting the terminal title.",
142 "Enable auto setting the terminal title.",
140 "Disable auto setting the terminal title."
143 "Disable auto setting the terminal title."
141 )
144 )
142 classic_config = Config()
145 classic_config = Config()
143 classic_config.InteractiveShell.cache_size = 0
146 classic_config.InteractiveShell.cache_size = 0
144 classic_config.PlainTextFormatter.pprint = False
147 classic_config.PlainTextFormatter.pprint = False
145 classic_config.PromptManager.in_template = '>>> '
148 classic_config.PromptManager.in_template = '>>> '
146 classic_config.PromptManager.in2_template = '... '
149 classic_config.PromptManager.in2_template = '... '
147 classic_config.PromptManager.out_template = ''
150 classic_config.PromptManager.out_template = ''
148 classic_config.InteractiveShell.separate_in = ''
151 classic_config.InteractiveShell.separate_in = ''
149 classic_config.InteractiveShell.separate_out = ''
152 classic_config.InteractiveShell.separate_out = ''
150 classic_config.InteractiveShell.separate_out2 = ''
153 classic_config.InteractiveShell.separate_out2 = ''
151 classic_config.InteractiveShell.colors = 'NoColor'
154 classic_config.InteractiveShell.colors = 'NoColor'
152 classic_config.InteractiveShell.xmode = 'Plain'
155 classic_config.InteractiveShell.xmode = 'Plain'
153
156
154 frontend_flags['classic']=(
157 frontend_flags['classic']=(
155 classic_config,
158 classic_config,
156 "Gives IPython a similar feel to the classic Python prompt."
159 "Gives IPython a similar feel to the classic Python prompt."
157 )
160 )
158 # # log doesn't make so much sense this way anymore
161 # # log doesn't make so much sense this way anymore
159 # paa('--log','-l',
162 # paa('--log','-l',
160 # action='store_true', dest='InteractiveShell.logstart',
163 # action='store_true', dest='InteractiveShell.logstart',
161 # help="Start logging to the default log file (./ipython_log.py).")
164 # help="Start logging to the default log file (./ipython_log.py).")
162 #
165 #
163 # # quick is harder to implement
166 # # quick is harder to implement
164 frontend_flags['quick']=(
167 frontend_flags['quick']=(
165 {'TerminalIPythonApp' : {'quick' : True}},
168 {'TerminalIPythonApp' : {'quick' : True}},
166 "Enable quick startup with no config files."
169 "Enable quick startup with no config files."
167 )
170 )
168
171
169 frontend_flags['i'] = (
172 frontend_flags['i'] = (
170 {'TerminalIPythonApp' : {'force_interact' : True}},
173 {'TerminalIPythonApp' : {'force_interact' : True}},
171 """If running code from the command line, become interactive afterwards.
174 """If running code from the command line, become interactive afterwards.
172 Note: can also be given simply as '-i.'"""
175 Note: can also be given simply as '-i.'"""
173 )
176 )
174 frontend_flags['pylab'] = (
177 frontend_flags['pylab'] = (
175 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
178 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
176 """Pre-load matplotlib and numpy for interactive use with
179 """Pre-load matplotlib and numpy for interactive use with
177 the default matplotlib backend."""
180 the default matplotlib backend."""
178 )
181 )
179 flags.update(frontend_flags)
182 flags.update(frontend_flags)
180
183
181 aliases = dict(base_aliases)
184 aliases = dict(base_aliases)
182 aliases.update(shell_aliases)
185 aliases.update(shell_aliases)
183
186
184 # it's possible we don't want short aliases for *all* of these:
187 # it's possible we don't want short aliases for *all* of these:
185 aliases.update(dict(
188 aliases.update(dict(
186 gui='TerminalIPythonApp.gui',
189 gui='TerminalIPythonApp.gui',
187 pylab='TerminalIPythonApp.pylab',
190 pylab='TerminalIPythonApp.pylab',
188 ))
191 ))
189
192
190 #-----------------------------------------------------------------------------
193 #-----------------------------------------------------------------------------
191 # Main classes and functions
194 # Main classes and functions
192 #-----------------------------------------------------------------------------
195 #-----------------------------------------------------------------------------
193
196
197
198 class LocateIPythonApp(BaseIPythonApplication):
199 description = """print the path to the IPython dir"""
200 subcommands = Dict(dict(
201 profile=('IPython.core.profileapp.ProfileLocate',
202 "print the path to an IPython profile directory",
203 ),
204 ))
205 def start(self):
206 if self.subapp is not None:
207 return self.subapp.start()
208 else:
209 print self.ipython_dir
210
211
194 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
212 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
195 name = u'ipython'
213 name = u'ipython'
196 description = usage.cl_usage
214 description = usage.cl_usage
197 default_config_file_name = default_config_file_name
215 default_config_file_name = default_config_file_name
198 crash_handler_class = IPAppCrashHandler
216 crash_handler_class = IPAppCrashHandler
199 examples = _examples
217 examples = _examples
200
218
201 flags = Dict(flags)
219 flags = Dict(flags)
202 aliases = Dict(aliases)
220 aliases = Dict(aliases)
203 classes = List()
221 classes = List()
204 def _classes_default(self):
222 def _classes_default(self):
205 """This has to be in a method, for TerminalIPythonApp to be available."""
223 """This has to be in a method, for TerminalIPythonApp to be available."""
206 return [
224 return [
207 InteractiveShellApp, # ShellApp comes before TerminalApp, because
225 InteractiveShellApp, # ShellApp comes before TerminalApp, because
208 self.__class__, # it will also affect subclasses (e.g. QtConsole)
226 self.__class__, # it will also affect subclasses (e.g. QtConsole)
209 TerminalInteractiveShell,
227 TerminalInteractiveShell,
210 PromptManager,
228 PromptManager,
211 HistoryManager,
229 HistoryManager,
212 ProfileDir,
230 ProfileDir,
213 PlainTextFormatter,
231 PlainTextFormatter,
214 IPCompleter,
232 IPCompleter,
215 ]
233 ]
216
234
217 subcommands = Dict(dict(
235 subcommands = Dict(dict(
218 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
236 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
219 """Launch the IPython Qt Console."""
237 """Launch the IPython Qt Console."""
220 ),
238 ),
221 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
239 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
222 """Launch the IPython HTML Notebook Server."""
240 """Launch the IPython HTML Notebook Server."""
223 ),
241 ),
224 profile = ("IPython.core.profileapp.ProfileApp",
242 profile = ("IPython.core.profileapp.ProfileApp",
225 "Create and manage IPython profiles."
243 "Create and manage IPython profiles."
226 ),
244 ),
227 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
245 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
228 "Start a kernel without an attached frontend."
246 "Start a kernel without an attached frontend."
229 ),
247 ),
230 console=('IPython.frontend.terminal.console.app.ZMQTerminalIPythonApp',
248 console=('IPython.frontend.terminal.console.app.ZMQTerminalIPythonApp',
231 """Launch the IPython terminal-based Console."""
249 """Launch the IPython terminal-based Console."""
232 ),
250 ),
251 locate=('IPython.frontend.terminal.ipapp.LocateIPythonApp',
252 LocateIPythonApp.description
253 ),
233 ))
254 ))
234
255
235 # *do* autocreate requested profile, but don't create the config file.
256 # *do* autocreate requested profile, but don't create the config file.
236 auto_create=Bool(True)
257 auto_create=Bool(True)
237 # configurables
258 # configurables
238 ignore_old_config=Bool(False, config=True,
259 ignore_old_config=Bool(False, config=True,
239 help="Suppress warning messages about legacy config files"
260 help="Suppress warning messages about legacy config files"
240 )
261 )
241 quick = Bool(False, config=True,
262 quick = Bool(False, config=True,
242 help="""Start IPython quickly by skipping the loading of config files."""
263 help="""Start IPython quickly by skipping the loading of config files."""
243 )
264 )
244 def _quick_changed(self, name, old, new):
265 def _quick_changed(self, name, old, new):
245 if new:
266 if new:
246 self.load_config_file = lambda *a, **kw: None
267 self.load_config_file = lambda *a, **kw: None
247 self.ignore_old_config=True
268 self.ignore_old_config=True
248
269
249 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
270 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
250 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
271 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
251 )
272 )
252 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
273 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
253 config=True,
274 config=True,
254 help="""Pre-load matplotlib and numpy for interactive use,
275 help="""Pre-load matplotlib and numpy for interactive use,
255 selecting a particular matplotlib backend and loop integration.
276 selecting a particular matplotlib backend and loop integration.
256 """
277 """
257 )
278 )
258 display_banner = Bool(True, config=True,
279 display_banner = Bool(True, config=True,
259 help="Whether to display a banner upon starting IPython."
280 help="Whether to display a banner upon starting IPython."
260 )
281 )
261
282
262 # if there is code of files to run from the cmd line, don't interact
283 # if there is code of files to run from the cmd line, don't interact
263 # unless the --i flag (App.force_interact) is true.
284 # unless the --i flag (App.force_interact) is true.
264 force_interact = Bool(False, config=True,
285 force_interact = Bool(False, config=True,
265 help="""If a command or file is given via the command-line,
286 help="""If a command or file is given via the command-line,
266 e.g. 'ipython foo.py"""
287 e.g. 'ipython foo.py"""
267 )
288 )
268 def _force_interact_changed(self, name, old, new):
289 def _force_interact_changed(self, name, old, new):
269 if new:
290 if new:
270 self.interact = True
291 self.interact = True
271
292
272 def _file_to_run_changed(self, name, old, new):
293 def _file_to_run_changed(self, name, old, new):
273 if new:
294 if new:
274 self.something_to_run = True
295 self.something_to_run = True
275 if new and not self.force_interact:
296 if new and not self.force_interact:
276 self.interact = False
297 self.interact = False
277 _code_to_run_changed = _file_to_run_changed
298 _code_to_run_changed = _file_to_run_changed
278 _module_to_run_changed = _file_to_run_changed
299 _module_to_run_changed = _file_to_run_changed
279
300
280 # internal, not-configurable
301 # internal, not-configurable
281 interact=Bool(True)
302 interact=Bool(True)
282 something_to_run=Bool(False)
303 something_to_run=Bool(False)
283
304
284 def parse_command_line(self, argv=None):
305 def parse_command_line(self, argv=None):
285 """override to allow old '-pylab' flag with deprecation warning"""
306 """override to allow old '-pylab' flag with deprecation warning"""
286
307
287 argv = sys.argv[1:] if argv is None else argv
308 argv = sys.argv[1:] if argv is None else argv
288
309
289 if '-pylab' in argv:
310 if '-pylab' in argv:
290 # deprecated `-pylab` given,
311 # deprecated `-pylab` given,
291 # warn and transform into current syntax
312 # warn and transform into current syntax
292 argv = argv[:] # copy, don't clobber
313 argv = argv[:] # copy, don't clobber
293 idx = argv.index('-pylab')
314 idx = argv.index('-pylab')
294 warn.warn("`-pylab` flag has been deprecated.\n"
315 warn.warn("`-pylab` flag has been deprecated.\n"
295 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
316 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
296 sub = '--pylab'
317 sub = '--pylab'
297 if len(argv) > idx+1:
318 if len(argv) > idx+1:
298 # check for gui arg, as in '-pylab qt'
319 # check for gui arg, as in '-pylab qt'
299 gui = argv[idx+1]
320 gui = argv[idx+1]
300 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
321 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
301 sub = '--pylab='+gui
322 sub = '--pylab='+gui
302 argv.pop(idx+1)
323 argv.pop(idx+1)
303 argv[idx] = sub
324 argv[idx] = sub
304
325
305 return super(TerminalIPythonApp, self).parse_command_line(argv)
326 return super(TerminalIPythonApp, self).parse_command_line(argv)
306
327
307 @catch_config_error
328 @catch_config_error
308 def initialize(self, argv=None):
329 def initialize(self, argv=None):
309 """Do actions after construct, but before starting the app."""
330 """Do actions after construct, but before starting the app."""
310 super(TerminalIPythonApp, self).initialize(argv)
331 super(TerminalIPythonApp, self).initialize(argv)
311 if self.subapp is not None:
332 if self.subapp is not None:
312 # don't bother initializing further, starting subapp
333 # don't bother initializing further, starting subapp
313 return
334 return
314 if not self.ignore_old_config:
335 if not self.ignore_old_config:
315 check_for_old_config(self.ipython_dir)
336 check_for_old_config(self.ipython_dir)
316 # print self.extra_args
337 # print self.extra_args
317 if self.extra_args and not self.something_to_run:
338 if self.extra_args and not self.something_to_run:
318 self.file_to_run = self.extra_args[0]
339 self.file_to_run = self.extra_args[0]
319 self.init_path()
340 self.init_path()
320 # create the shell
341 # create the shell
321 self.init_shell()
342 self.init_shell()
322 # and draw the banner
343 # and draw the banner
323 self.init_banner()
344 self.init_banner()
324 # Now a variety of things that happen after the banner is printed.
345 # Now a variety of things that happen after the banner is printed.
325 self.init_gui_pylab()
346 self.init_gui_pylab()
326 self.init_extensions()
347 self.init_extensions()
327 self.init_code()
348 self.init_code()
328
349
329 def init_shell(self):
350 def init_shell(self):
330 """initialize the InteractiveShell instance"""
351 """initialize the InteractiveShell instance"""
331 # Create an InteractiveShell instance.
352 # Create an InteractiveShell instance.
332 # shell.display_banner should always be False for the terminal
353 # shell.display_banner should always be False for the terminal
333 # based app, because we call shell.show_banner() by hand below
354 # based app, because we call shell.show_banner() by hand below
334 # so the banner shows *before* all extension loading stuff.
355 # so the banner shows *before* all extension loading stuff.
335 self.shell = TerminalInteractiveShell.instance(config=self.config,
356 self.shell = TerminalInteractiveShell.instance(config=self.config,
336 display_banner=False, profile_dir=self.profile_dir,
357 display_banner=False, profile_dir=self.profile_dir,
337 ipython_dir=self.ipython_dir)
358 ipython_dir=self.ipython_dir)
338 self.shell.configurables.append(self)
359 self.shell.configurables.append(self)
339
360
340 def init_banner(self):
361 def init_banner(self):
341 """optionally display the banner"""
362 """optionally display the banner"""
342 if self.display_banner and self.interact:
363 if self.display_banner and self.interact:
343 self.shell.show_banner()
364 self.shell.show_banner()
344 # Make sure there is a space below the banner.
365 # Make sure there is a space below the banner.
345 if self.log_level <= logging.INFO: print
366 if self.log_level <= logging.INFO: print
346
367
347
368
348 def init_gui_pylab(self):
369 def init_gui_pylab(self):
349 """Enable GUI event loop integration, taking pylab into account."""
370 """Enable GUI event loop integration, taking pylab into account."""
350 gui = self.gui
371 gui = self.gui
351
372
352 # Using `pylab` will also require gui activation, though which toolkit
373 # Using `pylab` will also require gui activation, though which toolkit
353 # to use may be chosen automatically based on mpl configuration.
374 # to use may be chosen automatically based on mpl configuration.
354 if self.pylab:
375 if self.pylab:
355 activate = self.shell.enable_pylab
376 activate = self.shell.enable_pylab
356 if self.pylab == 'auto':
377 if self.pylab == 'auto':
357 gui = None
378 gui = None
358 else:
379 else:
359 gui = self.pylab
380 gui = self.pylab
360 else:
381 else:
361 # Enable only GUI integration, no pylab
382 # Enable only GUI integration, no pylab
362 activate = inputhook.enable_gui
383 activate = inputhook.enable_gui
363
384
364 if gui or self.pylab:
385 if gui or self.pylab:
365 try:
386 try:
366 self.log.info("Enabling GUI event loop integration, "
387 self.log.info("Enabling GUI event loop integration, "
367 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
388 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
368 if self.pylab:
389 if self.pylab:
369 activate(gui, import_all=self.pylab_import_all)
390 activate(gui, import_all=self.pylab_import_all)
370 else:
391 else:
371 activate(gui)
392 activate(gui)
372 except:
393 except:
373 self.log.warn("Error in enabling GUI event loop integration:")
394 self.log.warn("Error in enabling GUI event loop integration:")
374 self.shell.showtraceback()
395 self.shell.showtraceback()
375
396
376 def start(self):
397 def start(self):
377 if self.subapp is not None:
398 if self.subapp is not None:
378 return self.subapp.start()
399 return self.subapp.start()
379 # perform any prexec steps:
400 # perform any prexec steps:
380 if self.interact:
401 if self.interact:
381 self.log.debug("Starting IPython's mainloop...")
402 self.log.debug("Starting IPython's mainloop...")
382 self.shell.mainloop()
403 self.shell.mainloop()
383 else:
404 else:
384 self.log.debug("IPython not interactive...")
405 self.log.debug("IPython not interactive...")
385
406
386
407
387 def load_default_config(ipython_dir=None):
408 def load_default_config(ipython_dir=None):
388 """Load the default config file from the default ipython_dir.
409 """Load the default config file from the default ipython_dir.
389
410
390 This is useful for embedded shells.
411 This is useful for embedded shells.
391 """
412 """
392 if ipython_dir is None:
413 if ipython_dir is None:
393 ipython_dir = get_ipython_dir()
414 ipython_dir = get_ipython_dir()
394 profile_dir = os.path.join(ipython_dir, 'profile_default')
415 profile_dir = os.path.join(ipython_dir, 'profile_default')
395 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
416 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
396 try:
417 try:
397 config = cl.load_config()
418 config = cl.load_config()
398 except ConfigFileNotFound:
419 except ConfigFileNotFound:
399 # no config found
420 # no config found
400 config = Config()
421 config = Config()
401 return config
422 return config
402
423
403
424
404 def launch_new_instance():
425 def launch_new_instance():
405 """Create and run a full blown IPython instance"""
426 """Create and run a full blown IPython instance"""
406 app = TerminalIPythonApp.instance()
427 app = TerminalIPythonApp.instance()
407 app.initialize()
428 app.initialize()
408 app.start()
429 app.start()
409
430
410
431
411 if __name__ == '__main__':
432 if __name__ == '__main__':
412 launch_new_instance()
433 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now