##// END OF EJS Templates
add README to startup dir
MinRK -
Show More
@@ -0,0 +1,11 b''
1 This is the IPython startup directory
2
3 .py and .ipy files in this directory will be run *prior* to any code or files specified
4 via the exec_lines or exec_files configurables whenever you load this profile.
5
6 Files will be run in lexicographical order, so you can control the execution order of files
7 with a prefix, e.g.::
8
9 00-first.py
10 50-middle.py
11 99-last.ipy
@@ -1,223 +1,228 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 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 26 import sys
27 27
28 28 from IPython.config.configurable import LoggingConfigurable
29 29 from IPython.config.loader import Config
30 30 from IPython.utils.path import get_ipython_package_dir, expand_path
31 31 from IPython.utils.traitlets import List, Unicode, Bool
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Classes and functions
35 35 #-----------------------------------------------------------------------------
36 36
37 37
38 38 #-----------------------------------------------------------------------------
39 39 # Module errors
40 40 #-----------------------------------------------------------------------------
41 41
42 42 class ProfileDirError(Exception):
43 43 pass
44 44
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Class for managing profile directories
48 48 #-----------------------------------------------------------------------------
49 49
50 50 class ProfileDir(LoggingConfigurable):
51 51 """An object to manage the profile directory and its resources.
52 52
53 53 The profile directory is used by all IPython applications, to manage
54 54 configuration, logging and security.
55 55
56 56 This object knows how to find, create and manage these directories. This
57 57 should be used by any code that wants to handle profiles.
58 58 """
59 59
60 60 security_dir_name = Unicode('security')
61 61 log_dir_name = Unicode('log')
62 62 startup_dir_name = Unicode('startup')
63 63 pid_dir_name = Unicode('pid')
64 64 security_dir = Unicode(u'')
65 65 log_dir = Unicode(u'')
66 66 startup_dir = Unicode(u'')
67 67 pid_dir = Unicode(u'')
68 68
69 69 location = Unicode(u'', config=True,
70 70 help="""Set the profile location directly. This overrides the logic used by the
71 71 `profile` option.""",
72 72 )
73 73
74 74 _location_isset = Bool(False) # flag for detecting multiply set location
75 75
76 76 def _location_changed(self, name, old, new):
77 77 if self._location_isset:
78 78 raise RuntimeError("Cannot set profile location more than once.")
79 79 self._location_isset = True
80 80 if not os.path.isdir(new):
81 81 os.makedirs(new)
82 82
83 83 # ensure config files exist:
84 84 self.security_dir = os.path.join(new, self.security_dir_name)
85 85 self.log_dir = os.path.join(new, self.log_dir_name)
86 86 self.startup_dir = os.path.join(new, self.startup_dir_name)
87 87 self.pid_dir = os.path.join(new, self.pid_dir_name)
88 88 self.check_dirs()
89 89
90 90 def _log_dir_changed(self, name, old, new):
91 91 self.check_log_dir()
92 92
93 93 def check_log_dir(self):
94 94 if not os.path.isdir(self.log_dir):
95 95 os.mkdir(self.log_dir)
96 96
97 97 def _startup_dir_changed(self, name, old, new):
98 98 self.check_startup_dir()
99 99
100 100 def check_startup_dir(self):
101 101 if not os.path.isdir(self.startup_dir):
102 102 os.mkdir(self.startup_dir)
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')
105 if not os.path.exists(readme):
106 shutil.copy(src, readme)
103 107
104 108 def _security_dir_changed(self, name, old, new):
105 109 self.check_security_dir()
106 110
107 111 def check_security_dir(self):
108 112 if not os.path.isdir(self.security_dir):
109 113 os.mkdir(self.security_dir, 0700)
110 114 else:
111 115 try:
112 116 os.chmod(self.security_dir, 0700)
113 117 except OSError:
114 118 self.log.warn("Could not set security dir permissions to private.")
115 119
116 120 def _pid_dir_changed(self, name, old, new):
117 121 self.check_pid_dir()
118 122
119 123 def check_pid_dir(self):
120 124 if not os.path.isdir(self.pid_dir):
121 125 os.mkdir(self.pid_dir, 0700)
122 126 else:
123 127 try:
124 128 os.chmod(self.pid_dir, 0700)
125 129 except OSError:
126 130 self.log.warn("Could not set pid dir permissions to private.")
127 131
128 132 def check_dirs(self):
129 133 self.check_security_dir()
130 134 self.check_log_dir()
131 135 self.check_pid_dir()
136 self.check_startup_dir()
132 137
133 138 def copy_config_file(self, config_file, path=None, overwrite=False):
134 139 """Copy a default config file into the active profile directory.
135 140
136 141 Default configuration files are kept in :mod:`IPython.config.default`.
137 142 This function moves these from that location to the working profile
138 143 directory.
139 144 """
140 145 dst = os.path.join(self.location, config_file)
141 146 if os.path.isfile(dst) and not overwrite:
142 147 return False
143 148 if path is None:
144 149 path = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
145 150 src = os.path.join(path, config_file)
146 151 shutil.copy(src, dst)
147 152 return True
148 153
149 154 @classmethod
150 155 def create_profile_dir(cls, profile_dir, config=None):
151 156 """Create a new profile directory given a full path.
152 157
153 158 Parameters
154 159 ----------
155 160 profile_dir : str
156 161 The full path to the profile directory. If it does exist, it will
157 162 be used. If not, it will be created.
158 163 """
159 164 return cls(location=profile_dir, config=config)
160 165
161 166 @classmethod
162 167 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
163 168 """Create a profile dir by profile name and path.
164 169
165 170 Parameters
166 171 ----------
167 172 path : unicode
168 173 The path (directory) to put the profile directory in.
169 174 name : unicode
170 175 The name of the profile. The name of the profile directory will
171 176 be "profile_<profile>".
172 177 """
173 178 if not os.path.isdir(path):
174 179 raise ProfileDirError('Directory not found: %s' % path)
175 180 profile_dir = os.path.join(path, u'profile_' + name)
176 181 return cls(location=profile_dir, config=config)
177 182
178 183 @classmethod
179 184 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
180 185 """Find an existing profile dir by profile name, return its ProfileDir.
181 186
182 187 This searches through a sequence of paths for a profile dir. If it
183 188 is not found, a :class:`ProfileDirError` exception will be raised.
184 189
185 190 The search path algorithm is:
186 191 1. ``os.getcwdu()``
187 192 2. ``ipython_dir``
188 193
189 194 Parameters
190 195 ----------
191 196 ipython_dir : unicode or str
192 197 The IPython directory to use.
193 198 name : unicode or str
194 199 The name of the profile. The name of the profile directory
195 200 will be "profile_<profile>".
196 201 """
197 202 dirname = u'profile_' + name
198 203 paths = [os.getcwdu(), ipython_dir]
199 204 for p in paths:
200 205 profile_dir = os.path.join(p, dirname)
201 206 if os.path.isdir(profile_dir):
202 207 return cls(location=profile_dir, config=config)
203 208 else:
204 209 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
205 210
206 211 @classmethod
207 212 def find_profile_dir(cls, profile_dir, config=None):
208 213 """Find/create a profile dir and return its ProfileDir.
209 214
210 215 This will create the profile directory if it doesn't exist.
211 216
212 217 Parameters
213 218 ----------
214 219 profile_dir : unicode or str
215 220 The path of the profile directory. This is expanded using
216 221 :func:`IPython.utils.genutils.expand_path`.
217 222 """
218 223 profile_dir = expand_path(profile_dir)
219 224 if not os.path.isdir(profile_dir):
220 225 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
221 226 return cls(location=profile_dir, config=config)
222 227
223 228
@@ -1,382 +1,382 b''
1 1 # encoding: utf-8
2 2 """
3 3 This module defines the things that are used in setup.py for building IPython
4 4
5 5 This includes:
6 6
7 7 * The basic arguments to setup
8 8 * Functions for finding things like packages, package data, etc.
9 9 * A function for checking dependencies.
10 10 """
11 11 from __future__ import print_function
12 12
13 13 #-------------------------------------------------------------------------------
14 14 # Copyright (C) 2008 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 import os
24 24 import sys
25 25
26 26 try:
27 27 from configparser import ConfigParser
28 28 except:
29 29 from ConfigParser import ConfigParser
30 30 from distutils.command.build_py import build_py
31 31 from glob import glob
32 32
33 33 from setupext import install_data_ext
34 34
35 35 #-------------------------------------------------------------------------------
36 36 # Useful globals and utility functions
37 37 #-------------------------------------------------------------------------------
38 38
39 39 # A few handy globals
40 40 isfile = os.path.isfile
41 41 pjoin = os.path.join
42 42
43 43 def oscmd(s):
44 44 print(">", s)
45 45 os.system(s)
46 46
47 47 try:
48 48 execfile
49 49 except NameError:
50 50 def execfile(fname, globs, locs=None):
51 51 locs = locs or globs
52 52 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
53 53
54 54 # A little utility we'll need below, since glob() does NOT allow you to do
55 55 # exclusion on multiple endings!
56 56 def file_doesnt_endwith(test,endings):
57 57 """Return true if test is a file and its name does NOT end with any
58 58 of the strings listed in endings."""
59 59 if not isfile(test):
60 60 return False
61 61 for e in endings:
62 62 if test.endswith(e):
63 63 return False
64 64 return True
65 65
66 66 #---------------------------------------------------------------------------
67 67 # Basic project information
68 68 #---------------------------------------------------------------------------
69 69
70 70 # release.py contains version, authors, license, url, keywords, etc.
71 71 execfile(pjoin('IPython','core','release.py'), globals())
72 72
73 73 # Create a dict with the basic information
74 74 # This dict is eventually passed to setup after additional keys are added.
75 75 setup_args = dict(
76 76 name = name,
77 77 version = version,
78 78 description = description,
79 79 long_description = long_description,
80 80 author = author,
81 81 author_email = author_email,
82 82 url = url,
83 83 download_url = download_url,
84 84 license = license,
85 85 platforms = platforms,
86 86 keywords = keywords,
87 87 classifiers = classifiers,
88 88 cmdclass = {'install_data': install_data_ext},
89 89 )
90 90
91 91
92 92 #---------------------------------------------------------------------------
93 93 # Find packages
94 94 #---------------------------------------------------------------------------
95 95
96 96 def find_packages():
97 97 """
98 98 Find all of IPython's packages.
99 99 """
100 100 excludes = ['deathrow']
101 101 packages = []
102 102 for dir,subdirs,files in os.walk('IPython'):
103 103 package = dir.replace(os.path.sep, '.')
104 104 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
105 105 # package is to be excluded (e.g. deathrow)
106 106 continue
107 107 if '__init__.py' not in files:
108 108 # not a package
109 109 continue
110 110 packages.append(package)
111 111 return packages
112 112
113 113 #---------------------------------------------------------------------------
114 114 # Find package data
115 115 #---------------------------------------------------------------------------
116 116
117 117 def find_package_data():
118 118 """
119 119 Find IPython's package_data.
120 120 """
121 121 # This is not enough for these things to appear in an sdist.
122 122 # We need to muck with the MANIFEST to get this to work
123 123
124 124 # walk notebook resources:
125 125 cwd = os.getcwd()
126 126 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
127 127 static_walk = list(os.walk('static'))
128 128 os.chdir(cwd)
129 129 static_data = []
130 130 for parent, dirs, files in static_walk:
131 131 for f in files:
132 132 static_data.append(os.path.join(parent, f))
133 133
134 134 package_data = {
135 'IPython.config.profile' : ['README', '*/*.py'],
135 'IPython.config.profile' : ['README*', '*/*.py'],
136 136 'IPython.testing' : ['*.txt'],
137 137 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
138 138 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
139 139 }
140 140 return package_data
141 141
142 142
143 143 #---------------------------------------------------------------------------
144 144 # Find data files
145 145 #---------------------------------------------------------------------------
146 146
147 147 def make_dir_struct(tag,base,out_base):
148 148 """Make the directory structure of all files below a starting dir.
149 149
150 150 This is just a convenience routine to help build a nested directory
151 151 hierarchy because distutils is too stupid to do this by itself.
152 152
153 153 XXX - this needs a proper docstring!
154 154 """
155 155
156 156 # we'll use these a lot below
157 157 lbase = len(base)
158 158 pathsep = os.path.sep
159 159 lpathsep = len(pathsep)
160 160
161 161 out = []
162 162 for (dirpath,dirnames,filenames) in os.walk(base):
163 163 # we need to strip out the dirpath from the base to map it to the
164 164 # output (installation) path. This requires possibly stripping the
165 165 # path separator, because otherwise pjoin will not work correctly
166 166 # (pjoin('foo/','/bar') returns '/bar').
167 167
168 168 dp_eff = dirpath[lbase:]
169 169 if dp_eff.startswith(pathsep):
170 170 dp_eff = dp_eff[lpathsep:]
171 171 # The output path must be anchored at the out_base marker
172 172 out_path = pjoin(out_base,dp_eff)
173 173 # Now we can generate the final filenames. Since os.walk only produces
174 174 # filenames, we must join back with the dirpath to get full valid file
175 175 # paths:
176 176 pfiles = [pjoin(dirpath,f) for f in filenames]
177 177 # Finally, generate the entry we need, which is a pari of (output
178 178 # path, files) for use as a data_files parameter in install_data.
179 179 out.append((out_path, pfiles))
180 180
181 181 return out
182 182
183 183
184 184 def find_data_files():
185 185 """
186 186 Find IPython's data_files.
187 187
188 188 Most of these are docs.
189 189 """
190 190
191 191 docdirbase = pjoin('share', 'doc', 'ipython')
192 192 manpagebase = pjoin('share', 'man', 'man1')
193 193
194 194 # Simple file lists can be made by hand
195 195 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
196 196 if not manpages:
197 197 # When running from a source tree, the manpages aren't gzipped
198 198 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
199 199 igridhelpfiles = filter(isfile,
200 200 glob(pjoin('IPython','extensions','igrid_help.*')))
201 201
202 202 # For nested structures, use the utility above
203 203 example_files = make_dir_struct(
204 204 'data',
205 205 pjoin('docs','examples'),
206 206 pjoin(docdirbase,'examples')
207 207 )
208 208 manual_files = make_dir_struct(
209 209 'data',
210 210 pjoin('docs','html'),
211 211 pjoin(docdirbase,'manual')
212 212 )
213 213
214 214 # And assemble the entire output list
215 215 data_files = [ (manpagebase, manpages),
216 216 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
217 217 ] + manual_files + example_files
218 218
219 219 return data_files
220 220
221 221
222 222 def make_man_update_target(manpage):
223 223 """Return a target_update-compliant tuple for the given manpage.
224 224
225 225 Parameters
226 226 ----------
227 227 manpage : string
228 228 Name of the manpage, must include the section number (trailing number).
229 229
230 230 Example
231 231 -------
232 232
233 233 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
234 234 ('docs/man/ipython.1.gz',
235 235 ['docs/man/ipython.1'],
236 236 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
237 237 """
238 238 man_dir = pjoin('docs', 'man')
239 239 manpage_gz = manpage + '.gz'
240 240 manpath = pjoin(man_dir, manpage)
241 241 manpath_gz = pjoin(man_dir, manpage_gz)
242 242 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
243 243 locals() )
244 244 return (manpath_gz, [manpath], gz_cmd)
245 245
246 246 #---------------------------------------------------------------------------
247 247 # Find scripts
248 248 #---------------------------------------------------------------------------
249 249
250 250 def find_scripts(entry_points=False, suffix=''):
251 251 """Find IPython's scripts.
252 252
253 253 if entry_points is True:
254 254 return setuptools entry_point-style definitions
255 255 else:
256 256 return file paths of plain scripts [default]
257 257
258 258 suffix is appended to script names if entry_points is True, so that the
259 259 Python 3 scripts get named "ipython3" etc.
260 260 """
261 261 if entry_points:
262 262 console_scripts = [s % suffix for s in [
263 263 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
264 264 'pycolor%s = IPython.utils.PyColorize:main',
265 265 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
266 266 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
267 267 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
268 268 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
269 269 'iptest%s = IPython.testing.iptest:main',
270 270 'irunner%s = IPython.lib.irunner:main'
271 271 ]]
272 272 gui_scripts = [s % suffix for s in [
273 273 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
274 274 ]]
275 275 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
276 276 else:
277 277 parallel_scripts = pjoin('IPython','parallel','scripts')
278 278 main_scripts = pjoin('IPython','scripts')
279 279 scripts = [
280 280 pjoin(parallel_scripts, 'ipengine'),
281 281 pjoin(parallel_scripts, 'ipcontroller'),
282 282 pjoin(parallel_scripts, 'ipcluster'),
283 283 pjoin(parallel_scripts, 'iplogger'),
284 284 pjoin(main_scripts, 'ipython'),
285 285 pjoin(main_scripts, 'pycolor'),
286 286 pjoin(main_scripts, 'irunner'),
287 287 pjoin(main_scripts, 'iptest')
288 288 ]
289 289 return scripts
290 290
291 291 #---------------------------------------------------------------------------
292 292 # Verify all dependencies
293 293 #---------------------------------------------------------------------------
294 294
295 295 def check_for_dependencies():
296 296 """Check for IPython's dependencies.
297 297
298 298 This function should NOT be called if running under setuptools!
299 299 """
300 300 from setupext.setupext import (
301 301 print_line, print_raw, print_status,
302 302 check_for_sphinx, check_for_pygments,
303 303 check_for_nose, check_for_pexpect,
304 304 check_for_pyzmq, check_for_readline
305 305 )
306 306 print_line()
307 307 print_raw("BUILDING IPYTHON")
308 308 print_status('python', sys.version)
309 309 print_status('platform', sys.platform)
310 310 if sys.platform == 'win32':
311 311 print_status('Windows version', sys.getwindowsversion())
312 312
313 313 print_raw("")
314 314 print_raw("OPTIONAL DEPENDENCIES")
315 315
316 316 check_for_sphinx()
317 317 check_for_pygments()
318 318 check_for_nose()
319 319 check_for_pexpect()
320 320 check_for_pyzmq()
321 321 check_for_readline()
322 322
323 323 def record_commit_info(pkg_dir, build_cmd=build_py):
324 324 """ Return extended build command class for recording commit
325 325
326 326 The extended command tries to run git to find the current commit, getting
327 327 the empty string if it fails. It then writes the commit hash into a file
328 328 in the `pkg_dir` path, named ``.git_commit_info.ini``.
329 329
330 330 In due course this information can be used by the package after it is
331 331 installed, to tell you what commit it was installed from if known.
332 332
333 333 To make use of this system, you need a package with a .git_commit_info.ini
334 334 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
335 335 this::
336 336
337 337 # This is an ini file that may contain information about the code state
338 338 [commit hash]
339 339 # The line below may contain a valid hash if it has been substituted
340 340 # during 'git archive'
341 341 archive_subst_hash=$Format:%h$
342 342 # This line may be modified by the install process
343 343 install_hash=
344 344
345 345 The .git_commit_info file above is also designed to be used with git
346 346 substitution - so you probably also want a ``.gitattributes`` file in the
347 347 root directory of your working tree that contains something like this::
348 348
349 349 myproject/.git_commit_info.ini export-subst
350 350
351 351 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
352 352 archive`` - useful in case someone makes such an archive - for example with
353 353 via the github 'download source' button.
354 354
355 355 Although all the above will work as is, you might consider having something
356 356 like a ``get_info()`` function in your package to display the commit
357 357 information at the terminal. See the ``pkg_info.py`` module in the nipy
358 358 package for an example.
359 359 """
360 360 class MyBuildPy(build_cmd):
361 361 ''' Subclass to write commit data into installation tree '''
362 362 def run(self):
363 363 build_cmd.run(self)
364 364 import subprocess
365 365 proc = subprocess.Popen('git rev-parse --short HEAD',
366 366 stdout=subprocess.PIPE,
367 367 stderr=subprocess.PIPE,
368 368 shell=True)
369 369 repo_commit, _ = proc.communicate()
370 370 # We write the installation commit even if it's empty
371 371 cfg_parser = ConfigParser()
372 372 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
373 373 if not cfg_parser.has_section('commit hash'):
374 374 # just in case the ini file is empty or doesn't exist, somehow
375 375 # we don't want the next line to raise
376 376 cfg_parser.add_section('commit hash')
377 377 cfg_parser.set('commit hash', 'install_hash', repo_commit.decode('ascii'))
378 378 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
379 379 out_file = open(out_pth, 'wt')
380 380 cfg_parser.write(out_file)
381 381 out_file.close()
382 382 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now