home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pytho152.zip / emx / lib / python1.5 / dospath.py < prev    next >
Text File  |  2000-08-10  |  8KB  |  334 lines

  1. # Module 'dospath' -- common operations on DOS pathnames
  2.  
  3. import os
  4. import stat
  5. import string
  6.  
  7.  
  8. # Normalize the case of a pathname.
  9. # On MS-DOS it maps the pathname to lowercase, turns slashes into
  10. # backslashes.
  11. # Other normalizations (such as optimizing '../' away) are not allowed
  12. # (this is done by normpath).
  13. # Previously, this version mapped invalid consecutive characters to a 
  14. # single '_', but this has been removed.  This functionality should 
  15. # possibly be added as a new function.
  16.  
  17. def normcase(s):
  18.     return string.lower(string.replace(s, "/", "\\"))
  19.  
  20.  
  21. # Return wheter a path is absolute.
  22. # Trivial in Posix, harder on the Mac or MS-DOS.
  23. # For DOS it is absolute if it starts with a slash or backslash (current
  24. # volume), or if a pathname after the volume letter and colon starts with
  25. # a slash or backslash.
  26.  
  27. def isabs(s):
  28.     s = splitdrive(s)[1]
  29.     return s != '' and s[:1] in '/\\'
  30.  
  31.  
  32. # Join two (or more) paths.
  33.  
  34. def join(a, *p):
  35.     path = a
  36.     for b in p:
  37.         if isabs(b):
  38.             path = b
  39.         elif path == '' or path[-1:] in '/\\':
  40.             path = path + b
  41.         else:
  42.             path = path + os.sep + b
  43.     return path
  44.  
  45.  
  46. # Split a path in a drive specification (a drive letter followed by a
  47. # colon) and the path specification.
  48. # It is always true that drivespec + pathspec == p
  49.  
  50. def splitdrive(p):
  51.     if p[1:2] == ':':
  52.         return p[0:2], p[2:]
  53.     return '', p
  54.  
  55.  
  56. # Split a path in head (everything up to the last '/') and tail (the
  57. # rest).  After the trailing '/' is stripped, the invariant
  58. # join(head, tail) == p holds.
  59. # The resulting head won't end in '/' unless it is the root.
  60.  
  61. def split(p):
  62.     d, p = splitdrive(p)
  63.     # set i to index beyond p's last slash
  64.     i = len(p)
  65.     while i and p[i-1] not in '/\\':
  66.         i = i - 1
  67.     head, tail = p[:i], p[i:]  # now tail has no slashes
  68.     # remove trailing slashes from head, unless it's all slashes
  69.     head2 = head
  70.     while head2 and head2[-1] in '/\\':
  71.         head2 = head2[:-1]
  72.     head = head2 or head
  73.     return d + head, tail
  74.  
  75.  
  76. # Split a path in root and extension.
  77. # The extension is everything starting at the first dot in the last
  78. # pathname component; the root is everything before that.
  79. # It is always true that root + ext == p.
  80.  
  81. def splitext(p):
  82.     root, ext = '', ''
  83.     for c in p:
  84.         if c in '/\\':
  85.             root, ext = root + ext + c, ''
  86.         elif c == '.' or ext:
  87.             ext = ext + c
  88.         else:
  89.             root = root + c
  90.     return root, ext
  91.  
  92.  
  93. # Return the tail (basename) part of a path.
  94.  
  95. def basename(p):
  96.     return split(p)[1]
  97.  
  98.  
  99. # Return the head (dirname) part of a path.
  100.  
  101. def dirname(p):
  102.     return split(p)[0]
  103.  
  104.  
  105. # Return the longest prefix of all list elements.
  106.  
  107. def commonprefix(m):
  108.     if not m: return ''
  109.     prefix = m[0]
  110.     for item in m:
  111.         for i in range(len(prefix)):
  112.             if prefix[:i+1] <> item[:i+1]:
  113.                 prefix = prefix[:i]
  114.                 if i == 0: return ''
  115.                 break
  116.     return prefix
  117.  
  118.  
  119. # Get size, mtime, atime of files.
  120.  
  121. def getsize(filename):
  122.     """Return the size of a file, reported by os.stat()."""
  123.     st = os.stat(filename)
  124.     return st[stat.ST_SIZE]
  125.  
  126. def getmtime(filename):
  127.     """Return the last modification time of a file, reported by os.stat()."""
  128.     st = os.stat(filename)
  129.     return st[stat.ST_MTIME]
  130.  
  131. def getatime(filename):
  132.     """Return the last access time of a file, reported by os.stat()."""
  133.     st = os.stat(filename)
  134.     return st[stat.ST_MTIME]
  135.  
  136.  
  137. # Is a path a symbolic link?
  138. # This will always return false on systems where posix.lstat doesn't exist.
  139.  
  140. def islink(path):
  141.     return 0
  142.  
  143.  
  144. # Does a path exist?
  145. # This is false for dangling symbolic links.
  146.  
  147. def exists(path):
  148.     try:
  149.         st = os.stat(path)
  150.     except os.error:
  151.         return 0
  152.     return 1
  153.  
  154.  
  155. # Is a path a dos directory?
  156. # This follows symbolic links, so both islink() and isdir() can be true
  157. # for the same path.
  158.  
  159. def isdir(path):
  160.     try:
  161.         st = os.stat(path)
  162.     except os.error:
  163.         return 0
  164.     return stat.S_ISDIR(st[stat.ST_MODE])
  165.  
  166.  
  167. # Is a path a regular file?
  168. # This follows symbolic links, so both islink() and isdir() can be true
  169. # for the same path.
  170.  
  171. def isfile(path):
  172.     try:
  173.         st = os.stat(path)
  174.     except os.error:
  175.         return 0
  176.     return stat.S_ISREG(st[stat.ST_MODE])
  177.  
  178.  
  179. # Is a path a mount point?
  180. # XXX This degenerates in: 'is this the root?' on DOS
  181.  
  182. def ismount(path):
  183.     return isabs(splitdrive(path)[1])
  184.  
  185.  
  186. # Directory tree walk.
  187. # For each directory under top (including top itself, but excluding
  188. # '.' and '..'), func(arg, dirname, filenames) is called, where
  189. # dirname is the name of the directory and filenames is the list
  190. # files files (and subdirectories etc.) in the directory.
  191. # The func may modify the filenames list, to implement a filter,
  192. # or to impose a different order of visiting.
  193.  
  194. def walk(top, func, arg):
  195.     try:
  196.         names = os.listdir(top)
  197.     except os.error:
  198.         return
  199.     func(arg, top, names)
  200.     exceptions = ('.', '..')
  201.     for name in names:
  202.         if name not in exceptions:
  203.             name = join(top, name)
  204.             if isdir(name):
  205.                 walk(name, func, arg)
  206.  
  207.  
  208. # Expand paths beginning with '~' or '~user'.
  209. # '~' means $HOME; '~user' means that user's home directory.
  210. # If the path doesn't begin with '~', or if the user or $HOME is unknown,
  211. # the path is returned unchanged (leaving error reporting to whatever
  212. # function is called with the expanded path as argument).
  213. # See also module 'glob' for expansion of *, ? and [...] in pathnames.
  214. # (A function should also be defined to do full *sh-style environment
  215. # variable expansion.)
  216.  
  217. def expanduser(path):
  218.     if path[:1] <> '~':
  219.         return path
  220.     i, n = 1, len(path)
  221.     while i < n and path[i] not in '/\\':
  222.         i = i+1
  223.     if i == 1:
  224.         if not os.environ.has_key('HOME'):
  225.             return path
  226.         userhome = os.environ['HOME']
  227.     else:
  228.         return path
  229.     return userhome + path[i:]
  230.  
  231.  
  232. # Expand paths containing shell variable substitutions.
  233. # The following rules apply:
  234. #    - no expansion within single quotes
  235. #    - no escape character, except for '$$' which is translated into '$'
  236. #    - ${varname} is accepted.
  237. #    - varnames can be made out of letters, digits and the character '_'
  238. # XXX With COMMAND.COM you can use any characters in a variable name,
  239. # XXX except '^|<>='.
  240.  
  241. varchars = string.letters + string.digits + '_-'
  242.  
  243. def expandvars(path):
  244.     if '$' not in path:
  245.         return path
  246.     res = ''
  247.     index = 0
  248.     pathlen = len(path)
  249.     while index < pathlen:
  250.         c = path[index]
  251.         if c == '\'':    # no expansion within single quotes
  252.             path = path[index + 1:]
  253.             pathlen = len(path)
  254.             try:
  255.                 index = string.index(path, '\'')
  256.                 res = res + '\'' + path[:index + 1]
  257.             except string.index_error:
  258.                 res = res + path
  259.                 index = pathlen -1
  260.         elif c == '$':    # variable or '$$'
  261.             if path[index + 1:index + 2] == '$':
  262.                 res = res + c
  263.                 index = index + 1
  264.             elif path[index + 1:index + 2] == '{':
  265.                 path = path[index+2:]
  266.                 pathlen = len(path)
  267.                 try:
  268.                     index = string.index(path, '}')
  269.                     var = path[:index]
  270.                     if os.environ.has_key(var):
  271.                         res = res + os.environ[var]
  272.                 except string.index_error:
  273.                     res = res + path
  274.                     index = pathlen - 1
  275.             else:
  276.                 var = ''
  277.                 index = index + 1
  278.                 c = path[index:index + 1]
  279.                 while c != '' and c in varchars:
  280.                     var = var + c
  281.                     index = index + 1
  282.                     c = path[index:index + 1]
  283.                 if os.environ.has_key(var):
  284.                     res = res + os.environ[var]
  285.                 if c != '':
  286.                     res = res + c
  287.         else:
  288.             res = res + c
  289.         index = index + 1
  290.     return res
  291.  
  292.  
  293. # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
  294. # Also, components of the path are silently truncated to 8+3 notation.
  295.  
  296. def normpath(path):
  297.     path = string.replace(path, "/", "\\")
  298.     prefix, path = splitdrive(path)
  299.     while path[:1] == os.sep:
  300.         prefix = prefix + os.sep
  301.         path = path[1:]
  302.     comps = string.splitfields(path, os.sep)
  303.     i = 0
  304.     while i < len(comps):
  305.         if comps[i] == '.':
  306.             del comps[i]
  307.         elif comps[i] == '..' and i > 0 and \
  308.                       comps[i-1] not in ('', '..'):
  309.             del comps[i-1:i+1]
  310.             i = i-1
  311.         elif comps[i] == '' and i > 0 and comps[i-1] <> '':
  312.             del comps[i]
  313.         elif '.' in comps[i]:
  314.             comp = string.splitfields(comps[i], '.')
  315.             comps[i] = comp[0][:8] + '.' + comp[1][:3]
  316.             i = i+1
  317.         elif len(comps[i]) > 8:
  318.             comps[i] = comps[i][:8]
  319.             i = i+1
  320.         else:
  321.             i = i+1
  322.     # If the path is now empty, substitute '.'
  323.     if not prefix and not comps:
  324.         comps.append('.')
  325.     return prefix + string.joinfields(comps, os.sep)
  326.  
  327.  
  328.  
  329. # Return an absolute path.
  330. def abspath(path):
  331.     if not isabs(path):
  332.         path = join(os.getcwd(), path)
  333.     return normpath(path)
  334.