-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Update matplotlibrc.template #10531
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
Update matplotlibrc.template #10531
Conversation
Update matplotlib.template with all currently supported rcParams
Some clarification: RcParams
TestsI added two tests:
|
What does |
pytest has a context manager to capture warnings, I suggest using that and then asserting that there are no warnings. The coverage report says that the coverage on the test suite has gone down, are you sure the new tests are actually running (pytest is always a bit mysterious to me)? |
|
re: 2) - yhea, you would think so, but pytest has all sorts of mechanisms
for skipping tests. Coverage means the percent of the codebase (in lines of
code) that is exercised by the tests.
…On Mon, Feb 19, 2018 at 10:31 AM, Importance of Being Ernest < ***@***.***> wrote:
1.
Ok, I changed it to raise an error if any warning happens.
2.
No, I'm not sure about anything here. ;-)
What is "coverage"? How would one find out the test is run? I was
under the impression that any function starting with test_ would be
run?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#10531 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-J0GDGvHb6IzrO4raYVQ4P-BGmVmks5tWZPsgaJpZM4SKfaI>
.
|
I tend to fall back to putting |
My test only covers 0.01% of the all the code, simply because it is only written to test one specific thing. I think I'm misunderstanding something fundamental here. Where exactly do you want me to put So if there is anything you want me to do for this to successfully "cover" something or to be run at all, just tell me what it is. Feel free to take your time and do so whenever you're less busy since rushed one-sentence answers do not usually help much in such cases. |
you can confirm that your test is being run up on Travis by putting an
`assert False` in that new test. The Travis report should then show that
the test failed, thereby confirming that it is at least running it.
…On Mon, Feb 19, 2018 at 12:59 PM, Importance of Being Ernest < ***@***.***> wrote:
My test only covers 0.01% of the all the code, simply because it is only
written to test one specific thing. I think I'm misunderstanding something
fundamental here.
Where exactly do you want me to put assert False and for what reason? I
have made sure the test does what I expect it to do locally on my computer,
is that what you mean?
So if there is anything you want me to do for this to successfully "cover"
something or to be run at all, just tell me what it is. Feel free to take
your time and do so whenever you're less busy since rushed one-sentence
answers do not usually help much in such cases.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#10531 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-J6P5rh7hVSzmA-7_WB7sJ3EwQsLks5tWbaPgaJpZM4SKfaI>
.
|
newlines.append(newline) | ||
#print(os.path.dirname(__file__)) | ||
fname = os.path.join(os.path.dirname(__file__), | ||
'testrcvalid.temp') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pytest has a tempfile fixture that would be better to use for this purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly is the problem with that? Do I not have permission to create a file? Using a fixture to create a temporary directory and create a file inside seems rather overkill.
I am still not exactly sure how the test coverage has gone down. Is the size of the codebase including the test suite itself? |
The tests with |
Actually, it is quite likely that you won't have permission to write in
that directory. And no, it isn't overkill. It is actually less code to use.
We use it elsewhere. It is very easy to use:
https://docs.pytest.org/en/latest/tmpdir.html
…On Mon, Feb 19, 2018 at 3:57 PM, Importance of Being Ernest < ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In lib/matplotlib/tests/test_rcparams.py
<#10531 (comment)>
:
> + with open(path_to_rc, "r") as f:
+ rclines = f.readlines()
+ newlines = []
+ for line in rclines:
+ if line[0] == "#":
+ newline = line[1:]
+ else:
+ newline = line
+ if "$TEMPLATE_BACKEND" in newline:
+ newline = "backend : Agg"
+ if "datapath" in newline:
+ newline = ""
+ newlines.append(newline)
+ #print(os.path.dirname(__file__))
+ fname = os.path.join(os.path.dirname(__file__),
+ 'testrcvalid.temp')
What exactly is the problem with that? Do I not have permission to create
a file? Using a fixture to create a temporary directory and create a file
inside seems rather overkill.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#10531 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-KjkX3FwHUyKCVmK10eswS54uwlpks5tWeAngaJpZM4SKfaI>
.
|
# This tests if the matplotlibrc.template file would result in a valid | ||
# rc file if all lines are uncommented. | ||
path_to_rc = mpl.matplotlib_fname() | ||
path_to_rc = "matplotlibrc.txt" #mpl.matplotlib_fname() # |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this left in here by accident?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please squash-merge this.
Should probably also clean out the debugging prints and other commented out things. But I am, in principle, +1 on this once we confirm that everything is working. |
The commented statements that are still left in the code are there by pupose: I was thinking that if someone has this test failing for his commit they would immediately direct him to the source of the problem. |
if not found: | ||
missing.update({k:v}) | ||
if missing: | ||
raise ValueError("The following params are missing " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert not missing
would be more inline with pytest conventions
assert missing == {}
would also work.
Both should provide a reasonably informative error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I'm missing
something, but assert not missing
would show exactly as assert not missing
in the Error, without any details, right? Here I would want to show all missing parameters in the error. That should make it relatively easy to just copy and paste them to the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pytest is pretty good about reporting. Consider the following:
$ cat test_simple.py
import pytest
@pytest.fixture
def missing():
return {'a': 1, 'b': 2}
def test_one(missing):
assert not missing
def test_two(missing):
assert missing == {}
So then running it:
============================== test session starts ===============================
platform linux -- Python 3.6.4, pytest-3.4.0, py-1.5.2, pluggy-0.6.0
Matplotlib: 2.1.2
Freetype: 2.8.1
rootdir: /mnt/c/Users/phobson/sources/scratch/simple_test, inifile:
plugins: pep8-1.0.6, mpl-0.9, cov-2.5.1
collected 2 items
test_simple.py FF [100%]
==================================== FAILURES ====================================
____________________________________ test_one ____________________________________
missing = {'a': 1, 'b': 2}
def test_one(missing):
> assert not missing
E AssertionError: assert not {'a': 1, 'b': 2}
test_simple.py:9: AssertionError
____________________________________ test_two ____________________________________
missing = {'a': 1, 'b': 2}
def test_two(missing):
> assert missing == {}
E AssertionError: assert {'a': 1, 'b': 2} == {}
E Left contains more items:
E {'a': 1, 'b': 2}
E Use -v to get the full diff
test_simple.py:13: AssertionError
============================ 2 failed in 0.28 seconds ============================
It's pretty clear what's in the dictionary that should be empty
Yeah, I kinda like the way it is now. It makes it extremely clear what the
failure is. pytest's introspection display for errors is useful for general
debugging, but specific messages are still quite valuable.
…On Mon, Feb 19, 2018 at 8:33 PM, Importance of Being Ernest < ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In lib/matplotlib/tests/test_rcparams.py
<#10531 (comment)>
:
> + missing = {}
+ for k,v in mpl.defaultParams.items():
+ if k[0] == "_":
+ continue
+ if k in deprecated:
+ continue
+ if "verbose" in k:
+ continue
+ found = False
+ for line in rclines:
+ if k in line:
+ found = True
+ if not found:
+ missing.update({k:v})
+ if missing:
+ raise ValueError("The following params are missing " +
Maybe I'm missing something, but assert not missing would show exactly as assert
not missing in the Error, without any details, right? Here I would want
to show all missing parameters in the error. That should make it relatively
easy to just copy and paste them to the file.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#10531 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-AkRF4K2jSLnWKYgdol89M297hMvks5tWiEEgaJpZM4SKfaI>
.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that if you go through the template and remove all the quote marks, it will be OK.
matplotlibrc.template
Outdated
#animation.convert_path: 'convert' ## Path to ImageMagick's convert binary. | ||
## On Windows use the full path since convert | ||
## is also the name of a system tool. | ||
#animation.convert_args: '' ## Additional arguments to pass to convert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and in all cases above, there should be no quotes for strings. A blank field is an empty string.
matplotlibrc.template
Outdated
#keymap.zoom : o ## zoom mnemonic | ||
#keymap.save : s ## saving current figure | ||
#keymap.quit : ctrl+w, cmd+w ## close the current figure | ||
#keymap.quit_all : 'W', 'cmd+W', 'Q' ## close all figures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no quotes.
probably should clarify that the string literals in the cycler do get
quoted as normal.
…On Mon, Feb 19, 2018 at 9:39 PM, Eric Firing ***@***.***> wrote:
***@***.**** requested changes on this pull request.
I think that if you go through the template and remove all the quote
marks, it will be OK.
------------------------------
In matplotlibrc.template
<#10531 (comment)>
:
> +#animation.writer : ffmpeg ## MovieWriter 'backend' to use
+#animation.codec : h264 ## Codec to use for writing movie
+#animation.bitrate: -1 ## Controls size/quality tradeoff for movie.
+ ## -1 implies let utility auto-determine
+#animation.frame_format: png ## Controls frame format used by temp files
+#animation.html_args: '' ## Additional arguments to pass to html writer
+#animation.ffmpeg_path: 'ffmpeg' ## Path to ffmpeg binary. Without full path
+ ## $PATH is searched
+#animation.ffmpeg_args: '' ## Additional arguments to pass to ffmpeg
+#animation.avconv_path: 'avconv' ## Path to avconv binary. Without full path
+ ## $PATH is searched
+#animation.avconv_args: '' ## Additional arguments to pass to avconv
+#animation.convert_path: 'convert' ## Path to ImageMagick's convert binary.
+ ## On Windows use the full path since convert
+ ## is also the name of a system tool.
+#animation.convert_args: '' ## Additional arguments to pass to convert
Here and in all cases above, there should be no quotes for strings. A
blank field is an empty string.
------------------------------
In matplotlibrc.template
<#10531 (comment)>
:
> +
+### docstring params
+##docstring.hardcopy = False ## set this when you want to generate hardcopy docstring
+
+## Event keys to interact with figures/plots via keyboard.
+## Customize these settings according to your needs.
+## Leave the field(s) empty if you don't need a key-map. (i.e., fullscreen : '')
+#keymap.fullscreen : f, ctrl+f ## toggling
+#keymap.home : h, r, home ## home or reset mnemonic
+#keymap.back : left, c, backspace ## forward / backward keys to enable
+#keymap.forward : right, v ## left handed quick navigation
+#keymap.pan : p ## pan mnemonic
+#keymap.zoom : o ## zoom mnemonic
+#keymap.save : s ## saving current figure
+#keymap.quit : ctrl+w, cmd+w ## close the current figure
+#keymap.quit_all : 'W', 'cmd+W', 'Q' ## close all figures
There should be no quotes.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#10531 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-O0MBWBoaWqOnZWqMBx6kq6g5lPjks5tWjBHgaJpZM4SKfaI>
.
|
That needs a big fat comment in the matplotlibrc.template, then, right before the prop_cycle line, pointing out that it is exceptional, and is the only place in the file where quotes are allowed, and that they are indeed required there. |
Thanks @efiring for coming back to the issue of string escapes. I brought his up here, but did not get any feedback, so I assumed this to be ok, as seen in #10421. So, to make this accurate now: I removed all
This brought up a number of parameters which did not match. I corrected those which needed to be updated or were obvious to fix. What remains is the following. Here the first item is the one from the defaultParams, the second is the one as read in from the template file. I'm trying to comment on each of them and would be happy about any feedback or action to take.
If those cases were not showing up, one could ideally add the comparisson above to the tests, making sure not only the keys are correct and the file is correctly read in, but also that the values are up to date and correct. |
So, off the bat, we have some aliases that essentially resolves to None. So
"standard" for savefig.bbox should be the same thing as the python None.
The svg.hashsalt shouldn't be set to 'None'. It will need an alias, or
maybe be set to an empty string, perhaps?
I think the way to do an empty list is with a comma? It might be that you
need the quotes for empty strings. I can't remember.
Backend names are case-insensitive. And I personally wouldn't worry about
the tuple/list difference.
…On Tue, Feb 20, 2018 at 11:46 AM, Importance of Being Ernest < ***@***.***> wrote:
Thanks @efiring <https://github.com/efiring> for coming back to the issue
of string escapes. I brought his up here
<#10406 (comment)>,
but did not get any feedback, so I assumed this to be ok, as seen in
#10421 <#10421>.
So, to make this accurate now: I removed *all* '' in the template, except
for the cycler. I then ran a comparisson between the loaded rcParams and
the defaultParams.
rc = mpl.rc_params_from_file(fname,
fail_on_error=True,
use_default_template=False)
d1 = dict(rc.items())
d2 = dict(mpl.defaultParams.items())
for k,v in d1.items():
if d2[k][0] != v:
print k
print " ", d2[k][0], v
print " ", type(d2[k][0]), type(v)
This brought up a number of parameters which did not match. I corrected
those which needed to be updated or were obvious to fix. What remains is
the following. Here the first item is the one from the defaultParams, the
second is the one as read in from the template file. I'm trying to comment
on each of them and would be happy about any feedback or action to take.
-
keymap.fullscreen
('f', 'ctrl+f') ['f', 'ctrl+f']
<type 'tuple'> <type 'list'>
All other keymaps seem to stored as list, except this one.
-
pgf.preamble
[''] []
<type 'list'> <type 'list'>
A list with an empty string cannot be created from within the rc file
syntax, or can it? If so how?
-
path.effects
[] []
<type 'list'> <type 'unicode'>
How to create an empty list instead of the string '[]'?
-
savefig.bbox
standard None
<type 'str'> <type 'NoneType'>
Despite the file saying savefig.bbox : standard the parsing yields
this as None.
-
axes.prop_cycle This shows up, simply because two different instances
of cycler.Cycler are created.
-
backend
Agg agg
<type 'str'> <type 'str'>
Even if the file says backend : Agg this is parsed as lower case,
while the defaultParams have the upper case string stored.
-
text.latex.preamble
[''] []
<type 'list'> <type 'list'>
A list with an empty string cannot be created from within the rc file
syntax, or can it? Same as pgf.preamble.
-
path.simplify_threshold
0.111111111111 0.111111111111
<type 'float'> <type 'float'>
I supposed the stored value is 1./9
-
svg.hashsalt
None None
<type 'NoneType'> <type 'unicode'>
String svg.hashsalt : None is not parsed to None, but "None".
If those cases were not showing up, one could ideally add the comparisson
above to the tests, making sure not only the keys are correct and the file
is correctly read in, but also that the values are up to date and correct.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#10531 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-Orp9dESnVv1z6tOjvCevr5wBIK2ks5tWvbLgaJpZM4SKfaI>
.
|
Partial response: I suspect that an empty list and a list with a single empty string are identical in practice--as they are subsequently used--but this can be checked. If not, it might be that some slight tweaks to the validation functions in rcsetup.py would be in order to fix that, but I would be very cautious about this. |
#patch.edgecolor : black # if forced, or patch is not filled | ||
#patch.force_edgecolor : False # True to always use edgecolor | ||
#patch.antialiased : True # render patches in antialiased (no jaggies) | ||
#patch.edgecolor : k ## if forced, or patch is not filled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to exchange the long color names if favor of the short ones? IMO the long names are easier to understand, especially for someone not familiar with the matplotlib color system.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to exactly the value used in defaultParams, which is "k"
or "w"
instead of "black"
or "white"
, this makes it now easy to identify which params have non-matching values compared to the default as stated above. Should I change it back?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the benefit of using the exact same values. From a user point of view, I would suggest to change the defaultParams to the long form. However I'm not an expert on matplotlib.rcParams and don't know if that has any negative side effects. This should be judged by someone with more experience in this field. I'll open an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with open(path_to_rc, "r") as f: | ||
rclines = f.readlines() | ||
missing = {} | ||
for k,v in mpl.defaultParams.items(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better readability, I'd slightly prefer for key, val
or for name, val
because the for loop is quite long.
rclines = f.readlines() | ||
missing = {} | ||
for k,v in mpl.defaultParams.items(): | ||
if k[0] == "_": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe join:
if k.startswith(' ') or k in deprecated or 'verbose' in k:
continue
continue | ||
if "verbose" in k: | ||
continue | ||
found = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This (and following lines) can be written more compact:
if not any(k in line for line in lines):
missing[k] = v
Note, that k in line
is a bit imprecise because it would also match values or comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. I think any better solution here would eventually lead to writing one single test and match the parsed file agains the defaultParams. Depends on if people think this should be done or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a big fan of "incrementally better", so I don't want to enforce a full parsing test. Your partial test is already a big improvement. Maybe you could add a short comment to clarify that this test is not expected to be 100%. And of course, use the compact form 😃.
Backport PR #10531 on branch v2.2.x
To fix #10494:
PR Checklist