diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst index 85d36367221295..ee501e80d9ed61 100644 --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -83,7 +83,7 @@ The following functions are defined: caller's environment. -.. function:: register(name, constructor, instance=None) +.. function:: register(name, constructor, instance=None, *, preferred=False) Register the browser type *name*. Once a browser type is registered, the :func:`get` function can return a controller for that browser type. If @@ -91,9 +91,11 @@ The following functions are defined: parameters to create an instance when needed. If *instance* is provided, *constructor* will never be called, and may be ``None``. - This entry point is only useful if you plan to either set the :envvar:`BROWSER` - variable or call :func:`get` with a nonempty argument matching the name of a - handler you declare. + Setting *preferred* to ``True`` makes this browser a preferred result for + a :func:`get` call with no argument. Otherwise, this entry point is only + useful if you plan to either set the :envvar:`BROWSER` variable or call + :func:`get` with a nonempty argument matching the name of a handler you + declare. A number of browser types are predefined. This table gives the type names that may be passed to the :func:`get` function and the corresponding instantiations diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index 6f43b7f1265d1a..a9eac69650546f 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -13,16 +13,21 @@ class Error(Exception): pass -_browsers = {} # Dictionary of available browser controllers -_tryorder = [] # Preference order of available browsers +_browsers = {} # Dictionary of available browser controllers +_tryorder = [] # Preference order of available browsers +_os_preferred_browser = None # The preferred browser -def register(name, klass, instance=None, update_tryorder=1): - """Register a browser connector and, optionally, connection.""" +def register(name, klass, instance=None, *, preferred=False): + """Register a browser connector.""" _browsers[name.lower()] = [klass, instance] - if update_tryorder > 0: - _tryorder.append(name) - elif update_tryorder < 0: + + # Preferred browsers go to the front of the list. + # Need to match to the default browser returned by xdg-settings, which + # may be of the form e.g. "firefox.desktop". + if preferred or (_os_preferred_browser and name in _os_preferred_browser): _tryorder.insert(0, name) + else: + _tryorder.append(name) def get(using=None): """Return a browser launcher instance appropriate for the environment.""" @@ -484,6 +489,14 @@ def register_X_browsers(): # Prefer X browsers if present if os.environ.get("DISPLAY"): + try: + cmd = "xdg-settings get default-web-browser".split() + result = subprocess.check_output(cmd).decode().strip() + except (FileNotFoundError, subprocess.CalledProcessError): + pass + else: + _os_preferred_browser = result + register_X_browsers() # Also try console browsers @@ -610,10 +623,10 @@ def open(self, url, new=0, autoraise=True): # Don't clear _tryorder or _browsers since OS X can use above Unix support # (but we prefer using the OS X specific stuff) - register("safari", None, MacOSXOSAScript('safari'), -1) - register("firefox", None, MacOSXOSAScript('firefox'), -1) - register("chrome", None, MacOSXOSAScript('chrome'), -1) - register("MacOSX", None, MacOSXOSAScript('default'), -1) + register("safari", None, MacOSXOSAScript('safari'), preferred=True) + register("firefox", None, MacOSXOSAScript('firefox'), preferred=True) + register("chrome", None, MacOSXOSAScript('chrome'), preferred=True) + register("MacOSX", None, MacOSXOSAScript('default'), preferred=True) # OK, now that we know what the default preference orders for each @@ -628,7 +641,7 @@ def open(self, url, new=0, autoraise=True): if cmdline != '': cmd = _synthesize(cmdline, -1) if cmd[1] is None: - register(cmdline, None, GenericBrowser(cmdline), -1) + register(cmdline, None, GenericBrowser(cmdline), preferred=True) cmdline = None # to make del work if _userchoices was empty del cmdline del _userchoices diff --git a/Misc/ACKS b/Misc/ACKS index 5ab6411688c7d1..e63a061098e8e0 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1458,6 +1458,7 @@ Quentin Stafford-Fraser Frank Stajano Joel Stanley Anthony Starks +David Steele Oliver Steele Greg Stein Marek Stepniowski diff --git a/Misc/NEWS b/Misc/NEWS index faae5f7e2a7196..87348ac73cc65d 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -433,6 +433,11 @@ Library - Issue #23262: The webbrowser module now supports Firefox 36+ and derived browsers. Based on patch by Oleg Broytman. +- Issue #24241: The webbrowser in an X environment now prefers using the + default browser directly. Also, the webbrowser register() function now has + a documented 'preferred' argument, to specify browsers to be returned by + get() with no arguments. Patch by David Steele + - Issue #27939: Fixed bugs in tkinter.ttk.LabeledScale and tkinter.Scale caused by representing the scale as float value internally in Tk. tkinter.IntVar now works if float value is set to underlying Tk variable.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: