Index: Doc/library/os.path.rst =================================================================== --- Doc/library/os.path.rst (revision 59859) +++ Doc/library/os.path.rst (working copy) @@ -134,6 +134,17 @@ .. versionadded:: 2.3 +.. function:: getshellfolders() + + Return a dict containing paths to Windows shell folders like My Documents. + The keys are all lower case, the values are either unicode objects or None + if a path for a shell folder could not be retrieved. Some of the paths + may not exist. + Availability: Windows. + + .. versionadded:: 2.6 + + .. function:: getsize(path) Return the size, in bytes, of *path*. Raise :exc:`os.error` if the file does Index: Lib/ntpath.py =================================================================== --- Lib/ntpath.py (revision 59859) +++ Lib/ntpath.py (working copy) @@ -16,7 +16,8 @@ "getatime","getctime", "islink","exists","lexists","isdir","isfile", "ismount","walk","expanduser","expandvars","normpath","abspath", "splitunc","curdir","pardir","sep","pathsep","defpath","altsep", - "extsep","devnull","realpath","supports_unicode_filenames","relpath"] + "extsep","devnull","realpath","supports_unicode_filenames","relpath", + "getshellfolders"] # strings representing various path-related bits and pieces curdir = '.' @@ -493,3 +494,10 @@ if not rel_list: return curdir return join(*rel_list) + +try: + from nt import _getshellfolders as getshellfolders +except ImportError: # not running on Windows - mock up something sensible + def getshellfolders(): + """Dummy method""" + return {} Index: Lib/test/test_ntpath.py =================================================================== --- Lib/test/test_ntpath.py (revision 59859) +++ Lib/test/test_ntpath.py (working copy) @@ -168,6 +168,17 @@ tester('ntpath.relpath("//conky/mountpoint/a", "//conky/mountpoint/b/c")', '..\\..\\a') tester('ntpath.relpath("a", "a")', '.') +def test_getshellfolder(): + r = os.path.getshellfolders() + assert len(r) > 10 + assert type(r) is dict + for k, v in r.items(): + assert type(k) is str + if v is None: + continue + assert type(v) is unicode +test_getshellfolder() + if errors: raise TestFailed(str(errors) + " errors.") elif verbose: Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 59859) +++ Modules/posixmodule.c (working copy) @@ -13,6 +13,12 @@ /* See also ../Dos/dosmodule.c */ +#ifdef _MSC_VER +/* required for ShlObj.h */ +#define NTDDI_VERSION NTDDI_WIN2K +#define _WIN32_WINNT _WIN32_WINNT_WIN2K +#endif + #ifdef __APPLE__ /* * Step 1 of support for weak-linking a number of symbols existing on @@ -8211,6 +8217,140 @@ } return result; } + +#include + +static int +set_shellfolder_path(PyObject *d, int folder, char* name) +{ + Py_UNICODE buf[MAX_PATH]; + HRESULT rc; + PyObject *o; + char lower[51]; + char *pname, *plower = lower; + + rc = SHGetFolderPathW(NULL, folder | CSIDL_FLAG_DONT_VERIFY, + NULL, SHGFP_TYPE_CURRENT, buf); + if (rc != S_OK) { + /*PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError, + (int)rc, name); + return -1; */ + o = Py_None; + Py_INCREF(o); + } + else { + o = PyUnicode_FromUnicode(buf, wcslen(buf)); + if (o == NULL) { + return -1; + } + } + if (strncmp(name, "CSIDL_", 6) == 0) { + pname = &name[6]; + while (*pname) { + *plower++ = tolower(*pname++); + } + *plower = '\0'; + pname = lower; + } + else { + pname = name; + } + if (PyDict_SetItemString(d, pname, o) != 0) { + Py_DECREF(o); + return -1; + } + + Py_DECREF(o); + return 0; +} + +PyDoc_STRVAR(win32_getshellfolders__doc__, +"getshellfolders() -> dict\n\n\ +Return a dict containing paths to Windows shell folders like My Documents.\n\ +The keys are all lower case, the values are either unicode objects or None\n\ +if a path for a shell folder couldn't be found."); + +static PyObject* +win32_getshellfolders(PyObject *self, PyObject *noargs) +{ + PyObject *d; + + d = PyDict_New(); + if (d == NULL) { + return NULL; + } + +#define SetShellFolderPath(cons) \ + if (set_shellfolder_path(d, cons, #cons) != 0) \ + return NULL; +#define SetShellFolderPathName(cons, name) \ + if (set_shellfolder_path(d, cons, name) != 0) \ + return NULL; + + SetShellFolderPath(CSIDL_DESKTOP); + SetShellFolderPath(CSIDL_INTERNET); + SetShellFolderPath(CSIDL_PROGRAMS); + SetShellFolderPath(CSIDL_CONTROLS); + SetShellFolderPath(CSIDL_PRINTERS); + SetShellFolderPathName(CSIDL_PERSONAL, "mydocuments"); + SetShellFolderPath(CSIDL_FAVORITES); + SetShellFolderPath(CSIDL_STARTUP); + SetShellFolderPath(CSIDL_RECENT); + SetShellFolderPath(CSIDL_SENDTO); + SetShellFolderPath(CSIDL_BITBUCKET); + SetShellFolderPath(CSIDL_STARTMENU); + SetShellFolderPath(CSIDL_PERSONAL); + SetShellFolderPath(CSIDL_MYMUSIC); + SetShellFolderPath(CSIDL_MYVIDEO); + SetShellFolderPath(CSIDL_DESKTOPDIRECTORY); + SetShellFolderPath(CSIDL_DRIVES); + SetShellFolderPath(CSIDL_NETWORK); + SetShellFolderPath(CSIDL_NETHOOD); + SetShellFolderPath(CSIDL_FONTS); + SetShellFolderPath(CSIDL_TEMPLATES); + SetShellFolderPath(CSIDL_COMMON_STARTMENU); + SetShellFolderPath(CSIDL_COMMON_PROGRAMS); + SetShellFolderPath(CSIDL_COMMON_STARTUP); + SetShellFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY); + SetShellFolderPath(CSIDL_APPDATA); + SetShellFolderPath(CSIDL_PRINTHOOD); + SetShellFolderPath(CSIDL_LOCAL_APPDATA); + SetShellFolderPath(CSIDL_LOCAL_APPDATA); + SetShellFolderPath(CSIDL_LOCAL_APPDATA); + SetShellFolderPath(CSIDL_ALTSTARTUP); + SetShellFolderPath(CSIDL_COMMON_ALTSTARTUP); + SetShellFolderPath(CSIDL_COMMON_FAVORITES); + SetShellFolderPath(CSIDL_INTERNET_CACHE); + SetShellFolderPath(CSIDL_COOKIES); + SetShellFolderPath(CSIDL_HISTORY); + SetShellFolderPath(CSIDL_COMMON_APPDATA); + SetShellFolderPath(CSIDL_WINDOWS); + SetShellFolderPath(CSIDL_SYSTEM); + SetShellFolderPath(CSIDL_PROGRAM_FILES); + SetShellFolderPath(CSIDL_MYPICTURES); + SetShellFolderPath(CSIDL_PROFILE); + SetShellFolderPath(CSIDL_PROGRAM_FILES_COMMON); + SetShellFolderPath(CSIDL_COMMON_TEMPLATES); + SetShellFolderPath(CSIDL_COMMON_DOCUMENTS); + SetShellFolderPath(CSIDL_COMMON_ADMINTOOLS); + SetShellFolderPath(CSIDL_ADMINTOOLS); + SetShellFolderPath(CSIDL_CONNECTIONS); + SetShellFolderPath(CSIDL_COMMON_MUSIC); + SetShellFolderPath(CSIDL_COMMON_PICTURES); + SetShellFolderPath(CSIDL_COMMON_VIDEO); + SetShellFolderPath(CSIDL_RESOURCES); + SetShellFolderPath(CSIDL_RESOURCES_LOCALIZED); + SetShellFolderPath(CSIDL_COMMON_OEM_LINKS); + SetShellFolderPath(CSIDL_CDBURN_AREA); + SetShellFolderPath(CSIDL_COMPUTERSNEARME); + +#undef SetShellFolderPath +#undef SetShellFolderPathName + + return d; +} + + #endif #ifdef __VMS @@ -8554,12 +8694,14 @@ #ifdef HAVE_GETLOADAVG {"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__}, #endif - #ifdef MS_WINDOWS - {"urandom", win32_urandom, METH_VARARGS, win32_urandom__doc__}, - #endif - #ifdef __VMS - {"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__}, - #endif +#ifdef MS_WINDOWS + {"urandom", win32_urandom, METH_VARARGS, win32_urandom__doc__}, + {"_getshellfolders", win32_getshellfolders, METH_NOARGS, + win32_getshellfolders__doc__}, +#endif +#ifdef __VMS + {"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__}, +#endif {NULL, NULL} /* Sentinel */ };