home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Lib / posixpath.py < prev    next >
Text File  |  1994-04-18  |  7KB  |  301 lines

  1. # Module 'posixpath' -- common operations on POSIX pathnames
  2.  
  3. import posix
  4. import stat
  5.  
  6.  
  7. # Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
  8. # On MS-DOS this may also turn slashes into backslashes; however, other
  9. # normalizations (such as optimizing '../' away) are not allowed
  10. # (another function should be defined to do that).
  11.  
  12. def normcase(s):
  13.     return s
  14.  
  15.  
  16. # Return wheter a path is absolute.
  17. # Trivial in Posix, harder on the Mac or MS-DOS.
  18.  
  19. def isabs(s):
  20.     return s[:1] == '/'
  21.  
  22.  
  23. # Join two pathnames.
  24. # Ignore the first part if the second part is absolute.
  25. # Insert a '/' unless the first part is empty or already ends in '/'.
  26.  
  27. def join(a, b):
  28.     if b[:1] == '/': return b
  29.     if a == '' or a[-1:] == '/': return a + b
  30.     # Note: join('x', '') returns 'x/'; is this what we want?
  31.     return a + '/' + b
  32.  
  33.  
  34. # Split a path in head (everything up to the last '/') and tail (the
  35. # rest).  If the original path ends in '/' but is not the root, this
  36. # '/' is stripped.  After the trailing '/' is stripped, the invariant
  37. # join(head, tail) == p holds.
  38. # The resulting head won't end in '/' unless it is the root.
  39.  
  40. def split(p):
  41.     if p[-1:] == '/' and p <> '/'*len(p):
  42.         while p[-1] == '/':
  43.             p = p[:-1]
  44.     head, tail = '', ''
  45.     for c in p:
  46.         tail = tail + c
  47.         if c == '/':
  48.             head, tail = head + tail, ''
  49.     if head[-1:] == '/' and head <> '/'*len(head):
  50.         while head[-1] == '/':
  51.             head = head[:-1]
  52.     return head, tail
  53.  
  54.  
  55. # Split a path in root and extension.
  56. # The extension is everything starting at the first dot in the last
  57. # pathname component; the root is everything before that.
  58. # It is always true that root + ext == p.
  59.  
  60. def splitext(p):
  61.     root, ext = '', ''
  62.     for c in p:
  63.         if c == '/':
  64.             root, ext = root + ext + c, ''
  65.         elif c == '.' or ext:
  66.             ext = ext + c
  67.         else:
  68.             root = root + c
  69.     return root, ext
  70.  
  71.  
  72. # Return the tail (basename) part of a path.
  73.  
  74. def basename(p):
  75.     return split(p)[1]
  76.  
  77.  
  78. # Return the head (dirname) part of a path.
  79.  
  80. def dirname(p):
  81.     return split(p)[0]
  82.  
  83.  
  84. # Return the longest prefix of all list elements.
  85.  
  86. def commonprefix(m):
  87.     if not m: return ''
  88.     prefix = m[0]
  89.     for item in m:
  90.         for i in range(len(prefix)):
  91.             if prefix[:i+1] <> item[:i+1]:
  92.                 prefix = prefix[:i]
  93.                 if i == 0: return ''
  94.                 break
  95.     return prefix
  96.  
  97.  
  98. # Is a path a symbolic link?
  99. # This will always return false on systems where posix.lstat doesn't exist.
  100.  
  101. def islink(path):
  102.     try:
  103.         st = posix.lstat(path)
  104.     except (posix.error, AttributeError):
  105.         return 0
  106.     return stat.S_ISLNK(st[stat.ST_MODE])
  107.  
  108.  
  109. # Does a path exist?
  110. # This is false for dangling symbolic links.
  111.  
  112. def exists(path):
  113.     try:
  114.         st = posix.stat(path)
  115.     except posix.error:
  116.         return 0
  117.     return 1
  118.  
  119.  
  120. # Is a path a posix directory?
  121. # This follows symbolic links, so both islink() and isdir() can be true
  122. # for the same path.
  123.  
  124. def isdir(path):
  125.     try:
  126.         st = posix.stat(path)
  127.     except posix.error:
  128.         return 0
  129.     return stat.S_ISDIR(st[stat.ST_MODE])
  130.  
  131.  
  132. # Is a path a regular file?
  133. # This follows symbolic links, so both islink() and isdir() can be true
  134. # for the same path.
  135.  
  136. def isfile(path):
  137.     try:
  138.         st = posix.stat(path)
  139.     except posix.error:
  140.         return 0
  141.     return stat.S_ISREG(st[stat.ST_MODE])
  142.  
  143.  
  144. # Are two filenames really pointing to the same file?
  145.  
  146. def samefile(f1, f2):
  147.     s1 = posix.stat(f1)
  148.     s2 = posix.stat(f2)
  149.     return samestat(s1, s2)
  150.  
  151.  
  152. # Are two open files really referencing the same file?
  153. # (Not necessarily the same file descriptor!)
  154. # XXX Oops, posix.fstat() doesn't exist yet!
  155.  
  156. def sameopenfile(fp1, fp2):
  157.     s1 = posix.fstat(fp1)
  158.     s2 = posix.fstat(fp2)
  159.     return samestat(s1, s2)
  160.  
  161.  
  162. # Are two stat buffers (obtained from stat, fstat or lstat)
  163. # describing the same file?
  164.  
  165. def samestat(s1, s2):
  166.     return s1[stat.ST_INO] == s2[stat.ST_INO] and \
  167.         s1[stat.ST_DEV] == s2[stat.ST_DEV]
  168.  
  169.  
  170. # Is a path a mount point?
  171. # (Does this work for all UNIXes?  Is it even guaranteed to work by POSIX?)
  172.  
  173. def ismount(path):
  174.     try:
  175.         s1 = posix.stat(path)
  176.         s2 = posix.stat(join(path, '..'))
  177.     except posix.error:
  178.         return 0 # It doesn't exist -- so not a mount point :-)
  179.     dev1 = s1[stat.ST_DEV]
  180.     dev2 = s2[stat.ST_DEV]
  181.     if dev1 != dev2:
  182.         return 1        # path/.. on a different device as path
  183.     ino1 = s1[stat.ST_INO]
  184.     ino2 = s2[stat.ST_INO]
  185.     if ino1 == ino2:
  186.         return 1        # path/.. is the same i-node as path
  187.     return 0
  188.  
  189.  
  190. # Directory tree walk.
  191. # For each directory under top (including top itself, but excluding
  192. # '.' and '..'), func(arg, dirname, filenames) is called, where
  193. # dirname is the name of the directory and filenames is the list
  194. # files files (and subdirectories etc.) in the directory.
  195. # The func may modify the filenames list, to implement a filter,
  196. # or to impose a different order of visiting.
  197.  
  198. def walk(top, func, arg):
  199.     try:
  200.         names = posix.listdir(top)
  201.     except posix.error:
  202.         return
  203.     func(arg, top, names)
  204.     exceptions = ('.', '..')
  205.     for name in names:
  206.         if name not in exceptions:
  207.             name = join(top, name)
  208.             if isdir(name):
  209.                 walk(name, func, arg)
  210.  
  211.  
  212. # Expand paths beginning with '~' or '~user'.
  213. # '~' means $HOME; '~user' means that user's home directory.
  214. # If the path doesn't begin with '~', or if the user or $HOME is unknown,
  215. # the path is returned unchanged (leaving error reporting to whatever
  216. # function is called with the expanded path as argument).
  217. # See also module 'glob' for expansion of *, ? and [...] in pathnames.
  218. # (A function should also be defined to do full *sh-style environment
  219. # variable expansion.)
  220.  
  221. def expanduser(path):
  222.     if path[:1] <> '~':
  223.         return path
  224.     i, n = 1, len(path)
  225.     while i < n and path[i] <> '/':
  226.         i = i+1
  227.     if i == 1:
  228.         if not posix.environ.has_key('HOME'):
  229.             return path
  230.         userhome = posix.environ['HOME']
  231.     else:
  232.         import pwd
  233.         try:
  234.             pwent = pwd.getpwnam(path[1:i])
  235.         except KeyError:
  236.             return path
  237.         userhome = pwent[5]
  238.     return userhome + path[i:]
  239.  
  240.  
  241. # Expand paths containing shell variable substitutions.
  242. # This expands the forms $variable and ${variable} only.
  243. # Non-existant variables are left unchanged.
  244.  
  245. _varprog = None
  246.  
  247. def expandvars(path):
  248.     global _varprog
  249.     if '$' not in path:
  250.         return path
  251.     if not _varprog:
  252.         import regex
  253.         _varprog = regex.compile('$\([a-zA-Z0-9_]+\|{[^}]*}\)')
  254.     i = 0
  255.     while 1:
  256.         i = _varprog.search(path, i)
  257.         if i < 0:
  258.             break
  259.         name = _varprog.group(1)
  260.         j = i + len(_varprog.group(0))
  261.         if name[:1] == '{' and name[-1:] == '}':
  262.             name = name[1:-1]
  263.         if posix.environ.has_key(name):
  264.             tail = path[j:]
  265.             path = path[:i] + posix.environ[name]
  266.             i = len(path)
  267.             path = path + tail
  268.         else:
  269.             i = j
  270.     return path
  271.  
  272.  
  273. # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
  274. # It should be understood that this may change the meaning of the path
  275. # if it contains symbolic links!
  276.  
  277. def normpath(path):
  278.     import string
  279.     # Treat initial slashes specially
  280.     slashes = ''
  281.     while path[:1] == '/':
  282.         slashes = slashes + '/'
  283.         path = path[1:]
  284.     comps = string.splitfields(path, '/')
  285.     i = 0
  286.     while i < len(comps):
  287.         if comps[i] == '.':
  288.             del comps[i]
  289.         elif comps[i] == '..' and i > 0 and \
  290.                       comps[i-1] not in ('', '..'):
  291.             del comps[i-1:i+1]
  292.             i = i-1
  293.         elif comps[i] == '' and i > 0 and comps[i-1] <> '':
  294.             del comps[i]
  295.         else:
  296.             i = i+1
  297.     # If the path is now empty, substitute '.'
  298.     if not comps and not slashes:
  299.         comps.append('.')
  300.     return slashes + string.joinfields(comps, '/')
  301.