Repository: encode/typesystem

Issue:
Callable defaults
Eg.

```python
class Something(typesystem.Schema):
    created = typesystem.DateTime(default=datetime.datetime.now)
    ...
```

Discussion:

Patch:
diff --git a/typesystem/fields.py b/typesystem/fields.py
index 90716ef..266177c 100644
--- a/typesystem/fields.py
+++ b/typesystem/fields.py
@@ -63,6 +63,12 @@ class Field:
     def has_default(self) -> bool:
         return hasattr(self, "default")
 
+    def get_default_value(self) -> typing.Any:
+        default = getattr(self, "default", None)
+        if callable(default):
+            return default()
+        return default
+
     def error(self, code: str) -> ValidationError:
         text = self.errors[code].format(**self.__dict__)
         return ValidationError(text=text, code=code)
@@ -423,7 +429,7 @@ class Object(Field):
         for key, child_schema in self.properties.items():
             if key not in value:
                 if child_schema.has_default():
-                    validated[key] = child_schema.default
+                    validated[key] = child_schema.get_default_value()
                 continue
             item = value[key]
             child_value, error = child_schema.validate(item, strict=strict)
diff --git a/typesystem/schemas.py b/typesystem/schemas.py
index 6cb847c..fe2f873 100644
--- a/typesystem/schemas.py
+++ b/typesystem/schemas.py
@@ -68,7 +68,7 @@ class Schema(Mapping, metaclass=SchemaMetaclass):
                     raise TypeError(message)
                 setattr(self, key, value)
             elif schema.has_default():
-                setattr(self, key, schema.default)
+                setattr(self, key, schema.get_default_value())
 
         if kwargs:
             key = list(kwargs.keys())[0]


Test patch:
diff --git a/tests/test_schemas.py b/tests/test_schemas.py
index c4e2ecc..202af7b 100644
--- a/tests/test_schemas.py
+++ b/tests/test_schemas.py
@@ -125,3 +125,12 @@ def test_schema_decimal_serialization():
 
     assert item.price == decimal.Decimal("123.45")
     assert item["price"] == 123.45
+
+
+def test_schema_with_callable_default():
+    class Example(typesystem.Schema):
+        created = typesystem.Date(default=datetime.date.today)
+
+    value, error = Example.validate({})
+    print(value)
+    assert value.created == datetime.date.today()