def _hint(self, x):
if isinstance(x, (ast.Name, ast.Str)):
name = x.id if isinstance(x, ast.Name) else x.s
if name in BUILTIN_SIMPLE_TYPES:
return BUILTIN_SIMPLE_TYPES[name]
elif name in self.type_env.top.values:
return name
elif isinstance(x, ast.Subscript) and isinstance(x.value, (ast.Name, ast.Str)):
name = x.value.id if isinstance(x.value, ast.Name) else x.value.s
if name in ['List', 'Set', 'Dict', 'Tuple', 'Callable']:
if name not in self._typing_imports:
raise translation_error('please add\nfrom typing import %s on top to use it\n' % name, (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
if not isinstance(x.slice, ast.Index):
raise translation_error('invalid index', (x.value.lineno, x.value.col_offset), self.lines[x.lineno])
index = x.slice.value
if name in ['List', 'Set']:
if not isinstance(index, (ast.Name, ast.Subscript)):
raise type_check_error('%s expects one valid generic arguments' % name, (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
return [name, self._hint(index)]
elif name == 'Tuple':
if not isinstance(index, ast.Tuple) or any(not isinstance(y, (ast.Name, ast.Subscript)) for y in index.elts):
raise type_check_error('Tuple expected valid generic arguments', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
return ['Tuple'] + [self._hint(y) for y in index.elts]
elif name == 'Dict':
if not isinstance(index, ast.Tuple) or len(index.elts) != 2 or not isinstance(index.elts[1], (ast.Name, ast.Subscript)):
raise type_check_error('Dict expected 2 valid generic arguments', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
if not isinstance(index.elts[0], ast.Name) or index.elts[0].id not in KEY_TYPES:
raise type_check_error('type not supported as a dictionary key type', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno],
suggestions='only those types are supported:\n %s ' % '\n '.join(PSEUDO_KEY_TYPES),
right=' Dict[str, List[int]]',
wrong=' Dict[List[int], Tuple[int]]')
return ['Dictionary', self._hint(index.elts[0]), self._hint(index.elts[1])]
else:
if not isinstance(index, ast.Tuple) or len(index.elts) != 2 or not isinstance(index.elts[0], ast.List) or not isinstance(index.elts[1], (ast.Name, ast.Subscript)) or any(not isinstance(y, (ast.Name, ast.Subscript)) for y in index.elts[0].elts):
raise type_check_error('Callable expected valid generic arguments of the form Callable[[<arg_type>, <arg_type>*], <return>]', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
return ['Function'] + [self._hint(y) for y in index.elts[0].elts] + [self._hint(index.elts[1])]
raise type_check_error('type not recognized',
(x.lineno, x.col_offset), self.lines[x.lineno],
suggestions='supported type hints are:\n ' + '\n '.join(
['int', 'float', 'str', 'bool',
'List[<element_hint>]', 'Dict[<key_hint>, <value_hint>]', 'Tuple[<element_hints>..]', 'Set[<element_hint>]', 'Callable[[<arg_hint>*], <return_hin>]'
'your class e.g. Human']))
评论列表
文章目录