xref: /aosp_15_r20/external/clang/tools/scan-view/share/startfile.py (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li"""Utility for opening a file using the default application in a cross-platform
2*67e74705SXin Limanner. Modified from http://code.activestate.com/recipes/511443/.
3*67e74705SXin Li"""
4*67e74705SXin Li
5*67e74705SXin Li__version__ = '1.1x'
6*67e74705SXin Li__all__ = ['open']
7*67e74705SXin Li
8*67e74705SXin Liimport os
9*67e74705SXin Liimport sys
10*67e74705SXin Liimport webbrowser
11*67e74705SXin Liimport subprocess
12*67e74705SXin Li
13*67e74705SXin Li_controllers = {}
14*67e74705SXin Li_open = None
15*67e74705SXin Li
16*67e74705SXin Li
17*67e74705SXin Liclass BaseController(object):
18*67e74705SXin Li    '''Base class for open program controllers.'''
19*67e74705SXin Li
20*67e74705SXin Li    def __init__(self, name):
21*67e74705SXin Li        self.name = name
22*67e74705SXin Li
23*67e74705SXin Li    def open(self, filename):
24*67e74705SXin Li        raise NotImplementedError
25*67e74705SXin Li
26*67e74705SXin Li
27*67e74705SXin Liclass Controller(BaseController):
28*67e74705SXin Li    '''Controller for a generic open program.'''
29*67e74705SXin Li
30*67e74705SXin Li    def __init__(self, *args):
31*67e74705SXin Li        super(Controller, self).__init__(os.path.basename(args[0]))
32*67e74705SXin Li        self.args = list(args)
33*67e74705SXin Li
34*67e74705SXin Li    def _invoke(self, cmdline):
35*67e74705SXin Li        if sys.platform[:3] == 'win':
36*67e74705SXin Li            closefds = False
37*67e74705SXin Li            startupinfo = subprocess.STARTUPINFO()
38*67e74705SXin Li            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
39*67e74705SXin Li        else:
40*67e74705SXin Li            closefds = True
41*67e74705SXin Li            startupinfo = None
42*67e74705SXin Li
43*67e74705SXin Li        if (os.environ.get('DISPLAY') or sys.platform[:3] == 'win' or
44*67e74705SXin Li                                                    sys.platform == 'darwin'):
45*67e74705SXin Li            inout = file(os.devnull, 'r+')
46*67e74705SXin Li        else:
47*67e74705SXin Li            # for TTY programs, we need stdin/out
48*67e74705SXin Li            inout = None
49*67e74705SXin Li
50*67e74705SXin Li        # if possible, put the child precess in separate process group,
51*67e74705SXin Li        # so keyboard interrupts don't affect child precess as well as
52*67e74705SXin Li        # Python
53*67e74705SXin Li        setsid = getattr(os, 'setsid', None)
54*67e74705SXin Li        if not setsid:
55*67e74705SXin Li            setsid = getattr(os, 'setpgrp', None)
56*67e74705SXin Li
57*67e74705SXin Li        pipe = subprocess.Popen(cmdline, stdin=inout, stdout=inout,
58*67e74705SXin Li                                stderr=inout, close_fds=closefds,
59*67e74705SXin Li                                preexec_fn=setsid, startupinfo=startupinfo)
60*67e74705SXin Li
61*67e74705SXin Li        # It is assumed that this kind of tools (gnome-open, kfmclient,
62*67e74705SXin Li        # exo-open, xdg-open and open for OSX) immediately exit after lauching
63*67e74705SXin Li        # the specific application
64*67e74705SXin Li        returncode = pipe.wait()
65*67e74705SXin Li        if hasattr(self, 'fixreturncode'):
66*67e74705SXin Li            returncode = self.fixreturncode(returncode)
67*67e74705SXin Li        return not returncode
68*67e74705SXin Li
69*67e74705SXin Li    def open(self, filename):
70*67e74705SXin Li        if isinstance(filename, basestring):
71*67e74705SXin Li            cmdline = self.args + [filename]
72*67e74705SXin Li        else:
73*67e74705SXin Li            # assume it is a sequence
74*67e74705SXin Li            cmdline = self.args + filename
75*67e74705SXin Li        try:
76*67e74705SXin Li            return self._invoke(cmdline)
77*67e74705SXin Li        except OSError:
78*67e74705SXin Li            return False
79*67e74705SXin Li
80*67e74705SXin Li
81*67e74705SXin Li# Platform support for Windows
82*67e74705SXin Liif sys.platform[:3] == 'win':
83*67e74705SXin Li
84*67e74705SXin Li    class Start(BaseController):
85*67e74705SXin Li        '''Controller for the win32 start progam through os.startfile.'''
86*67e74705SXin Li
87*67e74705SXin Li        def open(self, filename):
88*67e74705SXin Li            try:
89*67e74705SXin Li                os.startfile(filename)
90*67e74705SXin Li            except WindowsError:
91*67e74705SXin Li                # [Error 22] No application is associated with the specified
92*67e74705SXin Li                # file for this operation: '<URL>'
93*67e74705SXin Li                return False
94*67e74705SXin Li            else:
95*67e74705SXin Li                return True
96*67e74705SXin Li
97*67e74705SXin Li    _controllers['windows-default'] = Start('start')
98*67e74705SXin Li    _open = _controllers['windows-default'].open
99*67e74705SXin Li
100*67e74705SXin Li
101*67e74705SXin Li# Platform support for MacOS
102*67e74705SXin Lielif sys.platform == 'darwin':
103*67e74705SXin Li    _controllers['open']= Controller('open')
104*67e74705SXin Li    _open = _controllers['open'].open
105*67e74705SXin Li
106*67e74705SXin Li
107*67e74705SXin Li# Platform support for Unix
108*67e74705SXin Lielse:
109*67e74705SXin Li
110*67e74705SXin Li    import commands
111*67e74705SXin Li
112*67e74705SXin Li    # @WARNING: use the private API of the webbrowser module
113*67e74705SXin Li    from webbrowser import _iscommand
114*67e74705SXin Li
115*67e74705SXin Li    class KfmClient(Controller):
116*67e74705SXin Li        '''Controller for the KDE kfmclient program.'''
117*67e74705SXin Li
118*67e74705SXin Li        def __init__(self, kfmclient='kfmclient'):
119*67e74705SXin Li            super(KfmClient, self).__init__(kfmclient, 'exec')
120*67e74705SXin Li            self.kde_version = self.detect_kde_version()
121*67e74705SXin Li
122*67e74705SXin Li        def detect_kde_version(self):
123*67e74705SXin Li            kde_version = None
124*67e74705SXin Li            try:
125*67e74705SXin Li                info = commands.getoutput('kde-config --version')
126*67e74705SXin Li
127*67e74705SXin Li                for line in info.splitlines():
128*67e74705SXin Li                    if line.startswith('KDE'):
129*67e74705SXin Li                        kde_version = line.split(':')[-1].strip()
130*67e74705SXin Li                        break
131*67e74705SXin Li            except (OSError, RuntimeError):
132*67e74705SXin Li                pass
133*67e74705SXin Li
134*67e74705SXin Li            return kde_version
135*67e74705SXin Li
136*67e74705SXin Li        def fixreturncode(self, returncode):
137*67e74705SXin Li            if returncode is not None and self.kde_version > '3.5.4':
138*67e74705SXin Li                return returncode
139*67e74705SXin Li            else:
140*67e74705SXin Li                return os.EX_OK
141*67e74705SXin Li
142*67e74705SXin Li    def detect_desktop_environment():
143*67e74705SXin Li        '''Checks for known desktop environments
144*67e74705SXin Li
145*67e74705SXin Li        Return the desktop environments name, lowercase (kde, gnome, xfce)
146*67e74705SXin Li        or "generic"
147*67e74705SXin Li
148*67e74705SXin Li        '''
149*67e74705SXin Li
150*67e74705SXin Li        desktop_environment = 'generic'
151*67e74705SXin Li
152*67e74705SXin Li        if os.environ.get('KDE_FULL_SESSION') == 'true':
153*67e74705SXin Li            desktop_environment = 'kde'
154*67e74705SXin Li        elif os.environ.get('GNOME_DESKTOP_SESSION_ID'):
155*67e74705SXin Li            desktop_environment = 'gnome'
156*67e74705SXin Li        else:
157*67e74705SXin Li            try:
158*67e74705SXin Li                info = commands.getoutput('xprop -root _DT_SAVE_MODE')
159*67e74705SXin Li                if ' = "xfce4"' in info:
160*67e74705SXin Li                    desktop_environment = 'xfce'
161*67e74705SXin Li            except (OSError, RuntimeError):
162*67e74705SXin Li                pass
163*67e74705SXin Li
164*67e74705SXin Li        return desktop_environment
165*67e74705SXin Li
166*67e74705SXin Li
167*67e74705SXin Li    def register_X_controllers():
168*67e74705SXin Li        if _iscommand('kfmclient'):
169*67e74705SXin Li            _controllers['kde-open'] = KfmClient()
170*67e74705SXin Li
171*67e74705SXin Li        for command in ('gnome-open', 'exo-open', 'xdg-open'):
172*67e74705SXin Li            if _iscommand(command):
173*67e74705SXin Li                _controllers[command] = Controller(command)
174*67e74705SXin Li
175*67e74705SXin Li    def get():
176*67e74705SXin Li        controllers_map = {
177*67e74705SXin Li            'gnome': 'gnome-open',
178*67e74705SXin Li            'kde': 'kde-open',
179*67e74705SXin Li            'xfce': 'exo-open',
180*67e74705SXin Li        }
181*67e74705SXin Li
182*67e74705SXin Li        desktop_environment = detect_desktop_environment()
183*67e74705SXin Li
184*67e74705SXin Li        try:
185*67e74705SXin Li            controller_name = controllers_map[desktop_environment]
186*67e74705SXin Li            return _controllers[controller_name].open
187*67e74705SXin Li
188*67e74705SXin Li        except KeyError:
189*67e74705SXin Li            if _controllers.has_key('xdg-open'):
190*67e74705SXin Li                return _controllers['xdg-open'].open
191*67e74705SXin Li            else:
192*67e74705SXin Li                return webbrowser.open
193*67e74705SXin Li
194*67e74705SXin Li
195*67e74705SXin Li    if os.environ.get("DISPLAY"):
196*67e74705SXin Li        register_X_controllers()
197*67e74705SXin Li    _open = get()
198*67e74705SXin Li
199*67e74705SXin Li
200*67e74705SXin Lidef open(filename):
201*67e74705SXin Li    '''Open a file or an URL in the registered default application.'''
202*67e74705SXin Li
203*67e74705SXin Li    return _open(filename)
204