[Python-Dev] urllib.browse() issues

Eric S. Raymond esr@thyrsus.com
Thu, 6 Jul 2000 16:35:11 -0400

Fred L. Drake, Jr. <fdrake@beopen.com>:
>   If Guido doesn't object to moving this module, the task falls to me
> since I wrote it.  Were there any requirements you had that the
> existing BrowserControl doesn't support?  If so, please tell us from
> the requirements side.

Frankly, what's there strikes me as overly complex and tied to the
heavyweight IDLE environment.  Here's the latest version of my code
for comparison.  Comment and critique follows.

# Support for launching a browser

_browsers = None

def iscommand(cmd):
    # I'd still like to put a cross-platform version of this in the library
    if os.name == 'posix':
        return os.system('which 1>/dev/null 2>&1 ' + cmd) == 0
	return 1

def urlbrowse(url):
    """Launch a browser, in background if possible, pointed at the given URL.
    Accept either a string or a parsed URL tuple. 
    Interpret the BROWSER environment variable, if it exists,
    as a colon-separated list of browser commands to try.
    from urlparse import urlunparse 
    if type(url) == ():
        url = urlunparse(url)
    global _browsers
    if os.environ.has_key("BROWSER"):
	_browsers = string.split(os.environ["BROWSER"], ":")
    elif os.name == 'posix':
	_browsers = ["mozilla %s &",
		    "netscape -remote 'openURL(%s)'",
		    "netscape %s &",
		    "lynx %s",
		    "w3m %s"]
    elif os.name == 'nt':
	_browsers = ['start %s']
    for browser in _browsers:
        if _iscommand(string.split(browser)[0]):
            if os.system((browser % url)) == 0:
                return 1
    return 0

One significant difference is that my code gets the user preference
for a browser from an environment variable, rather than a profile.
This is appropriate for a preference that will be shared across multiple
applications, and follows the pattern of well-known Unix envirinment
variables like EDITOR.

Another difference is that my code tries harder to have smart default
behavior.  Notice the order of attempts -- X browsers are tried first
in background, then character browsers in the foreground.  This means
you are more likely to get some reasonable behavior independent of
whether the calling Python program is launched from within X, from an
Xterm, or on an X-less console.

The register() calls seem kind of overelaborate.  Why not just
update a global dictionary directly?

Things I like about the IDLE code, on the other hand...the
distinction between open() and open_new() methods is good.  It's also
clearly smarter about the actual mechanics of browser invocation.

I think what I'd like to see is a merged version that starts with your
class organization, discards the .ini profile cruft in favor of an
environment-variable check, uses my logic for hunting up a browser,
and uses your incantations for actually invoking the browser.
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

Of all tyrannies, a tyranny exercised for the good of its victims may
be the most oppressive. It may be better to live under robber barons
than under omnipotent moral busybodies. The robber baron's cruelty may
sometimes sleep, his cupidity may at some point be satiated; but those
who torment us for our own good will torment us without end, for they
do so with the approval of their consciences.
	-- C. S. Lewis