diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -125,6 +125,11 @@ #endif #endif +#ifdef __APPLE__ +#include +#include +#endif + #ifdef HAVE_DLFCN_H #include #endif @@ -10215,6 +10220,118 @@ return NULL; } +#ifdef __APPLE__ +PyDoc_STRVAR(macosx_startfile__doc__, +"startfile(filepath [, operation]) - Start a file with its associated\n\ +application.\n\ +" +); + +static PyObject * +macosx_startfile(PyObject *self, PyObject *args) +{ + PyObject* retval = NULL; + path_t path; + char *operation = NULL; + LSLaunchURLSpec launch_spec = { NULL, NULL, NULL, kLSLaunchDefaults, NULL }; + CFURLRef itemURL = NULL; + OSStatus r; + + memset(&path, 0, sizeof(path)); + + if (!PyArg_ParseTuple(args, "O&|s:startfile", + path_converter, &path, &operation)) { + return NULL; + } + + itemURL = CFURLCreateFromFileSystemRepresentation( + kCFAllocatorDefault, + (const UInt8 *)path.narrow, strlen(path.narrow), + false); + if (itemURL == NULL) { + PyErr_NoMemory(); + goto done; + } + + launch_spec.itemURLs = CFArrayCreate( + kCFAllocatorDefault, + (const void**)&itemURL, 1, + &kCFTypeArrayCallBacks); + if (launch_spec.itemURLs == NULL) { + PyErr_NoMemory(); + goto done; + } + + if (operation) { + if (strcmp(operation, "open") == 0) { + /* pass */ + + } else if (strcmp(operation, "edit") == 0) { + r = LSGetApplicationForURL(itemURL, kLSRolesEditor, NULL, &launch_spec.appURL); + if (r) { + PyErr_Format(PyExc_RuntimeError, "LSApplicationForURL failed with code %d", (int)r); + goto done; + } +#if 0 + /* activate this code to show the file URL, application that will be used to open the file + * and the list of applications that claim the "editor" role. + */ + CFShow(itemURL); + CFShow(launch_spec.appURL); + CFShow(LSCopyApplicationURLsForURL(itemURL, kLSRolesEditor)); +#endif + + } else if (strcmp(operation, "execute") == 0) { + r = LSGetApplicationForURL(itemURL, kLSRolesShell, NULL, &launch_spec.appURL); + if (r) { + PyErr_Format(PyExc_RuntimeError, "LSApplicationForURL failed with code %d", (int)r); + goto done; + } + } else if (strcmp(operation, "print") == 0) { + launch_spec.launchFlags = kLSLaunchAndPrint; + + } else if (strcmp(operation, "explore") == 0) { +#define FINDER_PATH "/System/Library/CoreServices/Finder.app" + launch_spec.appURL = CFURLCreateFromFileSystemRepresentation( + kCFAllocatorDefault, + (const UInt8 *)FINDER_PATH, sizeof(FINDER_PATH)-1, true); +#undef FINDER_PATH + if (launch_spec.appURL == 0) { + PyErr_NoMemory(); + goto done; + } + + } else { + PyErr_SetString(PyExc_ValueError, "Unsupported value for 'operation'"); + goto done; + } + } + + r = LSOpenFromURLSpec(&launch_spec, NULL); + if (r) { + PyErr_Format(PyExc_RuntimeError, "LSOpenFromURLSpec failed with code %d", (int)r); + goto done; + } + + retval = Py_None; + Py_INCREF(retval); + + +done: + if (itemURL) { + CFRelease(itemURL); + } + if (launch_spec.itemURLs) { + CFRelease(launch_spec.itemURLs); + } + if (launch_spec.appURL) { + CFRelease(launch_spec.appURL); + } + path_cleanup(&path); + return retval; +} +#endif + #ifdef MS_WINDOWS PyDoc_STRVAR(win32_startfile__doc__, "startfile(filepath [, operation]) - Start a file with its associated\n\ @@ -11067,6 +11184,9 @@ #ifdef HAVE_PLOCK {"plock", posix_plock, METH_VARARGS, posix_plock__doc__}, #endif /* HAVE_PLOCK */ +#ifdef __APPLE__ + {"startfile", macosx_startfile, METH_VARARGS, macosx_startfile__doc__}, +#endif #ifdef MS_WINDOWS {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__}, {"kill", win32_kill, METH_VARARGS, win32_kill__doc__},