text: """Tests for field serialization."""
  from collections import namedtuple, OrderedDict
  import datetime as dt
  import itertools
  import decimal
  import uuid
  import ipaddress
  
  import pytest
  
  from marshmallow import Schema, fields, missing as missing_
  
  from tests.base import User, ALL_FIELDS, central
  
  
  class DateTimeList:
      def __init__(self, dtimes):
          self.dtimes = dtimes
  
  
  class IntegerList:
      def __init__(self, ints):
          self.ints = ints
  
  
  class DateTimeIntegerTuple:
      def __init__(self, dtime_int):
          self.dtime_int = dtime_int
  
  
  class TestFieldSerialization:
      @pytest.fixture
      def user(self):
          return User("Foo", email="foo@bar.com", age=42)
  
      @pytest.mark.parametrize(
          ("value", "expected"), [(42, float(42)), (0, float(0)), (None, None)]
      )
      def test_number(self, value, expected, user):
          field = fields.Number()
          user.age = value
          assert field.serialize("age", user) == expected
  
      def test_number_as_string(self, user):
          user.age = 42
          field = fields.Number(as_string=True)
          assert field.serialize("age", user) == str(float(user.age))
  
      def test_number_as_string_passed_none(self, user):
          user.age = None
          field = fields.Number(as_string=True, allow_none=True)
          assert field.serialize("age", user) is None
  
      def test_function_field_passed_func(self, user):
          field = fields.Function(lambda obj: obj.name.upper())
          assert "FOO" == field.serialize("key", user)
  
      def test_function_field_passed_serialize_only_is_dump_only(self, user):
          field = fields.Function(serialize=lambda obj: obj.name.upper())
          assert field.dump_only is True
  
      def test_function_field_passed_deserialize_and_serialize_is_not_dump_only(self):
          field = fields.Function(
              serialize=lambda val: val.lower(), deserialize=lambda val: val.upper()
          )
          assert field.dump_only is False
  
      def test_function_field_passed_serialize(self, user):
          field = fields.Function(serialize=lambda obj: obj.name.upper())
          assert "FOO" == field.serialize("key", user)
  
      # https://github.com/marshmallow-code/marshmallow/issues/395
      def test_function_field_does_not_swallow_attribute_error(self, user):
          def raise_error(obj):
              raise AttributeError()
  
          field = fields.Function(serialize=raise_error)
          with pytest.raises(AttributeError):
              field.serialize("key", user)
  
      def test_serialize_with_load_only_param(self):
          class AliasingUserSerializer(Schema):
              name = fields.String()
              years = fields.Integer(load_only=True)
              size = fields.Integer(dump_only=True, load_only=True)
              nicknames = fields.List(fields.Str(), load_only=True)
  
          data = {
              "name": "Mick",
              "years": "42",
              "size": "12",
              "nicknames": ["Your Majesty", "Brenda"],
          }
          result = AliasingUserSerializer().dump(data)
          assert result["name"] == "Mick"
          assert "years" not in result
          assert "size" not in result
          assert "nicknames" not in result
  
      def test_function_field_load_only(self):
          field = fields.Function(deserialize=lambda obj: None)
          assert field.load_only
  
      def test_function_field_passed_serialize_with_context(self, user, monkeypatch):
          class Parent(Schema):
              pass
  
          field = fields.Function(
              serialize=lambda obj, context: obj.name.upper() + context["key"]
          )
          field.parent = Parent(context={"key": "BAR"})
          assert "FOOBAR" == field.serialize("key", user)
  
      def test_function_field_passed_uncallable_object(self):
          with pytest.raises(TypeError):
              fields.Function("uncallable")
  
      def test_integer_field(self, user):
          field = fields.Integer()
          assert field.serialize("age", user) == 42
  
      def test_integer_as_string_field(self, user):
          field = fields.Integer(as_string=True)
          assert field.serialize("age", user) == "42"
  
      def test_integer_field_default(self, user):
          user.age = None
          field = fields.Integer(dump_default=0)
          assert field.serialize("age", user) is None
          # missing
          assert field.serialize("age", {}) == 0
  
      def test_integer_field_default_set_to_none(self, user):
          user.age = None
          field = fields.Integer(dump_default=None)
          assert field.serialize("age", user) is None
  
      def test_uuid_field(self, user):
          user.uuid1 = uuid.UUID("12345678123456781234567812345678")
          user.uuid2 = None
  
          field = fields.UUID()
          assert isinstance(field.serialize("uuid1", user), str)
          assert field.serialize("uuid1", user) == "12345678-1234-5678-1234-567812345678"
          assert field.serialize("uuid2", user) is None
  
      def test_ip_address_field(self, user):
  
          ipv4_string = "192.168.0.1"
          ipv6_string = "ffff::ffff"
          ipv6_exploded_string = ipaddress.ip_address("ffff::ffff").exploded
  
          user.ipv4 = ipaddress.ip_address(ipv4_string)
          user.ipv6 = ipaddress.ip_address(ipv6_string)
          user.empty_ip = None
  
          field_compressed = fields.IP()
          assert isinstance(field_compressed.serialize("ipv4", user), str)
          assert field_compressed.serialize("ipv4", user) == ipv4_string
          assert isinstance(field_compressed.serialize("ipv6", user), str)
          assert field_compressed.serialize("ipv6", user) == ipv6_string
          assert field_compressed.serialize("empty_ip", user) is None
  
          field_exploded = fields.IP(exploded=True)
          assert isinstance(field_exploded.serialize("ipv6", user), str)
          assert field_exploded.serialize("ipv6", user) == ipv6_exploded_string
  
      def test_ipv4_address_field(self, user):
  
          ipv4_string = "192.168.0.1"
  
          user.ipv4 = ipaddress.ip_address(ipv4_string)
          user.empty_ip = None
  
          field = fields.IPv4()
          assert isinstance(field.serialize("ipv4", user), str)
          assert field.serialize("ipv4", user) == ipv4_string
          assert field.serialize("empty_ip", user) is None
  
      def test_ipv6_address_field(self, user):
  
          ipv6_string = "ffff::ffff"
          ipv6_exploded_string = ipaddress.ip_address("ffff::ffff").exploded
  
          user.ipv6 = ipaddress.ip_address(ipv6_string)
          user.empty_ip = None
  
          field_compressed = fields.IPv6()
          assert isinstance(field_compressed.serialize("ipv6", user), str)
          assert field_compressed.serialize("ipv6", user) == ipv6_string
          assert field_compressed.serialize("empty_ip", user) is None
  
          field_exploded = fields.IPv6(exploded=True)
          assert isinstance(field_exploded.serialize("ipv6", user), str)
          assert field_exploded.serialize("ipv6", user) == ipv6_exploded_string
  
      def test_ip_interface_field(self, user):
  
          ipv4interface_string = "192.168.0.1/24"
          ipv6interface_string = "ffff::ffff/128"
          ipv6interface_exploded_string = ipaddress.ip_interface(
              "ffff::ffff/128"
          ).exploded
  
          user.ipv4interface = ipaddress.ip_interface(ipv4interface_string)
          user.ipv6interface = ipaddress.ip_interface(ipv6interface_string)
          user.empty_ipinterface = None
  
          field_compressed = fields.IPInterface()
          assert isinstance(field_compressed.serialize("ipv4interface", user), str)
          assert field_compressed.serialize("ipv4interface", user) == ipv4interface_string
          assert isinstance(field_compressed.serialize("ipv6interface", user), str)
          assert field_compressed.serialize("ipv6interface", user) == ipv6interface_string
          assert field_compressed.serialize("empty_ipinterface", user) is None
  
          field_exploded = fields.IPInterface(exploded=True)
          assert isinstance(field_exploded.serialize("ipv6interface", user), str)
          assert (
              field_exploded.serialize("ipv6interface", user)
              == ipv6interface_exploded_string
          )
  
      def test_ipv4_interface_field(self, user):
  
          ipv4interface_string = "192.168.0.1/24"
  
          user.ipv4interface = ipaddress.ip_interface(ipv4interface_string)
          user.empty_ipinterface = None
  
          field = fields.IPv4Interface()
          assert isinstance(field.serialize("ipv4interface", user), str)
          assert field.serialize("ipv4interface", user) == ipv4interface_string
          assert field.serialize("empty_ipinterface", user) is None
  
      def test_ipv6_interface_field(self, user):
  
          ipv6interface_string = "ffff::ffff/128"
          ipv6interface_exploded_string = ipaddress.ip_interface(
              "ffff::ffff/128"
          ).exploded
  
          user.ipv6interface = ipaddress.ip_interface(ipv6interface_string)
          user.empty_ipinterface = None
  
          field_compressed = fields.IPv6Interface()
          assert isinstance(field_compressed.serialize("ipv6interface", user), str)
          assert field_compressed.serialize("ipv6interface", user) == ipv6interface_string
          assert field_compressed.serialize("empty_ipinterface", user) is None
  
          field_exploded = fields.IPv6Interface(exploded=True)
          assert isinstance(field_exploded.serialize("ipv6interface", user), str)
          assert (
              field_exploded.serialize("ipv6interface", user)
              == ipv6interface_exploded_string
          )
  
      def test_decimal_field(self, user):
          user.m1 = 12
          user.m2 = "12.355"
          user.m3 = decimal.Decimal(1)
          user.m4 = None
  
          field = fields.Decimal()
          assert isinstance(field.serialize("m1", user), decimal.Decimal)
          assert field.serialize("m1", user) == decimal.Decimal(12)
          assert isinstance(field.serialize("m2", user), decimal.Decimal)
          assert field.serialize("m2", user) == decimal.Decimal("12.355")
          assert isinstance(field.serialize("m3", user), decimal.Decimal)
          assert field.serialize("m3", user) == decimal.Decimal(1)
          assert field.serialize("m4", user) is None
  
          field = fields.Decimal(1)
          assert isinstance(field.serialize("m1", user), decimal.Decimal)
          assert field.serialize("m1", user) == decimal.Decimal(12)
          assert isinstance(field.serialize("m2", user), decimal.Decimal)
          assert field.serialize("m2", user) == decimal.Decimal("12.4")
          assert isinstance(field.serialize("m3", user), decimal.Decimal)
          assert field.serialize("m3", user) == decimal.Decimal(1)
          assert field.serialize("m4", user) is None
  
          field = fields.Decimal(1, decimal.ROUND_DOWN)
          assert isinstance(field.serialize("m1", user), decimal.Decimal)
          assert field.serialize("m1", user) == decimal.Decimal(12)
          assert isinstance(field.serialize("m2", user), decimal.Decimal)
          assert field.serialize("m2", user) == decimal.Decimal("12.3")
          assert isinstance(field.serialize("m3", user), decimal.Decimal)
          assert field.serialize("m3", user) == decimal.Decimal(1)
          assert field.serialize("m4", user) is None
  
      def test_decimal_field_string(self, user):
          user.m1 = 12
          user.m2 = "12.355"
          user.m3 = decimal.Decimal(1)
          user.m4 = None
  
          field = fields.Decimal(as_string=True)
          assert isinstance(field.serialize("m1", user), str)
          assert field.serialize("m1", user) == "12"
          assert isinstance(field.serialize("m2", user), str)
          assert field.serialize("m2", user) == "12.355"
          assert isinstance(field.serialize("m3", user), str)
          assert field.serialize("m3", user) == "1"
          assert field.serialize("m4", user) is None
  
          field = fields.Decimal(1, as_string=True)
          assert isinstance(field.serialize("m1", user), str)
          assert field.serialize("m1", user) == "12.0"
          assert isinstance(field.serialize("m2", user), str)
          assert field.serialize("m2", user) == "12.4"
          assert isinstance(field.serialize("m3", user), str)
          assert field.serialize("m3", user) == "1.0"
          assert field.serialize("m4", user) is None
  
          field = fields.Decimal(1, decimal.ROUND_DOWN, as_string=True)
          assert isinstance(field.serialize("m1", user), str)
          assert field.serialize("m1", user) == "12.0"
          assert isinstance(field.serialize("m2", user), str)
          assert field.serialize("m2", user) == "12.3"
          assert isinstance(field.serialize("m3", user), str)
          assert field.serialize("m3", user) == "1.0"
          assert field.serialize("m4", user) is None
  
      def test_decimal_field_special_values(self, user):
          user.m1 = "-NaN"
          user.m2 = "NaN"
          user.m3 = "-sNaN"
          user.m4 = "sNaN"
          user.m5 = "-Infinity"
          user.m6 = "Infinity"
          user.m7 = "-0"
  
          field = fields.Decimal(places=2, allow_nan=True)
  
          m1s = field.serialize("m1", user)
          assert isinstance(m1s, decimal.Decimal)
          assert m1s.is_qnan() and not m1s.is_signed()
  
          m2s = field.serialize("m2", user)
          assert isinstance(m2s, decimal.Decimal)
          assert m2s.is_qnan() and not m2s.is_signed()
  
          m3s = field.serialize("m3", user)
          assert isinstance(m3s, decimal.Decimal)
          assert m3s.is_qnan() and not m3s.is_signed()
  
          m4s = field.serialize("m4", user)
          assert isinstance(m4s, decimal.Decimal)
          assert m4s.is_qnan() and not m4s.is_signed()
  
          m5s = field.serialize("m5", user)
          assert isinstance(m5s, decimal.Decimal)
          assert m5s.is_infinite() and m5s.is_signed()
  
          m6s = field.serialize("m6", user)
          assert isinstance(m6s, decimal.Decimal)
          assert m6s.is_infinite() and not m6s.is_signed()
  
          m7s = field.serialize("m7", user)
          assert isinstance(m7s, decimal.Decimal)
          assert m7s.is_zero() and m7s.is_signed()
  
          field = fields.Decimal(as_string=True, allow_nan=True)
  
          m2s = field.serialize("m2", user)
          assert isinstance(m2s, str)
          assert m2s == user.m2
  
          m5s = field.serialize("m5", user)
          assert isinstance(m5s, str)
          assert m5s == user.m5
  
          m6s = field.serialize("m6", user)
          assert isinstance(m6s, str)
          assert m6s == user.m6
  
      def test_decimal_field_special_values_not_permitted(self, user):
          user.m7 = "-0"
  
          field = fields.Decimal(places=2)
  
          m7s = field.serialize("m7", user)
          assert isinstance(m7s, decimal.Decimal)
          assert m7s.is_zero() and m7s.is_signed()
  
      def test_decimal_field_fixed_point_representation(self, user):
          """
          Test we get fixed-point string representation for a Decimal number that would normally
          output in engineering notation.
          """
          user.m1 = "0.00000000100000000"
  
          field = fields.Decimal()
          s = field.serialize("m1", user)
          assert isinstance(s, decimal.Decimal)
          assert s == decimal.Decimal("1.00000000E-9")
  
          field = fields.Decimal(as_string=True)
          s = field.serialize("m1", user)
          assert isinstance(s, str)
          assert s == user.m1
  
          field = fields.Decimal(as_string=True, places=2)
          s = field.serialize("m1", user)
          assert isinstance(s, str)
          assert s == "0.00"
  
      def test_boolean_field_serialization(self, user):
          field = fields.Boolean()
  
          user.truthy = "non-falsy-ish"
          user.falsy = "false"
          user.none = None
  
          assert field.serialize("truthy", user) is True
          assert field.serialize("falsy", user) is False
          assert field.serialize("none", user) is None
  
      def test_email_field_serialize_none(self, user):
          user.email = None
          field = fields.Email()
          assert field.serialize("email", user) is None
  
      def test_dict_field_serialize_none(self, user):
          user.various_data = None
          field = fields.Dict()
          assert field.serialize("various_data", user) is None
  
      def test_dict_field_serialize(self, user):
          user.various_data = {"foo": "bar"}
          field = fields.Dict()
          dump = field.serialize("various_data", user)
          assert dump == {"foo": "bar"}
          # Check dump is a distinct object
          dump["foo"] = "baz"
          assert user.various_data["foo"] == "bar"
  
      def test_dict_field_serialize_ordereddict(self, user):
          user.various_data = OrderedDict([("foo", "bar"), ("bar", "baz")])
          field = fields.Dict()
          assert field.serialize("various_data", user) == OrderedDict(
              [("foo", "bar"), ("bar", "baz")]
          )
  
      def test_structured_dict_value_serialize(self, user):
          user.various_data = {"foo": decimal.Decimal("1")}
          field = fields.Dict(values=fields.Decimal)
          assert field.serialize("various_data", user) == {"foo": 1}
  
      def test_structured_dict_key_serialize(self, user):
          user.various_data = {1: "bar"}
          field = fields.Dict(keys=fields.Str)
          assert field.serialize("various_data", user) == {"1": "bar"}
  
      def test_structured_dict_key_value_serialize(self, user):
          user.various_data = {1: decimal.Decimal("1")}
          field = fields.Dict(keys=fields.Str, values=fields.Decimal)
          assert field.serialize("various_data", user) == {"1": 1}
  
      def test_url_field_serialize_none(self, user):
          user.homepage = None
          field = fields.Url()
          assert field.serialize("homepage", user) is None
  
      def test_method_field_with_method_missing(self):
          class BadSerializer(Schema):
              bad_field = fields.Method("invalid")
  
          with pytest.raises(AttributeError):
              BadSerializer()
  
      def test_method_field_passed_serialize_only_is_dump_only(self, user):
          field = fields.Method(serialize="method")
          assert field.dump_only is True
          assert field.load_only is False
  
      def test_method_field_passed_deserialize_only_is_load_only(self):
          field = fields.Method(deserialize="somemethod")
          assert field.load_only is True
          assert field.dump_only is False
  
      def test_method_field_with_uncallable_attribute(self):
          class BadSerializer(Schema):
              foo = "not callable"
              bad_field = fields.Method("foo")
  
          with pytest.raises(TypeError):
              BadSerializer()
  
      # https://github.com/marshmallow-code/marshmallow/issues/395
      def test_method_field_does_not_swallow_attribute_error(self):
          class MySchema(Schema):
              mfield = fields.Method("raise_error")
  
              def raise_error(self, obj):
                  raise AttributeError()
  
          with pytest.raises(AttributeError):
              MySchema().dump({})
  
      def test_method_with_no_serialize_is_missing(self):
          m = fields.Method()
          m.parent = Schema()
  
          assert m.serialize("", "", "") is missing_
  
      def test_serialize_with_data_key_param(self):
          class DumpToSchema(Schema):
              name = fields.String(data_key="NamE")
              years = fields.Integer(data_key="YearS")
  
          data = {"name": "Richard", "years": 11}
          result = DumpToSchema().dump(data)
          assert result == {"NamE": "Richard", "YearS": 11}
  
      def test_serialize_with_data_key_as_empty_string(self):
          class MySchema(Schema):
              name = fields.Field(data_key="")
  
          schema = MySchema()
          assert schema.dump({"name": "Grace"}) == {"": "Grace"}
  
      def test_serialize_with_attribute_and_data_key_uses_data_key(self):
          class ConfusedDumpToAndAttributeSerializer(Schema):
              name = fields.String(data_key="FullName")
              username = fields.String(attribute="uname", data_key="UserName")
              years = fields.Integer(attribute="le_wild_age", data_key="Years")
  
          data = {"name": "Mick", "uname": "mick_the_awesome", "le_wild_age": 999}
          result = ConfusedDumpToAndAttributeSerializer().dump(data)
  
          assert result == {
              "FullName": "Mick",
              "UserName": "mick_the_awesome",
              "Years": 999,
          }
  
      @pytest.mark.parametrize("fmt", ["rfc", "rfc822"])
      @pytest.mark.parametrize(
          ("value", "expected"),
          [
              (dt.datetime(2013, 11, 10, 1, 23, 45), "Sun, 10 Nov 2013 01:23:45 -0000"),
              (
                  dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=dt.timezone.utc),
                  "Sun, 10 Nov 2013 01:23:45 +0000",
              ),
              (
                  central.localize(dt.datetime(2013, 11, 10, 1, 23, 45), is_dst=False),
                  "Sun, 10 Nov 2013 01:23:45 -0600",
              ),
          ],
      )
      def test_datetime_field_rfc822(self, fmt, value, expected):
          field = fields.DateTime(format=fmt)
          assert field.serialize("d", {"d": value}) == expected
  
      @pytest.mark.parametrize("fmt", ["iso", "iso8601", None])
      @pytest.mark.parametrize(
          ("value", "expected"),
          [
              (dt.datetime(2013, 11, 10, 1, 23, 45), "2013-11-10T01:23:45"),
              (
                  dt.datetime(2013, 11, 10, 1, 23, 45, 123456, tzinfo=dt.timezone.utc),
                  "2013-11-10T01:23:45.123456+00:00",
              ),
              (
                  dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=dt.timezone.utc),
                  "2013-11-10T01:23:45+00:00",
              ),
              (
                  central.localize(dt.datetime(2013, 11, 10, 1, 23, 45), is_dst=False),
                  "2013-11-10T01:23:45-06:00",
              ),
          ],
      )
      def test_datetime_field_iso8601(self, fmt, value, expected):
          if fmt is None:
              # Test default is ISO
              field = fields.DateTime()
          else:
              field = fields.DateTime(format=fmt)
          assert field.serialize("d", {"d": value}) == expected
  
      def test_datetime_field_format(self, user):
          format = "%Y-%m-%d"
          field = fields.DateTime(format=format)
          assert field.serialize("created", user) == user.created.strftime(format)
  
      def test_string_field(self):
          field = fields.String()
          user = User(name=b"foo")
          assert field.serialize("name", user) == "foo"
          field = fields.String(allow_none=True)
          user.name = None
          assert field.serialize("name", user) is None
  
      def test_string_field_default_to_empty_string(self, user):
          field = fields.String(dump_default="")
          assert field.serialize("notfound", {}) == ""
  
      def test_time_field(self, user):
          field = fields.Time()
          expected = user.time_registered.isoformat()[:15]
          assert field.serialize("time_registered", user) == expected
  
          user.time_registered = None
          assert field.serialize("time_registered", user) is None
  
      @pytest.mark.parametrize("fmt", ["iso", "iso8601", None])
      @pytest.mark.parametrize(
          ("value", "expected"),
          [
              (dt.time(1, 23, 45), "01:23:45"),
              (dt.time(1, 23, 45, 123000), "01:23:45.123000"),
              (dt.time(1, 23, 45, 123456), "01:23:45.123456"),
          ],
      )
      def test_time_field_iso8601(self, fmt, value, expected):
          if fmt is None:
              # Test default is ISO
              field = fields.Time()
          else:
              field = fields.Time(format=fmt)
          assert field.serialize("d", {"d": value}) == expected
  
      def test_time_field_format(self, user):
          fmt = "%H:%M:%S"
          field = fields.Time(format=fmt)
          assert field.serialize("birthtime", user) == user.birthtime.strftime(fmt)
  
      def test_date_field(self, user):
          field = fields.Date()
          assert field.serialize("birthdate", user) == user.birthdate.isoformat()
  
          user.birthdate = None
          assert field.serialize("birthdate", user) is None
  
      def test_timedelta_field(self, user):
          user.d1 = dt.timedelta(days=1, seconds=1, microseconds=1)
          user.d2 = dt.timedelta(days=0, seconds=86401, microseconds=1)
          user.d3 = dt.timedelta(days=0, seconds=0, microseconds=86401000001)
          user.d4 = dt.timedelta(days=0, seconds=0, microseconds=0)
          user.d5 = dt.timedelta(days=-1, seconds=0, microseconds=0)
          user.d6 = dt.timedelta(
              days=1,
              seconds=1,
              microseconds=1,
              milliseconds=1,
              minutes=1,
              hours=1,
              weeks=1,
          )
  
          field = fields.TimeDelta(fields.TimeDelta.DAYS)
          assert field.serialize("d1", user) == 1
          field = fields.TimeDelta(fields.TimeDelta.SECONDS)
          assert field.serialize("d1", user) == 86401
          field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)
          assert field.serialize("d1", user) == 86401000001
          field = fields.TimeDelta(fields.TimeDelta.HOURS)
          assert field.serialize("d1", user) == 24
  
          field = fields.TimeDelta(fields.TimeDelta.DAYS)
          assert field.serialize("d2", user) == 1
          field = fields.TimeDelta(fields.TimeDelta.SECONDS)
          assert field.serialize("d2", user) == 86401
          field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)
          assert field.serialize("d2", user) == 86401000001
  
          field = fields.TimeDelta(fields.TimeDelta.DAYS)
          assert field.serialize("d3", user) == 1
          field = fields.TimeDelta(fields.TimeDelta.SECONDS)
          assert field.serialize("d3", user) == 86401
          field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)
          assert field.serialize("d3", user) == 86401000001
  
          field = fields.TimeDelta(fields.TimeDelta.DAYS)
          assert field.serialize("d4", user) == 0
          field = fields.TimeDelta(fields.TimeDelta.SECONDS)
          assert field.serialize("d4", user) == 0
          field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)
          assert field.serialize("d4", user) == 0
  
          field = fields.TimeDelta(fields.TimeDelta.DAYS)
          assert field.serialize("d5", user) == -1
          field = fields.TimeDelta(fields.TimeDelta.SECONDS)
          assert field.serialize("d5", user) == -86400
          field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)
          assert field.serialize("d5", user) == -86400000000
  
          field = fields.TimeDelta(fields.TimeDelta.WEEKS)
          assert field.serialize("d6", user) == 1
          field = fields.TimeDelta(fields.TimeDelta.DAYS)
          assert field.serialize("d6", user) == 7 + 1
          field = fields.TimeDelta(fields.TimeDelta.HOURS)
          assert field.serialize("d6", user) == 7 * 24 + 24 + 1
          field = fields.TimeDelta(fields.TimeDelta.MINUTES)
          assert field.serialize("d6", user) == 7 * 24 * 60 + 24 * 60 + 60 + 1
          d6_seconds = (
              7 * 24 * 60 * 60
              + 24 * 60 * 60  # 1 week
              + 60 * 60  # 1 day
              + 60  # 1 hour
              + 1  # 1 minute
          )
          field = fields.TimeDelta(fields.TimeDelta.SECONDS)
          assert field.serialize("d6", user) == d6_seconds
          field = fields.TimeDelta(fields.TimeDelta.MILLISECONDS)
          assert field.serialize("d6", user) == d6_seconds * 1000 + 1
          field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)
          assert field.serialize("d6", user) == d6_seconds * 10**6 + 1000 + 1
  
          user.d7 = None
          assert field.serialize("d7", user) is None
  
          # https://github.com/marshmallow-code/marshmallow/issues/1856
          user.d8 = dt.timedelta(milliseconds=345)
          field = fields.TimeDelta(fields.TimeDelta.MILLISECONDS)
          assert field.serialize("d8", user) == 345
  
          user.d9 = dt.timedelta(milliseconds=1999)
          field = fields.TimeDelta(fields.TimeDelta.SECONDS)
          assert field.serialize("d9", user) == 1
  
      def test_datetime_list_field(self):
          obj = DateTimeList([dt.datetime.utcnow(), dt.datetime.now()])
          field = fields.List(fields.DateTime)
          result = field.serialize("dtimes", obj)
          assert all(type(each) == str for each in result)
  
      def test_list_field_serialize_none_returns_none(self):
          obj = DateTimeList(None)
          field = fields.List(fields.DateTime)
          assert field.serialize("dtimes", obj) is None
  
      def test_list_field_work_with_generator_single_value(self):
          def custom_generator():
              yield dt.datetime.utcnow()
  
          obj = DateTimeList(custom_generator())
          field = fields.List(fields.DateTime)
          result = field.serialize("dtimes", obj)
          assert len(result) == 1
  
      def test_list_field_work_with_generators_multiple_values(self):
          def custom_generator():
              yield from [dt.datetime.utcnow(), dt.datetime.now()]
  
          obj = DateTimeList(custom_generator())
          field = fields.List(fields.DateTime)
          result = field.serialize("dtimes", obj)
          assert len(result) == 2
  
      def test_list_field_work_with_generators_empty_generator_returns_none_for_every_non_returning_yield_statement(  # noqa: B950
          self,
      ):
          def custom_generator():
              yield
              yield
  
          obj = DateTimeList(custom_generator())
          field = fields.List(fields.DateTime, allow_none=True)
          result = field.serialize("dtimes", obj)
          assert len(result) == 2
          assert result[0] is None
          assert result[1] is None
  
      def test_list_field_work_with_set(self):
          custom_set = {1, 2, 3}
          obj = IntegerList(custom_set)
          field = fields.List(fields.Int)
          result = field.serialize("ints", obj)
          assert len(result) == 3
          assert 1 in result
          assert 2 in result
          assert 3 in result
  
      def test_list_field_work_with_custom_class_with_iterator_protocol(self):
          class IteratorSupportingClass:
              def __init__(self, iterable):
                  self.iterable = iterable
  
              def __iter__(self):
                  return iter(self.iterable)
  
          ints = IteratorSupportingClass([1, 2, 3])
          obj = IntegerList(ints)
          field = fields.List(fields.Int)
          result = field.serialize("ints", obj)
          assert len(result) == 3
          assert result[0] == 1
          assert result[1] == 2
          assert result[2] == 3
  
      def test_bad_list_field(self):
          class ASchema(Schema):
              id = fields.Int()
  
          with pytest.raises(ValueError):
              fields.List("string")
          expected_msg = (
              "The list elements must be a subclass or instance of "
              "marshmallow.base.FieldABC"
          )
          with pytest.raises(ValueError, match=expected_msg):
              fields.List(ASchema)
  
      def test_datetime_integer_tuple_field(self):
          obj = DateTimeIntegerTuple((dt.datetime.utcnow(), 42))
          field = fields.Tuple([fields.DateTime, fields.Integer])
          result = field.serialize("dtime_int", obj)
          assert type(result[0]) == str
          assert type(result[1]) == int
  
      def test_tuple_field_serialize_none_returns_none(self):
          obj = DateTimeIntegerTuple(None)
          field = fields.Tuple([fields.DateTime, fields.Integer])
          assert field.serialize("dtime_int", obj) is None
  
      def test_bad_tuple_field(self):
          class ASchema(Schema):
              id = fields.Int()
  
          with pytest.raises(ValueError):
              fields.Tuple(["string"])
          with pytest.raises(ValueError):
              fields.Tuple(fields.String)
          expected_msg = (
              'Elements of "tuple_fields" must be subclasses or '
              "instances of marshmallow.base.FieldABC."
          )
          with pytest.raises(ValueError, match=expected_msg):
              fields.Tuple([ASchema])
  
      def test_serialize_does_not_apply_validators(self, user):
          field = fields.Field(validate=lambda x: False)
          # No validation error raised
          assert field.serialize("age", user) == user.age
  
      def test_constant_field_serialization(self, user):
          field = fields.Constant("something")
          assert field.serialize("whatever", user) == "something"
  
      def test_constant_is_always_included_in_serialized_data(self):
          class MySchema(Schema):
              foo = fields.Constant(42)
  
          sch = MySchema()
          assert sch.dump({"bar": 24})["foo"] == 42
          assert sch.dump({"foo": 24})["foo"] == 42
  
      def test_constant_field_serialize_when_omitted(self):
          class MiniUserSchema(Schema):
              name = fields.Constant("bill")
  
          s = MiniUserSchema()
          assert s.dump({})["name"] == "bill"
  
      @pytest.mark.parametrize("FieldClass", ALL_FIELDS)
      def test_all_fields_serialize_none_to_none(self, FieldClass):
          field = FieldClass(allow_none=True)
          res = field.serialize("foo", {"foo": None})
          assert res is None
  
  
  class TestSchemaSerialization:
      def test_serialize_with_missing_param_value(self):
          class AliasingUserSerializer(Schema):
              name = fields.String()
              birthdate = fields.DateTime(dump_default=dt.datetime(2017, 9, 29))
  
          data = {"name": "Mick"}
          result = AliasingUserSerializer().dump(data)
          assert result["name"] == "Mick"
          assert result["birthdate"] == "2017-09-29T00:00:00"
  
      def test_serialize_with_missing_param_callable(self):
          class AliasingUserSerializer(Schema):
              name = fields.String()
              birthdate = fields.DateTime(dump_default=lambda: dt.datetime(2017, 9, 29))
  
          data = {"name": "Mick"}
          result = AliasingUserSerializer().dump(data)
          assert result["name"] == "Mick"
          assert result["birthdate"] == "2017-09-29T00:00:00"
  
  
  def test_serializing_named_tuple():
      Point = namedtuple("Point", ["x", "y"])
  
      field = fields.Field()
  
      p = Point(x=4, y=2)
  
      assert field.serialize("x", p) == 4
  
  
  def test_serializing_named_tuple_with_meta():
      Point = namedtuple("Point", ["x", "y"])
      p = Point(x=4, y=2)
  
      class PointSerializer(Schema):
          class Meta:
              fields = ("x", "y")
  
      serialized = PointSerializer().dump(p)
      assert serialized["x"] == 4
      assert serialized["y"] == 2
  
  
  def test_serializing_slice():
      values = [{"value": value} for value in range(5)]
      slice = itertools.islice(values, None)
  
      class ValueSchema(Schema):
          value = fields.Int()
  
      serialized = ValueSchema(many=True).dump(slice)
      assert serialized == values
  
  
  # https://github.com/marshmallow-code/marshmallow/issues/1163
  def test_nested_field_many_serializing_generator():
      class MySchema(Schema):
          name = fields.Str()
  
      class OtherSchema(Schema):
          objects = fields.Nested(MySchema, many=True)
  
      def gen():
          yield {"name": "foo"}
          yield {"name": "bar"}
  
      obj = {"objects": gen()}
      data = OtherSchema().dump(obj)
  
      assert data.get("objects") == [{"name": "foo"}, {"name": "bar"}]
  