Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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