def _sendfile(self, inputfile, filetype, params): method = {'photo': 'sendPhoto', 'audio': 'sendAudio', 'document': 'sendDocument', 'sticker': 'sendSticker', 'video': 'sendVideo', 'voice': 'sendVoice',}[filetype] if _isstring(inputfile): params[filetype] = inputfile return (yield from _post(self._methodurl(method), self._http_timeout, data=_rectify(params))) else: if isinstance(inputfile, tuple): if len(inputfile) == 2: filename, fileobj = inputfile else: raise ValueError('Tuple must have exactly 2 elements: filename, fileobj') else: filename, fileobj = guess_filename(inputfile) or filetype, inputfile mpwriter = aiohttp.MultipartWriter('form-data') part = mpwriter.append(fileobj) part.set_content_disposition('form-data', name=filetype, filename=filename) return (yield from _post(self._methodurl(method), None, params=_rectify(params), data=mpwriter))
def _sendfile(self, inputfile, filetype, params): method = {'photo': 'sendPhoto', 'audio': 'sendAudio', 'document': 'sendDocument', 'sticker': 'sendSticker', 'video': 'sendVideo', 'voice': 'sendVoice',}[filetype] if _isstring(inputfile): params[filetype] = inputfile return (yield from _post(self._methodurl(method), self._http_timeout, data=_rectify(params))) else: if isinstance(inputfile, tuple): if len(inputfile) == 2: filename, fileobj = inputfile else: raise ValueError('Tuple must have exactly 2 elements: filename, fileobj') else: filename, fileobj = guess_filename(inputfile) or filetype, inputfile data = FormData() for key,value in _rectify(params).items(): data.add_field(key, str(value)) data.add_field(filetype, fileobj, filename=filename) return (yield from _post(self._methodurl(method), None, data=data))
def _guess_mime_type(key, val): if not isinstance(val, (tuple, list)): filename = guess_filename(val) or key filetype = _guess_content_type(filename) val = (filename, val, filetype) elif len(val) < 3 or val[2] is None: filename = val[0] filetype = _guess_content_type(filename) # val = (*val[:2], filetype, *val[3:]) # FIXME: Python 2 val = tuple(val[:2]) + (filetype,) + tuple(val[3:]) return key, val
def _sendFile(self, inputfile, filetype, params): method = { 'photo': 'sendPhoto', 'audio': 'sendAudio', 'document': 'sendDocument', 'sticker': 'sendSticker', 'video': 'sendVideo', 'voice': 'sendVoice', }[filetype] if telepot._isstring(inputfile): params[filetype] = inputfile r = yield from asyncio.wait_for( aiohttp.post(self._methodurl(method), data=self._rectify( params, allow_namedtuple=['reply_markup'])), self._http_timeout) else: if isinstance(inputfile, tuple): if len(inputfile) == 2: filename, fileobj = inputfile else: raise ValueError( 'Tuple must have exactly 2 elements: filename, fileobj' ) else: filename, fileobj = guess_filename( inputfile) or filetype, inputfile mpwriter = aiohttp.MultipartWriter('form-data') part = mpwriter.append(fileobj) part.set_content_disposition('form-data', name=filetype, filename=filename) r = yield from aiohttp.post(self._methodurl(method), params=self._rectify( params, allow_namedtuple=['reply_markup']), data=mpwriter) # `_http_timeout` is not used here because, for some reason, the larger the file, # the longer it takes for the server to respond (after upload is finished). It is hard to say # what value `_http_timeout` should be. In the future, maybe I should let user specify. return (yield from self._parse(r))
def _compose_data(req, **user_kw): token, method, params, files = req data = aiohttp.helpers.FormData() if params: for key,value in params.items(): data.add_field(key, str(value)) if files: for key,f in files.items(): if isinstance(f, tuple): if len(f) == 2: filename, fileobj = f else: raise ValueError('Tuple must have exactly 2 elements: filename, fileobj') else: filename, fileobj = guess_filename(f) or key, f data.add_field(key, fileobj, filename=filename) return data
def _sendFile(self, inputfile, filetype, params): method = {'photo': 'sendPhoto', 'audio': 'sendAudio', 'document': 'sendDocument', 'sticker': 'sendSticker', 'video': 'sendVideo', 'voice': 'sendVoice',}[filetype] if telepot._isstring(inputfile): params[filetype] = inputfile r = yield from asyncio.wait_for( aiohttp.post( self._methodurl(method), data=self._rectify(params, allow_namedtuple=['reply_markup'])), self._http_timeout) else: if isinstance(inputfile, tuple): if len(inputfile) == 2: filename, fileobj = inputfile else: raise ValueError('Tuple must have exactly 2 elements: filename, fileobj') else: filename, fileobj = guess_filename(inputfile) or filetype, inputfile mpwriter = aiohttp.MultipartWriter('form-data') part = mpwriter.append(fileobj) part.set_content_disposition('form-data', name=filetype, filename=filename) r = yield from aiohttp.post( self._methodurl(method), params=self._rectify(params, allow_namedtuple=['reply_markup']), data=mpwriter) # `_http_timeout` is not used here because, for some reason, the larger the file, # the longer it takes for the server to respond (after upload is finished). It is hard to say # what value `_http_timeout` should be. In the future, maybe I should let user specify. return (yield from self._parse(r))
def _sendfile(self, inputfile, filetype, params): method = { 'photo': 'sendPhoto', 'audio': 'sendAudio', 'document': 'sendDocument', 'sticker': 'sendSticker', 'video': 'sendVideo', 'voice': 'sendVoice', }[filetype] if _isstring(inputfile): params[filetype] = inputfile return (yield from _post(self._methodurl(method), self._http_timeout, data=_rectify(params))) else: if isinstance(inputfile, tuple): if len(inputfile) == 2: filename, fileobj = inputfile else: raise ValueError( 'Tuple must have exactly 2 elements: filename, fileobj' ) else: filename, fileobj = guess_filename( inputfile) or filetype, inputfile mpwriter = aiohttp.MultipartWriter('form-data') part = mpwriter.append(fileobj) part.set_content_disposition('form-data', name=filetype, filename=filename) return (yield from _post(self._methodurl(method), None, params=_rectify(params), data=mpwriter))
def test_guess_filename_valid(self, value, expected_type): obj = type('Fake', (object,), {'name': value})() result = guess_filename(obj) assert result == value assert isinstance(result, expected_type)
def test_guess_filename_invalid(self, value): assert guess_filename(value) is None
def _encode_files(files: dict, data: dict): """Build the body for a multipart/form-data request. Will successfully encode files when passed as a dict or a list of tuples. Order is retained if data is a list of tuples but arbitrary if parameters are supplied as a dict. The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype) or 4-tuples (filename, fileobj, contentype, custom_headers). """ if not files: raise ValueError("Files must be provided.") elif isinstance(data, str): raise ValueError("Data must not be a string.") index = {} index.update(data) index.update(files) index = Utils.reorder_by_hash_code(index) new_fields = [] for key, value in index.items(): if key in files: # support for explicit filename ft = None fh = None if isinstance(value, (tuple, list)): if len(value) == 2: fn, fp = value elif len(value) == 3: fn, fp, ft = value else: fn, fp, ft, fh = value else: fn = guess_filename(value) or key fp = value if isinstance(fp, (str, bytes, bytearray)): fdata = fp elif hasattr(fp, 'read'): fdata = fp.read() elif fp is None: continue else: fdata = fp rf = RequestField(name=key, data=fdata, filename=fn, headers=fh) rf.make_multipart(content_type=ft) new_fields.append(rf) elif key in data: if isinstance(value, str) or not hasattr(value, '__iter__'): value = [value] for value in value: if value is not None: # Don't call str() on bytestrings: in Py3 it all goes wrong. if not isinstance(value, bytes): value = str(value) new_fields.append((key.decode('utf-8') if isinstance( key, bytes) else key, value.encode('utf-8') if isinstance(value, str) else value)) body, content_type = encode_multipart_formdata(new_fields) # TODO: compress body return body, content_type