You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
Merge branch 'master' into string-const
This commit is contained in:
BIN
test/bytecode_3.3_run/04_def_annotate.pyc
Normal file
BIN
test/bytecode_3.3_run/04_def_annotate.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.4_run/04_def_annotate.pyc
Normal file
BIN
test/bytecode_3.4_run/04_def_annotate.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.5_run/04_def_annotate.pyc
Normal file
BIN
test/bytecode_3.5_run/04_def_annotate.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.6_run/00_docstring.pyc
Normal file
BIN
test/bytecode_3.6_run/00_docstring.pyc
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,13 +1,42 @@
|
|||||||
# Python 3 annotations
|
# Python 3 positional, kwonly, varargs, and annotations. Ick.
|
||||||
|
|
||||||
def foo(a, b: 'annotating b', c: int) -> float:
|
# RUNNABLE!
|
||||||
print(a + b + c)
|
def test1(args_1, c: int, w=4, *varargs: int, **kwargs: 'annotating kwargs') -> tuple:
|
||||||
|
return (args_1, c, w, kwargs)
|
||||||
|
|
||||||
|
def test2(args_1, args_2, c: int, w=4, *varargs: int, **kwargs: 'annotating kwargs'):
|
||||||
|
return (args_1, args_2, c, w, varargs, kwargs)
|
||||||
|
|
||||||
|
def test3(c: int, w=4, *varargs: int, **kwargs: 'annotating kwargs') -> float:
|
||||||
|
return 5.4
|
||||||
|
|
||||||
|
def test4(a: float, c: int, *varargs: int, **kwargs: 'annotating kwargs') -> float:
|
||||||
|
return 5.4
|
||||||
|
|
||||||
|
def test5(a: float, c: int = 5, *varargs: int, **kwargs: 'annotating kwargs') -> float:
|
||||||
|
return 5.4
|
||||||
|
|
||||||
|
def test6(a: float, c: int, test=None):
|
||||||
|
return (a, c, test)
|
||||||
|
|
||||||
|
def test7(*varargs: int, **kwargs):
|
||||||
|
return (varargs, kwargs)
|
||||||
|
|
||||||
|
def test8(x=55, *varargs: int, **kwargs) -> list:
|
||||||
|
return (x, varargs, kwargs)
|
||||||
|
|
||||||
|
def test9(arg_1=55, *varargs: int, y=5, **kwargs):
|
||||||
|
return x, varargs, int, y, kwargs
|
||||||
|
|
||||||
|
def test10(args_1, b: 'annotating b', c: int) -> float:
|
||||||
|
return 5.4
|
||||||
|
|
||||||
|
class IOBase:
|
||||||
|
pass
|
||||||
|
|
||||||
# Python 3.1 _pyio.py uses the -> "IOBase" annotation
|
# Python 3.1 _pyio.py uses the -> "IOBase" annotation
|
||||||
def open(file, mode = "r", buffering = None,
|
def o(f, mode = "r", buffering = None) -> "IOBase":
|
||||||
encoding = None, errors = None,
|
return (f, mode, buffering)
|
||||||
newline = None, closefd = True) -> "IOBase":
|
|
||||||
return text
|
|
||||||
|
|
||||||
def foo1(x: 'an argument that defaults to 5' = 5):
|
def foo1(x: 'an argument that defaults to 5' = 5):
|
||||||
print(x)
|
print(x)
|
||||||
@@ -18,29 +47,38 @@ def div(a: dict(type=float, help='the dividend'),
|
|||||||
"""Divide a by b"""
|
"""Divide a by b"""
|
||||||
return a / b
|
return a / b
|
||||||
|
|
||||||
class TestSignatureObject():
|
# FIXME:
|
||||||
def test_signature_on_wkwonly(self):
|
# class TestSignatureObject():
|
||||||
def test(*, a:float, b:str) -> int:
|
# def test_signature_on_wkwonly(self):
|
||||||
pass
|
# def test(*, a:float, b:str) -> int:
|
||||||
|
# pass
|
||||||
|
|
||||||
class SupportsInt():
|
class SupportsInt():
|
||||||
|
|
||||||
def __int__(self) -> int:
|
def __int__(self) -> int:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def foo2(a, b: 'annotating b', c: int, *args: str) -> float:
|
def ann1(args_1, b: 'annotating b', c: int, *varargs: str) -> float:
|
||||||
assert foo2.__annotations__['b'] == 'annotating b'
|
assert ann1.__annotations__['b'] == 'annotating b'
|
||||||
assert foo2.__annotations__['c'] == int
|
assert ann1.__annotations__['c'] == int
|
||||||
assert foo2.__annotations__['args'] == str
|
assert ann1.__annotations__['varargs'] == str
|
||||||
assert foo2.__annotations__['return'] == float
|
assert ann1.__annotations__['return'] == float
|
||||||
|
|
||||||
def foo3(a, b: int = 5, **kwargs: float) -> float:
|
def ann2(args_1, b: int = 5, **kwargs: float) -> float:
|
||||||
assert foo3.__annotations__['b'] == int
|
assert ann2.__annotations__['b'] == int
|
||||||
assert foo3.__annotations__['kwargs'] == float
|
assert ann2.__annotations__['kwargs'] == float
|
||||||
assert foo3.__annotations__['return'] == float
|
assert ann2.__annotations__['return'] == float
|
||||||
assert b == 5
|
assert b == 5
|
||||||
|
|
||||||
|
|
||||||
|
assert test1(1, 5) == (1, 5, 4, {})
|
||||||
|
assert test1(1, 5, 6, foo='bar') == (1, 5, 6, {'foo': 'bar'})
|
||||||
|
assert test2(2, 3, 4) == (2, 3, 4, 4, (), {})
|
||||||
|
assert test3(10, foo='bar') == 5.4
|
||||||
|
assert test4(9.5, 7, 6, 4, bar='baz') == 5.4
|
||||||
|
### FIXME: fill in...
|
||||||
|
assert test6(1.2, 3) == (1.2, 3, None)
|
||||||
|
assert test6(2.3, 4, 5) == (2.3, 4, 5)
|
||||||
|
|
||||||
foo2(1, 'test', 5)
|
ann1(1, 'test', 5)
|
||||||
foo3(1)
|
ann2(1)
|
||||||
|
@@ -26,6 +26,7 @@ If we succeed in creating a parse tree, then we have a Python program
|
|||||||
that a later phase can turn into a sequence of ASCII text.
|
that a later phase can turn into a sequence of ASCII text.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
from uncompyle6.scanners.tok import Token
|
from uncompyle6.scanners.tok import Token
|
||||||
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
|
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
|
||||||
from uncompyle6.parsers.treenode import SyntaxTree
|
from uncompyle6.parsers.treenode import SyntaxTree
|
||||||
@@ -1050,7 +1051,7 @@ class Python3Parser(PythonParser):
|
|||||||
(kwargs, 'pos_arg ' * args_pos, opname))
|
(kwargs, 'pos_arg ' * args_pos, opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
|
|
||||||
if opname.startswith('MAKE_FUNCTION_A'):
|
if re.search('^MAKE_FUNCTION.*_A', opname):
|
||||||
if self.version >= 3.6:
|
if self.version >= 3.6:
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_STR %s' %
|
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_STR %s' %
|
||||||
(('pos_arg ' * (args_pos)),
|
(('pos_arg ' * (args_pos)),
|
||||||
@@ -1063,21 +1064,33 @@ class Python3Parser(PythonParser):
|
|||||||
# Normally we remove EXTENDED_ARG from the opcodes, but in the case of
|
# Normally we remove EXTENDED_ARG from the opcodes, but in the case of
|
||||||
# annotated functions can use the EXTENDED_ARG tuple to signal we have an annotated function.
|
# annotated functions can use the EXTENDED_ARG tuple to signal we have an annotated function.
|
||||||
# Yes this is a little hacky
|
# Yes this is a little hacky
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_STR EXTENDED_ARG %s' %
|
if self.version < 3.5:
|
||||||
(('pos_arg ' * (args_pos)),
|
# 3.3 and 3.4 put kwargs before pos_arg
|
||||||
|
pos_kw_tuple = (('kwargs ' * args_kw), ('pos_arg ' * (args_pos)))
|
||||||
|
else:
|
||||||
|
# 3.5 puts pos_arg before kwargs
|
||||||
|
pos_kw_tuple = (('pos_arg ' * (args_pos), ('kwargs ' * args_kw)))
|
||||||
|
if self.version < 3.5:
|
||||||
|
# 3.3 and 3.4 put kwargs before pos_arg
|
||||||
|
pos_kw_tuple = (('kwargs ' * args_kw), ('pos_arg ' * (args_pos)))
|
||||||
|
else:
|
||||||
|
# 3.5 puts pos_arg before kwargs
|
||||||
|
pos_kw_tuple = (('pos_arg ' * (args_pos), ('kwargs ' * args_kw)))
|
||||||
|
rule = ('mkfunc_annotate ::= %s%s%s%sannotate_tuple LOAD_CONST LOAD_STR EXTENDED_ARG %s' %
|
||||||
|
( pos_kw_tuple[0], pos_kw_tuple[1],
|
||||||
('call ' * (annotate_args-1)), opname))
|
('call ' * (annotate_args-1)), opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_STR EXTENDED_ARG %s' %
|
rule = ('mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CONST LOAD_STR EXTENDED_ARG %s' %
|
||||||
(('pos_arg ' * (args_pos)),
|
( pos_kw_tuple[0], pos_kw_tuple[1],
|
||||||
('annotate_arg ' * (annotate_args-1)), opname))
|
('annotate_arg ' * (annotate_args-1)), opname))
|
||||||
else:
|
else:
|
||||||
# See above comment about use of EXTENDED_ARG
|
# See above comment about use of EXTENDED_ARG
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST EXTENDED_ARG %s' %
|
rule = ('mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CONST EXTENDED_ARG %s' %
|
||||||
(('pos_arg ' * (args_pos)),
|
(('pos_arg ' * (args_pos)), ('kwargs ' * args_kw),
|
||||||
('annotate_arg ' * (annotate_args-1)), opname))
|
('annotate_arg ' * (annotate_args-1)), opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST EXTENDED_ARG %s' %
|
rule = ('mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CONST EXTENDED_ARG %s' %
|
||||||
(('pos_arg ' * (args_pos)),
|
(('pos_arg ' * (args_pos)), ('kwargs ' * args_kw),
|
||||||
('call ' * (annotate_args-1)), opname))
|
('call ' * (annotate_args-1)), opname))
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
elif opname == 'RETURN_VALUE_LAMBDA':
|
elif opname == 'RETURN_VALUE_LAMBDA':
|
||||||
|
@@ -333,9 +333,10 @@ class Scanner3(Scanner):
|
|||||||
attr = attr[:4] # remove last value: attr[5] == False
|
attr = attr[:4] # remove last value: attr[5] == False
|
||||||
else:
|
else:
|
||||||
pos_args, name_pair_args, annotate_args = parse_fn_counts(inst.argval)
|
pos_args, name_pair_args, annotate_args = parse_fn_counts(inst.argval)
|
||||||
pattr = ("%d positional, %d keyword pair, %d annotated" %
|
pattr = ("%d positional, %d keyword only, %d annotated" %
|
||||||
(pos_args, name_pair_args, annotate_args))
|
(pos_args, name_pair_args, annotate_args))
|
||||||
if name_pair_args > 0:
|
if name_pair_args > 0:
|
||||||
|
# FIXME: this should probably be K_
|
||||||
opname = '%s_N%d' % (opname, name_pair_args)
|
opname = '%s_N%d' % (opname, name_pair_args)
|
||||||
pass
|
pass
|
||||||
if annotate_args > 0:
|
if annotate_args > 0:
|
||||||
|
@@ -135,10 +135,6 @@ def make_function3_annotate(self, node, is_lambda, nested=1,
|
|||||||
indent = ' ' * l
|
indent = ' ' * l
|
||||||
line_number = self.line_number
|
line_number = self.line_number
|
||||||
|
|
||||||
if code_has_star_arg(code):
|
|
||||||
self.write('*%s' % code.co_varnames[argc + kw_pairs])
|
|
||||||
argc += 1
|
|
||||||
|
|
||||||
i = len(paramnames) - len(defparams)
|
i = len(paramnames) - len(defparams)
|
||||||
suffix = ''
|
suffix = ''
|
||||||
|
|
||||||
@@ -148,7 +144,7 @@ def make_function3_annotate(self, node, is_lambda, nested=1,
|
|||||||
self.write(suffix, param)
|
self.write(suffix, param)
|
||||||
suffix = ', '
|
suffix = ', '
|
||||||
if param in annotate_tuple[0].attr:
|
if param in annotate_tuple[0].attr:
|
||||||
p = annotate_tuple[0].attr.index(param)
|
p = annotate_tuple[0].attr.index(param) + pos_args
|
||||||
self.write(': ')
|
self.write(': ')
|
||||||
self.preorder(node[p])
|
self.preorder(node[p])
|
||||||
if (line_number != self.line_number):
|
if (line_number != self.line_number):
|
||||||
@@ -187,7 +183,17 @@ def make_function3_annotate(self, node, is_lambda, nested=1,
|
|||||||
suffix = ', '
|
suffix = ', '
|
||||||
|
|
||||||
|
|
||||||
|
if code_has_star_arg(code):
|
||||||
|
star_arg = code.co_varnames[argc + kw_pairs]
|
||||||
|
self.write(suffix, '*%s' % star_arg)
|
||||||
|
if star_arg in annotate_tuple[0].attr:
|
||||||
|
p = annotate_tuple[0].attr.index(star_arg) + pos_args + kw_args
|
||||||
|
self.write(': ')
|
||||||
|
self.preorder(node[p])
|
||||||
|
argc += 1
|
||||||
|
|
||||||
# self.println(indent, '#flags:\t', int(code.co_flags))
|
# self.println(indent, '#flags:\t', int(code.co_flags))
|
||||||
|
ends_in_comma = False
|
||||||
if kw_args + annotate_argc > 0:
|
if kw_args + annotate_argc > 0:
|
||||||
if no_paramnames:
|
if no_paramnames:
|
||||||
if not code_has_star_arg(code):
|
if not code_has_star_arg(code):
|
||||||
@@ -198,49 +204,47 @@ def make_function3_annotate(self, node, is_lambda, nested=1,
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.write(", ")
|
self.write(", ")
|
||||||
|
ends_in_comma = True
|
||||||
|
|
||||||
kwargs = node[0]
|
kwargs = node[1]
|
||||||
last = len(kwargs)-1
|
last = len(kwargs)-1
|
||||||
i = 0
|
i = 0
|
||||||
for n in node[0]:
|
for n in node[1]:
|
||||||
if n == 'kwarg':
|
if n == 'kwarg':
|
||||||
if (line_number != self.line_number):
|
if argc > 0 and not ends_in_comma:
|
||||||
self.write("\n" + indent)
|
self.write(', ')
|
||||||
line_number = self.line_number
|
if (line_number != self.line_number):
|
||||||
self.write('%s=' % n[0].pattr)
|
self.write("\n" + indent)
|
||||||
self.preorder(n[1])
|
line_number = self.line_number
|
||||||
if i < last:
|
kn = n[0].pattr
|
||||||
self.write(', ')
|
if kn in annotate_tuple[0].attr:
|
||||||
i += 1
|
p = annotate_tuple[0].attr.index(star_arg) + pos_args + kw_args
|
||||||
pass
|
self.write('%s: ' % kn)
|
||||||
pass
|
self.preorder(node[p])
|
||||||
annotate_args = []
|
self.write('=')
|
||||||
for n in node:
|
else:
|
||||||
if n == 'annotate_arg':
|
self.write('%s=' % kn)
|
||||||
annotate_args.append(n[0])
|
self.preorder(n[1])
|
||||||
elif n == 'annotate_tuple':
|
if i < last:
|
||||||
t = n[0].attr
|
self.write(', ')
|
||||||
if t[-1] == 'return':
|
ends_in_comma = True
|
||||||
t = t[0:-1]
|
else:
|
||||||
annotate_args = annotate_args[:-1]
|
ends_in_comma = False
|
||||||
pass
|
i += 1
|
||||||
last = len(annotate_args) - 1
|
|
||||||
for i in range(len(annotate_args)):
|
|
||||||
self.write("%s: " % (t[i]))
|
|
||||||
self.preorder(annotate_args[i])
|
|
||||||
if i < last:
|
|
||||||
self.write(', ')
|
|
||||||
pass
|
|
||||||
pass
|
|
||||||
break
|
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
if code_has_star_star_arg(code):
|
if code_has_star_star_arg(code):
|
||||||
if argc > 0:
|
if argc > 0 and not ends_in_comma:
|
||||||
self.write(', ')
|
self.write(', ')
|
||||||
self.write('**%s' % code.co_varnames[argc + kw_pairs])
|
star_star_arg = code.co_varnames[argc + kw_pairs]
|
||||||
|
self.write('**%s' % star_star_arg)
|
||||||
|
if star_star_arg in annotate_tuple[0].attr:
|
||||||
|
p = annotate_tuple[0].attr.index(star_star_arg) + pos_args + kw_args
|
||||||
|
self.write(': ')
|
||||||
|
self.preorder(node[p])
|
||||||
|
|
||||||
if is_lambda:
|
if is_lambda:
|
||||||
self.write(": ")
|
self.write(": ")
|
||||||
|
Reference in New Issue
Block a user