Skip to content
This repository was archived by the owner on Dec 16, 2022. It is now read-only.

Commit 11d8327

Browse files
authored
Fix typing for python 3.7 (#2393)
* Fix typing for python 3.7 * Fix mypy, check sys.version_info instead of using try/catch * Better way of checking version
1 parent 7525c61 commit 11d8327

File tree

1 file changed

+42
-8
lines changed

1 file changed

+42
-8
lines changed

allennlp/semparse/domain_languages/domain_language.py

+42-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from collections import defaultdict
2-
from typing import Any, Callable, CallableMeta, Dict, GenericMeta, List, Set, Tuple, Type, Union # type: ignore
2+
from typing import Any, Callable, Dict, List, Set, Tuple, Type, Union
33
import inspect
44
import logging
5+
import sys
56
import traceback
67
import types
78

@@ -12,6 +13,41 @@
1213

1314
logger = logging.getLogger(__name__)
1415

16+
17+
# We rely heavily on the typing module and its type annotations for our grammar induction code.
18+
# Unfortunately, the behavior of the typing module changed somewhat substantially between python
19+
# 3.6 and 3.7, so we need to do some gymnastics to get some of our checks to work with both.
20+
# That's what these three methods are about.
21+
22+
def is_callable(type_: Type) -> bool:
23+
if sys.version_info < (3, 7):
24+
from typing import CallableMeta # type: ignore
25+
return isinstance(type_, CallableMeta) # type: ignore
26+
else:
27+
return getattr(type_, '_name', None) == 'Callable'
28+
29+
30+
def is_generic(type_: Type) -> bool:
31+
if sys.version_info < (3, 7):
32+
from typing import GenericMeta # type: ignore
33+
return isinstance(type_, GenericMeta) # type: ignore
34+
else:
35+
# pylint: disable=protected-access
36+
from typing import _GenericAlias # type: ignore
37+
return isinstance(type_, _GenericAlias) # type: ignore
38+
39+
40+
def get_generic_name(type_: Type) -> str:
41+
if sys.version_info < (3, 7):
42+
origin = type_.__origin__.__name__
43+
else:
44+
# In python 3.7, type_.__origin__ switched to the built-in class, instead of the typing
45+
# class.
46+
origin = type_._name # pylint: disable=protected-access
47+
args = type_.__args__
48+
return f'{origin}[{",".join(arg.__name__ for arg in args)}]'
49+
50+
1551
class PredicateType:
1652
"""
1753
A base class for `types` in a domain language. This serves much the same purpose as
@@ -31,17 +67,15 @@ def get_type(type_: Type) -> 'PredicateType':
3167
those specially, so that the ``name`` for the ``BasicType`` remains ``List[str]``, as you
3268
would expect.
3369
"""
34-
if isinstance(type_, CallableMeta):
70+
if is_callable(type_):
3571
callable_args = type_.__args__
3672
argument_types = [PredicateType.get_type(t) for t in callable_args[:-1]]
3773
return_type = PredicateType.get_type(callable_args[-1])
3874
return FunctionType(argument_types, return_type)
39-
elif isinstance(type_, GenericMeta):
40-
# This is something like List[int]. type_.__name__ will only give 'List', though, so
41-
# we need to do some magic here.
42-
origin = type_.__origin__
43-
args = type_.__args__
44-
name = f'{origin.__name__}[{",".join(arg.__name__ for arg in args)}]'
75+
elif is_generic(type_):
76+
# This is something like List[int]. type_.__name__ doesn't do the right thing (and
77+
# crashes in python 3.7), so we need to do some magic here.
78+
name = get_generic_name(type_)
4579
else:
4680
name = type_.__name__
4781
return BasicType(name)

0 commit comments

Comments
 (0)