Repository: d0c-s4vage/lookatme

Issue:
Default styles aren't quite working
**Describe the bug**
A clear and concise description of what the bug is.

#116 made lookatme compatible with the latest version of marshmallow, but it  broke some of the default styles from loading correctly. This is most noticeable with the margin and padding values.

**To Reproduce**

Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Environment (please complete the following information):**
 - OS: [e.g. iOS]
 - Lookatme Version [e.g. `lookatme --version`]

**Additional context**
Add any other context about the problem here.


Discussion:

Patch:
diff --git a/lookatme/contrib/file_loader.py b/lookatme/contrib/file_loader.py
index c9bd704..b897a49 100644
--- a/lookatme/contrib/file_loader.py
+++ b/lookatme/contrib/file_loader.py
@@ -46,8 +46,8 @@ class FileSchema(Schema):
     transform = fields.Str(default=None, missing=None)
     lines = fields.Nested(
         LineRange,
-        default=LineRange().dump({}),
-        missing=LineRange().dump({})
+        default=LineRange().dump(None),
+        missing=LineRange().dump(None)
     )
 
     class Meta:
diff --git a/lookatme/schemas.py b/lookatme/schemas.py
index 8c168f1..cbabd94 100644
--- a/lookatme/schemas.py
+++ b/lookatme/schemas.py
@@ -193,12 +193,12 @@ class StyleSchema(Schema):
         "right": 10,
     })
 
-    headings = fields.Nested(HeadingsSchema, default=HeadingsSchema().dump({}))
-    bullets = fields.Nested(BulletsSchema, default=BulletsSchema().dump({}))
-    numbering = fields.Nested(NumberingSchema, default=NumberingSchema().dump({}))
-    table = fields.Nested(TableSchema, default=TableSchema().dump({}))
-    quote = fields.Nested(BlockQuoteSchema, default=BlockQuoteSchema().dump({}))
-    hrule = fields.Nested(HruleSchema, default=HruleSchema().dump({}))
+    headings = fields.Nested(HeadingsSchema, default=HeadingsSchema().dump(None))
+    bullets = fields.Nested(BulletsSchema, default=BulletsSchema().dump(None))
+    numbering = fields.Nested(NumberingSchema, default=NumberingSchema().dump(None))
+    table = fields.Nested(TableSchema, default=TableSchema().dump(None))
+    quote = fields.Nested(BlockQuoteSchema, default=BlockQuoteSchema().dump(None))
+    hrule = fields.Nested(HruleSchema, default=HruleSchema().dump(None))
     link = fields.Nested(StyleFieldSchema, default={
         "fg": "#33c,underline",
         "bg": "default",
@@ -217,5 +217,9 @@ class MetaSchema(Schema):
         missing=datetime.datetime.now(),
     )
     author = fields.Str(default="", missing="")
-    styles = fields.Nested(StyleSchema, default={}, missing={})
-    extensions = fields.List(fields.Str(), default=[], missing={})
+    styles = fields.Nested(
+        StyleSchema,
+        default=StyleSchema().dump(None),
+        missing=StyleSchema().dump(None),
+    )
+    extensions = fields.List(fields.Str(), default=[], missing=[])
diff --git a/lookatme/themes/__init__.py b/lookatme/themes/__init__.py
index 6e23ec1..a7bc30a 100644
--- a/lookatme/themes/__init__.py
+++ b/lookatme/themes/__init__.py
@@ -14,6 +14,6 @@ from lookatme.utils import dict_deep_update
 def ensure_defaults(mod):
     """Ensure that all required attributes exist within the provided module
     """
-    defaults = StyleSchema().dump(StyleSchema())
+    defaults = StyleSchema().dump(None)
     dict_deep_update(defaults, mod.theme)
     return defaults


Test patch:
diff --git a/tests/test_schemas.py b/tests/test_schemas.py
index 1136364..1dc52fc 100644
--- a/tests/test_schemas.py
+++ b/tests/test_schemas.py
@@ -3,6 +3,11 @@ Test tha lookatme YAML schemas behave as expected
 """
 
 
+import datetime
+from marshmallow import fields, Schema
+import pytest
+
+
 from lookatme.schemas import *
 
 
@@ -24,3 +29,53 @@ date: {date}
     assert schema["date"].year == 2019
     assert schema["date"].month == 1
     assert schema["date"].day == 1
+
+
+def _validate_field_recursive(path, field, gend_value):
+    """Only validate the leaf nodes - we want *specific* values that have
+    changed!
+    """
+    if isinstance(field, Schema):
+        for field_name, sub_field in field.fields.items():
+            _validate_field_recursive(path + "." + field_name, sub_field, gend_value[field_name])
+    elif isinstance(field, fields.Nested):
+        if field.default is None:
+            nested_field = field.nested()
+            _validate_field_recursive(path, nested_field, gend_value)
+        else:
+            assert field.default == gend_value, f"Default value not correct at {path}"
+    elif isinstance(field, fields.Field):
+        if isinstance(field.default, datetime.datetime):
+            return
+        assert field.default == gend_value, f"Default value not correct at {path}"
+
+
+def test_sanity_check_that_errors_are_detected():
+    """Perform a sanity check that we can actually catch errors in generating
+    the default schema values.
+    """
+    schema = MetaSchema()
+
+    # force a discrepancy in the 
+    gend_default = MetaSchema().dump(None)
+    gend_default["styles"]["padding"]["left"] = 100
+
+    with pytest.raises(AssertionError) as excinfo:
+        _validate_field_recursive("__root__.styles", schema.styles.nested(), gend_default['styles'])
+    assert "Default value not correct at __root__.styles.padding" in str(excinfo)
+
+
+def test_styles_defaults():
+    """Ensure that style value defaults are generated correctly
+    """
+    schema = MetaSchema()
+    gend_default = MetaSchema().dump(None)
+    _validate_field_recursive("__root__.styles", schema.styles.nested(), gend_default['styles'])
+
+
+def test_meta_defaults():
+    """Test that the default values in the schema are actually used
+    """
+    schema = MetaSchema()
+    gend_default = MetaSchema().dump(None)
+    _validate_field_recursive("__root__", schema, gend_default)