using frombuffer instead of fromstring - #6785
Conversation
|
Hi there @bsipocz 👋 - thanks for the pull request! I'm just a friendly 🤖 that checks for issues related to the changelog and making sure that this pull request is milestoned and labelled correctly. This is mainly intended for the maintainers, so if you are not a maintainer you can ignore this, and a maintainer will let you know if any action is required on your part 😃. Everything looks good from my point of view! 👍 If there are any issues with this message, please report them here |
| # their underlying file object, instead of the decompressed bytes | ||
| read_size = np.dtype(dtype).itemsize * count | ||
| s = infile.read(read_size) | ||
| return np.fromstring(s, dtype=dtype, count=count, sep=sep) |
There was a problem hiding this comment.
This may be wrong: is sep ever given as a real string? Certainly, fromfile can handle both an empty string (binary) and a given separation string (text). Unless we are sure sep is always '', we probably are stuck with
if sep == '':
return np.frombuffer(...)
else:
return np.fromstring(..., sep=sep)
There was a problem hiding this comment.
OK, I've added this back (GH just doesn't recognize it).
There was a problem hiding this comment.
sep is always used with an empty string so I think it's safe to simplify this, see #6813
| nblanks = input.count(' ') | ||
| nmax = max(nblanks, len(input) // strlen + 1) | ||
| arr = np.fromstring((input + ' '), dtype=(bytes, 1)) | ||
| arr = np.frombuffer((input + ' ').encode('utf8'), dtype=(bytes, 1)) |
There was a problem hiding this comment.
This is quite ugly; really should rewrite the below without using an array. But that's beyond the scope of this PR...
There was a problem hiding this comment.
I was reading this while looking at other uses of np.frombuffer, and actually I wonder why this function exists instead of using textwrap.wrap... maybe some weird edge case that I don't see, but on a simple string (as tested with test_long_string_value it gives the same result).
pllim
left a comment
There was a problem hiding this comment.
Cron job didn't crash, so 👍 for io.votable changes.
|
I'll have a look at the PR wrt to |
| # Convert the header to a string. | ||
| s = str(self._header) | ||
| # Convert the header to bytes. | ||
| s = self._header.tostring().encode('utf8') |
There was a problem hiding this comment.
I thinks it's impossible to pass in non-ascii (or non-latin-1) characters in a Header. However the binary representation of these should be the same as for utf-8 so there's (probably) no problem.
| Split a long string into parts where each part is no longer | ||
| than `strlen` and no word is cut into two pieces. But if | ||
| there is one single word which is longer than `strlen`, then | ||
| than ``strlen`` and no word is cut into two pieces. But if |
|
We have 3 favorable reviews, so merging. Thanks! |
Following astropy#6785, `sep` is always an empty string so no need to keep the `np.fromstring` case.
using frombuffer instead of fromstring
Fix astropy#6862. astropy#6785 replaced uses of np.fromstring with np.frombuffer but the latter returns a read-only view of the binary buffer. So copying the array is needed to get a writeable array (and np.fromstring was doing the copy internally).
| def binparse(self, read): | ||
| result = np.fromstring(read(self._memsize), | ||
| result = np.frombuffer(read(self._memsize), | ||
| dtype=self._bigendian_format)[0] |
There was a problem hiding this comment.
The two uses of np.frombuffer here should be checked to see if it's safe if result a read-only array, (or if something is untested). poke @pllim 😉
There was a problem hiding this comment.
Consider me poked. I'll investigate and report back. (Also, whoever wants to be a maintainer for votable, feel free to volunteer...) 😉
|
@saimn , from what I can understand, it does not seem to be a problem for
Example 1 -- Using >>> from astropy.table import Table
>>> tab = Table.read('regression.xml', table_id=0)
>>> tab
<Table masked=True length=5>
string_test string_test_2 ... bitarray2 [16]
object bytes10 ... bool
----------------- ------------- ... --------------
String & test Fixed stri ... True .. False
String & test 0123456789 ... -- .. --
XXXX XXXX ... -- .. --
... -- .. --
... -- .. --
>>> tab['string_test'][0] = 'stringcheese'
>>> tab
<Table masked=True length=5>
string_test string_test_2 ... bitarray2 [16]
object bytes10 ... bool
----------------- ------------- ... --------------
stringcheese Fixed stri ... True .. False
String & test 0123456789 ... -- .. --
XXXX XXXX ... -- .. --
... -- .. --
... -- .. --
>>> tab.write('mystringcheese.xml', format='votable') # Gives me the modified tableExample 2 -- Using >>> from astropy.io.votable.table import parse
>>> tt = parse('regression.xml')
>>> tab = tt.get_first_table()
>>> tab
<Table masked=True length=5>
string_test string_test_2 ... bitarray2 [16]
object bytes10 ... bool
----------------- ------------- ... --------------
String & test Fixed stri ... True .. False
String & test 0123456789 ... -- .. --
XXXX XXXX ... -- .. --
... -- .. --
... -- .. --
>>> tab.array[0][0] = b'stringcheese'
>>> tab
<Table masked=True length=5>
string_test string_test_2 ... bitarray2 [16]
object bytes10 ... bool
----------------- ------------- ... --------------
stringcheese Fixed stri ... True .. False
String & test 0123456789 ... -- .. --
XXXX XXXX ... -- .. --
... -- .. --
... -- .. --Is this convincing enough? If not, please suggest other ways I could test this. Thanks! |
|
|
This is to fix #6784 as a follow-up for recent numpy deprecations (numpy/numpy#9487).
I'm not sure whether I choose the right encoding for the fits modifications, but requesting a review from the maintainers to advise otherwise.
If possible, this also needs to be backported.