You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b21e8b8b57 | ||
|
4007b8b702 | ||
|
598b58796d | ||
|
f7bad891a4 | ||
|
357f28dd89 | ||
|
5cc572147a | ||
|
11be90758f | ||
|
e3720515ae | ||
|
7dec354a47 | ||
|
2a8daca25d | ||
|
7799819cad | ||
|
c6c50b5dfb | ||
|
d357898bbf | ||
|
c4e7ddf90a | ||
|
02f502c40a | ||
|
de4fbb08f2 | ||
|
e14675c2dc | ||
|
3449be024b | ||
|
8b50b15f0a | ||
|
e2e925679d | ||
|
7deeee8502 | ||
|
acdd025162 | ||
|
9acb3cf068 | ||
|
40a653cd3b | ||
|
3ac3979535 | ||
|
7eba933cfa | ||
|
ad5d3333da |
@@ -36,9 +36,11 @@ jobs:
|
|||||||
# fallback to using the latest cache if no exact match is found
|
# fallback to using the latest cache if no exact match is found
|
||||||
- v2-dependencies-
|
- v2-dependencies-
|
||||||
|
|
||||||
- run: pip install --user --upgrade setuptools
|
- run:
|
||||||
- run: pip install --user -e .
|
command: | # Use pip to install dependengcies
|
||||||
- run: pip install --user -r requirements-dev.txt
|
pip install --user --upgrade setuptools
|
||||||
|
pip install --user -e .
|
||||||
|
pip install --user -r requirements-dev.txt
|
||||||
|
|
||||||
# Save dependency cache
|
# Save dependency cache
|
||||||
- save_cache:
|
- save_cache:
|
||||||
|
18
NEWS.md
18
NEWS.md
@@ -1,3 +1,21 @@
|
|||||||
|
3.7.2: 2020-6-27
|
||||||
|
================
|
||||||
|
|
||||||
|
* Use newer xdis
|
||||||
|
* Docstrings (again) which were broken again on earlier Python
|
||||||
|
* Fix 2.6 and 2.7 decompilation bug in handling "list if" comprehensions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3.7.1: 2020-6-12 Fleetwood66
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
Released to pick up new xdis version which has fixes to read bytestings better on 3.x
|
||||||
|
|
||||||
|
* Handle 3.7+ "else" branch removal adAs seen in `_cmp()` of `python3.8/distutils/version.py` with optimization `-O2`
|
||||||
|
* 3.6+ "with" and "with .. as" grammar improvements
|
||||||
|
* ast-check for "for" loop was missing some grammar rules
|
||||||
|
|
||||||
3.7.0: 2020-5-19 Primidi 1st Prairial - Alfalfa - HF
|
3.7.0: 2020-5-19 Primidi 1st Prairial - Alfalfa - HF
|
||||||
====================================================
|
====================================================
|
||||||
|
|
||||||
|
@@ -69,7 +69,7 @@ entry_points = {
|
|||||||
]}
|
]}
|
||||||
ftp_url = None
|
ftp_url = None
|
||||||
install_requires = ["spark-parser >= 1.8.9, < 1.9.0",
|
install_requires = ["spark-parser >= 1.8.9, < 1.9.0",
|
||||||
"xdis >= 4.6.0, < 4.7.0"]
|
"xdis >= 4.7.0, <5.1.0"]
|
||||||
|
|
||||||
license = "GPL3"
|
license = "GPL3"
|
||||||
mailing_list = "python-debugger@googlegroups.com"
|
mailing_list = "python-debugger@googlegroups.com"
|
||||||
|
@@ -2,17 +2,17 @@
|
|||||||
**Table of Contents**
|
**Table of Contents**
|
||||||
|
|
||||||
- [Get latest sources:](#get-latest-sources)
|
- [Get latest sources:](#get-latest-sources)
|
||||||
- [Change version in uncompyle6/version.py](#change-version-in-uncompyle6versionpy)
|
- [Change version in uncompyle6/version.py:](#change-version-in-uncompyle6versionpy)
|
||||||
- [Update ChangeLog:](#update-changelog)
|
- [Update ChangeLog:](#update-changelog)
|
||||||
- [Update NEWS from ChangeLog:](#update-news-from-changelog)
|
- [Update NEWS.md from ChangeLog:](#update-newsmd-from-changelog)
|
||||||
- [Make sure pyenv is running and check newer versions](#make-sure-pyenv-is-running-and-check-newer-versions)
|
- [Make sure pyenv is running and check newer versions](#make-sure-pyenv-is-running-and-check-newer-versions)
|
||||||
- [Switch to python-2.4, sync that up and build that first since it creates a tarball which we don't want.](#switch-to-python-24-sync-that-up-and-build-that-first-since-it-creates-a-tarball-which-we-dont-want)
|
- [Switch to python-2.4, sync that up and build that first since it creates a tarball which we don't want.](#switch-to-python-24-sync-that-up-and-build-that-first-since-it-creates-a-tarball-which-we-dont-want)
|
||||||
- [Update NEWS from master branch](#update-news-from-master-branch)
|
- [Check against older versions](#check-against-older-versions)
|
||||||
- [Check against all versions](#check-against-all-versions)
|
|
||||||
- [Make packages and tag](#make-packages-and-tag)
|
- [Make packages and tag](#make-packages-and-tag)
|
||||||
- [Upload single package and look at Rst Formating](#upload-single-package-and-look-at-rst-formating)
|
- [Check package on github](#check-package-on-github)
|
||||||
- [Upload rest of versions](#upload-rest-of-versions)
|
- [Release on Github](#release-on-github)
|
||||||
- [Push tags:](#push-tags)
|
- [Get onto PyPI](#get-onto-pypi)
|
||||||
|
- [Update tags:](#update-tags)
|
||||||
|
|
||||||
<!-- markdown-toc end -->
|
<!-- markdown-toc end -->
|
||||||
# Get latest sources:
|
# Get latest sources:
|
||||||
@@ -60,27 +60,36 @@
|
|||||||
$ . ./admin-tools/make-dist-newer.sh
|
$ . ./admin-tools/make-dist-newer.sh
|
||||||
$ twine check dist/uncompyle6-$VERSION*
|
$ twine check dist/uncompyle6-$VERSION*
|
||||||
|
|
||||||
# Upload single package and look at Rst Formating
|
# Check package on github
|
||||||
|
|
||||||
$ twine check dist/uncompyle6-${VERSION}*
|
$ mkdir /tmp/gittest; pushd /tmp/gittest
|
||||||
$ twine upload dist/uncompyle6-${VERSION}-py3.3.egg
|
$ pyenv local 3.7.5
|
||||||
|
$ pip install -e git://github.com/rocky/python-uncompyle6.git#egg=uncompyle6
|
||||||
|
$ uncompyle6 --help
|
||||||
|
$ pip uninstall uncompyle6
|
||||||
|
$ popd
|
||||||
|
|
||||||
# Upload rest of versions
|
# Release on Github
|
||||||
|
|
||||||
$ twine upload dist/uncompyle6-${VERSION}*
|
|
||||||
|
|
||||||
Goto https://github.com/rocky/python-uncompyle6/releases
|
Goto https://github.com/rocky/python-uncompyle6/releases
|
||||||
|
|
||||||
# Push tags:
|
Now check the *tagged* release. (Checking the untagged release was previously done).
|
||||||
|
|
||||||
|
Todo: turn this into a script in `admin-tools`
|
||||||
|
|
||||||
|
$ pushd /tmp/gittest
|
||||||
|
$ pip install -e git://github.com/rocky/python-uncompyle6.git@$VERSION#egg=uncompyle6
|
||||||
|
$ uncompyle6 --help
|
||||||
|
$ pip uninstall uncompyle6
|
||||||
|
$ popd
|
||||||
|
|
||||||
|
|
||||||
|
# Get onto PyPI
|
||||||
|
|
||||||
|
$ twine upload dist/uncompyle6-${VERSION}*
|
||||||
|
|
||||||
|
|
||||||
|
# Update tags:
|
||||||
|
|
||||||
$ git push --tags
|
$ git push --tags
|
||||||
|
$ git pull --tags
|
||||||
# Check on a VM
|
|
||||||
|
|
||||||
$ cd /virtual/vagrant/virtual/vagrant/ubuntu-zesty
|
|
||||||
$ vagrant up
|
|
||||||
$ vagrant ssh
|
|
||||||
$ pyenv local 3.5.2
|
|
||||||
$ pip install --upgrade uncompyle6
|
|
||||||
$ exit
|
|
||||||
$ vagrant halt
|
|
||||||
|
@@ -19,6 +19,7 @@ for path in py_source:
|
|||||||
else:
|
else:
|
||||||
cfile = "bytecode_%s%s/%s" % (version, suffix, short) + "c"
|
cfile = "bytecode_%s%s/%s" % (version, suffix, short) + "c"
|
||||||
print("byte-compiling %s to %s" % (path, cfile))
|
print("byte-compiling %s to %s" % (path, cfile))
|
||||||
py_compile.compile(path, cfile)
|
optimize = 2
|
||||||
|
py_compile.compile(path, cfile, optimize=optimize)
|
||||||
if isinstance(version, str) or version >= (2, 6, 0):
|
if isinstance(version, str) or version >= (2, 6, 0):
|
||||||
os.system("../bin/uncompyle6 -a -T %s" % cfile)
|
os.system("../bin/uncompyle6 -a -T %s" % cfile)
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.7/03_else_removal.pyc
Normal file
BIN
test/bytecode_3.7/03_else_removal.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.8/03_else_removal.pyc
Normal file
BIN
test/bytecode_3.8/03_else_removal.pyc
Normal file
Binary file not shown.
@@ -51,7 +51,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.2 | 3.1.5 | 3.0.1 )
|
3.7.7 | 3.8.3 | 3.1.5 | 3.0.1 )
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
3.5.9 )
|
3.5.9 )
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
# Bug was code not knowing which Python versions
|
# Bug was code not knowing which Python versions
|
||||||
# have kwargs coming before positional args in code.
|
# have kwargs coming before positional args in code.
|
||||||
|
|
||||||
|
"""This program is self-checking!"""
|
||||||
# RUNNABLE!
|
# RUNNABLE!
|
||||||
|
|
||||||
def tometadata(self, metadata, schema, Table, args, name=None):
|
def tometadata(self, metadata, schema, Table, args, name=None):
|
||||||
|
12
test/simple_source/bug37/03_else_removal.py
Normal file
12
test/simple_source/bug37/03_else_removal.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# From python3.8/distutils/version.py with optimization -O2
|
||||||
|
# The bug was that the other "else" constant propagated removed.
|
||||||
|
|
||||||
|
# NOTE: this program needs to be compile with optimization
|
||||||
|
def _cmp (b, c):
|
||||||
|
if b:
|
||||||
|
if c:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
assert False, "never get here"
|
@@ -16,3 +16,25 @@ def withas_bug(self, nested, a, b):
|
|||||||
with self.assertRaises(ZeroDivisionError):
|
with self.assertRaises(ZeroDivisionError):
|
||||||
with nested(a(), b()) as (x, y):
|
with nested(a(), b()) as (x, y):
|
||||||
1 // 0
|
1 // 0
|
||||||
|
|
||||||
|
# From 3.7.7 test_functools.py
|
||||||
|
# Bug is a unreachable code after "return"
|
||||||
|
def test_invalid_registrations(x):
|
||||||
|
return
|
||||||
|
with x:
|
||||||
|
x = 1
|
||||||
|
|
||||||
|
# From 3.7.7 test_re.py
|
||||||
|
# Bug was hooking in c_with.
|
||||||
|
def test_re_tests(tests):
|
||||||
|
for t in tests:
|
||||||
|
with a:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Adapted from 3.8 distutils/command/config.py
|
||||||
|
# In 3.8 the problem was in handling "with .. as" code
|
||||||
|
def _gen_temp_sourcefile(x, a, headers, lang):
|
||||||
|
with x as y:
|
||||||
|
if a:
|
||||||
|
y = 2
|
||||||
|
return 5
|
||||||
|
@@ -55,7 +55,6 @@ SKIP_TESTS=(
|
|||||||
[test_ossaudiodev.py]=1 # it fails on its own
|
[test_ossaudiodev.py]=1 # it fails on its own
|
||||||
[test_pdb.py]=1 # Line-number specific
|
[test_pdb.py]=1 # Line-number specific
|
||||||
[test_pep277.py]=1 # it fails on its own
|
[test_pep277.py]=1 # it fails on its own
|
||||||
[test_pep352.py]=1 # Investigate
|
|
||||||
[test_plistlib.py]=1 # it fails on its own
|
[test_plistlib.py]=1 # it fails on its own
|
||||||
[test_pwd.py]=1 # Long test - might work? Control flow?
|
[test_pwd.py]=1 # Long test - might work? Control flow?
|
||||||
[test_pyclbr.py]=1 # Investigate
|
[test_pyclbr.py]=1 # Investigate
|
||||||
|
@@ -60,7 +60,6 @@ SKIP_TESTS=(
|
|||||||
[test_ossaudiodev.py]=1 # it fails on its own
|
[test_ossaudiodev.py]=1 # it fails on its own
|
||||||
|
|
||||||
[test_pep277.py]=1 # it fails on its own
|
[test_pep277.py]=1 # it fails on its own
|
||||||
[test_pep352.py]=1 # Investigate
|
|
||||||
[test_pyclbr.py]=1 # Investigate
|
[test_pyclbr.py]=1 # Investigate
|
||||||
[test_pwd.py]=1 # Long test - might work? Control flow?
|
[test_pwd.py]=1 # Long test - might work? Control flow?
|
||||||
[test_py3kwarn.py]=1 # it fails on its own
|
[test_py3kwarn.py]=1 # it fails on its own
|
||||||
|
@@ -17,8 +17,6 @@ SKIP_TESTS=(
|
|||||||
[test_peepholer.py]=1
|
[test_peepholer.py]=1
|
||||||
[test_pep352.py]=1
|
[test_pep352.py]=1
|
||||||
|
|
||||||
[test_quopri.py]=1 # TypeError: Can't convert 'bytes' object to str implicitly
|
|
||||||
|
|
||||||
[test_runpy.py]=1
|
[test_runpy.py]=1
|
||||||
|
|
||||||
[test_ssl.py]=1 # too installation specific
|
[test_ssl.py]=1 # too installation specific
|
||||||
@@ -35,5 +33,4 @@ if (( BATCH )) ; then
|
|||||||
# Fails in crontab environment?
|
# Fails in crontab environment?
|
||||||
# Figure out what's up here
|
# Figure out what's up here
|
||||||
SKIP_TESTS[test_exception_variations.py]=1
|
SKIP_TESTS[test_exception_variations.py]=1
|
||||||
SKIP_TESTS[test_quopri.py]=1
|
|
||||||
fi
|
fi
|
||||||
|
@@ -1,4 +1,15 @@
|
|||||||
SKIP_TESTS=(
|
SKIP_TESTS=(
|
||||||
|
# FIXME: Did this work sometime in the past ?
|
||||||
|
# for elem in g(s):
|
||||||
|
# if not tgt and isOdd(elem): continue
|
||||||
|
# is erroneously:
|
||||||
|
# for elem in g(s):
|
||||||
|
# if tgt or isOdd(elem):
|
||||||
|
# pass
|
||||||
|
# else:
|
||||||
|
# tgt.append(elem)
|
||||||
|
[test_itertools.py]=1
|
||||||
|
|
||||||
[test_buffer.py]=1 # FIXME: Works on c90ff51
|
[test_buffer.py]=1 # FIXME: Works on c90ff51
|
||||||
[test_cmath.py]=1 # FIXME: Works on c90ff51
|
[test_cmath.py]=1 # FIXME: Works on c90ff51
|
||||||
|
|
||||||
|
@@ -1,4 +1,15 @@
|
|||||||
SKIP_TESTS=(
|
SKIP_TESTS=(
|
||||||
|
# FIXME: Did this work sometime in the past ?
|
||||||
|
# for elem in g(s):
|
||||||
|
# if not tgt and isOdd(elem): continue
|
||||||
|
# is erroneously:
|
||||||
|
# for elem in g(s):
|
||||||
|
# if tgt or isOdd(elem):
|
||||||
|
# pass
|
||||||
|
# else:
|
||||||
|
# tgt.append(elem)
|
||||||
|
[test_itertools.py]=1
|
||||||
|
|
||||||
[test_buffer.py]=1 # FIXME: Works on c90ff51
|
[test_buffer.py]=1 # FIXME: Works on c90ff51
|
||||||
[test_cmath.py]=1 # FIXME: Works on c90ff51
|
[test_cmath.py]=1 # FIXME: Works on c90ff51
|
||||||
[test_strftime.py]=1 # FIXME: Works on c90ff51
|
[test_strftime.py]=1 # FIXME: Works on c90ff51
|
||||||
@@ -87,5 +98,4 @@ if (( batch )) ; then
|
|||||||
# Figure out what's up here
|
# Figure out what's up here
|
||||||
SKIP_TESTS[test_exception_variations.py]=1
|
SKIP_TESTS[test_exception_variations.py]=1
|
||||||
SKIP_TESTS[test_mailbox.py]=1 # Takes to long on POWER; over 15 secs
|
SKIP_TESTS[test_mailbox.py]=1 # Takes to long on POWER; over 15 secs
|
||||||
SKIP_TESTS[test_quopri.py]=1
|
|
||||||
fi
|
fi
|
||||||
|
@@ -138,7 +138,6 @@ if (( BATCH )) ; then
|
|||||||
SKIP_TESTS[test_ioctl.py]=1 # it fails on its own
|
SKIP_TESTS[test_ioctl.py]=1 # it fails on its own
|
||||||
SKIP_TESTS[test_poplib.py]=1 # May be a result of POWER installation
|
SKIP_TESTS[test_poplib.py]=1 # May be a result of POWER installation
|
||||||
|
|
||||||
SKIP_TESTS[test_quopri.py]=1
|
|
||||||
SKIP_TESTS[test_sysconfig.py]=1 # POWER extension fails
|
SKIP_TESTS[test_sysconfig.py]=1 # POWER extension fails
|
||||||
SKIP_TESTS[test_tarfile.py]=1 # too long to run on POWER 15 secs
|
SKIP_TESTS[test_tarfile.py]=1 # too long to run on POWER 15 secs
|
||||||
SKIP_TESTS[test_venv.py]=1 # takes too long 11 seconds
|
SKIP_TESTS[test_venv.py]=1 # takes too long 11 seconds
|
||||||
|
@@ -123,8 +123,6 @@ SKIP_TESTS=(
|
|||||||
[test_pyclbr.py]=1 # it fails on its own
|
[test_pyclbr.py]=1 # it fails on its own
|
||||||
[test_pydoc.py]=1 # it fails on its own
|
[test_pydoc.py]=1 # it fails on its own
|
||||||
|
|
||||||
[test_quopri.py]=1 # AssertionError: b'123=four' != '123=four'
|
|
||||||
|
|
||||||
[test_random.py]=1 # it fails on its own
|
[test_random.py]=1 # it fails on its own
|
||||||
[test_range.py]=1
|
[test_range.py]=1
|
||||||
[test_regrtest.py]=1 # test takes too long to run: 12 seconds
|
[test_regrtest.py]=1 # test takes too long to run: 12 seconds
|
||||||
|
@@ -1,4 +1,19 @@
|
|||||||
SKIP_TESTS=(
|
SKIP_TESTS=(
|
||||||
|
# FIXME: Did this work sometime in the past ?
|
||||||
|
# for elem in g(s):
|
||||||
|
# if not tgt and isOdd(elem): continue
|
||||||
|
# is erroneously:
|
||||||
|
# for elem in g(s):
|
||||||
|
# if tgt or isOdd(elem):
|
||||||
|
# pass
|
||||||
|
# else:
|
||||||
|
# tgt.append(elem)
|
||||||
|
[test_itertools.py]=1
|
||||||
|
|
||||||
|
# Fails on decompyle3 as well.
|
||||||
|
# complicated control flow and "and/or" expressions
|
||||||
|
[test_pickle.py]=1
|
||||||
|
|
||||||
[test_builtin.py]=1 # FIXME works on decompyle6
|
[test_builtin.py]=1 # FIXME works on decompyle6
|
||||||
[test_context.py]=1 # FIXME works on decompyle6
|
[test_context.py]=1 # FIXME works on decompyle6
|
||||||
[test_doctest2.py]=1 # FIXME works on decompyle6
|
[test_doctest2.py]=1 # FIXME works on decompyle6
|
||||||
@@ -48,6 +63,7 @@ SKIP_TESTS=(
|
|||||||
|
|
||||||
[test_faulthandler.py]=1 # test takes too long before decompiling
|
[test_faulthandler.py]=1 # test takes too long before decompiling
|
||||||
[test_fileinput.py]=1 # Test assertion failures
|
[test_fileinput.py]=1 # Test assertion failures
|
||||||
|
[test_finalization.py]=1 # if/else logic
|
||||||
[test_frame.py]=1 # test assertion errors
|
[test_frame.py]=1 # test assertion errors
|
||||||
[test_ftplib.py]=1 # parse error
|
[test_ftplib.py]=1 # parse error
|
||||||
[test_fstring.py]=1 # need to disambiguate leading fstrings from docstrings
|
[test_fstring.py]=1 # need to disambiguate leading fstrings from docstrings
|
||||||
|
@@ -78,7 +78,6 @@ case $PYVERSION in
|
|||||||
# Fails in crontab environment?
|
# Fails in crontab environment?
|
||||||
# Figure out what's up here
|
# Figure out what's up here
|
||||||
SKIP_TESTS[test_exception_variations.py]=1
|
SKIP_TESTS[test_exception_variations.py]=1
|
||||||
SKIP_TESTS[test_quopri.py]=1
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
3.1)
|
3.1)
|
||||||
@@ -91,7 +90,6 @@ case $PYVERSION in
|
|||||||
# Fails in crontab environment?
|
# Fails in crontab environment?
|
||||||
# Figure out what's up here
|
# Figure out what's up here
|
||||||
SKIP_TESTS[test_exception_variations.py]=1
|
SKIP_TESTS[test_exception_variations.py]=1
|
||||||
SKIP_TESTS[test_quopri.py]=1
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
3.2)
|
3.2)
|
||||||
|
@@ -119,12 +119,10 @@ def decompile(
|
|||||||
mapstream = _get_outstream(mapstream)
|
mapstream = _get_outstream(mapstream)
|
||||||
|
|
||||||
deparsed = deparse_code_with_map(
|
deparsed = deparse_code_with_map(
|
||||||
bytecode_version,
|
|
||||||
co,
|
co,
|
||||||
out,
|
out,
|
||||||
showasm,
|
bytecode_version,
|
||||||
showast,
|
debug_opts,
|
||||||
showgrammar,
|
|
||||||
code_objects=code_objects,
|
code_objects=code_objects,
|
||||||
is_pypy=is_pypy,
|
is_pypy=is_pypy,
|
||||||
)
|
)
|
||||||
|
@@ -232,7 +232,10 @@ class Python26Parser(Python2Parser):
|
|||||||
|
|
||||||
comp_for ::= SETUP_LOOP expr for_iter store comp_iter jb_pb_come_from
|
comp_for ::= SETUP_LOOP expr for_iter store comp_iter jb_pb_come_from
|
||||||
|
|
||||||
comp_body ::= gen_comp_body
|
comp_iter ::= comp_if_not
|
||||||
|
comp_if_not ::= expr jmp_true comp_iter
|
||||||
|
|
||||||
|
comp_body ::= gen_comp_body
|
||||||
|
|
||||||
for_block ::= l_stmts_opt _come_froms POP_TOP JUMP_BACK
|
for_block ::= l_stmts_opt _come_froms POP_TOP JUMP_BACK
|
||||||
|
|
||||||
|
@@ -8,7 +8,6 @@ from uncompyle6.parser import PythonParserSingle, nop_func
|
|||||||
from uncompyle6.parsers.parse2 import Python2Parser
|
from uncompyle6.parsers.parse2 import Python2Parser
|
||||||
from uncompyle6.parsers.reducecheck import (
|
from uncompyle6.parsers.reducecheck import (
|
||||||
or_check,
|
or_check,
|
||||||
ifelsestmt,
|
|
||||||
tryelsestmt,
|
tryelsestmt,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -679,6 +679,7 @@ class Python3Parser(PythonParser):
|
|||||||
"RAISE",
|
"RAISE",
|
||||||
"SETUP",
|
"SETUP",
|
||||||
"UNPACK",
|
"UNPACK",
|
||||||
|
"WITH",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2019 Rocky Bernstein
|
# Copyright (c) 2016-2020 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
|
||||||
@@ -305,28 +305,25 @@ class Python36Parser(Python35Parser):
|
|||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
# Check to combine assignment + annotation into one statement
|
# Check to combine assignment + annotation into one statement
|
||||||
self.check_reduce['assign'] = 'token'
|
self.check_reduce['assign'] = 'token'
|
||||||
|
elif opname == "WITH_CLEANUP_START":
|
||||||
|
rules_str = """
|
||||||
|
stmt ::= with_null
|
||||||
|
with_null ::= with_suffix
|
||||||
|
with_suffix ::= WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
|
"""
|
||||||
|
self.addRule(rules_str, nop_func)
|
||||||
elif opname == 'SETUP_WITH':
|
elif opname == 'SETUP_WITH':
|
||||||
rules_str = """
|
rules_str = """
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt COME_FROM_WITH
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
with_suffix
|
||||||
|
|
||||||
# Removes POP_BLOCK LOAD_CONST from 3.6-
|
# Removes POP_BLOCK LOAD_CONST from 3.6-
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
with_suffix
|
||||||
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
||||||
|
BEGIN_FINALLY COME_FROM_WITH
|
||||||
|
with_suffix
|
||||||
"""
|
"""
|
||||||
if self.version < 3.8:
|
|
||||||
rules_str += """
|
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
|
||||||
LOAD_CONST
|
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
|
||||||
"""
|
|
||||||
else:
|
|
||||||
rules_str += """
|
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
|
||||||
BEGIN_FINALLY COME_FROM_WITH
|
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH
|
|
||||||
END_FINALLY
|
|
||||||
"""
|
|
||||||
self.addRule(rules_str, nop_func)
|
self.addRule(rules_str, nop_func)
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
|
@@ -94,6 +94,9 @@ class Python37Parser(Python37BaseParser):
|
|||||||
else_suitec ::= c_stmts
|
else_suitec ::= c_stmts
|
||||||
else_suitec ::= returns
|
else_suitec ::= returns
|
||||||
|
|
||||||
|
else_suite_opt ::= else_suite
|
||||||
|
else_suite_opt ::= pass
|
||||||
|
|
||||||
stmt ::= classdef
|
stmt ::= classdef
|
||||||
stmt ::= call_stmt
|
stmt ::= call_stmt
|
||||||
|
|
||||||
@@ -635,6 +638,12 @@ class Python37Parser(Python37BaseParser):
|
|||||||
if_exp37 ::= expr expr jf_cfs expr COME_FROM
|
if_exp37 ::= expr expr jf_cfs expr COME_FROM
|
||||||
jf_cfs ::= JUMP_FORWARD _come_froms
|
jf_cfs ::= JUMP_FORWARD _come_froms
|
||||||
ifelsestmt ::= testexpr c_stmts_opt jf_cfs else_suite opt_come_from_except
|
ifelsestmt ::= testexpr c_stmts_opt jf_cfs else_suite opt_come_from_except
|
||||||
|
|
||||||
|
# This is probably more realistically an "ifstmt" (with a null else)
|
||||||
|
# see _cmp() of python3.8/distutils/__pycache__/version.cpython-38.opt-1.pyc
|
||||||
|
ifelsestmt ::= testexpr stmts jf_cfs else_suite_opt opt_come_from_except
|
||||||
|
|
||||||
|
|
||||||
expr_pjit ::= expr POP_JUMP_IF_TRUE
|
expr_pjit ::= expr POP_JUMP_IF_TRUE
|
||||||
expr_jit ::= expr JUMP_IF_TRUE
|
expr_jit ::= expr JUMP_IF_TRUE
|
||||||
expr_jt ::= expr jmp_true
|
expr_jt ::= expr jmp_true
|
||||||
|
@@ -127,6 +127,7 @@ class Python37BaseParser(PythonParser):
|
|||||||
"RAISE",
|
"RAISE",
|
||||||
"SETUP",
|
"SETUP",
|
||||||
"UNPACK",
|
"UNPACK",
|
||||||
|
"WITH",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -993,55 +994,70 @@ class Python37BaseParser(PythonParser):
|
|||||||
)
|
)
|
||||||
custom_ops_processed.add(opname)
|
custom_ops_processed.add(opname)
|
||||||
|
|
||||||
|
elif opname == "WITH_CLEANUP_START":
|
||||||
|
rules_str = """
|
||||||
|
stmt ::= with_null
|
||||||
|
with_null ::= with_suffix
|
||||||
|
with_suffix ::= WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
||||||
|
"""
|
||||||
|
self.addRule(rules_str, nop_func)
|
||||||
elif opname == "SETUP_WITH":
|
elif opname == "SETUP_WITH":
|
||||||
rules_str = """
|
rules_str = """
|
||||||
stmt ::= with
|
stmt ::= with
|
||||||
stmt ::= withasstmt
|
stmt ::= withasstmt
|
||||||
|
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt COME_FROM_WITH
|
with ::= expr
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
SETUP_WITH POP_TOP
|
||||||
|
suite_stmts_opt
|
||||||
|
COME_FROM_WITH
|
||||||
|
with_suffix
|
||||||
withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
with_suffix
|
||||||
|
|
||||||
|
with ::= expr
|
||||||
|
SETUP_WITH POP_TOP
|
||||||
|
suite_stmts_opt
|
||||||
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
|
with_suffix
|
||||||
|
|
||||||
|
withasstmt ::= expr
|
||||||
|
SETUP_WITH store suite_stmts_opt
|
||||||
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
|
with_suffix
|
||||||
|
|
||||||
with ::= expr
|
with ::= expr
|
||||||
SETUP_WITH POP_TOP suite_stmts_opt
|
SETUP_WITH POP_TOP suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
with_suffix
|
||||||
withasstmt ::= expr
|
withasstmt ::= expr
|
||||||
SETUP_WITH store suite_stmts_opt
|
SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
with_suffix
|
||||||
|
|
||||||
with ::= expr
|
|
||||||
SETUP_WITH POP_TOP suite_stmts_opt
|
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
|
||||||
withasstmt ::= expr
|
|
||||||
SETUP_WITH store suite_stmts_opt
|
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
|
||||||
"""
|
"""
|
||||||
if self.version < 3.8:
|
if self.version < 3.8:
|
||||||
rules_str += """
|
rules_str += """
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
||||||
LOAD_CONST
|
LOAD_CONST
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
with_suffix
|
||||||
"""
|
"""
|
||||||
else:
|
else:
|
||||||
rules_str += """
|
rules_str += """
|
||||||
with ::= expr
|
with ::= expr
|
||||||
SETUP_WITH POP_TOP suite_stmts_opt
|
SETUP_WITH POP_TOP suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
|
with_suffix
|
||||||
|
|
||||||
withasstmt ::= expr
|
withasstmt ::= expr
|
||||||
SETUP_WITH store suite_stmts_opt
|
SETUP_WITH store suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
|
|
||||||
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
withasstmt ::= expr
|
||||||
|
SETUP_WITH store suite_stmts
|
||||||
|
POP_BLOCK BEGIN_FINALLY COME_FROM_WITH with_suffix
|
||||||
|
|
||||||
|
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
|
||||||
BEGIN_FINALLY COME_FROM_WITH
|
BEGIN_FINALLY COME_FROM_WITH
|
||||||
WITH_CLEANUP_START WITH_CLEANUP_FINISH
|
with_suffix
|
||||||
END_FINALLY
|
|
||||||
"""
|
"""
|
||||||
self.addRule(rules_str, nop_func)
|
self.addRule(rules_str, nop_func)
|
||||||
|
|
||||||
|
@@ -45,6 +45,7 @@ class Python38Parser(Python37Parser):
|
|||||||
stmt ::= try_elsestmtl38
|
stmt ::= try_elsestmtl38
|
||||||
stmt ::= try_except_ret38
|
stmt ::= try_except_ret38
|
||||||
stmt ::= try_except38
|
stmt ::= try_except38
|
||||||
|
stmt ::= try_except_as
|
||||||
stmt ::= whilestmt38
|
stmt ::= whilestmt38
|
||||||
stmt ::= whileTruestmt38
|
stmt ::= whileTruestmt38
|
||||||
stmt ::= call_stmt
|
stmt ::= call_stmt
|
||||||
@@ -133,6 +134,8 @@ class Python38Parser(Python37Parser):
|
|||||||
except_cond1 ::= DUP_TOP expr COMPARE_OP jmp_false
|
except_cond1 ::= DUP_TOP expr COMPARE_OP jmp_false
|
||||||
POP_TOP POP_TOP POP_TOP
|
POP_TOP POP_TOP POP_TOP
|
||||||
POP_EXCEPT
|
POP_EXCEPT
|
||||||
|
except_cond_as ::= DUP_TOP expr COMPARE_OP POP_JUMP_IF_FALSE
|
||||||
|
POP_TOP STORE_FAST POP_TOP
|
||||||
|
|
||||||
try_elsestmtl38 ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
try_elsestmtl38 ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
||||||
except_handler38 COME_FROM
|
except_handler38 COME_FROM
|
||||||
@@ -145,6 +148,10 @@ class Python38Parser(Python37Parser):
|
|||||||
# suite_stmts has a return
|
# suite_stmts has a return
|
||||||
try_except38 ::= SETUP_FINALLY POP_BLOCK suite_stmts
|
try_except38 ::= SETUP_FINALLY POP_BLOCK suite_stmts
|
||||||
except_handler38b
|
except_handler38b
|
||||||
|
try_except_as ::= SETUP_FINALLY POP_BLOCK suite_stmts
|
||||||
|
except_handler_as END_FINALLY COME_FROM
|
||||||
|
try_except_as ::= SETUP_FINALLY suite_stmts
|
||||||
|
except_handler_as END_FINALLY COME_FROM
|
||||||
|
|
||||||
try_except_ret38 ::= SETUP_FINALLY returns except_ret38a
|
try_except_ret38 ::= SETUP_FINALLY returns except_ret38a
|
||||||
try_except_ret38a ::= SETUP_FINALLY returns except_handler38c
|
try_except_ret38a ::= SETUP_FINALLY returns except_handler38c
|
||||||
@@ -165,6 +172,11 @@ class Python38Parser(Python37Parser):
|
|||||||
except_handler38a ::= COME_FROM_FINALLY POP_TOP POP_TOP POP_TOP
|
except_handler38a ::= COME_FROM_FINALLY POP_TOP POP_TOP POP_TOP
|
||||||
POP_EXCEPT POP_TOP stmts END_FINALLY
|
POP_EXCEPT POP_TOP stmts END_FINALLY
|
||||||
|
|
||||||
|
except_handler38c ::= COME_FROM_FINALLY except_cond1a except_stmts
|
||||||
|
POP_EXCEPT JUMP_FORWARD COME_FROM
|
||||||
|
except_handler_as ::= COME_FROM_FINALLY except_cond_as tryfinallystmt
|
||||||
|
POP_EXCEPT JUMP_FORWARD COME_FROM
|
||||||
|
|
||||||
tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
|
||||||
BEGIN_FINALLY COME_FROM_FINALLY suite_stmts_opt
|
BEGIN_FINALLY COME_FROM_FINALLY suite_stmts_opt
|
||||||
END_FINALLY
|
END_FINALLY
|
||||||
|
@@ -95,6 +95,34 @@ IFELSE_STMT_RULES = frozenset(
|
|||||||
"else_suite",
|
"else_suite",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"ifelsestmt",
|
||||||
|
(
|
||||||
|
"testexpr",
|
||||||
|
"stmts",
|
||||||
|
"jf_cfs",
|
||||||
|
"else_suite_opt",
|
||||||
|
"opt_come_from_except",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ifelsestmt",
|
||||||
|
(
|
||||||
|
"testexpr",
|
||||||
|
"stmts",
|
||||||
|
"jf_cfs",
|
||||||
|
"\\e_else_suite_opt",
|
||||||
|
"\\e_opt_come_from_except")
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ifelsestmt",
|
||||||
|
(
|
||||||
|
"testexpr",
|
||||||
|
"stmts",
|
||||||
|
"jf_cfs",
|
||||||
|
"\\e_else_suite_opt",
|
||||||
|
"opt_come_from_except")
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
|
def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
|
||||||
@@ -103,12 +131,17 @@ def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
|
|||||||
# ifelsestmt jumped outside of loop. No good.
|
# ifelsestmt jumped outside of loop. No good.
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# print("XXX", first, last)
|
||||||
|
# for t in range(first, last):
|
||||||
|
# print(tokens[t])
|
||||||
|
# print("=" * 30)
|
||||||
|
|
||||||
if rule not in IFELSE_STMT_RULES:
|
if rule not in IFELSE_STMT_RULES:
|
||||||
# print("XXX", rule)
|
# print("XXX", rule)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Avoid if/else where the "then" is a "raise_stmt1" for an
|
# Avoid if/else where the "then" is a "raise_stmt1" for an
|
||||||
# assert statemetn. Parse this as an "assert" instead.
|
# assert statement. Parse this as an "assert" instead.
|
||||||
stmts = ast[1]
|
stmts = ast[1]
|
||||||
if stmts in ("c_stmts",) and len(stmts) == 1:
|
if stmts in ("c_stmts",) and len(stmts) == 1:
|
||||||
raise_stmt1 = stmts[0]
|
raise_stmt1 = stmts[0]
|
||||||
@@ -176,9 +209,7 @@ def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
|
|||||||
if jump_else_end == "jf_cf_pop":
|
if jump_else_end == "jf_cf_pop":
|
||||||
jump_else_end = jump_else_end[0]
|
jump_else_end = jump_else_end[0]
|
||||||
|
|
||||||
jump_to_jump = False
|
|
||||||
if jump_else_end == "JUMP_FORWARD":
|
if jump_else_end == "JUMP_FORWARD":
|
||||||
jump_to_jump = True
|
|
||||||
endif_target = int(jump_else_end.pattr)
|
endif_target = int(jump_else_end.pattr)
|
||||||
last_offset = tokens[last].off2int()
|
last_offset = tokens[last].off2int()
|
||||||
if endif_target != last_offset:
|
if endif_target != last_offset:
|
||||||
|
@@ -8,22 +8,29 @@ FIXME idea: extend parsing system to do same kinds of checks or nonterminal
|
|||||||
before reduction and don't reduce when there is a problem.
|
before reduction and don't reduce when there is a problem.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def checker(ast, in_loop, errors):
|
def checker(ast, in_loop, errors):
|
||||||
if ast is None:
|
if ast is None:
|
||||||
return
|
return
|
||||||
in_loop = (in_loop or (ast.kind in ('while1stmt', 'whileTruestmt',
|
in_loop = (
|
||||||
'whilestmt', 'whileelsestmt', 'while1elsestmt',
|
in_loop
|
||||||
'for_block'))
|
or ast.kind.startswith("for")
|
||||||
or ast.kind.startswith('async_for'))
|
or ast.kind.startswith("while")
|
||||||
if ast.kind in ('aug_assign1', 'aug_assign2') and ast[0][0] == 'and':
|
or ast.kind.startswith("async_for")
|
||||||
|
)
|
||||||
|
if ast.kind in ("aug_assign1", "aug_assign2") and ast[0][0] == "and":
|
||||||
text = str(ast)
|
text = str(ast)
|
||||||
error_text = '\n# improper augmented assigment (e.g. +=, *=, ...):\n#\t' + '\n# '.join(text.split("\n")) + '\n'
|
error_text = (
|
||||||
|
"\n# improper augmented assigment (e.g. +=, *=, ...):\n#\t"
|
||||||
|
+ "\n# ".join(text.split("\n"))
|
||||||
|
+ "\n"
|
||||||
|
)
|
||||||
errors.append(error_text)
|
errors.append(error_text)
|
||||||
|
|
||||||
for node in ast:
|
for node in ast:
|
||||||
if not in_loop and node.kind in ('continue', 'break'):
|
if not in_loop and node.kind in ("continue", "break"):
|
||||||
text = str(node)
|
text = str(node)
|
||||||
error_text = '\n# not in loop:\n#\t' + '\n# '.join(text.split("\n"))
|
error_text = "\n# not in loop:\n#\t" + "\n# ".join(text.split("\n"))
|
||||||
errors.append(error_text)
|
errors.append(error_text)
|
||||||
if hasattr(node, '__repr1__'):
|
if hasattr(node, "__repr1__"):
|
||||||
checker(node, in_loop, errors)
|
checker(node, in_loop, errors)
|
||||||
|
@@ -50,12 +50,24 @@ def customize_for_version38(self, version):
|
|||||||
"%|%c\n", 0
|
"%|%c\n", 0
|
||||||
),
|
),
|
||||||
|
|
||||||
|
"except_cond_as": (
|
||||||
|
"%|except %c as %c:\n",
|
||||||
|
(1, "expr"),
|
||||||
|
(-2, "STORE_FAST"),
|
||||||
|
),
|
||||||
|
|
||||||
'except_handler38': (
|
'except_handler38': (
|
||||||
'%c', (2, 'except_stmts') ),
|
'%c', (2, 'except_stmts') ),
|
||||||
|
|
||||||
'except_handler38a': (
|
'except_handler38a': (
|
||||||
'%c', (-2, 'stmts') ),
|
'%c', (-2, 'stmts') ),
|
||||||
|
|
||||||
|
"except_handler_as": (
|
||||||
|
"%c%+\n%+%c%-",
|
||||||
|
(1, "except_cond_as"),
|
||||||
|
(2, "tryfinallystmt"),
|
||||||
|
),
|
||||||
|
|
||||||
'except_ret38a': (
|
'except_ret38a': (
|
||||||
'return %c', (4, 'expr') ),
|
'return %c', (4, 'expr') ),
|
||||||
|
|
||||||
@@ -105,6 +117,13 @@ def customize_for_version38(self, version):
|
|||||||
'try_except38': (
|
'try_except38': (
|
||||||
'%|try:\n%+%c\n%-%|except:\n%|%-%c\n\n',
|
'%|try:\n%+%c\n%-%|except:\n%|%-%c\n\n',
|
||||||
(-2, 'suite_stmts_opt'), (-1, 'except_handler38a') ),
|
(-2, 'suite_stmts_opt'), (-1, 'except_handler38a') ),
|
||||||
|
|
||||||
|
"try_except_as": (
|
||||||
|
"%|try:\n%+%c%-\n%|%-%c\n\n",
|
||||||
|
(-4, "suite_stmts"), # Go from the end because of POP_BLOCK variation
|
||||||
|
(-3, "except_handler_as"),
|
||||||
|
),
|
||||||
|
|
||||||
"try_except_ret38": (
|
"try_except_ret38": (
|
||||||
"%|try:\n%+%c%-\n%|except:\n%+%|%c%-\n\n",
|
"%|try:\n%+%c%-\n%|except:\n%+%|%c%-\n\n",
|
||||||
(1, "returns"),
|
(1, "returns"),
|
||||||
|
@@ -895,6 +895,12 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
doc_node = node[0]
|
doc_node = node[0]
|
||||||
if doc_node.attr:
|
if doc_node.attr:
|
||||||
docstring = doc_node.attr
|
docstring = doc_node.attr
|
||||||
|
if not isinstance(docstring, str):
|
||||||
|
# FIXME: we have mistakenly tagged something as a doc
|
||||||
|
# string in transform when it isn't one.
|
||||||
|
# The rule in n_mkfunc is pretty flaky.
|
||||||
|
self.prune()
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
docstring = node[0].pattr
|
docstring = node[0].pattr
|
||||||
|
|
||||||
|
@@ -95,10 +95,18 @@ class TreeTransform(GenericASTTraversal, object):
|
|||||||
|
|
||||||
code = find_code_node(node, code_index).attr
|
code = find_code_node(node, code_index).attr
|
||||||
|
|
||||||
|
mkfunc_pattr = node[-1].pattr
|
||||||
|
if isinstance(mkfunc_pattr, tuple):
|
||||||
|
assert len(mkfunc_pattr, 4) and isinstance(mkfunc_pattr, int)
|
||||||
|
is_closure = node[-1].pattr[3] != 0
|
||||||
|
else:
|
||||||
|
# FIXME: This is what we had before. It is hoaky and probably wrong.
|
||||||
|
is_closure = mkfunc_pattr == "closure"
|
||||||
|
|
||||||
if (
|
if (
|
||||||
node[-1].pattr != "closure"
|
(not is_closure)
|
||||||
and len(code.co_consts) > 0
|
and len(code.co_consts) > 0
|
||||||
and code.co_consts[0] is not None
|
and isinstance(code.co_consts[0], str)
|
||||||
):
|
):
|
||||||
docstring_node = SyntaxTree(
|
docstring_node = SyntaxTree(
|
||||||
"docstring", [Token("LOAD_STR", has_arg=True, pattr=code.co_consts[0])]
|
"docstring", [Token("LOAD_STR", has_arg=True, pattr=code.co_consts[0])]
|
||||||
@@ -433,6 +441,7 @@ class TreeTransform(GenericASTTraversal, object):
|
|||||||
ast[i] = ast[i][0]
|
ast[i] = ast[i][0]
|
||||||
|
|
||||||
if is_docstring(self.ast[i]):
|
if is_docstring(self.ast[i]):
|
||||||
|
load_const = self.ast[i].first_child()
|
||||||
docstring_ast = SyntaxTree(
|
docstring_ast = SyntaxTree(
|
||||||
"docstring",
|
"docstring",
|
||||||
[
|
[
|
||||||
@@ -440,8 +449,8 @@ class TreeTransform(GenericASTTraversal, object):
|
|||||||
"LOAD_STR",
|
"LOAD_STR",
|
||||||
has_arg=True,
|
has_arg=True,
|
||||||
offset=0,
|
offset=0,
|
||||||
attr=self.ast[i][0][0].attr,
|
attr=load_const.attr,
|
||||||
pattr=self.ast[i][0][0].pattr,
|
pattr=load_const.pattr,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@@ -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.0" # noqa
|
VERSION="3.7.2" # noqa
|
||||||
|
Reference in New Issue
Block a user