Repository: iterait/apistrap

Issue:
Handle schematics type subclasses correctly
e.g. `class NonNanFloatType(FloatType)` is converted to string (should be float). https://github.com/iterait/apistrap/blob/dev/apistrap/schematics_converters.py#L69

Discussion:

Patch:
diff --git a/apistrap/schematics_converters.py b/apistrap/schematics_converters.py
index 030d697..049cc6d 100644
--- a/apistrap/schematics_converters.py
+++ b/apistrap/schematics_converters.py
@@ -1,4 +1,5 @@
 from typing import Type, Generator, Dict, Any
+from inspect import getmro
 
 from schematics import Model
 from schematics.types.base import (BaseType, NumberType, IntType, LongType, FloatType,
@@ -61,12 +62,22 @@ SCHEMATICS_OPTIONS_TO_JSON_SCHEMA = {
     'regex': 'pattern',
     'min_value': 'minimum',
     'max_value': 'maximum',
+    'min_size': 'minItems',
+    'max_size': 'maxItems'
 }
 
 
+def _get_field_type(field: BaseType):
+    for cls in getmro(field.__class__):
+        if cls in SCHEMATICS_TYPE_TO_JSON_TYPE.keys():
+            return SCHEMATICS_TYPE_TO_JSON_TYPE[cls]
+
+    return 'string'
+
+
 def _primitive_field_to_schema_object(field: BaseType) -> Dict[str, str]:
     schema = {
-        "type": SCHEMATICS_TYPE_TO_JSON_TYPE.get(field.__class__, 'string')
+        "type": _get_field_type(field)
     }
 
     for schematics_attr, json_schema_attr in SCHEMATICS_OPTIONS_TO_JSON_SCHEMA.items():


Test patch:
diff --git a/tests/test_field_subtyping.py b/tests/test_field_subtyping.py
new file mode 100644
index 0000000..e30d2f6
--- /dev/null
+++ b/tests/test_field_subtyping.py
@@ -0,0 +1,45 @@
+import pytest
+from flask import jsonify
+
+from schematics import Model
+from schematics.types import IntType
+
+
+def extract_definition_name(definition_spec: str):
+    return definition_spec.split("/")[-1]
+
+
+class CustomType(IntType):
+    pass
+
+
+class RequestModel(Model):
+    field = CustomType(required=True)
+
+
+@pytest.fixture()
+def app_with_accepts(app, swagger):
+    @app.route("/", methods=["POST"])
+    @swagger.autodoc()
+    @swagger.accepts(RequestModel)
+    def view(req: RequestModel):
+        return jsonify()
+
+
+def test_int_subtype(client, app_with_accepts):
+    spec = client.get("/swagger.json").json
+    path = spec["paths"]["/"]["post"]
+    body = next(filter(lambda item: item["in"] == "body", path["parameters"]), None)
+    assert body is not None
+
+    ref = extract_definition_name(body["schema"]["$ref"])
+    assert spec["definitions"][ref] == {
+        "title": RequestModel.__name__,
+        "type": "object",
+        "properties": {
+            "field": {
+                "type": "integer"
+            }
+        },
+        "required": ["field"]
+    }