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