def telegram_encoder(content, *args, **kwargs): try: return dumps(content, cls=TelegramJsonEncoder) except ContainsFileError: pass formatter = TelegramModelFormatterIter(content) kwargs['endpoint_desc']['stream_request'] = True mp = MultipartWriter('form-data') for field, value in formatter: content_dispositon = {'name': field} if isinstance(value, FileModel): part = get_payload(value.stream, headers=CIMultiDict()) if value.name: content_dispositon['filename'] = value.name if value.mime_type: part.headers[CONTENT_TYPE] = value.mime_type else: part = get_payload(str(value), headers=CIMultiDict()) part.set_content_disposition("form-data", **content_dispositon) mp.append_payload(part) try: kwargs['request_params']['headers'].update(mp.headers) except KeyError: kwargs['request_params']['headers'] = mp.headers return mp
def test_POST_MULTIPART(self): with run_server(self.loop, router=Functional) as httpd: url = httpd.url('method', 'post') with MultipartWriter('form-data') as writer: writer.append('foo') writer.append_json({'bar': 'баз'}) writer.append_form([('тест', '4'), ('сетс', '2')]) r = self.loop.run_until_complete( client.request('post', url, data=writer, loop=self.loop)) content = self.loop.run_until_complete(r.json()) self.assertEqual(3, len(content['multipart-data'])) self.assertEqual({ 'content-type': 'text/plain', 'data': 'foo' }, content['multipart-data'][0]) self.assertEqual( { 'content-type': 'application/json', 'data': '{"bar": "\\u0431\\u0430\\u0437"}' }, content['multipart-data'][1]) self.assertEqual( { 'content-type': 'application/x-www-form-urlencoded', 'data': '%D1%82%D0%B5%D1%81%D1%82=4&' '%D1%81%D0%B5%D1%82%D1%81=2' }, content['multipart-data'][2]) self.assertEqual(r.status, 200) r.close()
def test_POST_MULTIPART(loop, test_client): @asyncio.coroutine def handler(request): data = yield from request.post() lst = list(data.values()) assert 3 == len(lst) assert lst[0] == 'foo' assert lst[1] == {'bar': 'баз'} assert b'data' == data['unknown'].file.read() assert data['unknown'].content_type == 'application/octet-stream' assert data['unknown'].filename == 'unknown' return web.HTTPOk() app = web.Application(loop=loop) app.router.add_post('/', handler) client = yield from test_client(app) with MultipartWriter('form-data') as writer: writer.append('foo') writer.append_json({'bar': 'баз'}) writer.append_form([('тест', '4'), ('сетс', '2')]) resp = yield from client.post('/', data=writer) assert 200 == resp.status resp.close()
async def step2(session: ClientSession, f_image: FileIO, s3_fields: dict) -> None: """ Upload the image to the S3 location """ with MultipartWriter() as mpwriter: for key in s3_fields: mpwriter.append(s3_fields[key], name=key) mpwriter.append(f_image, name="image.jpg") url = "https://wombo-user-content.s3.amazonaws.com/" async with session.post(url, data=mpwriter) as response: response.raise_for_status()
def function1236(self): with function147(self.attribute2267, router=Class273) as var4065: var2123 = var4065.var2123('method', 'post') with MultipartWriter('form-data') as var4608: var4608.append('foo') var4608.append_json({'bar': 'баз', }) var4608.append_form([('тест', '4'), ('сетс', '2')]) var101 = client.ClientSession(loop=self.attribute2267) var983 = self.attribute2267.run_until_complete(var101.request('post', var2123, data=var4608)) var4642 = self.attribute2267.run_until_complete(var983.json()) self.assertEqual(3, len(var4642['multipart-data'])) self.assertEqual({'content-type': 'text/plain', 'data': 'foo', }, var4642['multipart-data'][0]) self.assertEqual({'content-type': 'application/json', 'data': '{"bar": "\\u0431\\u0430\\u0437"}', }, var4642['multipart-data'][1]) self.assertEqual({'content-type': 'application/x-www-form-urlencoded', 'data': '%D1%82%D0%B5%D1%81%D1%82=4&%D1%81%D0%B5%D1%82%D1%81=2', }, var4642['multipart-data'][2]) self.assertEqual(var983.status, 200) var983.close() var101.close()
def update(self, doc, *, atts=None, auth=None, batch=None, new_edits=None, rev=None): """`Updates a document`_ on server. :param dict doc: Document object. Should implement :class:`~collections.abc.MutableMapping` interface :param auth: :class:`aiocouchdb.authn.AuthProvider` instance :param dict atts: Attachments mapping where keys are represents attachment name and value is file-like object or bytes :param str batch: Updates in batch mode (asynchronously) This argument accepts only ``"ok"`` value. :param bool new_edits: Signs about new document edition. When ``False`` allows to create conflicts manually :param str rev: Document revision. Optional, since document ``_rev`` field is also respected :rtype: dict .. warning:: Updating document with attachments is not able to use all the advantages of multipart request due to `COUCHDB-2295`_ issue, so don't even try to update a document with several gigabytes attachments with this method. Put them one-by-one via :meth:`aiocouchdb.v1.attachment.Attachment.update` method. .. _Updates a document: http://docs.couchdb.org/en/latest/api/document/common.html#put--db-docid .. _COUCHDB-2295: https://issues.apache.org/jira/browse/COUCHDB-2295 """ params = dict((key, value) for key, value in locals().items() if (key not in {'self', 'doc', 'auth', 'atts'} and value is not None)) if not isinstance(doc, MutableMapping): raise TypeError('MutableMapping instance expected, like a dict') if '_id' in doc and doc['_id'] != self.id: raise ValueError('Attempt to store document with different ID: ' '%r ; expected: %r. May be you want to .copy() it?' % (doc['_id'], self.id)) if atts: writer = MultipartWriter('related') doc.setdefault('_attachments', {}) # A little hack to sync the order of attachments definition # between JSON and multipart body parts for name in atts: doc['_attachments'][name] = {} for name, stub in doc['_attachments'].items(): if stub: continue att = atts[name] if not isinstance(att, (bytes, io.BytesIO, io.BufferedIOBase)): raise TypeError('attachment payload should be a source of' ' binary data (bytes, BytesIO, file ' ' opened in binary mode), got %r' % att) part = writer.append(att) part.set_content_disposition('attachment', filename=name) doc['_attachments'][name] = { 'length': int(part.headers[CONTENT_LENGTH]), 'follows': True, 'content_type': part.headers[CONTENT_TYPE] } writer.append_json(doc) # CouchDB expects document at the first body part writer.parts.insert(0, writer.parts.pop()) # workaround of COUCHDB-2295, I really sorry for that body = b''.join(writer.serialize()) resp = yield from self.resource.put(auth=auth, data=body, headers=writer.headers, params=params) for info in doc['_attachments'].values(): info.pop('follows') info['stub'] = True else: resp = yield from self.resource.put(auth=auth, data=doc, params=params) yield from resp.maybe_raise_error() return (yield from resp.json())
def update(self, doc, *, atts=None, auth=None, batch=None, new_edits=None, rev=None): """`Updates a document`_ on server. :param dict doc: Document object. Should implement :class:`~collections.abc.MutableMapping` interface :param auth: :class:`aiocouchdb.authn.AuthProvider` instance :param dict atts: Attachments mapping where keys are represents attachment name and value is file-like object or bytes :param str batch: Updates in batch mode (asynchronously) This argument accepts only ``"ok"`` value. :param bool new_edits: Signs about new document edition. When ``False`` allows to create conflicts manually :param str rev: Document revision. Optional, since document ``_rev`` field is also respected :rtype: dict .. _Updates a document: http://docs.couchdb.org/en/latest/api/document/common.html#put--db-docid """ params = dict((key, value) for key, value in locals().items() if ( key not in {'self', 'doc', 'auth', 'atts'} and value is not None)) if not isinstance(doc, MutableMapping): raise TypeError('MutableMapping instance expected, like a dict') if '_id' in doc and doc['_id'] != self.id: raise ValueError( 'Attempt to store document with different ID: ' '%r ; expected: %r. May be you want to .copy() it?' % (doc['_id'], self.id)) if atts: writer = MultipartWriter('related') writer.append_json(doc) doc.setdefault('_attachments', {}) # A little hack to sync the order of attachments definition # between JSON and multipart body parts for name in atts: doc['_attachments'][name] = {} for name, stub in doc['_attachments'].items(): if stub: continue att = atts[name] if not isinstance(att, (bytes, io.BytesIO, io.BufferedIOBase)): raise TypeError('attachment payload should be a source of' ' binary data (bytes, BytesIO, file ' ' opened in binary mode), got %r' % att) part = writer.append(att) part.set_content_disposition('attachment', filename=name) doc['_attachments'][name] = { 'length': int(part.headers[CONTENT_LENGTH]), 'follows': True, 'content_type': part.headers[CONTENT_TYPE] } first_part = writer._parts[0] first_part[0].headers[CONTENT_LENGTH] = \ str(len(json.dumps(doc).encode('utf-8'))) # workaround of COUCHDB-2295 writer.headers[CONTENT_LENGTH] = str(writer.size) resp = yield from self.resource.put(auth=auth, data=writer, params=params) for info in doc['_attachments'].values(): info.pop('follows') info['stub'] = True else: resp = yield from self.resource.put(auth=auth, data=doc, params=params) yield from resp.maybe_raise_error() return (yield from resp.json())