blob: df333864a8a6fa1ce8e4f783a9e6a417a3077e4d [file] [log] [blame]
"""Common pathname manipulations, JDK version.
Instead of importing this module directly, import os and refer to this
module as os.path.
"""
# Incompletely implemented:
# ismount -- How?
# normcase -- How?
# Missing:
# sameopenfile -- Java doesn't have fstat nor file descriptors?
# samestat -- How?
import stat
import sys
from java.io import File
import java.io.IOException
from java.lang import System
import os
from org.python.core.Py import newString as asPyString
def _tostr(s, method):
if isinstance(s, basestring):
return s
raise TypeError, "%s() argument must be a str or unicode object, not %s" % (
method, _type_name(s))
def _type_name(obj):
TPFLAGS_HEAPTYPE = 1 << 9
type_name = ''
obj_type = type(obj)
is_heap = obj_type.__flags__ & TPFLAGS_HEAPTYPE == TPFLAGS_HEAPTYPE
if not is_heap and obj_type.__module__ != '__builtin__':
type_name = '%s.' % obj_type.__module__
type_name += obj_type.__name__
return type_name
def dirname(path):
"""Return the directory component of a pathname"""
path = _tostr(path, "dirname")
result = asPyString(File(path).getParent())
if not result:
if isabs(path):
result = path # Must be root
else:
result = ""
return result
def basename(path):
"""Return the final component of a pathname"""
path = _tostr(path, "basename")
return asPyString(File(path).getName())
def split(path):
"""Split a pathname.
Return tuple "(head, tail)" where "tail" is everything after the
final slash. Either part may be empty.
"""
path = _tostr(path, "split")
return (dirname(path), basename(path))
def splitext(path):
"""Split the extension from a pathname.
Extension is everything from the last dot to the end. Return
"(root, ext)", either part may be empty.
"""
i = 0
n = -1
for c in path:
if c == '.': n = i
i = i+1
if n < 0:
return (path, "")
else:
return (path[:n], path[n:])
def splitdrive(path):
"""Split a pathname into drive and path specifiers.
Returns a 2-tuple "(drive,path)"; either part may be empty.
"""
# Algorithm based on CPython's ntpath.splitdrive and ntpath.isabs.
if path[1:2] == ':' and path[0].lower() in 'abcdefghijklmnopqrstuvwxyz' \
and (path[2:] == '' or path[2] in '/\\'):
return path[:2], path[2:]
return '', path
def exists(path):
"""Test whether a path exists.
Returns false for broken symbolic links.
"""
path = _tostr(path, "exists")
return File(sys.getPath(path)).exists()
def isabs(path):
"""Test whether a path is absolute"""
path = _tostr(path, "isabs")
return File(path).isAbsolute()
def isfile(path):
"""Test whether a path is a regular file"""
path = _tostr(path, "isfile")
return File(sys.getPath(path)).isFile()
def isdir(path):
"""Test whether a path is a directory"""
path = _tostr(path, "isdir")
return File(sys.getPath(path)).isDirectory()
def join(path, *args):
"""Join two or more pathname components, inserting os.sep as needed"""
path = _tostr(path, "join")
f = File(path)
for a in args:
a = _tostr(a, "join")
g = File(a)
if g.isAbsolute() or len(f.getPath()) == 0:
f = g
else:
if a == "":
a = os.sep
f = File(f, a)
return asPyString(f.getPath())
def normcase(path):
"""Normalize case of pathname.
XXX Not done right under JDK.
"""
path = _tostr(path, "normcase")
return asPyString(File(path).getPath())
def commonprefix(m):
"Given a list of pathnames, return the longest common leading component"
if not m: return ''
prefix = m[0]
for item in m:
for i in range(len(prefix)):
if prefix[:i+1] <> item[:i+1]:
prefix = prefix[:i]
if i == 0: return ''
break
return prefix
def islink(path):
"""Test whether a path is a symbolic link"""
try:
st = os.lstat(path)
except (os.error, AttributeError):
return False
return stat.S_ISLNK(st.st_mode)
def samefile(path, path2):
"""Test whether two pathnames reference the same actual file"""
path = _tostr(path, "samefile")
path2 = _tostr(path2, "samefile")
return _realpath(path) == _realpath(path2)
def ismount(path):
"""Test whether a path is a mount point.
XXX This incorrectly always returns false under JDK.
"""
return 0
def walk(top, func, arg):
"""Walk a directory tree.
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)
def expanduser(path):
if path[:1] == "~":
c = path[1:2]
if not c:
return gethome()
if c == os.sep:
return asPyString(File(gethome(), path[2:]).getPath())
return path
def getuser():
return System.getProperty("user.name")
def gethome():
return System.getProperty("user.home")
# normpath() from Python 1.5.2, with Java appropriate generalizations
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
# It should be understood that this may change the meaning of the path
# if it contains symbolic links!
def normpath(path):
"""Normalize path, eliminating double slashes, etc."""
sep = os.sep
if sep == '\\':
path = path.replace("/", sep)
curdir = os.curdir
pardir = os.pardir
import string
# Treat initial slashes specially
slashes = ''
while path[:1] == sep:
slashes = slashes + sep
path = path[1:]
comps = string.splitfields(path, sep)
i = 0
while i < len(comps):
if comps[i] == curdir:
del comps[i]
while i < len(comps) and comps[i] == '':
del comps[i]
elif comps[i] == pardir and i > 0 and comps[i-1] not in ('', pardir):
del comps[i-1:i+1]
i = i-1
elif comps[i] == '' and i > 0 and comps[i-1] <> '':
del comps[i]
else:
i = i+1
# If the path is now empty, substitute '.'
if not comps and not slashes:
comps.append(curdir)
return slashes + string.joinfields(comps, sep)
def abspath(path):
"""Return an absolute path normalized but symbolic links not eliminated"""
path = _tostr(path, "abspath")
return _abspath(path)
def _abspath(path):
# Must use normpath separately because getAbsolutePath doesn't normalize
# and getCanonicalPath would eliminate symlinks.
return normpath(asPyString(File(sys.getPath(path)).getAbsolutePath()))
def realpath(path):
"""Return an absolute path normalized and symbolic links eliminated"""
path = _tostr(path, "realpath")
return _realpath(path)
def _realpath(path):
try:
return asPyString(File(sys.getPath(path)).getCanonicalPath())
except java.io.IOException:
return _abspath(path)
def getsize(path):
path = _tostr(path, "getsize")
f = File(sys.getPath(path))
size = f.length()
# Sadly, if the returned length is zero, we don't really know if the file
# is zero sized or does not exist.
if size == 0 and not f.exists():
raise OSError(0, 'No such file or directory', path)
return size
def getmtime(path):
path = _tostr(path, "getmtime")
f = File(sys.getPath(path))
if not f.exists():
raise OSError(0, 'No such file or directory', path)
return f.lastModified() / 1000.0
def getatime(path):
# We can't detect access time so we return modification time. This
# matches the behaviour in os.stat().
path = _tostr(path, "getatime")
f = File(sys.getPath(path))
if not f.exists():
raise OSError(0, 'No such file or directory', path)
return f.lastModified() / 1000.0
# expandvars is stolen from CPython-2.1.1's Lib/ntpath.py:
# Expand paths containing shell variable substitutions.
# The following rules apply:
# - no expansion within single quotes
# - no escape character, except for '$$' which is translated into '$'
# - ${varname} is accepted.
# - varnames can be made out of letters, digits and the character '_'
# XXX With COMMAND.COM you can use any characters in a variable name,
# XXX except '^|<>='.
def expandvars(path):
"""Expand shell variables of form $var and ${var}.
Unknown variables are left unchanged."""
if '$' not in path:
return path
import string
varchars = string.letters + string.digits + '_-'
res = ''
index = 0
pathlen = len(path)
while index < pathlen:
c = path[index]
if c == '\'': # no expansion within single quotes
path = path[index + 1:]
pathlen = len(path)
try:
index = path.index('\'')
res = res + '\'' + path[:index + 1]
except ValueError:
res = res + path
index = pathlen - 1
elif c == '$': # variable or '$$'
if path[index + 1:index + 2] == '$':
res = res + c
index = index + 1
elif path[index + 1:index + 2] == '{':
path = path[index+2:]
pathlen = len(path)
try:
index = path.index('}')
var = path[:index]
if os.environ.has_key(var):
res = res + os.environ[var]
except ValueError:
res = res + path
index = pathlen - 1
else:
var = ''
index = index + 1
c = path[index:index + 1]
while c != '' and c in varchars:
var = var + c
index = index + 1
c = path[index:index + 1]
if os.environ.has_key(var):
res = res + os.environ[var]
if c != '':
res = res + c
else:
res = res + c
index = index + 1
return res