8000 Support for method type hints · atg/pseudo-python@6a7c316 · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit 6a7c316

Browse files
committed
Support for method type hints
1 parent ed0f757 commit 6a7c316

File tree

3 files changed

+98
-33
lines changed
  • example
  • pseudo_python
  • 3 files changed

    +98
    -33
    lines changed

    example/f.pseudo.yaml

    Lines changed: 40 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -20,6 +20,46 @@ definitions:
    2020
    - Int
    2121
    return_type: Int
    2222
    type: function_definition
    23+
    - attrs: []
    24+
    base: null
    25+
    constructor: null
    26+
    methods:
    27+
    - block:
    28+
    - pseudo_type: B
    29+
    type: implicit_return
    30+
    value:
    31+
    class: {name: B, type: typename}
    32+
    params:
    33+
    - {name: a, pseudo_type: Int, type: local}
    34+
    pseudo_type: B
    35+
    type: new_instance
    36+
    is_public: true
    37+
    name: expand
    38+
    params: [a]
    39+
    pseudo_type: [Function, Int, B]
    40+
    return_type: B
    41+
    this: {name: A, type: typename}
    42+
    type: method_definition
    43+
    name: A
    44+
    type: class_definition
    45+
    - attrs:
    46+
    - {is_public: false, name: a, pseudo_type: Int, type: class_attr}
    47+
    base: null
    48+
    constructor:
    49+
    block:
    50+
    - pseudo_type: Void
    51+
    target: {name: a, pseudo_type: Int, type: instance_variable}
    52+
    type: assignment
    53+
    value: {name: a, pseudo_type: Int, type: local}
    54+
    name: __init__
    55+
    params: [a]
    56+
    pseudo_type: [Function, Int, B]
    57+
    return_type: null
    58+
    this: {name: B, type: typename}
    59+
    type: constructor
    60+
    methods: []
    61+
    name: B
    62+
    type: class_definition
    2363
    dependencies: []
    2464
    main: []
    2565
    type: module

    example/f.py

    Lines changed: 9 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,6 +1,15 @@
    11
    from typing import Dict, List, Tuple, Callable
    2+
    23
    def f(s: Callable[[int], int]) -> int:
    34
    return s(2)
    45

    6+
    class A:
    7+
    def expand(self, a: int) -> 'B':
    8+
    return B(a)
    9+
    10+
    class B:
    11+
    def __init__(self, a):
    12+
    self.a = a
    13+
    514
    # f(2)
    615

    pseudo_python/ast_translator.py

    Lines changed: 49 additions & 33 deletions
    Original file line numberDiff line numberDiff line change
    @@ -109,6 +109,10 @@ def _translate_definitions(self):
    109109
    in self._attrs[definition[1]] if not self._attr_index[definition[1]][a][1]], 'methods': [], 'constructor': None}
    110110
    for method in definition[3]:
    111111
    m = self._definition_index[definition[1]][method]
    112+
    if not isinstance(m, dict):
    113+
    # input(self.type_env[d 628C efinition[1]])
    114+
    self._translate_hinted_fun(method, definition[1])
    115+
    m = self._definition_index[definition[1]][method]
    112116
    if not isinstance(m, dict):
    113117
    raise cant_infer_error('%s#%s' % (definition[1], method), self.lines[m.lineno])
    114118

    @@ -359,6 +363,9 @@ def _translate_init(self, name, params, location):
    359363
    self._definition_index[name]['__init__'] = self._translate_function(self._definition_index[name]['__init__'], name, {'pseudo_type': name}, '__init__', [p['pseudo_type'] for p in params])
    360364
    init[-1] = name
    361365

    366+
    for label, m in self._definition_index[name].items():
    367+
    self._translate_hinted_fun(label, name)
    368+
    362369
    for label, m in self._definition_index[name].items():
    363370
    if len(self.type_env.top[name][label]) == 2 and label != '__init__':
    364371
    self._definition_index[name][label] = self._translate_function(m, name, {'pseudo_type': name}, label, [])
    @@ -1236,50 +1243,59 @@ def _translate_pure_functions(self):
    12361243

    12371244
    def _translate_hinted_functions(self):
    12381245
    for f in self.definitions:
    1239-
    # import pdb; pdb.set_trace();
    1240-
    1241-
    if f[0] == 'function' and len(self.type_env['functions'][f[1]]) > 2 and self._definition_index['functions'][f[1]].args.args[0].annotation:
    1242-
    types = []
    1243-
    for h in self._definition_index['functions'][f[1]].args.args:
    1244-
    if h.annotation:
    1245-
    # if isinstance(h.annotation, ast.Name):
    1246-
    types.append(self._hint(h.annotation))
    1247-
    # elif isinstance(h.annotation, ast.Subscript):
    1248-
    else:
    1249-
    raise translation_error('expected annotations for all args, no annotation for %s' % h.arg,
    1250-
    (h.lineno, h.col_offset), self.lines[h.lineno])
    1251-
    1252-
    return_annotation = self._definition_index['functions'][f[1]].returns
    1253-
    if return_annotation:
    1254-
    return_type = self._hint(return_annotation)
    1246+
    if f[0] == 'function':
    1247+
    self._translate_hinted_fun(f[1], 'functions')
    1248+
    1249+
    def _translate_hinted_fun(self, f, namespace):
    1250+
    print(namespace, self.type_env[namespace])
    1251+
    if isinstance(self._definition_index< F438 /span>[namespace][f], dict):
    1252+
    return
    1253+
    if namespace == 'functions':
    1254+
    args = self._definition_index[namespace][f].args.args
    1255+
    else:
    1256+
    args = self._definition_index[namespace][f].args.args[1:]
    1257+
    if len(self.type_env[namespace][f]) > 2 and args[0].annotation:
    1258+
    types = []
    1259+
    for h in args:
    1260+
    if h.annotation:
    1261+
    types.append(self._hint(h.annotation))
    12551262
    else:
    1256-
    return_type = 'Void' # None
    1257-
    self.type_env['functions'][f[1]][1:] = types + [return_type]
    1258-
    self._definition_index['functions'][f[1]] = self._translate_function(self._definition_index['functions'][f[1]], 'functions', None, f[1], None)
    1263+
    raise translation_error('expected annotations for all args, no annotation for %s' % h.arg,
    1264+
    (h.lineno, h.col_offset), self.lines[h.lineno])
    1265+
    1266+
    return_annotation = self._definition_index[namespace][f].returns
    1267+
    if return_annotation:
    1268+
    return_type = self._hint(return_annotation)
    1269+
    else:
    1270+
    return_type = 'Void' # None
    1271+
    self.type_env[namespace][f][1:] = types + [return_type]
    1272+
    self._definition_index[namespace][f] = self._translate_function(self._definition_index[namespace][f], namespace, None, f, None)
    12591273

    12601274
    def _hint(self, x):
    1261-
    if isinstance(x, ast.Name):
    1262-
    if x.id in BUILTIN_SIMPLE_TYPES:
    1263-
    return BUILTIN_SIMPLE_TYPES[x.id]
    1264-
    elif x.id in self.type_env.top.values:
    1265-
    return x.id
    1266-
    elif isinstance(x, ast.Subscript) and isinstance(x.value, ast.Name):
    1267-
    if x.value.id in ['List', 'Set', 'Dict', 'Tuple', 'Callable']:
    1268-
    if x.value.id not in self._typing_imports:
    1269-
    raise translation_error('please add\nfrom typing import %s on top to use it\n' % x.value.id, (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
    1275+
    if isinstance(x, (ast.Name, ast.Str)):
    1276+
    name = x.id if isinstance(x, ast.Name) else x.s
    1277+
    if name in BUILTIN_SIMPLE_TYPES:
    1278+
    return BUILTIN_SIMPLE_TYPES[name]
    1279+
    elif name in self.type_env.top.values:
    1280+
    return name
    1281+
    elif isinstance(x, ast.Subscript) and isinstance(x.value, (ast.Name, ast.Str)):
    1282+
    name = x.value.id if isinstance(x.value, ast.Name) else x.value.s
    1283+
    if name in ['List', 'Set', 'Dict', 'Tuple', 'Callable']:
    1284+
    if name not in self._typing_imports:
    1285+
    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])
    12701286
    if not isinstance(x.slice, ast.Index):
    12711287
    raise translation_error('invalid index', (x.value.lineno, x.value.col_offset), self.lines[x.lineno])
    12721288
    index = x.slice.value
    1273-
    if x.value.id in ['List', 'Set']:
    1289+
    if name in ['List', 'Set']:
    12741290
    if not isinstance(index, (ast.Name, ast.Subscript)):
    1275-
    raise type_check_error('%s expects one valid generic arguments' % x.value.id, (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
    1276-
    return [x.value.id, self._hint(index)]
    1277-
    elif x.value.id == 'Tuple':
    1291+
    raise type_check_error('%s expects one valid generic arguments' % name, (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
    1292+
    return [name, self._hint(index)]
    1293+
    elif name == 'Tuple':
    12781294
    # import pdb;pdb.set_trace()
    12791295
    if not isinstance(index, ast.Tuple) or any(not isinstance(y, (ast.Name, ast.Subscript)) for y in index.elts):
    12801296
    raise type_check_error('Tuple expected valid generic arguments', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
    12811297
    return ['Tuple'] + [self._hint(y) for y in index.elts]
    1282-
    elif x.value.id == 'Dict':
    1298+
    elif name == 'Dict':
    12831299
    if not isinstance(index, ast.Tuple) or len(index.elts) != 2 or not isinstance(index.elts[1], (ast.Name, ast.Subscript)):
    12841300
    raise type_check_error('Dict expected 2 valid generic arguments', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
    12851301
    if not isinstance(index.elts[0], ast.Name) or index.elts[0].id not in KEY_TYPES:

    0 commit comments

    Comments
     (0)
    0