desktop

desktop/__init__.py

56:8e64df19342b
2007-12-15 paulb [project @ 2007-12-15 18:52:22 by paulb] Updated release information. Changed installation to install a package, not a module.
     1 #!/usr/bin/env python     2      3 """     4 Simple desktop integration for Python. This module provides desktop environment     5 detection and resource opening support for a selection of common and     6 standardised desktop environments.     7      8 Copyright (C) 2005, 2006, 2007 Paul Boddie <paul@boddie.org.uk>     9     10 This library is free software; you can redistribute it and/or    11 modify it under the terms of the GNU Lesser General Public    12 License as published by the Free Software Foundation; either    13 version 2.1 of the License, or (at your option) any later version.    14     15 This library is distributed in the hope that it will be useful,    16 but WITHOUT ANY WARRANTY; without even the implied warranty of    17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    18 Lesser General Public License for more details.    19     20 You should have received a copy of the GNU Lesser General Public    21 License along with this library; if not, write to the Free Software    22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA    23     24 --------    25     26 Desktop Detection    27 -----------------    28     29 To detect a specific desktop environment, use the get_desktop function.    30 To detect whether the desktop environment is standardised (according to the    31 proposed DESKTOP_LAUNCH standard), use the is_standard function.    32     33 Opening URLs    34 ------------    35     36 To open a URL in the current desktop environment, relying on the automatic    37 detection of that environment, use the desktop.open function as follows:    38     39 desktop.open("http://www.python.org")    40     41 To override the detected desktop, specify the desktop parameter to the open    42 function as follows:    43     44 desktop.open("http://www.python.org", "KDE") # Insists on KDE    45 desktop.open("http://www.python.org", "GNOME") # Insists on GNOME    46     47 Without overriding using the desktop parameter, the open function will attempt    48 to use the "standard" desktop opening mechanism which is controlled by the    49 DESKTOP_LAUNCH environment variable as described below.    50     51 The DESKTOP_LAUNCH Environment Variable    52 ---------------------------------------    53     54 The DESKTOP_LAUNCH environment variable must be shell-quoted where appropriate,    55 as shown in some of the following examples:    56     57 DESKTOP_LAUNCH="kdialog --msgbox"       Should present any opened URLs in    58                                         their entirety in a KDE message box.    59                                         (Command "kdialog" plus parameter.)    60 DESKTOP_LAUNCH="my\ opener"             Should run the "my opener" program to    61                                         open URLs.    62                                         (Command "my opener", no parameters.)    63 DESKTOP_LAUNCH="my\ opener --url"       Should run the "my opener" program to    64                                         open URLs.    65                                         (Command "my opener" plus parameter.)    66     67 Details of the DESKTOP_LAUNCH environment variable convention can be found here:    68 http://lists.freedesktop.org/archives/xdg/2004-August/004489.html    69 """    70     71 __version__ = "0.3"    72     73 import os    74 import sys    75     76 # Provide suitable process creation functions.    77     78 try:    79     import subprocess    80     def _run(cmd, shell, wait):    81         opener = subprocess.Popen(cmd, shell=shell)    82         if wait: opener.wait()    83         return opener.pid    84     85     def _readfrom(cmd, shell):    86         opener = subprocess.Popen(cmd, shell=shell, stdin=subprocess.PIPE, stdout=subprocess.PIPE)    87         opener.stdin.close()    88         return opener.stdout.read()    89     90     def _status(cmd, shell):    91         opener = subprocess.Popen(cmd, shell=shell)    92         opener.wait()    93         return opener.returncode == 0    94     95 except ImportError:    96     import popen2    97     def _run(cmd, shell, wait):    98         opener = popen2.Popen3(cmd)    99         if wait: opener.wait()   100         return opener.pid   101    102     def _readfrom(cmd, shell):   103         opener = popen2.Popen3(cmd)   104         opener.tochild.close()   105         opener.childerr.close()   106         return opener.fromchild.read()   107    108     def _status(cmd, shell):   109         opener = popen2.Popen3(cmd)   110         opener.wait()   111         return opener.poll() == 0   112    113 import commands   114    115 # Private functions.   116    117 def _get_x11_vars():   118    119     "Return suitable environment definitions for X11."   120    121     if not os.environ.get("DISPLAY", "").strip():   122         return "DISPLAY=:0.0 "   123     else:   124         return ""   125    126 def _is_xfce():   127    128     "Return whether XFCE is in use."   129    130     # XFCE detection involves testing the output of a program.   131    132     try:   133         return _readfrom(_get_x11_vars() + "xprop -root _DT_SAVE_MODE", shell=1).strip().endswith(' = "xfce4"')   134     except OSError:   135         return 0   136    137 def _is_x11():   138    139     "Return whether the X Window System is in use."   140    141     return os.environ.has_key("DISPLAY")   142    143 # Introspection functions.   144    145 def get_desktop():   146    147     """   148     Detect the current desktop environment, returning the name of the   149     environment. If no environment could be detected, None is returned.   150     """   151    152     if os.environ.has_key("KDE_FULL_SESSION") or \   153         os.environ.has_key("KDE_MULTIHEAD"):   154         return "KDE"   155     elif os.environ.has_key("GNOME_DESKTOP_SESSION_ID") or \   156         os.environ.has_key("GNOME_KEYRING_SOCKET"):   157         return "GNOME"   158     elif sys.platform == "darwin":   159         return "Mac OS X"   160     elif hasattr(os, "startfile"):   161         return "Windows"   162     elif _is_xfce():   163         return "XFCE"   164    165     # KDE, GNOME and XFCE run on X11, so we have to test for X11 last.   166    167     if _is_x11():   168         return "X11"   169     else:   170         return None   171    172 def use_desktop(desktop):   173    174     """   175     Decide which desktop should be used, based on the detected desktop and a   176     supplied 'desktop' argument (which may be None). Return an identifier   177     indicating the desktop type as being either "standard" or one of the results   178     from the 'get_desktop' function.   179     """   180    181     # Attempt to detect a desktop environment.   182    183     detected = get_desktop()   184    185     # Start with desktops whose existence can be easily tested.   186    187     if (desktop is None or desktop == "standard") and is_standard():   188         return "standard"   189     elif (desktop is None or desktop == "Windows") and detected == "Windows":   190         return "Windows"   191    192     # Test for desktops where the overriding is not verified.   193    194     elif (desktop or detected) == "KDE":   195         return "KDE"   196     elif (desktop or detected) == "GNOME":   197         return "GNOME"   198     elif (desktop or detected) == "XFCE":   199         return "XFCE"   200     elif (desktop or detected) == "Mac OS X":   201         return "Mac OS X"   202     elif (desktop or detected) == "X11":   203         return "X11"   204     else:   205         return None   206    207 def is_standard():   208    209     """   210     Return whether the current desktop supports standardised application   211     launching.   212     """   213    214     return os.environ.has_key("DESKTOP_LAUNCH")   215    216 # Activity functions.   217    218 def open(url, desktop=None, wait=0):   219    220     """   221     Open the 'url' in the current desktop's preferred file browser. If the   222     optional 'desktop' parameter is specified then attempt to use that   223     particular desktop environment's mechanisms to open the 'url' instead of   224     guessing or detecting which environment is being used.   225    226     Suggested values for 'desktop' are "standard", "KDE", "GNOME", "XFCE",   227     "Mac OS X", "Windows" where "standard" employs a DESKTOP_LAUNCH environment   228     variable to open the specified 'url'. DESKTOP_LAUNCH should be a command,   229     possibly followed by arguments, and must have any special characters   230     shell-escaped.   231    232     The process identifier of the "opener" (ie. viewer, editor, browser or   233     program) associated with the 'url' is returned by this function. If the   234     process identifier cannot be determined, None is returned.   235    236     An optional 'wait' parameter is also available for advanced usage and, if   237     'wait' is set to a true value, this function will wait for the launching   238     mechanism to complete before returning (as opposed to immediately returning   239     as is the default behaviour).   240     """   241    242     # Decide on the desktop environment in use.   243    244     desktop_in_use = use_desktop(desktop)   245    246     if desktop_in_use == "standard":   247         arg = "".join([os.environ["DESKTOP_LAUNCH"], commands.mkarg(url)])   248         return _run(arg, 1, wait)   249    250     elif desktop_in_use == "Windows":   251         # NOTE: This returns None in current implementations.   252         return os.startfile(url)   253    254     elif desktop_in_use == "KDE":   255         cmd = ["kfmclient", "exec", url]   256    257     elif desktop_in_use == "GNOME":   258         cmd = ["gnome-open", url]   259    260     elif desktop_in_use == "XFCE":   261         cmd = ["exo-open", url]   262    263     elif desktop_in_use == "Mac OS X":   264         cmd = ["open", url]   265    266     elif desktop_in_use == "X11" and os.environ.has_key("BROWSER"):   267         cmd = [os.environ["BROWSER"], url]   268    269     # Finish with an error where no suitable desktop was identified.   270    271     else:   272         raise OSError, "Desktop '%s' not supported (neither DESKTOP_LAUNCH nor os.startfile could be used)" % desktop_in_use   273    274     return _run(cmd, 0, wait)   275    276 # vim: tabstop=4 expandtab shiftwidth=4