##// END OF EJS Templates
Don't crash if README_STARTUP is missing...
Jussi Sainio -
Show More
@@ -1,228 +1,232 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An object for managing IPython profile directories.
3 An object for managing IPython profile directories.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 * Fernando Perez
8 * Fernando Perez
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 os
24 import os
25 import shutil
25 import shutil
26 import sys
26 import sys
27
27
28 from IPython.config.configurable import LoggingConfigurable
28 from IPython.config.configurable import LoggingConfigurable
29 from IPython.config.loader import Config
29 from IPython.config.loader import Config
30 from IPython.utils.path import get_ipython_package_dir, expand_path
30 from IPython.utils.path import get_ipython_package_dir, expand_path
31 from IPython.utils.traitlets import List, Unicode, Bool
31 from IPython.utils.traitlets import List, Unicode, Bool
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Classes and functions
34 # Classes and functions
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37
37
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39 # Module errors
39 # Module errors
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41
41
42 class ProfileDirError(Exception):
42 class ProfileDirError(Exception):
43 pass
43 pass
44
44
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Class for managing profile directories
47 # Class for managing profile directories
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50 class ProfileDir(LoggingConfigurable):
50 class ProfileDir(LoggingConfigurable):
51 """An object to manage the profile directory and its resources.
51 """An object to manage the profile directory and its resources.
52
52
53 The profile directory is used by all IPython applications, to manage
53 The profile directory is used by all IPython applications, to manage
54 configuration, logging and security.
54 configuration, logging and security.
55
55
56 This object knows how to find, create and manage these directories. This
56 This object knows how to find, create and manage these directories. This
57 should be used by any code that wants to handle profiles.
57 should be used by any code that wants to handle profiles.
58 """
58 """
59
59
60 security_dir_name = Unicode('security')
60 security_dir_name = Unicode('security')
61 log_dir_name = Unicode('log')
61 log_dir_name = Unicode('log')
62 startup_dir_name = Unicode('startup')
62 startup_dir_name = Unicode('startup')
63 pid_dir_name = Unicode('pid')
63 pid_dir_name = Unicode('pid')
64 security_dir = Unicode(u'')
64 security_dir = Unicode(u'')
65 log_dir = Unicode(u'')
65 log_dir = Unicode(u'')
66 startup_dir = Unicode(u'')
66 startup_dir = Unicode(u'')
67 pid_dir = Unicode(u'')
67 pid_dir = Unicode(u'')
68
68
69 location = Unicode(u'', config=True,
69 location = Unicode(u'', config=True,
70 help="""Set the profile location directly. This overrides the logic used by the
70 help="""Set the profile location directly. This overrides the logic used by the
71 `profile` option.""",
71 `profile` option.""",
72 )
72 )
73
73
74 _location_isset = Bool(False) # flag for detecting multiply set location
74 _location_isset = Bool(False) # flag for detecting multiply set location
75
75
76 def _location_changed(self, name, old, new):
76 def _location_changed(self, name, old, new):
77 if self._location_isset:
77 if self._location_isset:
78 raise RuntimeError("Cannot set profile location more than once.")
78 raise RuntimeError("Cannot set profile location more than once.")
79 self._location_isset = True
79 self._location_isset = True
80 if not os.path.isdir(new):
80 if not os.path.isdir(new):
81 os.makedirs(new)
81 os.makedirs(new)
82
82
83 # ensure config files exist:
83 # ensure config files exist:
84 self.security_dir = os.path.join(new, self.security_dir_name)
84 self.security_dir = os.path.join(new, self.security_dir_name)
85 self.log_dir = os.path.join(new, self.log_dir_name)
85 self.log_dir = os.path.join(new, self.log_dir_name)
86 self.startup_dir = os.path.join(new, self.startup_dir_name)
86 self.startup_dir = os.path.join(new, self.startup_dir_name)
87 self.pid_dir = os.path.join(new, self.pid_dir_name)
87 self.pid_dir = os.path.join(new, self.pid_dir_name)
88 self.check_dirs()
88 self.check_dirs()
89
89
90 def _log_dir_changed(self, name, old, new):
90 def _log_dir_changed(self, name, old, new):
91 self.check_log_dir()
91 self.check_log_dir()
92
92
93 def check_log_dir(self):
93 def check_log_dir(self):
94 if not os.path.isdir(self.log_dir):
94 if not os.path.isdir(self.log_dir):
95 os.mkdir(self.log_dir)
95 os.mkdir(self.log_dir)
96
96
97 def _startup_dir_changed(self, name, old, new):
97 def _startup_dir_changed(self, name, old, new):
98 self.check_startup_dir()
98 self.check_startup_dir()
99
99
100 def check_startup_dir(self):
100 def check_startup_dir(self):
101 if not os.path.isdir(self.startup_dir):
101 if not os.path.isdir(self.startup_dir):
102 os.mkdir(self.startup_dir)
102 os.mkdir(self.startup_dir)
103 readme = os.path.join(self.startup_dir, 'README')
103 readme = os.path.join(self.startup_dir, 'README')
104 src = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'README_STARTUP')
104 src = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'README_STARTUP')
105 if not os.path.exists(readme):
105
106 if not os.path.exists(src):
107 self.log.warn("Could not copy README_STARTUP to startup dir. Source file %s does not exist." % src)
108
109 if os.path.exists(src) and not os.path.exists(readme):
106 shutil.copy(src, readme)
110 shutil.copy(src, readme)
107
111
108 def _security_dir_changed(self, name, old, new):
112 def _security_dir_changed(self, name, old, new):
109 self.check_security_dir()
113 self.check_security_dir()
110
114
111 def check_security_dir(self):
115 def check_security_dir(self):
112 if not os.path.isdir(self.security_dir):
116 if not os.path.isdir(self.security_dir):
113 os.mkdir(self.security_dir, 0o700)
117 os.mkdir(self.security_dir, 0o700)
114 else:
118 else:
115 try:
119 try:
116 os.chmod(self.security_dir, 0o700)
120 os.chmod(self.security_dir, 0o700)
117 except OSError:
121 except OSError:
118 self.log.warn("Could not set security dir permissions to private.")
122 self.log.warn("Could not set security dir permissions to private.")
119
123
120 def _pid_dir_changed(self, name, old, new):
124 def _pid_dir_changed(self, name, old, new):
121 self.check_pid_dir()
125 self.check_pid_dir()
122
126
123 def check_pid_dir(self):
127 def check_pid_dir(self):
124 if not os.path.isdir(self.pid_dir):
128 if not os.path.isdir(self.pid_dir):
125 os.mkdir(self.pid_dir, 0o700)
129 os.mkdir(self.pid_dir, 0o700)
126 else:
130 else:
127 try:
131 try:
128 os.chmod(self.pid_dir, 0o700)
132 os.chmod(self.pid_dir, 0o700)
129 except OSError:
133 except OSError:
130 self.log.warn("Could not set pid dir permissions to private.")
134 self.log.warn("Could not set pid dir permissions to private.")
131
135
132 def check_dirs(self):
136 def check_dirs(self):
133 self.check_security_dir()
137 self.check_security_dir()
134 self.check_log_dir()
138 self.check_log_dir()
135 self.check_pid_dir()
139 self.check_pid_dir()
136 self.check_startup_dir()
140 self.check_startup_dir()
137
141
138 def copy_config_file(self, config_file, path=None, overwrite=False):
142 def copy_config_file(self, config_file, path=None, overwrite=False):
139 """Copy a default config file into the active profile directory.
143 """Copy a default config file into the active profile directory.
140
144
141 Default configuration files are kept in :mod:`IPython.config.default`.
145 Default configuration files are kept in :mod:`IPython.config.default`.
142 This function moves these from that location to the working profile
146 This function moves these from that location to the working profile
143 directory.
147 directory.
144 """
148 """
145 dst = os.path.join(self.location, config_file)
149 dst = os.path.join(self.location, config_file)
146 if os.path.isfile(dst) and not overwrite:
150 if os.path.isfile(dst) and not overwrite:
147 return False
151 return False
148 if path is None:
152 if path is None:
149 path = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
153 path = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
150 src = os.path.join(path, config_file)
154 src = os.path.join(path, config_file)
151 shutil.copy(src, dst)
155 shutil.copy(src, dst)
152 return True
156 return True
153
157
154 @classmethod
158 @classmethod
155 def create_profile_dir(cls, profile_dir, config=None):
159 def create_profile_dir(cls, profile_dir, config=None):
156 """Create a new profile directory given a full path.
160 """Create a new profile directory given a full path.
157
161
158 Parameters
162 Parameters
159 ----------
163 ----------
160 profile_dir : str
164 profile_dir : str
161 The full path to the profile directory. If it does exist, it will
165 The full path to the profile directory. If it does exist, it will
162 be used. If not, it will be created.
166 be used. If not, it will be created.
163 """
167 """
164 return cls(location=profile_dir, config=config)
168 return cls(location=profile_dir, config=config)
165
169
166 @classmethod
170 @classmethod
167 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
171 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
168 """Create a profile dir by profile name and path.
172 """Create a profile dir by profile name and path.
169
173
170 Parameters
174 Parameters
171 ----------
175 ----------
172 path : unicode
176 path : unicode
173 The path (directory) to put the profile directory in.
177 The path (directory) to put the profile directory in.
174 name : unicode
178 name : unicode
175 The name of the profile. The name of the profile directory will
179 The name of the profile. The name of the profile directory will
176 be "profile_<profile>".
180 be "profile_<profile>".
177 """
181 """
178 if not os.path.isdir(path):
182 if not os.path.isdir(path):
179 raise ProfileDirError('Directory not found: %s' % path)
183 raise ProfileDirError('Directory not found: %s' % path)
180 profile_dir = os.path.join(path, u'profile_' + name)
184 profile_dir = os.path.join(path, u'profile_' + name)
181 return cls(location=profile_dir, config=config)
185 return cls(location=profile_dir, config=config)
182
186
183 @classmethod
187 @classmethod
184 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
188 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
185 """Find an existing profile dir by profile name, return its ProfileDir.
189 """Find an existing profile dir by profile name, return its ProfileDir.
186
190
187 This searches through a sequence of paths for a profile dir. If it
191 This searches through a sequence of paths for a profile dir. If it
188 is not found, a :class:`ProfileDirError` exception will be raised.
192 is not found, a :class:`ProfileDirError` exception will be raised.
189
193
190 The search path algorithm is:
194 The search path algorithm is:
191 1. ``os.getcwdu()``
195 1. ``os.getcwdu()``
192 2. ``ipython_dir``
196 2. ``ipython_dir``
193
197
194 Parameters
198 Parameters
195 ----------
199 ----------
196 ipython_dir : unicode or str
200 ipython_dir : unicode or str
197 The IPython directory to use.
201 The IPython directory to use.
198 name : unicode or str
202 name : unicode or str
199 The name of the profile. The name of the profile directory
203 The name of the profile. The name of the profile directory
200 will be "profile_<profile>".
204 will be "profile_<profile>".
201 """
205 """
202 dirname = u'profile_' + name
206 dirname = u'profile_' + name
203 paths = [os.getcwdu(), ipython_dir]
207 paths = [os.getcwdu(), ipython_dir]
204 for p in paths:
208 for p in paths:
205 profile_dir = os.path.join(p, dirname)
209 profile_dir = os.path.join(p, dirname)
206 if os.path.isdir(profile_dir):
210 if os.path.isdir(profile_dir):
207 return cls(location=profile_dir, config=config)
211 return cls(location=profile_dir, config=config)
208 else:
212 else:
209 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
213 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
210
214
211 @classmethod
215 @classmethod
212 def find_profile_dir(cls, profile_dir, config=None):
216 def find_profile_dir(cls, profile_dir, config=None):
213 """Find/create a profile dir and return its ProfileDir.
217 """Find/create a profile dir and return its ProfileDir.
214
218
215 This will create the profile directory if it doesn't exist.
219 This will create the profile directory if it doesn't exist.
216
220
217 Parameters
221 Parameters
218 ----------
222 ----------
219 profile_dir : unicode or str
223 profile_dir : unicode or str
220 The path of the profile directory. This is expanded using
224 The path of the profile directory. This is expanded using
221 :func:`IPython.utils.genutils.expand_path`.
225 :func:`IPython.utils.genutils.expand_path`.
222 """
226 """
223 profile_dir = expand_path(profile_dir)
227 profile_dir = expand_path(profile_dir)
224 if not os.path.isdir(profile_dir):
228 if not os.path.isdir(profile_dir):
225 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
229 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
226 return cls(location=profile_dir, config=config)
230 return cls(location=profile_dir, config=config)
227
231
228
232
General Comments 0
You need to be logged in to leave comments. Login now