python-twitter
python-twitter copied to clipboard
PostUpdate() doesn't handle StringIO media like PostMedia() did
Both the deprecated PostMedia() and the preferred PostUpdate() methods of the API say they can post media taken from "file like objects (something with a read() method)".
In my case, I am posting a StringIO buffer full of a JPEG image. This works in with PostMedia() but fails in PostUpdate() with the following:
status = self.api.PostUpdate(mess, media=image)
File "/usr/local/lib/python2.7/dist-packages/twitter/api.py", line 1058, in PostUpdate
_, _, file_size, _ = parse_media_file(media)
File "/usr/local/lib/python2.7/dist-packages/twitter/twitter_utils.py", line 226, in parse_media_file
if passed_media.mode != 'rb':
AttributeError: StringIO instance has no attribute 'mode'
Python-twitter version 3.2.1, pythin 2.7
My brief analysis: PostMedia() checks if the media argument is has a read attribute. If so, it read()s the media into data[media] and moves on.
PostUpdate() passes the media argument to parse_media_file() which checks if the media has a mode attribute. Apparantly it does not.
I'm not sure if this a ramification to Twitter's deprecation of the endpoint that PostMedia is based on. I see parse_media_file() doing other mimetype-like stuff. I'm also not sure that StringIO is the best way to do what I want to do (post an image from a buffer)
I'm willing to help troubleshoot further. Thank you!
Jeremy
Yeah, there's a lot going on in that function, which could probably be broken out a bit.
So with the old method (PostMedia()), the API just assumed that you were posting a photo (cause, at the time, that's all you could post to twitter) and so read()ing in a stream of data made sense. Now the API can handle GIFs and videos and each of those have different file-size limitations and attachment limitations, so we try to figure out what you want to upload before uploading the data.
The problem with using a StringIO buffer to post a photo or video is that there's no way (that I know of) of determining if the buffer contains a photo or video or GIF. (Off the top of my head, there may be a way you could probably do it by reading the first bytes of the buffer and then guessing the file type from that, but I don't know without further research.) So this doesn't have anything to do with Twitter's deprecation of that endpoint, just with our manner of figuring out what a user wants to upload.
As for a solution, you can write the buffer out to a NamedTemporaryFile with the extension you want and then pass that to PostUpdate since it'll have a read and mode attribute. This is effectively what we do when we get a URL (check out the http_to_file() method in twitter_utils.py).
Let me know if that solves the problem for you.
Is this issue solved ? Because I am still having problems using BytesIO buffer with the same exception on python 3.7