Repository: omni-us/jsonargparse

Issue:
'builtins.type' type hint is not parsed properly
### Setup to reproduce the issue:
Within module _**my_module**_:

_**a.py**_:
```
class A:
    def __init__(self, a: int = 10):
        self.a = a
```

_**b.py**_:
```
from jsonargparse import ArgumentParser
from my_module.a import A


class B:
    def __init__(self, cls: type = A):
        self.o = cls(10)


if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_class_arguments(B, 'B')
    config = parser.parse_args()
    init = parser.instantiate_classes(config)
```

Run command:
`python b.py --B.cls my_module.a.A`

### Current behavior:
Exits with:
```
usage: b.py [-h] [--B.cls CLS]
b.py: error: Parser key "B.cls": 'NoneType' object is not subscriptable
```

### Expected behavior
When using `typing.Type` type hint it works as expected and no errors are thrown. With `builtins.type` (as in example above) it works only when parametrized (`type[A]`). I think behavior with `builtins.type` and `typing.Type`  should be consistent and example code should not crash.

Probably the issue goes deeper than this example and is caused by changes introduced in Python 3.9 [(Generic Alias Type)](https://docs.python.org/3/library/stdtypes.html#types-genericalias), but I have not experienced any problems with other types (e.g. `list`, `dict`, etc.)

Comments:

Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5fae308..e58e0d9 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -17,6 +17,10 @@ Added
 - Support for parsing ``Mapping`` and ``MutableMapping`` types.
 - Support for parsing ``frozenset``, ``MutableSequence`` and ``MutableSet`` types.
 
+Changed
+^^^^^^^
+- Docstrings no longer supported for python 3.5.
+
 
 v3.17.0 (2021-07-19)
 --------------------
diff --git a/jsonargparse/typehints.py b/jsonargparse/typehints.py
index 8c2cf40..6008cb1 100644
--- a/jsonargparse/typehints.py
+++ b/jsonargparse/typehints.py
@@ -346,11 +346,11 @@ def adapt_typehints(val, typehint, serialize=False, instantiate_classes=False, s
     elif typehint in {Type, type} or typehint_origin in {Type, type}:
         if serialize:
             val = object_path_serializer(val)
-        elif not serialize and not isinstance(val, Type):
+        elif not serialize and not isinstance(val, type):
             path = val
             val = import_object(val)
-            if (typehint in {Type, type} and not isinstance(val, (Type, type))) or \
-               (typehint != Type and typehint_origin in {Type, type} and not _issubclass(val, subtypehints[0])):
+            if (typehint in {Type, type} and not isinstance(val, type)) or \
+               (typehint not in {Type, type} and not _issubclass(val, subtypehints[0])):
                 raise ValueError('Value "'+str(path)+'" is not a '+str(typehint)+'.')
 
     # Union
diff --git a/setup.cfg b/setup.cfg
index d6aa6ce..4559f9b 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -18,7 +18,7 @@ all =
     %(typing_extensions)s
     %(reconplogger)s
 signatures =
-    docstring-parser>=0.7.3
+    docstring-parser>=0.7.3; python_version >= '3.6'
 jsonschema =
     jsonschema>=3.2.0
 jsonnet =


Test patch:
diff --git a/jsonargparse_tests/typehints_tests.py b/jsonargparse_tests/typehints_tests.py
index 4135798..4bd0b10 100755
--- a/jsonargparse_tests/typehints_tests.py
+++ b/jsonargparse_tests/typehints_tests.py
@@ -209,20 +209,39 @@ class TypeHintsTests(unittest.TestCase):
         self.assertRaises(ParserError, lambda: parser.parse_args(['--false=true']))
 
 
-    def test_type_Type(self):
+    def _test_typehint_non_parameterized_types(self, type):
         parser = ArgumentParser(error_handler=None)
-        ActionTypeHint.is_supported_typehint(Type, full=True)
-        parser.add_argument('--type', type=Type)
-        parser.add_argument('--cal', type=Type[Calendar])
+        ActionTypeHint.is_supported_typehint(type, full=True)
+        parser.add_argument('--type', type=type)
         cfg = parser.parse_args(['--type=uuid.UUID'])
         self.assertEqual(cfg.type, uuid.UUID)
         self.assertEqual(parser.dump(cfg), 'type: uuid.UUID\n')
+
+
+    def _test_typehint_parameterized_types(self, type):
+        parser = ArgumentParser(error_handler=None)
+        ActionTypeHint.is_supported_typehint(type, full=True)
+        parser.add_argument('--cal', type=type[Calendar])
         cfg = parser.parse_args(['--cal=calendar.Calendar'])
         self.assertEqual(cfg.cal, Calendar)
         self.assertEqual(parser.dump(cfg), 'cal: calendar.Calendar\n')
         self.assertRaises(ParserError, lambda: parser.parse_args(['--cal=uuid.UUID']))
 
 
+    def test_typehint_Type(self):
+        self._test_typehint_non_parameterized_types(type=Type)
+        self._test_typehint_parameterized_types(type=Type)
+
+
+    def test_typehint_non_parameterized_type(self):
+        self._test_typehint_non_parameterized_types(type=type)
+
+
+    @unittest.skipIf(sys.version_info[:2] < (3, 9), '[] support for builtins introduced in python 3.9')
+    def test_typehint_parametrized_type(self):
+        self._test_typehint_parameterized_types(type=type)
+
+
     def test_uuid(self):
         id1 = uuid.uuid4()
         id2 = uuid.uuid4()