From d58fbe6170eb65a00f1cd8268c463d0eaea4bce5 Mon Sep 17 00:00:00 2001 From: Goffi Date: Mon, 25 Mar 2019 07:06:41 +0100 Subject: [PATCH] plugin android: workaround to seek() bug, fixing file upload: seek() is bugged on current version of P4A, arguments are inverted. More details can be found at https://github.com/kivy/python-for-android/issues/1768 --- sat/plugins/plugin_misc_android.py | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sat/plugins/plugin_misc_android.py b/sat/plugins/plugin_misc_android.py index d3ffd934..3729c537 100644 --- a/sat/plugins/plugin_misc_android.py +++ b/sat/plugins/plugin_misc_android.py @@ -20,6 +20,7 @@ import sys import os import os.path +import tempfile from sat.core.i18n import _, D_ from sat.core.constants import Const as C from sat.core.log import getLogger @@ -27,6 +28,7 @@ from sat.core import exceptions from twisted.internet import reactor from twisted.internet import protocol from twisted.internet import error as int_error +from twisted.web import client as web_client log = getLogger(__name__) @@ -57,6 +59,38 @@ STATE_STOPPED = "stopped" STATES = (STATE_RUNNING, STATE_PAUSED, STATE_STOPPED) +def determineLength_workaround(self, fObj): + """Method working around seek() bug on Android""" + try: + seek = fObj.seek + tell = fObj.tell + except AttributeError: + return web_client.UNKNOWN_LENGTH + originalPosition = tell() + seek(os.SEEK_END) + end = tell() + seek(os.SEEK_SET, originalPosition) + return end - originalPosition + + +def patch_seek_bug(): + """Check seek bug and apply a workaround if still here + + cf. https://github.com/kivy/python-for-android/issues/1768 + """ + with tempfile.TemporaryFile() as f: + f.write(b'1234567890') + f.seek(0, os.SEEK_END) + size = f.tell() + if size == 10: + log.info(u"seek() bug not present anymore, workaround code can be removed") + else: + log.warning(u"seek() bug detected, applying a workaround") + web_client.FileBodyProducer._determineLength = determineLength_workaround + +patch_seek_bug() + + class FrontendStateProtocol(protocol.Protocol): def __init__(self, android_plugin):