mirror of https://github.com/python/cpython
bpo-29645: Speed up importing the webbrowser module. (#484)
This commit is contained in:
parent
8606e9524a
commit
a7cba27aea
|
@ -266,5 +266,30 @@ class BrowserRegistrationTest(unittest.TestCase):
|
|||
self._check_registration(preferred=True)
|
||||
|
||||
|
||||
class ImportTest(unittest.TestCase):
|
||||
def test_register(self):
|
||||
webbrowser = support.import_fresh_module('webbrowser')
|
||||
self.assertIsNone(webbrowser._tryorder)
|
||||
self.assertFalse(webbrowser._browsers)
|
||||
|
||||
class ExampleBrowser:
|
||||
pass
|
||||
webbrowser.register('Example1', ExampleBrowser)
|
||||
self.assertTrue(webbrowser._tryorder)
|
||||
self.assertEqual(webbrowser._tryorder[-1], 'Example1')
|
||||
self.assertTrue(webbrowser._browsers)
|
||||
self.assertIn('example1', webbrowser._browsers)
|
||||
self.assertEqual(webbrowser._browsers['example1'], [ExampleBrowser, None])
|
||||
|
||||
def test_get(self):
|
||||
webbrowser = support.import_fresh_module('webbrowser')
|
||||
self.assertIsNone(webbrowser._tryorder)
|
||||
self.assertFalse(webbrowser._browsers)
|
||||
|
||||
with self.assertRaises(webbrowser.Error):
|
||||
webbrowser.get('fakebrowser')
|
||||
self.assertIsNotNone(webbrowser._tryorder)
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -7,30 +7,39 @@ import shlex
|
|||
import shutil
|
||||
import sys
|
||||
import subprocess
|
||||
import threading
|
||||
|
||||
__all__ = ["Error", "open", "open_new", "open_new_tab", "get", "register"]
|
||||
|
||||
class Error(Exception):
|
||||
pass
|
||||
|
||||
_lock = threading.RLock()
|
||||
_browsers = {} # Dictionary of available browser controllers
|
||||
_tryorder = [] # Preference order of available browsers
|
||||
_tryorder = None # Preference order of available browsers
|
||||
_os_preferred_browser = None # The preferred browser
|
||||
|
||||
def register(name, klass, instance=None, *, preferred=False):
|
||||
"""Register a browser connector."""
|
||||
_browsers[name.lower()] = [klass, instance]
|
||||
with _lock:
|
||||
if _tryorder is None:
|
||||
register_standard_browsers()
|
||||
_browsers[name.lower()] = [klass, instance]
|
||||
|
||||
# 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)
|
||||
# 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."""
|
||||
if _tryorder is None:
|
||||
with _lock:
|
||||
if _tryorder is None:
|
||||
register_standard_browsers()
|
||||
if using is not None:
|
||||
alternatives = [using]
|
||||
else:
|
||||
|
@ -60,6 +69,10 @@ def get(using=None):
|
|||
# instead of "from webbrowser import *".
|
||||
|
||||
def open(url, new=0, autoraise=True):
|
||||
if _tryorder is None:
|
||||
with _lock:
|
||||
if _tryorder is None:
|
||||
register_standard_browsers()
|
||||
for name in _tryorder:
|
||||
browser = get(name)
|
||||
if browser.open(url, new, autoraise):
|
||||
|
@ -487,34 +500,76 @@ def register_X_browsers():
|
|||
if shutil.which("grail"):
|
||||
register("grail", Grail, None)
|
||||
|
||||
# Prefer X browsers if present
|
||||
if os.environ.get("DISPLAY"):
|
||||
try:
|
||||
cmd = "xdg-settings get default-web-browser".split()
|
||||
raw_result = subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
|
||||
result = raw_result.decode().strip()
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
pass
|
||||
def register_standard_browsers():
|
||||
global _tryorder
|
||||
_tryorder = []
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
register("MacOSX", None, MacOSXOSAScript('default'))
|
||||
register("chrome", None, MacOSXOSAScript('chrome'))
|
||||
register("firefox", None, MacOSXOSAScript('firefox'))
|
||||
register("safari", None, MacOSXOSAScript('safari'))
|
||||
# OS X can use below Unix support (but we prefer using the OS X
|
||||
# specific stuff)
|
||||
|
||||
if sys.platform[:3] == "win":
|
||||
# First try to use the default Windows browser
|
||||
register("windows-default", WindowsDefault)
|
||||
|
||||
# Detect some common Windows browsers, fallback to IE
|
||||
iexplore = os.path.join(os.environ.get("PROGRAMFILES", "C:\\Program Files"),
|
||||
"Internet Explorer\\IEXPLORE.EXE")
|
||||
for browser in ("firefox", "firebird", "seamonkey", "mozilla",
|
||||
"netscape", "opera", iexplore):
|
||||
if shutil.which(browser):
|
||||
register(browser, None, BackgroundBrowser(browser))
|
||||
else:
|
||||
_os_preferred_browser = result
|
||||
# Prefer X browsers if present
|
||||
if os.environ.get("DISPLAY"):
|
||||
try:
|
||||
cmd = "xdg-settings get default-web-browser".split()
|
||||
raw_result = subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
|
||||
result = raw_result.decode().strip()
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
pass
|
||||
else:
|
||||
global _os_preferred_browser
|
||||
_os_preferred_browser = result
|
||||
|
||||
register_X_browsers()
|
||||
register_X_browsers()
|
||||
|
||||
# Also try console browsers
|
||||
if os.environ.get("TERM"):
|
||||
if shutil.which("www-browser"):
|
||||
register("www-browser", None, GenericBrowser("www-browser"))
|
||||
# The Links/elinks browsers <http://artax.karlin.mff.cuni.cz/~mikulas/links/>
|
||||
if shutil.which("links"):
|
||||
register("links", None, GenericBrowser("links"))
|
||||
if shutil.which("elinks"):
|
||||
register("elinks", None, Elinks("elinks"))
|
||||
# The Lynx browser <http://lynx.isc.org/>, <http://lynx.browser.org/>
|
||||
if shutil.which("lynx"):
|
||||
register("lynx", None, GenericBrowser("lynx"))
|
||||
# The w3m browser <http://w3m.sourceforge.net/>
|
||||
if shutil.which("w3m"):
|
||||
register("w3m", None, GenericBrowser("w3m"))
|
||||
|
||||
# OK, now that we know what the default preference orders for each
|
||||
# platform are, allow user to override them with the BROWSER variable.
|
||||
if "BROWSER" in os.environ:
|
||||
userchoices = os.environ["BROWSER"].split(os.pathsep)
|
||||
userchoices.reverse()
|
||||
|
||||
# Treat choices in same way as if passed into get() but do register
|
||||
# and prepend to _tryorder
|
||||
for cmdline in userchoices:
|
||||
if cmdline != '':
|
||||
cmd = _synthesize(cmdline, -1)
|
||||
if cmd[1] is None:
|
||||
register(cmdline, None, GenericBrowser(cmdline), preferred=True)
|
||||
|
||||
# what to do if _tryorder is now empty?
|
||||
|
||||
# Also try console browsers
|
||||
if os.environ.get("TERM"):
|
||||
if shutil.which("www-browser"):
|
||||
register("www-browser", None, GenericBrowser("www-browser"))
|
||||
# The Links/elinks browsers <http://artax.karlin.mff.cuni.cz/~mikulas/links/>
|
||||
if shutil.which("links"):
|
||||
register("links", None, GenericBrowser("links"))
|
||||
if shutil.which("elinks"):
|
||||
register("elinks", None, Elinks("elinks"))
|
||||
# The Lynx browser <http://lynx.isc.org/>, <http://lynx.browser.org/>
|
||||
if shutil.which("lynx"):
|
||||
register("lynx", None, GenericBrowser("lynx"))
|
||||
# The w3m browser <http://w3m.sourceforge.net/>
|
||||
if shutil.which("w3m"):
|
||||
register("w3m", None, GenericBrowser("w3m"))
|
||||
|
||||
#
|
||||
# Platform support for Windows
|
||||
|
@ -532,20 +587,6 @@ if sys.platform[:3] == "win":
|
|||
else:
|
||||
return True
|
||||
|
||||
_tryorder = []
|
||||
_browsers = {}
|
||||
|
||||
# First try to use the default Windows browser
|
||||
register("windows-default", WindowsDefault)
|
||||
|
||||
# Detect some common Windows browsers, fallback to IE
|
||||
iexplore = os.path.join(os.environ.get("PROGRAMFILES", "C:\\Program Files"),
|
||||
"Internet Explorer\\IEXPLORE.EXE")
|
||||
for browser in ("firefox", "firebird", "seamonkey", "mozilla",
|
||||
"netscape", "opera", iexplore):
|
||||
if shutil.which(browser):
|
||||
register(browser, None, BackgroundBrowser(browser))
|
||||
|
||||
#
|
||||
# Platform support for MacOS
|
||||
#
|
||||
|
@ -622,34 +663,6 @@ if sys.platform == 'darwin':
|
|||
return not rc
|
||||
|
||||
|
||||
# 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'), 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
|
||||
# platform are, allow user to override them with the BROWSER variable.
|
||||
if "BROWSER" in os.environ:
|
||||
_userchoices = os.environ["BROWSER"].split(os.pathsep)
|
||||
_userchoices.reverse()
|
||||
|
||||
# Treat choices in same way as if passed into get() but do register
|
||||
# and prepend to _tryorder
|
||||
for cmdline in _userchoices:
|
||||
if cmdline != '':
|
||||
cmd = _synthesize(cmdline, -1)
|
||||
if cmd[1] is None:
|
||||
register(cmdline, None, GenericBrowser(cmdline), preferred=True)
|
||||
cmdline = None # to make del work if _userchoices was empty
|
||||
del cmdline
|
||||
del _userchoices
|
||||
|
||||
# what to do if _tryorder is now empty?
|
||||
|
||||
|
||||
def main():
|
||||
import getopt
|
||||
usage = """Usage: %s [-n | -t] url
|
||||
|
|
Loading…
Reference in New Issue