Repository: ilevkivskyi/typing_inspect

Issue:
Python 3.9 support breaks List
There was a regression in release 0.7.0 from 0.6.0.

Currently, 
```python
>>> from typing import List, Set
>>> from typing_inspect import get_args
>>> get_args(list[str])  # Yay this works! Great to see support for Python 3.9!
(<class 'str'>,)
>>> get_args(List)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jessemichel/Dependencies/miniconda3/envs/py39/lib/python3.9/site-packages/typing_inspect.py", line 471, in get_args
    res = tp.__args__
  File "/Users/jessemichel/Dependencies/miniconda3/envs/py39/lib/python3.9/typing.py", line 694, in __getattr__
    raise AttributeError(attr)
AttributeError: __args__
```

Previously, 
```python
>>> get_args(List)
(~T,)
```

I believe the fix would be changing this line:
https://github.com/ilevkivskyi/typing_inspect/blob/d1d46f4c2429dd0a60f902fa7b728d67bb2d1582/typing_inspect.py#L471
to
```python
res = tp.__args__ if hasattr(tp, '__args__') else ()
```

Discussion:

Patch:
diff --git a/typing_inspect.py b/typing_inspect.py
index c11b856..4c765e3 100644
--- a/typing_inspect.py
+++ b/typing_inspect.py
@@ -467,7 +467,8 @@ def get_args(tp, evaluate=None):
     if NEW_TYPING:
         if evaluate is not None and not evaluate:
             raise ValueError('evaluate can only be True in Python >= 3.7')
-        if isinstance(tp, typingGenericAlias):
+        # Note special aliases on Python 3.9 don't have __args__.
+        if isinstance(tp, typingGenericAlias) and hasattr(tp, '__args__'):
             res = tp.__args__
             if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis:
                 res = (list(res[:-1]), res[-1])


Test patch:
diff --git a/test_typing_inspect.py b/test_typing_inspect.py
index 58a03ee..7e9d432 100644
--- a/test_typing_inspect.py
+++ b/test_typing_inspect.py
@@ -402,6 +402,8 @@ class GetUtilityTestCase(TestCase):
             self.assertEqual(get_args(list[int]), (int,))
             self.assertEqual(get_args(tuple[int, str]), (int, str))
             self.assertEqual(get_args(list[list[int]]), (list[int],))
+            # This would return (~T,) before Python 3.9.
+            self.assertEqual(get_args(List), ())
 
     def test_bound(self):
         T = TypeVar('T')