diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst index 4667b81e38ada2..dec75b918899a9 100644 --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -80,6 +80,12 @@ The following functions are defined: equivalent to :func:`open_new`. +.. function:: open_incognito(url) + + Open *url* in incognito, or private, mode of the default browser, if possible, otherwise + equivalent to :func:`open_new`. + + .. function:: get(using=None) Return a controller object for the browser type *using*. If *using* is @@ -221,6 +227,12 @@ module-level convenience functions: possible, otherwise equivalent to :func:`open_new`. +.. method:: controller.open_incognito(url) + + Open *url* in a incognito, or private, mode of the browser handled by this controller, if + possible, otherwise equivalent to :func:`open_new`. + + .. rubric:: Footnotes .. [1] Executables named here without a full path will be searched in the diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index 2d695bc883131f..5b0495d4145cc0 100644 --- a/Lib/test/test_webbrowser.py +++ b/Lib/test/test_webbrowser.py @@ -94,6 +94,11 @@ def test_open_new_tab(self): options=[], arguments=[URL]) + def test_open_incognito(self): + self._test('open_incognito', + options=["--incognito"], + arguments=[URL]) + class EdgeCommandTest(CommandTestMixin, unittest.TestCase): @@ -119,6 +124,11 @@ def test_open_new_tab(self): options=[], arguments=[URL]) + def test_open_incognito(self): + self._test('open_incognito', + options=["--inprivate"], + arguments=[URL]) + class MozillaCommandTest(CommandTestMixin, unittest.TestCase): @@ -144,6 +154,10 @@ def test_open_new_tab(self): options=[], arguments=['-new-tab', URL]) + def test_open_incognito(self): + self._test('open_incognito', + options=["--private-window"], + arguments=[URL]) class EpiphanyCommandTest(CommandTestMixin, unittest.TestCase): @@ -169,6 +183,10 @@ def test_open_new_tab(self): options=['-w'], arguments=[URL]) + def test_open_incognito(self): + self._test('open_incognito', + options=["--incognito-mode"], + arguments=[URL]) class OperaCommandTest(CommandTestMixin, unittest.TestCase): diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index 8b0628745c57fc..017c5048d22b0d 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -19,6 +19,7 @@ class Error(Exception): _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.""" with _lock: @@ -75,6 +76,7 @@ def open(url, new=0, autoraise=True): - 0: the same browser window (the default). - 1: a new browser window. - 2: a new browser page ("tab"). + - 3: an incognito/ private browser. If possible, autoraise raises the window (the default) or not. """ if _tryorder is None: @@ -101,6 +103,12 @@ def open_new_tab(url): """ return open(url, 2) +def open_incognito(url): + """Open url in incognito mode of the default browser. + + If not possible, then the behavior becomes equivalent to open_new(). + """ + return open(url, 3) def _synthesize(browser, *, preferred=False): """Attempt to synthesize a controller based on existing controllers. @@ -154,6 +162,9 @@ def open_new(self, url): def open_new_tab(self, url): return self.open(url, 2) + def open_incognito(self, url): + return self.open(url, 3) + class GenericBrowser(BaseBrowser): """Class for all browsers started with a command @@ -218,6 +229,7 @@ class UnixBrowser(BaseBrowser): remote_action = None remote_action_newwin = None remote_action_newtab = None + remote_action_incognito = "" def _invoke(self, args, remote, autoraise, url=None): raise_opt = [] @@ -265,9 +277,11 @@ def open(self, url, new=0, autoraise=True): action = self.remote_action_newwin else: action = self.remote_action_newtab + elif new == 3: + action = self.remote_action_incognito else: raise Error("Bad 'new' parameter to open(); " + - "expected 0, 1, or 2, got %s" % new) + f"expected 0, 1, 2, or 3, got {new}") args = [arg.replace("%s", url).replace("%action", action) for arg in self.remote_args] @@ -288,6 +302,7 @@ class Mozilla(UnixBrowser): remote_action = "" remote_action_newwin = "-new-window" remote_action_newtab = "-new-tab" + remote_action_incognito = "--private-window" background = True @@ -298,6 +313,7 @@ class Epiphany(UnixBrowser): remote_args = ['%action', '%s'] remote_action = "-n" remote_action_newwin = "-w" + remote_action_incognito = "--incognito-mode" background = True @@ -308,6 +324,7 @@ class Chrome(UnixBrowser): remote_action = "" remote_action_newwin = "--new-window" remote_action_newtab = "" + remote_action_incognito = "--incognito" background = True Chromium = Chrome @@ -397,6 +414,7 @@ class Edge(UnixBrowser): remote_action = "" remote_action_newwin = "--new-window" remote_action_newtab = "" + remote_action_incognito = "--inprivate" background = True @@ -588,14 +606,23 @@ def open(self, url, new=0, autoraise=True): return not rc +def _get_supported_browsers(): + if _tryorder is None: + register_standard_browsers() + return _browsers.keys() + + def main(): import getopt - usage = """Usage: %s [-n | -t | -h] url + usage = """Usage: %s [-l] | [-b browser] [-i | -n | -t | -h] url -n: open new window -t: open new tab + -i: open with private mode + -l: list available browsers + -b : uses to open -h, --help: show help""" % sys.argv[0] try: - opts, args = getopt.getopt(sys.argv[1:], 'ntdh',['help']) + opts, args = getopt.getopt(sys.argv[1:], 'lintb:dh',['help']) except getopt.error as msg: print(msg, file=sys.stderr) print(usage, file=sys.stderr) @@ -604,6 +631,14 @@ def main(): for o, a in opts: if o == '-n': new_win = 1 elif o == '-t': new_win = 2 + elif o == "-i": + new_win = 3 + elif o == "-b": + browser = a + elif o == "-l": + for nam in _get_supported_browsers(): + print(nam) + sys.exit() elif o == '-h' or o == '--help': print(usage, file=sys.stderr) sys.exit() @@ -612,7 +647,15 @@ def main(): sys.exit(1) url = args[0] - open(url, new_win) + if browser: + try: + br = get(browser) + except: + print(f"browser {browser} not found", file=sys.stderr) + sys.exit(1) + br.open(url, new_win) + else: + open(url, new_win) print("\a") diff --git a/Misc/NEWS.d/next/Library/2023-06-22-09-14-45.gh-issue-105983.7osoHj.rst b/Misc/NEWS.d/next/Library/2023-06-22-09-14-45.gh-issue-105983.7osoHj.rst new file mode 100644 index 00000000000000..de0a057e861228 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-06-22-09-14-45.gh-issue-105983.7osoHj.rst @@ -0,0 +1 @@ +Add support for incognito / private browsing for :func:`webbrowser.open`.