##// END OF EJS Templates
fallback on defaultencoding if filesystemencoding is None...
MinRK -
Show More
@@ -1,393 +1,395
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 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 import os
17 import os
18 import sys
18 import sys
19
19
20 import IPython
20 import IPython
21 from IPython.utils.process import system
21 from IPython.utils.process import system
22 from IPython.utils.importstring import import_item
22 from IPython.utils.importstring import import_item
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Code
25 # Code
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 # in case filesystemencoding() returns None:
29 fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
28
30
29 def _get_long_path_name(path):
31 def _get_long_path_name(path):
30 """Dummy no-op."""
32 """Dummy no-op."""
31 return path
33 return path
32
34
33
35
34 if sys.platform == 'win32':
36 if sys.platform == 'win32':
35 def _get_long_path_name(path):
37 def _get_long_path_name(path):
36 """Get a long path name (expand ~) on Windows using ctypes.
38 """Get a long path name (expand ~) on Windows using ctypes.
37
39
38 Examples
40 Examples
39 --------
41 --------
40
42
41 >>> get_long_path_name('c:\\docume~1')
43 >>> get_long_path_name('c:\\docume~1')
42 u'c:\\\\Documents and Settings'
44 u'c:\\\\Documents and Settings'
43
45
44 """
46 """
45 try:
47 try:
46 import ctypes
48 import ctypes
47 except ImportError:
49 except ImportError:
48 raise ImportError('you need to have ctypes installed for this to work')
50 raise ImportError('you need to have ctypes installed for this to work')
49 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
51 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
50 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
52 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
51 ctypes.c_uint ]
53 ctypes.c_uint ]
52
54
53 buf = ctypes.create_unicode_buffer(260)
55 buf = ctypes.create_unicode_buffer(260)
54 rv = _GetLongPathName(path, buf, 260)
56 rv = _GetLongPathName(path, buf, 260)
55 if rv == 0 or rv > 260:
57 if rv == 0 or rv > 260:
56 return path
58 return path
57 else:
59 else:
58 return buf.value
60 return buf.value
59
61
60
62
61 def get_long_path_name(path):
63 def get_long_path_name(path):
62 """Expand a path into its long form.
64 """Expand a path into its long form.
63
65
64 On Windows this expands any ~ in the paths. On other platforms, it is
66 On Windows this expands any ~ in the paths. On other platforms, it is
65 a null operation.
67 a null operation.
66 """
68 """
67 return _get_long_path_name(path)
69 return _get_long_path_name(path)
68
70
69
71
70 def get_py_filename(name):
72 def get_py_filename(name):
71 """Return a valid python filename in the current directory.
73 """Return a valid python filename in the current directory.
72
74
73 If the given name is not a file, it adds '.py' and searches again.
75 If the given name is not a file, it adds '.py' and searches again.
74 Raises IOError with an informative message if the file isn't found."""
76 Raises IOError with an informative message if the file isn't found."""
75
77
76 name = os.path.expanduser(name)
78 name = os.path.expanduser(name)
77 if not os.path.isfile(name) and not name.endswith('.py'):
79 if not os.path.isfile(name) and not name.endswith('.py'):
78 name += '.py'
80 name += '.py'
79 if os.path.isfile(name):
81 if os.path.isfile(name):
80 return name
82 return name
81 else:
83 else:
82 raise IOError,'File `%s` not found.' % name
84 raise IOError,'File `%s` not found.' % name
83
85
84
86
85 def filefind(filename, path_dirs=None):
87 def filefind(filename, path_dirs=None):
86 """Find a file by looking through a sequence of paths.
88 """Find a file by looking through a sequence of paths.
87
89
88 This iterates through a sequence of paths looking for a file and returns
90 This iterates through a sequence of paths looking for a file and returns
89 the full, absolute path of the first occurence of the file. If no set of
91 the full, absolute path of the first occurence of the file. If no set of
90 path dirs is given, the filename is tested as is, after running through
92 path dirs is given, the filename is tested as is, after running through
91 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
93 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
92
94
93 filefind('myfile.txt')
95 filefind('myfile.txt')
94
96
95 will find the file in the current working dir, but::
97 will find the file in the current working dir, but::
96
98
97 filefind('~/myfile.txt')
99 filefind('~/myfile.txt')
98
100
99 Will find the file in the users home directory. This function does not
101 Will find the file in the users home directory. This function does not
100 automatically try any paths, such as the cwd or the user's home directory.
102 automatically try any paths, such as the cwd or the user's home directory.
101
103
102 Parameters
104 Parameters
103 ----------
105 ----------
104 filename : str
106 filename : str
105 The filename to look for.
107 The filename to look for.
106 path_dirs : str, None or sequence of str
108 path_dirs : str, None or sequence of str
107 The sequence of paths to look for the file in. If None, the filename
109 The sequence of paths to look for the file in. If None, the filename
108 need to be absolute or be in the cwd. If a string, the string is
110 need to be absolute or be in the cwd. If a string, the string is
109 put into a sequence and the searched. If a sequence, walk through
111 put into a sequence and the searched. If a sequence, walk through
110 each element and join with ``filename``, calling :func:`expandvars`
112 each element and join with ``filename``, calling :func:`expandvars`
111 and :func:`expanduser` before testing for existence.
113 and :func:`expanduser` before testing for existence.
112
114
113 Returns
115 Returns
114 -------
116 -------
115 Raises :exc:`IOError` or returns absolute path to file.
117 Raises :exc:`IOError` or returns absolute path to file.
116 """
118 """
117
119
118 # If paths are quoted, abspath gets confused, strip them...
120 # If paths are quoted, abspath gets confused, strip them...
119 filename = filename.strip('"').strip("'")
121 filename = filename.strip('"').strip("'")
120 # If the input is an absolute path, just check it exists
122 # If the input is an absolute path, just check it exists
121 if os.path.isabs(filename) and os.path.isfile(filename):
123 if os.path.isabs(filename) and os.path.isfile(filename):
122 return filename
124 return filename
123
125
124 if path_dirs is None:
126 if path_dirs is None:
125 path_dirs = ("",)
127 path_dirs = ("",)
126 elif isinstance(path_dirs, basestring):
128 elif isinstance(path_dirs, basestring):
127 path_dirs = (path_dirs,)
129 path_dirs = (path_dirs,)
128
130
129 for path in path_dirs:
131 for path in path_dirs:
130 if path == '.': path = os.getcwd()
132 if path == '.': path = os.getcwd()
131 testname = expand_path(os.path.join(path, filename))
133 testname = expand_path(os.path.join(path, filename))
132 if os.path.isfile(testname):
134 if os.path.isfile(testname):
133 return os.path.abspath(testname)
135 return os.path.abspath(testname)
134
136
135 raise IOError("File %r does not exist in any of the search paths: %r" %
137 raise IOError("File %r does not exist in any of the search paths: %r" %
136 (filename, path_dirs) )
138 (filename, path_dirs) )
137
139
138
140
139 class HomeDirError(Exception):
141 class HomeDirError(Exception):
140 pass
142 pass
141
143
142
144
143 def get_home_dir():
145 def get_home_dir():
144 """Return the closest possible equivalent to a 'home' directory.
146 """Return the closest possible equivalent to a 'home' directory.
145
147
146 * On POSIX, we try $HOME.
148 * On POSIX, we try $HOME.
147 * On Windows we try:
149 * On Windows we try:
148 - %HOMESHARE%
150 - %HOMESHARE%
149 - %HOMEDRIVE\%HOMEPATH%
151 - %HOMEDRIVE\%HOMEPATH%
150 - %USERPROFILE%
152 - %USERPROFILE%
151 - Registry hack for My Documents
153 - Registry hack for My Documents
152 - %HOME%: rare, but some people with unix-like setups may have defined it
154 - %HOME%: rare, but some people with unix-like setups may have defined it
153 * On Dos C:\
155 * On Dos C:\
154
156
155 Currently only Posix and NT are implemented, a HomeDirError exception is
157 Currently only Posix and NT are implemented, a HomeDirError exception is
156 raised for all other OSes.
158 raised for all other OSes.
157 """
159 """
158
160
159 isdir = os.path.isdir
161 isdir = os.path.isdir
160 env = os.environ
162 env = os.environ
161
163
162 # first, check py2exe distribution root directory for _ipython.
164 # first, check py2exe distribution root directory for _ipython.
163 # This overrides all. Normally does not exist.
165 # This overrides all. Normally does not exist.
164
166
165 if hasattr(sys, "frozen"): #Is frozen by py2exe
167 if hasattr(sys, "frozen"): #Is frozen by py2exe
166 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
168 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
167 root, rest = IPython.__file__.lower().split('library.zip')
169 root, rest = IPython.__file__.lower().split('library.zip')
168 else:
170 else:
169 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
171 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
170 root=os.path.abspath(root).rstrip('\\')
172 root=os.path.abspath(root).rstrip('\\')
171 if isdir(os.path.join(root, '_ipython')):
173 if isdir(os.path.join(root, '_ipython')):
172 os.environ["IPYKITROOT"] = root
174 os.environ["IPYKITROOT"] = root
173 return root.decode(sys.getfilesystemencoding())
175 return root.decode(fs_encoding)
174
176
175 if os.name == 'posix':
177 if os.name == 'posix':
176 # Linux, Unix, AIX, OS X
178 # Linux, Unix, AIX, OS X
177 try:
179 try:
178 homedir = env['HOME']
180 homedir = env['HOME']
179 except KeyError:
181 except KeyError:
180 # Last-ditch attempt at finding a suitable $HOME, on systems where
182 # Last-ditch attempt at finding a suitable $HOME, on systems where
181 # it may not be defined in the environment but the system shell
183 # it may not be defined in the environment but the system shell
182 # still knows it - reported once as:
184 # still knows it - reported once as:
183 # https://github.com/ipython/ipython/issues/154
185 # https://github.com/ipython/ipython/issues/154
184 from subprocess import Popen, PIPE
186 from subprocess import Popen, PIPE
185 homedir = Popen('echo $HOME', shell=True,
187 homedir = Popen('echo $HOME', shell=True,
186 stdout=PIPE).communicate()[0].strip()
188 stdout=PIPE).communicate()[0].strip()
187 if homedir:
189 if homedir:
188 return homedir.decode(sys.getfilesystemencoding())
190 return homedir.decode(fs_encoding)
189 else:
191 else:
190 raise HomeDirError('Undefined $HOME, IPython cannot proceed.')
192 raise HomeDirError('Undefined $HOME, IPython cannot proceed.')
191 else:
193 else:
192 return homedir.decode(sys.getfilesystemencoding())
194 return homedir.decode(fs_encoding)
193 elif os.name == 'nt':
195 elif os.name == 'nt':
194 # Now for win9x, XP, Vista, 7?
196 # Now for win9x, XP, Vista, 7?
195 # For some strange reason all of these return 'nt' for os.name.
197 # For some strange reason all of these return 'nt' for os.name.
196 # First look for a network home directory. This will return the UNC
198 # First look for a network home directory. This will return the UNC
197 # path (\\server\\Users\%username%) not the mapped path (Z:\). This
199 # path (\\server\\Users\%username%) not the mapped path (Z:\). This
198 # is needed when running IPython on cluster where all paths have to
200 # is needed when running IPython on cluster where all paths have to
199 # be UNC.
201 # be UNC.
200 try:
202 try:
201 homedir = env['HOMESHARE']
203 homedir = env['HOMESHARE']
202 except KeyError:
204 except KeyError:
203 pass
205 pass
204 else:
206 else:
205 if isdir(homedir):
207 if isdir(homedir):
206 return homedir.decode(sys.getfilesystemencoding())
208 return homedir.decode(fs_encoding)
207
209
208 # Now look for a local home directory
210 # Now look for a local home directory
209 try:
211 try:
210 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
212 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
211 except KeyError:
213 except KeyError:
212 pass
214 pass
213 else:
215 else:
214 if isdir(homedir):
216 if isdir(homedir):
215 return homedir.decode(sys.getfilesystemencoding())
217 return homedir.decode(fs_encoding)
216
218
217 # Now the users profile directory
219 # Now the users profile directory
218 try:
220 try:
219 homedir = os.path.join(env['USERPROFILE'])
221 homedir = os.path.join(env['USERPROFILE'])
220 except KeyError:
222 except KeyError:
221 pass
223 pass
222 else:
224 else:
223 if isdir(homedir):
225 if isdir(homedir):
224 return homedir.decode(sys.getfilesystemencoding())
226 return homedir.decode(fs_encoding)
225
227
226 # Use the registry to get the 'My Documents' folder.
228 # Use the registry to get the 'My Documents' folder.
227 try:
229 try:
228 import _winreg as wreg
230 import _winreg as wreg
229 key = wreg.OpenKey(
231 key = wreg.OpenKey(
230 wreg.HKEY_CURRENT_USER,
232 wreg.HKEY_CURRENT_USER,
231 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
233 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
232 )
234 )
233 homedir = wreg.QueryValueEx(key,'Personal')[0]
235 homedir = wreg.QueryValueEx(key,'Personal')[0]
234 key.Close()
236 key.Close()
235 except:
237 except:
236 pass
238 pass
237 else:
239 else:
238 if isdir(homedir):
240 if isdir(homedir):
239 return homedir.decode(sys.getfilesystemencoding())
241 return homedir.decode(fs_encoding)
240
242
241 # A user with a lot of unix tools in win32 may have defined $HOME.
243 # A user with a lot of unix tools in win32 may have defined $HOME.
242 # Try this as a last ditch option.
244 # Try this as a last ditch option.
243 try:
245 try:
244 homedir = env['HOME']
246 homedir = env['HOME']
245 except KeyError:
247 except KeyError:
246 pass
248 pass
247 else:
249 else:
248 if isdir(homedir):
250 if isdir(homedir):
249 return homedir.decode(sys.getfilesystemencoding())
251 return homedir.decode(fs_encoding)
250
252
251 # If all else fails, raise HomeDirError
253 # If all else fails, raise HomeDirError
252 raise HomeDirError('No valid home directory could be found')
254 raise HomeDirError('No valid home directory could be found')
253 elif os.name == 'dos':
255 elif os.name == 'dos':
254 # Desperate, may do absurd things in classic MacOS. May work under DOS.
256 # Desperate, may do absurd things in classic MacOS. May work under DOS.
255 return 'C:\\'.decode(sys.getfilesystemencoding())
257 return 'C:\\'.decode(fs_encoding)
256 else:
258 else:
257 raise HomeDirError('No valid home directory could be found for your OS')
259 raise HomeDirError('No valid home directory could be found for your OS')
258
260
259 def get_xdg_dir():
261 def get_xdg_dir():
260 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
262 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
261
263
262 This is only for posix (Linux,Unix,OS X, etc) systems.
264 This is only for posix (Linux,Unix,OS X, etc) systems.
263 """
265 """
264
266
265 isdir = os.path.isdir
267 isdir = os.path.isdir
266 env = os.environ
268 env = os.environ
267
269
268 if os.name == 'posix':
270 if os.name == 'posix':
269 # Linux, Unix, AIX, OS X
271 # Linux, Unix, AIX, OS X
270 # use ~/.config if not set OR empty
272 # use ~/.config if not set OR empty
271 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
273 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
272 if xdg and isdir(xdg):
274 if xdg and isdir(xdg):
273 return xdg.decode(sys.getfilesystemencoding())
275 return xdg.decode(fs_encoding)
274
276
275 return None
277 return None
276
278
277
279
278 def get_ipython_dir():
280 def get_ipython_dir():
279 """Get the IPython directory for this platform and user.
281 """Get the IPython directory for this platform and user.
280
282
281 This uses the logic in `get_home_dir` to find the home directory
283 This uses the logic in `get_home_dir` to find the home directory
282 and the adds .ipython to the end of the path.
284 and the adds .ipython to the end of the path.
283 """
285 """
284
286
285 env = os.environ
287 env = os.environ
286 pjoin = os.path.join
288 pjoin = os.path.join
287 exists = os.path.exists
289 exists = os.path.exists
288
290
289 ipdir_def = '.ipython'
291 ipdir_def = '.ipython'
290 xdg_def = 'ipython'
292 xdg_def = 'ipython'
291
293
292 home_dir = get_home_dir()
294 home_dir = get_home_dir()
293 xdg_dir = get_xdg_dir()
295 xdg_dir = get_xdg_dir()
294 # import pdb; pdb.set_trace() # dbg
296 # import pdb; pdb.set_trace() # dbg
295 ipdir = env.get('IPYTHON_DIR', env.get('IPYTHONDIR', None))
297 ipdir = env.get('IPYTHON_DIR', env.get('IPYTHONDIR', None))
296 if ipdir is None:
298 if ipdir is None:
297 # not set explicitly, use XDG_CONFIG_HOME or HOME
299 # not set explicitly, use XDG_CONFIG_HOME or HOME
298 home_ipdir = pjoin(home_dir, ipdir_def)
300 home_ipdir = pjoin(home_dir, ipdir_def)
299 if xdg_dir:
301 if xdg_dir:
300 # use XDG, as long as the user isn't already
302 # use XDG, as long as the user isn't already
301 # using $HOME/.ipython and *not* XDG/ipython
303 # using $HOME/.ipython and *not* XDG/ipython
302
304
303 xdg_ipdir = pjoin(xdg_dir, xdg_def)
305 xdg_ipdir = pjoin(xdg_dir, xdg_def)
304
306
305 if exists(xdg_ipdir) or not exists(home_ipdir):
307 if exists(xdg_ipdir) or not exists(home_ipdir):
306 ipdir = xdg_ipdir
308 ipdir = xdg_ipdir
307
309
308 if ipdir is None:
310 if ipdir is None:
309 # not using XDG
311 # not using XDG
310 ipdir = home_ipdir
312 ipdir = home_ipdir
311
313
312 return ipdir.decode(sys.getfilesystemencoding())
314 return ipdir.decode(fs_encoding)
313
315
314
316
315 def get_ipython_package_dir():
317 def get_ipython_package_dir():
316 """Get the base directory where IPython itself is installed."""
318 """Get the base directory where IPython itself is installed."""
317 ipdir = os.path.dirname(IPython.__file__)
319 ipdir = os.path.dirname(IPython.__file__)
318 return ipdir.decode(sys.getfilesystemencoding())
320 return ipdir.decode(fs_encoding)
319
321
320
322
321 def get_ipython_module_path(module_str):
323 def get_ipython_module_path(module_str):
322 """Find the path to an IPython module in this version of IPython.
324 """Find the path to an IPython module in this version of IPython.
323
325
324 This will always find the version of the module that is in this importable
326 This will always find the version of the module that is in this importable
325 IPython package. This will always return the path to the ``.py``
327 IPython package. This will always return the path to the ``.py``
326 version of the module.
328 version of the module.
327 """
329 """
328 if module_str == 'IPython':
330 if module_str == 'IPython':
329 return os.path.join(get_ipython_package_dir(), '__init__.py')
331 return os.path.join(get_ipython_package_dir(), '__init__.py')
330 mod = import_item(module_str)
332 mod = import_item(module_str)
331 the_path = mod.__file__.replace('.pyc', '.py')
333 the_path = mod.__file__.replace('.pyc', '.py')
332 the_path = the_path.replace('.pyo', '.py')
334 the_path = the_path.replace('.pyo', '.py')
333 return the_path.decode(sys.getfilesystemencoding())
335 return the_path.decode(fs_encoding)
334
336
335
337
336 def expand_path(s):
338 def expand_path(s):
337 """Expand $VARS and ~names in a string, like a shell
339 """Expand $VARS and ~names in a string, like a shell
338
340
339 :Examples:
341 :Examples:
340
342
341 In [2]: os.environ['FOO']='test'
343 In [2]: os.environ['FOO']='test'
342
344
343 In [3]: expand_path('variable FOO is $FOO')
345 In [3]: expand_path('variable FOO is $FOO')
344 Out[3]: 'variable FOO is test'
346 Out[3]: 'variable FOO is test'
345 """
347 """
346 # This is a pretty subtle hack. When expand user is given a UNC path
348 # This is a pretty subtle hack. When expand user is given a UNC path
347 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
349 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
348 # the $ to get (\\server\share\%username%). I think it considered $
350 # the $ to get (\\server\share\%username%). I think it considered $
349 # alone an empty var. But, we need the $ to remains there (it indicates
351 # alone an empty var. But, we need the $ to remains there (it indicates
350 # a hidden share).
352 # a hidden share).
351 if os.name=='nt':
353 if os.name=='nt':
352 s = s.replace('$\\', 'IPYTHON_TEMP')
354 s = s.replace('$\\', 'IPYTHON_TEMP')
353 s = os.path.expandvars(os.path.expanduser(s))
355 s = os.path.expandvars(os.path.expanduser(s))
354 if os.name=='nt':
356 if os.name=='nt':
355 s = s.replace('IPYTHON_TEMP', '$\\')
357 s = s.replace('IPYTHON_TEMP', '$\\')
356 return s
358 return s
357
359
358
360
359 def target_outdated(target,deps):
361 def target_outdated(target,deps):
360 """Determine whether a target is out of date.
362 """Determine whether a target is out of date.
361
363
362 target_outdated(target,deps) -> 1/0
364 target_outdated(target,deps) -> 1/0
363
365
364 deps: list of filenames which MUST exist.
366 deps: list of filenames which MUST exist.
365 target: single filename which may or may not exist.
367 target: single filename which may or may not exist.
366
368
367 If target doesn't exist or is older than any file listed in deps, return
369 If target doesn't exist or is older than any file listed in deps, return
368 true, otherwise return false.
370 true, otherwise return false.
369 """
371 """
370 try:
372 try:
371 target_time = os.path.getmtime(target)
373 target_time = os.path.getmtime(target)
372 except os.error:
374 except os.error:
373 return 1
375 return 1
374 for dep in deps:
376 for dep in deps:
375 dep_time = os.path.getmtime(dep)
377 dep_time = os.path.getmtime(dep)
376 if dep_time > target_time:
378 if dep_time > target_time:
377 #print "For target",target,"Dep failed:",dep # dbg
379 #print "For target",target,"Dep failed:",dep # dbg
378 #print "times (dep,tar):",dep_time,target_time # dbg
380 #print "times (dep,tar):",dep_time,target_time # dbg
379 return 1
381 return 1
380 return 0
382 return 0
381
383
382
384
383 def target_update(target,deps,cmd):
385 def target_update(target,deps,cmd):
384 """Update a target with a given command given a list of dependencies.
386 """Update a target with a given command given a list of dependencies.
385
387
386 target_update(target,deps,cmd) -> runs cmd if target is outdated.
388 target_update(target,deps,cmd) -> runs cmd if target is outdated.
387
389
388 This is just a wrapper around target_outdated() which calls the given
390 This is just a wrapper around target_outdated() which calls the given
389 command if target is outdated."""
391 command if target is outdated."""
390
392
391 if target_outdated(target,deps):
393 if target_outdated(target,deps):
392 system(cmd)
394 system(cmd)
393
395
General Comments 0
You need to be logged in to leave comments. Login now