11
11
12
12
__all__ = ["Error" , "open" , "open_new" , "open_new_tab" , "get" , "register" ]
13
13
14
+
14
15
class Error (Exception ):
15
16
pass
16
17
18
+
17
19
_lock = threading .RLock ()
18
20
_browsers = {} # Dictionary of available browser controllers
19
21
_tryorder = None # Preference order of available browsers
20
22
_os_preferred_browser = None # The preferred browser
21
23
24
+
22
25
def register (name , klass , instance = None , * , preferred = False ):
23
26
"""Register a browser connector."""
24
27
with _lock :
@@ -34,6 +37,7 @@ def register(name, klass, instance=None, *, preferred=False):
34
37
else :
35
38
_tryorder .append (name )
36
39
40
+
37
41
def get (using = None ):
38
42
"""Return a browser launcher instance appropriate for the environment."""
39
43
if _tryorder is None :
@@ -64,6 +68,7 @@ def get(using=None):
64
68
return command [0 ]()
65
69
raise Error ("could not locate runnable browser" )
66
70
71
+
67
72
# Please note: the following definition hides a builtin function.
68
73
# It is recommended one does "import webbrowser" and uses webbrowser.open(url)
69
74
# instead of "from webbrowser import *".
@@ -87,13 +92,15 @@ def open(url, new=0, autoraise=True):
87
92
return True
88
93
return False
89
94
95
+
90
96
def open_new (url ):
91
97
"""Open url in a new window of the default browser.
92
98
93
99
If not possible, then open url in the only browser window.
94
100
"""
95
101
return open (url , 1 )
96
102
103
+
97
104
def open_new_tab (url ):
98
105
"""Open url in a new page ("tab") of the default browser.
99
106
@@ -136,7 +143,7 @@ def _synthesize(browser, *, preferred=False):
136
143
137
144
# General parent classes
138
145
139
- class BaseBrowser ( object ) :
146
+ class BaseBrowser :
140
147
"""Parent class for all browsers. Do not use directly."""
141
148
142
149
args = ['%s' ]
@@ -197,7 +204,7 @@ def open(self, url, new=0, autoraise=True):
197
204
else :
198
205
p = subprocess .Popen (cmdline , close_fds = True ,
199
206
start_new_session = True )
200
- return ( p .poll () is None )
207
+ return p .poll () is None
201
208
except OSError :
202
209
return False
203
210
@@ -225,7 +232,8 @@ def _invoke(self, args, remote, autoraise, url=None):
225
232
# use autoraise argument only for remote invocation
226
233
autoraise = int (autoraise )
227
234
opt = self .raise_opts [autoraise ]
228
- if opt : raise_opt = [opt ]
235
+ if opt :
236
+ raise_opt = [opt ]
229
237
230
238
cmdline = [self .name ] + raise_opt + args
231
239
@@ -266,8 +274,8 @@ def open(self, url, new=0, autoraise=True):
266
274
else :
267
275
action = self .remote_action_newtab
268
276
else :
269
- raise Error ("Bad 'new' parameter to open(); " +
270
- "expected 0, 1, or 2, got %s" % new )
277
+ raise Error ("Bad 'new' parameter to open(); "
278
+ f "expected 0, 1, or 2, got { new } " )
271
279
272
280
args = [arg .replace ("%s" , url ).replace ("%action" , action )
273
281
for arg in self .remote_args ]
@@ -302,19 +310,20 @@ class Epiphany(UnixBrowser):
302
310
303
311
304
312
class Chrome (UnixBrowser ):
305
- "Launcher class for Google Chrome browser."
313
+ """ Launcher class for Google Chrome browser."" "
306
314
307
315
remote_args = ['%action' , '%s' ]
308
316
remote_action = ""
309
317
remote_action_newwin = "--new-window"
310
318
remote_action_newtab = ""
311
319
background = True
312
320
321
+
313
322
Chromium = Chrome
314
323
315
324
316
325
class Opera (UnixBrowser ):
317
- "Launcher class for Opera browser."
326
+ """ Launcher class for Opera browser."" "
318
327
319
328
remote_args = ['%action' , '%s' ]
320
329
remote_action = ""
@@ -324,7 +333,7 @@ class Opera(UnixBrowser):
324
333
325
334
326
335
class Elinks (UnixBrowser ):
327
- "Launcher class for Elinks browsers."
336
+ """ Launcher class for Elinks browsers."" "
328
337
329
338
remote_args = ['-remote' , 'openURL(%s%action)' ]
330
339
remote_action = ""
@@ -387,11 +396,11 @@ def open(self, url, new=0, autoraise=True):
387
396
except OSError :
388
397
return False
389
398
else :
390
- return ( p .poll () is None )
399
+ return p .poll () is None
391
400
392
401
393
402
class Edge (UnixBrowser ):
394
- "Launcher class for Microsoft Edge browser."
403
+ """ Launcher class for Microsoft Edge browser."" "
395
404
396
405
remote_args = ['%action' , '%s' ]
397
406
remote_action = ""
@@ -461,7 +470,6 @@ def register_X_browsers():
461
470
if shutil .which ("opera" ):
462
471
register ("opera" , None , Opera ("opera" ))
463
472
464
-
465
473
if shutil .which ("microsoft-edge" ):
466
474
register ("microsoft-edge" , None , Edge ("microsoft-edge" ))
467
475
@@ -514,7 +522,8 @@ def register_standard_browsers():
514
522
cmd = "xdg-settings get default-web-browser" .split ()
515
523
raw_result = subprocess .check_output (cmd , stderr = subprocess .DEVNULL )
516
524
result = raw_result .decode ().strip ()
517
- except (FileNotFoundError , subprocess .CalledProcessError , PermissionError , NotADirectoryError ) :
525
+ except (FileNotFoundError , subprocess .CalledProcessError ,
526
+ PermissionError , NotADirectoryError ):
518
527
pass
519
528
else :
520
529
global _os_preferred_browser
@@ -584,15 +593,16 @@ def __init__(self, name='default'):
584
593
585
594
def open (self , url , new = 0 , autoraise = True ):
586
595
sys .audit ("webbrowser.open" , url )
596
+ url = url .replace ('"' , '%22' )
587
597
if self .name == 'default' :
588
- script = 'open location "%s"' % url . replace ( '"' , '%22' ) # opens in default browser
598
+ script = f 'open location "{ url } "' # opens in default browser
589
599
else :
590
600
script = f'''
591
- tell application "%s "
601
+ tell application "{ self . name } "
592
602
activate
593
- open location "%s "
603
+ open location "{ url } "
594
604
end
595
- ''' % ( self . name , url . replace ( '"' , '%22' ))
605
+ '''
596
606
597
607
osapipe = os .popen ("osascript" , "w" )
598
608
if osapipe is None :
@@ -667,33 +677,31 @@ def open(self, url, new=0, autoraise=True):
667
677
return True
668
678
669
679
670
- def main ():
671
- import getopt
672
- usage = """Usage: %s [-n | -t | -h] url
673
- -n: open new window
674
- -t: open new tab
675
- -h, --help: show help""" % sys .argv [0 ]
676
- try :
677
- opts , args = getopt .getopt (sys .argv [1 :], 'ntdh' ,['help' ])
678
- except getopt .error as msg :
679
- print (msg , file = sys .stderr )
680
- print (usage , file = sys .stderr )
681
- sys .exit (1 )
682
- new_win = 0
683
- for o , a in opts :
684
- if o == '-n' : new_win = 1
685
- elif o == '-t' : new_win = 2
686
- elif o == '-h' or o == '--help' :
687
- print (usage , file = sys .stderr )
688
- sys .exit ()
689
- if len (args ) != 1 :
690
- print (usage , file = sys .stderr )
691
- sys .exit (1 )
692
-
693
- url = args [0 ]
694
- open (url , new_win )
680
+ def parse_args (arg_list : list [str ] | None ):
681
+ import argparse
682
+ parser = argparse .ArgumentParser (description = "Open URL in a web browser." )
683
+ parser .add_argument ("url" , help = "URL to open" )
684
+
685
+ group = parser .add_mutually_exclusive_group ()
686
+ group .add_argument ("-n" , "--new-window" , action = "store_const" ,
687
+ const = 1 , default = 0 , dest = "new_win" ,
688
+ help = "open new window" )
689
+ group .add_argument ("-t" , "--new-tab" , action = "store_const" ,
690
+ const = 2 , default = 0 , dest = "new_win" ,
691
+ help = "open new tab" )
692
+
693
+ args = parser .parse_args (arg_list )
694
+
695
+ return args
696
+
697
+
698
+ def main (arg_list : list [str ] | None = None ):
699
+ args = parse_args (arg_list )
700
+
701
+ open (args .url , args .new_win )
695
702
696
703
print ("\a " )
697
704
705
+
698
706
if __name__ == "__main__" :
699
707
main ()
0 commit comments