gh-128540: lookup default webbrowser on macOS (#130535)

Ensure web browser is launched by `webbrowser.open` on macOS, even for `file://` URLs.
This commit is contained in:
Min RK 2025-03-14 07:51:15 +01:00 committed by GitHub
parent f3e275f1a9
commit 96492785b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 93 additions and 1 deletions

View file

@ -1,3 +1,4 @@
import io
import os
import re
import shlex
@ -5,6 +6,7 @@ import subprocess
import sys
import unittest
import webbrowser
from functools import partial
from test import support
from test.support import import_helper
from test.support import is_apple_mobile
@ -301,6 +303,69 @@ class IOSBrowserTest(unittest.TestCase):
self._test('open_new_tab')
class MockPopenPipe:
def __init__(self, cmd, mode):
self.cmd = cmd
self.mode = mode
self.pipe = io.StringIO()
self._closed = False
def write(self, buf):
self.pipe.write(buf)
def close(self):
self._closed = True
return None
@unittest.skipUnless(sys.platform == "darwin", "macOS specific test")
@requires_subprocess()
class MacOSXOSAScriptTest(unittest.TestCase):
def setUp(self):
support.patch(self, os, "popen", self.mock_popen)
self.browser = webbrowser.MacOSXOSAScript("default")
def mock_popen(self, cmd, mode):
self.popen_pipe = MockPopenPipe(cmd, mode)
return self.popen_pipe
def test_default(self):
browser = webbrowser.get()
assert isinstance(browser, webbrowser.MacOSXOSAScript)
self.assertEqual(browser.name, "default")
def test_default_open(self):
url = "https://python.org"
self.browser.open(url)
self.assertTrue(self.popen_pipe._closed)
self.assertEqual(self.popen_pipe.cmd, "osascript")
script = self.popen_pipe.pipe.getvalue()
self.assertEqual(script.strip(), f'open location "{url}"')
def test_url_quote(self):
self.browser.open('https://python.org/"quote"')
script = self.popen_pipe.pipe.getvalue()
self.assertEqual(
script.strip(), 'open location "https://python.org/%22quote%22"'
)
def test_default_browser_lookup(self):
url = "file:///tmp/some-file.html"
self.browser.open(url)
script = self.popen_pipe.pipe.getvalue()
# doesn't actually test the browser lookup works,
# just that the branch is taken
self.assertIn("URLForApplicationToOpenURL", script)
self.assertIn(f'open location "{url}"', script)
def test_explicit_browser(self):
browser = webbrowser.MacOSXOSAScript("safari")
browser.open("https://python.org")
script = self.popen_pipe.pipe.getvalue()
self.assertIn('tell application "safari"', script)
self.assertIn('open location "https://python.org"', script)
class BrowserRegistrationTest(unittest.TestCase):
def setUp(self):

View file

@ -597,7 +597,32 @@ if sys.platform == 'darwin':
sys.audit("webbrowser.open", url)
url = url.replace('"', '%22')
if self.name == 'default':
script = f'open location "{url}"' # opens in default browser
proto, _sep, _rest = url.partition(":")
if _sep and proto.lower() in {"http", "https"}:
# default web URL, don't need to lookup browser
script = f'open location "{url}"'
else:
# if not a web URL, need to lookup default browser to ensure a browser is launched
# this should always work, but is overkill to lookup http handler
# before launching http
script = f"""
use framework "AppKit"
use AppleScript version "2.4"
use scripting additions
property NSWorkspace : a reference to current application's NSWorkspace
property NSURL : a reference to current application's NSURL
set http_url to NSURL's URLWithString:"https://python.org"
set browser_url to (NSWorkspace's sharedWorkspace)'s ¬
URLForApplicationToOpenURL:http_url
set app_path to browser_url's relativePath as text -- NSURL to absolute path '/Applications/Safari.app'
tell application app_path
activate
open location "{url}"
end tell
"""
else:
script = f'''
tell application "{self.name}"

View file

@ -0,0 +1,2 @@
Ensure web browser is launched by :func:`webbrowser.open` on macOS, even for
``file://`` URLs.