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