import sys, os, subprocess, errno #.. function:: open(path) # # Attempts to open the given file/directory in its associated (typically GUI) application, as determined by the underlying platform. # On Windows, uses XXXXXXX API call. # On Mac OS X, uses the ```open `_`` command. # On non-Mac Unix, uses the ```xdg-open `_`` command and fails if it can't be run (normally, when it's not installed). # # :param path: the path to the file or directory to open # :type path: bytes on Unix [???] (including Mac OS X), str on Windows [???] # :raises NotImplementedError: on non-Mac Unix when ``xdg-open`` can't be executed # :raises IOError: with *:attr:`errno` = :data:`errno.ENOENT`*, when the given path does not exist # :raises OSError: with *:attr:`errno` = :data:`errno.ENOSYS`*, when no application is associated with files/directories of the given path's type # :returns: None # FIXME: is OSError(errno.ENOSYS) the right choice of error to raise? if os.name == 'nt':# or sys.platform.startswith('win32') ??? def open(path): # starting point(?): os.startfile() # Target path nonexistent: ERROR_FILE_NOT_FOUND and/or ERROR_PATH_NOT_FOUND # No associated application: SE_ERR_NOASSOC pass elif sys.platform.startswith('darwin'): def open(path): # manpage: https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/open.1.html proc = subprocess.Popen(['open', path], stderr=subprocess.PIPE, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL) _, stderr_output = proc.communicate() if proc.returncode: if stderr_output.endswith("does not exist."): raise IOError(errno.ENOENT, "The path %s does not exist" % repr(path), path) from err elif stderr_output.startswith("No application knows how to open"): raise OSError(errno.ENOSYS, "No application is associated with files/directories of the given type", path) from err elif os.name == 'posix': def open(path): try: subprocess.check_call(['xdg-open', path], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError as err: # see http://portland.freedesktop.org/xdg-utils-1.0/xdg-open.html manpage for return code meanings if err.returncode == 2: raise IOError(errno.ENOENT, "The path %s does not exist" % repr(path), path) from err elif err.returncode == 3: raise OSError(errno.ENOSYS, "No application is associated with files/directories of the given type", path) from err else: raise except EnvironmentError as err: if err.errno == errno.ENOENT: raise NotImplementedError from err # xdg-open not installed/accessible else: raise