Beispiel #1
0
    def field_decoder_factory(
            self, field: FieldDescriptor) -> Callable[[_Value], Any]:
        from venom.protocol import JSONProtocol

        if field.repeated:
            protocol = JSONProtocol(field.type)

            def _decode_value(msg):
                return protocol.unpacks(msg.encode('utf-8'))

            if field.key_type:
                return lambda dct: {
                    k: _decode_value(v)
                    for k, v in _cast_value(dict, dct).items()
                }
            return lambda lst: [
                _decode_value(item) for item in _cast_value(list, lst)
            ]

        if issubclass(field.type, Message):
            protocol = JSONProtocol(field.type)

            def _decode_value(msg):
                return protocol.unpacks(msg.encode('utf-8'))

            return _decode_value

        if field.type is str:
            return lambda s: s

        if field.type is bytes:
            # TODO catch TypeError
            return lambda b: b64decode(b)

        return partial(_cast_value_from_string, field.type)
Beispiel #2
0
    def test_encode_decode_map(self):
        class FooInner(Message):
            i = String()

        class Foo(Message):
            m = MapField(str)
            f = MapField(FooInner)

        message = Foo(m={'a': 'b'}, f={'k': FooInner(i='in')})
        protocol = JSONProtocol(Foo)
        self.assertEqual(dict(message.m), {'a': 'b'})
        self.assertEqual(dict(message.f), {'k': FooInner(i='in')})
        self.assertEqual(protocol.encode(message), {
            'm': {
                'a': 'b'
            },
            'f': {
                'k': {
                    'i': 'in'
                }
            }
        })
        self.assertEqual(
            protocol.decode({
                'm': {
                    'a': 'b'
                },
                'f': {
                    'k': {
                        'i': 'in'
                    }
                }
            }), message)
Beispiel #3
0
    def test_pack(self):
        class Pet(Message):
            sound = String()

        protocol = JSONProtocol(Pet)
        self.assertEqual(protocol.pack(Pet()), b'{}')
        self.assertEqual(protocol.pack(Pet('hiss!')), b'{"sound":"hiss!"}')
Beispiel #4
0
    def test_encode_zero_numeric(self):
        class Pet(Message):
            cuteness: float

        protocol = JSONProtocol(Pet)
        self.assertEqual(protocol.encode(Pet(0.0)), {'cuteness': 0.0})
        self.assertEqual(protocol.decode({'cuteness': 0.0}), Pet(0.0))
Beispiel #5
0
    def test_encode_message_json_name(self):
        class Pet(Message):
            size = Number(json_name='$size')

        protocol = JSONProtocol(Pet)

        pet = Pet()
        pet.size = 2.5
        self.assertEqual(protocol.encode(pet), {'$size': 2.5})
        self.assertEqual(protocol.decode({'$size': 2.5}), Pet(size=2.5))
Beispiel #6
0
    def test_validation_field_string(self):
        class Foo(Message):
            string = String()

        protocol = JSONProtocol(Foo)
        with self.assertRaises(ValidationError) as e:
            protocol.decode({'string': None})

        self.assertEqual(e.exception.description, "None is not of type 'str'")
        self.assertEqual(e.exception.path, ['string'])
Beispiel #7
0
    def test_string_value(self):
        protocol = JSONProtocol(StringValue)

        self.assertEqual(protocol.encode(StringValue('hiss!')), 'hiss!')
        self.assertEqual(protocol.decode('hiss!'), StringValue('hiss!'))

        self.assertEqual(protocol.pack(StringValue()), b'""')
        self.assertEqual(protocol.pack(StringValue('hiss!')), b'"hiss!"')

        with self.assertRaises(ValidationError):
            protocol.decode(42)
Beispiel #8
0
    def test_bool_value(self):
        protocol = JSONProtocol(BoolValue)

        self.assertEqual(protocol.encode(BoolValue()), False)
        self.assertEqual(protocol.encode(BoolValue(True)), True)
        self.assertEqual(protocol.decode(False), BoolValue(False))

        with self.assertRaises(ValidationError):
            protocol.decode('hiss!')
Beispiel #9
0
    def test_repeat(self):
        class Pet(Message):
            sounds: Repeat[str]

        protocol = JSONProtocol(Pet)

        self.assertEqual(protocol.encode(Pet(['hiss!', '(slither)'])),
                         {'sounds': ['hiss!', '(slither)']})
        self.assertEqual(protocol.decode({"sounds": ['hiss!']}),
                         Pet(['hiss!']))
        self.assertEqual(protocol.decode({}), Pet())

        self.assertEqual(protocol.pack(Pet()), b'{}')
        self.assertEqual(protocol.pack(Pet([])), b'{"sounds":[]}')
        self.assertEqual(protocol.pack(Pet(['hiss!'])),
                         b'{"sounds":["hiss!"]}')

        self.assertEqual(protocol.unpack(b'{}'), Pet())
        self.assertEqual(protocol.unpack(b'{"sounds":["hiss!"]}'),
                         Pet(['hiss!']))
Beispiel #10
0
    def test_integer_value(self):
        protocol = JSONProtocol(IntegerValue)

        self.assertEqual(protocol.encode(IntegerValue(2)), 2)
        self.assertEqual(protocol.decode(2), IntegerValue(2))

        with self.assertRaises(ValidationError):
            protocol.decode('hiss!')
Beispiel #11
0
    def test_number_value(self):
        protocol = JSONProtocol(NumberValue)

        self.assertEqual(protocol.encode(NumberValue(2.5)), 2.5)
        self.assertEqual(protocol.decode(2.5), NumberValue(2.5))

        with self.assertRaises(ValidationError):
            protocol.decode('hiss!')
Beispiel #12
0
    def test_openapi_simple(self):
        class PetSimple(Message):
            id: int

        class PetServiceSimple(Service):
            class Meta:
                name = 'PetService'

            @http.GET('./pet/{id}')
            def get_pet(self, request: PetSimple) -> PetSimple:
                return request

            @http.POST('./pet')
            def create_pet_body(self, request: PetSimple) -> PetSimple:
                return request

        reflect = Reflect()
        reflect.add(PetServiceSimple)
        schema = make_openapi_schema(reflect)
        protocol = JSONProtocol(OpenAPISchema)
        with open(TEST_DIR + '/data/openapi_simple.json', 'rb') as f:
            schema_correct = protocol.unpack(f.read())
            self.assertEqual(schema.paths, schema_correct.paths)
            self.assertEqual(schema.definitions, schema_correct.definitions)
Beispiel #13
0
    def test_timestamp(self):
        protocol = JSONProtocol(Timestamp)

        self.assertEqual(protocol.decode('2017-10-10T12:34:56Z'),
                         Timestamp(1507638896, 0))
        self.assertEqual(protocol.encode(Timestamp(1507638896, 12345)),
                         '2017-10-10T12:34:56.000012')

        with self.assertRaises(ValidationError):
            protocol.decode('yesterday')
Beispiel #14
0
    def test_encode_message(self):
        class Pet(Message):
            sound: str

        protocol = JSONProtocol(Pet)
        self.assertEqual(protocol.encode(Pet('hiss!')), {'sound': 'hiss!'})
        self.assertEqual(protocol.decode({'sound': 'meow'}), Pet('meow'))
        self.assertEqual(protocol.decode({}), Pet())

        with self.assertRaises(ValidationError) as e:
            protocol.decode('bad')

        self.assertEqual(e.exception.description,
                         "'bad' is not of type 'object'")
        self.assertEqual(e.exception.path, [])
Beispiel #15
0
    def test_encode_repeat_field(self):
        class Pet(Message):
            sounds = repeated(String())

        self.assertEqual(Pet.sounds.repeated, True)

        protocol = JSONProtocol(Pet)
        self.assertEqual(protocol.encode(Pet(['hiss!', 'slither'])),
                         {'sounds': ['hiss!', 'slither']})
        self.assertEqual(protocol.decode({'sounds': ['meow', 'purr']}),
                         Pet(['meow', 'purr']))
        self.assertEqual(protocol.decode({}), Pet())
        self.assertEqual(protocol.encode(Pet()), {})

        with self.assertRaises(ValidationError) as e:
            protocol.decode({'sounds': 'meow, purr'})

        self.assertEqual(e.exception.description,
                         "'meow, purr' is not of type 'list'")
        self.assertEqual(e.exception.path, ['sounds'])
Beispiel #16
0
    def test_validation_path(self):
        protocol = JSONProtocol(Foo)

        with self.assertRaises(ValidationError) as e:
            protocol.decode({'string': 42})

        self.assertEqual(e.exception.description, "42 is not of type 'str'")
        self.assertEqual(e.exception.path, ['string'])

        # FIXME With custom encoding/decoding for values this won't happen.
        with self.assertRaises(ValidationError) as e:
            protocol.decode({'stringValue': {'value': None}})

        self.assertEqual(e.exception.description,
                         "{'value': None} is not of type 'str'")
        self.assertEqual(e.exception.path, ['stringValue'])

        with self.assertRaises(ValidationError) as e:
            protocol.decode({'parent': {'stringValue': 42}})

        self.assertEqual(e.exception.description, "42 is not of type 'str'")
        self.assertEqual(e.exception.path, ['parent', 'stringValue'])
Beispiel #17
0
    def test_unpack_invalid_json(self):
        class Pet(Message):
            sound = String()

        protocol = JSONProtocol(Pet)

        with self.assertRaises(ValidationError) as e:
            protocol.unpack(b'')

        self.assertEqual(e.exception.description,
                         "Invalid JSONProtocol: Expected object or value")
        self.assertEqual(e.exception.path, [])

        with self.assertRaises(ValidationError) as e:
            protocol.unpack(b'fs"ad')
Beispiel #18
0
def http_view_factory(venom: 'venom.rpc.Venom',
                      method: venom.rpc.method.Method,
                      protocol_factory: Type[Protocol],
                      loop: 'asyncio.BaseEventLoop' = None):
    rpc_response = protocol_factory(method.response)
    rpc_error_response = protocol_factory(ErrorResponse)

    http_status = method.http_status

    http_field_locations = method.http_field_locations()
    http_request_body = JSONProtocol(
        method.request,
        FieldMask(http_field_locations[HTTPFieldLocation.BODY]))
    http_request_query = URIStringDictMessageTranscoder(
        URIStringProtocol, method.request,
        FieldMask(http_field_locations[HTTPFieldLocation.QUERY]))
    http_request_path = URIStringDictMessageTranscoder(
        URIStringProtocol, method.request,
        FieldMask(http_field_locations[HTTPFieldLocation.PATH]))

    if loop is None:
        loop = asyncio.get_event_loop()

    def view(**kwargs):
        try:
            request = http_request_body.unpack(flask.request.get_data())
            http_request_query.decode(flask.request.args, request)
            http_request_path.decode(kwargs, request)

            response = loop.run_until_complete(
                venom.invoke(method, request, loop=loop))
            return flask.Response(rpc_response.pack(response),
                                  mimetype=rpc_error_response.mime,
                                  status=http_status)
        except Error as e:
            return flask.Response(rpc_error_response.pack(e.format()),
                                  mimetype=rpc_error_response.mime,
                                  status=e.http_status)

    return view
Beispiel #19
0
    def field_encoder_factory(
            self, field: FieldDescriptor) -> Callable[[Any], _Value]:
        from venom.protocol import JSONProtocol

        if field.repeated:
            protocol = JSONProtocol(field.type)

            if field.key_type:
                return lambda dct: {
                    k: protocol.packs(v)
                    for k, v in dct.items()
                }
            return lambda lst: [protocol.packs(v) for v in lst]

        if issubclass(field.type, Message):
            protocol = JSONProtocol(field.type)
            return protocol.packs

        if field.type is bytes:
            return lambda b: b64encode(b)

        return lambda x: str(x)
Beispiel #20
0
    def test_field_mask(self):
        protocol = JSONProtocol(FieldMask)

        self.assertEqual(protocol.encode(FieldMask(['a', 'b'])), 'a,b')
        self.assertEqual(protocol.decode('a,b'), FieldMask(['a', 'b']))
Beispiel #21
0
 def test_json_value(self):
     protocol = JSONProtocol(JSONValue)
     self.assertEqual(protocol.decode(True), JSONValue(True))
     self.assertEqual(protocol.encode(JSONValue(1)), 1)
     self.assertEqual(protocol.decode('str'), JSONValue('str'))
     self.assertEqual(protocol.encode(JSONValue('str')), 'str')
     self.assertEqual(protocol.decode({'a': 'b'}), JSONValue({'a': 'b'}))
     self.assertEqual(protocol.encode(JSONValue({'a': 'b'})), {'a': 'b'})
     self.assertEqual(protocol.decode([1, 2, 3]), JSONValue([1, 2, 3]))
     self.assertEqual(protocol.encode(JSONValue([1, 2, 3])), [1, 2, 3])
     self.assertEqual(
         protocol.decode({
             'a': ['h', 'l'],
             'b': [9, 8, 7],
             'c': 1
         }), JSONValue({
             'a': ['h', 'l'],
             'b': [9, 8, 7],
             'c': 1
         }))
     self.assertEqual(
         protocol.encode(
             JSONValue({
                 'a': ['h', 'l'],
                 'b': [9, 8, 7],
                 'c': 1
             })), {
                 'a': ['h', 'l'],
                 'b': [9, 8, 7],
                 'c': 1
             })