Skip to content

chrome/chromium renderer not detected correctly on Ubuntu (name is chromium-browser) #2348

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

Closed
emmanuelle opened this issue Apr 2, 2020 · 15 comments
Labels
bug something broken

Comments

@emmanuelle
Copy link
Contributor

On my Ubuntu machine I cannot configure a chrome renderer (my default browser is firefox). The reason is that Chromium is registered with the name chromium-browser as shown below, so that webbrowser.get throws an error when called with chrome.

>>> import plotly.io as pio                                                                                                      
>>> pio.renderers.default = 'chromium'                                                                                           
>>> import plotly.graph_objects as go                                                                                            
>>> go.Figure(go.Scatter(x=[1], y=[0])).show()                                                                                   
Traceback (most recent call last):
  File "<ipython-input-5-d0da89a1679b>", line 1, in <module>
    go.Figure(go.Scatter(x=[1], y=[0])).show()
  File "/home/emma/code/plotly.py/packages/python/plotly/plotly/basedatatypes.py", line 2794, in show
    return pio.show(self, *args, **kwargs)
  File "/home/emma/code/plotly.py/packages/python/plotly/plotly/io/_renderers.py", line 391, in show
    renderers._perform_external_rendering(fig_dict, renderers_string=renderer, **kwargs)
  File "/home/emma/code/plotly.py/packages/python/plotly/plotly/io/_renderers.py", line 340, in _perform_external_rendering
    renderer.render(fig_dict)
  File "/home/emma/code/plotly.py/packages/python/plotly/plotly/io/_base_renderers.py", line 736, in render
    open_html_in_browser(html, self.using, self.new, self.autoraise)
  File "/home/emma/code/plotly.py/packages/python/plotly/plotly/io/_base_renderers.py", line 681, in open_html_in_browser
    webbrowser.get(using).open(
  File "/usr/lib/python3.7/webbrowser.py", line 65, in get
    raise Error("could not locate runnable browser")
Error: could not locate runnable browser

>>> import webbrowser                                                                                                            
>>> print(webbrowser._browsers)                                                                                                  
{'xdg-open': [None, <webbrowser.BackgroundBrowser object at 0x7fe81203fef0>], 'gvfs-open': [None, <webbrowser.BackgroundBrowser object at 0x7fe81203fbe0>], 'x-www-browser': [None, <webbrowser.BackgroundBrowser object at 0x7fe81203f7b8>], 'firefox': [None, <webbrowser.Mozilla object at 0x7fe81203ff98>], 'chromium-browser': [None, <webbrowser.Chrome object at 0x7fe81203f860>]}

We could either add another renderer name chromium-browser, or query matching strings in webbrowser._browser.keys(). The second solution is probably cleaner and could also make it possible to remove either 'chrome' or 'chromium' if we want. Thoughts @jonmmease @nicolaskruchten ?

@emmanuelle emmanuelle added the bug something broken label Apr 2, 2020
@nicolaskruchten
Copy link
Contributor

Happy to go with the cleaner solution. What does setting the renderer to browser do?

@emmanuelle
Copy link
Contributor Author

It uses the default browser.

@emmanuelle
Copy link
Contributor Author

I wanted to reproduce a problem which a user was having on Chrome without having to change my default browser.

@jonmmease
Copy link
Contributor

... or query matching strings in webbrowser._browser.keys()

Yeah, I like this idea. I think attempting to separate chrome and chromium is still a good idea. We could have the BrowserRenderer class accept a list of strings as the using argument, and have it use the first browser in the list that's present in webbrowser._browser.keys. Then we could have lines like

renderers["chrome"] = BrowserRenderer(config=config, using=["chrome", "chrome-browser"])
renderers["chromium"] = BrowserRenderer(config=config, using=["chromium", "chromium-browser"])

@c-chaitanya
Copy link
Contributor

Hi @emmanuelle @jonmmease @nicolaskruchten

I have gone through the code and realised that this issue isn't fixed yet. Just wanted to confirm if I could start working on the fix or if it was being worked on by someone else?

@nicolaskruchten
Copy link
Contributor

A fix would be welcome, thank you :)

@c-chaitanya
Copy link
Contributor

c-chaitanya commented Jan 12, 2021

Thanks for the response @nicolaskruchten

Running webbrowser._browser.keys gives me the following list on my Ubuntu 16.04 distro

['firefox', 'xdg-open', 'gvfs-open', 'x-www-browser', 'google-chrome', 'chromium-browser', 'opera']

From @emmanuelle code we see that using chromium (in line 2) breaks the code , simillarly using chrome also breaks the code on my system.
Again using OS registered strings like chromium-browser or google-chrome does not throw any error.

import plotly.io as pio                                                                                                      
pio.renderers.default = 'chromium'                                                                                           
import plotly.graph_objects as go                                                                                            
go.Figure(go.Scatter(x=[1], y=[0])).show()

Experimenting with string matching seems to be the best solution(as was discussed above).
I could come up with this code for the same

self.using = using
    # Checks if self.using is not None and that it isn't available in the list returned by webbrowser._browsers.keys()
    if self.using and self.using not in webbrowser._browsers.keys():
       # Performs substring matching to fetch the browser closest to the provided name
       self.using = [browser for browser in webbrowser._browsers.keys() if self.using in browser][0]

let me know your views on the same.
Thank you

@jonmmease
Copy link
Contributor

jonmmease commented Jan 12, 2021

I think you've got the right idea. My intuition here would be to allow the using argument to open_html_in_browser to be a tuple of strings.

def open_html_in_browser(html, using=None, new=0, autoraise=True):

Like I mentioned in #2348 (comment), then open_html_in_browser could scan through webbrowser._browser.keys and use the first entry that matches the using argument (Either an exact match if a string, or any entry in the tuple).

For import time, we want to make sure that none of this logic happens on import. So it shouldn't happen in BrowserRenderer the constructor.

@c-chaitanya
Copy link
Contributor

c-chaitanya commented Jan 13, 2021

Thank you for the suggestion @jonmmease. I have made the changes you have suggested in my local branch ( c-chaitanya@5ae493c ).

@c-chaitanya
Copy link
Contributor

c-chaitanya commented Jan 20, 2021

Hi @jonmmease, understanding other parts of the renderer code more clearly, I see that renderers are also invoked as follows chrome+colab+notebook+vscode, there is a method to also check if isinstance is a string such that they could be split on +.

If we have a look at the changes in these two files ( c-chaitanya@5ae493c ) we see that the parameters passed to using
in renderers["chrome"] = BrowserRenderer(config=config, using=("chrome", "google-chrome")) makes no difference even if it a string as follows renderers["chrome"] = BrowserRenderer(config=config, using="chrome"), it would internally perform string matching to fetch the closest matching browser. If using is a tuple it breaks integration with other renderer types.

@jonmmease
Copy link
Contributor

Hi @c-chaitanya. Your changes in that commit look fine to me, I don't quite follow what issue you're running into.

The chrome in "chrome+colab+notebook+vscode" refers to the name of the renderer (renderers["chrome"]) and doesn't have any relationship with the value passed to the using argument of BrowserRenderer. So I don't think there's any problem here, but let me know if you're running into a problem.

Also, feel free to go ahead and make a PR even if you're not sure it's finished yet. It'll be a little easier to talk through specific code questions that way. Thanks!

@c-chaitanya
Copy link
Contributor

Hi @jonmmease , I have given a pull request #3278 to fix this issue. The CircleCi fails for one test "Check formating with black". The thing was when I ran black on my local branch it gave me "903 files reformatted, 10053 files left unchanged". 903 was a big number so i did not add the reformatted files. Shoud I reformat and give a new pull request?

@c-chaitanya
Copy link
Contributor

c-chaitanya commented Jun 25, 2021

Hi @jonmmease @nicolaskruchten I reformatted using black and gave a pull request again. This time I notice CircleCI fails for test related to orca. Just to check if errors were due to my changes, I ran the pytests on the plotly.py master branch and I notice the same orca errors. Thus I deduced that the errors preexisted in the master branch and were not induced by these changes. Is there anything I can do to fix these errors?.

nicolaskruchten added a commit that referenced this issue Jul 21, 2021
fix for chromium renderer on linux systems (issue #2348)
@nicolaskruchten
Copy link
Contributor

Closed in #3278 and improved in #3310

@nicolaskruchten
Copy link
Contributor

Thanks @c-chaitanya 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken
Projects
None yet
Development

No branches or pull requests

4 participants