svn-gvsig-desktop / tags / v1_1_Build_1013 / extensions / extScripting / scripts / jython / Lib / ntpath.py @ 13521
History | View | Annotate | Download (12.6 KB)
1 | 5782 | jmvivo | # Module 'ntpath' -- common operations on WinNT/Win95 pathnames
|
---|---|---|---|
2 | """Common pathname manipulations, WindowsNT/95 version.
|
||
3 |
|
||
4 | Instead of importing this module directly, import os and refer to this
|
||
5 | module as os.path.
|
||
6 | """
|
||
7 | |||
8 | import os |
||
9 | import stat |
||
10 | |||
11 | __all__ = ["normcase","isabs","join","splitdrive","split","splitext", |
||
12 | "basename","dirname","commonprefix","getsize","getmtime", |
||
13 | "getatime","islink","exists","isdir","isfile","ismount", |
||
14 | "walk","expanduser","expandvars","normpath","abspath","splitunc"] |
||
15 | |||
16 | # Normalize the case of a pathname and map slashes to backslashes.
|
||
17 | # Other normalizations (such as optimizing '../' away) are not done
|
||
18 | # (this is done by normpath).
|
||
19 | |||
20 | def normcase(s): |
||
21 | """Normalize case of pathname.
|
||
22 |
|
||
23 | Makes all characters lowercase and all slashes into backslashes."""
|
||
24 | return s.replace("/", "\\").lower() |
||
25 | |||
26 | |||
27 | # Return whether a path is absolute.
|
||
28 | # Trivial in Posix, harder on the Mac or MS-DOS.
|
||
29 | # For DOS it is absolute if it starts with a slash or backslash (current
|
||
30 | # volume), or if a pathname after the volume letter and colon / UNC resource
|
||
31 | # starts with a slash or backslash.
|
||
32 | |||
33 | def isabs(s): |
||
34 | """Test whether a path is absolute"""
|
||
35 | s = splitdrive(s)[1]
|
||
36 | return s != '' and s[:1] in '/\\' |
||
37 | |||
38 | |||
39 | # Join two (or more) paths.
|
||
40 | |||
41 | def join(a, *p): |
||
42 | """Join two or more pathname components, inserting "\\" as needed"""
|
||
43 | path = a |
||
44 | for b in p: |
||
45 | if isabs(b):
|
||
46 | path = b |
||
47 | elif path == '' or path[-1:] in '/\\:': |
||
48 | path = path + b |
||
49 | else:
|
||
50 | path = path + "\\" + b
|
||
51 | return path
|
||
52 | |||
53 | |||
54 | # Split a path in a drive specification (a drive letter followed by a
|
||
55 | # colon) and the path specification.
|
||
56 | # It is always true that drivespec + pathspec == p
|
||
57 | def splitdrive(p): |
||
58 | """Split a pathname into drive and path specifiers. Returns a 2-tuple
|
||
59 | "(drive,path)"; either part may be empty"""
|
||
60 | if p[1:2] == ':': |
||
61 | return p[0:2], p[2:] |
||
62 | return '', p |
||
63 | |||
64 | |||
65 | # Parse UNC paths
|
||
66 | def splitunc(p): |
||
67 | """Split a pathname into UNC mount point and relative path specifiers.
|
||
68 |
|
||
69 | Return a 2-tuple (unc, rest); either part may be empty.
|
||
70 | If unc is not empty, it has the form '//host/mount' (or similar
|
||
71 | using backslashes). unc+rest is always the input path.
|
||
72 | Paths containing drive letters never have an UNC part.
|
||
73 | """
|
||
74 | if p[1:2] == ':': |
||
75 | return '', p # Drive letter present |
||
76 | firstTwo = p[0:2] |
||
77 | if firstTwo == '//' or firstTwo == '\\\\': |
||
78 | # is a UNC path:
|
||
79 | # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter
|
||
80 | # \\machine\mountpoint\directories...
|
||
81 | # directory ^^^^^^^^^^^^^^^
|
||
82 | normp = normcase(p) |
||
83 | index = normp.find('\\', 2) |
||
84 | if index == -1: |
||
85 | ##raise RuntimeError, 'illegal UNC path: "' + p + '"'
|
||
86 | return ("", p) |
||
87 | index = normp.find('\\', index + 1) |
||
88 | if index == -1: |
||
89 | index = len(p)
|
||
90 | return p[:index], p[index:]
|
||
91 | return '', p |
||
92 | |||
93 | |||
94 | # Split a path in head (everything up to the last '/') and tail (the
|
||
95 | # rest). After the trailing '/' is stripped, the invariant
|
||
96 | # join(head, tail) == p holds.
|
||
97 | # The resulting head won't end in '/' unless it is the root.
|
||
98 | |||
99 | def split(p): |
||
100 | """Split a pathname.
|
||
101 |
|
||
102 | Return tuple (head, tail) where tail is everything after the final slash.
|
||
103 | Either part may be empty."""
|
||
104 | |||
105 | d, p = splitdrive(p) |
||
106 | # set i to index beyond p's last slash
|
||
107 | i = len(p)
|
||
108 | while i and p[i-1] not in '/\\': |
||
109 | i = i - 1
|
||
110 | head, tail = p[:i], p[i:] # now tail has no slashes
|
||
111 | # remove trailing slashes from head, unless it's all slashes
|
||
112 | head2 = head |
||
113 | while head2 and head2[-1] in '/\\': |
||
114 | head2 = head2[:-1]
|
||
115 | head = head2 or head
|
||
116 | return d + head, tail
|
||
117 | |||
118 | |||
119 | # Split a path in root and extension.
|
||
120 | # The extension is everything starting at the last dot in the last
|
||
121 | # pathname component; the root is everything before that.
|
||
122 | # It is always true that root + ext == p.
|
||
123 | |||
124 | def splitext(p): |
||
125 | """Split the extension from a pathname.
|
||
126 |
|
||
127 | Extension is everything from the last dot to the end.
|
||
128 | Return (root, ext), either part may be empty."""
|
||
129 | root, ext = '', '' |
||
130 | for c in p: |
||
131 | if c in ['/','\\']: |
||
132 | root, ext = root + ext + c, ''
|
||
133 | elif c == '.': |
||
134 | if ext:
|
||
135 | root, ext = root + ext, c |
||
136 | else:
|
||
137 | ext = c |
||
138 | elif ext:
|
||
139 | ext = ext + c |
||
140 | else:
|
||
141 | root = root + c |
||
142 | return root, ext
|
||
143 | |||
144 | |||
145 | # Return the tail (basename) part of a path.
|
||
146 | |||
147 | def basename(p): |
||
148 | """Returns the final component of a pathname"""
|
||
149 | return split(p)[1] |
||
150 | |||
151 | |||
152 | # Return the head (dirname) part of a path.
|
||
153 | |||
154 | def dirname(p): |
||
155 | """Returns the directory component of a pathname"""
|
||
156 | return split(p)[0] |
||
157 | |||
158 | |||
159 | # Return the longest prefix of all list elements.
|
||
160 | |||
161 | def commonprefix(m): |
||
162 | "Given a list of pathnames, returns the longest common leading component"
|
||
163 | if not m: return '' |
||
164 | prefix = m[0]
|
||
165 | for item in m: |
||
166 | for i in range(len(prefix)): |
||
167 | if prefix[:i+1] != item[:i+1]: |
||
168 | prefix = prefix[:i] |
||
169 | if i == 0: return '' |
||
170 | break
|
||
171 | return prefix
|
||
172 | |||
173 | |||
174 | # Get size, mtime, atime of files.
|
||
175 | |||
176 | def getsize(filename): |
||
177 | """Return the size of a file, reported by os.stat()"""
|
||
178 | st = os.stat(filename) |
||
179 | return st[stat.ST_SIZE]
|
||
180 | |||
181 | def getmtime(filename): |
||
182 | """Return the last modification time of a file, reported by os.stat()"""
|
||
183 | st = os.stat(filename) |
||
184 | return st[stat.ST_MTIME]
|
||
185 | |||
186 | def getatime(filename): |
||
187 | """Return the last access time of a file, reported by os.stat()"""
|
||
188 | st = os.stat(filename) |
||
189 | return st[stat.ST_ATIME]
|
||
190 | |||
191 | |||
192 | # Is a path a symbolic link?
|
||
193 | # This will always return false on systems where posix.lstat doesn't exist.
|
||
194 | |||
195 | def islink(path): |
||
196 | """Test for symbolic link. On WindowsNT/95 always returns false"""
|
||
197 | return 0 |
||
198 | |||
199 | |||
200 | # Does a path exist?
|
||
201 | # This is false for dangling symbolic links.
|
||
202 | |||
203 | def exists(path): |
||
204 | """Test whether a path exists"""
|
||
205 | try:
|
||
206 | st = os.stat(path) |
||
207 | except os.error:
|
||
208 | return 0 |
||
209 | return 1 |
||
210 | |||
211 | |||
212 | # Is a path a dos directory?
|
||
213 | # This follows symbolic links, so both islink() and isdir() can be true
|
||
214 | # for the same path.
|
||
215 | |||
216 | def isdir(path): |
||
217 | """Test whether a path is a directory"""
|
||
218 | try:
|
||
219 | st = os.stat(path) |
||
220 | except os.error:
|
||
221 | return 0 |
||
222 | return stat.S_ISDIR(st[stat.ST_MODE])
|
||
223 | |||
224 | |||
225 | # Is a path a regular file?
|
||
226 | # This follows symbolic links, so both islink() and isdir() can be true
|
||
227 | # for the same path.
|
||
228 | |||
229 | def isfile(path): |
||
230 | """Test whether a path is a regular file"""
|
||
231 | try:
|
||
232 | st = os.stat(path) |
||
233 | except os.error:
|
||
234 | return 0 |
||
235 | return stat.S_ISREG(st[stat.ST_MODE])
|
||
236 | |||
237 | |||
238 | # Is a path a mount point? Either a root (with or without drive letter)
|
||
239 | # or an UNC path with at most a / or \ after the mount point.
|
||
240 | |||
241 | def ismount(path): |
||
242 | """Test whether a path is a mount point (defined as root of drive)"""
|
||
243 | unc, rest = splitunc(path) |
||
244 | if unc:
|
||
245 | return rest in ("", "/", "\\") |
||
246 | p = splitdrive(path)[1]
|
||
247 | return len(p) == 1 and p[0] in '/\\' |
||
248 | |||
249 | |||
250 | # Directory tree walk.
|
||
251 | # For each directory under top (including top itself, but excluding
|
||
252 | # '.' and '..'), func(arg, dirname, filenames) is called, where
|
||
253 | # dirname is the name of the directory and filenames is the list
|
||
254 | # files files (and subdirectories etc.) in the directory.
|
||
255 | # The func may modify the filenames list, to implement a filter,
|
||
256 | # or to impose a different order of visiting.
|
||
257 | |||
258 | def walk(top, func, arg): |
||
259 | """Directory tree walk whth callback function.
|
||
260 |
|
||
261 | walk(top, func, arg) calls func(arg, d, files) for each directory d
|
||
262 | in the tree rooted at top (including top itself); files is a list
|
||
263 | of all the files and subdirs in directory d."""
|
||
264 | try:
|
||
265 | names = os.listdir(top) |
||
266 | except os.error:
|
||
267 | return
|
||
268 | func(arg, top, names) |
||
269 | exceptions = ('.', '..') |
||
270 | for name in names: |
||
271 | if name not in exceptions: |
||
272 | name = join(top, name) |
||
273 | if isdir(name):
|
||
274 | walk(name, func, arg) |
||
275 | |||
276 | |||
277 | # Expand paths beginning with '~' or '~user'.
|
||
278 | # '~' means $HOME; '~user' means that user's home directory.
|
||
279 | # If the path doesn't begin with '~', or if the user or $HOME is unknown,
|
||
280 | # the path is returned unchanged (leaving error reporting to whatever
|
||
281 | # function is called with the expanded path as argument).
|
||
282 | # See also module 'glob' for expansion of *, ? and [...] in pathnames.
|
||
283 | # (A function should also be defined to do full *sh-style environment
|
||
284 | # variable expansion.)
|
||
285 | |||
286 | def expanduser(path): |
||
287 | """Expand ~ and ~user constructs.
|
||
288 |
|
||
289 | If user or $HOME is unknown, do nothing."""
|
||
290 | if path[:1] != '~': |
||
291 | return path
|
||
292 | i, n = 1, len(path) |
||
293 | while i < n and path[i] not in '/\\': |
||
294 | i = i + 1
|
||
295 | if i == 1: |
||
296 | if os.environ.has_key('HOME'): |
||
297 | userhome = os.environ['HOME']
|
||
298 | elif not os.environ.has_key('HOMEPATH'): |
||
299 | return path
|
||
300 | else:
|
||
301 | try:
|
||
302 | drive = os.environ['HOMEDRIVE']
|
||
303 | except KeyError: |
||
304 | drive = ''
|
||
305 | userhome = join(drive, os.environ['HOMEPATH'])
|
||
306 | else:
|
||
307 | return path
|
||
308 | return userhome + path[i:]
|
||
309 | |||
310 | |||
311 | # Expand paths containing shell variable substitutions.
|
||
312 | # The following rules apply:
|
||
313 | # - no expansion within single quotes
|
||
314 | # - no escape character, except for '$$' which is translated into '$'
|
||
315 | # - ${varname} is accepted.
|
||
316 | # - varnames can be made out of letters, digits and the character '_'
|
||
317 | # XXX With COMMAND.COM you can use any characters in a variable name,
|
||
318 | # XXX except '^|<>='.
|
||
319 | |||
320 | def expandvars(path): |
||
321 | """Expand shell variables of form $var and ${var}.
|
||
322 |
|
||
323 | Unknown variables are left unchanged."""
|
||
324 | if '$' not in path: |
||
325 | return path
|
||
326 | import string |
||
327 | varchars = string.letters + string.digits + '_-'
|
||
328 | res = ''
|
||
329 | index = 0
|
||
330 | pathlen = len(path)
|
||
331 | while index < pathlen:
|
||
332 | c = path[index] |
||
333 | if c == '\'': # no expansion within single quotes |
||
334 | path = path[index + 1:]
|
||
335 | pathlen = len(path)
|
||
336 | try:
|
||
337 | index = path.index('\'')
|
||
338 | res = res + '\'' + path[:index + 1] |
||
339 | except ValueError: |
||
340 | res = res + path |
||
341 | index = pathlen - 1
|
||
342 | elif c == '$': # variable or '$$' |
||
343 | if path[index + 1:index + 2] == '$': |
||
344 | res = res + c |
||
345 | index = index + 1
|
||
346 | elif path[index + 1:index + 2] == '{': |
||
347 | path = path[index+2:]
|
||
348 | pathlen = len(path)
|
||
349 | try:
|
||
350 | index = path.index('}')
|
||
351 | var = path[:index] |
||
352 | if os.environ.has_key(var):
|
||
353 | res = res + os.environ[var] |
||
354 | except ValueError: |
||
355 | res = res + path |
||
356 | index = pathlen - 1
|
||
357 | else:
|
||
358 | var = ''
|
||
359 | index = index + 1
|
||
360 | c = path[index:index + 1]
|
||
361 | while c != '' and c in varchars: |
||
362 | var = var + c |
||
363 | index = index + 1
|
||
364 | c = path[index:index + 1]
|
||
365 | if os.environ.has_key(var):
|
||
366 | res = res + os.environ[var] |
||
367 | if c != '': |
||
368 | res = res + c |
||
369 | else:
|
||
370 | res = res + c |
||
371 | index = index + 1
|
||
372 | return res
|
||
373 | |||
374 | |||
375 | # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
|
||
376 | # Previously, this function also truncated pathnames to 8+3 format,
|
||
377 | # but as this module is called "ntpath", that's obviously wrong!
|
||
378 | |||
379 | def normpath(path): |
||
380 | """Normalize path, eliminating double slashes, etc."""
|
||
381 | path = path.replace("/", "\\") |
||
382 | prefix, path = splitdrive(path) |
||
383 | while path[:1] == "\\": |
||
384 | prefix = prefix + "\\"
|
||
385 | path = path[1:]
|
||
386 | comps = path.split("\\")
|
||
387 | i = 0
|
||
388 | while i < len(comps): |
||
389 | if comps[i] == '.': |
||
390 | del comps[i]
|
||
391 | elif comps[i] == '..' and i > 0 and comps[i-1] not in ('', '..'): |
||
392 | del comps[i-1:i+1] |
||
393 | i = i - 1
|
||
394 | elif comps[i] == '' and i > 0 and comps[i-1] != '': |
||
395 | del comps[i]
|
||
396 | else:
|
||
397 | i = i + 1
|
||
398 | # If the path is now empty, substitute '.'
|
||
399 | if not prefix and not comps: |
||
400 | comps.append('.')
|
||
401 | return prefix + "\\".join(comps) |
||
402 | |||
403 | |||
404 | # Return an absolute path.
|
||
405 | def abspath(path): |
||
406 | """Return the absolute version of a path"""
|
||
407 | try:
|
||
408 | import win32api |
||
409 | except ImportError: |
||
410 | global abspath
|
||
411 | def _abspath(path): |
||
412 | if not isabs(path): |
||
413 | path = join(os.getcwd(), path) |
||
414 | return normpath(path)
|
||
415 | abspath = _abspath |
||
416 | return _abspath(path)
|
||
417 | if path: # Empty path must return current working directory. |
||
418 | try:
|
||
419 | path = win32api.GetFullPathName(path) |
||
420 | except win32api.error:
|
||
421 | pass # Bad path - return unchanged. |
||
422 | else:
|
||
423 | path = os.getcwd() |
||
424 | return normpath(path) |