##// END OF EJS Templates
remove the function unicode_to_str as in python3 it has become redundant
Srinivas Reddy Thatiparthy -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,57 +1,57 b''
1 """Support for interactive macros in IPython"""
1 """Support for interactive macros in IPython"""
2
2
3 #*****************************************************************************
3 #*****************************************************************************
4 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
4 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
5 #
5 #
6 # Distributed under the terms of the BSD License. The full license is in
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
7 # the file COPYING, distributed as part of this software.
8 #*****************************************************************************
8 #*****************************************************************************
9
9
10 import re
10 import re
11
11
12 from IPython.utils import py3compat
12 from IPython.utils import py3compat
13 from IPython.utils.encoding import DEFAULT_ENCODING
13 from IPython.utils.encoding import DEFAULT_ENCODING
14
14
15 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
15 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
16
16
17 class Macro(object):
17 class Macro(object):
18 """Simple class to store the value of macros as strings.
18 """Simple class to store the value of macros as strings.
19
19
20 Macro is just a callable that executes a string of IPython
20 Macro is just a callable that executes a string of IPython
21 input when called.
21 input when called.
22 """
22 """
23
23
24 def __init__(self,code):
24 def __init__(self,code):
25 """store the macro value, as a single string which can be executed"""
25 """store the macro value, as a single string which can be executed"""
26 lines = []
26 lines = []
27 enc = None
27 enc = None
28 for line in code.splitlines():
28 for line in code.splitlines():
29 coding_match = coding_declaration.match(line)
29 coding_match = coding_declaration.match(line)
30 if coding_match:
30 if coding_match:
31 enc = coding_match.group(1)
31 enc = coding_match.group(1)
32 else:
32 else:
33 lines.append(line)
33 lines.append(line)
34 code = "\n".join(lines)
34 code = "\n".join(lines)
35 if isinstance(code, bytes):
35 if isinstance(code, bytes):
36 code = code.decode(enc or DEFAULT_ENCODING)
36 code = code.decode(enc or DEFAULT_ENCODING)
37 self.value = code + '\n'
37 self.value = code + '\n'
38
38
39 def __str__(self):
39 def __str__(self):
40 return py3compat.unicode_to_str(self.value)
40 return self.value
41
41
42 def __unicode__(self):
42 def __unicode__(self):
43 return self.value
43 return self.value
44
44
45 def __repr__(self):
45 def __repr__(self):
46 return 'IPython.macro.Macro(%s)' % repr(self.value)
46 return 'IPython.macro.Macro(%s)' % repr(self.value)
47
47
48 def __getstate__(self):
48 def __getstate__(self):
49 """ needed for safe pickling via %store """
49 """ needed for safe pickling via %store """
50 return {'value': self.value}
50 return {'value': self.value}
51
51
52 def __add__(self, other):
52 def __add__(self, other):
53 if isinstance(other, Macro):
53 if isinstance(other, Macro):
54 return Macro(self.value + other.value)
54 return Macro(self.value + other.value)
55 elif isinstance(other, str):
55 elif isinstance(other, str):
56 return Macro(self.value + other)
56 return Macro(self.value + other)
57 raise TypeError
57 raise TypeError
@@ -1,74 +1,74 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for IPython.core.application"""
2 """Tests for IPython.core.application"""
3
3
4 import os
4 import os
5 import tempfile
5 import tempfile
6
6
7 import nose.tools as nt
7 import nose.tools as nt
8
8
9 from traitlets import Unicode
9 from traitlets import Unicode
10
10
11 from IPython.core.application import BaseIPythonApplication
11 from IPython.core.application import BaseIPythonApplication
12 from IPython.testing import decorators as dec
12 from IPython.testing import decorators as dec
13 from IPython.utils import py3compat
13 from IPython.utils import py3compat
14 from IPython.utils.tempdir import TemporaryDirectory
14 from IPython.utils.tempdir import TemporaryDirectory
15
15
16
16
17 @dec.onlyif_unicode_paths
17 @dec.onlyif_unicode_paths
18 def test_unicode_cwd():
18 def test_unicode_cwd():
19 """Check that IPython starts with non-ascii characters in the path."""
19 """Check that IPython starts with non-ascii characters in the path."""
20 wd = tempfile.mkdtemp(suffix=u"€")
20 wd = tempfile.mkdtemp(suffix=u"€")
21
21
22 old_wd = py3compat.getcwd()
22 old_wd = py3compat.getcwd()
23 os.chdir(wd)
23 os.chdir(wd)
24 #raise Exception(repr(py3compat.getcwd()))
24 #raise Exception(repr(py3compat.getcwd()))
25 try:
25 try:
26 app = BaseIPythonApplication()
26 app = BaseIPythonApplication()
27 # The lines below are copied from Application.initialize()
27 # The lines below are copied from Application.initialize()
28 app.init_profile_dir()
28 app.init_profile_dir()
29 app.init_config_files()
29 app.init_config_files()
30 app.load_config_file(suppress_errors=False)
30 app.load_config_file(suppress_errors=False)
31 finally:
31 finally:
32 os.chdir(old_wd)
32 os.chdir(old_wd)
33
33
34 @dec.onlyif_unicode_paths
34 @dec.onlyif_unicode_paths
35 def test_unicode_ipdir():
35 def test_unicode_ipdir():
36 """Check that IPython starts with non-ascii characters in the IP dir."""
36 """Check that IPython starts with non-ascii characters in the IP dir."""
37 ipdir = tempfile.mkdtemp(suffix=u"€")
37 ipdir = tempfile.mkdtemp(suffix=u"€")
38
38
39 # Create the config file, so it tries to load it.
39 # Create the config file, so it tries to load it.
40 with open(os.path.join(ipdir, 'ipython_config.py'), "w") as f:
40 with open(os.path.join(ipdir, 'ipython_config.py'), "w") as f:
41 pass
41 pass
42
42
43 old_ipdir1 = os.environ.pop("IPYTHONDIR", None)
43 old_ipdir1 = os.environ.pop("IPYTHONDIR", None)
44 old_ipdir2 = os.environ.pop("IPYTHON_DIR", None)
44 old_ipdir2 = os.environ.pop("IPYTHON_DIR", None)
45 os.environ["IPYTHONDIR"] = py3compat.unicode_to_str(ipdir, "utf-8")
45 os.environ["IPYTHONDIR"] = ipdir
46 try:
46 try:
47 app = BaseIPythonApplication()
47 app = BaseIPythonApplication()
48 # The lines below are copied from Application.initialize()
48 # The lines below are copied from Application.initialize()
49 app.init_profile_dir()
49 app.init_profile_dir()
50 app.init_config_files()
50 app.init_config_files()
51 app.load_config_file(suppress_errors=False)
51 app.load_config_file(suppress_errors=False)
52 finally:
52 finally:
53 if old_ipdir1:
53 if old_ipdir1:
54 os.environ["IPYTHONDIR"] = old_ipdir1
54 os.environ["IPYTHONDIR"] = old_ipdir1
55 if old_ipdir2:
55 if old_ipdir2:
56 os.environ["IPYTHONDIR"] = old_ipdir2
56 os.environ["IPYTHONDIR"] = old_ipdir2
57
57
58 def test_cli_priority():
58 def test_cli_priority():
59 with TemporaryDirectory() as td:
59 with TemporaryDirectory() as td:
60
60
61 class TestApp(BaseIPythonApplication):
61 class TestApp(BaseIPythonApplication):
62 test = Unicode().tag(config=True)
62 test = Unicode().tag(config=True)
63
63
64 # Create the config file, so it tries to load it.
64 # Create the config file, so it tries to load it.
65 with open(os.path.join(td, 'ipython_config.py'), "w") as f:
65 with open(os.path.join(td, 'ipython_config.py'), "w") as f:
66 f.write("c.TestApp.test = 'config file'")
66 f.write("c.TestApp.test = 'config file'")
67
67
68 app = TestApp()
68 app = TestApp()
69 app.initialize(['--profile-dir', td])
69 app.initialize(['--profile-dir', td])
70 nt.assert_equal(app.test, 'config file')
70 nt.assert_equal(app.test, 'config file')
71 app = TestApp()
71 app = TestApp()
72 app.initialize(['--profile-dir', td, '--TestApp.test=cli'])
72 app.initialize(['--profile-dir', td, '--TestApp.test=cli'])
73 nt.assert_equal(app.test, 'cli')
73 nt.assert_equal(app.test, 'cli')
74
74
@@ -1,447 +1,447 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for path handling.
3 Utilities for path handling.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 import os
9 import os
10 import sys
10 import sys
11 import errno
11 import errno
12 import shutil
12 import shutil
13 import random
13 import random
14 import glob
14 import glob
15 from warnings import warn
15 from warnings import warn
16 from hashlib import md5
16 from hashlib import md5
17
17
18 from IPython.utils.process import system
18 from IPython.utils.process import system
19 from IPython.utils import py3compat
19 from IPython.utils import py3compat
20 from IPython.utils.decorators import undoc
20 from IPython.utils.decorators import undoc
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Code
23 # Code
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 fs_encoding = sys.getfilesystemencoding()
26 fs_encoding = sys.getfilesystemencoding()
27
27
28 def _writable_dir(path):
28 def _writable_dir(path):
29 """Whether `path` is a directory, to which the user has write access."""
29 """Whether `path` is a directory, to which the user has write access."""
30 return os.path.isdir(path) and os.access(path, os.W_OK)
30 return os.path.isdir(path) and os.access(path, os.W_OK)
31
31
32 if sys.platform == 'win32':
32 if sys.platform == 'win32':
33 def _get_long_path_name(path):
33 def _get_long_path_name(path):
34 """Get a long path name (expand ~) on Windows using ctypes.
34 """Get a long path name (expand ~) on Windows using ctypes.
35
35
36 Examples
36 Examples
37 --------
37 --------
38
38
39 >>> get_long_path_name('c:\\docume~1')
39 >>> get_long_path_name('c:\\docume~1')
40 u'c:\\\\Documents and Settings'
40 u'c:\\\\Documents and Settings'
41
41
42 """
42 """
43 try:
43 try:
44 import ctypes
44 import ctypes
45 except ImportError:
45 except ImportError:
46 raise ImportError('you need to have ctypes installed for this to work')
46 raise ImportError('you need to have ctypes installed for this to work')
47 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
47 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
48 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
48 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
49 ctypes.c_uint ]
49 ctypes.c_uint ]
50
50
51 buf = ctypes.create_unicode_buffer(260)
51 buf = ctypes.create_unicode_buffer(260)
52 rv = _GetLongPathName(path, buf, 260)
52 rv = _GetLongPathName(path, buf, 260)
53 if rv == 0 or rv > 260:
53 if rv == 0 or rv > 260:
54 return path
54 return path
55 else:
55 else:
56 return buf.value
56 return buf.value
57 else:
57 else:
58 def _get_long_path_name(path):
58 def _get_long_path_name(path):
59 """Dummy no-op."""
59 """Dummy no-op."""
60 return path
60 return path
61
61
62
62
63
63
64 def get_long_path_name(path):
64 def get_long_path_name(path):
65 """Expand a path into its long form.
65 """Expand a path into its long form.
66
66
67 On Windows this expands any ~ in the paths. On other platforms, it is
67 On Windows this expands any ~ in the paths. On other platforms, it is
68 a null operation.
68 a null operation.
69 """
69 """
70 return _get_long_path_name(path)
70 return _get_long_path_name(path)
71
71
72
72
73 def unquote_filename(name, win32=(sys.platform=='win32')):
73 def unquote_filename(name, win32=(sys.platform=='win32')):
74 """ On Windows, remove leading and trailing quotes from filenames.
74 """ On Windows, remove leading and trailing quotes from filenames.
75
75
76 This function has been deprecated and should not be used any more:
76 This function has been deprecated and should not be used any more:
77 unquoting is now taken care of by :func:`IPython.utils.process.arg_split`.
77 unquoting is now taken care of by :func:`IPython.utils.process.arg_split`.
78 """
78 """
79 warn("'unquote_filename' is deprecated since IPython 5.0 and should not "
79 warn("'unquote_filename' is deprecated since IPython 5.0 and should not "
80 "be used anymore", DeprecationWarning, stacklevel=2)
80 "be used anymore", DeprecationWarning, stacklevel=2)
81 if win32:
81 if win32:
82 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
82 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
83 name = name[1:-1]
83 name = name[1:-1]
84 return name
84 return name
85
85
86
86
87 def compress_user(path):
87 def compress_user(path):
88 """Reverse of :func:`os.path.expanduser`
88 """Reverse of :func:`os.path.expanduser`
89 """
89 """
90 path = py3compat.unicode_to_str(path, sys.getfilesystemencoding())
90 path = str(path)
91 home = os.path.expanduser('~')
91 home = os.path.expanduser('~')
92 if path.startswith(home):
92 if path.startswith(home):
93 path = "~" + path[len(home):]
93 path = "~" + path[len(home):]
94 return path
94 return path
95
95
96 def get_py_filename(name, force_win32=None):
96 def get_py_filename(name, force_win32=None):
97 """Return a valid python filename in the current directory.
97 """Return a valid python filename in the current directory.
98
98
99 If the given name is not a file, it adds '.py' and searches again.
99 If the given name is not a file, it adds '.py' and searches again.
100 Raises IOError with an informative message if the file isn't found.
100 Raises IOError with an informative message if the file isn't found.
101 """
101 """
102
102
103 name = os.path.expanduser(name)
103 name = os.path.expanduser(name)
104 if force_win32 is not None:
104 if force_win32 is not None:
105 warn("The 'force_win32' argument to 'get_py_filename' is deprecated "
105 warn("The 'force_win32' argument to 'get_py_filename' is deprecated "
106 "since IPython 5.0 and should not be used anymore",
106 "since IPython 5.0 and should not be used anymore",
107 DeprecationWarning, stacklevel=2)
107 DeprecationWarning, stacklevel=2)
108 if not os.path.isfile(name) and not name.endswith('.py'):
108 if not os.path.isfile(name) and not name.endswith('.py'):
109 name += '.py'
109 name += '.py'
110 if os.path.isfile(name):
110 if os.path.isfile(name):
111 return name
111 return name
112 else:
112 else:
113 raise IOError('File `%r` not found.' % name)
113 raise IOError('File `%r` not found.' % name)
114
114
115
115
116 def filefind(filename, path_dirs=None):
116 def filefind(filename, path_dirs=None):
117 """Find a file by looking through a sequence of paths.
117 """Find a file by looking through a sequence of paths.
118
118
119 This iterates through a sequence of paths looking for a file and returns
119 This iterates through a sequence of paths looking for a file and returns
120 the full, absolute path of the first occurence of the file. If no set of
120 the full, absolute path of the first occurence of the file. If no set of
121 path dirs is given, the filename is tested as is, after running through
121 path dirs is given, the filename is tested as is, after running through
122 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
122 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
123
123
124 filefind('myfile.txt')
124 filefind('myfile.txt')
125
125
126 will find the file in the current working dir, but::
126 will find the file in the current working dir, but::
127
127
128 filefind('~/myfile.txt')
128 filefind('~/myfile.txt')
129
129
130 Will find the file in the users home directory. This function does not
130 Will find the file in the users home directory. This function does not
131 automatically try any paths, such as the cwd or the user's home directory.
131 automatically try any paths, such as the cwd or the user's home directory.
132
132
133 Parameters
133 Parameters
134 ----------
134 ----------
135 filename : str
135 filename : str
136 The filename to look for.
136 The filename to look for.
137 path_dirs : str, None or sequence of str
137 path_dirs : str, None or sequence of str
138 The sequence of paths to look for the file in. If None, the filename
138 The sequence of paths to look for the file in. If None, the filename
139 need to be absolute or be in the cwd. If a string, the string is
139 need to be absolute or be in the cwd. If a string, the string is
140 put into a sequence and the searched. If a sequence, walk through
140 put into a sequence and the searched. If a sequence, walk through
141 each element and join with ``filename``, calling :func:`expandvars`
141 each element and join with ``filename``, calling :func:`expandvars`
142 and :func:`expanduser` before testing for existence.
142 and :func:`expanduser` before testing for existence.
143
143
144 Returns
144 Returns
145 -------
145 -------
146 Raises :exc:`IOError` or returns absolute path to file.
146 Raises :exc:`IOError` or returns absolute path to file.
147 """
147 """
148
148
149 # If paths are quoted, abspath gets confused, strip them...
149 # If paths are quoted, abspath gets confused, strip them...
150 filename = filename.strip('"').strip("'")
150 filename = filename.strip('"').strip("'")
151 # If the input is an absolute path, just check it exists
151 # If the input is an absolute path, just check it exists
152 if os.path.isabs(filename) and os.path.isfile(filename):
152 if os.path.isabs(filename) and os.path.isfile(filename):
153 return filename
153 return filename
154
154
155 if path_dirs is None:
155 if path_dirs is None:
156 path_dirs = ("",)
156 path_dirs = ("",)
157 elif isinstance(path_dirs, str):
157 elif isinstance(path_dirs, str):
158 path_dirs = (path_dirs,)
158 path_dirs = (path_dirs,)
159
159
160 for path in path_dirs:
160 for path in path_dirs:
161 if path == '.': path = py3compat.getcwd()
161 if path == '.': path = py3compat.getcwd()
162 testname = expand_path(os.path.join(path, filename))
162 testname = expand_path(os.path.join(path, filename))
163 if os.path.isfile(testname):
163 if os.path.isfile(testname):
164 return os.path.abspath(testname)
164 return os.path.abspath(testname)
165
165
166 raise IOError("File %r does not exist in any of the search paths: %r" %
166 raise IOError("File %r does not exist in any of the search paths: %r" %
167 (filename, path_dirs) )
167 (filename, path_dirs) )
168
168
169
169
170 class HomeDirError(Exception):
170 class HomeDirError(Exception):
171 pass
171 pass
172
172
173
173
174 def get_home_dir(require_writable=False):
174 def get_home_dir(require_writable=False):
175 """Return the 'home' directory, as a unicode string.
175 """Return the 'home' directory, as a unicode string.
176
176
177 Uses os.path.expanduser('~'), and checks for writability.
177 Uses os.path.expanduser('~'), and checks for writability.
178
178
179 See stdlib docs for how this is determined.
179 See stdlib docs for how this is determined.
180 $HOME is first priority on *ALL* platforms.
180 $HOME is first priority on *ALL* platforms.
181
181
182 Parameters
182 Parameters
183 ----------
183 ----------
184
184
185 require_writable : bool [default: False]
185 require_writable : bool [default: False]
186 if True:
186 if True:
187 guarantees the return value is a writable directory, otherwise
187 guarantees the return value is a writable directory, otherwise
188 raises HomeDirError
188 raises HomeDirError
189 if False:
189 if False:
190 The path is resolved, but it is not guaranteed to exist or be writable.
190 The path is resolved, but it is not guaranteed to exist or be writable.
191 """
191 """
192
192
193 homedir = os.path.expanduser('~')
193 homedir = os.path.expanduser('~')
194 # Next line will make things work even when /home/ is a symlink to
194 # Next line will make things work even when /home/ is a symlink to
195 # /usr/home as it is on FreeBSD, for example
195 # /usr/home as it is on FreeBSD, for example
196 homedir = os.path.realpath(homedir)
196 homedir = os.path.realpath(homedir)
197
197
198 if not _writable_dir(homedir) and os.name == 'nt':
198 if not _writable_dir(homedir) and os.name == 'nt':
199 # expanduser failed, use the registry to get the 'My Documents' folder.
199 # expanduser failed, use the registry to get the 'My Documents' folder.
200 try:
200 try:
201 try:
201 try:
202 import winreg as wreg # Py 3
202 import winreg as wreg # Py 3
203 except ImportError:
203 except ImportError:
204 import _winreg as wreg # Py 2
204 import _winreg as wreg # Py 2
205 key = wreg.OpenKey(
205 key = wreg.OpenKey(
206 wreg.HKEY_CURRENT_USER,
206 wreg.HKEY_CURRENT_USER,
207 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
207 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
208 )
208 )
209 homedir = wreg.QueryValueEx(key,'Personal')[0]
209 homedir = wreg.QueryValueEx(key,'Personal')[0]
210 key.Close()
210 key.Close()
211 except:
211 except:
212 pass
212 pass
213
213
214 if (not require_writable) or _writable_dir(homedir):
214 if (not require_writable) or _writable_dir(homedir):
215 return py3compat.cast_unicode(homedir, fs_encoding)
215 return py3compat.cast_unicode(homedir, fs_encoding)
216 else:
216 else:
217 raise HomeDirError('%s is not a writable dir, '
217 raise HomeDirError('%s is not a writable dir, '
218 'set $HOME environment variable to override' % homedir)
218 'set $HOME environment variable to override' % homedir)
219
219
220 def get_xdg_dir():
220 def get_xdg_dir():
221 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
221 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
222
222
223 This is only for non-OS X posix (Linux,Unix,etc.) systems.
223 This is only for non-OS X posix (Linux,Unix,etc.) systems.
224 """
224 """
225
225
226 env = os.environ
226 env = os.environ
227
227
228 if os.name == 'posix' and sys.platform != 'darwin':
228 if os.name == 'posix' and sys.platform != 'darwin':
229 # Linux, Unix, AIX, etc.
229 # Linux, Unix, AIX, etc.
230 # use ~/.config if empty OR not set
230 # use ~/.config if empty OR not set
231 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
231 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
232 if xdg and _writable_dir(xdg):
232 if xdg and _writable_dir(xdg):
233 return py3compat.cast_unicode(xdg, fs_encoding)
233 return py3compat.cast_unicode(xdg, fs_encoding)
234
234
235 return None
235 return None
236
236
237
237
238 def get_xdg_cache_dir():
238 def get_xdg_cache_dir():
239 """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
239 """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
240
240
241 This is only for non-OS X posix (Linux,Unix,etc.) systems.
241 This is only for non-OS X posix (Linux,Unix,etc.) systems.
242 """
242 """
243
243
244 env = os.environ
244 env = os.environ
245
245
246 if os.name == 'posix' and sys.platform != 'darwin':
246 if os.name == 'posix' and sys.platform != 'darwin':
247 # Linux, Unix, AIX, etc.
247 # Linux, Unix, AIX, etc.
248 # use ~/.cache if empty OR not set
248 # use ~/.cache if empty OR not set
249 xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
249 xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
250 if xdg and _writable_dir(xdg):
250 if xdg and _writable_dir(xdg):
251 return py3compat.cast_unicode(xdg, fs_encoding)
251 return py3compat.cast_unicode(xdg, fs_encoding)
252
252
253 return None
253 return None
254
254
255
255
256 @undoc
256 @undoc
257 def get_ipython_dir():
257 def get_ipython_dir():
258 warn("get_ipython_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
258 warn("get_ipython_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
259 from IPython.paths import get_ipython_dir
259 from IPython.paths import get_ipython_dir
260 return get_ipython_dir()
260 return get_ipython_dir()
261
261
262 @undoc
262 @undoc
263 def get_ipython_cache_dir():
263 def get_ipython_cache_dir():
264 warn("get_ipython_cache_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
264 warn("get_ipython_cache_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
265 from IPython.paths import get_ipython_cache_dir
265 from IPython.paths import get_ipython_cache_dir
266 return get_ipython_cache_dir()
266 return get_ipython_cache_dir()
267
267
268 @undoc
268 @undoc
269 def get_ipython_package_dir():
269 def get_ipython_package_dir():
270 warn("get_ipython_package_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
270 warn("get_ipython_package_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
271 from IPython.paths import get_ipython_package_dir
271 from IPython.paths import get_ipython_package_dir
272 return get_ipython_package_dir()
272 return get_ipython_package_dir()
273
273
274 @undoc
274 @undoc
275 def get_ipython_module_path(module_str):
275 def get_ipython_module_path(module_str):
276 warn("get_ipython_module_path has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
276 warn("get_ipython_module_path has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
277 from IPython.paths import get_ipython_module_path
277 from IPython.paths import get_ipython_module_path
278 return get_ipython_module_path(module_str)
278 return get_ipython_module_path(module_str)
279
279
280 @undoc
280 @undoc
281 def locate_profile(profile='default'):
281 def locate_profile(profile='default'):
282 warn("locate_profile has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
282 warn("locate_profile has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
283 from IPython.paths import locate_profile
283 from IPython.paths import locate_profile
284 return locate_profile(profile=profile)
284 return locate_profile(profile=profile)
285
285
286 def expand_path(s):
286 def expand_path(s):
287 """Expand $VARS and ~names in a string, like a shell
287 """Expand $VARS and ~names in a string, like a shell
288
288
289 :Examples:
289 :Examples:
290
290
291 In [2]: os.environ['FOO']='test'
291 In [2]: os.environ['FOO']='test'
292
292
293 In [3]: expand_path('variable FOO is $FOO')
293 In [3]: expand_path('variable FOO is $FOO')
294 Out[3]: 'variable FOO is test'
294 Out[3]: 'variable FOO is test'
295 """
295 """
296 # This is a pretty subtle hack. When expand user is given a UNC path
296 # This is a pretty subtle hack. When expand user is given a UNC path
297 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
297 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
298 # the $ to get (\\server\share\%username%). I think it considered $
298 # the $ to get (\\server\share\%username%). I think it considered $
299 # alone an empty var. But, we need the $ to remains there (it indicates
299 # alone an empty var. But, we need the $ to remains there (it indicates
300 # a hidden share).
300 # a hidden share).
301 if os.name=='nt':
301 if os.name=='nt':
302 s = s.replace('$\\', 'IPYTHON_TEMP')
302 s = s.replace('$\\', 'IPYTHON_TEMP')
303 s = os.path.expandvars(os.path.expanduser(s))
303 s = os.path.expandvars(os.path.expanduser(s))
304 if os.name=='nt':
304 if os.name=='nt':
305 s = s.replace('IPYTHON_TEMP', '$\\')
305 s = s.replace('IPYTHON_TEMP', '$\\')
306 return s
306 return s
307
307
308
308
309 def unescape_glob(string):
309 def unescape_glob(string):
310 """Unescape glob pattern in `string`."""
310 """Unescape glob pattern in `string`."""
311 def unescape(s):
311 def unescape(s):
312 for pattern in '*[]!?':
312 for pattern in '*[]!?':
313 s = s.replace(r'\{0}'.format(pattern), pattern)
313 s = s.replace(r'\{0}'.format(pattern), pattern)
314 return s
314 return s
315 return '\\'.join(map(unescape, string.split('\\\\')))
315 return '\\'.join(map(unescape, string.split('\\\\')))
316
316
317
317
318 def shellglob(args):
318 def shellglob(args):
319 """
319 """
320 Do glob expansion for each element in `args` and return a flattened list.
320 Do glob expansion for each element in `args` and return a flattened list.
321
321
322 Unmatched glob pattern will remain as-is in the returned list.
322 Unmatched glob pattern will remain as-is in the returned list.
323
323
324 """
324 """
325 expanded = []
325 expanded = []
326 # Do not unescape backslash in Windows as it is interpreted as
326 # Do not unescape backslash in Windows as it is interpreted as
327 # path separator:
327 # path separator:
328 unescape = unescape_glob if sys.platform != 'win32' else lambda x: x
328 unescape = unescape_glob if sys.platform != 'win32' else lambda x: x
329 for a in args:
329 for a in args:
330 expanded.extend(glob.glob(a) or [unescape(a)])
330 expanded.extend(glob.glob(a) or [unescape(a)])
331 return expanded
331 return expanded
332
332
333
333
334 def target_outdated(target,deps):
334 def target_outdated(target,deps):
335 """Determine whether a target is out of date.
335 """Determine whether a target is out of date.
336
336
337 target_outdated(target,deps) -> 1/0
337 target_outdated(target,deps) -> 1/0
338
338
339 deps: list of filenames which MUST exist.
339 deps: list of filenames which MUST exist.
340 target: single filename which may or may not exist.
340 target: single filename which may or may not exist.
341
341
342 If target doesn't exist or is older than any file listed in deps, return
342 If target doesn't exist or is older than any file listed in deps, return
343 true, otherwise return false.
343 true, otherwise return false.
344 """
344 """
345 try:
345 try:
346 target_time = os.path.getmtime(target)
346 target_time = os.path.getmtime(target)
347 except os.error:
347 except os.error:
348 return 1
348 return 1
349 for dep in deps:
349 for dep in deps:
350 dep_time = os.path.getmtime(dep)
350 dep_time = os.path.getmtime(dep)
351 if dep_time > target_time:
351 if dep_time > target_time:
352 #print "For target",target,"Dep failed:",dep # dbg
352 #print "For target",target,"Dep failed:",dep # dbg
353 #print "times (dep,tar):",dep_time,target_time # dbg
353 #print "times (dep,tar):",dep_time,target_time # dbg
354 return 1
354 return 1
355 return 0
355 return 0
356
356
357
357
358 def target_update(target,deps,cmd):
358 def target_update(target,deps,cmd):
359 """Update a target with a given command given a list of dependencies.
359 """Update a target with a given command given a list of dependencies.
360
360
361 target_update(target,deps,cmd) -> runs cmd if target is outdated.
361 target_update(target,deps,cmd) -> runs cmd if target is outdated.
362
362
363 This is just a wrapper around target_outdated() which calls the given
363 This is just a wrapper around target_outdated() which calls the given
364 command if target is outdated."""
364 command if target is outdated."""
365
365
366 if target_outdated(target,deps):
366 if target_outdated(target,deps):
367 system(cmd)
367 system(cmd)
368
368
369 @undoc
369 @undoc
370 def filehash(path):
370 def filehash(path):
371 """Make an MD5 hash of a file, ignoring any differences in line
371 """Make an MD5 hash of a file, ignoring any differences in line
372 ending characters."""
372 ending characters."""
373 warn("filehash() is deprecated since IPython 4.0", DeprecationWarning, stacklevel=2)
373 warn("filehash() is deprecated since IPython 4.0", DeprecationWarning, stacklevel=2)
374 with open(path, "rU") as f:
374 with open(path, "rU") as f:
375 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
375 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
376
376
377 ENOLINK = 1998
377 ENOLINK = 1998
378
378
379 def link(src, dst):
379 def link(src, dst):
380 """Hard links ``src`` to ``dst``, returning 0 or errno.
380 """Hard links ``src`` to ``dst``, returning 0 or errno.
381
381
382 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
382 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
383 supported by the operating system.
383 supported by the operating system.
384 """
384 """
385
385
386 if not hasattr(os, "link"):
386 if not hasattr(os, "link"):
387 return ENOLINK
387 return ENOLINK
388 link_errno = 0
388 link_errno = 0
389 try:
389 try:
390 os.link(src, dst)
390 os.link(src, dst)
391 except OSError as e:
391 except OSError as e:
392 link_errno = e.errno
392 link_errno = e.errno
393 return link_errno
393 return link_errno
394
394
395
395
396 def link_or_copy(src, dst):
396 def link_or_copy(src, dst):
397 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
397 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
398
398
399 Attempts to maintain the semantics of ``shutil.copy``.
399 Attempts to maintain the semantics of ``shutil.copy``.
400
400
401 Because ``os.link`` does not overwrite files, a unique temporary file
401 Because ``os.link`` does not overwrite files, a unique temporary file
402 will be used if the target already exists, then that file will be moved
402 will be used if the target already exists, then that file will be moved
403 into place.
403 into place.
404 """
404 """
405
405
406 if os.path.isdir(dst):
406 if os.path.isdir(dst):
407 dst = os.path.join(dst, os.path.basename(src))
407 dst = os.path.join(dst, os.path.basename(src))
408
408
409 link_errno = link(src, dst)
409 link_errno = link(src, dst)
410 if link_errno == errno.EEXIST:
410 if link_errno == errno.EEXIST:
411 if os.stat(src).st_ino == os.stat(dst).st_ino:
411 if os.stat(src).st_ino == os.stat(dst).st_ino:
412 # dst is already a hard link to the correct file, so we don't need
412 # dst is already a hard link to the correct file, so we don't need
413 # to do anything else. If we try to link and rename the file
413 # to do anything else. If we try to link and rename the file
414 # anyway, we get duplicate files - see http://bugs.python.org/issue21876
414 # anyway, we get duplicate files - see http://bugs.python.org/issue21876
415 return
415 return
416
416
417 new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), )
417 new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), )
418 try:
418 try:
419 link_or_copy(src, new_dst)
419 link_or_copy(src, new_dst)
420 except:
420 except:
421 try:
421 try:
422 os.remove(new_dst)
422 os.remove(new_dst)
423 except OSError:
423 except OSError:
424 pass
424 pass
425 raise
425 raise
426 os.rename(new_dst, dst)
426 os.rename(new_dst, dst)
427 elif link_errno != 0:
427 elif link_errno != 0:
428 # Either link isn't supported, or the filesystem doesn't support
428 # Either link isn't supported, or the filesystem doesn't support
429 # linking, or 'src' and 'dst' are on different filesystems.
429 # linking, or 'src' and 'dst' are on different filesystems.
430 shutil.copy(src, dst)
430 shutil.copy(src, dst)
431
431
432 def ensure_dir_exists(path, mode=0o755):
432 def ensure_dir_exists(path, mode=0o755):
433 """ensure that a directory exists
433 """ensure that a directory exists
434
434
435 If it doesn't exist, try to create it and protect against a race condition
435 If it doesn't exist, try to create it and protect against a race condition
436 if another process is doing the same.
436 if another process is doing the same.
437
437
438 The default permissions are 755, which differ from os.makedirs default of 777.
438 The default permissions are 755, which differ from os.makedirs default of 777.
439 """
439 """
440 if not os.path.exists(path):
440 if not os.path.exists(path):
441 try:
441 try:
442 os.makedirs(path, mode=mode)
442 os.makedirs(path, mode=mode)
443 except OSError as e:
443 except OSError as e:
444 if e.errno != errno.EEXIST:
444 if e.errno != errno.EEXIST:
445 raise
445 raise
446 elif not os.path.isdir(path):
446 elif not os.path.isdir(path):
447 raise IOError("%r exists but is not a directory" % path)
447 raise IOError("%r exists but is not a directory" % path)
General Comments 0
You need to be logged in to leave comments. Login now