##// END OF EJS Templates
Merge 'XDG', introducing basic XDG_CONFIG_HOME support...
MinRK -
r3356:15ce9bf5 merge
parent child Browse files
Show More
@@ -105,7 +105,7 b' class Application(object):'
105 105 default_log_level = logging.WARN
106 106 #: Set by --profile option
107 107 profile_name = None
108 #: User's ipython directory, typically ~/.ipython/
108 #: User's ipython directory, typically ~/.ipython or ~/.config/ipython/
109 109 ipython_dir = None
110 110 #: Internal defaults, implemented in code.
111 111 default_config = None
@@ -395,7 +395,7 b" to 'mydir', if it exists."
395 395
396 396 You can define your own magic functions to extend the system. See the supplied
397 397 ipythonrc and example-magic.py files for details (in your ipython
398 configuration directory, typically $HOME/.ipython/).
398 configuration directory, typically $HOME/.config/ipython on Linux or $HOME/.ipython elsewhere).
399 399
400 400 You can also define your own aliased names for magic functions. In your
401 401 ipythonrc file, placing a line like:
@@ -30,9 +30,10 b' IPython: an enhanced interactive Python shell.'
30 30 command line, simply because they are not practical here. Look into your
31 31 ipython_config.py configuration file for details on those.
32 32
33 This file typically installed in the $HOME/.ipython directory. For Windows
34 users, $HOME resolves to C:\\Documents and Settings\\YourUserName in most
35 instances.
33 This file is typically installed in the IPYTHON_DIR directory. For Linux
34 users, this will be $HOME/.config/ipython, and for other users it will be
35 $HOME/.ipython. For Windows users, $HOME resolves to C:\\Documents and
36 Settings\\YourUserName in most instances.
36 37
37 38 In IPython's documentation, we will refer to this directory as IPYTHON_DIR,
38 39 you can change its default location by setting any path you want in this
@@ -186,7 +186,7 b' class ControllerService(object, service.Service):'
186 186 This method takes the assigned id, ip/port and pid of the engine
187 187 and saves it to a file of the form:
188 188
189 ~/.ipython/log/ipcontroller-###-engine-info.log
189 IPYTHON_DIR/log/ipcontroller-###-engine-info.log
190 190
191 191 where ### is the pid of the controller.
192 192
@@ -49,7 +49,7 b' The IPython controller provides a gateway between the IPython engines and'
49 49 clients. The controller needs to be started before the engines and can be
50 50 configured using command line options or using a cluster directory. Cluster
51 51 directories contain config, log and security files and are usually located in
52 your .ipython directory and named as "cluster_<profile>". See the --profile
52 your ipython directory and named as "cluster_<profile>". See the --profile
53 53 and --cluster-dir options for details.
54 54 """
55 55
@@ -60,7 +60,7 b' IPython engines run in parallel and perform computations on behalf of a client'
60 60 and controller. A controller needs to be started before the engines. The
61 61 engine can be configured using command line options or using a cluster
62 62 directory. Cluster directories contain config, log and security files and are
63 usually located in your .ipython directory and named as "cluster_<profile>".
63 usually located in your ipython directory and named as "cluster_<profile>".
64 64 See the --profile and --cluster-dir options for details.
65 65 """
66 66
@@ -246,6 +246,24 b' def get_home_dir():'
246 246 else:
247 247 raise HomeDirError('No valid home directory could be found for your OS')
248 248
249 def get_xdg_dir():
250 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
251
252 This is only for posix (Linux,Unix,OS X, etc) systems.
253 """
254
255 isdir = os.path.isdir
256 env = os.environ
257
258 if os.name == 'posix':
259 # Linux, Unix, AIX, OS X
260 # use ~/.config if not set OR empty
261 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
262 if xdg and isdir(xdg):
263 return xdg.decode(sys.getfilesystemencoding())
264
265 return None
266
249 267
250 268 def get_ipython_dir():
251 269 """Get the IPython directory for this platform and user.
@@ -253,14 +271,34 b' def get_ipython_dir():'
253 271 This uses the logic in `get_home_dir` to find the home directory
254 272 and the adds .ipython to the end of the path.
255 273 """
274
275 env = os.environ
276 pjoin = os.path.join
277 exists = os.path.exists
278
256 279 ipdir_def = '.ipython'
280 xdg_def = 'ipython'
281
257 282 home_dir = get_home_dir()
283 xdg_dir = get_xdg_dir()
258 284 # import pdb; pdb.set_trace() # dbg
259 ipdir = os.environ.get(
260 'IPYTHON_DIR', os.environ.get(
261 'IPYTHONDIR', os.path.join(home_dir, ipdir_def)
262 )
263 )
285 ipdir = env.get('IPYTHON_DIR', env.get('IPYTHONDIR', None))
286 if ipdir is None:
287 # not set explicitly, use XDG_CONFIG_HOME or HOME
288 home_ipdir = pjoin(home_dir, ipdir_def)
289 if xdg_dir:
290 # use XDG, as long as the user isn't already
291 # using $HOME/.ipython and *not* XDG/ipython
292
293 xdg_ipdir = pjoin(xdg_dir, xdg_def)
294
295 if exists(xdg_ipdir) or not exists(home_ipdir):
296 ipdir = xdg_ipdir
297
298 if ipdir is None:
299 # not using XDG
300 ipdir = home_ipdir
301
264 302 return ipdir.decode(sys.getfilesystemencoding())
265 303
266 304
@@ -46,6 +46,7 b' env = os.environ'
46 46 TEST_FILE_PATH = split(abspath(__file__))[0]
47 47 TMP_TEST_DIR = tempfile.mkdtemp()
48 48 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
49 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
49 50 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
50 51 #
51 52 # Setup/teardown functions/decorators
@@ -59,6 +60,7 b' def setup():'
59 60 # Do not mask exceptions here. In particular, catching WindowsError is a
60 61 # problem because that exception is only defined on Windows...
61 62 os.makedirs(IP_TEST_DIR)
63 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
62 64
63 65
64 66 def teardown():
@@ -236,9 +238,93 b' def test_get_ipython_dir_2():'
236 238 os.name = "posix"
237 239 env.pop('IPYTHON_DIR', None)
238 240 env.pop('IPYTHONDIR', None)
241 env.pop('XDG_CONFIG_HOME', None)
239 242 ipdir = path.get_ipython_dir()
240 243 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
241 244
245 @with_environment
246 def test_get_ipython_dir_3():
247 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
248 path.get_home_dir = lambda : "someplace"
249 os.name = "posix"
250 env.pop('IPYTHON_DIR', None)
251 env.pop('IPYTHONDIR', None)
252 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
253 ipdir = path.get_ipython_dir()
254 nt.assert_equal(ipdir, os.path.join(XDG_TEST_DIR, "ipython"))
255
256 @with_environment
257 def test_get_ipython_dir_4():
258 """test_get_ipython_dir_4, use XDG if both exist."""
259 path.get_home_dir = lambda : HOME_TEST_DIR
260 os.name = "posix"
261 env.pop('IPYTHON_DIR', None)
262 env.pop('IPYTHONDIR', None)
263 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
264 xdg_ipdir = os.path.join(XDG_TEST_DIR, "ipython")
265 ipdir = path.get_ipython_dir()
266 nt.assert_equal(ipdir, xdg_ipdir)
267
268 @with_environment
269 def test_get_ipython_dir_5():
270 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
271 os.name = "posix"
272 env.pop('IPYTHON_DIR', None)
273 env.pop('IPYTHONDIR', None)
274 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
275 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
276 ipdir = path.get_ipython_dir()
277 nt.assert_equal(ipdir, IP_TEST_DIR)
278
279 @with_environment
280 def test_get_ipython_dir_6():
281 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
282 path.get_home_dir = lambda : 'somehome'
283 path.get_xdg_dir = lambda : 'somexdg'
284 os.name = "posix"
285 env.pop('IPYTHON_DIR', None)
286 env.pop('IPYTHONDIR', None)
287 xdg_ipdir = os.path.join("somexdg", "ipython")
288 ipdir = path.get_ipython_dir()
289 nt.assert_equal(ipdir, xdg_ipdir)
290
291 @with_environment
292 def test_get_xdg_dir_1():
293 """test_get_xdg_dir_1, check xdg_dir"""
294 reload(path)
295 path.get_home_dir = lambda : 'somewhere'
296 os.name = "posix"
297 env.pop('IPYTHON_DIR', None)
298 env.pop('IPYTHONDIR', None)
299 env.pop('XDG_CONFIG_HOME', None)
300
301 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
302
303
304 @with_environment
305 def test_get_xdg_dir_1():
306 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
307 reload(path)
308 path.get_home_dir = lambda : HOME_TEST_DIR
309 os.name = "posix"
310 env.pop('IPYTHON_DIR', None)
311 env.pop('IPYTHONDIR', None)
312 env.pop('XDG_CONFIG_HOME', None)
313 nt.assert_equal(path.get_xdg_dir(), None)
314
315 @with_environment
316 def test_get_xdg_dir_2():
317 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
318 reload(path)
319 path.get_home_dir = lambda : HOME_TEST_DIR
320 os.name = "posix"
321 env.pop('IPYTHON_DIR', None)
322 env.pop('IPYTHONDIR', None)
323 env.pop('XDG_CONFIG_HOME', None)
324 cfgdir=os.path.join(path.get_home_dir(), '.config')
325 os.makedirs(cfgdir)
326
327 nt.assert_equal(path.get_xdg_dir(), cfgdir)
242 328
243 329 def test_filefind():
244 330 """Various tests for filefind"""
@@ -12,7 +12,8 b' Outdated configuration information that might still be useful'
12 12 This section will help you set various things in your environment for
13 13 your IPython sessions to be as efficient as possible. All of IPython's
14 14 configuration information, along with several example files, is stored
15 in a directory named by default $HOME/.ipython. You can change this by
15 in a directory named by default $HOME/.config/ipython if $HOME/.config
16 exists (Linux), or $HOME/.ipython as a secondary default. You can change this by
16 17 defining the environment variable IPYTHONDIR, or at runtime with the
17 18 command line option -ipythondir.
18 19
@@ -94,7 +95,7 b" sequences. You can go to a 'no color' mode by typing '%colors NoColor'."
94 95
95 96 You can try using a different terminal emulator program (Emacs users,
96 97 see below). To permanently set your color preferences, edit the file
97 $HOME/.ipython/ipythonrc and set the colors option to the desired value.
98 $IPYTHON_DIR/ipythonrc and set the colors option to the desired value.
98 99
99 100
100 101 Object details (types, docstrings, source code, etc.)
@@ -235,6 +235,9 b' This class hierarchy and configuration file accomplishes the following:'
235 235 configuration file. Because :class:`Foo` is the parent of :class:`Bar`
236 236 it doesn't know anything about the :attr:`othervalue` attribute.
237 237
238
239 .. _ipython_dir:
240
238 241 Configuration file location
239 242 ===========================
240 243
@@ -246,11 +249,19 b' this directory is determined by the following algorithm:'
246 249
247 250 * If not, the value returned by :func:`IPython.utils.path.get_ipython_dir`
248 251 is used. This function will first look at the :envvar:`IPYTHON_DIR`
249 environment variable and then default to the directory
250 :file:`$HOME/.ipython`.
252 environment variable and then default to a platform-specific default.
253
254 On posix systems (Linux, Unix, etc.), IPython respects the ``$XDG_CONFIG_HOME``
255 part of the `XDG Base Directory`_ specification. If ``$XDG_CONFIG_HOME`` is
256 defined and exists ( ``XDG_CONFIG_HOME`` has a default interpretation of
257 :file:`$HOME/.config`), then IPython's config directory will be located in
258 :file:`$XDG_CONFIG_HOME/ipython`. If users still have an IPython directory
259 in :file:`$HOME/.ipython`, then that will be used. in preference to the
260 system default.
251 261
252 262 For most users, the default value will simply be something like
253 :file:`$HOME/.ipython`.
263 :file:`$HOME/.config/ipython` on Linux, or :file:`$HOME/.ipython`
264 elsewhere.
254 265
255 266 Once the location of the IPython directory has been determined, you need to
256 267 know what filename to use for the configuration file. The basic idea is that
@@ -327,3 +338,5 b' Here are the main requirements we wanted our configuration system to have:'
327 338 dynamic language and you don't always know everything that needs to be
328 339 configured when a program starts.
329 340
341
342 .. _`XDG Base Directory`: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
@@ -51,7 +51,7 b' An interactive Python session::'
51 51
52 52 >>> from IPython.utils.path import get_ipython_dir
53 53 >>> get_ipython_dir()
54 '/home/fperez/.ipython'
54 '/home/fperez/.config/ipython'
55 55
56 56 An IPython session:
57 57
@@ -27,11 +27,12 b' file and ignore your configuration setup.'
27 27
28 28 Please note that some of the configuration options are not available at
29 29 the command line, simply because they are not practical here. Look into
30 your ipythonrc configuration file for details on those. This file
31 typically installed in the $HOME/.ipython directory. For Windows users,
32 $HOME resolves to C:\\Documents and Settings\\YourUserName in most
33 instances. In the rest of this text, we will refer to this directory as
34 IPYTHON_DIR.
30 your ipythonrc configuration file for details on those. This file is typically
31 installed in the IPYTHON_DIR directory. For Linux
32 users, this will be $HOME/.config/ipython, and for other users it will be
33 $HOME/.ipython. For Windows users, $HOME resolves to C:\\Documents and
34 Settings\\YourUserName in most instances.
35
35 36
36 37
37 38
@@ -218,9 +219,9 b' All options with a [no] prepended can be specified in negated form'
218 219 include this one and load extra things for particular
219 220 tasks. For example:
220 221
221 1. $HOME/.ipython/ipythonrc : load basic things you always want.
222 2. $HOME/.ipython/ipythonrc-math : load (1) and basic math-related modules.
223 3. $HOME/.ipython/ipythonrc-numeric : load (1) and Numeric and plotting modules.
222 1. $IPYTHON_DIR/ipythonrc : load basic things you always want.
223 2. $IPYTHON_DIR/ipythonrc-math : load (1) and basic math-related modules.
224 3. $IPYTHON_DIR/ipythonrc-numeric : load (1) and Numeric and plotting modules.
224 225
225 226 Since it is possible to create an endless loop by having
226 227 circular file inclusions, IPython will stop if it reaches 15
@@ -25,7 +25,7 b' the "pysh" shortcut in start menu.'
25 25 If you want to use the features of sh profile as your defaults (which
26 26 might be a good idea if you use other profiles a lot of the time but
27 27 still want the convenience of sh profile), add ``import ipy_profile_sh``
28 to your ~/.ipython/ipy_user_conf.py.
28 to your $IPYTHON_DIR/ipy_user_conf.py.
29 29
30 30 The 'sh' profile is different from the default profile in that:
31 31
@@ -138,13 +138,13 b' these keys are known as Foolscap URLs, or FURLs, because of the underlying'
138 138 network protocol we are using. As a user, you don't need to know anything
139 139 about the details of these FURLs, other than that when the controller starts,
140 140 it saves a set of FURLs to files named :file:`something.furl`. The default
141 location of these files is the :file:`~./ipython/security` directory.
141 location of these files is the :file:`$IPYTHON_DIR/cluster_<profile>/security` directory.
142 142
143 143 To connect and authenticate to the controller an engine or client simply needs
144 144 to present an appropriate FURL (that was originally created by the controller)
145 145 to the controller. Thus, the FURL files need to be copied to a location where
146 146 the clients and engines can find them. Typically, this is the
147 :file:`~./ipython/security` directory on the host where the client/engine is
147 :file:`$IPYTHON_DIR/cluster_<profile>/security` directory on the host where the client/engine is
148 148 running (which could be a different host than the controller). Once the FURL
149 149 files are copied over, everything should work fine.
150 150
@@ -212,7 +212,7 b' everything is working correctly, try the following commands:'
212 212 Remember, a client also needs to present a FURL file to the controller. How
213 213 does this happen? When a multiengine client is created with no arguments, the
214 214 client tries to find the corresponding FURL file in the local
215 :file:`~./ipython/security` directory. If it finds it, you are set. If you
215 :file:`$IPYTHON_DIR/cluster_<profile>/security` directory. If it finds it, you are set. If you
216 216 have put the FURL file in a different location or it has a different name,
217 217 create the client like this::
218 218
@@ -37,7 +37,7 b' and then create a :class:`MultiEngineClient` instance:'
37 37 In [2]: mec = client.MultiEngineClient()
38 38
39 39 This form assumes that the :file:`ipcontroller-mec.furl` is in the
40 :file:`~./ipython/security` directory on the client's host. If not, the
40 :file:`$IPYTHON_DIR/cluster_<profile>/security` directory on the client's host. If not, the
41 41 location of the FURL file must be given as an argument to the
42 42 constructor:
43 43
@@ -40,14 +40,14 b' hosts ``host1``-``hostn``. The following steps are then required:'
40 40
41 41 At this point, the controller and engines will be connected. By default, the
42 42 FURL files created by the controller are put into the
43 :file:`~/.ipython/security` directory. If the engines share a filesystem with
43 :file:`$IPYTHON_DIR/cluster_<profile>/security` directory. If the engines share a filesystem with
44 44 the controller, step 2 can be skipped as the engines will automatically look
45 45 at that location.
46 46
47 47 The final step required required to actually use the running controller from a
48 48 client is to move the FURL files :file:`ipcontroller-mec.furl` and
49 49 :file:`ipcontroller-tc.furl` from ``host0`` to the host where the clients will
50 be run. If these file are put into the :file:`~/.ipython/security` directory
50 be run. If these file are put into the :file:`$IPYTHON_DIR/cluster_<profile>/security` directory
51 51 of the client's host, they will be found automatically. Otherwise, the full
52 52 path to them has to be passed to the client's constructor.
53 53
@@ -74,7 +74,7 b' controller and engines in the following situations:'
74 74 .. note::
75 75
76 76 Currently :command:`ipcluster` requires that the
77 :file:`~/.ipython/security` directory live on a shared filesystem that is
77 :file:`$IPYTHON_DIR/cluster_<profile>/security` directory live on a shared filesystem that is
78 78 seen by both the controller and engines. If you don't have a shared file
79 79 system you will need to use :command:`ipcontroller` and
80 80 :command:`ipengine` directly. This constraint can be relaxed if you are
@@ -289,7 +289,7 b' the command::'
289 289 $ ipengine
290 290
291 291 The engines should start and automatically connect to the controller using the
292 FURL files in :file:`~./ipython/security`. You are now ready to use the
292 FURL files in :file:`$IPYTHON_DIR/cluster_<profile>/security`. You are now ready to use the
293 293 controller and engines from IPython.
294 294
295 295 .. warning::
@@ -312,7 +312,7 b' When the controller and engines are running on different hosts, things are'
312 312 slightly more complicated, but the underlying ideas are the same:
313 313
314 314 1. Start the controller on a host using :command:`ipcontroller`.
315 2. Copy :file:`ipcontroller-engine.furl` from :file:`~./ipython/security` on
315 2. Copy :file:`ipcontroller-engine.furl` from :file:`$IPYTHON_DIR/cluster_<profile>/security` on
316 316 the controller's host to the host where the engines will run.
317 317 3. Use :command:`ipengine` on the engine's hosts to start the engines.
318 318
@@ -320,7 +320,7 b' The only thing you have to be careful of is to tell :command:`ipengine` where'
320 320 the :file:`ipcontroller-engine.furl` file is located. There are two ways you
321 321 can do this:
322 322
323 * Put :file:`ipcontroller-engine.furl` in the :file:`~./ipython/security`
323 * Put :file:`ipcontroller-engine.furl` in the :file:`$IPYTHON_DIR/cluster_<profile>/security`
324 324 directory on the engine's host, where it will be found automatically.
325 325 * Call :command:`ipengine` with the ``--furl-file=full_path_to_the_file``
326 326 flag.
@@ -332,7 +332,7 b' The ``--furl-file`` flag works like this::'
332 332 .. note::
333 333
334 334 If the controller's and engine's hosts all have a shared file system
335 (:file:`~./ipython/security` is the same on all of them), then things
335 (:file:`$IPYTHON_DIR/cluster_<profile>/security` is the same on all of them), then things
336 336 will just work!
337 337
338 338 Make FURL files persistent
@@ -346,7 +346,7 b' to be able to create the key (or FURL file) once, and then simply use it at'
346 346 any point in the future.
347 347
348 348 This is possible, but before you do this, you **must** remove any old FURL
349 files in the :file:`~/.ipython/security` directory.
349 files in the :file:`$IPYTHON_DIR/cluster_<profile>/security` directory.
350 350
351 351 .. warning::
352 352
@@ -379,7 +379,7 b' Log files'
379 379
380 380 All of the components of IPython have log files associated with them.
381 381 These log files can be extremely useful in debugging problems with
382 IPython and can be found in the directory :file:`~/.ipython/log`. Sending
382 IPython and can be found in the directory :file:`$IPYTHON_DIR/cluster_<profile>/log`. Sending
383 383 the log files to us will often help us to debug any problems.
384 384
385 385
@@ -117,7 +117,7 b' controller creates a number of FURLs for different purposes:'
117 117 to execute.
118 118
119 119 Upon starting, the controller creates these different FURLS and writes them
120 files in the user-read-only directory :file:`$HOME/.ipython/security`. Thus,
120 files in the user-read-only directory :file:`$IPYTHON_DIR/cluster_default/security`. Thus,
121 121 only the user who starts the controller has access to the FURLs.
122 122
123 123 For an IPython client or engine to authenticate with a controller, it must
@@ -41,7 +41,7 b' and then create a :class:`TaskClient` instance:'
41 41 In [2]: tc = client.TaskClient()
42 42
43 43 This form assumes that the :file:`ipcontroller-tc.furl` is in the
44 :file:`~./ipython/security` directory on the client's host. If not, the
44 :file:`$IPYTHON_DIR/cluster_<profile>/security` directory on the client's host. If not, the
45 45 location of the FURL file must be given as an argument to the
46 46 constructor:
47 47
General Comments 0
You need to be logged in to leave comments. Login now