-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add support for png_text metadata, allow to customize metadata for other backends. #7349
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
Conversation
Instead of replacing the entire metadata, I'd have the argument update the existing dictionary that was originally generated in the code. That way, the user doesn't need to figure out the default strings (version info and such), but can still provide other metadata or override it if really wanted. |
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 update the existing meta-data rather than completely replacing it with the user supplied metadata.
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.
A few small issues.
@@ -552,8 +552,16 @@ def print_png(self, filename_or_obj, *args, **kwargs): | |||
else: | |||
close = False | |||
|
|||
version_str = 'matplotlib version ' + __version__ + \ | |||
', http://matplotlib.org/' | |||
metadata = {six.b('Software'): six.b(version_str)} |
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 would be confusing for users, as they would probably provide regular strings (as that's what all the other ones accept.) If bytestrings are really required here, it should do the encoding after obtaining the user's metadata.
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.
You also don't need six.b
because we don't need to support Python 2.5.
@@ -469,10 +469,13 @@ def __init__(self, filename): | |||
|
|||
revision = '' | |||
self.infoDict = { | |||
'Creator': 'matplotlib %s, http://matplotlib.org' % __version__, | |||
'Creator': 'matplotlib ' + __version__ + | |||
', http://matplotlib.org', |
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.
Unnecessary change, looks like.
#ifdef PNG_TEXT_SUPPORTED | ||
// Save the metadata | ||
if (metadata != NULL) | ||
{ |
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.
Brace is on the wrong line (comparatively speaking.)
// Save the metadata | ||
if (metadata != NULL) | ||
{ | ||
meta_size = PyDict_Size(metadata); |
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.
Should be 4-space indent.
text[meta_pos].key = PyBytes_AsString(meta_key); | ||
text[meta_pos].text = PyBytes_AsString(meta_val); | ||
if (PyUnicode_Check(meta_key)) { | ||
PyObject *temp_key = PyUnicode_AsEncodedString(meta_key, "ASCII", "strict"); |
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 believe it's actually (some small subset of) latin1/iso-8859-1.
@@ -2423,8 +2425,11 @@ def __init__(self, filename, keep_empty=True): | |||
keep_empty: bool, optional | |||
If set to False, then empty pdf files will be deleted automatically | |||
when closed. | |||
metadata: dictionary, optional | |||
Information dictionary object (see PDF reference section 10.2.1 |
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 don't find this documentation particularly useful. You could you add at least some examples of metadata ?
Also, numpydoc format requires a space before the column : metadata : dictionary, …
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.
The original parameters all don't have a space before the colon, and rendered fine, so I don't think that's a requirement.
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.
It is. The current documentation is not rendered properly.
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.
Oh yes, I missed that the bolding is wrong.
98d79ed
to
ef48e6a
Compare
@@ -1073,13 +1073,19 @@ def write(self, *kl, **kwargs): | |||
self.figure.set_facecolor(origfacecolor) | |||
self.figure.set_edgecolor(origedgecolor) | |||
|
|||
# check for custom metadata | |||
metadata = kwargs.pop("metadata", None) |
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.
Mild preference for adding metadata=None
to the signature.
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 pop
needs to be removed?
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.
err, sorry, there were two of these and I grew confused reading the diffs.
Can you add |
Sorry in advance if I am asking obvious questions, just trying to understand the libpng API. From http://www.libpng.org/pub/png/libpng-manual.txt
I can not quite sort out the difference between This is valuable work thank you again for taking this on! |
AFAICT, it's totally ignored. There's an explicit
I'm not sure how to interpret the standard either. In libpng there's explicit:
in the loop over
It's checked internally. If the key exceeds 79 it is truncated and warning is issued:
|
It makes sense that it takes care of the length it's self (so we can not lie to it, that seems like an obvious attack vector). I am a tad concerned about the Might be worth turning that warning into a python warning? I am 👍 with punting on that for this PR. |
2451840
to
170e9a3
Compare
ping, is there anything else left to do before this PR is merged? |
This looks like a good contribution, but it would be nice to have @mdboom look at the agg part and @jkseppan look at the pdf and pd parts. As @tacaswell noted, it will need a whats-new entry. I have a question about the API and behavior: it looks like the present scheme, in which metadata comes in as a dictionary, has the undesirable side effect of making the order in which the metadata appear in the file non-deterministic (and at the very least, not under the control of the user). This could be avoided by using an OrderedDict, or by using a sequence of (key, value) tuples. Correct? |
Sorry, it wasn't clear who's supposed to add it. I'll work on it.
In principle you are right. However, since there are no methods to read text value by its index why would it matter? I would say that random order is desirable side effect. It will prevent people from writing software that makes ill assumptions about metadata. |
On the bright side, with python 3.6 dictionary order is deterministic again! |
I know zilch about metadata in image files, but I am guessing that utilities dump the metadata in the order in which it is found, e.g. for display to the screen, in which case it would be nice to control the order--wouldn't it? Regarding deterministic vs non-deterministic, see #6317 for a discussion. |
170e9a3
to
716a7b7
Compare
Current coverage is 62.07% (diff: 81.81%)@@ master #7349 diff @@
==========================================
Files 174 174
Lines 56007 56021 +14
Methods 0 0
Messages 0 0
Branches 0 0
==========================================
+ Hits 34765 34773 +8
- Misses 21242 21248 +6
Partials 0 0
|
'power cycled' to restart against current master |
Hi @Xarthisius |
9840805
to
8897f0f
Compare
@Xarthisius Thanks! Sorry this took so long to get merged. |
PNG Specification allows for custom
png_text
structures as an image attributes. The keywords that are given in the PNG specs are:This PR allows to pass a dictionary with a metadata that can be used to fill those key/value pairs in png writer. Structure of the data and its type is not validated.
Additionally this PR allows to customize "software/creator" values in other backends such as PDF and PS.