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