symbian-qemu-0.9.1-12/python-2.6.1/Lib/plat-riscos/riscospath.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 # Module 'riscospath' -- common operations on RISC OS pathnames.
       
     2 
       
     3 # contributed by Andrew Clover  ( andrew@oaktree.co.uk )
       
     4 
       
     5 # The "os.path" name is an alias for this module on RISC OS systems;
       
     6 # on other systems (e.g. Mac, Windows), os.path provides the same
       
     7 # operations in a manner specific to that platform, and is an alias
       
     8 # to another module (e.g. macpath, ntpath).
       
     9 
       
    10 """
       
    11 Instead of importing this module directly, import os and refer to this module
       
    12 as os.path.
       
    13 """
       
    14 
       
    15 # strings representing various path-related bits and pieces
       
    16 curdir = '@'
       
    17 pardir = '^'
       
    18 extsep = '/'
       
    19 sep = '.'
       
    20 pathsep = ','
       
    21 defpath = '<Run$Dir>'
       
    22 altsep = None
       
    23 
       
    24 # Imports - make an error-generating swi object if the swi module is not
       
    25 # available (ie. we are not running on RISC OS Python)
       
    26 
       
    27 import os, stat, string
       
    28 
       
    29 try:
       
    30     import swi
       
    31 except ImportError:
       
    32     class _swi:
       
    33         def swi(*a):
       
    34             raise AttributeError, 'This function only available under RISC OS'
       
    35         block= swi
       
    36     swi= _swi()
       
    37 
       
    38 [_false, _true]= range(2)
       
    39 
       
    40 _roots= ['$', '&', '%', '@', '\\']
       
    41 
       
    42 
       
    43 # _allowMOSFSNames
       
    44 # After importing riscospath, set _allowMOSFSNames true if you want the module
       
    45 # to understand the "-SomeFS-" notation left over from the old BBC Master MOS,
       
    46 # as well as the standard "SomeFS:" notation. Set this to be fully backwards
       
    47 # compatible but remember that "-SomeFS-" can also be a perfectly valid file
       
    48 # name so care must be taken when splitting and joining paths.
       
    49 
       
    50 _allowMOSFSNames= _false
       
    51 
       
    52 
       
    53 ## Path manipulation, RISC OS stylee.
       
    54 
       
    55 def _split(p):
       
    56     """
       
    57   split filing system name (including special field) and drive specifier from rest
       
    58   of path. This is needed by many riscospath functions.
       
    59   """
       
    60     dash= _allowMOSFSNames and p[:1]=='-'
       
    61     if dash:
       
    62         q= string.find(p, '-', 1)+1
       
    63     else:
       
    64         if p[:1]==':':
       
    65             q= 0
       
    66         else:
       
    67             q= string.find(p, ':')+1 # q= index of start of non-FS portion of path
       
    68     s= string.find(p, '#')
       
    69     if s==-1 or s>q:
       
    70         s= q # find end of main FS name, not including special field
       
    71     else:
       
    72         for c in p[dash:s]:
       
    73             if c not in string.ascii_letters:
       
    74                 q= 0
       
    75                 break # disallow invalid non-special-field characters in FS name
       
    76     r= q
       
    77     if p[q:q+1]==':':
       
    78         r= string.find(p, '.', q+1)+1
       
    79         if r==0:
       
    80             r= len(p) # find end of drive name (if any) following FS name (if any)
       
    81     return (p[:q], p[q:r], p[r:])
       
    82 
       
    83 
       
    84 def normcase(p):
       
    85     """
       
    86   Normalize the case of a pathname. This converts to lowercase as the native RISC
       
    87   OS filesystems are case-insensitive. However, not all filesystems have to be,
       
    88   and there's no simple way to find out what type an FS is argh.
       
    89   """
       
    90     return string.lower(p)
       
    91 
       
    92 
       
    93 def isabs(p):
       
    94     """
       
    95   Return whether a path is absolute. Under RISC OS, a file system specifier does
       
    96   not make a path absolute, but a drive name or number does, and so does using the
       
    97   symbol for root, URD, library, CSD or PSD. This means it is perfectly possible
       
    98   to have an "absolute" URL dependent on the current working directory, and
       
    99   equally you can have a "relative" URL that's on a completely different device to
       
   100   the current one argh.
       
   101   """
       
   102     (fs, drive, path)= _split(p)
       
   103     return drive!='' or path[:1] in _roots
       
   104 
       
   105 
       
   106 def join(a, *p):
       
   107     """
       
   108   Join path elements with the directory separator, replacing the entire path when
       
   109   an absolute or FS-changing path part is found.
       
   110   """
       
   111     j= a
       
   112     for b in p:
       
   113         (fs, drive, path)= _split(b)
       
   114         if j=='' or fs!='' or drive!='' or path[:1] in _roots:
       
   115             j= b
       
   116         elif j[-1]==':':
       
   117             j= j+b
       
   118         else:
       
   119             j= j+'.'+b
       
   120     return j
       
   121 
       
   122 
       
   123 def split(p):
       
   124     """
       
   125   Split a path in head (everything up to the last '.') and tail (the rest). FS
       
   126   name must still be dealt with separately since special field may contain '.'.
       
   127   """
       
   128     (fs, drive, path)= _split(p)
       
   129     q= string.rfind(path, '.')
       
   130     if q!=-1:
       
   131         return (fs+drive+path[:q], path[q+1:])
       
   132     return ('', p)
       
   133 
       
   134 
       
   135 def splitext(p):
       
   136     """
       
   137   Split a path in root and extension. This assumes the 'using slash for dot and
       
   138   dot for slash with foreign files' convention common in RISC OS is in force.
       
   139   """
       
   140     (tail, head)= split(p)
       
   141     if '/' in head:
       
   142         q= len(head)-string.rfind(head, '/')
       
   143         return (p[:-q], p[-q:])
       
   144     return (p, '')
       
   145 
       
   146 
       
   147 def splitdrive(p):
       
   148     """
       
   149   Split a pathname into a drive specification (including FS name) and the rest of
       
   150   the path. The terminating dot of the drive name is included in the drive
       
   151   specification.
       
   152   """
       
   153     (fs, drive, path)= _split(p)
       
   154     return (fs+drive, p)
       
   155 
       
   156 
       
   157 def basename(p):
       
   158     """
       
   159   Return the tail (basename) part of a path.
       
   160   """
       
   161     return split(p)[1]
       
   162 
       
   163 
       
   164 def dirname(p):
       
   165     """
       
   166   Return the head (dirname) part of a path.
       
   167   """
       
   168     return split(p)[0]
       
   169 
       
   170 
       
   171 def commonprefix(m):
       
   172     "Given a list of pathnames, returns the longest common leading component"
       
   173     if not m: return ''
       
   174     s1 = min(m)
       
   175     s2 = max(m)
       
   176     n = min(len(s1), len(s2))
       
   177     for i in xrange(n):
       
   178         if s1[i] != s2[i]:
       
   179             return s1[:i]
       
   180     return s1[:n]
       
   181 
       
   182 
       
   183 ## File access functions. Why are we in os.path?
       
   184 
       
   185 def getsize(p):
       
   186     """
       
   187   Return the size of a file, reported by os.stat().
       
   188   """
       
   189     st= os.stat(p)
       
   190     return st[stat.ST_SIZE]
       
   191 
       
   192 
       
   193 def getmtime(p):
       
   194     """
       
   195   Return the last modification time of a file, reported by os.stat().
       
   196   """
       
   197     st = os.stat(p)
       
   198     return st[stat.ST_MTIME]
       
   199 
       
   200 getatime= getmtime
       
   201 
       
   202 
       
   203 # RISC OS-specific file access functions
       
   204 
       
   205 def exists(p):
       
   206     """
       
   207   Test whether a path exists.
       
   208   """
       
   209     try:
       
   210         return swi.swi('OS_File', '5s;i', p)!=0
       
   211     except swi.error:
       
   212         return 0
       
   213 
       
   214 lexists = exists
       
   215 
       
   216 
       
   217 def isdir(p):
       
   218     """
       
   219   Is a path a directory? Includes image files.
       
   220   """
       
   221     try:
       
   222         return swi.swi('OS_File', '5s;i', p) in [2, 3]
       
   223     except swi.error:
       
   224         return 0
       
   225 
       
   226 
       
   227 def isfile(p):
       
   228     """
       
   229   Test whether a path is a file, including image files.
       
   230   """
       
   231     try:
       
   232         return swi.swi('OS_File', '5s;i', p) in [1, 3]
       
   233     except swi.error:
       
   234         return 0
       
   235 
       
   236 
       
   237 def islink(p):
       
   238     """
       
   239   RISC OS has no links or mounts.
       
   240   """
       
   241     return _false
       
   242 
       
   243 ismount= islink
       
   244 
       
   245 
       
   246 # Same-file testing.
       
   247 
       
   248 # samefile works on filename comparison since there is no ST_DEV and ST_INO is
       
   249 # not reliably unique (esp. directories). First it has to normalise the
       
   250 # pathnames, which it can do 'properly' using OS_FSControl since samefile can
       
   251 # assume it's running on RISC OS (unlike normpath).
       
   252 
       
   253 def samefile(fa, fb):
       
   254     """
       
   255   Test whether two pathnames reference the same actual file.
       
   256   """
       
   257     l= 512
       
   258     b= swi.block(l)
       
   259     swi.swi('OS_FSControl', 'isb..i', 37, fa, b, l)
       
   260     fa= b.ctrlstring()
       
   261     swi.swi('OS_FSControl', 'isb..i', 37, fb, b, l)
       
   262     fb= b.ctrlstring()
       
   263     return fa==fb
       
   264 
       
   265 
       
   266 def sameopenfile(a, b):
       
   267     """
       
   268   Test whether two open file objects reference the same file.
       
   269   """
       
   270     return os.fstat(a)[stat.ST_INO]==os.fstat(b)[stat.ST_INO]
       
   271 
       
   272 
       
   273 ## Path canonicalisation
       
   274 
       
   275 # 'user directory' is taken as meaning the User Root Directory, which is in
       
   276 # practice never used, for anything.
       
   277 
       
   278 def expanduser(p):
       
   279     (fs, drive, path)= _split(p)
       
   280     l= 512
       
   281     b= swi.block(l)
       
   282 
       
   283     if path[:1]!='@':
       
   284         return p
       
   285     if fs=='':
       
   286         fsno= swi.swi('OS_Args', '00;i')
       
   287         swi.swi('OS_FSControl', 'iibi', 33, fsno, b, l)
       
   288         fsname= b.ctrlstring()
       
   289     else:
       
   290         if fs[:1]=='-':
       
   291             fsname= fs[1:-1]
       
   292         else:
       
   293             fsname= fs[:-1]
       
   294         fsname= string.split(fsname, '#', 1)[0] # remove special field from fs
       
   295     x= swi.swi('OS_FSControl', 'ib2s.i;.....i', 54, b, fsname, l)
       
   296     if x<l:
       
   297         urd= b.tostring(0, l-x-1)
       
   298     else: # no URD! try CSD
       
   299         x= swi.swi('OS_FSControl', 'ib0s.i;.....i', 54, b, fsname, l)
       
   300         if x<l:
       
   301             urd= b.tostring(0, l-x-1)
       
   302         else: # no CSD! use root
       
   303             urd= '$'
       
   304     return fsname+':'+urd+path[1:]
       
   305 
       
   306 # Environment variables are in angle brackets.
       
   307 
       
   308 def expandvars(p):
       
   309     """
       
   310   Expand environment variables using OS_GSTrans.
       
   311   """
       
   312     l= 512
       
   313     b= swi.block(l)
       
   314     return b.tostring(0, swi.swi('OS_GSTrans', 'sbi;..i', p, b, l))
       
   315 
       
   316 
       
   317 # Return an absolute path. RISC OS' osfscontrol_canonicalise_path does this among others
       
   318 abspath = os.expand
       
   319 
       
   320 
       
   321 # realpath is a no-op on systems without islink support
       
   322 realpath = abspath
       
   323 
       
   324 
       
   325 # Normalize a path. Only special path element under RISC OS is "^" for "..".
       
   326 
       
   327 def normpath(p):
       
   328     """
       
   329   Normalize path, eliminating up-directory ^s.
       
   330   """
       
   331     (fs, drive, path)= _split(p)
       
   332     rhs= ''
       
   333     ups= 0
       
   334     while path!='':
       
   335         (path, el)= split(path)
       
   336         if el=='^':
       
   337             ups= ups+1
       
   338         else:
       
   339             if ups>0:
       
   340                 ups= ups-1
       
   341             else:
       
   342                 if rhs=='':
       
   343                     rhs= el
       
   344                 else:
       
   345                     rhs= el+'.'+rhs
       
   346     while ups>0:
       
   347         ups= ups-1
       
   348         rhs= '^.'+rhs
       
   349     return fs+drive+rhs
       
   350 
       
   351 
       
   352 # Directory tree walk.
       
   353 # Independent of host system. Why am I in os.path?
       
   354 
       
   355 def walk(top, func, arg):
       
   356     """Directory tree walk with callback function.
       
   357 
       
   358     For each directory in the directory tree rooted at top (including top
       
   359     itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
       
   360     dirname is the name of the directory, and fnames a list of the names of
       
   361     the files and subdirectories in dirname (excluding '.' and '..').  func
       
   362     may modify the fnames list in-place (e.g. via del or slice assignment),
       
   363     and walk will only recurse into the subdirectories whose names remain in
       
   364     fnames; this can be used to implement a filter, or to impose a specific
       
   365     order of visiting.  No semantics are defined for, or required of, arg,
       
   366     beyond that arg is always passed to func.  It can be used, e.g., to pass
       
   367     a filename pattern, or a mutable object designed to accumulate
       
   368     statistics.  Passing None for arg is common."""
       
   369 
       
   370     try:
       
   371         names= os.listdir(top)
       
   372     except os.error:
       
   373         return
       
   374     func(arg, top, names)
       
   375     for name in names:
       
   376         name= join(top, name)
       
   377         if isdir(name) and not islink(name):
       
   378             walk(name, func, arg)