8000 get_backend() backward compatibility · Issue #11852 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

get_backend() backward compatibility #11852

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
ngoldbaum opened this issue Aug 13, 2018 · 8 comments
Closed

get_backend() backward compatibility #11852

ngoldbaum opened this issue Aug 13, 2018 · 8 comments
Labels
Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
Milestone

Comments

@ngoldbaum
Copy link
Contributor

Under matplotlib 3.0.0rc1, the return value of matplotlib.get_backend() is a sentinel object:

In [2]: matplotlib.get_backend()
Out[2]: <object at 0x111292d50>

In [3]: backend = matplotlib.get_backend()

In [4]: backend.lower()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-f3c7164fcd07> in <module>()
----> 1 backend.lower()

AttributeError: 'object' object has no attribute 'lower'

Under matplotlib 2.2.3 I get:

In [1]: import matplotlib

In [2]: matplotlib.get_backend()
Out[2]: 'MacOSX'

In [3]: backend = matplotlib.get_backend()

In [4]: backend.lower()
Out[4]: 'macosx'

For backward compatibility purposes it would be really nice if matplotlib 3.0.0 could return an object that at least acted like a string. In particular right now I'd like it to have a lower() method. I'd also like it if it had a nice __repr__ or __str__ implementation instead of printing out as an opaque object of type object.

The former is for backward compatibility, as the change breaks some of the yt plotting code --- in particular here's a failure from the test suite:

======================================================================
ERROR: Failure: AttributeError ('object' object has no attribute 'lower')
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/nose/failure.py", line 39, in runTest
    raise self.exc_val.with_traceback(self.tb)
  File "/usr/local/lib/python3.7/site-packages/nose/loader.py", line 418, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/local/lib/python3.7/site-packages/nose/importer.py", line 47, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/local/lib/python3.7/site-packages/nose/importer.py", line 94, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/imp.py", line 235, in load_module
    return load_source(name, filename, file)
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/imp.py", line 172, in load_source
    module = _load(spec)
  File "<frozen importlib._bootstrap>", line 696, in _load
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/Users/goldbaum/Documents/yt-git-fixes/yt/visualization/tests/test_color_maps.py", line 23, in <module>
    class TestColorMaps(unittest.TestCase):
  File "/Users/goldbaum/Documents/yt-git-fixes/yt/visualization/tests/test_color_maps.py", line 34, in TestColorMaps
    @requires_backend('Agg')
  File "/Users/goldbaum/Documents/yt-git-fixes/yt/testing.py", line 1143, in requires_backend
    if backend.lower() == matplotlib.get_backend().lower():
AttributeError: 'object' object has no attribute 'lower'

This is code that's internal to yt's test suite, but I wouldn't be at all surprised if there's other code out there that assumes matplotlib.get_backend() returns a string. For example:

https://github.com/search?q=matplotlib+get_backend+lower&type=Code

@jklymak jklymak added this to the v3.0 milestone Aug 13, 2018
@jklymak jklymak added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Aug 13, 2018
@anntzer
Copy link
Contributor
anntzer commented Aug 13, 2018

The issue is #11600 (comment) and I think (quite strongly) that it makes sense for get_backend() to, well, perform backend resolution and return an actual backend.
Giving the sentinel object a .lower() method is only going to make things worse IMO.

@ngoldbaum
Copy link
Contributor Author

I don't really care too much what type get_backend returns. I'd kinda prefer it to return something stringlike just on the principle that it would be better if old code continued working, but I also acknowledge that you're doing a major version number increment so some level of breakage is to be expected.

@fredrik-1
Copy link
Contributor

I don't understand this. I am on v3.0.0rc1 on my git version but matplotlib.get_backend() returns a string for me and the docstring says that it should return the name.

@anntzer
Copy link
Contributor
anntzer commented Aug 14, 2018

That's likely because this should only happen if you don't have a backend set in your matplotlibrc.

@fredrik-1
Copy link
Contributor

That seems like a strange api to me. Why do it return an object when the backend is not set and not for example '' and a string when it is set? (that was the behavior that I got when I tested).

that it makes sense for get_backend() to, well, perform backend resolution and return an actual backend.

Why? The docstring for matplotlib.get_backend is "Return the name of the current backend."

@anntzer
Copy link
Contributor
anntzer commented Aug 14, 2018

As explained above, it's a bug (IMO) and should be fixed.

@tacaswell
Copy link
Member

The simplest fix may be to switch the sentinel to the string 'auto'? That way it can go in the .matplotlibrc and returns the expected type from get_backend()

I would prefer that if we keep the non-string sentinel that the backend resolution logic moves up to __init__ rather than adding another buried pyplot import.

@tacaswell
Copy link
Member

Closing this in favor of #11844 which is addressing a slightly larger set of issues to keep the discussion from getting too fragmented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
Projects
None yet
Development

No branches or pull requests

5 participants
0