diff -r 524a032c8e0f Doc/library/os.rst --- a/Doc/library/os.rst Tue Feb 21 22:10:16 2012 +0100 +++ b/Doc/library/os.rst Wed Feb 22 00:46:11 2012 +0100 @@ -1881,6 +1881,16 @@ Files and Directories Added support for Windows 6.0 (Vista) symbolic links. +.. function:: realpath(path) + + Return a string representing the canonicalized pathname of *path*. + See :manpage:`realpath(3)` for more information. + + Availability: Unix + + .. versionadded:: 3.3 + + .. function:: remove(path) Remove (delete) the file *path*. If *path* is a directory, :exc:`OSError` is diff -r 524a032c8e0f Lib/posixpath.py --- a/Lib/posixpath.py Tue Feb 21 22:10:16 2012 +0100 +++ b/Lib/posixpath.py Wed Feb 22 00:46:11 2012 +0100 @@ -380,32 +380,11 @@ def abspath(path): def realpath(filename): """Return the canonical path of the specified filename, eliminating any -symbolic links encountered in the path.""" - if isinstance(filename, bytes): - sep = b'/' - empty = b'' + symbolic links encountered in the path.""" + if filename: + return os.realpath(filename) else: - sep = '/' - empty = '' - if isabs(filename): - bits = [sep] + filename.split(sep)[1:] - else: - bits = [empty] + filename.split(sep) - - for i in range(2, len(bits)+1): - component = join(*bits[0:i]) - # Resolve symbolic links. - if islink(component): - resolved = _resolve_link(component) - if resolved is None: - # Infinite loop -- return original component + rest of the path - return abspath(join(*([component] + bits[i:]))) - else: - newpath = join(*([resolved] + bits[i:])) - return realpath(newpath) - - return abspath(filename) - + return os.getcwd() def _resolve_link(path): """Internal helper function. Takes a path and follows symlinks diff -r 524a032c8e0f Modules/posixmodule.c --- a/Modules/posixmodule.c Tue Feb 21 22:10:16 2012 +0100 +++ b/Modules/posixmodule.c Wed Feb 22 00:46:11 2012 +0100 @@ -8167,6 +8167,46 @@ win32__getdiskusage(PyObject *self, PyOb #endif +#ifdef HAVE_REALPATH +PyDoc_STRVAR(posix_realpath__doc__, +"realpath(path) -> path\n\n\ +Return the canonicalized pathname of the given path."); + +static PyObject * +posix_realpath(PyObject *self, PyObject *args) +{ + PyObject *opath, *orpath; + char *path, *rpath; +#ifndef HAVE_CANONICALIZE_FILE_NAME + char buffer[MAXPATHLEN]; +#endif + + if (!PyArg_ParseTuple(args, "O&:realpath", + PyUnicode_FSConverter, &opath)) + return NULL; + path = PyBytes_AsString(opath); + +#ifdef HAVE_CANONICALIZE_FILE_NAME + Py_BEGIN_ALLOW_THREADS + rpath = canonicalize_file_name(path); + Py_END_ALLOW_THREADS +#else + Py_BEGIN_ALLOW_THREADS + rpath = realpath(path, buffer); + Py_END_ALLOW_THREADS +#endif + if (rpath == NULL) + return posix_error_with_allocated_filename(opath); + orpath = PyUnicode_DecodeFSDefault(rpath); +#ifdef HAVE_CANONICALIZE_FILE_NAME + free(rpath); +#endif + Py_DECREF(opath); + return orpath; +} +#endif + + /* This is used for fpathconf(), pathconf(), confstr() and sysconf(). * It maps strings representing configuration variable names to * integer values, allowing those functions to be called with the @@ -10927,6 +10967,9 @@ static PyMethodDef posix_methods[] = { #ifdef HAVE_PATHCONF {"pathconf", posix_pathconf, METH_VARARGS, posix_pathconf__doc__}, #endif +#ifdef HAVE_REALPATH + {"realpath", posix_realpath, METH_VARARGS, posix_realpath__doc__}, +#endif /* HAVE_READLINK */ {"abort", posix_abort, METH_NOARGS, posix_abort__doc__}, #ifdef MS_WINDOWS {"_getfullpathname", posix__getfullpathname, METH_VARARGS, NULL}, diff -r 524a032c8e0f configure --- a/configure Tue Feb 21 22:10:16 2012 +0100 +++ b/configure Wed Feb 22 00:46:11 2012 +0100 @@ -9395,7 +9395,8 @@ fi $as_echo "MACHDEP_OBJS" >&6; } # checks for library functions -for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ +for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset \ + canonicalize_file_name chown \ clock confstr ctermid execv faccessat fchmod fchmodat fchown fchownat \ fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ futimens futimes gai_strerror \ @@ -14599,8 +14600,8 @@ esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. -config_files="`echo $ac_config_files`" -config_headers="`echo $ac_config_headers`" +config_files="$ac_config_files" +config_headers="$ac_config_headers" _ACEOF diff -r 524a032c8e0f configure.in --- a/configure.in Tue Feb 21 22:10:16 2012 +0100 +++ b/configure.in Wed Feb 22 00:46:11 2012 +0100 @@ -2561,7 +2561,8 @@ fi AC_MSG_RESULT(MACHDEP_OBJS) # checks for library functions -AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ +AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset \ + canonicalize_file_name chown \ clock confstr ctermid execv faccessat fchmod fchmodat fchown fchownat \ fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ futimens futimes gai_strerror \ diff -r 524a032c8e0f pyconfig.h.in --- a/pyconfig.h.in Tue Feb 21 22:10:16 2012 +0100 +++ b/pyconfig.h.in Wed Feb 22 00:46:11 2012 +0100 @@ -101,6 +101,9 @@ /* Define this if you have the type _Bool. */ #undef HAVE_C99_BOOL +/* Define to 1 if you have the `canonicalize_file_name' function. */ +#undef HAVE_CANONICALIZE_FILE_NAME + /* Define to 1 if you have the 'chflags' function. */ #undef HAVE_CHFLAGS