brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · c72475e Raw
217 lines · python
1#!/usr/bin/env python2# -*- coding: utf-8 -*-3 4"""Utility for opening a file using the default application in a cross-platform5manner. Modified from http://code.activestate.com/recipes/511443/.6"""7 8__version__ = "1.1x"9__all__ = ["open"]10 11import os12import sys13import webbrowser14import subprocess15 16_controllers = {}17_open = None18 19 20class BaseController(object):21    """Base class for open program controllers."""22 23    def __init__(self, name):24        self.name = name25 26    def open(self, filename):27        raise NotImplementedError28 29 30class Controller(BaseController):31    """Controller for a generic open program."""32 33    def __init__(self, *args):34        super(Controller, self).__init__(os.path.basename(args[0]))35        self.args = list(args)36 37    def _invoke(self, cmdline):38        if sys.platform[:3] == "win":39            closefds = False40            startupinfo = subprocess.STARTUPINFO()41            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW42        else:43            closefds = True44            startupinfo = None45 46        if (47            os.environ.get("DISPLAY")48            or sys.platform[:3] == "win"49            or sys.platform == "darwin"50        ):51            inout = subprocess.DEVNULL52        else:53            # for TTY programs, we need stdin/out54            inout = None55 56        # if possible, put the child precess in separate process group,57        # so keyboard interrupts don't affect child precess as well as58        # Python59        setsid = getattr(os, "setsid", None)60        if not setsid:61            setsid = getattr(os, "setpgrp", None)62 63        pipe = subprocess.Popen(64            cmdline,65            stdin=inout,66            stdout=inout,67            stderr=inout,68            close_fds=closefds,69            preexec_fn=setsid,70            startupinfo=startupinfo,71        )72 73        # It is assumed that this kind of tools (gnome-open, kfmclient,74        # exo-open, xdg-open and open for OSX) immediately exit after launching75        # the specific application76        returncode = pipe.wait()77        if hasattr(self, "fixreturncode"):78            returncode = self.fixreturncode(returncode)79        return not returncode80 81    def open(self, filename):82        if isinstance(filename, basestring):83            cmdline = self.args + [filename]84        else:85            # assume it is a sequence86            cmdline = self.args + filename87        try:88            return self._invoke(cmdline)89        except OSError:90            return False91 92 93# Platform support for Windows94if sys.platform[:3] == "win":95 96    class Start(BaseController):97        """Controller for the win32 start program through os.startfile."""98 99        def open(self, filename):100            try:101                os.startfile(filename)102            except WindowsError:103                # [Error 22] No application is associated with the specified104                # file for this operation: '<URL>'105                return False106            else:107                return True108 109    _controllers["windows-default"] = Start("start")110    _open = _controllers["windows-default"].open111 112 113# Platform support for MacOS114elif sys.platform == "darwin":115    _controllers["open"] = Controller("open")116    _open = _controllers["open"].open117 118 119# Platform support for Unix120else:121 122    try:123        from commands import getoutput124    except ImportError:125        from subprocess import getoutput126 127    # @WARNING: use the private API of the webbrowser module128    from webbrowser import _iscommand129 130    class KfmClient(Controller):131        """Controller for the KDE kfmclient program."""132 133        def __init__(self, kfmclient="kfmclient"):134            super(KfmClient, self).__init__(kfmclient, "exec")135            self.kde_version = self.detect_kde_version()136 137        def detect_kde_version(self):138            kde_version = None139            try:140                info = getoutput("kde-config --version")141 142                for line in info.splitlines():143                    if line.startswith("KDE"):144                        kde_version = line.split(":")[-1].strip()145                        break146            except (OSError, RuntimeError):147                pass148 149            return kde_version150 151        def fixreturncode(self, returncode):152            if returncode is not None and self.kde_version > "3.5.4":153                return returncode154            else:155                return os.EX_OK156 157    def detect_desktop_environment():158        """Checks for known desktop environments159 160        Return the desktop environments name, lowercase (kde, gnome, xfce)161        or "generic"162 163        """164 165        desktop_environment = "generic"166 167        if os.environ.get("KDE_FULL_SESSION") == "true":168            desktop_environment = "kde"169        elif os.environ.get("GNOME_DESKTOP_SESSION_ID"):170            desktop_environment = "gnome"171        else:172            try:173                info = getoutput("xprop -root _DT_SAVE_MODE")174                if ' = "xfce4"' in info:175                    desktop_environment = "xfce"176            except (OSError, RuntimeError):177                pass178 179        return desktop_environment180 181    def register_X_controllers():182        if _iscommand("kfmclient"):183            _controllers["kde-open"] = KfmClient()184 185        for command in ("gnome-open", "exo-open", "xdg-open"):186            if _iscommand(command):187                _controllers[command] = Controller(command)188 189    def get():190        controllers_map = {191            "gnome": "gnome-open",192            "kde": "kde-open",193            "xfce": "exo-open",194        }195 196        desktop_environment = detect_desktop_environment()197 198        try:199            controller_name = controllers_map[desktop_environment]200            return _controllers[controller_name].open201 202        except KeyError:203            if "xdg-open" in _controllers:204                return _controllers["xdg-open"].open205            else:206                return webbrowser.open207 208    if os.environ.get("DISPLAY"):209        register_X_controllers()210    _open = get()211 212 213def open(filename):214    """Open a file or a URL in the registered default application."""215 216    return _open(filename)217