diff options
author | Guido van Rossum <guido@python.org> | 2001-03-02 05:58:11 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-03-02 05:58:11 (GMT) |
commit | 228d80736c39e41a6b46dad211df0ba871b0c8f8 (patch) | |
tree | c15c8ecf8664d6c225b6d2f2821068c31e2302d8 /Lib/plat-riscos | |
parent | c92cdf7aa770ee84a2c8e8f219fde4889e5adc92 (diff) | |
download | cpython-228d80736c39e41a6b46dad211df0ba871b0c8f8.zip cpython-228d80736c39e41a6b46dad211df0ba871b0c8f8.tar.gz cpython-228d80736c39e41a6b46dad211df0ba871b0c8f8.tar.bz2 |
RISCOS files by dschwertberger
Diffstat (limited to 'Lib/plat-riscos')
-rw-r--r-- | Lib/plat-riscos/riscosenviron.py | 46 | ||||
-rw-r--r-- | Lib/plat-riscos/riscospath.py | 354 | ||||
-rw-r--r-- | Lib/plat-riscos/rourl2path.py | 82 |
3 files changed, 482 insertions, 0 deletions
diff --git a/Lib/plat-riscos/riscosenviron.py b/Lib/plat-riscos/riscosenviron.py new file mode 100644 index 0000000..d44aa0a --- /dev/null +++ b/Lib/plat-riscos/riscosenviron.py @@ -0,0 +1,46 @@ +"""A more or less complete user-defined wrapper around dictionary objects.""" + +import riscos + +class _Environ: + def __init__(self): + pass + def __repr__(self): + return repr(riscos.getenvdict()) + def __cmp__(self, dict): + if isinstance(dict, UserDict): + return cmp(riscos.getenvdict(), dict) + def __len__(self): + return len(riscos.getenvdict()) + def __getitem__(self, key): + ret = riscos.getenv(key) + if ret<>None: + return ret + else: + raise KeyError + def __setitem__(self, key, item): + riscos.setenv(key, item) + def __delitem__(self, key): + riscos.delenv(key) + def clear(self): + # too dangerous on RISC OS + pass + def copy(self): + return riscos.getenvdict() + def keys(self): return riscos.getenvdict().keys() + def items(self): return riscos.getenvdict().items() + def values(self): return riscos.getenvdict().values() + def has_key(self, key): + value = riscos.getenv(key) + return value<>None + def update(self, dict): + for k, v in dict.items(): + riscos.putenv(k, v) + def get(self, key, failobj=None): + value = riscos.getenv(key) + if value<>None: + return value + else: + return failobj + +environ = _Environ() diff --git a/Lib/plat-riscos/riscospath.py b/Lib/plat-riscos/riscospath.py new file mode 100644 index 0000000..b83c632 --- /dev/null +++ b/Lib/plat-riscos/riscospath.py @@ -0,0 +1,354 @@ +# Module 'riscospath' -- common operations on RISC OS pathnames. + +# contributed by Andrew Clover ( andrew@oaktree.co.uk ) + +# The "os.path" name is an alias for this module on RISC OS systems; +# on other systems (e.g. Mac, Windows), os.path provides the same +# operations in a manner specific to that platform, and is an alias +# to another module (e.g. macpath, ntpath). + +""" +Instead of importing this module directly, import os and refer to this module +as os.path. +""" + + +# Imports - make an error-generating swi object if the swi module is not +# available (ie. we are not running on RISC OS Python) + +import os, stat, string + +try: + import swi +except ImportError: + class _swi: + def swi(*a): + raise AttributeError, 'This function only available under RISC OS' + block= swi + swi= _swi() + +[_false, _true]= range(2) + +_roots= ['$', '&', '%', '@', '\\'] + + +# _allowMOSFSNames +# After importing riscospath, set _allowMOSFSNames true if you want the module +# to understand the "-SomeFS-" notation left over from the old BBC Master MOS, +# as well as the standard "SomeFS:" notation. Set this to be fully backwards +# compatible but remember that "-SomeFS-" can also be a perfectly valid file +# name so care must be taken when splitting and joining paths. + +_allowMOSFSNames= _false + + +## Path manipulation, RISC OS stylee. + +def _split(p): + """ +split filing system name (including special field) and drive specifier from rest +of path. This is needed by many riscospath functions. +""" + dash= _allowMOSFSNames and p[:1]=='-' + if dash: + q= string.find(p, '-', 1)+1 + else: + if p[:1]==':': + q= 0 + else: + q= string.find(p, ':')+1 # q= index of start of non-FS portion of path + s= string.find(p, '#') + if s==-1 or s>q: + s= q # find end of main FS name, not including special field + else: + for c in p[dash:s]: + if c not in string.letters: + q= 0 + break # disallow invalid non-special-field characters in FS name + r= q + if p[q:q+1]==':': + r= string.find(p, '.', q+1)+1 + if r==0: + r= len(p) # find end of drive name (if any) following FS name (if any) + return (p[:q], p[q:r], p[r:]) + + +def normcase(p): + """ +Normalize the case of a pathname. This converts to lowercase as the native RISC +OS filesystems are case-insensitive. However, not all filesystems have to be, +and there's no simple way to find out what type an FS is argh. +""" + return string.lower(p) + + +def isabs(p): + """ +Return whether a path is absolute. Under RISC OS, a file system specifier does +not make a path absolute, but a drive name or number does, and so does using the +symbol for root, URD, library, CSD or PSD. This means it is perfectly possible +to have an "absolute" URL dependent on the current working directory, and +equally you can have a "relative" URL that's on a completely different device to +the current one argh. +""" + (fs, drive, path)= _split(p) + return drive!='' or path[:1] in _roots + + +def join(a, *p): + """ +Join path elements with the directory separator, replacing the entire path when +an absolute or FS-changing path part is found. +""" + j= a + for b in p: + (fs, drive, path)= _split(b) + if fs!='' or drive!='' or path[:1] in _roots: + j= b + else: + j= j+'.'+b + return j + + +def split(p): + """ +Split a path in head (everything up to the last '.') and tail (the rest). FS +name must still be dealt with separately since special field may contain '.'. +""" + (fs, drive, path)= _split(p) + q= string.rfind(path, '.') + if q!=-1: + return (fs+drive+path[:q], path[q+1:]) + return ('', p) + + +def splitext(p): + """ +Split a path in root and extension. This assumes the 'using slash for dot and +dot for slash with foreign files' convention common in RISC OS is in force. +""" + (tail, head)= split(p) + if '/' in head: + q= len(head)-string.rfind(head, '/') + return (p[:-q], p[-q:]) + return (p, '') + + +def splitdrive(p): + """ +Split a pathname into a drive specification (including FS name) and the rest of +the path. The terminating dot of the drive name is included in the drive +specification. +""" + (fs, drive, path)= _split(p) + return (fs+drive, p) + + +def basename(p): + """ +Return the tail (basename) part of a path. +""" + return split(p)[1] + + +def dirname(p): + """ +Return the head (dirname) part of a path. +""" + return split(p)[0] + + +def commonprefix(ps): + """ +Return the longest prefix of all list elements. Purely string-based; does not +separate any path parts. Why am I in os.path? +""" + if len(ps)==0: + return '' + prefix= ps[0] + for p in ps[1:]: + prefix= prefix[:len(p)] + for i in range(len(prefix)): + if prefix[i] <> p[i]: + prefix= prefix[:i] + if i==0: + return '' + break + return prefix + + +## File access functions. Why are we in os.path? + +def getsize(p): + """ +Return the size of a file, reported by os.stat(). +""" + st= os.stat(p) + return st[stat.ST_SIZE] + + +def getmtime(p): + """ +Return the last modification time of a file, reported by os.stat(). +""" + st = os.stat(p) + return st[stat.ST_MTIME] + +getatime= getmtime + + +# RISC OS-specific file access functions + +def exists(p): + """ +Test whether a path exists. +""" + return swi.swi('OS_File', '5s;i', p)!=0 + + +def isdir(p): + """ +Is a path a directory? Includes image files. +""" + return swi.swi('OS_File', '5s;i', p) in [2, 3] + + +def isfile(p): + """ +Test whether a path is a file, including image files. +""" + return swi.swi('OS_File', '5s;i', p) in [1, 3] + + +def islink(p): + """ +RISC OS has no links or mounts. +""" + return _false + +ismount= islink + + +# Same-file testing. + +# samefile works on filename comparison since there is no ST_DEV and ST_INO is +# not reliably unique (esp. directories). First it has to normalise the +# pathnames, which it can do 'properly' using OS_FSControl since samefile can +# assume it's running on RISC OS (unlike normpath). + +def samefile(fa, fb): + """ +Test whether two pathnames reference the same actual file. +""" + l= 512 + b= swi.block(l) + swi.swi('OS_FSControl', 'isb..i', 37, fa, b, l) + fa= b.ctrlstring() + swi.swi('OS_FSControl', 'isb..i', 37, fb, b, l) + fb= b.ctrlstring() + return fa==fb + + +def sameopenfile(a, b): + """ +Test whether two open file objects reference the same file. +""" + return os.fstat(a)[stat.ST_INO]==os.fstat(b)[stat.ST_INO] + + +## Path canonicalisation + +# 'user directory' is taken as meaning the User Root Directory, which is in +# practice never used, for anything. + +def expanduser(p): + (fs, drive, path)= _split(p) + l= 512 + b= swi.block(l) + + if path[:1]!='@': + return p + if fs=='': + fsno= swi.swi('OS_Args', '00;i') + swi.swi('OS_FSControl', 'iibi', 33, fsno, b, l) + fsname= b.ctrlstring() + else: + if fs[:1]=='-': + fsname= fs[1:-1] + else: + fsname= fs[:-1] + fsname= string.split(fsname, '#', 1)[0] # remove special field from fs + x= swi.swi('OS_FSControl', 'ib2s.i;.....i', 54, b, fsname, l) + if x<l: + urd= b.tostring(0, l-x-1) + else: # no URD! try CSD + x= swi.swi('OS_FSControl', 'ib0s.i;.....i', 54, b, fsname, l) + if x<l: + urd= b.tostring(0, l-x-1) + else: # no CSD! use root + urd= '$' + return fsname+':'+urd+path[1:] + +# Environment variables are in angle brackets. + +def expandvars(p): + """ +Expand environment variables using OS_GSTrans. +""" + l= 512 + b= swi.block(l) + return b.tostring(0, swi.swi('OS_GSTrans', 'sbi;..i', p, b, l)) + + +# Return an absolute path. + +def abspath(p): + return normpath(join(os.getcwd(), p)) + + +# Normalize a path. Only special path element under RISC OS is "^" for "..". + +def normpath(p): + """ +Normalize path, eliminating up-directory ^s. +""" + (fs, drive, path)= _split(p) + rhs= '' + ups= 0 + while path!='': + (path, el)= split(path) + if el=='^': + ups= ups+1 + else: + if ups>0: + ups= ups-1 + else: + if rhs=='': + rhs= el + else: + rhs= el+'.'+rhs + while ups>0: + ups= ups-1 + rhs= '^.'+rhs + return fs+drive+rhs + + +# Directory tree walk. +# Independent of host system. Why am I in os.path? + +def walk(top, func, arg): + """ +walk(top,func,args) calls func(arg, d, files) for each directory "d" in the tree +rooted at "top" (including "top" itself). "files" is a list of all the files and +subdirs in directory "d". +""" + try: + names= os.listdir(top) + except os.error: + return + func(arg, top, names) + for name in names: + name= join(top, name) + if isdir(name) and not islink(name): + walk(name, func, arg) + diff --git a/Lib/plat-riscos/rourl2path.py b/Lib/plat-riscos/rourl2path.py new file mode 100644 index 0000000..033e621 --- /dev/null +++ b/Lib/plat-riscos/rourl2path.py @@ -0,0 +1,82 @@ +"""riscos specific module for conversion between pathnames and URLs. +Based on macurl2path. +Do not import directly, use urllib instead.""" + +import string +import urllib +import os + +def url2pathname(pathname): + "Convert /-delimited pathname to mac pathname" + # + # XXXX The .. handling should be fixed... + # + tp = urllib.splittype(pathname)[0] + if tp and tp <> 'file': + raise RuntimeError, 'Cannot convert non-local URL to pathname' + components = string.split(pathname, '/') + # Remove . and embedded .. + i = 0 + while i < len(components): + if components[i] == '.': + del components[i] + elif components[i] == '..' and i > 0 and \ + components[i-1] not in ('', '..'): + del components[i-1:i+1] + i = i-1 + elif components[i] == '' and i > 0 and components[i-1] <> '': + del components[i] + else: + if components[i]<>'..' and string.find(components[i], '.')<>-1 : + components[i] = string.join(string.split(components[i],'.'),'/') + i = i+1 + if not components[0]: + # Absolute unix path, don't start with colon + return string.join(components[1:], '.') + else: + # relative unix path, start with colon. First replace + # leading .. by empty strings (giving ::file) + i = 0 + while i < len(components) and components[i] == '..': + components[i] = '^' + i = i + 1 + return string.join(components, '.') + +def pathname2url(pathname): + "convert mac pathname to /-delimited pathname" + if '/' in pathname: + raise RuntimeError, "Cannot convert pathname containing slashes" + components = string.split(pathname, ':') + # Replace empty string ('::') by .. (will result in '/../' later) + for i in range(1, len(components)): + if components[i] == '': + components[i] = '..' + # Truncate names longer than 31 bytes + components = map(lambda x: x[:31], components) + + if os.path.isabs(pathname): + return '/' + string.join(components, '/') + else: + return string.join(components, '/') + +def test(): + for url in ["index.html", + "/SCSI::SCSI4/$/Anwendung/Comm/Apps/!Fresco/Welcome", + "../index.html", + "bar/index.html", + "/foo/bar/index.html", + "/foo/bar/", + "/"]: + print `url`, '->', `url2pathname(url)` + for path in ["drive:", + "drive:dir:", + "drive:dir:file", + "drive:file", + "file", + ":file", + ":dir:", + ":dir:file"]: + print `path`, '->', `pathname2url(path)` + +if __name__ == '__main__': + test() |