Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
webbrowser.py
Go to the documentation of this file.
1 """Interfaces for launching and remotely controlling Web browsers."""
2 
3 import os
4 import sys
5 
6 __all__ = ["Error", "open", "get", "register"]
7 
8 class Error(Exception):
9  pass
10 
11 _browsers = {} # Dictionary of available browser controllers
12 _tryorder = [] # Preference order of available browsers
13 
14 def register(name, klass, instance=None):
15  """Register a browser connector and, optionally, connection."""
16  _browsers[name.lower()] = [klass, instance]
17 
18 def get(using=None):
19  """Return a browser launcher instance appropriate for the environment."""
20  if using:
21  alternatives = [using]
22  else:
23  alternatives = _tryorder
24  for browser in alternatives:
25  if browser.find('%s') > -1:
26  # User gave us a command line, don't mess with it.
27  return GenericBrowser(browser)
28  else:
29  # User gave us a browser name.
30  try:
31  command = _browsers[browser.lower()]
32  except KeyError:
33  command = _synthesize(browser)
34  if command[1] is None:
35  return command[0]()
36  else:
37  return command[1]
38  raise Error("could not locate runnable browser")
39 
40 # Please note: the following definition hides a builtin function.
41 
42 def open(url, new=0, autoraise=1):
43  get().open(url, new, autoraise)
44 
45 def open_new(url):
46  get().open(url, 1)
47 
48 
49 def _synthesize(browser):
50  """Attempt to synthesize a controller base on existing controllers.
51 
52  This is useful to create a controller when a user specifies a path to
53  an entry in the BROWSER environment variable -- we can copy a general
54  controller to operate using a specific installation of the desired
55  browser in this way.
56 
57  If we can't create a controller in this way, or if there is no
58  executable for the requested browser, return [None, None].
59 
60  """
61  if not os.path.exists(browser):
62  return [None, None]
63  name = os.path.basename(browser)
64  try:
65  command = _browsers[name.lower()]
66  except KeyError:
67  return [None, None]
68  # now attempt to clone to fit the new name:
69  controller = command[1]
70  if controller and name.lower() == controller.basename:
71  import copy
72  controller = copy.copy(controller)
73  controller.name = browser
74  controller.basename = os.path.basename(browser)
75  register(browser, None, controller)
76  return [None, controller]
77  return [None, None]
78 
79 
80 def _iscommand(cmd):
81  """Return true if cmd can be found on the executable search path."""
82  path = os.environ.get("PATH")
83  if not path:
84  return 0
85  for d in path.split(os.pathsep):
86  exe = os.path.join(d, cmd)
87  if os.path.isfile(exe):
88  return 1
89  return 0
90 
91 
92 PROCESS_CREATION_DELAY = 4
93 
94 
96  def __init__(self, cmd):
97  self.name, self.args = cmd.split(None, 1)
98  self.basename = os.path.basename(self.name)
99 
100  def open(self, url, new=0, autoraise=1):
101  assert "'" not in url
102  command = "%s %s" % (self.name, self.args)
103  os.system(command % url)
104 
105  def open_new(self, url):
106  self.open(url)
107 
108 
109 class Netscape:
110  "Launcher class for Netscape browsers."
111  def __init__(self, name):
112  self.name = name
113  self.basename = os.path.basename(name)
114 
115  def _remote(self, action, autoraise):
116  raise_opt = ("-noraise", "-raise")[autoraise]
117  cmd = "%s %s -remote '%s' >/dev/null 2>&1" % (self.name,
118  raise_opt,
119  action)
120  rc = os.system(cmd)
121  if rc:
122  import time
123  os.system("%s &" % self.name)
124  time.sleep(PROCESS_CREATION_DELAY)
125  rc = os.system(cmd)
126  return not rc
127 
128  def open(self, url, new=0, autoraise=1):
129  if new:
130  self._remote("openURL(%s, new-window)"%url, autoraise)
131  else:
132  self._remote("openURL(%s)" % url, autoraise)
133 
134  def open_new(self, url):
135  self.open(url, 1)
136 
137 
138 class Konqueror:
139  """Controller for the KDE File Manager (kfm, or Konqueror).
140 
141  See http://developer.kde.org/documentation/other/kfmclient.html
142  for more information on the Konqueror remote-control interface.
143 
144  """
145  def __init__(self):
146  if _iscommand("konqueror"):
147  self.name = self.basename = "konqueror"
148  else:
149  self.name = self.basename = "kfm"
150 
151  def _remote(self, action):
152  assert "'" not in action
153  cmd = "kfmclient '%s' >/dev/null 2>&1" % action
154  rc = os.system(cmd)
155  if rc:
156  import time
157  if self.basename == "konqueror":
158  os.system(self.name + " --silent &")
159  else:
160  os.system(self.name + " -d &")
161  time.sleep(PROCESS_CREATION_DELAY)
162  rc = os.system(cmd)
163  return not rc
164 
165  def open(self, url, new=1, autoraise=1):
166  # XXX Currently I know no way to prevent KFM from
167  # opening a new win.
168  self._remote("openURL '%s'" % url)
169 
170  open_new = open
171 
172 
173 class Grail:
174  # There should be a way to maintain a connection to Grail, but the
175  # Grail remote control protocol doesn't really allow that at this
176  # point. It probably neverwill!
177  def _find_grail_rc(self):
178  import glob
179  import pwd
180  import socket
181  import tempfile
182  tempdir = os.path.join(tempfile.gettempdir(),
183  ".grail-unix")
184  user = pwd.getpwuid(os.getuid())[0]
185  filename = os.path.join(tempdir, user + "-*")
186  maybes = glob.glob(filename)
187  if not maybes:
188  return None
189  s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
190  for fn in maybes:
191  # need to PING each one until we find one that's live
192  try:
193  s.connect(fn)
194  except socket.error:
195  # no good; attempt to clean it out, but don't fail:
196  try:
197  os.unlink(fn)
198  except IOError:
199  pass
200  else:
201  return s
202 
203  def _remote(self, action):
204  s = self._find_grail_rc()
205  if not s:
206  return 0
207  s.send(action)
208  s.close()
209  return 1
210 
211  def open(self, url, new=0, autoraise=1):
212  if new:
213  self._remote("LOADNEW " + url)
214  else:
215  self._remote("LOAD " + url)
216 
217  def open_new(self, url):
218  self.open(url, 1)
219 
220 
222  def open(self, url, new=0, autoraise=1):
223  os.startfile(url)
224 
225  def open_new(self, url):
226  self.open(url)
227 
228 #
229 # Platform support for Unix
230 #
231 
232 # This is the right test because all these Unix browsers require either
233 # a console terminal of an X display to run. Note that we cannot split
234 # the TERM and DISPLAY cases, because we might be running Python from inside
235 # an xterm.
236 if os.environ.get("TERM") or os.environ.get("DISPLAY"):
237  _tryorder = ["mozilla","netscape","kfm","grail","links","lynx","w3m"]
238 
239  # Easy cases first -- register console browsers if we have them.
240  if os.environ.get("TERM"):
241  # The Links browser <http://artax.karlin.mff.cuni.cz/~mikulas/links/>
242  if _iscommand("links"):
243  register("links", None, GenericBrowser("links '%s'"))
244  # The Lynx browser <http://lynx.browser.org/>
245  if _iscommand("lynx"):
246  register("lynx", None, GenericBrowser("lynx '%s'"))
247  # The w3m browser <http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/eng/>
248  if _iscommand("w3m"):
249  register("w3m", None, GenericBrowser("w3m '%s'"))
250 
251  # X browsers have more in the way of options
252  if os.environ.get("DISPLAY"):
253  # First, the Netscape series
254  if _iscommand("mozilla"):
255  register("mozilla", None, Netscape("mozilla"))
256  if _iscommand("netscape"):
257  register("netscape", None, Netscape("netscape"))
258 
259  # Next, Mosaic -- old but still in use.
260  if _iscommand("mosaic"):
261  register("mosaic", None, GenericBrowser(
262  "mosaic '%s' >/dev/null &"))
263 
264  # Konqueror/kfm, the KDE browser.
265  if _iscommand("kfm") or _iscommand("konqueror"):
266  register("kfm", Konqueror, Konqueror())
267 
268  # Grail, the Python browser.
269  if _iscommand("grail"):
270  register("grail", Grail, None)
271 
272 
274  def open(self, url, new=0, autoraise=1):
275  ic.launchurl(url)
276 
277  def open_new(self, url):
278  self.open(url)
279 
280 
281 #
282 # Platform support for Windows
283 #
284 
285 if sys.platform[:3] == "win":
286  _tryorder = ["netscape", "windows-default"]
287  register("windows-default", WindowsDefault)
288 
289 #
290 # Platform support for MacOS
291 #
292 
293 try:
294  import ic
295 except ImportError:
296  pass
297 else:
298  # internet-config is the only supported controller on MacOS,
299  # so don't mess with the default!
300  _tryorder = ["internet-config"]
301  register("internet-config", InternetConfig)
302 
303 #
304 # Platform support for OS/2
305 #
306 
307 if sys.platform[:3] == "os2" and _iscommand("netscape.exe"):
308  _tryorder = ["os2netscape"]
309  register("os2netscape", None,
310  GenericBrowser("start netscape.exe %s"))
311 
312 # OK, now that we know what the default preference orders for each
313 # platform are, allow user to override them with the BROWSER variable.
314 #
315 if os.environ.has_key("BROWSER"):
316  # It's the user's responsibility to register handlers for any unknown
317  # browser referenced by this value, before calling open().
318  _tryorder = os.environ["BROWSER"].split(os.pathsep)
319 
320 for cmd in _tryorder:
321  if not _browsers.has_key(cmd.lower()):
322  if _iscommand(cmd.lower()):
323  register(cmd.lower(), None, GenericBrowser(
324  "%s '%%s'" % cmd.lower()))
325 
326 _tryorder = filter(lambda x: _browsers.has_key(x.lower())
327  or x.find("%s") > -1, _tryorder)
328 # what to do if _tryorder is now empty?