##// END OF EJS Templates
Same in profileapp.py , profiledir.py, shellapp.py
Pierre Gerold -
Show More
@@ -1,311 +1,311 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for managing IPython profiles.
4 4
5 5 To be invoked as the `ipython profile` subcommand.
6 6
7 7 Authors:
8 8
9 9 * Min RK
10 10
11 11 """
12 12 from __future__ import print_function
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Copyright (C) 2008 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-----------------------------------------------------------------------------
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Imports
23 23 #-----------------------------------------------------------------------------
24 24
25 25 import os
26 26
27 27 from traitlets.config.application import Application
28 28 from IPython.core.application import (
29 29 BaseIPythonApplication, base_flags
30 30 )
31 31 from IPython.core.profiledir import ProfileDir
32 32 from IPython.utils.importstring import import_item
33 33 from IPython.paths import get_ipython_dir, get_ipython_package_dir
34 34 from IPython.utils import py3compat
35 35 from traitlets import Unicode, Bool, Dict
36 36
37 37 #-----------------------------------------------------------------------------
38 38 # Constants
39 39 #-----------------------------------------------------------------------------
40 40
41 41 create_help = """Create an IPython profile by name
42 42
43 43 Create an ipython profile directory by its name or
44 44 profile directory path. Profile directories contain
45 45 configuration, log and security related files and are named
46 46 using the convention 'profile_<name>'. By default they are
47 47 located in your ipython directory. Once created, you will
48 48 can edit the configuration files in the profile
49 49 directory to configure IPython. Most users will create a
50 50 profile directory by name,
51 51 `ipython profile create myprofile`, which will put the directory
52 52 in `<ipython_dir>/profile_myprofile`.
53 53 """
54 54 list_help = """List available IPython profiles
55 55
56 56 List all available profiles, by profile location, that can
57 57 be found in the current working directly or in the ipython
58 58 directory. Profile directories are named using the convention
59 59 'profile_<profile>'.
60 60 """
61 61 profile_help = """Manage IPython profiles
62 62
63 63 Profile directories contain
64 64 configuration, log and security related files and are named
65 65 using the convention 'profile_<name>'. By default they are
66 66 located in your ipython directory. You can create profiles
67 67 with `ipython profile create <name>`, or see the profiles you
68 68 already have with `ipython profile list`
69 69
70 70 To get started configuring IPython, simply do:
71 71
72 72 $> ipython profile create
73 73
74 74 and IPython will create the default profile in <ipython_dir>/profile_default,
75 75 where you can edit ipython_config.py to start configuring IPython.
76 76
77 77 """
78 78
79 79 _list_examples = "ipython profile list # list all profiles"
80 80
81 81 _create_examples = """
82 82 ipython profile create foo # create profile foo w/ default config files
83 83 ipython profile create foo --reset # restage default config files over current
84 84 ipython profile create foo --parallel # also stage parallel config files
85 85 """
86 86
87 87 _main_examples = """
88 88 ipython profile create -h # show the help string for the create subcommand
89 89 ipython profile list -h # show the help string for the list subcommand
90 90
91 91 ipython locate profile foo # print the path to the directory for profile 'foo'
92 92 """
93 93
94 94 #-----------------------------------------------------------------------------
95 95 # Profile Application Class (for `ipython profile` subcommand)
96 96 #-----------------------------------------------------------------------------
97 97
98 98
99 99 def list_profiles_in(path):
100 100 """list profiles in a given root directory"""
101 101 files = os.listdir(path)
102 102 profiles = []
103 103 for f in files:
104 104 try:
105 105 full_path = os.path.join(path, f)
106 106 except UnicodeError:
107 107 continue
108 108 if os.path.isdir(full_path) and f.startswith('profile_'):
109 109 profiles.append(f.split('_',1)[-1])
110 110 return profiles
111 111
112 112
113 113 def list_bundled_profiles():
114 114 """list profiles that are bundled with IPython."""
115 115 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
116 116 files = os.listdir(path)
117 117 profiles = []
118 118 for profile in files:
119 119 full_path = os.path.join(path, profile)
120 120 if os.path.isdir(full_path) and profile != "__pycache__":
121 121 profiles.append(profile)
122 122 return profiles
123 123
124 124
125 125 class ProfileLocate(BaseIPythonApplication):
126 126 description = """print the path to an IPython profile dir"""
127 127
128 128 def parse_command_line(self, argv=None):
129 129 super(ProfileLocate, self).parse_command_line(argv)
130 130 if self.extra_args:
131 131 self.profile = self.extra_args[0]
132 132
133 133 def start(self):
134 134 print(self.profile_dir.location)
135 135
136 136
137 137 class ProfileList(Application):
138 138 name = u'ipython-profile'
139 139 description = list_help
140 140 examples = _list_examples
141 141
142 142 aliases = Dict({
143 143 'ipython-dir' : 'ProfileList.ipython_dir',
144 144 'log-level' : 'Application.log_level',
145 145 })
146 146 flags = Dict(dict(
147 147 debug = ({'Application' : {'log_level' : 0}},
148 148 "Set Application.log_level to 0, maximizing log output."
149 149 )
150 150 ))
151 151
152 152 ipython_dir = Unicode(get_ipython_dir(), config=True,
153 153 help="""
154 154 The name of the IPython directory. This directory is used for logging
155 155 configuration (through profiles), history storage, etc. The default
156 156 is usually $HOME/.ipython. This options can also be specified through
157 157 the environment variable IPYTHONDIR.
158 158 """
159 159 )
160 160
161 161
162 162 def _print_profiles(self, profiles):
163 163 """print list of profiles, indented."""
164 164 for profile in profiles:
165 165 print(' %s' % profile)
166 166
167 167 def list_profile_dirs(self):
168 168 profiles = list_bundled_profiles()
169 169 if profiles:
170 170 print()
171 171 print("Available profiles in IPython:")
172 172 self._print_profiles(profiles)
173 173 print()
174 174 print(" The first request for a bundled profile will copy it")
175 175 print(" into your IPython directory (%s)," % self.ipython_dir)
176 176 print(" where you can customize it.")
177 177
178 178 profiles = list_profiles_in(self.ipython_dir)
179 179 if profiles:
180 180 print()
181 181 print("Available profiles in %s:" % self.ipython_dir)
182 182 self._print_profiles(profiles)
183 183
184 184 profiles = list_profiles_in(py3compat.getcwd())
185 185 if profiles:
186 186 print()
187 187 print("Available profiles in current directory (%s):" % py3compat.getcwd())
188 188 self._print_profiles(profiles)
189 189
190 190 print()
191 191 print("To use any of the above profiles, start IPython with:")
192 192 print(" ipython --profile=<name>")
193 193 print()
194 194
195 195 def start(self):
196 196 self.list_profile_dirs()
197 197
198 198
199 199 create_flags = {}
200 200 create_flags.update(base_flags)
201 201 # don't include '--init' flag, which implies running profile create in other apps
202 202 create_flags.pop('init')
203 203 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
204 204 "reset config files in this profile to the defaults.")
205 205 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
206 206 "Include the config files for parallel "
207 207 "computing apps (ipengine, ipcontroller, etc.)")
208 208
209 209
210 210 class ProfileCreate(BaseIPythonApplication):
211 211 name = u'ipython-profile'
212 212 description = create_help
213 213 examples = _create_examples
214 214 auto_create = Bool(True, config=False)
215 215 def _log_format_default(self):
216 216 return "[%(name)s] %(message)s"
217 217
218 218 def _copy_config_files_default(self):
219 219 return True
220 220
221 221 parallel = Bool(False, config=True,
222 222 help="whether to include parallel computing config files")
223 223 def _parallel_changed(self, name, old, new):
224 224 parallel_files = [ 'ipcontroller_config.py',
225 225 'ipengine_config.py',
226 226 'ipcluster_config.py'
227 227 ]
228 228 if new:
229 229 for cf in parallel_files:
230 230 self.config_files.append(cf)
231 231 else:
232 232 for cf in parallel_files:
233 233 if cf in self.config_files:
234 234 self.config_files.remove(cf)
235 235
236 236 def parse_command_line(self, argv):
237 237 super(ProfileCreate, self).parse_command_line(argv)
238 238 # accept positional arg as profile name
239 239 if self.extra_args:
240 240 self.profile = self.extra_args[0]
241 241
242 242 flags = Dict(create_flags)
243 243
244 244 classes = [ProfileDir]
245 245
246 246 def _import_app(self, app_path):
247 247 """import an app class"""
248 248 app = None
249 249 name = app_path.rsplit('.', 1)[-1]
250 250 try:
251 251 app = import_item(app_path)
252 252 except ImportError:
253 253 self.log.info("Couldn't import %s, config file will be excluded", name)
254 254 except Exception:
255 self.log.warn('Unexpected error importing %s', name, exc_info=True)
255 self.log.warning('Unexpected error importing %s', name, exc_info=True)
256 256 return app
257 257
258 258 def init_config_files(self):
259 259 super(ProfileCreate, self).init_config_files()
260 260 # use local imports, since these classes may import from here
261 261 from IPython.terminal.ipapp import TerminalIPythonApp
262 262 apps = [TerminalIPythonApp]
263 263 for app_path in (
264 264 'ipykernel.kernelapp.IPKernelApp',
265 265 ):
266 266 app = self._import_app(app_path)
267 267 if app is not None:
268 268 apps.append(app)
269 269 if self.parallel:
270 270 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
271 271 from ipyparallel.apps.ipengineapp import IPEngineApp
272 272 from ipyparallel.apps.ipclusterapp import IPClusterStart
273 273 apps.extend([
274 274 IPControllerApp,
275 275 IPEngineApp,
276 276 IPClusterStart,
277 277 ])
278 278 for App in apps:
279 279 app = App()
280 280 app.config.update(self.config)
281 281 app.log = self.log
282 282 app.overwrite = self.overwrite
283 283 app.copy_config_files=True
284 284 app.ipython_dir=self.ipython_dir
285 285 app.profile_dir=self.profile_dir
286 286 app.init_config_files()
287 287
288 288 def stage_default_config_file(self):
289 289 pass
290 290
291 291
292 292 class ProfileApp(Application):
293 293 name = u'ipython profile'
294 294 description = profile_help
295 295 examples = _main_examples
296 296
297 297 subcommands = Dict(dict(
298 298 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
299 299 list = (ProfileList, ProfileList.description.splitlines()[0]),
300 300 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
301 301 ))
302 302
303 303 def start(self):
304 304 if self.subapp is None:
305 305 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
306 306 print()
307 307 self.print_description()
308 308 self.print_subcommands()
309 309 self.exit(1)
310 310 else:
311 311 return self.subapp.start()
@@ -1,234 +1,234 b''
1 1 # encoding: utf-8
2 2 """An object for managing IPython profile directories."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 import os
8 8 import shutil
9 9 import errno
10 10
11 11 from traitlets.config.configurable import LoggingConfigurable
12 12 from IPython.paths import get_ipython_package_dir
13 13 from IPython.utils.path import expand_path, ensure_dir_exists
14 14 from IPython.utils import py3compat
15 15 from traitlets import Unicode, Bool
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Module errors
19 19 #-----------------------------------------------------------------------------
20 20
21 21 class ProfileDirError(Exception):
22 22 pass
23 23
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Class for managing profile directories
27 27 #-----------------------------------------------------------------------------
28 28
29 29 class ProfileDir(LoggingConfigurable):
30 30 """An object to manage the profile directory and its resources.
31 31
32 32 The profile directory is used by all IPython applications, to manage
33 33 configuration, logging and security.
34 34
35 35 This object knows how to find, create and manage these directories. This
36 36 should be used by any code that wants to handle profiles.
37 37 """
38 38
39 39 security_dir_name = Unicode('security')
40 40 log_dir_name = Unicode('log')
41 41 startup_dir_name = Unicode('startup')
42 42 pid_dir_name = Unicode('pid')
43 43 static_dir_name = Unicode('static')
44 44 security_dir = Unicode(u'')
45 45 log_dir = Unicode(u'')
46 46 startup_dir = Unicode(u'')
47 47 pid_dir = Unicode(u'')
48 48 static_dir = Unicode(u'')
49 49
50 50 location = Unicode(u'', config=True,
51 51 help="""Set the profile location directly. This overrides the logic used by the
52 52 `profile` option.""",
53 53 )
54 54
55 55 _location_isset = Bool(False) # flag for detecting multiply set location
56 56
57 57 def _location_changed(self, name, old, new):
58 58 if self._location_isset:
59 59 raise RuntimeError("Cannot set profile location more than once.")
60 60 self._location_isset = True
61 61 ensure_dir_exists(new)
62 62
63 63 # ensure config files exist:
64 64 self.security_dir = os.path.join(new, self.security_dir_name)
65 65 self.log_dir = os.path.join(new, self.log_dir_name)
66 66 self.startup_dir = os.path.join(new, self.startup_dir_name)
67 67 self.pid_dir = os.path.join(new, self.pid_dir_name)
68 68 self.static_dir = os.path.join(new, self.static_dir_name)
69 69 self.check_dirs()
70 70
71 71 def _log_dir_changed(self, name, old, new):
72 72 self.check_log_dir()
73 73
74 74 def _mkdir(self, path, mode=None):
75 75 """ensure a directory exists at a given path
76 76
77 77 This is a version of os.mkdir, with the following differences:
78 78
79 79 - returns True if it created the directory, False otherwise
80 80 - ignores EEXIST, protecting against race conditions where
81 81 the dir may have been created in between the check and
82 82 the creation
83 83 - sets permissions if requested and the dir already exists
84 84 """
85 85 if os.path.exists(path):
86 86 if mode and os.stat(path).st_mode != mode:
87 87 try:
88 88 os.chmod(path, mode)
89 89 except OSError:
90 self.log.warn(
90 self.log.warning(
91 91 "Could not set permissions on %s",
92 92 path
93 93 )
94 94 return False
95 95 try:
96 96 if mode:
97 97 os.mkdir(path, mode)
98 98 else:
99 99 os.mkdir(path)
100 100 except OSError as e:
101 101 if e.errno == errno.EEXIST:
102 102 return False
103 103 else:
104 104 raise
105 105
106 106 return True
107 107
108 108 def check_log_dir(self):
109 109 self._mkdir(self.log_dir)
110 110
111 111 def _startup_dir_changed(self, name, old, new):
112 112 self.check_startup_dir()
113 113
114 114 def check_startup_dir(self):
115 115 self._mkdir(self.startup_dir)
116 116
117 117 readme = os.path.join(self.startup_dir, 'README')
118 118 src = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'README_STARTUP')
119 119
120 120 if not os.path.exists(src):
121 121 self.log.warn("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
122 122
123 123 if os.path.exists(src) and not os.path.exists(readme):
124 124 shutil.copy(src, readme)
125 125
126 126 def _security_dir_changed(self, name, old, new):
127 127 self.check_security_dir()
128 128
129 129 def check_security_dir(self):
130 130 self._mkdir(self.security_dir, 0o40700)
131 131
132 132 def _pid_dir_changed(self, name, old, new):
133 133 self.check_pid_dir()
134 134
135 135 def check_pid_dir(self):
136 136 self._mkdir(self.pid_dir, 0o40700)
137 137
138 138 def _static_dir_changed(self, name, old, new):
139 139 self.check_startup_dir()
140 140
141 141 def check_dirs(self):
142 142 self.check_security_dir()
143 143 self.check_log_dir()
144 144 self.check_pid_dir()
145 145 self.check_startup_dir()
146 146
147 147 def copy_config_file(self, config_file, path=None, overwrite=False):
148 148 """Copy a default config file into the active profile directory.
149 149
150 150 Default configuration files are kept in :mod:`IPython.core.profile`.
151 151 This function moves these from that location to the working profile
152 152 directory.
153 153 """
154 154 dst = os.path.join(self.location, config_file)
155 155 if os.path.isfile(dst) and not overwrite:
156 156 return False
157 157 if path is None:
158 158 path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default')
159 159 src = os.path.join(path, config_file)
160 160 shutil.copy(src, dst)
161 161 return True
162 162
163 163 @classmethod
164 164 def create_profile_dir(cls, profile_dir, config=None):
165 165 """Create a new profile directory given a full path.
166 166
167 167 Parameters
168 168 ----------
169 169 profile_dir : str
170 170 The full path to the profile directory. If it does exist, it will
171 171 be used. If not, it will be created.
172 172 """
173 173 return cls(location=profile_dir, config=config)
174 174
175 175 @classmethod
176 176 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
177 177 """Create a profile dir by profile name and path.
178 178
179 179 Parameters
180 180 ----------
181 181 path : unicode
182 182 The path (directory) to put the profile directory in.
183 183 name : unicode
184 184 The name of the profile. The name of the profile directory will
185 185 be "profile_<profile>".
186 186 """
187 187 if not os.path.isdir(path):
188 188 raise ProfileDirError('Directory not found: %s' % path)
189 189 profile_dir = os.path.join(path, u'profile_' + name)
190 190 return cls(location=profile_dir, config=config)
191 191
192 192 @classmethod
193 193 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
194 194 """Find an existing profile dir by profile name, return its ProfileDir.
195 195
196 196 This searches through a sequence of paths for a profile dir. If it
197 197 is not found, a :class:`ProfileDirError` exception will be raised.
198 198
199 199 The search path algorithm is:
200 200 1. ``py3compat.getcwd()``
201 201 2. ``ipython_dir``
202 202
203 203 Parameters
204 204 ----------
205 205 ipython_dir : unicode or str
206 206 The IPython directory to use.
207 207 name : unicode or str
208 208 The name of the profile. The name of the profile directory
209 209 will be "profile_<profile>".
210 210 """
211 211 dirname = u'profile_' + name
212 212 paths = [py3compat.getcwd(), ipython_dir]
213 213 for p in paths:
214 214 profile_dir = os.path.join(p, dirname)
215 215 if os.path.isdir(profile_dir):
216 216 return cls(location=profile_dir, config=config)
217 217 else:
218 218 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
219 219
220 220 @classmethod
221 221 def find_profile_dir(cls, profile_dir, config=None):
222 222 """Find/create a profile dir and return its ProfileDir.
223 223
224 224 This will create the profile directory if it doesn't exist.
225 225
226 226 Parameters
227 227 ----------
228 228 profile_dir : unicode or str
229 229 The path of the profile directory.
230 230 """
231 231 profile_dir = expand_path(profile_dir)
232 232 if not os.path.isdir(profile_dir):
233 233 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
234 234 return cls(location=profile_dir, config=config)
@@ -1,433 +1,433 b''
1 1 # encoding: utf-8
2 2 """
3 3 A mixin for :class:`~IPython.core.application.Application` classes that
4 4 launch InteractiveShell instances, load extensions, etc.
5 5 """
6 6
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 from __future__ import absolute_import
11 11 from __future__ import print_function
12 12
13 13 import glob
14 14 import os
15 15 import sys
16 16
17 17 from traitlets.config.application import boolean_flag
18 18 from traitlets.config.configurable import Configurable
19 19 from traitlets.config.loader import Config
20 20 from IPython.core import pylabtools
21 21 from IPython.utils import py3compat
22 22 from IPython.utils.contexts import preserve_keys
23 23 from IPython.utils.path import filefind
24 24 from traitlets import (
25 25 Unicode, Instance, List, Bool, CaselessStrEnum
26 26 )
27 27 from IPython.lib.inputhook import guis
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Aliases and Flags
31 31 #-----------------------------------------------------------------------------
32 32
33 33 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
34 34
35 35 backend_keys = sorted(pylabtools.backends.keys())
36 36 backend_keys.insert(0, 'auto')
37 37
38 38 shell_flags = {}
39 39
40 40 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
41 41 addflag('autoindent', 'InteractiveShell.autoindent',
42 42 'Turn on autoindenting.', 'Turn off autoindenting.'
43 43 )
44 44 addflag('automagic', 'InteractiveShell.automagic',
45 45 """Turn on the auto calling of magic commands. Type %%magic at the
46 46 IPython prompt for more information.""",
47 47 'Turn off the auto calling of magic commands.'
48 48 )
49 49 addflag('pdb', 'InteractiveShell.pdb',
50 50 "Enable auto calling the pdb debugger after every exception.",
51 51 "Disable auto calling the pdb debugger after every exception."
52 52 )
53 53 # pydb flag doesn't do any config, as core.debugger switches on import,
54 54 # which is before parsing. This just allows the flag to be passed.
55 55 shell_flags.update(dict(
56 56 pydb = ({},
57 57 """Use the third party 'pydb' package as debugger, instead of pdb.
58 58 Requires that pydb is installed."""
59 59 )
60 60 ))
61 61 addflag('pprint', 'PlainTextFormatter.pprint',
62 62 "Enable auto pretty printing of results.",
63 63 "Disable auto pretty printing of results."
64 64 )
65 65 addflag('color-info', 'InteractiveShell.color_info',
66 66 """IPython can display information about objects via a set of functions,
67 67 and optionally can use colors for this, syntax highlighting
68 68 source code and various other elements. This is on by default, but can cause
69 69 problems with some pagers. If you see such problems, you can disable the
70 70 colours.""",
71 71 "Disable using colors for info related things."
72 72 )
73 73 addflag('deep-reload', 'InteractiveShell.deep_reload',
74 74 """ **Deprecated** Enable deep (recursive) reloading by default. IPython can use the
75 75 deep_reload module which reloads changes in modules recursively (it
76 76 replaces the reload() function, so you don't need to change anything to
77 77 use it). deep_reload() forces a full reload of modules whose code may
78 78 have changed, which the default reload() function does not. When
79 79 deep_reload is off, IPython will use the normal reload(), but
80 80 deep_reload will still be available as dreload(). This feature is off
81 81 by default [which means that you have both normal reload() and
82 82 dreload()].""",
83 83 "Disable deep (recursive) reloading by default."
84 84 )
85 85 nosep_config = Config()
86 86 nosep_config.InteractiveShell.separate_in = ''
87 87 nosep_config.InteractiveShell.separate_out = ''
88 88 nosep_config.InteractiveShell.separate_out2 = ''
89 89
90 90 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
91 91 shell_flags['pylab'] = (
92 92 {'InteractiveShellApp' : {'pylab' : 'auto'}},
93 93 """Pre-load matplotlib and numpy for interactive use with
94 94 the default matplotlib backend."""
95 95 )
96 96 shell_flags['matplotlib'] = (
97 97 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
98 98 """Configure matplotlib for interactive use with
99 99 the default matplotlib backend."""
100 100 )
101 101
102 102 # it's possible we don't want short aliases for *all* of these:
103 103 shell_aliases = dict(
104 104 autocall='InteractiveShell.autocall',
105 105 colors='InteractiveShell.colors',
106 106 logfile='InteractiveShell.logfile',
107 107 logappend='InteractiveShell.logappend',
108 108 c='InteractiveShellApp.code_to_run',
109 109 m='InteractiveShellApp.module_to_run',
110 110 ext='InteractiveShellApp.extra_extension',
111 111 gui='InteractiveShellApp.gui',
112 112 pylab='InteractiveShellApp.pylab',
113 113 matplotlib='InteractiveShellApp.matplotlib',
114 114 )
115 115 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
116 116
117 117 #-----------------------------------------------------------------------------
118 118 # Main classes and functions
119 119 #-----------------------------------------------------------------------------
120 120
121 121 class InteractiveShellApp(Configurable):
122 122 """A Mixin for applications that start InteractiveShell instances.
123 123
124 124 Provides configurables for loading extensions and executing files
125 125 as part of configuring a Shell environment.
126 126
127 127 The following methods should be called by the :meth:`initialize` method
128 128 of the subclass:
129 129
130 130 - :meth:`init_path`
131 131 - :meth:`init_shell` (to be implemented by the subclass)
132 132 - :meth:`init_gui_pylab`
133 133 - :meth:`init_extensions`
134 134 - :meth:`init_code`
135 135 """
136 136 extensions = List(Unicode(), config=True,
137 137 help="A list of dotted module names of IPython extensions to load."
138 138 )
139 139 extra_extension = Unicode('', config=True,
140 140 help="dotted module name of an IPython extension to load."
141 141 )
142 142
143 143 reraise_ipython_extension_failures = Bool(
144 144 False,
145 145 config=True,
146 146 help="Reraise exceptions encountered loading IPython extensions?",
147 147 )
148 148
149 149 # Extensions that are always loaded (not configurable)
150 150 default_extensions = List(Unicode(), [u'storemagic'], config=False)
151 151
152 152 hide_initial_ns = Bool(True, config=True,
153 153 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
154 154 be hidden from tools like %who?"""
155 155 )
156 156
157 157 exec_files = List(Unicode(), config=True,
158 158 help="""List of files to run at IPython startup."""
159 159 )
160 160 exec_PYTHONSTARTUP = Bool(True, config=True,
161 161 help="""Run the file referenced by the PYTHONSTARTUP environment
162 162 variable at IPython startup."""
163 163 )
164 164 file_to_run = Unicode('', config=True,
165 165 help="""A file to be run""")
166 166
167 167 exec_lines = List(Unicode(), config=True,
168 168 help="""lines of code to run at IPython startup."""
169 169 )
170 170 code_to_run = Unicode('', config=True,
171 171 help="Execute the given command string."
172 172 )
173 173 module_to_run = Unicode('', config=True,
174 174 help="Run the module as a script."
175 175 )
176 176 gui = CaselessStrEnum(gui_keys, config=True, allow_none=True,
177 177 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
178 178 )
179 179 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
180 180 config=True,
181 181 help="""Configure matplotlib for interactive use with
182 182 the default matplotlib backend."""
183 183 )
184 184 pylab = CaselessStrEnum(backend_keys, allow_none=True,
185 185 config=True,
186 186 help="""Pre-load matplotlib and numpy for interactive use,
187 187 selecting a particular matplotlib backend and loop integration.
188 188 """
189 189 )
190 190 pylab_import_all = Bool(True, config=True,
191 191 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
192 192 and an ``import *`` is done from numpy and pylab, when using pylab mode.
193 193
194 194 When False, pylab mode should not import any names into the user namespace.
195 195 """
196 196 )
197 197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
198 198 allow_none=True)
199 199
200 200 user_ns = Instance(dict, args=None, allow_none=True)
201 201 def _user_ns_changed(self, name, old, new):
202 202 if self.shell is not None:
203 203 self.shell.user_ns = new
204 204 self.shell.init_user_ns()
205 205
206 206 def init_path(self):
207 207 """Add current working directory, '', to sys.path"""
208 208 if sys.path[0] != '':
209 209 sys.path.insert(0, '')
210 210
211 211 def init_shell(self):
212 212 raise NotImplementedError("Override in subclasses")
213 213
214 214 def init_gui_pylab(self):
215 215 """Enable GUI event loop integration, taking pylab into account."""
216 216 enable = False
217 217 shell = self.shell
218 218 if self.pylab:
219 219 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
220 220 key = self.pylab
221 221 elif self.matplotlib:
222 222 enable = shell.enable_matplotlib
223 223 key = self.matplotlib
224 224 elif self.gui:
225 225 enable = shell.enable_gui
226 226 key = self.gui
227 227
228 228 if not enable:
229 229 return
230 230
231 231 try:
232 232 r = enable(key)
233 233 except ImportError:
234 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
234 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
235 235 self.shell.showtraceback()
236 236 return
237 237 except Exception:
238 self.log.warn("GUI event loop or pylab initialization failed")
238 self.log.warning("GUI event loop or pylab initialization failed")
239 239 self.shell.showtraceback()
240 240 return
241 241
242 242 if isinstance(r, tuple):
243 243 gui, backend = r[:2]
244 244 self.log.info("Enabling GUI event loop integration, "
245 245 "eventloop=%s, matplotlib=%s", gui, backend)
246 246 if key == "auto":
247 247 print("Using matplotlib backend: %s" % backend)
248 248 else:
249 249 gui = r
250 250 self.log.info("Enabling GUI event loop integration, "
251 251 "eventloop=%s", gui)
252 252
253 253 def init_extensions(self):
254 254 """Load all IPython extensions in IPythonApp.extensions.
255 255
256 256 This uses the :meth:`ExtensionManager.load_extensions` to load all
257 257 the extensions listed in ``self.extensions``.
258 258 """
259 259 try:
260 260 self.log.debug("Loading IPython extensions...")
261 261 extensions = self.default_extensions + self.extensions
262 262 if self.extra_extension:
263 263 extensions.append(self.extra_extension)
264 264 for ext in extensions:
265 265 try:
266 266 self.log.info("Loading IPython extension: %s" % ext)
267 267 self.shell.extension_manager.load_extension(ext)
268 268 except:
269 269 if self.reraise_ipython_extension_failures:
270 270 raise
271 271 msg = ("Error in loading extension: {ext}\n"
272 272 "Check your config files in {location}".format(
273 273 ext=ext,
274 274 location=self.profile_dir.location
275 275 ))
276 self.log.warn(msg, exc_info=True)
276 self.log.warning(msg, exc_info=True)
277 277 except:
278 278 if self.reraise_ipython_extension_failures:
279 279 raise
280 self.log.warn("Unknown error in loading extensions:", exc_info=True)
280 self.log.warning("Unknown error in loading extensions:", exc_info=True)
281 281
282 282 def init_code(self):
283 283 """run the pre-flight code, specified via exec_lines"""
284 284 self._run_startup_files()
285 285 self._run_exec_lines()
286 286 self._run_exec_files()
287 287
288 288 # Hide variables defined here from %who etc.
289 289 if self.hide_initial_ns:
290 290 self.shell.user_ns_hidden.update(self.shell.user_ns)
291 291
292 292 # command-line execution (ipython -i script.py, ipython -m module)
293 293 # should *not* be excluded from %whos
294 294 self._run_cmd_line_code()
295 295 self._run_module()
296 296
297 297 # flush output, so itwon't be attached to the first cell
298 298 sys.stdout.flush()
299 299 sys.stderr.flush()
300 300
301 301 def _run_exec_lines(self):
302 302 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
303 303 if not self.exec_lines:
304 304 return
305 305 try:
306 306 self.log.debug("Running code from IPythonApp.exec_lines...")
307 307 for line in self.exec_lines:
308 308 try:
309 309 self.log.info("Running code in user namespace: %s" %
310 310 line)
311 311 self.shell.run_cell(line, store_history=False)
312 312 except:
313 self.log.warn("Error in executing line in user "
313 self.log.warning("Error in executing line in user "
314 314 "namespace: %s" % line)
315 315 self.shell.showtraceback()
316 316 except:
317 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
317 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
318 318 self.shell.showtraceback()
319 319
320 320 def _exec_file(self, fname, shell_futures=False):
321 321 try:
322 322 full_filename = filefind(fname, [u'.', self.ipython_dir])
323 323 except IOError as e:
324 self.log.warn("File not found: %r"%fname)
324 self.log.warning("File not found: %r"%fname)
325 325 return
326 326 # Make sure that the running script gets a proper sys.argv as if it
327 327 # were run from a system shell.
328 328 save_argv = sys.argv
329 329 sys.argv = [full_filename] + self.extra_args[1:]
330 330 # protect sys.argv from potential unicode strings on Python 2:
331 331 if not py3compat.PY3:
332 332 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
333 333 try:
334 334 if os.path.isfile(full_filename):
335 335 self.log.info("Running file in user namespace: %s" %
336 336 full_filename)
337 337 # Ensure that __file__ is always defined to match Python
338 338 # behavior.
339 339 with preserve_keys(self.shell.user_ns, '__file__'):
340 340 self.shell.user_ns['__file__'] = fname
341 341 if full_filename.endswith('.ipy'):
342 342 self.shell.safe_execfile_ipy(full_filename,
343 343 shell_futures=shell_futures)
344 344 else:
345 345 # default to python, even without extension
346 346 self.shell.safe_execfile(full_filename,
347 347 self.shell.user_ns,
348 348 shell_futures=shell_futures,
349 349 raise_exceptions=True)
350 350 finally:
351 351 sys.argv = save_argv
352 352
353 353 def _run_startup_files(self):
354 354 """Run files from profile startup directory"""
355 355 startup_dir = self.profile_dir.startup_dir
356 356 startup_files = []
357 357
358 358 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
359 359 not (self.file_to_run or self.code_to_run or self.module_to_run):
360 360 python_startup = os.environ['PYTHONSTARTUP']
361 361 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
362 362 try:
363 363 self._exec_file(python_startup)
364 364 except:
365 self.log.warn("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
365 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
366 366 self.shell.showtraceback()
367 367 finally:
368 368 # Many PYTHONSTARTUP files set up the readline completions,
369 369 # but this is often at odds with IPython's own completions.
370 370 # Do not allow PYTHONSTARTUP to set up readline.
371 371 if self.shell.has_readline:
372 372 self.shell.set_readline_completer()
373 373
374 374 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
375 375 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
376 376 if not startup_files:
377 377 return
378 378
379 379 self.log.debug("Running startup files from %s...", startup_dir)
380 380 try:
381 381 for fname in sorted(startup_files):
382 382 self._exec_file(fname)
383 383 except:
384 self.log.warn("Unknown error in handling startup files:")
384 self.log.warning("Unknown error in handling startup files:")
385 385 self.shell.showtraceback()
386 386
387 387 def _run_exec_files(self):
388 388 """Run files from IPythonApp.exec_files"""
389 389 if not self.exec_files:
390 390 return
391 391
392 392 self.log.debug("Running files in IPythonApp.exec_files...")
393 393 try:
394 394 for fname in self.exec_files:
395 395 self._exec_file(fname)
396 396 except:
397 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
397 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
398 398 self.shell.showtraceback()
399 399
400 400 def _run_cmd_line_code(self):
401 401 """Run code or file specified at the command-line"""
402 402 if self.code_to_run:
403 403 line = self.code_to_run
404 404 try:
405 405 self.log.info("Running code given at command line (c=): %s" %
406 406 line)
407 407 self.shell.run_cell(line, store_history=False)
408 408 except:
409 self.log.warn("Error in executing line in user namespace: %s" %
409 self.log.warning("Error in executing line in user namespace: %s" %
410 410 line)
411 411 self.shell.showtraceback()
412 412
413 413 # Like Python itself, ignore the second if the first of these is present
414 414 elif self.file_to_run:
415 415 fname = self.file_to_run
416 416 try:
417 417 self._exec_file(fname, shell_futures=True)
418 418 except:
419 419 self.shell.showtraceback(tb_offset=4)
420 420 self.exit(1)
421 421
422 422 def _run_module(self):
423 423 """Run module specified at the command-line."""
424 424 if self.module_to_run:
425 425 # Make sure that the module gets a proper sys.argv as if it were
426 426 # run using `python -m`.
427 427 save_argv = sys.argv
428 428 sys.argv = [sys.executable] + self.extra_args
429 429 try:
430 430 self.shell.safe_run_module(self.module_to_run,
431 431 self.shell.user_ns)
432 432 finally:
433 433 sys.argv = save_argv
General Comments 0
You need to be logged in to leave comments. Login now