mirror of
https://github.com/python/cpython.git
synced 2025-07-08 20:05:28 +00:00
bpo-24241: Improve preferred webbrowser handling (#85)
- Add 'preferred' argument to webbrowser.register - Use xdg-settings to specify preferred X browser The first change replaces the existing undocumented tri-state 'try_order' parameter with the documented boolean keyword-only 'preferred' parameter. Setting it to True places the browser at the front of the list, preferring it as the return to a subsequent get() call. The second change adds a private `_os_preferred_browser` setting and then uses that to make the default browser reported by `xdg-settings` first in the try list when running under X (or another environment that sets the `DISPLAY` variable). This avoids the problem where the first entry in the tryorder queue otherwise defaults to xdg-open, which doesn't support the "new window" option.
This commit is contained in:
parent
e3bf4cdd3d
commit
e3ce69522f
4 changed files with 37 additions and 16 deletions
|
@ -83,7 +83,7 @@ The following functions are defined:
|
||||||
caller's environment.
|
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
|
Register the browser type *name*. Once a browser type is registered, the
|
||||||
:func:`get` function can return a controller for that browser type. If
|
: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,
|
parameters to create an instance when needed. If *instance* is provided,
|
||||||
*constructor* will never be called, and may be ``None``.
|
*constructor* will never be called, and may be ``None``.
|
||||||
|
|
||||||
This entry point is only useful if you plan to either set the :envvar:`BROWSER`
|
Setting *preferred* to ``True`` makes this browser a preferred result for
|
||||||
variable or call :func:`get` with a nonempty argument matching the name of a
|
a :func:`get` call with no argument. Otherwise, this entry point is only
|
||||||
handler you declare.
|
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
|
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
|
may be passed to the :func:`get` function and the corresponding instantiations
|
||||||
|
|
|
@ -15,14 +15,19 @@ class Error(Exception):
|
||||||
|
|
||||||
_browsers = {} # Dictionary of available browser controllers
|
_browsers = {} # Dictionary of available browser controllers
|
||||||
_tryorder = [] # Preference order of available browsers
|
_tryorder = [] # Preference order of available browsers
|
||||||
|
_os_preferred_browser = None # The preferred browser
|
||||||
|
|
||||||
def register(name, klass, instance=None, update_tryorder=1):
|
def register(name, klass, instance=None, *, preferred=False):
|
||||||
"""Register a browser connector and, optionally, connection."""
|
"""Register a browser connector."""
|
||||||
_browsers[name.lower()] = [klass, instance]
|
_browsers[name.lower()] = [klass, instance]
|
||||||
if update_tryorder > 0:
|
|
||||||
_tryorder.append(name)
|
# Preferred browsers go to the front of the list.
|
||||||
elif update_tryorder < 0:
|
# 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)
|
_tryorder.insert(0, name)
|
||||||
|
else:
|
||||||
|
_tryorder.append(name)
|
||||||
|
|
||||||
def get(using=None):
|
def get(using=None):
|
||||||
"""Return a browser launcher instance appropriate for the environment."""
|
"""Return a browser launcher instance appropriate for the environment."""
|
||||||
|
@ -484,6 +489,14 @@ def register_X_browsers():
|
||||||
|
|
||||||
# Prefer X browsers if present
|
# Prefer X browsers if present
|
||||||
if os.environ.get("DISPLAY"):
|
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()
|
register_X_browsers()
|
||||||
|
|
||||||
# Also try console browsers
|
# Also try console browsers
|
||||||
|
@ -610,10 +623,10 @@ if sys.platform == 'darwin':
|
||||||
|
|
||||||
# Don't clear _tryorder or _browsers since OS X can use above Unix support
|
# Don't clear _tryorder or _browsers since OS X can use above Unix support
|
||||||
# (but we prefer using the OS X specific stuff)
|
# (but we prefer using the OS X specific stuff)
|
||||||
register("safari", None, MacOSXOSAScript('safari'), -1)
|
register("safari", None, MacOSXOSAScript('safari'), preferred=True)
|
||||||
register("firefox", None, MacOSXOSAScript('firefox'), -1)
|
register("firefox", None, MacOSXOSAScript('firefox'), preferred=True)
|
||||||
register("chrome", None, MacOSXOSAScript('chrome'), -1)
|
register("chrome", None, MacOSXOSAScript('chrome'), preferred=True)
|
||||||
register("MacOSX", None, MacOSXOSAScript('default'), -1)
|
register("MacOSX", None, MacOSXOSAScript('default'), preferred=True)
|
||||||
|
|
||||||
|
|
||||||
# OK, now that we know what the default preference orders for each
|
# OK, now that we know what the default preference orders for each
|
||||||
|
@ -628,7 +641,7 @@ if "BROWSER" in os.environ:
|
||||||
if cmdline != '':
|
if cmdline != '':
|
||||||
cmd = _synthesize(cmdline, -1)
|
cmd = _synthesize(cmdline, -1)
|
||||||
if cmd[1] is None:
|
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
|
cmdline = None # to make del work if _userchoices was empty
|
||||||
del cmdline
|
del cmdline
|
||||||
del _userchoices
|
del _userchoices
|
||||||
|
|
|
@ -1458,6 +1458,7 @@ Quentin Stafford-Fraser
|
||||||
Frank Stajano
|
Frank Stajano
|
||||||
Joel Stanley
|
Joel Stanley
|
||||||
Anthony Starks
|
Anthony Starks
|
||||||
|
David Steele
|
||||||
Oliver Steele
|
Oliver Steele
|
||||||
Greg Stein
|
Greg Stein
|
||||||
Marek Stepniowski
|
Marek Stepniowski
|
||||||
|
|
|
@ -433,6 +433,11 @@ Library
|
||||||
- Issue #23262: The webbrowser module now supports Firefox 36+ and derived
|
- Issue #23262: The webbrowser module now supports Firefox 36+ and derived
|
||||||
browsers. Based on patch by Oleg Broytman.
|
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
|
- Issue #27939: Fixed bugs in tkinter.ttk.LabeledScale and tkinter.Scale caused
|
||||||
by representing the scale as float value internally in Tk. tkinter.IntVar
|
by representing the scale as float value internally in Tk. tkinter.IntVar
|
||||||
now works if float value is set to underlying Tk variable.
|
now works if float value is set to underlying Tk variable.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue