text: import pytest
  
  from marshmallow import fields, Schema, ValidationError, EXCLUDE, INCLUDE, RAISE, missing
  from marshmallow.exceptions import StringNotCollectionError
  
  from tests.base import ALL_FIELDS
  
  
  @pytest.mark.parametrize(
      ('alias', 'field'),
      [
          (fields.Int, fields.Integer),
          (fields.Str, fields.String),
          (fields.Bool, fields.Boolean),
          (fields.URL, fields.Url),
      ],
  )
  def test_field_aliases(alias, field):
      assert alias is field
  
  
  class TestField:
  
      def test_repr(self):
          default = 'œ∑´'
          field = fields.Field(default=default, attribute=None)
          assert repr(field) == (
              '<fields.Field(default={0!r}, attribute=None, '
              'validate=None, required=False, '
              'load_only=False, dump_only=False, '
              'missing={missing}, allow_none=False, '
              'error_messages={error_messages})>'
              .format(
                  default, missing=missing,
                  error_messages=field.error_messages,
              )
          )
          int_field = fields.Integer(validate=lambda x: True)
          assert '<fields.Integer' in repr(int_field)
  
      def test_error_raised_if_uncallable_validator_passed(self):
          with pytest.raises(ValueError, match='must be a callable'):
              fields.Field(validate='notcallable')
  
      def test_error_raised_if_missing_is_set_on_required_field(self):
          with pytest.raises(ValueError, match="'missing' must not be set for required fields"):
              fields.Field(required=True, missing=42)
  
      def test_custom_field_receives_attr_and_obj(self):
          class MyField(fields.Field):
              def _deserialize(self, val, attr, data):
                  assert attr == 'name'
                  assert data['foo'] == 42
                  return val
  
          class MySchema(Schema):
              name = MyField()
  
          result = MySchema(unknown=EXCLUDE).load({'name': 'Monty', 'foo': 42})
          assert result == {'name': 'Monty'}
  
      def test_custom_field_receives_data_key_if_set(self):
          class MyField(fields.Field):
              def _deserialize(self, val, attr, data):
                  assert attr == 'name'
                  assert data['foo'] == 42
                  return val
  
          class MySchema(Schema):
              Name = MyField(data_key='name')
  
          result = MySchema(unknown=EXCLUDE).load({'name': 'Monty', 'foo': 42})
          assert result == {'Name': 'Monty'}
  
      def test_custom_field_follows_data_key_if_set(self):
          class MyField(fields.Field):
              def _serialize(self, val, attr, data):
                  assert attr == 'name'
                  assert data['foo'] == 42
                  return val
  
          class MySchema(Schema):
              name = MyField(data_key='_NaMe')
  
          result = MySchema().dump({'name': 'Monty', 'foo': 42})
          assert result == {'_NaMe': 'Monty'}
  
      def test_number_fields_prohbits_boolean(self):
          strict_field = fields.Float()
          with pytest.raises(ValidationError) as excinfo:
              strict_field.serialize('value', {'value': False})
          assert excinfo.value.args[0] == 'Not a valid number.'
          with pytest.raises(ValidationError) as excinfo:
              strict_field.serialize('value', {'value': True})
          assert excinfo.value.args[0] == 'Not a valid number.'
  
  class TestParentAndName:
      class MySchema(Schema):
          foo = fields.Field()
          bar = fields.List(fields.Str())
          baz = fields.Tuple([fields.Str(), fields.Int()])
  
      @pytest.fixture()
      def schema(self):
          return self.MySchema()
  
      def test_simple_field_parent_and_name(self, schema):
          assert schema.fields['foo'].parent == schema
          assert schema.fields['foo'].name == 'foo'
          assert schema.fields['bar'].parent == schema
          assert schema.fields['bar'].name == 'bar'
  
      # https://github.com/marshmallow-code/marshmallow/pull/572#issuecomment-275800288
      def test_unbound_field_root_returns_none(self):
          field = fields.Str()
          assert field.root is None
  
          inner_field = fields.Nested(self.MySchema())
          outer_field = fields.List(inner_field)
  
          assert outer_field.root is None
          assert inner_field.root is None
  
      def test_list_field_inner_parent_and_name(self, schema):
          assert schema.fields['bar'].container.parent == schema.fields['bar']
          assert schema.fields['bar'].container.name == 'bar'
  
      def test_tuple_field_inner_parent_and_name(self, schema):
          for container in schema.fields['baz'].tuple_fields:
              assert container.parent == schema.fields['baz']
              assert container.name == 'baz'
  
      def test_simple_field_root(self, schema):
          assert schema.fields['foo'].root == schema
          assert schema.fields['bar'].root == schema
  
      def test_list_field_inner_root(self, schema):
          assert schema.fields['bar'].container.root == schema
  
      def test_tuple_field_inner_root(self, schema):
          for container in schema.fields['baz'].tuple_fields:
              assert container.root == schema
  
      def test_list_root_inheritance(self, schema):
          class OtherSchema(TestParentAndName.MySchema):
              pass
  
          schema2 = OtherSchema()
          assert schema.fields['bar'].container.root == schema
          assert schema2.fields['bar'].container.root == schema2
  
      def test_dict_root_inheritance(self):
          class MySchema(Schema):
              foo = fields.Dict(keys=fields.Str(), values=fields.Int())
  
          class OtherSchema(MySchema):
              pass
  
          schema = MySchema()
          schema2 = OtherSchema()
          assert schema.fields['foo'].key_container.root == schema
          assert schema.fields['foo'].value_container.root == schema
          assert schema2.fields['foo'].key_container.root == schema2
          assert schema2.fields['foo'].value_container.root == schema2
  
  
  class TestMetadata:
  
      @pytest.mark.parametrize('FieldClass', ALL_FIELDS)
      def test_extra_metadata_may_be_added_to_field(self, FieldClass):  # noqa
          field = FieldClass(description='Just a normal field.')
          assert field.metadata['description'] == 'Just a normal field.'
          field = FieldClass(
              required=True, default=None, validate=lambda v: True,
              description='foo', widget='select',
          )
          assert field.metadata == {'description': 'foo', 'widget': 'select'}
  
  
  class TestErrorMessages:
  
      class MyField(fields.Field):
          default_error_messages = {
              'custom': 'Custom error message.',
          }
  
      def test_default_error_messages_get_merged_with_parent_error_messages_cstm_msg(self):
          field = self.MyField()
          assert field.error_messages['custom'] == 'Custom error message.'
          assert 'required' in field.error_messages
  
      def test_default_error_messages_get_merged_with_parent_error_messages(self):
          field = self.MyField(error_messages={'passed': 'Passed error message'})
          assert field.error_messages['passed'] == 'Passed error message'
  
      def test_fail(self):
          field = self.MyField()
  
          with pytest.raises(ValidationError) as excinfo:
              field.fail('required')
          assert excinfo.value.args[0] == 'Missing data for required field.'
  
          with pytest.raises(ValidationError) as excinfo:
              field.fail('null')
          assert excinfo.value.args[0] == 'Field may not be null.'
  
          with pytest.raises(ValidationError) as excinfo:
              field.fail('custom')
          assert excinfo.value.args[0] == 'Custom error message.'
  
          with pytest.raises(ValidationError) as excinfo:
              field.fail('validator_failed')
          assert excinfo.value.args[0] == 'Invalid value.'
  
          with pytest.raises(AssertionError) as excinfo:
              field.fail('doesntexist')
  
          assert 'doesntexist' in excinfo.value.args[0]
          assert 'MyField' in excinfo.value.args[0]
  
  
  class TestNestedField:
  
      @pytest.mark.parametrize('param', ('only', 'exclude'))
      def test_nested_only_and_exclude_as_string(self, param):
          with pytest.raises(StringNotCollectionError):
              fields.Nested(Schema, **{param: 'foo'})
  
      @pytest.mark.parametrize('schema_unknown', (EXCLUDE, INCLUDE, RAISE))
      @pytest.mark.parametrize('field_unknown', (None, EXCLUDE, INCLUDE, RAISE))
      def test_nested_unknown_override(self, schema_unknown, field_unknown):
          class NestedSchema(Schema):
              class Meta:
                  unknown = schema_unknown
  
          class MySchema(Schema):
              nested = fields.Nested(NestedSchema, unknown=field_unknown)
  
          if field_unknown == EXCLUDE or (schema_unknown == EXCLUDE and not field_unknown):
              assert MySchema().load({'nested': {'x': 1}}) == {'nested': {}}
          elif field_unknown == INCLUDE or (schema_unknown == INCLUDE and not field_unknown):
              assert MySchema().load({'nested': {'x': 1}}) == {'nested': {'x': 1}}
          elif field_unknown == RAISE or (schema_unknown == RAISE and not field_unknown):
              with pytest.raises(ValidationError):
                  MySchema().load({'nested': {'x': 1}})
  