Esempio n. 1
0
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
Esempio n. 2
0
    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()
Esempio n. 3
0
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()
Esempio n. 4
0
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()
Esempio n. 6
0
    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())
Esempio n. 7
0
    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())