diff --git a/mercator/__init__.py b/mercator/__init__.py index 8827e86..79470f2 100644 --- a/mercator/__init__.py +++ b/mercator/__init__.py @@ -121,15 +121,16 @@ def cast(self, value): :param value: a python object that is compatible with the given ``target_type`` :returns: list of items target type coerced into the ``target_type``. Supports ProtoMappings by automatically calling :py:meth:`~mercator.ProtoMapping.to_protobuf`. """ - result = super().cast(value) - - if result is None: + if value is None: return if not isinstance(value, (list, tuple)): raise TypeCastError(f'ProtoList.cast() received a non-list value ' f'(type {type(value).__name__}): {value}') + if self.target_type is None: + return value + if issubclass(self.target_type, ProtoMapping): return [self.target_type(item).to_protobuf() for item in value] diff --git a/tests/unit/test_proto_list.py b/tests/unit/test_proto_list.py index 3f8dec2..8984cd7 100644 --- a/tests/unit/test_proto_list.py +++ b/tests/unit/test_proto_list.py @@ -66,3 +66,37 @@ def test_proto_list_native_type(): t1, t2 = result t1.should.be.a(str) t2.should.be.a(str) + + +def test_proto_list_int_type(): + "ProtoList() should return a list of integers if target_type is int" + + field = ProtoList('user_ids', int) + result = field.cast(['1', 2]) + + result.should.be.a(list) + result.should.have.length_of(2) + result.should.equal([1, 2]) + + t1, t2 = result + t1.should.be.a(int) + t2.should.be.a(int) + + +def test_proto_list_with_target_type_none(): + "ProtoList() cast should return an origin value if target_type is None" + field = ProtoList('user_ids') + result = field.cast(['1', 2]) + + result.should.be.a(list) + result.should.have.length_of(2) + result.should.equal(['1', 2]) + + +def test_proto_list_with_target_type_none_and_non_list_tuple(): + "ProtoList() should raise an error if target_type is None and not fed with a list or tuple" + + field = ProtoList('tokens') + when_called = field.cast.when.called_with('some tokens as string') + + when_called.should.have.raised(TypeCastError)