You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
Merge branch 'master' into python-2.4
This commit is contained in:
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [rocky]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@
|
||||
/.pytest_cache
|
||||
/.python-version
|
||||
/.tox
|
||||
.mypy_cache
|
||||
/.venv*
|
||||
/README
|
||||
/__pkginfo__.pyc
|
||||
|
@@ -21,6 +21,17 @@
|
||||
# less elegant than having it here with reduced code, albeit there
|
||||
# still is some room for improvement.
|
||||
|
||||
# Python-version | package | last-version |
|
||||
# -----------------------------------------
|
||||
# 2.5 | pip | 1.1 |
|
||||
# 2.6 | pip | 1.5.6 |
|
||||
# 2.7 | pip | 19.2.3 |
|
||||
# 2.7 | pip | 1.2.1 |
|
||||
# 3.1 | pip | 1.5.6 |
|
||||
# 3.2 | pip | 7.1.2 |
|
||||
# 3.3 | pip | 10.0.1 |
|
||||
# 3.4 | pip | 19.1.1 |
|
||||
|
||||
# Things that change more often go here.
|
||||
copyright = """
|
||||
Copyright (C) 2015-2020 Rocky Bernstein <rb@dustyfeet.com>.
|
||||
@@ -58,7 +69,7 @@ entry_points = {
|
||||
]}
|
||||
ftp_url = None
|
||||
install_requires = ["spark-parser >= 1.8.9, < 1.9.0",
|
||||
"xdis >= 4.5.1, < 4.6.0"]
|
||||
"xdis >= 4.6.0, < 4.7.0"]
|
||||
|
||||
license = "GPL3"
|
||||
mailing_list = "python-debugger@googlegroups.com"
|
||||
|
@@ -5,4 +5,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
|
||||
echo "This script should be *sourced* rather than run directly through bash"
|
||||
exit 1
|
||||
fi
|
||||
export PYVERSIONS='3.5.9 3.6.10 2.6.9 3.3.7 2.7.18 3.2.6 3.1.5 3.4.10 3.7.7 3.8.2'
|
||||
export PYVERSIONS='3.5.9 3.6.10 2.6.9 3.3.7 2.7.18 3.2.6 3.1.5 3.4.10 3.7.7 3.8.3'
|
||||
|
@@ -12,8 +12,7 @@ import functools
|
||||
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY, code_deparse
|
||||
|
||||
# TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there
|
||||
from xdis.bytecode import Bytecode
|
||||
from xdis.main import get_opcode
|
||||
from xdis import Bytecode, get_opcode
|
||||
|
||||
opc = get_opcode(PYTHON_VERSION, IS_PYPY)
|
||||
Bytecode = functools.partial(Bytecode, opc=opc)
|
||||
|
57
setup.py
57
setup.py
@@ -15,29 +15,40 @@ if not ((2, 4) <= SYS_VERSION <= (2, 7)):
|
||||
print(mess)
|
||||
raise Exception(mess)
|
||||
|
||||
from __pkginfo__ import \
|
||||
author, author_email, install_requires, \
|
||||
license, long_description, classifiers, \
|
||||
entry_points, modname, py_modules, \
|
||||
short_desc, VERSION, web, \
|
||||
zip_safe
|
||||
from __pkginfo__ import (
|
||||
author,
|
||||
author_email,
|
||||
install_requires,
|
||||
license,
|
||||
long_description,
|
||||
classifiers,
|
||||
entry_points,
|
||||
modname,
|
||||
py_modules,
|
||||
short_desc,
|
||||
VERSION,
|
||||
web,
|
||||
zip_safe,
|
||||
)
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
author = author,
|
||||
author_email = author_email,
|
||||
classifiers = classifiers,
|
||||
description = short_desc,
|
||||
entry_points = entry_points,
|
||||
install_requires = install_requires,
|
||||
license = license,
|
||||
long_description = long_description,
|
||||
long_description_content_type = "text/x-rst",
|
||||
name = modname,
|
||||
packages = find_packages(),
|
||||
py_modules = py_modules,
|
||||
test_suite = 'nose.collector',
|
||||
url = web,
|
||||
tests_require = ['nose>=1.0'],
|
||||
version = VERSION,
|
||||
zip_safe = zip_safe)
|
||||
author=author,
|
||||
author_email=author_email,
|
||||
classifiers=classifiers,
|
||||
description=short_desc,
|
||||
entry_points=entry_points,
|
||||
install_requires=install_requires,
|
||||
license=license,
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/x-rst",
|
||||
name=modname,
|
||||
packages=find_packages(),
|
||||
py_modules=py_modules,
|
||||
test_suite="nose.collector",
|
||||
url=web,
|
||||
tests_require=["nose>=1.0"],
|
||||
version=VERSION,
|
||||
zip_safe=zip_safe,
|
||||
)
|
||||
|
5
test/.gitignore
vendored
5
test/.gitignore
vendored
@@ -1,3 +1,8 @@
|
||||
/.coverage
|
||||
/.python-version
|
||||
/nohup.out
|
||||
/pycdc
|
||||
/test_pycdc_tests.sh
|
||||
/test_uncompyle2.py
|
||||
/test_unpy33.py
|
||||
/test_unpy37.py
|
||||
|
Binary file not shown.
BIN
test/bytecode_3.7_run/10_async.pyc
Normal file
BIN
test/bytecode_3.7_run/10_async.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.8_run/10_async.pyc
Normal file
BIN
test/bytecode_3.8_run/10_async.pyc
Normal file
Binary file not shown.
@@ -1,23 +0,0 @@
|
||||
# from 3.7 test_contextlib_async.py
|
||||
# Bugs were not adding "async" when a function is a decorator,
|
||||
# and a misaligment when using "async with as".
|
||||
@_async_test
|
||||
async def test_enter(self):
|
||||
self.assertIs(await manager.__aenter__(), manager)
|
||||
|
||||
async with manager as context:
|
||||
async with woohoo() as x:
|
||||
x = 1
|
||||
y = 2
|
||||
assert manager is context
|
||||
|
||||
# From 3.7.6 test_coroutines.py
|
||||
# Bug was different form of code for "async with" below
|
||||
class CoroutineTest():
|
||||
def test_with_8(self):
|
||||
CNT = 0
|
||||
async def foo():
|
||||
nonlocal CNT
|
||||
async with CM():
|
||||
CNT += 1
|
||||
return
|
70
test/simple_source/bug37/10_async.py
Normal file
70
test/simple_source/bug37/10_async.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# from 3.7 test_contextlib_async.py
|
||||
# Bugs were not adding "async" when a function is a decorator,
|
||||
# and a misaligment when using "async with ... as".
|
||||
|
||||
"""This program is self-checking!"""
|
||||
import asyncio
|
||||
from contextlib import asynccontextmanager, AbstractAsyncContextManager
|
||||
import functools
|
||||
|
||||
|
||||
def _async_test(func):
|
||||
"""Decorator to turn an async function into a test case."""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
coro = func(*args, **kwargs)
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
try:
|
||||
return loop.run_until_complete(coro)
|
||||
finally:
|
||||
loop.close()
|
||||
asyncio.set_event_loop(None)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
state = []
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def woohoo():
|
||||
state.append(1)
|
||||
yield 42
|
||||
state.append(999)
|
||||
|
||||
|
||||
@_async_test
|
||||
async def test_enter():
|
||||
class DefaultEnter(AbstractAsyncContextManager):
|
||||
async def __aexit__(*args):
|
||||
return
|
||||
# await super().__aexit__(*args)
|
||||
|
||||
manager = DefaultEnter()
|
||||
got_manager = await manager.__aenter__()
|
||||
# print(got_manager, manager)
|
||||
assert got_manager is manager
|
||||
|
||||
async with manager as context:
|
||||
async with woohoo() as x:
|
||||
x = 1
|
||||
y = 2
|
||||
assert manager is context
|
||||
|
||||
|
||||
# From 3.7.6 test_coroutines.py
|
||||
# Bug was different form of code for "async with" below
|
||||
class CoroutineTest:
|
||||
def test_with_8(self):
|
||||
CNT = 0
|
||||
|
||||
async def foo():
|
||||
nonlocal CNT
|
||||
async with CM():
|
||||
CNT += 1
|
||||
return
|
||||
|
||||
|
||||
test_enter()
|
2
test/stdlib/.gitignore
vendored
2
test/stdlib/.gitignore
vendored
@@ -1 +1,3 @@
|
||||
/.python-version
|
||||
/runun33.sh
|
||||
/runun7.sh
|
||||
|
@@ -1,4 +1,12 @@
|
||||
SKIP_TESTS=(
|
||||
# ifelsestmt is borked in:
|
||||
# if filename == 'srcfile':
|
||||
# return srcfile
|
||||
# if filename == 'destfile':
|
||||
# return destfile
|
||||
# assert 0 # shouldn't reach here.
|
||||
[test_shutil.py]=1
|
||||
|
||||
|
||||
[test___all__.py]=1 # it fails on its own
|
||||
[test___all__.py]=1 # it fails on its own
|
||||
@@ -59,6 +67,7 @@ SKIP_TESTS=(
|
||||
|
||||
[test_scriptpackages.py]=1 # it fails on its own
|
||||
[test_select.py]=1 # test takes too long to run: 11 seconds
|
||||
|
||||
[test_socket.py]=1 # test takes too long to run: 12 seconds
|
||||
[test_startfile.py]=1 # it fails on its own
|
||||
[test_structmembers.py]=1 # it fails on its own
|
||||
|
@@ -32,8 +32,8 @@ want to run on earlier Python versions.
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
from xdis import iscode
|
||||
from xdis.load import check_object_path, load_module
|
||||
from xdis import iscode, load_module
|
||||
from xdis.load import check_object_path
|
||||
from uncompyle6.scanner import get_scanner
|
||||
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2015-2016, 2818 by Rocky Bernstein
|
||||
# Copyright (c) 2015-2016, 2818, 2020 by Rocky Bernstein
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -15,14 +15,27 @@
|
||||
|
||||
from collections import deque
|
||||
|
||||
from xdis import iscode
|
||||
from xdis.load import load_file, load_module
|
||||
from xdis.main import get_opcode
|
||||
from xdis.bytecode import Bytecode, findlinestarts, offset2line
|
||||
from xdis import (
|
||||
Bytecode,
|
||||
iscode,
|
||||
findlinestarts,
|
||||
get_opcode,
|
||||
offset2line,
|
||||
load_file,
|
||||
load_module,
|
||||
)
|
||||
|
||||
|
||||
def line_number_mapping(pyc_filename, src_filename):
|
||||
(version, timestamp, magic_int, code1, is_pypy,
|
||||
source_size, sip_hash) = load_module(pyc_filename)
|
||||
(
|
||||
version,
|
||||
timestamp,
|
||||
magic_int,
|
||||
code1,
|
||||
is_pypy,
|
||||
source_size,
|
||||
sip_hash,
|
||||
) = load_module(pyc_filename)
|
||||
try:
|
||||
code2 = load_file(src_filename)
|
||||
except SyntaxError, e:
|
||||
@@ -44,7 +57,10 @@ def number_loop(queue, mappings, opc):
|
||||
assert code1.co_name == code2.co_name
|
||||
linestarts_orig = findlinestarts(code1)
|
||||
linestarts_uncompiled = list(findlinestarts(code2))
|
||||
mappings += [[line, offset2line(offset, linestarts_uncompiled)] for offset, line in linestarts_orig]
|
||||
mappings += [
|
||||
[line, offset2line(offset, linestarts_uncompiled)]
|
||||
for offset, line in linestarts_orig
|
||||
]
|
||||
bytecode1 = Bytecode(code1, opc)
|
||||
bytecode2 = Bytecode(code2, opc)
|
||||
instr2s = bytecode2.get_instructions(code2)
|
||||
|
@@ -21,8 +21,7 @@ Common uncompyle6 parser routines.
|
||||
|
||||
import sys
|
||||
|
||||
from xdis import iscode
|
||||
from xdis.magics import py_str2float
|
||||
from xdis import iscode, py_str2float
|
||||
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
from uncompyle6.show import maybe_show_asm
|
||||
|
||||
|
@@ -7,7 +7,7 @@ from uncompyle6.parsers.parse11 import Python11Parser
|
||||
|
||||
class Python10Parser(Python11Parser):
|
||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||
super(Python11Parser, self).__init__(debug_parser)
|
||||
super(Python10Parser, self).__init__(debug_parser)
|
||||
self.customized = {}
|
||||
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Rocky Bernstein
|
||||
# Copyright (c) 2019-2020 Rocky Bernstein
|
||||
|
||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
from uncompyle6.parser import PythonParserSingle
|
||||
@@ -7,7 +7,7 @@ from uncompyle6.parsers.parse12 import Python12Parser
|
||||
|
||||
class Python11Parser(Python12Parser):
|
||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||
super(Python12Parser, self).__init__(debug_parser)
|
||||
super(Python11Parser, self).__init__(debug_parser)
|
||||
self.customized = {}
|
||||
|
||||
|
||||
|
@@ -8,7 +8,7 @@ from uncompyle6.parsers.parse22 import Python22Parser
|
||||
class Python21Parser(Python22Parser):
|
||||
|
||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||
super(Python22Parser, self).__init__(debug_parser)
|
||||
super(Python21Parser, self).__init__(debug_parser)
|
||||
self.customized = {}
|
||||
|
||||
def p_forstmt21(self, args):
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2016-2017 Rocky Bernstein
|
||||
# Copyright (c) 2016-2017, 2020 Rocky Bernstein
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <hartmut@goebel.noris.de>
|
||||
|
||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
@@ -8,7 +8,7 @@ from uncompyle6.parsers.parse23 import Python23Parser
|
||||
class Python22Parser(Python23Parser):
|
||||
|
||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||
super(Python23Parser, self).__init__(debug_parser)
|
||||
super(Python22Parser, self).__init__(debug_parser)
|
||||
self.customized = {}
|
||||
|
||||
def p_misc22(self, args):
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2016-2018 Rocky Bernstein
|
||||
# Copyright (c) 2016-2018, 2020 Rocky Bernstein
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <hartmut@goebel.noris.de>
|
||||
# Copyright (c) 1999 John Aycock
|
||||
|
||||
@@ -9,7 +9,7 @@ from uncompyle6.parsers.parse24 import Python24Parser
|
||||
class Python23Parser(Python24Parser):
|
||||
|
||||
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
|
||||
super(Python24Parser, self).__init__(debug_parser)
|
||||
super(Python23Parser, self).__init__(debug_parser)
|
||||
self.customized = {}
|
||||
|
||||
def p_misc23(self, args):
|
||||
|
@@ -929,8 +929,10 @@ class Python37Parser(Python37BaseParser):
|
||||
|
||||
jitop_come_from_expr ::= JUMP_IF_TRUE_OR_POP come_froms expr
|
||||
jifop_come_from ::= JUMP_IF_FALSE_OR_POP come_froms
|
||||
expr_jitop ::= expr JUMP_IF_TRUE_OR_POP
|
||||
|
||||
or ::= and jitop_come_from_expr COME_FROM
|
||||
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
||||
or ::= expr_jitop expr COME_FROM
|
||||
or ::= expr_jit expr COME_FROM
|
||||
or ::= expr_pjit expr POP_JUMP_IF_FALSE COME_FROM
|
||||
|
||||
@@ -953,8 +955,8 @@ class Python37Parser(Python37BaseParser):
|
||||
and ::= expr JUMP_IF_FALSE_OR_POP expr come_from_opt
|
||||
and ::= expr jifop_come_from expr
|
||||
|
||||
pjit_come_from ::= POP_JUMP_IF_TRUE COME_FROM
|
||||
or ::= expr pjit_come_from expr
|
||||
expr_pjit_come_from ::= expr POP_JUMP_IF_TRUE COME_FROM
|
||||
or ::= expr_pjit_come_from expr
|
||||
|
||||
## Note that "jmp_false" is what we check on in the "and" reduce rule.
|
||||
and ::= expr jmp_false expr COME_FROM
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2017-2019 Rocky Bernstein
|
||||
# Copyright (c) 2017-2020 Rocky Bernstein
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -38,14 +38,17 @@ class Python38Parser(Python37Parser):
|
||||
stmt ::= forelselaststmtl38
|
||||
stmt ::= tryfinally38stmt
|
||||
stmt ::= tryfinally38rstmt
|
||||
stmt ::= tryfinally38rstmt2
|
||||
stmt ::= tryfinally38rstmt3
|
||||
stmt ::= tryfinally38astmt
|
||||
stmt ::= try_elsestmtl38
|
||||
stmt ::= try_except_ret38
|
||||
stmt ::= try_except38
|
||||
stmt ::= whilestmt38
|
||||
stmt ::= whileTruestmt38
|
||||
stmt ::= call
|
||||
stmt ::= call_stmt
|
||||
|
||||
call_stmt ::= call
|
||||
break ::= POP_BLOCK BREAK_LOOP
|
||||
break ::= POP_BLOCK POP_TOP BREAK_LOOP
|
||||
break ::= POP_TOP BREAK_LOOP
|
||||
@@ -53,15 +56,12 @@ class Python38Parser(Python37Parser):
|
||||
|
||||
# FIXME: this should be restricted to being inside a try block
|
||||
stmt ::= except_ret38
|
||||
stmt ::= except_ret38a
|
||||
|
||||
# FIXME: this should be added only when seeing GET_AITER or YIELD_FROM
|
||||
async_for_stmt38 ::= expr
|
||||
GET_AITER
|
||||
SETUP_FINALLY
|
||||
GET_ANEXT
|
||||
LOAD_CONST
|
||||
YIELD_FROM
|
||||
POP_BLOCK
|
||||
async_for ::= GET_AITER _come_froms
|
||||
SETUP_FINALLY GET_ANEXT LOAD_CONST YIELD_FROM POP_BLOCK
|
||||
async_for_stmt38 ::= expr async_for
|
||||
store for_block
|
||||
COME_FROM_FINALLY
|
||||
END_ASYNC_FOR
|
||||
@@ -80,7 +80,20 @@ class Python38Parser(Python37Parser):
|
||||
END_ASYNC_FOR
|
||||
else_suite
|
||||
|
||||
return ::= ret_expr ROT_TWO POP_TOP RETURN_VALUE
|
||||
# Seems to be used to discard values before a return in a "for" loop
|
||||
discard_top ::= ROT_TWO POP_TOP
|
||||
discard_tops ::= discard_top+
|
||||
|
||||
return ::= ret_expr
|
||||
discard_tops RETURN_VALUE
|
||||
|
||||
return ::= popb_return
|
||||
return ::= pop_return
|
||||
return ::= pop_ex_return
|
||||
except_stmt ::= pop_ex_return
|
||||
pop_return ::= POP_TOP ret_expr RETURN_VALUE
|
||||
popb_return ::= ret_expr POP_BLOCK RETURN_VALUE
|
||||
pop_ex_return ::= ret_expr ROT_FOUR POP_EXCEPT RETURN_VALUE
|
||||
|
||||
# 3.8 can push a looping JUMP_BACK into into a JUMP_ from a statement that jumps to it
|
||||
lastl_stmt ::= ifpoplaststmtl
|
||||
@@ -127,8 +140,14 @@ class Python38Parser(Python37Parser):
|
||||
except_handler38
|
||||
try_except38 ::= SETUP_FINALLY POP_BLOCK POP_TOP suite_stmts_opt
|
||||
except_handler38a
|
||||
try_except_ret38 ::= SETUP_FINALLY expr POP_BLOCK
|
||||
RETURN_VALUE except_ret38a
|
||||
|
||||
# suite_stmts has a return
|
||||
try_except38 ::= SETUP_FINALLY POP_BLOCK suite_stmts
|
||||
except_handler38b
|
||||
|
||||
try_except_ret38 ::= SETUP_FINALLY returns except_ret38a
|
||||
try_except_ret38a ::= SETUP_FINALLY returns except_handler38c
|
||||
END_FINALLY come_from_opt
|
||||
|
||||
# Note: there is a suite_stmts_opt which seems
|
||||
# to be bookkeeping which is not expressed in source code
|
||||
@@ -148,19 +167,42 @@ class Python38Parser(Python37Parser):
|
||||
tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
||||
BEGIN_FINALLY COME_FROM_FINALLY suite_stmts_opt
|
||||
END_FINALLY
|
||||
tryfinally38rstmt ::= SETUP_FINALLY POP_BLOCK CALL_FINALLY
|
||||
|
||||
|
||||
lc_setup_finally ::= LOAD_CONST SETUP_FINALLY
|
||||
call_finally_pt ::= CALL_FINALLY POP_TOP
|
||||
cf_cf_finally ::= come_from_opt COME_FROM_FINALLY
|
||||
pop_finally_pt ::= POP_FINALLY POP_TOP
|
||||
ss_end_finally ::= suite_stmts END_FINALLY
|
||||
sf_pb_call_returns ::= SETUP_FINALLY POP_BLOCK CALL_FINALLY returns
|
||||
|
||||
|
||||
# FIXME: DRY rules below
|
||||
tryfinally38rstmt ::= sf_pb_call_returns
|
||||
cf_cf_finally
|
||||
ss_end_finally
|
||||
tryfinally38rstmt ::= sf_pb_call_returns
|
||||
cf_cf_finally END_FINALLY
|
||||
suite_stmts
|
||||
tryfinally38rstmt ::= sf_pb_call_returns
|
||||
cf_cf_finally POP_FINALLY
|
||||
ss_end_finally
|
||||
tryfinally38rstmt ::= sf_bp_call_returns
|
||||
COME_FROM_FINALLY POP_FINALLY
|
||||
ss_end_finally
|
||||
|
||||
tryfinally38rstmt2 ::= lc_setup_finally POP_BLOCK call_finally_pt
|
||||
returns
|
||||
COME_FROM_FINALLY END_FINALLY suite_stmts
|
||||
tryfinally38rstmt ::= SETUP_FINALLY POP_BLOCK CALL_FINALLY
|
||||
returns
|
||||
COME_FROM_FINALLY POP_FINALLY returns
|
||||
END_FINALLY
|
||||
tryfinally38stmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
||||
BEGIN_FINALLY COME_FROM_FINALLY
|
||||
POP_FINALLY suite_stmts_opt END_FINALLY
|
||||
cf_cf_finally pop_finally_pt
|
||||
ss_end_finally POP_TOP
|
||||
tryfinally38rstmt3 ::= SETUP_FINALLY expr POP_BLOCK CALL_FINALLY RETURN_VALUE
|
||||
COME_FROM COME_FROM_FINALLY
|
||||
ss_end_finally
|
||||
|
||||
tryfinally38stmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
||||
BEGIN_FINALLY COME_FROM_FINALLY
|
||||
POP_FINALLY suite_stmts_opt END_FINALLY
|
||||
|
||||
tryfinally38astmt ::= LOAD_CONST SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
||||
BEGIN_FINALLY COME_FROM_FINALLY
|
||||
POP_FINALLY POP_TOP suite_stmts_opt END_FINALLY POP_TOP
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 by Rocky Bernstein
|
||||
# Copyright (c) 2019-2020 by Rocky Bernstein
|
||||
"""
|
||||
Python PyPy 3.3 decompiler scanner.
|
||||
|
||||
@@ -10,6 +10,7 @@ import uncompyle6.scanners.scanner33 as scan
|
||||
|
||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||
from xdis.opcodes import opcode_33pypy as opc
|
||||
|
||||
JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs)
|
||||
|
||||
# We base this off of 3.3
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -896,6 +896,7 @@ class Scanner3(Scanner):
|
||||
start, self.next_stmt[offset], self.opc.POP_JUMP_IF_FALSE, target
|
||||
)
|
||||
|
||||
# FIXME: Remoeve this whole "if" block
|
||||
# If we still have any offsets in set, start working on it
|
||||
if match:
|
||||
is_jump_forward = self.is_jump_forward(pre_rtarget)
|
||||
@@ -964,7 +965,7 @@ class Scanner3(Scanner):
|
||||
)
|
||||
):
|
||||
pass
|
||||
else:
|
||||
elif self.version <= 3.2:
|
||||
fix = None
|
||||
jump_ifs = self.inst_matches(
|
||||
start,
|
||||
|
@@ -339,7 +339,11 @@ TABLE_DIRECT = {
|
||||
"raise_stmt1": ("%|raise %c\n", 0),
|
||||
"raise_stmt3": ("%|raise %c, %c, %c\n", 0, 1, 2),
|
||||
# "yield": ( "yield %c", 0),
|
||||
# "return": ( "%|return %c\n", 0),
|
||||
|
||||
# Note: we have a custom rule, which calls when we don't
|
||||
# have "return None"
|
||||
"return": ( "%|return %c\n", 0),
|
||||
|
||||
"return_if_stmt": ("return %c\n", 0),
|
||||
"ifstmt": (
|
||||
"%|if %c:\n%+%c%-",
|
||||
|
@@ -29,9 +29,9 @@ def customize_for_version38(self, version):
|
||||
# del TABLE_DIRECT[lhs]
|
||||
|
||||
TABLE_DIRECT.update({
|
||||
'async_for_stmt38': (
|
||||
'%|async for %c in %c:\n%+%c%-%-\n\n',
|
||||
(7, 'store'), (0, 'expr'), (8, 'for_block') ),
|
||||
"async_for_stmt38": (
|
||||
"%|async for %c in %c:\n%+%c%-%-\n\n",
|
||||
(2, "store"), (0, "expr"), (3, "for_block") ),
|
||||
|
||||
'async_forelse_stmt38': (
|
||||
'%|async for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n',
|
||||
@@ -46,6 +46,10 @@ def customize_for_version38(self, version):
|
||||
(0, 'expr'), (6, 'store'),
|
||||
(7, 'suite_stmts') ),
|
||||
|
||||
"call_stmt": (
|
||||
"%|%c\n", 0
|
||||
),
|
||||
|
||||
'except_handler38': (
|
||||
'%c', (2, 'except_stmts') ),
|
||||
|
||||
@@ -101,12 +105,26 @@ def customize_for_version38(self, version):
|
||||
'try_except38': (
|
||||
'%|try:\n%+%c\n%-%|except:\n%|%-%c\n\n',
|
||||
(-2, 'suite_stmts_opt'), (-1, 'except_handler38a') ),
|
||||
'try_except_ret38': (
|
||||
'%|try:\n%+%|return %c%-\n%|except:\n%+%|%c%-\n\n',
|
||||
(1, 'expr'), (-1, 'except_ret38a') ),
|
||||
"try_except_ret38": (
|
||||
"%|try:\n%+%c%-\n%|except:\n%+%|%c%-\n\n",
|
||||
(1, "returns"),
|
||||
(2, "except_ret38a"),
|
||||
),
|
||||
'tryfinally38rstmt': (
|
||||
'%|try:\n%+%c%-%|finally:\n%+%c%-\n\n',
|
||||
(3, 'returns'), 6 ),
|
||||
(0, "sf_pb_call_returns"),
|
||||
(-1, ("ss_end_finally", "suite_stmts")),
|
||||
),
|
||||
"tryfinally38rstmt2": (
|
||||
"%|try:\n%+%c%-%|finally:\n%+%c%-\n\n",
|
||||
(4, "returns"),
|
||||
-2, "ss_end_finally"
|
||||
),
|
||||
"tryfinally38rstmt3": (
|
||||
"%|try:\n%+%|return %c%-\n%|finally:\n%+%c%-\n\n",
|
||||
(1, "expr"),
|
||||
(-1, "ss_end_finally")
|
||||
),
|
||||
'tryfinally38stmt': (
|
||||
'%|try:\n%+%c%-%|finally:\n%+%c%-\n\n',
|
||||
(1, "suite_stmts_opt"),
|
||||
|
@@ -65,8 +65,7 @@ The node position 0 will be associated with "import".
|
||||
|
||||
import re
|
||||
|
||||
from xdis import iscode
|
||||
from xdis.magics import sysinfo2float
|
||||
from xdis import iscode, sysinfo2float
|
||||
from uncompyle6.semantics import pysource
|
||||
from uncompyle6 import parser
|
||||
from uncompyle6.scanner import Token, Code, get_scanner
|
||||
|
@@ -16,8 +16,7 @@
|
||||
All the crazy things we have to do to handle Python functions in 3.0-3.5 or so.
|
||||
The saga of changes before and after is in other files.
|
||||
"""
|
||||
from xdis import iscode, code_has_star_arg, code_has_star_star_arg
|
||||
from xdis.util import CO_GENERATOR
|
||||
from xdis import iscode, code_has_star_arg, code_has_star_star_arg, CO_GENERATOR
|
||||
from uncompyle6.scanner import Code
|
||||
from uncompyle6.parsers.treenode import SyntaxTree
|
||||
from uncompyle6.semantics.parser_error import ParserError
|
||||
@@ -33,6 +32,7 @@ from uncompyle6.show import maybe_show_tree_param_default
|
||||
|
||||
# FIXME: DRY the below code...
|
||||
|
||||
|
||||
def make_function3_annotate(
|
||||
self, node, is_lambda, nested=1, code_node=None, annotate_last=-1
|
||||
):
|
||||
@@ -265,8 +265,8 @@ def make_function3_annotate(
|
||||
self.write("\n" + indent)
|
||||
line_number = self.line_number
|
||||
self.write(" -> ")
|
||||
if 'return' in annotate_dict:
|
||||
self.write(annotate_dict['return'])
|
||||
if "return" in annotate_dict:
|
||||
self.write(annotate_dict["return"])
|
||||
else:
|
||||
# value, string = annotate_args['return']
|
||||
# if string:
|
||||
@@ -423,9 +423,7 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None):
|
||||
lc_index = -3
|
||||
pass
|
||||
|
||||
if (len(node) > 2
|
||||
and (have_kwargs or node[lc_index].kind != "load_closure")
|
||||
):
|
||||
if len(node) > 2 and (have_kwargs or node[lc_index].kind != "load_closure"):
|
||||
|
||||
# Find the index in "node" where the first default
|
||||
# parameter value is located. Note this is in contrast to
|
||||
@@ -483,7 +481,7 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None):
|
||||
if is_lambda:
|
||||
kwargs = []
|
||||
for i in range(kwonlyargcount):
|
||||
paramnames.append(scanner_code.co_varnames[argc+i])
|
||||
paramnames.append(scanner_code.co_varnames[argc + i])
|
||||
pass
|
||||
else:
|
||||
kwargs = list(scanner_code.co_varnames[argc : argc + kwonlyargcount])
|
||||
@@ -686,5 +684,5 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None):
|
||||
if need_bogus_yield:
|
||||
self.template_engine(("%|if False:\n%+%|yield None%-",), node)
|
||||
|
||||
scanner_code._tokens = None # save memory
|
||||
scanner_code._tokens = None # save memory
|
||||
scanner_code._customize = None # save memory
|
||||
|
@@ -16,8 +16,13 @@
|
||||
All the crazy things we have to do to handle Python functions in 3.6 and above.
|
||||
The saga of changes before 3.6 is in other files.
|
||||
"""
|
||||
from xdis import iscode, code_has_star_arg, code_has_star_star_arg
|
||||
from xdis.util import CO_GENERATOR, CO_ASYNC_GENERATOR
|
||||
from xdis import (
|
||||
iscode,
|
||||
code_has_star_arg,
|
||||
code_has_star_star_arg,
|
||||
CO_GENERATOR,
|
||||
CO_ASYNC_GENERATOR,
|
||||
)
|
||||
from uncompyle6.scanner import Code
|
||||
from uncompyle6.parsers.treenode import SyntaxTree
|
||||
from uncompyle6.semantics.parser_error import ParserError
|
||||
@@ -103,9 +108,7 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
if annotate_node == "dict" and annotate_name_node.kind.startswith(
|
||||
"BUILD_CONST_KEY_MAP"
|
||||
):
|
||||
types = [
|
||||
self.traverse(n, indent="") for n in annotate_node[:-2]
|
||||
]
|
||||
types = [self.traverse(n, indent="") for n in annotate_node[:-2]]
|
||||
names = annotate_node[-2].attr
|
||||
l = len(types)
|
||||
assert l == len(names)
|
||||
@@ -328,9 +331,7 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
self.write(" -> %s" % annotate_dict["return"])
|
||||
self.println(":")
|
||||
|
||||
if (
|
||||
node[-2] == "docstring" and not is_lambda
|
||||
):
|
||||
if node[-2] == "docstring" and not is_lambda:
|
||||
# docstring exists, dump it
|
||||
self.println(self.traverse(node[-2]))
|
||||
|
||||
@@ -369,5 +370,5 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
if need_bogus_yield:
|
||||
self.template_engine(("%|if False:\n%+%|yield None%-",), node)
|
||||
|
||||
scanner_code._tokens = None # save memory
|
||||
scanner_code._tokens = None # save memory
|
||||
scanner_code._customize = None # save memory
|
||||
|
@@ -510,14 +510,14 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.preorder(node[0])
|
||||
self.prune()
|
||||
else:
|
||||
self.write(self.indent, "return")
|
||||
# One reason we worry over whether we use "return None" or "return"
|
||||
# is that inside a generator, "return None" is illegal.
|
||||
# Thank you, Python!
|
||||
if self.return_none or not self.is_return_none(node):
|
||||
self.write(" ")
|
||||
self.preorder(node[0])
|
||||
self.println()
|
||||
self.default(node)
|
||||
else:
|
||||
self.template_engine(("%|return\n",), node)
|
||||
|
||||
self.prune() # stop recursing
|
||||
|
||||
def n_return_if_stmt(self, node):
|
||||
@@ -2053,10 +2053,17 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
elif typ == "c":
|
||||
index = entry[arg]
|
||||
if isinstance(index, tuple):
|
||||
assert node[index[0]] == index[1], (
|
||||
"at %s[%d], expected '%s' node; got '%s'"
|
||||
% (node.kind, arg, index[1], node[index[0]].kind)
|
||||
)
|
||||
if isinstance(index[1], str):
|
||||
assert node[index[0]] == index[1], (
|
||||
"at %s[%d], expected '%s' node; got '%s'"
|
||||
% (node.kind, arg, index[1], node[index[0]].kind)
|
||||
)
|
||||
else:
|
||||
assert node[index[0]] in index[1], (
|
||||
"at %s[%d], expected to be in '%s' node; got '%s'"
|
||||
% (node.kind, arg, index[1], node[index[0]].kind)
|
||||
)
|
||||
|
||||
index = index[0]
|
||||
assert isinstance(
|
||||
index, int
|
||||
@@ -2065,6 +2072,16 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
arg,
|
||||
type(index),
|
||||
)
|
||||
|
||||
try:
|
||||
node[index]
|
||||
except IndexError:
|
||||
raise RuntimeError(
|
||||
"""
|
||||
Expanding '%' in template '%s[%s]':
|
||||
%s is invalid; has only %d entries
|
||||
""" % (node,kind, enty, arg, index, len(node))
|
||||
)
|
||||
self.preorder(node[index])
|
||||
|
||||
arg += 1
|
||||
|
@@ -10,6 +10,6 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# This file is suitable for sourcing inside bash as
|
||||
# This file is suitable for sourcing inside POSIX shell as
|
||||
# well as importing into Python
|
||||
VERSION="3.6.7" # noqa
|
||||
|
Reference in New Issue
Block a user