cpython/Lib/webbrowser.py
Tim Peters f58a7aafea Implemented new os.startfile function, unique to Windows, exposing a
subset of Win32 ShellExecute's functionality.  Guido wants this because
IDLE's Help -> Docs function currently crashes his machine because of a
conflict between his version of Norton AntiVirus (6.10.20) and MS's
_popen.  Docs for startfile are being mailed to Fred (or just read the
docstring -- it tells the whole story).
Changed webbrowser.py to use os.startfile instead of os.popen on Windows.
Changed IDLE's EditorWindow.py to pass an absolute path for the docs
(hardcoding ShellExecute's "directory" arg to "." as used to be done let
IDLE work, but made the startfile command exceedingly obscure for other
uses -- the MS docs are terrible, of course, & still not sure I
understand it).
Note that Windows Python must link with shell32.lib now!  That's where
ShellExecute lives.
2000-09-22 10:05:54 +00:00

228 lines
5.5 KiB
Python

"""Remote-control interfaces to some browsers."""
import os
import sys
PROCESS_CREATION_DELAY = 4
class Error(Exception):
pass
_browsers = {}
def register(name, klass, instance=None):
"""Register a browser connector and, optionally, connection."""
_browsers[name.lower()] = [klass, instance]
def get(name=None):
"""Retrieve a connection to a browser by type name, or the default
browser."""
name = name or DEFAULT_BROWSER
try:
L = _browsers[name.lower()]
except KeyError:
raise ValueError, "unknown browser type: " + `name`
if L[1] is None:
L[1] = L[0]()
return L[1]
# Please note: the following definition hides a builtin function.
def open(url, new=0):
get().open(url, new)
def open_new(url):
get().open_new(url)
def _iscommand(cmd):
"""Return true if cmd can be found on the executable search path."""
path = os.environ.get("PATH")
if not path:
return 0
for d in path.split(os.pathsep):
exe = os.path.join(d, cmd)
if os.path.isfile(exe):
return 1
return 0
class CommandLineBrowser:
_browsers = []
if os.environ.get("DISPLAY"):
_browsers.extend([
("netscape", "netscape %s >/dev/null &"),
("mosaic", "mosaic %s >/dev/null &"),
])
_browsers.extend([
("lynx", "lynx %s"),
("w3m", "w3m %s"),
])
def open(self, url, new=0):
for exe, cmd in self._browsers:
if _iscommand(exe):
os.system(cmd % url)
return
raise Error("could not locate runnable browser")
def open_new(self, url):
self.open(url)
register("command-line", CommandLineBrowser)
class Netscape:
autoRaise = 1
def _remote(self, action):
raise_opt = ("-noraise", "-raise")[self.autoRaise]
cmd = "netscape %s -remote '%s' >/dev/null 2>&1" % (raise_opt, action)
rc = os.system(cmd)
if rc:
import time
os.system("netscape -no-about-splash &")
time.sleep(PROCESS_CREATION_DELAY)
rc = os.system(cmd)
return not rc
def open(self, url, new=0):
if new:
self.open_new(url)
else:
self._remote("openURL(%s)" % url)
def open_new(self, url):
self._remote("openURL(%s, new-window)" % url)
register("netscape", Netscape)
class Konquerer:
"""Controller for the KDE File Manager (kfm, or Konquerer).
See http://developer.kde.org/documentation/other/kfmclient.html
for more information on the Konquerer remote-control interface.
"""
def _remote(self, action):
cmd = "kfmclient %s >/dev/null 2>&1" % action
rc = os.system(cmd)
if rc:
import time
os.system("kfm -d &")
time.sleep(PROCESS_CREATION_DELAY)
rc = os.system(cmd)
return not rc
def open(self, url, new=1):
# XXX currently I know no way to prevent KFM from opening a new win.
self.open_new(url)
def open_new(self, url):
self._remote("openURL %s" % url)
register("kfm", Konquerer)
class Grail:
# There should be a way to maintain a connection to Grail, but the
# Grail remote control protocol doesn't really allow that at this
# point. It probably never will!
def _find_grail_rc(self):
import glob
import pwd
import socket
import tempfile
tempdir = os.path.join(tempfile.gettempdir(), ".grail-unix")
user = pwd.getpwuid(_os.getuid())[0]
filename = os.path.join(tempdir, user + "-*")
maybes = glob.glob(filename)
if not maybes:
return None
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
for fn in maybes:
# need to PING each one until we find one that's live
try:
s.connect(fn)
except socket.error:
# no good; attempt to clean it out, but don't fail:
try:
os.unlink(fn)
except IOError:
pass
else:
return s
def _remote(self, action):
s = self._find_grail_rc()
if not s:
return 0
s.send(action)
s.close()
return 1
def open(self, url, new=0):
if new:
self.open_new(url)
else:
self._remote("LOAD " + url)
def open_new(self, url):
self._remote("LOADNEW " + url)
register("grail", Grail)
class WindowsDefault:
def open(self, url, new=0):
os.startfile(url)
def open_new(self, url):
self.open(url)
DEFAULT_BROWSER = "command-line"
if sys.platform[:3] == "win":
del _browsers["kfm"]
register("windows-default", WindowsDefault)
DEFAULT_BROWSER = "windows-default"
elif os.environ.get("DISPLAY"):
if os.environ.get("KDEDIR"):
DEFAULT_BROWSER = "kfm"
elif _iscommand("netscape"):
DEFAULT_BROWSER = "netscape"
# If the $BROWSER environment variable is set and true, let that be
# the name of the browser to use:
#
DEFAULT_BROWSER = os.environ.get("BROWSER") or DEFAULT_BROWSER
# Now try to support the MacOS world. This is the only supported
# controller on that platform, so don't mess with the default!
try:
import ic
except ImportError:
pass
else:
class InternetConfig:
def open(self, url, new=0):
ic.launcurl(url)
def open_new(self, url):
self.open(url)
_browsers.clear()
register("internet-config", InternetConfig)
DEFAULT_BROWSER = "internet-config"