8000 gh-128540: lookup default webbrowser on macOS by minrk · Pull Request #130535 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-128540: lookup default webbrowser on macOS #130535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments. 8000
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions Lib/test/test_webbrowser.py
8000
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import io
import os
import re
import shlex
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
Expand Down Expand Up @@ -301,6 +303,69 @@ def test_open_new_tab(self):
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):
Expand Down
27 changes: 26 additions & 1 deletion Lib/webbrowser.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,32 @@ def open(self, url, new=0, autoraise=True):
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}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Ensure web browser is launched by :func:`webbrowser.open` on macOS, even for
``file://`` URLs.
Loading
0