Repository: lovasoa/marshmallow_dataclass

Issue:
`base_schema` of nested dataclasses is ingored
The base_schema of the nested field is ignored.

## Example:
```py
from marshmallow import Schema, post_dump
from marshmallow_dataclass import dataclass


class DoubleSchema(Schema):
    @post_dump
    def double(self, data, **kwargs):
        return dict(double=data['number'] * 2)


@dataclass(base_schema=DoubleSchema)
class A:
    number: int


@dataclass
class B:
    a: A


print('is A.Schema correct?', issubclass(A.Schema, DoubleSchema))
print('is B.a.Schema correct?', isinstance(B.Schema._declared_fields['a'].schema, DoubleSchema))
print()

print('expected:')
print("    {'a': {'double': 2}}")
print('actual:')
print('   ', B.Schema().dump(B(A(1))))

```
stdout:
```
is A.Schema correct? True
is B.a.Schema correct? False

expected:
    {'a': {'double': 2}}
actual:
    {'a': {'number': 1}}
```

## How to fix
```diff
--- marshmallow_dataclass/__init__.py   2019-11-25 14:59:36.146392038 +0200
+++ marshmallow_dataclass/__init__.py.fixed     2019-11-25 15:01:01.947898497 +0200
@@ -422,9 +422,12 @@ def field_for_schema(
 
+    # Nested marshmellow dataclass
+    nested_schema = getattr(typ, 'Schema', None)
+
     # Nested dataclasses
     forward_reference = getattr(typ, "__forward_arg__", None)
-    nested = forward_reference or class_schema(typ, base_schema=base_schema)
+    nested = nested_schema or forward_reference or class_schema(typ, base_schema=base_schema)
     return marshmallow.fields.Nested(nested, **metadata)

```

Comments:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 982f4eb..ffe5fdc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # marshmallow_dataclass change log
 
+## v7.1.1
+ - Fix behavior when `base_schema` is passed to a nested dataclass/schema
+   ([#52](https://github.com/lovasoa/marshmallow_dataclass/issues/52)).
+   Thanks [@ADR-007-SoftServe](https://github.com/ADR-007-SoftServe)
+   for the catch and patch.
+
 ## v7.1.0
  - Improved documentation
  - The library now has more unit tests
diff --git a/marshmallow_dataclass/__init__.py b/marshmallow_dataclass/__init__.py
index a9b3119..a2dd954 100644
--- a/marshmallow_dataclass/__init__.py
+++ b/marshmallow_dataclass/__init__.py
@@ -117,7 +117,7 @@ def add_schema(_cls: Type[_U]) -> Type[_U]:
 
 @overload
 def add_schema(
-    base_schema: Type[marshmallow.Schema] = None
+    base_schema: Type[marshmallow.Schema] = None,
 ) -> Callable[[Type[_U]], Type[_U]]:
     ...
 
@@ -422,9 +422,15 @@ def field_for_schema(
 
         return marshmallow_enum.EnumField(typ, **metadata)
 
+    # Nested marshmallow dataclass
+    nested_schema = getattr(typ, "Schema", None)
+
     # Nested dataclasses
     forward_reference = getattr(typ, "__forward_arg__", None)
-    nested = forward_reference or class_schema(typ, base_schema=base_schema)
+    nested = (
+        nested_schema or forward_reference or class_schema(typ, base_schema=base_schema)
+    )
+
     return marshmallow.fields.Nested(nested, **metadata)
 
 


Test patch:
diff --git a/tests/test_field_for_schema.py b/tests/test_field_for_schema.py
index 4d8b0a0..8f356e9 100644
--- a/tests/test_field_for_schema.py
+++ b/tests/test_field_for_schema.py
@@ -1,11 +1,12 @@
+import inspect
 import typing
 import unittest
 from enum import Enum
 from typing import Dict, Optional, Union, Any
 
-from marshmallow import fields
+from marshmallow import fields, Schema
 
-from marshmallow_dataclass import field_for_schema
+from marshmallow_dataclass import field_for_schema, dataclass
 
 
 class TestFieldForSchema(unittest.TestCase):
@@ -13,7 +14,11 @@ class TestFieldForSchema(unittest.TestCase):
         self.assertEqual(a.__class__, b.__class__, "field class")
 
         def attrs(x):
-            return {k: repr(v) for k, v in x.__dict__.items() if not k.startswith("_")}
+            return {
+                k: f"{v!r} ({v.__mro__!r})" if inspect.isclass(v) else repr(v)
+                for k, v in x.__dict__.items()
+                if not k.startswith("_")
+            }
 
         self.assertEqual(attrs(a), attrs(b))
 
@@ -97,6 +102,19 @@ class TestFieldForSchema(unittest.TestCase):
             fields.Integer(required=False, description="UserId", default=0, missing=0),
         )
 
+    def test_marshmallow_dataclass(self):
+        class NewSchema(Schema):
+            pass
+
+        @dataclass(base_schema=NewSchema)
+        class NewDataclass:
+            pass
+
+        self.assertFieldsEqual(
+            field_for_schema(NewDataclass, metadata=dict(required=False)),
+            fields.Nested(NewDataclass.Schema),
+        )
+
 
 if __name__ == "__main__":
     unittest.main()