You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
Merge branch 'master' into python-2.4
This commit is contained in:
11
NEWS.md
11
NEWS.md
@@ -1,3 +1,14 @@
|
|||||||
|
3.7.4: 2020-8-05
|
||||||
|
================
|
||||||
|
|
||||||
|
* Fragment parsing was borked. This means deparsing in trepan2/trepan3k was broken
|
||||||
|
* 3.7+: narrow precedence for call tatement
|
||||||
|
* del_stmt -> delete to better match Python AST
|
||||||
|
* 3.8+ Add another `forelsestmt` (found only in a loop)
|
||||||
|
* 3.8+ Add precedence on walrus operator
|
||||||
|
* More files blackened
|
||||||
|
* bump min xdis version
|
||||||
|
|
||||||
3.7.3: 2020-7-25
|
3.7.3: 2020-7-25
|
||||||
================
|
================
|
||||||
|
|
||||||
|
@@ -33,65 +33,71 @@
|
|||||||
# 3.4 | pip | 19.1.1 |
|
# 3.4 | pip | 19.1.1 |
|
||||||
|
|
||||||
# Things that change more often go here.
|
# Things that change more often go here.
|
||||||
copyright = """
|
copyright = """
|
||||||
Copyright (C) 2015-2020 Rocky Bernstein <rb@dustyfeet.com>.
|
Copyright (C) 2015-2020 Rocky Bernstein <rb@dustyfeet.com>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
classifiers = ["Development Status :: 5 - Production/Stable",
|
classifiers = [
|
||||||
"Intended Audience :: Developers",
|
"Development Status :: 5 - Production/Stable",
|
||||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
"Intended Audience :: Developers",
|
||||||
"Operating System :: OS Independent",
|
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||||
"Programming Language :: Python",
|
"Operating System :: OS Independent",
|
||||||
"Programming Language :: Python :: 2.4",
|
"Programming Language :: Python",
|
||||||
"Programming Language :: Python :: 2.5",
|
"Programming Language :: Python :: 2.4",
|
||||||
"Programming Language :: Python :: 2.6",
|
"Programming Language :: Python :: 2.5",
|
||||||
"Programming Language :: Python :: 2.7",
|
"Programming Language :: Python :: 2.6",
|
||||||
"Programming Language :: Python :: 3.0",
|
"Programming Language :: Python :: 2.7",
|
||||||
"Programming Language :: Python :: 3.1",
|
"Programming Language :: Python :: 3.0",
|
||||||
"Programming Language :: Python :: 3.2",
|
"Programming Language :: Python :: 3.1",
|
||||||
"Programming Language :: Python :: 3.3",
|
"Programming Language :: Python :: 3.2",
|
||||||
"Programming Language :: Python :: 3.4",
|
"Programming Language :: Python :: 3.3",
|
||||||
"Programming Language :: Python :: 3.5",
|
"Programming Language :: Python :: 3.4",
|
||||||
"Programming Language :: Python :: 3.6",
|
"Programming Language :: Python :: 3.5",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.6",
|
||||||
"Programming Language :: Python :: 3.8",
|
"Programming Language :: Python :: 3.7",
|
||||||
"Topic :: Software Development :: Debuggers",
|
"Programming Language :: Python :: 3.8",
|
||||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
"Topic :: Software Development :: Debuggers",
|
||||||
]
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
]
|
||||||
|
|
||||||
# The rest in alphabetic order
|
# The rest in alphabetic order
|
||||||
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
|
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
|
||||||
author_email = "rb@dustyfeet.com"
|
author_email = "rb@dustyfeet.com"
|
||||||
entry_points = {
|
entry_points = {
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"uncompyle6=uncompyle6.bin.uncompile:main_bin",
|
"uncompyle6=uncompyle6.bin.uncompile:main_bin",
|
||||||
"pydisassemble=uncompyle6.bin.pydisassemble:main",
|
"pydisassemble=uncompyle6.bin.pydisassemble:main",
|
||||||
]}
|
]
|
||||||
ftp_url = None
|
}
|
||||||
install_requires = ["spark-parser >= 1.8.9, < 1.9.0",
|
ftp_url = None
|
||||||
"xdis >= 4.7.0, <5.1.0"]
|
install_requires = ["spark-parser >= 1.8.9, < 1.9.0", "xdis >= 5.0.4, <5.1.0"]
|
||||||
|
|
||||||
license = "GPL3"
|
license = "GPL3"
|
||||||
mailing_list = "python-debugger@googlegroups.com"
|
mailing_list = "python-debugger@googlegroups.com"
|
||||||
modname = "uncompyle6"
|
modname = "uncompyle6"
|
||||||
py_modules = None
|
py_modules = None
|
||||||
short_desc = "Python cross-version byte-code decompiler"
|
short_desc = "Python cross-version byte-code decompiler"
|
||||||
web = "https://github.com/rocky/python-uncompyle6/"
|
web = "https://github.com/rocky/python-uncompyle6/"
|
||||||
|
|
||||||
# tracebacks in zip files are funky and not debuggable
|
# tracebacks in zip files are funky and not debuggable
|
||||||
zip_safe = True
|
zip_safe = True
|
||||||
|
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
|
||||||
def get_srcdir():
|
def get_srcdir():
|
||||||
filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__)))
|
filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__)))
|
||||||
return os.path.realpath(filename)
|
return os.path.realpath(filename)
|
||||||
|
|
||||||
|
|
||||||
srcdir = get_srcdir()
|
srcdir = get_srcdir()
|
||||||
|
|
||||||
|
|
||||||
def read(*rnames):
|
def read(*rnames):
|
||||||
return open(os.path.join(srcdir, *rnames)).read()
|
return open(os.path.join(srcdir, *rnames)).read()
|
||||||
|
|
||||||
|
|
||||||
# Get info from files; set: long_description and VERSION
|
# Get info from files; set: long_description and VERSION
|
||||||
long_description = ( read("README.rst") + "\n" )
|
long_description = read("README.rst") + "\n"
|
||||||
exec(read("uncompyle6/version.py"))
|
exec(read("uncompyle6/version.py"))
|
||||||
|
@@ -5,4 +5,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
|
|||||||
echo "This script should be *sourced* rather than run directly through bash"
|
echo "This script should be *sourced* rather than run directly through bash"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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.4'
|
export PYVERSIONS='3.5.9 3.6.12 2.6.9 3.3.7 2.7.18 3.2.6 3.1.5 3.4.10 3.7.9 3.8.5'
|
||||||
|
@@ -50,7 +50,7 @@ for VERSION in $PYVERSIONS ; do
|
|||||||
LOGFILE=/tmp/${MAIN}-$VERSION-$$.log
|
LOGFILE=/tmp/${MAIN}-$VERSION-$$.log
|
||||||
|
|
||||||
case "$VERSION" in
|
case "$VERSION" in
|
||||||
3.7.7 | 3.8.3 | 3.1.5 | 3.0.1 )
|
3.7.8 | 3.8.5 | 3.1.5 | 3.0.1 )
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
3.5.9 )
|
3.5.9 )
|
||||||
@@ -65,7 +65,7 @@ for VERSION in $PYVERSIONS ; do
|
|||||||
3.4.10 )
|
3.4.10 )
|
||||||
MAX_TESTS=800
|
MAX_TESTS=800
|
||||||
;;
|
;;
|
||||||
3.6.10 )
|
3.6.11 )
|
||||||
# MAX_TESTS=1300 # about 2139 exist
|
# MAX_TESTS=1300 # about 2139 exist
|
||||||
# fails on _pyio.cpython-36.opt-1.pyc
|
# fails on _pyio.cpython-36.opt-1.pyc
|
||||||
MAX_TESTS=34
|
MAX_TESTS=34
|
||||||
|
@@ -8,7 +8,7 @@ b = [4, 5, 6]
|
|||||||
del b[1]
|
del b[1]
|
||||||
del b[:]
|
del b[:]
|
||||||
|
|
||||||
# del_stmt ::= expr expr DELETE_SLICE+1
|
# delete ::= expr expr DELETE_SLICE+1
|
||||||
l = [None] * 10
|
l = [None] * 10
|
||||||
del l[-2:]
|
del l[-2:]
|
||||||
|
|
||||||
|
@@ -8,6 +8,37 @@ SKIP_TESTS=(
|
|||||||
[test_urllib2.py]=1 # FIXME: works on uncompyle6?
|
[test_urllib2.py]=1 # FIXME: works on uncompyle6?
|
||||||
[test_zipimport.py]=1 # FIXME: works on uncompyle6
|
[test_zipimport.py]=1 # FIXME: works on uncompyle6
|
||||||
|
|
||||||
|
# From decompyle3 excludes
|
||||||
|
# Very Simple example. Compare with 3.7 Need 3.8 parse rules for exception handling return
|
||||||
|
# for proto in p:
|
||||||
|
# try:
|
||||||
|
# drop = 5
|
||||||
|
# except StopIteration:
|
||||||
|
# continue
|
||||||
|
|
||||||
|
[test_dict.py]=1 #
|
||||||
|
|
||||||
|
# Simple example. Compare with 3.7 Need 3.8 parse rules for exception handling return
|
||||||
|
# try:
|
||||||
|
# return 5
|
||||||
|
# except KeyError:
|
||||||
|
# return res
|
||||||
|
# except TypeError:
|
||||||
|
# return 10
|
||||||
|
|
||||||
|
# These and the above may be due to new code generation or tests
|
||||||
|
# between 3.8.3 and 3.8.5 ?
|
||||||
|
[test_decorators.py]=1 #
|
||||||
|
|
||||||
|
[test_dtrace.py]=1 #
|
||||||
|
[test_exceptions.py]=1 #
|
||||||
|
[test_ftplib.py]=1 #
|
||||||
|
[test_gc.py]=1 #
|
||||||
|
[test_gzip.py]=1 #
|
||||||
|
[test_hashlib.py]=1 #
|
||||||
|
[test_iter.py]=1 #
|
||||||
|
[test_itertools.py]=1 #
|
||||||
|
|
||||||
[test___all__.py]=1 # it fails on its own
|
[test___all__.py]=1 # it fails on its own
|
||||||
[test_argparse.py]=1 #- it fails on its own
|
[test_argparse.py]=1 #- it fails on its own
|
||||||
[test_array.py]=1 #- parse error
|
[test_array.py]=1 #- parse error
|
||||||
|
@@ -52,7 +52,7 @@ for VERSION in $PYVERSIONS ; do
|
|||||||
LOGFILE=/tmp/runtests-$VERSION-$$.log
|
LOGFILE=/tmp/runtests-$VERSION-$$.log
|
||||||
|
|
||||||
case "$VERSION" in
|
case "$VERSION" in
|
||||||
3.0.1 | 3.1.5 | 3.2.6 | 3.8.1 )
|
3.0.1 | 3.1.5 | 3.2.6 | 3.8.5 )
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
2
tox.ini
2
tox.ini
@@ -3,7 +3,7 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
exclude = .tox,./build,./trepan/processor/command/tmp
|
exclude = .tox,./build,./trepan/processor/command/tmp
|
||||||
filename = *.py
|
filename = *.py
|
||||||
ignore = C901,E113,E121,E122,E123,E124,E125,E126,E127,E128,E129,E201,E202,E203,E221,E222,E225,E226,E241,E242,E251,E261,E271,E272,E302,E401,E402,E501,F401,E701,E702
|
ignore = C901,E113,E121,E122,E123,E124,E125,E126,E127,E128,E129,E201,E202,E203,E221,E222,E225,E226,E241,E242,E251,E261,E271,E272,E302,E401,E402,E501,F401,E701,E702,W503
|
||||||
|
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py27, py34, pypy
|
envlist = py27, py34, pypy
|
||||||
|
@@ -352,10 +352,10 @@ class PythonParser(GenericASTBuilder):
|
|||||||
stmt ::= with
|
stmt ::= with
|
||||||
stmt ::= withasstmt
|
stmt ::= withasstmt
|
||||||
|
|
||||||
stmt ::= del_stmt
|
stmt ::= delete
|
||||||
del_stmt ::= DELETE_FAST
|
delete ::= DELETE_FAST
|
||||||
del_stmt ::= DELETE_NAME
|
delete ::= DELETE_NAME
|
||||||
del_stmt ::= DELETE_GLOBAL
|
delete ::= DELETE_GLOBAL
|
||||||
|
|
||||||
|
|
||||||
stmt ::= return
|
stmt ::= return
|
||||||
|
@@ -97,9 +97,9 @@ class Python2Parser(PythonParser):
|
|||||||
for ::= SETUP_LOOP expr for_iter store
|
for ::= SETUP_LOOP expr for_iter store
|
||||||
for_block POP_BLOCK _come_froms
|
for_block POP_BLOCK _come_froms
|
||||||
|
|
||||||
del_stmt ::= delete_subscript
|
delete ::= delete_subscript
|
||||||
delete_subscript ::= expr expr DELETE_SUBSCR
|
delete_subscript ::= expr expr DELETE_SUBSCR
|
||||||
del_stmt ::= expr DELETE_ATTR
|
delete ::= expr DELETE_ATTR
|
||||||
|
|
||||||
_mklambda ::= load_closure mklambda
|
_mklambda ::= load_closure mklambda
|
||||||
kwarg ::= LOAD_CONST expr
|
kwarg ::= LOAD_CONST expr
|
||||||
@@ -421,17 +421,17 @@ class Python2Parser(PythonParser):
|
|||||||
custom_seen_ops.add(opname)
|
custom_seen_ops.add(opname)
|
||||||
continue
|
continue
|
||||||
elif opname == "DELETE_ATTR":
|
elif opname == "DELETE_ATTR":
|
||||||
self.addRule("del_stmt ::= expr DELETE_ATTR", nop_func)
|
self.addRule("delete ::= expr DELETE_ATTR", nop_func)
|
||||||
custom_seen_ops.add(opname)
|
custom_seen_ops.add(opname)
|
||||||
continue
|
continue
|
||||||
elif opname.startswith("DELETE_SLICE"):
|
elif opname.startswith("DELETE_SLICE"):
|
||||||
self.addRule(
|
self.addRule(
|
||||||
"""
|
"""
|
||||||
del_expr ::= expr
|
del_expr ::= expr
|
||||||
del_stmt ::= del_expr DELETE_SLICE+0
|
delete ::= del_expr DELETE_SLICE+0
|
||||||
del_stmt ::= del_expr del_expr DELETE_SLICE+1
|
delete ::= del_expr del_expr DELETE_SLICE+1
|
||||||
del_stmt ::= del_expr del_expr DELETE_SLICE+2
|
delete ::= del_expr del_expr DELETE_SLICE+2
|
||||||
del_stmt ::= del_expr del_expr del_expr DELETE_SLICE+3
|
delete ::= del_expr del_expr del_expr DELETE_SLICE+3
|
||||||
""",
|
""",
|
||||||
nop_func,
|
nop_func,
|
||||||
)
|
)
|
||||||
@@ -451,7 +451,7 @@ class Python2Parser(PythonParser):
|
|||||||
elif opname == "DELETE_SUBSCR":
|
elif opname == "DELETE_SUBSCR":
|
||||||
self.addRule(
|
self.addRule(
|
||||||
"""
|
"""
|
||||||
del_stmt ::= delete_subscript
|
delete ::= delete_subscript
|
||||||
delete_subscript ::= expr expr DELETE_SUBSCR
|
delete_subscript ::= expr expr DELETE_SUBSCR
|
||||||
""",
|
""",
|
||||||
nop_func,
|
nop_func,
|
||||||
|
@@ -48,7 +48,7 @@ class Python23Parser(Python24Parser):
|
|||||||
while1stmt ::= _while1test l_stmts JUMP_BACK
|
while1stmt ::= _while1test l_stmts JUMP_BACK
|
||||||
POP_TOP POP_BLOCK
|
POP_TOP POP_BLOCK
|
||||||
|
|
||||||
list_comp ::= BUILD_LIST_0 DUP_TOP LOAD_ATTR store list_iter del_stmt
|
list_comp ::= BUILD_LIST_0 DUP_TOP LOAD_ATTR store list_iter delete
|
||||||
list_for ::= expr for_iter store list_iter JUMP_BACK come_froms POP_TOP JUMP_BACK
|
list_for ::= expr for_iter store list_iter JUMP_BACK come_froms POP_TOP JUMP_BACK
|
||||||
|
|
||||||
lc_body ::= LOAD_NAME expr CALL_FUNCTION_1 POP_TOP
|
lc_body ::= LOAD_NAME expr CALL_FUNCTION_1 POP_TOP
|
||||||
|
@@ -230,9 +230,9 @@ class Python26Parser(Python2Parser):
|
|||||||
list_iter ::= list_if JUMP_BACK
|
list_iter ::= list_if JUMP_BACK
|
||||||
list_iter ::= list_if JUMP_BACK COME_FROM POP_TOP
|
list_iter ::= list_if JUMP_BACK COME_FROM POP_TOP
|
||||||
list_comp ::= BUILD_LIST_0 DUP_TOP
|
list_comp ::= BUILD_LIST_0 DUP_TOP
|
||||||
store list_iter del_stmt
|
store list_iter delete
|
||||||
list_comp ::= BUILD_LIST_0 DUP_TOP
|
list_comp ::= BUILD_LIST_0 DUP_TOP
|
||||||
store list_iter JUMP_BACK del_stmt
|
store list_iter JUMP_BACK delete
|
||||||
lc_body ::= LOAD_NAME expr LIST_APPEND
|
lc_body ::= LOAD_NAME expr LIST_APPEND
|
||||||
lc_body ::= LOAD_FAST expr LIST_APPEND
|
lc_body ::= LOAD_FAST expr LIST_APPEND
|
||||||
|
|
||||||
|
@@ -254,7 +254,7 @@ class Python3Parser(PythonParser):
|
|||||||
END_FINALLY _jump
|
END_FINALLY _jump
|
||||||
|
|
||||||
except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM_FINALLY
|
except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM_FINALLY
|
||||||
LOAD_CONST store del_stmt
|
LOAD_CONST store delete
|
||||||
|
|
||||||
except_suite ::= returns
|
except_suite ::= returns
|
||||||
|
|
||||||
@@ -935,7 +935,7 @@ class Python3Parser(PythonParser):
|
|||||||
self.addRule("continue ::= CONTINUE_LOOP", nop_func)
|
self.addRule("continue ::= CONTINUE_LOOP", nop_func)
|
||||||
custom_ops_processed.add(opname)
|
custom_ops_processed.add(opname)
|
||||||
elif opname == "DELETE_ATTR":
|
elif opname == "DELETE_ATTR":
|
||||||
self.addRule("del_stmt ::= expr DELETE_ATTR", nop_func)
|
self.addRule("delete ::= expr DELETE_ATTR", nop_func)
|
||||||
custom_ops_processed.add(opname)
|
custom_ops_processed.add(opname)
|
||||||
elif opname == "DELETE_DEREF":
|
elif opname == "DELETE_DEREF":
|
||||||
self.addRule(
|
self.addRule(
|
||||||
@@ -949,7 +949,7 @@ class Python3Parser(PythonParser):
|
|||||||
elif opname == "DELETE_SUBSCR":
|
elif opname == "DELETE_SUBSCR":
|
||||||
self.addRule(
|
self.addRule(
|
||||||
"""
|
"""
|
||||||
del_stmt ::= delete_subscript
|
delete ::= delete_subscript
|
||||||
delete_subscript ::= expr expr DELETE_SUBSCR
|
delete_subscript ::= expr expr DELETE_SUBSCR
|
||||||
""",
|
""",
|
||||||
nop_func,
|
nop_func,
|
||||||
|
@@ -17,15 +17,15 @@ class Python31Parser(Python32Parser):
|
|||||||
with ::= expr setupwith SETUP_FINALLY
|
with ::= expr setupwith SETUP_FINALLY
|
||||||
suite_stmts_opt
|
suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
|
||||||
load del_stmt WITH_CLEANUP END_FINALLY
|
load delete WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
# Keeps Python 3.1 withas desigator in the same position as it is in other version
|
# Keeps Python 3.1 withas desigator in the same position as it is in other version
|
||||||
setupwithas31 ::= setupwithas SETUP_FINALLY load del_stmt
|
setupwithas31 ::= setupwithas SETUP_FINALLY load delete
|
||||||
|
|
||||||
withasstmt ::= expr setupwithas31 store
|
withasstmt ::= expr setupwithas31 store
|
||||||
suite_stmts_opt
|
suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
|
||||||
load del_stmt WITH_CLEANUP END_FINALLY
|
load delete WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
store ::= STORE_NAME
|
store ::= STORE_NAME
|
||||||
load ::= LOAD_FAST
|
load ::= LOAD_FAST
|
||||||
|
@@ -112,10 +112,10 @@ class Python37Parser(Python37BaseParser):
|
|||||||
stmt ::= tryelsestmt
|
stmt ::= tryelsestmt
|
||||||
stmt ::= tryfinallystmt
|
stmt ::= tryfinallystmt
|
||||||
|
|
||||||
stmt ::= del_stmt
|
stmt ::= delete
|
||||||
del_stmt ::= DELETE_FAST
|
delete ::= DELETE_FAST
|
||||||
del_stmt ::= DELETE_NAME
|
delete ::= DELETE_NAME
|
||||||
del_stmt ::= DELETE_GLOBAL
|
delete ::= DELETE_GLOBAL
|
||||||
|
|
||||||
stmt ::= return
|
stmt ::= return
|
||||||
return ::= ret_expr RETURN_VALUE
|
return ::= ret_expr RETURN_VALUE
|
||||||
@@ -888,7 +888,7 @@ class Python37Parser(Python37BaseParser):
|
|||||||
END_FINALLY _jump
|
END_FINALLY _jump
|
||||||
|
|
||||||
except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM_FINALLY
|
except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM_FINALLY
|
||||||
LOAD_CONST store del_stmt
|
LOAD_CONST store delete
|
||||||
|
|
||||||
except_suite ::= returns
|
except_suite ::= returns
|
||||||
|
|
||||||
|
@@ -541,7 +541,7 @@ class Python37BaseParser(PythonParser):
|
|||||||
self.addRule("continue ::= CONTINUE_LOOP", nop_func)
|
self.addRule("continue ::= CONTINUE_LOOP", nop_func)
|
||||||
custom_ops_processed.add(opname)
|
custom_ops_processed.add(opname)
|
||||||
elif opname == "DELETE_ATTR":
|
elif opname == "DELETE_ATTR":
|
||||||
self.addRule("del_stmt ::= expr DELETE_ATTR", nop_func)
|
self.addRule("delete ::= expr DELETE_ATTR", nop_func)
|
||||||
custom_ops_processed.add(opname)
|
custom_ops_processed.add(opname)
|
||||||
elif opname == "DELETE_DEREF":
|
elif opname == "DELETE_DEREF":
|
||||||
self.addRule(
|
self.addRule(
|
||||||
@@ -555,7 +555,7 @@ class Python37BaseParser(PythonParser):
|
|||||||
elif opname == "DELETE_SUBSCR":
|
elif opname == "DELETE_SUBSCR":
|
||||||
self.addRule(
|
self.addRule(
|
||||||
"""
|
"""
|
||||||
del_stmt ::= delete_subscript
|
delete ::= delete_subscript
|
||||||
delete_subscript ::= expr expr DELETE_SUBSCR
|
delete_subscript ::= expr expr DELETE_SUBSCR
|
||||||
""",
|
""",
|
||||||
nop_func,
|
nop_func,
|
||||||
|
@@ -111,6 +111,8 @@ class Python38Parser(Python37Parser):
|
|||||||
for38 ::= expr get_for_iter store for_block
|
for38 ::= expr get_for_iter store for_block
|
||||||
|
|
||||||
forelsestmt38 ::= expr get_for_iter store for_block POP_BLOCK else_suite
|
forelsestmt38 ::= expr get_for_iter store for_block POP_BLOCK else_suite
|
||||||
|
forelsestmt38 ::= expr get_for_iter store for_block JUMP_BACK _come_froms else_suite
|
||||||
|
|
||||||
forelselaststmt38 ::= expr get_for_iter store for_block POP_BLOCK else_suitec
|
forelselaststmt38 ::= expr get_for_iter store for_block POP_BLOCK else_suitec
|
||||||
forelselaststmtl38 ::= expr get_for_iter store for_block POP_BLOCK else_suitel
|
forelselaststmtl38 ::= expr get_for_iter store for_block POP_BLOCK else_suitel
|
||||||
|
|
||||||
|
@@ -76,8 +76,8 @@ if PYTHON3:
|
|||||||
intern = sys.intern
|
intern = sys.intern
|
||||||
L65536 = 65536
|
L65536 = 65536
|
||||||
|
|
||||||
def long(l):
|
def long(num):
|
||||||
return l
|
return num
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@@ -327,7 +327,10 @@ TABLE_DIRECT = {
|
|||||||
# For compatibility with older Python, we'll use "%" instead of
|
# For compatibility with older Python, we'll use "%" instead of
|
||||||
# a format string.
|
# a format string.
|
||||||
"string_at_beginning": ('%|"%%s" %% %c\n', 0),
|
"string_at_beginning": ('%|"%%s" %% %c\n', 0),
|
||||||
"call_stmt": ("%|%p\n", (0, 200)),
|
"call_stmt": ( "%|%p\n",
|
||||||
|
# When a call statement contains only a named_expr (:=)
|
||||||
|
# the named_expr should have parenthesis around it.
|
||||||
|
(0, PRECEDENCE["named_expr"]-1)),
|
||||||
"break": ("%|break\n",),
|
"break": ("%|break\n",),
|
||||||
"continue": ("%|continue\n",),
|
"continue": ("%|continue\n",),
|
||||||
"raise_stmt0": ("%|raise\n",),
|
"raise_stmt0": ("%|raise\n",),
|
||||||
@@ -436,7 +439,7 @@ MAP_R = (TABLE_R, -1)
|
|||||||
MAP = {
|
MAP = {
|
||||||
"stmt": MAP_R,
|
"stmt": MAP_R,
|
||||||
"call": MAP_R,
|
"call": MAP_R,
|
||||||
"del_stmt": MAP_R,
|
"delete": MAP_R,
|
||||||
"store": MAP_R,
|
"store": MAP_R,
|
||||||
"exprlist": MAP_R0,
|
"exprlist": MAP_R0,
|
||||||
}
|
}
|
||||||
|
@@ -149,6 +149,11 @@ def customize_for_version37(self, version):
|
|||||||
(1, "store"), (0, "get_aiter"), (3, "list_iter"),
|
(1, "store"), (0, "get_aiter"), (3, "list_iter"),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
"list_afor": (
|
||||||
|
" async for %[1]{%c} in %c%[1]{%c}",
|
||||||
|
(1, "store"), (0, "get_aiter"), (3, "list_iter"),
|
||||||
|
),
|
||||||
|
|
||||||
"list_if37": (" if %p%c", (0, 27), 1),
|
"list_if37": (" if %p%c", (0, 27), 1),
|
||||||
"list_if37_not": (" if not %p%c", (0, 27), 1),
|
"list_if37_not": (" if not %p%c", (0, 27), 1),
|
||||||
"testfalse_not_or": ("not %c or %c", (0, "expr"), (2, "expr")),
|
"testfalse_not_or": ("not %c or %c", (0, "expr"), (2, "expr")),
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2019 by Rocky Bernstein
|
# Copyright (c) 2019-2020 by Rocky Bernstein
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
# Python 3.8+ changes
|
# Python 3.8+ changes
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
from uncompyle6.semantics.consts import TABLE_DIRECT
|
from uncompyle6.semantics.consts import PRECEDENCE, TABLE_DIRECT
|
||||||
|
|
||||||
def customize_for_version38(self, version):
|
def customize_for_version38(self, version):
|
||||||
|
|
||||||
@@ -37,14 +37,15 @@ def customize_for_version38(self, version):
|
|||||||
'%|async for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n',
|
'%|async for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n',
|
||||||
(7, 'store'), (0, 'expr'), (8, 'for_block'), (-1, 'else_suite') ),
|
(7, 'store'), (0, 'expr'), (8, 'for_block'), (-1, 'else_suite') ),
|
||||||
|
|
||||||
'async_with_stmt38': (
|
"async_with_stmt38": (
|
||||||
'%|async with %c:\n%+%|%c%-',
|
"%|async with %c:\n%+%|%c%-",
|
||||||
(0, 'expr'), 7),
|
(0, "expr"), 7),
|
||||||
|
|
||||||
'async_with_as_stmt38': (
|
"async_with_as_stmt38": (
|
||||||
'%|async with %c as %c:\n%+%|%c%-',
|
"%|async with %c as %c:\n%+%|%c%-",
|
||||||
(0, 'expr'), (6, 'store'),
|
(0, "expr"), (6, "store"),
|
||||||
(7, 'suite_stmts') ),
|
(7, "suite_stmts")
|
||||||
|
),
|
||||||
|
|
||||||
"call_stmt": (
|
"call_stmt": (
|
||||||
"%|%c\n", 0
|
"%|%c\n", 0
|
||||||
@@ -80,11 +81,13 @@ def customize_for_version38(self, version):
|
|||||||
(2, 'store'),
|
(2, 'store'),
|
||||||
(0, 'expr'),
|
(0, 'expr'),
|
||||||
(3, 'for_block') ),
|
(3, 'for_block') ),
|
||||||
'forelsestmt38': (
|
|
||||||
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n',
|
"forelsestmt38": (
|
||||||
(2, 'store'),
|
"%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
|
||||||
(0, 'expr'),
|
(2, "store"),
|
||||||
(3, 'for_block'), -2 ),
|
(0, "expr"),
|
||||||
|
(3, "for_block"), -1 ),
|
||||||
|
|
||||||
'forelselaststmt38': (
|
'forelselaststmt38': (
|
||||||
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-',
|
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-',
|
||||||
(2, 'store'),
|
(2, 'store'),
|
||||||
@@ -153,6 +156,6 @@ def customize_for_version38(self, version):
|
|||||||
(2, "suite_stmts_opt"),
|
(2, "suite_stmts_opt"),
|
||||||
(8, "suite_stmts_opt") ),
|
(8, "suite_stmts_opt") ),
|
||||||
"named_expr": ( # AKA "walrus operator"
|
"named_expr": ( # AKA "walrus operator"
|
||||||
"%c := %c", (2, "store"), (0, "expr")
|
"%c := %p", (2, "store"), (0, "expr", PRECEDENCE["named_expr"]-1)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@@ -260,7 +260,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
raise GenericASTTraversalPruningException
|
raise GenericASTTraversalPruningException
|
||||||
|
|
||||||
n_slice0 = n_slice1 = n_slice2 = n_slice3 = n_subscript = table_r_node
|
n_slice0 = n_slice1 = n_slice2 = n_slice3 = n_subscript = table_r_node
|
||||||
n_aug_assign_1 = n_print_item = exec_stmt = print_to_item = del_stmt = table_r_node
|
n_aug_assign_1 = n_print_item = exec_stmt = print_to_item = delete = table_r_node
|
||||||
n_classdefco1 = n_classdefco2 = except_cond1 = except_cond2 = table_r_node
|
n_classdefco1 = n_classdefco2 = except_cond1 = except_cond2 = table_r_node
|
||||||
|
|
||||||
def n_pass(self, node):
|
def n_pass(self, node):
|
||||||
@@ -1211,7 +1211,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
p_insts = self.p.insts
|
p_insts = self.p.insts
|
||||||
self.p.insts = self.scanner.insts
|
self.p.insts = self.scanner.insts
|
||||||
self.p.offset2inst_index = self.scanner.offset2inst_index
|
self.p.offset2inst_index = self.scanner.offset2inst_index
|
||||||
ast = parser.parse(self.p, tokens, customize)
|
ast = parser.parse(self.p, tokens, customize, code)
|
||||||
self.p.insts = p_insts
|
self.p.insts = p_insts
|
||||||
except (parser.ParserError(e), AssertionError(e)):
|
except (parser.ParserError(e), AssertionError(e)):
|
||||||
raise ParserError(e, tokens, {})
|
raise ParserError(e, tokens, {})
|
||||||
@@ -1555,7 +1555,8 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
line_seperator = ",\n" + self.indent
|
line_seperator = ",\n" + self.indent
|
||||||
sep = INDENT_PER_LEVEL[:-1]
|
sep = INDENT_PER_LEVEL[:-1]
|
||||||
start = len(self.f.getvalue())
|
start = len(self.f.getvalue())
|
||||||
self.write("{")
|
if node[0] != "dict_entry":
|
||||||
|
self.write("{")
|
||||||
self.set_pos_info(node[0], start, start + 1)
|
self.set_pos_info(node[0], start, start + 1)
|
||||||
|
|
||||||
if self.version >= 3.0 and not self.is_pypy:
|
if self.version >= 3.0 and not self.is_pypy:
|
||||||
@@ -1581,7 +1582,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
i += 2
|
i += 2
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
elif node[1].kind.startswith("kvlist"):
|
elif len(node) > 1 and node[1].kind.startswith("kvlist"):
|
||||||
# Python 3.0..3.4 style key/value list in dict
|
# Python 3.0..3.4 style key/value list in dict
|
||||||
kv_node = node[1]
|
kv_node = node[1]
|
||||||
l = list(kv_node)
|
l = list(kv_node)
|
||||||
@@ -1607,37 +1608,98 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
i += 3
|
i += 3
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
|
elif node[-1].kind.startswith("BUILD_CONST_KEY_MAP"):
|
||||||
|
# Python 3.6+ style const map
|
||||||
|
keys = node[-2].pattr
|
||||||
|
values = node[:-2]
|
||||||
|
# FIXME: Line numbers?
|
||||||
|
for key, value in zip(keys, values):
|
||||||
|
self.write(sep)
|
||||||
|
self.write(repr(key))
|
||||||
|
line_number = self.line_number
|
||||||
|
self.write(":")
|
||||||
|
self.write(self.traverse(value[0]))
|
||||||
|
sep = ", "
|
||||||
|
if line_number != self.line_number:
|
||||||
|
sep += "\n" + self.indent + INDENT_PER_LEVEL[:-1]
|
||||||
|
line_number = self.line_number
|
||||||
|
else:
|
||||||
|
sep += " "
|
||||||
|
pass
|
||||||
|
pass
|
||||||
|
if sep.startswith(",\n"):
|
||||||
|
self.write(sep[1:])
|
||||||
|
pass
|
||||||
|
elif node[0].kind.startswith("dict_entry"):
|
||||||
|
assert self.version >= 3.5
|
||||||
|
template = ("%C", (0, len(node[0]), ", **"))
|
||||||
|
self.template_engine(template, node[0])
|
||||||
|
sep = ""
|
||||||
|
elif node[-1].kind.startswith("BUILD_MAP_UNPACK") or node[
|
||||||
|
-1
|
||||||
|
].kind.startswith("dict_entry"):
|
||||||
|
assert self.version >= 3.5
|
||||||
|
# FIXME: I think we can intermingle dict_comp's with other
|
||||||
|
# dictionary kinds of things. The most common though is
|
||||||
|
# a sequence of dict_comp's
|
||||||
|
kwargs = node[-1].attr
|
||||||
|
template = ("**%C", (0, kwargs, ", **"))
|
||||||
|
self.template_engine(template, node)
|
||||||
|
sep = ""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# Python 2 style kvlist
|
# Python 2 style kvlist. Find beginning of kvlist.
|
||||||
assert node[-1].kind.startswith("kvlist")
|
indent = self.indent + " "
|
||||||
kv_node = node[-1] # goto kvlist
|
line_number = self.line_number
|
||||||
|
if node[0].kind.startswith("BUILD_MAP"):
|
||||||
|
if len(node) > 1 and node[1].kind in ("kvlist", "kvlist_n"):
|
||||||
|
kv_node = node[1]
|
||||||
|
else:
|
||||||
|
kv_node = node[1:]
|
||||||
|
self.kv_map(kv_node, sep, line_number, indent)
|
||||||
|
|
||||||
for kv in kv_node:
|
else:
|
||||||
assert kv in ("kv", "kv2", "kv3")
|
sep = ""
|
||||||
# kv ::= DUP_TOP expr ROT_TWO expr STORE_SUBSCR
|
opname = node[-1].kind
|
||||||
# kv2 ::= DUP_TOP expr expr ROT_THREE STORE_SUBSCR
|
if self.is_pypy and self.version >= 3.5:
|
||||||
# kv3 ::= expr expr STORE_MAP
|
if opname.startswith("BUILD_CONST_KEY_MAP"):
|
||||||
if kv == "kv":
|
keys = node[-2].attr
|
||||||
name = self.traverse(kv[-2], indent="")
|
# FIXME: DRY this and the above
|
||||||
kv[1].parent = kv_node
|
for i in range(len(keys)):
|
||||||
value = self.traverse(
|
key = keys[i]
|
||||||
kv[1], indent=self.indent + (len(name) + 2) * " "
|
value = self.traverse(node[i], indent="")
|
||||||
)
|
self.write(sep, key, ": ", value)
|
||||||
elif kv == "kv2":
|
sep = ", "
|
||||||
name = self.traverse(kv[1], indent="")
|
if line_number != self.line_number:
|
||||||
kv[-3].parent = kv_node
|
sep += "\n" + self.indent + " "
|
||||||
value = self.traverse(
|
line_number = self.line_number
|
||||||
kv[-3], indent=self.indent + (len(name) + 2) * " "
|
pass
|
||||||
)
|
pass
|
||||||
elif kv == "kv3":
|
pass
|
||||||
name = self.traverse(kv[-2], indent="")
|
else:
|
||||||
kv[0].parent = kv_node
|
if opname.startswith("kvlist"):
|
||||||
value = self.traverse(
|
list_node = node[0]
|
||||||
kv[0], indent=self.indent + (len(name) + 2) * " "
|
else:
|
||||||
)
|
list_node = node
|
||||||
self.write(sep, name, ": ", value)
|
|
||||||
sep = line_seperator
|
assert list_node[-1].kind.startswith("BUILD_MAP")
|
||||||
|
for i in range(0, len(list_node) - 1, 2):
|
||||||
|
key = self.traverse(list_node[i], indent="")
|
||||||
|
value = self.traverse(list_node[i + 1], indent="")
|
||||||
|
self.write(sep, key, ": ", value)
|
||||||
|
sep = ", "
|
||||||
|
if line_number != self.line_number:
|
||||||
|
sep += "\n" + self.indent + " "
|
||||||
|
line_number = self.line_number
|
||||||
|
pass
|
||||||
|
pass
|
||||||
|
pass
|
||||||
|
elif opname.startswith("kvlist"):
|
||||||
|
kv_node = node[-1]
|
||||||
|
self.kv_map(node[-1], sep, line_number, indent)
|
||||||
|
|
||||||
|
pass
|
||||||
self.write("}")
|
self.write("}")
|
||||||
finish = len(self.f.getvalue())
|
finish = len(self.f.getvalue())
|
||||||
self.set_pos_info(node, start, finish)
|
self.set_pos_info(node, start, finish)
|
||||||
@@ -1942,7 +2004,7 @@ def code_deparse(
|
|||||||
co,
|
co,
|
||||||
out=StringIO(),
|
out=StringIO(),
|
||||||
version=None,
|
version=None,
|
||||||
is_pypy=None,
|
is_pypy=IS_PYPY,
|
||||||
debug_opts=DEFAULT_DEBUG_OPTS,
|
debug_opts=DEFAULT_DEBUG_OPTS,
|
||||||
code_objects={},
|
code_objects={},
|
||||||
compile_mode="exec",
|
compile_mode="exec",
|
||||||
@@ -1971,9 +2033,8 @@ def code_deparse(
|
|||||||
|
|
||||||
if version is None:
|
if version is None:
|
||||||
version = sysinfo2float()
|
version = sysinfo2float()
|
||||||
if is_pypy is None:
|
|
||||||
is_pypy = IS_PYPY
|
|
||||||
|
|
||||||
|
# store final output stream for case of error
|
||||||
scanner = get_scanner(version, is_pypy=is_pypy)
|
scanner = get_scanner(version, is_pypy=is_pypy)
|
||||||
|
|
||||||
show_asm = debug_opts.get("asm", None)
|
show_asm = debug_opts.get("asm", None)
|
||||||
@@ -2000,14 +2061,17 @@ def code_deparse(
|
|||||||
is_pypy=is_pypy,
|
is_pypy=is_pypy,
|
||||||
)
|
)
|
||||||
|
|
||||||
deparsed.ast = deparsed.build_ast(tokens, customize)
|
isTopLevel = co.co_name == "<module>"
|
||||||
|
deparsed.ast = deparsed.build_ast(tokens, customize, co, isTopLevel=isTopLevel)
|
||||||
|
|
||||||
assert deparsed.ast == "stmts", "Should have parsed grammar start"
|
assert deparsed.ast == "stmts", "Should have parsed grammar start"
|
||||||
|
|
||||||
del tokens # save memory
|
# save memory
|
||||||
|
del tokens
|
||||||
|
|
||||||
# convert leading '__doc__ = "..." into doc string
|
# convert leading '__doc__ = "..." into doc string
|
||||||
assert deparsed.ast == "stmts"
|
assert deparsed.ast == "stmts"
|
||||||
|
|
||||||
(deparsed.mod_globs, nonlocals) = pysource.find_globals_and_nonlocals(
|
(deparsed.mod_globs, nonlocals) = pysource.find_globals_and_nonlocals(
|
||||||
deparsed.ast, set(), set(), co, version
|
deparsed.ast, set(), set(), co, version
|
||||||
)
|
)
|
||||||
|
@@ -135,7 +135,7 @@ import sys
|
|||||||
IS_PYPY = "__pypy__" in sys.builtin_module_names
|
IS_PYPY = "__pypy__" in sys.builtin_module_names
|
||||||
PYTHON3 = sys.version_info >= (3, 0)
|
PYTHON3 = sys.version_info >= (3, 0)
|
||||||
|
|
||||||
from xdis import iscode, COMPILER_FLAG_BIT
|
from xdis import iscode, COMPILER_FLAG_BIT, sysinfo2float
|
||||||
|
|
||||||
from uncompyle6.parser import get_python_parser
|
from uncompyle6.parser import get_python_parser
|
||||||
from uncompyle6.parsers.treenode import SyntaxTree
|
from uncompyle6.parsers.treenode import SyntaxTree
|
||||||
@@ -980,7 +980,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
self.n_list_comp_pypy27(node)
|
self.n_list_comp_pypy27(node)
|
||||||
return
|
return
|
||||||
n = node[-1]
|
n = node[-1]
|
||||||
elif node[-1] == "del_stmt":
|
elif node[-1] == "delete":
|
||||||
if node[-2] == "JUMP_BACK":
|
if node[-2] == "JUMP_BACK":
|
||||||
n = node[-3]
|
n = node[-3]
|
||||||
else:
|
else:
|
||||||
@@ -1660,7 +1660,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
"""
|
"""
|
||||||
prettyprint a dict
|
prettyprint a dict
|
||||||
'dict' is something like k = {'a': 1, 'b': 42}"
|
'dict' is something like k = {'a': 1, 'b': 42}"
|
||||||
We will source-code use line breaks to guide us when to break.
|
We will use source-code line breaks to guide us when to break.
|
||||||
"""
|
"""
|
||||||
p = self.prec
|
p = self.prec
|
||||||
self.prec = 100
|
self.prec = 100
|
||||||
@@ -2565,7 +2565,7 @@ def code_deparse(
|
|||||||
assert iscode(co)
|
assert iscode(co)
|
||||||
|
|
||||||
if version is None:
|
if version is None:
|
||||||
version = float(sys.version[0:3])
|
version = sysinfo2float()
|
||||||
|
|
||||||
# store final output stream for case of error
|
# store final output stream for case of error
|
||||||
scanner = get_scanner(version, is_pypy=is_pypy)
|
scanner = get_scanner(version, is_pypy=is_pypy)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2018 Rocky Bernstein <rocky@gnu.org>
|
# Copyright (C) 2018, 2020 Rocky Bernstein <rocky@gnu.org>
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -50,8 +50,11 @@ def maybe_show_tree(walker, ast):
|
|||||||
stream = walker.showast
|
stream = walker.showast
|
||||||
else:
|
else:
|
||||||
stream = sys.stdout
|
stream = sys.stdout
|
||||||
if (isinstance(walker.showast, dict) and walker.showast.get("Full", False)
|
if (
|
||||||
and hasattr(walker, "str_with_template")):
|
isinstance(walker.showast, dict)
|
||||||
|
and walker.showast.get("Full", False)
|
||||||
|
and hasattr(walker, "str_with_template")
|
||||||
|
):
|
||||||
walker.str_with_template(ast)
|
walker.str_with_template(ast)
|
||||||
else:
|
else:
|
||||||
stream.write(str(ast))
|
stream.write(str(ast))
|
||||||
|
@@ -13,7 +13,6 @@ except:
|
|||||||
|
|
||||||
from uncompyle6 import PYTHON_VERSION
|
from uncompyle6 import PYTHON_VERSION
|
||||||
|
|
||||||
|
|
||||||
def better_repr(v, version):
|
def better_repr(v, version):
|
||||||
"""Work around Python's unorthogonal and unhelpful repr() for primitive float
|
"""Work around Python's unorthogonal and unhelpful repr() for primitive float
|
||||||
and complex."""
|
and complex."""
|
||||||
@@ -46,7 +45,6 @@ def better_repr(v, version):
|
|||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
elif isinstance(v, list):
|
elif isinstance(v, list):
|
||||||
better_repr(v)
|
|
||||||
if len(v) == 1:
|
if len(v) == 1:
|
||||||
return "[%s,]" % better_repr(v[0], version)
|
return "[%s,]" % better_repr(v[0], version)
|
||||||
return "[%s]" % ", ".join(better_repr(i) for i in v)
|
return "[%s]" % ", ".join(better_repr(i) for i in v)
|
||||||
|
@@ -12,4 +12,4 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
# This file is suitable for sourcing inside POSIX shell as
|
# This file is suitable for sourcing inside POSIX shell as
|
||||||
# well as importing into Python
|
# well as importing into Python
|
||||||
VERSION="3.7.3" # noqa
|
VERSION="3.7.4" # noqa
|
||||||
|
Reference in New Issue
Block a user