Changeset 3426


Ignore:
Timestamp:
Jun 14, 2007, 3:54:22 AM (18 years ago)
Author:
bird
Message:

os2knixpath.

Location:
trunk/essentials/dev-lang/python/Lib
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/essentials/dev-lang/python/Lib/os.py

    r3403 r3426  
    7575    except ImportError:
    7676        pass
    77     # if sys.version.find('EMX GCC') == -1 and sys.platform != 'os2knix':
    78     if sys.version.find('EMX GCC') == -1:
     77    if sys.platform == 'os2knix':
     78        import os2knixpath as path
     79    elif sys.version.find('EMX GCC') == -1:
    7980        import ntpath as path
    8081    else:
  • trunk/essentials/dev-lang/python/Lib/os2knixpath.py

    r3420 r3426  
    1 # Module 'os2emxpath' -- common operations on OS/2 pathnames
    2 """Common pathname manipulations, OS/2 EMX version.
    3 
    4 Instead of importing this module directly, import os and refer to this
    5 module as os.path.
     1"""Common operations on OS/2 kNIX pathnames.
     2
     3Instead of importing this module directly, import os and refer to
     4this module as os.path.  The "os.path" name is an alias for this
     5module on OS/2 kNIX Posix; on other systems (e.g. Mac, Windows),
     6os.path provides the same operations in a manner specific to that
     7platform, and is an alias to another module (e.g. macpath, ntpath).
     8
     9This is slightly different from both OS/2 EMX and POSIX, so in order
     10to avoid messing up those sources, the kNIX code has got a separate
     11file that drags from both EMX and POSIX.
    612"""
    713
     
    1117__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
    1218           "basename","dirname","commonprefix","getsize","getmtime",
    13            "getatime","getctime", "islink","exists","lexists","isdir","isfile",
     19           "getatime","getctime","islink","exists","lexists","isdir","isfile",
    1420           "ismount","walk","expanduser","expandvars","normpath","abspath",
    15            "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
    16            "extsep","devnull","realpath","supports_unicode_filenames"]
     21           "samefile","sameopenfile","samestat",
     22           "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
     23           "devnull","realpath","supports_unicode_filenames",
     24           "splitunc"]
    1725
    1826# strings representing various path-related bits and pieces
     
    2331altsep = '\\'
    2432pathsep = ';'
    25 defpath = '.;C:\\bin'
     33defpath = '.;/@unixroot/bin;/@unixroot/usr/bin;/@unixroot/usr/local/bin'
    2634devnull = 'nul'
    2735
    28 # Normalize the case of a pathname and map slashes to backslashes.
    29 # Other normalizations (such as optimizing '../' away) are not done
    30 # (this is done by normpath).
     36# Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
     37# On MS-DOS this may also turn slashes into backslashes; however, other
     38# normalizations (such as optimizing '../' away) are not allowed
     39# (another function should be defined to do that).
    3140
    3241def normcase(s):
    3342    """Normalize case of pathname.
    3443
    35     Makes all characters lowercase and all altseps into seps."""
    36     return s.replace('\\', '/').lower()
     44    XXX: This needs to call some kLIBC function to do case corrections, but
     45         I'm not up do that right now.
     46    """
     47    return s.replace('\\', '/')
    3748
    3849
     
    4960
    5061
    51 # Join two (or more) paths.
     62# Join pathnames.
     63# Ignore the previous parts if a part is absolute.
     64# Insert a '/' unless the first part is empty or already ends in '/'.
    5265
    5366def join(a, *p):
    54     """Join two or more pathname components, inserting sep as needed"""
     67    """Join two or more pathname components, inserting '/' as needed"""
    5568    path = a
    5669    for b in p:
     
    105118
    106119# Split a path in head (everything up to the last '/') and tail (the
    107 # rest).  After the trailing '/' is stripped, the invariant
    108 # join(head, tail) == p holds.
    109 # The resulting head won't end in '/' unless it is the root.
     120# rest).  If the path ends in '/', tail will be empty.  If there is no
     121# '/' in the path, head  will be empty.
     122# Trailing '/'es are stripped from head unless it is the root.
    110123
    111124def split(p):
    112     """Split a pathname.
    113 
    114     Return tuple (head, tail) where tail is everything after the final slash.
    115     Either part may be empty."""
     125    """Split a pathname.  Returns tuple "(head, tail)" where "tail" is
     126    everything after the final slash.  Either part may be empty."""
    116127
    117128    d, p = splitdrive(p)
     
    182193    return s1[:n]
    183194
    184 
    185195# Get size, mtime, atime of files.
    186196
    187197def getsize(filename):
    188     """Return the size of a file, reported by os.stat()"""
     198    """Return the size of a file, reported by os.stat()."""
    189199    return os.stat(filename).st_size
    190200
    191201def getmtime(filename):
    192     """Return the last modification time of a file, reported by os.stat()"""
     202    """Return the last modification time of a file, reported by os.stat()."""
    193203    return os.stat(filename).st_mtime
    194204
    195205def getatime(filename):
    196     """Return the last access time of a file, reported by os.stat()"""
     206    """Return the last access time of a file, reported by os.stat()."""
    197207    return os.stat(filename).st_atime
    198208
    199209def getctime(filename):
    200     """Return the creation time of a file, reported by os.stat()."""
     210    """Return the metadata change time of a file, reported by os.stat()."""
    201211    return os.stat(filename).st_ctime
    202212
    203213# Is a path a symbolic link?
    204 # This will always return false on systems where posix.lstat doesn't exist.
     214# This will always return false on systems where os.lstat doesn't exist.
    205215
    206216def islink(path):
    207     """Test for symbolic link.  On OS/2 always returns false"""
    208     return False
     217    """Test whether a path is a symbolic link"""
     218    try:
     219        st = os.lstat(path)
     220    except (os.error, AttributeError):
     221        return False
     222    return stat.S_ISLNK(st.st_mode)
    209223
    210224
     
    213227
    214228def exists(path):
    215     """Test whether a path exists"""
     229    """Test whether a path exists.  Returns False for broken symbolic links"""
    216230    try:
    217231        st = os.stat(path)
     
    220234    return True
    221235
    222 lexists = exists
     236
     237# Being true for dangling symbolic links is also useful.
     238
     239def lexists(path):
     240    """Test whether a path exists.  Returns True for broken symbolic links"""
     241    try:
     242        st = os.lstat(path)
     243    except os.error:
     244        return False
     245    return True
    223246
    224247
    225248# Is a path a directory?
     249# This follows symbolic links, so both islink() and isdir() can be true
     250# for the same path.
    226251
    227252def isdir(path):
     
    235260
    236261# Is a path a regular file?
    237 # This follows symbolic links, so both islink() and isdir() can be true
     262# This follows symbolic links, so both islink() and isfile() can be true
    238263# for the same path.
    239264
     
    247272
    248273
     274# Are two filenames really pointing to the same file?
     275
     276def samefile(f1, f2):
     277    """Test whether two pathnames reference the same actual file"""
     278    s1 = os.stat(f1)
     279    s2 = os.stat(f2)
     280    return samestat(s1, s2)
     281
     282
     283# Are two open files really referencing the same file?
     284# (Not necessarily the same file descriptor!)
     285
     286def sameopenfile(fp1, fp2):
     287    """Test whether two open file objects reference the same file"""
     288    s1 = os.fstat(fp1)
     289    s2 = os.fstat(fp2)
     290    return samestat(s1, s2)
     291
     292
     293# Are two stat buffers (obtained from stat, fstat or lstat)
     294# describing the same file?
     295
     296def samestat(s1, s2):
     297    """Test whether two stat buffers reference the same file"""
     298    return s1.st_ino == s2.st_ino and \
     299           s1.st_dev == s2.st_dev
     300
     301
    249302# Is a path a mount point?  Either a root (with or without drive letter)
    250303# or an UNC path with at most a / or \ after the mount point.
    251304
    252305def ismount(path):
    253     """Test whether a path is a mount point (defined as root of drive)"""
     306    """Test whether a path is a mount point (defined as root of drive)
     307    XXX: this isn't correct for if path is a symlink!
     308    """
    254309    unc, rest = splitunc(path)
    255310    if unc:
     
    268323
    269324def walk(top, func, arg):
    270     """Directory tree walk whth callback function.
    271 
    272     walk(top, func, arg) calls func(arg, d, files) for each directory d
    273     in the tree rooted at top (including top itself); files is a list
    274     of all the files and subdirs in directory d."""
     325    """Directory tree walk with callback function.
     326
     327    For each directory in the directory tree rooted at top (including top
     328    itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
     329    dirname is the name of the directory, and fnames a list of the names of
     330    the files and subdirectories in dirname (excluding '.' and '..').  func
     331    may modify the fnames list in-place (e.g. via del or slice assignment),
     332    and walk will only recurse into the subdirectories whose names remain in
     333    fnames; this can be used to implement a filter, or to impose a specific
     334    order of visiting.  No semantics are defined for, or required of, arg,
     335    beyond that arg is always passed to func.  It can be used, e.g., to pass
     336    a filename pattern, or a mutable object designed to accumulate
     337    statistics.  Passing None for arg is common."""
    275338    try:
    276339        names = os.listdir(top)
     
    307370        if 'HOME' in os.environ:
    308371            userhome = os.environ['HOME']
    309         elif not 'HOMEPATH' in os.environ:
    310             return path
    311         else:
     372        elif 'HOMEPATH' in os.environ:
    312373            try:
    313374                drive = os.environ['HOMEDRIVE']
     
    315376                drive = ''
    316377            userhome = join(drive, os.environ['HOMEPATH'])
     378        else:
     379            import pwd
     380            userhome = pwd.getpwuid(os.getuid()).pw_dir
    317381    else:
    318         return path
     382        import pwd
     383        try:
     384            pwent = pwd.getpwnam(path[1:i])
     385        except KeyError:
     386            return path
     387        userhome = pwent.pw_dir
     388
     389    if userhome.endswith('/') or userhome.endswith('\\'):
     390        i += 1
    319391    return userhome + path[i:]
    320392
     
    418490    return normpath(path)
    419491
    420 # realpath is a no-op on systems without islink support
    421 realpath = abspath
     492
     493# Return a canonical path (i.e. the absolute location of a file on the
     494# filesystem).
     495
     496def realpath(filename):
     497    """Return the canonical path of the specified filename, eliminating any
     498symbolic links encountered in the path."""
     499    filename.replace('\\', '/') # simpler this way..
     500    if isabs(filename):
     501        bits = ['/'] + filename.split('/')[1:]
     502    else:
     503        bits = [''] + filename.split('/')
     504
     505    for i in range(2, len(bits)+1):
     506        component = join(*bits[0:i])
     507        # Resolve symbolic links.
     508        if islink(component):
     509            resolved = _resolve_link(component)
     510            if resolved is None:
     511                # Infinite loop -- return original component + rest of the path
     512                return abspath(join(*([component] + bits[i:])))
     513            else:
     514                newpath = join(*([resolved] + bits[i:]))
     515                return realpath(newpath)
     516
     517    return abspath(filename)
     518
     519
     520def _resolve_link(path):
     521    """Internal helper function.  Takes a path and follows symlinks
     522    until we either arrive at something that isn't a symlink, or
     523    encounter a path we've seen before (meaning that there's a loop).
     524    """
     525    paths_seen = []
     526    while islink(path):
     527        if path in paths_seen:
     528            # Already seen this path, so we must have a symlink loop
     529            return None
     530        paths_seen.append(path)
     531        # Resolve where the link points to
     532        resolved = os.readlink(path)
     533        if not isabs(resolved):
     534            dir = dirname(path)
     535            path = normpath(join(dir, resolved))
     536        else:
     537            path = normpath(resolved)
     538    return path
    422539
    423540supports_unicode_filenames = False
     541
Note: See TracChangeset for help on using the changeset viewer.