Repository navigation
Fix handling of bounded variable-length char arrays in BINARY2 format - #18105
Conversation
|
Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.
|
There was a problem hiding this comment.
Welcome to Astropy 👋 and congratulations on your first pull request! 🎉
A project member will respond to you as soon as possible; in the meantime, please have a look over the Checklist for Contributed Code and make sure you've addressed as many of the questions there as possible.
If you feel that this pull request has not been responded to in a timely manner, please send a message directly to the development mailing list. If the issue is urgent or sensitive in nature (e.g., a security vulnerability) please send an e-mail directly to the private e-mail [email protected].
|
Looks like the test data files I added are not properly being resolved in the GH workflow. I've set this PR as a draft while I sort out what went wrong. Update: Was missing a test data file from the commit, that has now been added |
Co-authored-by: P. L. Lim <[email protected]>
1916022 to
04ce208
Compare
|
You can ignore the "dev version" allowed failure job. I restarted RTD. |
ManonMarchand
left a comment
There was a problem hiding this comment.
Thanks for the PR. I checked in the branch, and it works.
My only comment is that the tests could have an unicodeChar field instead of one of the char ones.
Thanks for the comment and for checking the branch @ManonMarchand .I've added a couple more unit tests for checking UnicodeChars & for validating handling of bounds. |
55b9690 to
9f90029
Compare
|
Looks good to me, thanks! |
|
Alas this missed v7.1. Another approval would be nice. Thanks, all. |
bsipocz
left a comment
There was a problem hiding this comment.
I only have minor comments, take or leave them as you wish.
| if self.arraysize != "*" and len(value) > self.arraysize: | ||
| vo_warn(W46, ("char", self.arraysize), None, None) | ||
| value = value[: self.arraysize] |
There was a problem hiding this comment.
is this a reasonable behaviour when len(value) > self.arraysize, should this maybe raise an exception rather than just a warning?
There was a problem hiding this comment.
That's an interesting point, are you suggesting we raise an exception in the output methods or the parse methods as well? I've gone with raising warning to keep consistent with the default Char parse method and generally in favour of being more forgiving for users, but I'm happy to also raise an exception if you think this is more appropriate here. If so do you want me to do the same for the parsing method?
There was a problem hiding this comment.
Yes, but neither the Char parser no here in e.g. L385 has any value loss, while in this method you chop the return at arraysize.
Maybe keep it a warning but don't chop?
There was a problem hiding this comment.
Thinking about this I think for consistency it may be best to truncate in the parser and the output method.
Providing a warning without truncating has potential to cause unexpected compatibility issues later on for users, for example if a user pre-allocates fixed buffers based on declared length. Also it feels wrong to generate a Table that will not conform with the schema.
If we didn't want to truncate, I'd also consider increasing the arraysize along with a warning, but that may also lead to unexpected issues.
Any thoughts on truncating both at parse and output? Otherwise I can also just not chop, the potential for the error occurring through some round-trip where on the other end they assume data that conforms with the bound is probably rare.
There was a problem hiding this comment.
I would lean towards not truncating in here, so it will be consistent (even if it's wrong) with the rest of the methods, and thus can be easily be backported. Then this PR can go in now without further discussion.
But then open a bug report issue asking for input/discussion, and possibly changing the behaviour, either by truncating or changing the schema. The former feels more correct to me, but I would like to see the input from others, too. Then potentially a fix/refactor; that is consistent with the Char methods, too, can go in the next feature release as a breaking change.
There was a problem hiding this comment.
Ok sounds good, I've removed the truncation for the output method. I've also added a few more test methods since I noticed codecov was complaining about the coverage. Let me know if you think anything else needs to be changed.
There was a problem hiding this comment.
Thanks!
Not sure why codecov is still complaining, I would suggest to ignore it for now and go ahead with the merge once CI is all green.
Would you mind opening an issue outlining the concerns you mentioned in #18105 (comment) ?
There was a problem hiding this comment.
By the way I noticed the CI failed during the link check here:
(api/astropy.io.votable.validator.make_validation_report: line 23) broken http://www.starlink.ac.uk/stilts - HTTPConnectionPool(host='www.starlink.ac.uk', port=80): Max retries exceeded with url: /stilts (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x7f33be2d7350>, 'Connection to www.starlink.ac.uk timed out. (connect timeout=180)'))
Is this a known issue? I noticed that it is using an older URL for the starlink docs:
Line 612 in 16a94b4
This should be the new URL I think:
https://www.star.bristol.ac.uk/mbt/stilts/
There was a problem hiding this comment.
Unrelated, so ignore it or open a separate PR.
(actually I'm not sure why we require the extra CIs for this PR, but at this point I'm just waiting for all the jobs on the exotic arc to finish)
| field.arraysize = field.arraysize.removesuffix("*") | ||
| is_variable = field.arraysize.endswith("*") | ||
|
|
||
| # Get numeric part without modifying field.arraysize | ||
| numeric_part = field.arraysize.removesuffix("*") |
There was a problem hiding this comment.
We could uniformize the comments here with between L326:L330 as currently they are complimenter for the same code content.
There was a problem hiding this comment.
Yes good point, should be done in new commit
| if self.arraysize != "*" and len(value) > self.arraysize: | ||
| vo_warn(W46, ("unicodeChar", self.arraysize), None, None) | ||
| value = value[: self.arraysize] | ||
| encoded = value.encode("utf_16_be") |
There was a problem hiding this comment.
remove the same line from L497 and deindent this one
…e in b2 output method
…ar arrays in BINARY2 format
|
|
||
| if self.arraysize != "*" and len(value) > self.arraysize: | ||
| vo_warn(W46, ("unicodeChar", self.arraysize), None, None) | ||
| value = value[: self.arraysize] |
There was a problem hiding this comment.
Ahh, review mistake, I didn't spot that this line still truncate and is now inconsistent with the same method in Char
There was a problem hiding this comment.
Is a follow-up PR planned? Thanks!
There was a problem hiding this comment.
I think we should do one, whatever the output of the conversation in #18167 is, we don't want a different behavior between the two field types.
There was a problem hiding this comment.
Oh I didn't notice that inconsistency, my bad!
…105-on-v7.1.x Backport PR #18105 on branch v7.1.x (Fix handling of bounded variable-length char arrays in BINARY2 format)
|
Alas, I think this broke astroquery, see #18179 |
Original PR #18105 by stvoutsin Original: astropy/astropy#18105
…rrays in BINARY2 format Merged from original PR #18105 Original: astropy/astropy#18105
Original PR #18105 by stvoutsin Original: astropy/astropy#18105
…rrays in BINARY2 format Merged from original PR #18105 Original: astropy/astropy#18105
Description
This pull request is to address issue #18099 with VOTable BINARY2 serialization where fields with bounded variable length char arrays (e.g., arraysize="128*") were being handled as fixed length.
Specifically, the parser was removing the asterisk from the arraysize attribute and treating these fields as fixed-length arrays, which caused them to be incorrectly encoded/decoded in BINARY2 format.
The issue resulted in either empty tables or exceptions when parsing VOTable results containing these field types.
Changes
__init__method to detect bounded variable length arrays (e.g. arraysize="128*") and use the appropriate var parsing methodsTechnical Details
The issue was caused by this code in the Char converter's
__init__method:field.arraysize = field.arraysize.removesuffix("*")This was removing the asterisk and therefore losing the information that this should be handled as a variable length field with an upper bound, which later in the
__init__method lead to the fixed length binary parsing methods being used. The changes should address this by recognizing that the field is a variable length field with an upper bound and assigning the converted the appropriate binary parsing methods. The changes also address the round-tripping of this information between astropy/votable tables.Testing
Added following new tests:
test_binary2_single_bounded_char_array: Test that variable length char arrays with a max length arraysize="128*") are read correctly in BINARY2 format.test_binary2_bounded_variable_length_char: Tests round-trip serialization of bounded variable length char arrays across all formatstest_binary2_bounded_variable_length_char_edge_cases: Tests edge casestest_binary2_char_fields_vizier_data: Test parsing a VOTable from a Vizier query which includes bounded variable-length char arrays (e.g., arraysize="7*"). Related issue: votable binary parsing appears to fail on null columns #8737This fix is particularly important for interoperability with IVOA services that commonly use this field type in their response formats.
Related Issues
Fixes #18099
Fixes #8737
Notes:
Let me know if I've misinterpreted the issue or if there are better ways to address it and I'd be happy to make any changes accordingly.