jarun / ddgr

:duck: DuckDuckGo from the terminal
GNU General Public License v3.0
2.93k stars 139 forks source link

Opening Links in GUI browser within WSL (bash on windows) does not work #61

Closed mrwhale closed 4 years ago

mrwhale commented 6 years ago

Not sure if specific to ddgr but I cannot open links with my default GUI browser when using ddgr in WSL

I've set browser ($BROWSER) to be /mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe

Distributor ID: Ubuntu
Description:    Ubuntu 16.04.3 LTS
Release:        16.04
Codename:       xenial
$ ddgr -d cheese
[DEBUG] ddgr version 1.2
[DEBUG] Python version 3.5.2
[DEBUG] q:cheese, region:us-en, page:0, curindex:1, safe:1
[DEBUG] nextParams:
[DEBUG] proxy:{'https': None}
[DEBUG] Response body written to '/tmp/ddgr-response-nu6ap22r'.
[DEBUG] Prev nextParams:
[DEBUG] Next nextParams: Keywords=cheese&xargs=12KPjg1slSrZquh831MeKMQeKUgRpd1tm58N0uXsYsfIwUpX9u6dFIEOacyZA6QO1xt77k%5FcDYpflNaKymwfaJExjXBRHcX726gZS7%5FYsrb%2DeWZZIezeZgn7Sy2tkTZXIFYk%2DBSQ%2E%2E&hData=12KPjg1qdOxJy7tuqnF9W2TeGj8m4%2E

 (1) Cheese.com - World's Greatest Cheese Resource  [cheese.com]
Cheese and wine, the perfect recipe for a great dinner party. Light or heavy; fruity or dry, learn more about the wonderful combinations.

 (2) Cheese - Wikipedia  [en.wikipedia.org]
Cheese is a dairy product derived from milk that is produced in a wide range of flavors, textures, and forms by coagulation of the milk protein casein.It comprises proteins and fat from milk, usually the milk of cows, buffalo, goats, or
sheep.

 (3) Cheese Recipes - Allrecipes.com  [www.allrecipes.com]
Looking for cheese recipes? Allrecipes has more than 4,840 trusted cheese recipes complete with how-to videos, ratings, reviews, and cooking tips.

 (4) Cheese - Walmart.com  [www.walmart.com]
Shop for Cheese in Dairy, Eggs & Cheese. Buy products such as 4C HomeStyle Parmesan Romano Grated Cheese, 6 oz, Velveeta Original Cheese 16 oz. Box at Walmart and save.

 (5) Cheese - definition of cheese by The Free Dictionary  [www.thefreedictionary.com]
cheese 1 (chēz) n. 1. a. A solid food prepared from the pressed curd of milk, often seasoned and aged. b. A molded mass of this substance. 2. Something resembling this ...

 (6) A Guide to Cheese | Whole Foods Market  [www.wholefoodsmarket.com]
Walk into our stores & you'll find some of the best cheeses in the world. Read up on all things cheese including types, cooking with cheese, & more.

 (7) Gourmet Cheese | Di Bruno Bros.  [dibruno.com]
Di Bruno Brothers carries the finest selection of artisan and gourmet cheese online. Shop online and get your gourmet cheese shipped directly to you.

 (8) Cheese - The New York Times  [www.nytimes.com]
News about cheese. Commentary and archival information about cheese from The New York Times.

 (9) Murray's Cheese | Gourmet Cheeses & Meats, Cheese of the ...  [www.murrayscheese.com]
Cheese and meat is one of the oldest pairings, and Olympia Provisions is one of America's foremost producers of artisanal meats—Bon Appetit calls them the country's best charcuterie, and they've won more Good Food Awards than any other
producer ever.

 (10) Chuck E. Cheese's - Where A Kid Can Be A Kid®  [www.chuckecheese.com]
Come experience great food and fun for all ages! Chuck E. Cheese's offers family fun and entertainment, Where A Kid Can Be A Kid®!

ddgr (? for help) O 1
[DEBUG] Opening https://cheese.com/
[DEBUG] <webbrowser.GenericBrowser object at 0x7fab6e768940>

and nothing happens

Using python directly (what looks to be the way the scripts opens a link) works great (opens a firefox window on my windows desktop)

Python 2.7.12 (default, Dec  4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import webbrowser
>>> import pprint
>>> vars(webbrowser.get())
{'basename': 'firefox.exe', 'args': ['%s'], 'name': '/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe'}
>>> webbrowser.open("www.github.com")
True
jarun commented 6 years ago

You are invoking the browser directly from the python prompt. We try the order: https://github.com/jarun/ddgr/blob/master/ddgr#L108

Can you please try:

>>> print(webbrowser._tryorder)
['w3m', 'xdg-open', 'x-www-browser', 'google-chrome', 'opera', 'www-browser', 'elinks', 'w3m']

and see how the browsers are ordered? The code tries to use the first non-text browser and it seems to find GenericBrowser in the list.

Please note that ddgr supports Python3 and above only.

Unfortunately, I don't have WSL (or a Windows box for that matter) so you'll have to debug a bit but I think it would be trivial now that you know where to look. It would be great if you could submit a PR.

jarun commented 6 years ago

Ahh OK!!! Your second line gives it away. If you have set $BROWSER to firefox directly, you do NOT need to use the text browser override option. Just use o (small o) or just the index to open the links from the omniprompt.

mrwhale commented 6 years ago

Okay sorry I didnt realise I was using python 2 in my tests, still works with python3

Python 3.5.2 (default, Sep 14 2017, 22:51:06)                                                                 
[GCC 5.4.0 20160609] on linux                                                                                 
Type "help", "copyright", "credits" or "license" for more information.                                        
>>> import webbrowser                                                                                         
>>> import pprint                                                                                             
>>> vars(webbrowser.get())                                                                                    
{'basename': 'firefox.exe', 'args': ['%s'], 'name': '/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe'} 
>>> vars(webbrowser._tryorder)                                                                                
Traceback (most recent call last):                                                                            
  File "<stdin>", line 1, in <module>                                                                         
TypeError: vars() argument must have __dict__ attribute                                                       
>>> print(webbrowser._tryorder)                                                                               
['/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe', 'xdg-open', 'www-browser', 'w3m']                  
>>> webbrowser.open("https://github.com")                                                                     
True

It still doesn't seem to work, even when specifying o or just the index. I've added some further debugging to the ddgr script and ran that instead, it seems it doesnt open browser. THe last debug output is from an added debug line to 131. seems its failing the try block in opening the browser in the first place. Happy to continue debugging if you can point me in the right direction too


$ ./ddgr.py -d cheese
[DEBUG] ddgr version 1.4
[DEBUG] Python version 3.5.2
[DEBUG] q:cheese, region:us-en, page:0, curindex:1, safe:1
[DEBUG] nextParams:
[DEBUG] proxy:{'https': None}
[DEBUG] Response body written to '/tmp/ddgr-response-qen1cd4w'.
[DEBUG] Prev nextParams:
[DEBUG] Next nextParams: Keywords=cheese&xargs=12KPjg1slSrZquh831MeKMQeKUgRpd1tm58N0uXsYsfIwUpX9u6dFIEOacyZA6QO1xt77k%5FcDYpflNaKymwfaJExjXBRHcX726gZS7%5FYsrb%2DeWZZIezeZgn7Sy2tkTZXIFYk%2DBSQ%2E%2E&hData=12KPjg1qdOxJy7tuqnF9W2TeGj8m4%2E

 (1) Cheese.com - World's Greatest Cheese Resource  [cheese.com]
Cheese and wine, the perfect recipe for a great dinner party. Light or heavy; fruity or dry, learn more about the wonderful combinations.

 (2) Cheese - Wikipedia  [en.wikipedia.org]
Cheese is a dairy product derived from milk that is produced in a wide range of flavors, textures, and forms by coagulation of the milk protein casein.It comprises proteins and fat from milk, usually the milk of cows, buffalo, goats, or
sheep.

 (3) Cheese Recipes - Allrecipes.com  [www.allrecipes.com]
Looking for cheese recipes? Allrecipes has more than 4,840 trusted cheese recipes complete with how-to videos, ratings, reviews, and cooking tips.

 (4) A Guide to Cheese | Whole Foods Market  [www.wholefoodsmarket.com]
Walk into our stores & you'll find some of the best cheeses in the world. Read up on all things cheese including types, cooking with cheese, & more.

 (5) Gourmet Cheese | Di Bruno Bros.  [dibruno.com]
Di Bruno Brothers carries the finest selection of artisan and gourmet cheese online. Shop online and get your gourmet cheese shipped directly to you.

 (6) Cheese - The New York Times  [www.nytimes.com]
News about cheese. Commentary and archival information about cheese from The New York Times.

 (7) Cheese - definition of cheese by The Free Dictionary  [www.thefreedictionary.com]
cheese 1 (chēz) n. 1. a. A solid food prepared from the pressed curd of milk, often seasoned and aged. b. A molded mass of this substance. 2. Something resembling this ...

 (8) Murray's Cheese | Gourmet Cheeses & Meats, Cheese of the ...  [www.murrayscheese.com]
Cheese and meat is one of the oldest pairings, and Olympia Provisions is one of America's foremost producers of artisanal meats—Bon Appetit calls them the country's best charcuterie, and they've won more Good Food Awards than any other
producer ever.

 (9) Chuck E. Cheese's - Where A Kid Can Be A Kid®  [www.chuckecheese.com]
Come experience great food and fun for all ages! Chuck E. Cheese's offers family fun and entertainment, Where A Kid Can Be A Kid®!

 (10) Sargento | Home of Real Cheese People®  [www.sargento.com]
Recipes, snack ideas and product information for Real Cheese People®.

ddgr (? for help) 1
[DEBUG] Opening https://cheese.com/
[DEBUG] {'args': ['%s'], 'basename': 'firefox.exe', 'name': '/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe'}
['/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe', 'xdg-open', 'www-browser', 'w3m']
[DEBUG] didnt open browser                                                                            
jarun commented 6 years ago

Please add an except clause after the try block and print the exception. That may give us a hint on what fails.

jarun commented 6 years ago

In addition, please try by removing the new=2 param to webbrowser.open() call.

jarun commented 6 years ago

And a question - does the terminal webbrowser w3m work as expected?

mrwhale commented 6 years ago

Okay I tried. But it seems to be skipping the try: block and going straight to finally:

I added

    try:
        logdbg("trying to open browser")
        browser.open(url)
    except Exception as e: print(e)
    finally:
        if open_url.suppress_browser_output:
            os.close(fd)
            os.dup2(_stderr, 2)
            os.dup2(_stdout, 1)
            logdbg("didnt open browser")

and i get

ddgr (? for help) 1
[DEBUG] Opening https://cheese.com/
[DEBUG] {'name': '/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe', 'args': ['%s'], 'basename': 'firefox.exe'}
[DEBUG] didnt open browser
ddgr (? for help) o 1
[DEBUG] Opening https://cheese.com/
[DEBUG] {'name': '/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe', 'args': ['%s'], 'basename': 'firefox.exe'}
[DEBUG] didnt open browser
mrwhale commented 6 years ago

and yep, If i change BROWSER to w3m it works as intended. Opens up w3m in the same console

jarun commented 6 years ago

The output is not coming due to log suppression.

For now, just try:

    try:
        browser.open(url)
    except Exception as e:
        if open_url.suppress_browser_output:
            os.close(fd)
            os.dup2(_stderr, 2)
            os.dup2(_stdout, 1)
        print(e)
    finally:
        logdbg("didnt open browser")
jarun commented 6 years ago

Also, what happens if you remove the second param to open?

jarun commented 6 years ago

OK. I borrowed my friend's Windows box and I tried your steps there. He has Firefox 64-bit.

With it the browser opens by default without any changes. The problem I see is the browser doesn't return after opening the URL (the open() call blocks)). Only after I close the browser the next URL is opened.

jarun commented 6 years ago

However, new=2 is supposed to open a new tab and return.

Also, I couldn't reproduce your issue as the browser opens for me (but blocks).

jarun commented 6 years ago

Same behaviour in the python3 prompt as well.

mrwhale commented 6 years ago

Thanks for helping debug! Must be something funky on my system. Strange that it works via python3 prompt and not this :'(

After editing that try block, when trying to open a link, it doesn't open, doesn't give an error, but is blocked (like you mentioned) so not quite sure whats going on there!

ddgr (? for help) 1
[DEBUG] Opening https://github.com/
[DEBUG] {'args': ['%s'], 'name': '/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe', 'basename': 'firefox.exe'}
jarun commented 6 years ago

Is there an exception at all? Try:

    try:
        browser.open(url)
    except Exception as e:
        if open_url.suppress_browser_output:
            os.close(fd)
            os.dup2(_stderr, 2)
            os.dup2(_stdout, 1)
        print(e)
        print(hello)
jarun commented 6 years ago

Another thing you can try:

Set suppress_browser_output to False at line 115.

mrwhale commented 6 years ago

Okay no exception at all, even adding that print(hello) Changing line 115 to false how no effect either

jarun commented 6 years ago

Is your system up-to-date?

I did an apt update+upgrade on the system before the tests.

If yours is also up-to-date I am just worried why the two systems don't behave the same way.

jarun commented 6 years ago

Also, if Firefox is open, close it and then try to open links from ddgr. I had an issue once where it won't work on windows. I think that's when we moved to the tabbed option.

mrwhale commented 6 years ago

Still no love. What console emulator where you using on the test machine?

jarun commented 6 years ago

I am using putty to connect over ssh.

jarun commented 6 years ago

Interesting! This friend has putty-url. He says he uses w3m >90% of the time and if he needs the GUI browser, he just clicks on the links.

Personally, I don't have the experience but I think it's a clever way to handle this with webbrowser.open() behaving differently across platforms and installations. And it's infinitely flexible too! ;)

mrwhale commented 6 years ago

Okay I managed to get to the bottom of it 2 issues I found

  1. It was getting stuck at lines 116-123. Removing this and the combination of point 2 made it work
    if open_url.suppress_browser_output:
        _stderr = os.dup(2)
        os.close(2)
        _stdout = os.dup(1)
        os.close(1)
        fd = os.open(os.devnull, os.O_RDWR)
        os.dup2(fd, 2)
    os.dup2(fd, 1)
  2. I created a quick python script to open up a webpage, I finally got it to give me some output which was /usr/bin/xdg-open: 778: /usr/bin/xdg-open: /mnt/c/Program: not found showing that it wasnt escaping spaces in my environment variable properly Changing my environment variable to be single quoted with no escaping slashes got it working BROWSER='/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe'

Now it opens a new tab, and returns to prompt to let me keep interacting with ddgr I don't quite get what lines 116-123 do. Even though it works now I do get alot of debug errors that suggest something isn't quite right

It still fires the finally block even though it successfully opens the browser

jarun commented 6 years ago

As long as I can't reproduce this I can't remove that code. These lines ensure the debug and error logs from a GUI browser are redirected to /dev/null. For me all of these work as expected but the browser doesn't quit.

I guess there's nothing further I can do about it right away.

mrwhale commented 6 years ago

All good! Totally understandable. It's probably a very specific issue with my setup so I'll just use my modified version and leave you be :) thanks for the help!

jarun commented 6 years ago

:+1:

anorm commented 4 years ago

I've got the same problem as OP. By removing lines 137 and 139, it works. Do the original file descriptors need to be closed? Isn't enough to replace them (line 141,142)?

diff --git a/ddgr b/ddgr
index ebe9184..a6327a4 100755
--- a/ddgr
+++ b/ddgr
@@ -134,9 +134,9 @@ def open_url(url):

     if open_url.suppress_browser_output:
         _stderr = os.dup(2)
-        os.close(2)
+        #os.close(2)
         _stdout = os.dup(1)
-        os.close(1)
+        #os.close(1)
         fd = os.open(os.devnull, os.O_RDWR)
         os.dup2(fd, 2)
         os.dup2(fd, 1)
jarun commented 4 years ago

I'll check it out.

jarun commented 4 years ago

@anorm are you on WSL?

if yes, please detect if inside WSL using the first method here (https://www.scivision.dev/python-detect-wsl/) and skip the lines you commented. If it works, please raise a PR. I don't have Windows to test this on.

Detection snippet:

import uname

if 'Microsoft' in uname().release
    ...
jarun commented 4 years ago

There's a problem on Linux with importing uname:

ModuleNotFoundError: No module named 'uname'
jarun commented 4 years ago

Try the following:

import platform

if "microsoft" in platform.uname()[3].lower()
    ...