Compare commits

..

94 Commits

Author SHA1 Message Date
rocky
3e3dd87c3b Get ready for release 3.6.0 2019-12-09 21:51:15 -05:00
rocky
edbbefb57d Start to remove crud in control-flow detection for 3.7+ 2019-12-09 18:28:57 -05:00
rocky
6546bbdaf9 Fix 2.x false tryelsestmtl detection...
With grammar reduction tests. Same as tryelsestmt. Lots of stdlib tests work
now. (More remain though.)
2019-12-09 16:19:10 -05:00
rocky
825ed3fef9 Reinstate some stdlib tests...
now that we distinguish try/else a little better
2019-12-09 14:13:30 -05:00
rocky
7d9c4ce8ca Better try/else detection 2019-12-09 14:04:57 -05:00
rocky
fdac1e3c46 Use 3.9-enabled xdis 2019-12-09 12:56:30 -05:00
rocky
daab1e8610 Start to tolerate 3.9 (in pydisassemble) 2019-12-09 12:20:00 -05:00
rocky
b8f4dca505 Update README.rsgt 2019-12-09 07:19:51 -05:00
rocky
99b8a99ffa Python 2.5 fixes..
* "with" handling.
* Go over 2.5 runtest.sh exclusions
2019-12-09 06:57:02 -05:00
rocky
8c879c02de Small logic correction in run-time test. 2019-12-09 04:09:44 -05:00
rocky
d11a9ea126 Remember rocky: use off2int() in offset testing! 2019-12-08 21:42:49 -05:00
rocky
4926474efc Add jump range check for 2.7 assert_expr_and 2019-12-08 21:37:45 -05:00
rocky
eba5226a04 Typos: decompyle3 -> uncompyle6 2019-12-08 18:05:37 -05:00
R. Bernstein
8d0ff367d8 Merge pull request #297 from rocky/decompile-merge
Merging in recent 3.7 and 3.8 improvements from decompyle6
2019-12-08 18:01:38 -05:00
rocky
c6ddefcef5 Merging in recent 3.7 and 3.8 improvements from decompyle6
This rebases 3.7, 3.8 ...decompilation off of 3.7ish rather than a 3.4
base.

Add more 3.7 and 3.8 tests
2019-12-08 17:54:59 -05:00
rocky
301464d646 Accomodate for optional docstring in function kw calculation 2019-12-02 12:58:26 -05:00
rocky
d5b52d44e0 Better bytecode detection for Python > 3.0...
Not perfect though. More work is needed on the xdis side.
2019-11-21 19:39:57 -05:00
rocky
322f491c83 Revise NEWS 2019-11-20 10:08:20 -05:00
rocky
2987d6a72b Go over some 3.0 and 3.1 tests 2019-11-18 22:46:27 -05:00
rocky
7609165967 Revise mixed expressions 2019-11-18 18:22:16 -05:00
rocky
655162a05e One more test 2019-11-18 18:15:30 -05:00
rocky
ca7f483dbb Better test coverage of operators (in 2.7 and 3.0) 2019-11-18 18:10:58 -05:00
rocky
e713169bdf Administrivia: go over tests...
Some tests were deferred and are not now
update Python 2.7 standard library tests
2019-11-18 12:30:48 -05:00
rocky
cc856e2b95 Refine 2.7 control flow reduction tests...
for "iflastsmtl" and "and"
2019-11-18 11:34:06 -05:00
rocky
d696443eb2 More 2.7 reduction checks for conditionals:
Specficially for "and" and "laststmtl"
2019-11-18 08:36:28 -05:00
rocky
a5e7eb19c6 Reinstate some tests 2019-11-18 06:59:27 -05:00
rocky
6659fffc0d Two Bugs ...
2.7: more stringent comparison and comp_if testing
2.6-2.7: fix botched dict constant translation
2019-11-18 06:49:36 -05:00
rocky
1868b566a1 RsT markup 2019-11-17 20:47:40 -05:00
rocky
791274c45d RsT markup 2019-11-17 20:47:13 -05:00
rocky
4327ee98e6 Update README for the current situation 2019-11-17 20:45:37 -05:00
rocky
2717a5e302 Administrivia 2019-11-17 20:26:35 -05:00
rocky
77dd3b8d50 Administrivia 2019-11-17 20:25:14 -05:00
rocky
2cfc60fbd7 Get ready for release 3.5.1 2019-11-17 19:59:26 -05:00
rocky
daa424cf0c Some grammar cleanup based on coverage info 2019-11-17 01:01:52 -05:00
rocky
7b68c9c838 Administriva - bump testing versions 2019-11-16 22:54:32 -05:00
rocky
df5df9364c Grammar debugging for 3.0, 3.7 and 3.8 2019-11-16 17:59:30 -05:00
rocky
f1496cad4d 3.0 return_if_stmt and...
* Some grammar cleanup
* add more grammar debugging
2019-11-16 17:32:48 -05:00
rocky
a3a15414d3 Add 3.0 whileTrue rule for recent CONTINUE change 2019-11-16 16:18:39 -05:00
rocky
9874553fb4 while1 rule adjustment for 3.0 2019-11-16 16:04:16 -05:00
rocky
d21d93fd84 Handle 3.0 call_stmt better 2019-11-16 15:21:59 -05:00
rocky
dbf2729f76 expand 3.0 "continue" detection 2019-11-16 12:23:09 -05:00
rocky
047e27c966 3.0 assert2...
Not like other 3.x due to the lack of POP_JUMP_IF
2019-11-16 09:10:14 -05:00
rocky
6a81a752a7 Adjust 3.0 iflastsmtl rule 2019-11-16 00:59:58 -05:00
rocky
44f0ba0efb Add 3.0 try/except rule 2019-11-15 23:39:36 -05:00
rocky
bc8907e752 Guard again improper assert transform...
we see this happen in getheader() from 3.0.1/lib/python3.0/http/client.pyc
2019-11-15 22:19:17 -05:00
rocky
4e9d8783d1 Add Python 3.0.1 list_comp rule 2019-11-15 21:32:31 -05:00
rocky
47c847644e Modify 3.0 _ifstmts_jump rule 2019-11-15 19:23:08 -05:00
rocky
af2ed31871 Add 3.0 whilestmt rule 2019-11-15 15:14:33 -05:00
rocky
49de5b5c9d add 3.0 iflaststmt rule 2019-11-15 14:07:37 -05:00
rocky
c8252ca9cb 3.0 import_from rule 2019-11-15 09:27:47 -05:00
rocky
0441fbc616 3.0.1 "ret_or", "ret_and", and "or" rules 2019-11-15 09:12:53 -05:00
rocky
1b4335edf1 Add 3.0.1 while loop rule 2019-11-15 07:48:23 -05:00
rocky
2e36551c02 Remove more 3.0 parse errors...
However this doesn't mean that some wrong rules still don't
kid in. We still have control-flow "if/and/else" vs "if/if/else" problems.
2019-11-14 18:32:52 -05:00
rocky
fff6f82dd7 expand 3.0 jump_except rule 2019-11-14 10:11:28 -05:00
rocky
7c8f3cc9ec Two 3.0 rules ...
- ifstmtlastl
- ifnotstmt30
2019-11-14 03:57:41 -05:00
rocky
78a595c8cf Bang on 3.0.1 control flow...
more word is needed though
2019-11-13 20:35:44 -05:00
rocky
cda0154594 Pypy 3.6.9 tolerance 2019-11-12 23:33:36 -05:00
rocky
d852f23962 3.3 "yield from" semantic action fix 2019-11-12 17:48:16 -05:00
rocky
065fd13b81 Small tweaks 2019-11-12 17:04:35 -05:00
rocky
659f37585b Bug in 3.0 rule in "jump_absolute_else" ...
and disallowing "else" to the wrong place.
2019-11-12 16:31:43 -05:00
rocky
bc18fcf7fa 3.0 tweak in iflastsmtl reduction validation 2019-11-12 06:37:43 -05:00
rocky
144f52da8e More 3.0 control flow pattern fixups 2019-11-12 06:08:30 -05:00
rocky
9f250b49ee Cope more JUMP/POP_IF not being in 3.0...
more is probably needed though.
2019-11-11 19:58:35 -05:00
rocky
4abdffecb9 More 3.0 control-flow rules...
Much more is needed though
2019-11-11 19:07:58 -05:00
rocky
1419acf019 More Python 3.0 for JUMP elimination ...
here, in except blocks.
2019-11-11 13:50:48 -05:00
rocky
bdc24d7f51 Add 3.0 gen_comp_body rule. 2019-11-11 05:10:54 -05:00
rocky
07ec8fa1fb More Python 3.0 custom "if" statment handling. 2019-11-10 18:44:43 -05:00
rocky
04c2240d63 Python 3.0 if/else handling 2019-11-10 17:23:33 -05:00
rocky
96dcdfd744 Last change but closer... 2019-11-10 16:09:17 -05:00
rocky
82ea77c592 Python 3.0 bytecode decoding 2019-11-10 15:56:04 -05:00
rocky
4f0e580438 Update testenv pypy 3.6 2019-11-10 13:44:52 -05:00
rocky
09cc0d775a Pypy 3.3 tolerance and ...
Remove some duplicate grammar rules
2019-11-10 13:34:51 -05:00
rocky
2da5a5649f Python 3.5 tolerance 2019-11-10 12:04:21 -05:00
rocky
373916f57c Pypy 3.5 tolerance 2019-11-09 21:56:36 -05:00
rocky
1c0c54991e Backend some buffers 2019-11-09 18:49:40 -05:00
rocky
5de5d2357f Update test_grammar for Python 3.8 2019-11-09 17:55:58 -05:00
rocky
6d296f11c9 Add another 3.8 test 2019-10-31 07:13:41 -04:00
rocky
0ae4acff9e Remove extraneous iter() in "for" of list comp...
Fixes #272
2019-10-30 21:58:14 -04:00
rocky
40c2f2962c Try expanding 3.8 testing 2019-10-30 19:36:42 -04:00
rocky
dae195e36e Expand 3.8 testing 2019-10-30 19:11:19 -04:00
rocky
2c503d5a14 Bump xdis ...
to handle pypy3.6 from Python 2
2019-10-30 11:58:39 -04:00
rocky
eed4c1025b Pypy 3.6 tolerance 2019-10-30 11:44:04 -04:00
rocky
86c1d12e69 Pypy 3.6 tolerance 2019-10-29 18:12:06 -04:00
rocky
61a367b0ae Don't test 3.8 except on 3.8 for now 2019-10-29 13:46:04 -04:00
rocky
dba6d24361 3.8 for block without a POP_BLOCK ...
and confusing JUMP_BACK for CONTINUE. Expect more like this.

Fixes #293
2019-10-29 13:32:43 -04:00
R. Bernstein
0b111f1568 Merge pull request #263 from rocky/pypy3.6
pypy3.6 handling
2019-10-29 12:55:30 -04:00
rocky
c666e2dc3d Remove pypy 3.6 testing for now 2019-10-29 12:08:00 -04:00
rocky
0a5fcc51d8 Pypy 3.6 fixes and tests 2019-10-29 11:43:09 -04:00
rocky
ade9f7a182 Add Pypy 3.6 file for showing unmarshal problem 2019-10-28 20:58:42 -04:00
rocky
d41ef3e5dc Pypy 3.6 tolerance 2019-10-28 14:46:45 -04:00
rocky
ebb0342b38 WIP pypy3.6 handling 2019-10-28 13:20:51 -04:00
rocky
f17ebf42a9 Administrative kinds of changes 2019-10-28 13:17:10 -04:00
rocky
85dcce4ff2 Add twine check in release process 2019-10-19 12:33:29 -04:00
rocky
bc9a16eaac Correct version number in NEWS.md 2019-10-12 20:10:29 -04:00
188 changed files with 6056 additions and 1086 deletions

View File

@@ -34,7 +34,7 @@ jobs:
# This is based on your 1.0 configuration file or project settings
- run:
working_directory: ~/rocky/python-uncompyle6
command: pyenv install 2.4.6 && pyenv local 2.4.6 && pyenv rehash && easy_install nose && pyenv rehash
command: pip install virtualenv && pip install nose && pip install pep8 && pyenv rehash
# Dependencies
# This would typically go in either a build or a build-and-test job when using workflows
# Restore the dependency cache
@@ -45,6 +45,7 @@ jobs:
- v2-dependencies-
# This is based on your 1.0 configuration file or project settings
- run: pip install --upgrade setuptools
- run: pip install -e .
- run: pip install -r requirements-dev.txt
@@ -64,8 +65,8 @@ jobs:
# Test
# This would typically be a build job when using workflows, possibly combined with build
# This is based on your 1.0 configuration file or project settings
- run: python ./setup.py develop && make check-2.4
- run: cd ./test/stdlib && pyenv local 2.4.6 && bash ./runtests.sh 'test_[p-z]*.py'
- run: python ./setup.py develop && make check-2.7
- run: cd ./test/stdlib && bash ./runtests.sh 'test_[p-z]*.py'
# Teardown
# If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each
# Save test results

View File

@@ -1,11 +1,15 @@
language: python
python:
- '2.7' # this is a cheat here because travis doesn't do 2.4-2.6
- '3.5'
- '2.7'
- '3.4'
- '3.6'
- '3.8'
matrix:
include:
- python: '2.7'
- python: '3.7'
dist: xenial # required for Python >= 3.7 (travis-ci/travis-ci#9069)
install:

View File

@@ -40,16 +40,19 @@ check-3.0 check-3.1 check-3.2 check-3.6:
check-3.7: pytest
$(MAKE) -C test check
#:Tests for Python 2.4-2.5 (don't have pytest)
check-2.4 check-2.5:
$(MAKE) -C test $@
check-3.8:
$(MAKE) -C test check
#:PyPy 2.6.1 PyPy 5.0.1, or PyPy 5.8.0-beta0
# Skip for now
2.6 5.0 5.3 5.6 5.8:
#:PyPy pypy3-2.4.0 Python 3:
pypy-3.2 2.4:
#:PyPy pypy3-2.4.0 Python 3.6.1:
7.1 pypy-3.2 2.4:
$(MAKE) -C test $@
#:PyPy pypy3-2.4.0 Python 3.6.9:
7.2:
$(MAKE) -C test $@
#: Run py.test tests

49
NEWS.md
View File

@@ -1,20 +1,52 @@
4.1.0 2019-10-12 Stony Brook Ride
3.6.0: 2019-12-10 gecko gecko
=============================
The main focus in this release was more accurate decompilation especially
for 3.7 and 3.8. However there are some improvments to Python 2.x as well,
including one of the long-standing problems of detecting the difference between
`try ... ` and `try else ...`.
With this release we now rebase Python 3.7 on off of a 3.7 base; This
is also as it is (now) in decompyle3. This facilitates removing some of the
cruft in control-flow detection in the 2.7 uncompyle2 base.
Alas, decompilation speed for 3.7 on is greatly increased. Hopefull
this is temporary (cough, cough) until we can do a static control flow
pass.
Finally, runing in 3.9-dev is tolerated. We can disassemble, but no parse tables yet.
3.5.1 2019-11-17 JNC
====================
- Pypy 3.3, 3.5, 3.6, and 3.6.9 support
- bump xdis version to handle newer Python releases, e.g. 2.7.17, 3.5.8, and 3.5.9
- Improve 3.0 decompilation
- no parse errors on stlib bytecode. However accurate translation in
control-flow and and/or detection needs work
- Remove extraneous iter() in "for" of list comprehension Fixes #272
- "for" block without a `POP_BLOCK `and confusing `JUMP_BACK` for `CONTINUE`. Fixes #293
- Fix unmarshal incompletness detected in Pypy 3.6
- Miscellaneous bugs fixed
3.5.0 2019-10-12 Stony Brook Ride
=================================
- Fix fragment bugs
* missing RETURN_LAST introduced when adding transformation layer
* missing `RETURN_LAST` introduced when adding transformation layer
* more parent entries on tokens
- Preliminary support for decompiling Python 1.0, 1.1. 1.2 and 1.6
* Newer xdis version needed
- Preliminary support for decompiling Python 1.0, 1.1, 1.2, and 1.6
* Newer _xdis_ version needed
3.4.1 2019-10-02
================
- Correct assert{,2} transforms Fixes #289
- Fragment parsing fixes:
* Wasn't handling 3-arg %p
* fielding error in code_deparse()
- Use newer xdis to better track Python 3.8.0
* Wasn't handling 3-arg `%p`
* fielding error in `code_deparse()`
- Use newer _xdis_ to better track Python 3.8.0
3.4.0 2019-08-24 Totoro
@@ -124,7 +156,8 @@ Lots of decomplation bugs, especially in the 3.x series fixed. Don't worry thoug
3.3.0 2019-04-14 Holy Week
==========================
* First cut at Python 3.8 (many bug remain)
* First cut at Python 3.8 (many bugs remain)
* Reinstate -c | --compile (compile before disassembly) option
* The usual smattering of bug and doc fixes
3.2.6 2019-03-23 Mueller Report

View File

@@ -15,7 +15,7 @@ Introduction
*uncompyle6* translates Python bytecode back into equivalent Python
source code. It accepts bytecodes from Python version 1.0 to version
3.8, spanning over 24 years of Python releases. We include Dropbox's
Python 2.5 bytecode and some PyPy bytecode.
Python 2.5 bytecode and some PyPy bytecodes.
Why this?
---------
@@ -46,14 +46,15 @@ not exist and there is just bytecode. Again, my debuggers make use of
this.
There were (and still are) a number of decompyle, uncompyle,
uncompyle2, uncompyle3 forks around. Almost all of them come basically
from the same code base, and (almost?) all of them are no longer
actively maintained. One was really good at decompiling Python 1.5-2.3
or so, another really good at Python 2.7, but that only. Another
handles Python 3.2 only; another patched that and handled only 3.3.
You get the idea. This code pulls all of these forks together and
*moves forward*. There is some serious refactoring and cleanup in this
code base over those old forks.
uncompyle2, uncompyle3 forks around. Many of them come basically from
the same code base, and (almost?) all of them are no longer actively
maintained. One was really good at decompiling Python 1.5-2.3, another
really good at Python 2.7, but that only. Another handles Python 3.2
only; another patched that and handled only 3.3. You get the
idea. This code pulls all of these forks together and *moves
forward*. There is some serious refactoring and cleanup in this code
base over those old forks. Even more experimental refactoring is going
on in decompile3_.
This demonstrably does the best in decompiling Python across all
Python versions. And even when there is another project that only
@@ -75,11 +76,11 @@ fixed in the other decompilers.
Requirements
------------
The code here can be run on Python versions 2.6 or later, PyPy 3-2.4,
or PyPy-5.0.1. Python versions 2.4-2.7 are supported in the
python-2.4 branch. The bytecode files it can read have been tested on
Python bytecodes from versions 1.4, 2.1-2.7, and 3.0-3.8 and the
above-mentioned PyPy versions.
The code here can be run on Python versions 2.6 or later, PyPy 3-2.4
and later. Python versions 2.4-2.7 are supported in the python-2.4
branch. The bytecode files it can read have been tested on Python
bytecodes from versions 1.4, 2.1-2.7, and 3.0-3.8 and later PyPy
versions.
Installation
------------
@@ -186,15 +187,21 @@ they had been rare. Perhaps to compensate for the additional
added. So in sum handling control flow by ad hoc means as is currently
done is worse.
Between Python 3.5, 3.6 and 3.7 there have been major changes to the
:code:`MAKE_FUNCTION` and :code:`CALL_FUNCTION` instructions.
Between Python 3.5, 3.6, 3.7 there have been major changes to the
:code:`MAKE_FUNCTION` and :code:`CALL_FUNCTION` instructions. Python
Python 3.8 removes :code:`SETUP_LOOP`, :code:`SETUP_EXCEPT`,
:code:`BREAK_LOOP`, and :code:`CONTINUE_LOOP`, instructions which may
make control-flow detection harder, lacking the more sophisticated
control-flow analysis that is planned. We'll see.
Currently not all Python magic numbers are supported. Specifically in
some versions of Python, notably Python 3.6, the magic number has
changes several times within a version.
**We support only released versions, not candidate versions.** Note however
that the magic of a released version is usually the same as the *last* candidate version prior to release.
**We support only released versions, not candidate versions.** Note
however that the magic of a released version is usually the same as
the *last* candidate version prior to release.
There are also customized Python interpreters, notably Dropbox,
which use their own magic and encrypt bytcode. With the exception of
@@ -216,7 +223,7 @@ There is lots to do, so please dig in and help.
See Also
--------
* https://github.com/zrax/pycdc : purports to support all versions of Python. It is written in C++ and is most accurate for Python versions around 2.7 and 3.3 when the code was more actively developed. Accuracy for more recent versions of Python 3 and early versions of Python are especially lacking. See its `issue tracker <https://github.com/zrax/pycdc/issues>`_ for details. Currently lightly maintained.
* https://github.com/rocky/python-decompile3 : Much smaller and more modern code, focusing on 3.7+. Changes in that will get migrated back ehre.
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique than what is used here. Currently unmaintained.
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Includes some fixes like supporting function annotations. Currently unmaintained.
* https://github.com/wibiti/uncompyle2 : supports Python 2.7 only, but does that fairly well. There are situations where :code:`uncompyle6` results are incorrect while :code:`uncompyle2` results are not, but more often uncompyle6 is correct when uncompyle2 is not. Because :code:`uncompyle6` adheres to accuracy over idiomatic Python, :code:`uncompyle2` can produce more natural-looking code when it is correct. Currently :code:`uncompyle2` is lightly maintained. See its issue `tracker <https://github.com/wibiti/uncompyle2/issues>`_ for more details
@@ -225,6 +232,7 @@ See Also
* https://github.com/rocky/python-xdis : Cross Python version disassembler
* https://github.com/rocky/python-xasm : Cross Python version assembler
* https://github.com/rocky/python-uncompyle6/wiki : Wiki Documents which describe the code and aspects of it in more detail
* https://github.com/zrax/pycdc : The README for this C++ code syas it aims to support all versions of Python. It is best for Python versions around 2.7 and 3.3 when the code was initially developed. Accuracy for current versions of Python3 and early versions of Python is lacking. Without major effort, it is unlikely it can be made to support current Python 3. See its `issue tracker <https://github.com/zrax/pycdc/issues>`_ for details. Currently lightly maintained.
.. _trepan: https://pypi.python.org/pypi/trepan2g
@@ -233,6 +241,7 @@ See Also
.. _debuggers: https://pypi.python.org/pypi/trepan3k
.. _remake: https://bashdb.sf.net/remake
.. _pycdc: https://github.com/zrax/pycdc
.. _decompile3: https://github.com/rocky/python-decompile3
.. _this: https://github.com/rocky/python-uncompyle6/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting
.. |buildstatus| image:: https://travis-ci.org/rocky/python-uncompyle6.svg
:target: https://travis-ci.org/rocky/python-uncompyle6

View File

@@ -58,7 +58,7 @@ entry_points = {
]}
ftp_url = None
install_requires = ["spark-parser >= 1.8.9, < 1.9.0",
"xdis >= 4.1.0, < 4.2.0"]
"xdis >= 4.2.0, < 4.3.0"]
license = "GPL3"
mailing_list = "python-debugger@googlegroups.com"

0
admin-tools/check-newer-versions.sh Normal file → Executable file
View File

0
admin-tools/check-older-versions.sh Normal file → Executable file
View File

View File

@@ -56,19 +56,21 @@
$ . ./admin-tools/make-dist-older.sh
$ git tag release-python-2.4-$VERSION
$ twine check dist/uncompyle6-$VERSION*
$ . ./admin-tools/make-dist-newer.sh
Goto https://github.com/rocky/python-uncompyle6/releases
$ twine check dist/uncompyle6-$VERSION*
# Upload single package and look at Rst Formating
$ twine check dist/uncompyle6-${VERSION}*
$ twine upload dist/uncompyle6-${VERSION}-py3.3.egg
# Upload rest of versions
$ twine upload dist/uncompyle6-${VERSION}*
Goto https://github.com/rocky/python-uncompyle6/releases
# Push tags:
$ git push --tags

View File

@@ -1,46 +0,0 @@
git pull
Change version in uncompyle6/version.py
source uncompyle6/version.py
echo $VERSION
git commit -m"Get ready for release $VERSION" .
Update ChangeLog:
make ChangeLog
Update NEWS from ChangeLog
make check
git commit --amend .
git push
Make sure pyenv is running
# Pyenv
source admin-tools/check-newer-versions.sh
# Switch to python-2.4 and build that first...
source admin-tools/setup-python-2.4
rm ChangeLog
git merge master
Update NEWS from master branch
git commit -m"Get ready for release $VERSION" .
source admin-tools/check-older-versions.sh
source admin-tools/check-newer-versions.sh
make-dist-older.sh
git tag release-python-2.4-$VERSION
./make-dist-newer.sh
git tag release-$VERSION
twine upload dist/uncompyle6-${VERSION}*

View File

@@ -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.6.9 3.7.4 2.6.9 3.3.7 2.7.16 3.2.6 3.1.5 3.4.10 3.5.7'
export PYVERSIONS='3.5.9 3.6.9 2.6.9 3.3.7 2.7.17 3.2.6 3.1.5 3.4.10 3.7.5'

View File

@@ -6,4 +6,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
export PYVERSIONS='2.4.6 2.5.6'
export PYVERSIONS='2.4.6 2.5.6 2.6.9'

2
admin-tools/setup-master.sh Normal file → Executable file
View File

@@ -1,5 +1,5 @@
#!/bin/bash
PYTHON_VERSION=3.6.8
PYTHON_VERSION=3.7.5
# FIXME put some of the below in a common routine
function finish {

0
admin-tools/setup-python-2.4.sh Normal file → Executable file
View File

View File

@@ -1,3 +0,0 @@
#!/bin/bash
cd $(dirname ${BASH_SOURCE[0]})/..
git pull

View File

@@ -30,7 +30,7 @@ def list_comp():
[y for y in range(3)]
def get_parsed_for_fn(fn):
code = fn.func_code
code = fn.__code__ if PYTHON3 else fn.func_code
return deparse(code, version=PYTHON_VERSION)
def check_expect(expect, parsed, fn_name):

View File

@@ -20,7 +20,7 @@ def bug_loop(disassemble, tb=None):
disassemble(tb)
def test_if_in_for():
code = bug.func_code
code = bug.__code__
scan = get_scanner(PYTHON_VERSION)
if 2.7 <= PYTHON_VERSION <= 3.0 and not IS_PYPY:
scan.build_instructions(code)

158
pytest/test_fstring.py Normal file
View File

@@ -0,0 +1,158 @@
# std
# test
import sys
from uncompyle6 import PYTHON_VERSION, code_deparse
import pytest
pytestmark = pytest.mark.skipif(
PYTHON_VERSION <= 2.6, reason="hypothesis needs 2.7 or later"
)
if PYTHON_VERSION > 2.6:
import hypothesis
from hypothesis import strategies as st
# uncompyle6
@st.composite
def expressions(draw):
# todo : would be nice to generate expressions using hypothesis however
# this is pretty involved so for now just use a corpus of expressions
# from which to select.
return draw(
st.sampled_from(
(
"abc",
"len(items)",
"x + 1",
"lineno",
"container",
"self.attribute",
"self.method()",
# These expressions are failing, I think these are control
# flow problems rather than problems with FORMAT_VALUE,
# however I need to confirm this...
#'sorted(items, key=lambda x: x.name)',
#'func(*args, **kwargs)',
#'text or default',
#'43 if life_the_universe and everything else None'
)
)
)
@st.composite
def format_specifiers(draw):
"""
Generate a valid format specifier using the rules:
format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]
fill ::= <any character>
align ::= "<" | ">" | "=" | "^"
sign ::= "+" | "-" | " "
width ::= integer
precision ::= integer
type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
See https://docs.python.org/2/library/string.html
:param draw: Let hypothesis draw from other strategies.
:return: An example format_specifier.
"""
alphabet_strategy = st.characters(
min_codepoint=ord("a"), max_codepoint=ord("z")
)
fill = draw(st.one_of(alphabet_strategy, st.none()))
align = draw(st.sampled_from(list("<>=^")))
fill_align = (fill + align or "") if fill else ""
type_ = draw(st.sampled_from("bcdeEfFgGnosxX%"))
can_have_sign = type_ in "deEfFgGnoxX%"
can_have_comma = type_ in "deEfFgG%"
can_have_precision = type_ in "fFgG"
can_have_pound = type_ in "boxX%"
can_have_zero = type_ in "oxX"
sign = draw(st.sampled_from(list("+- ") + [""])) if can_have_sign else ""
pound = draw(st.sampled_from(("#", ""))) if can_have_pound else ""
zero = draw(st.sampled_from(("0", ""))) if can_have_zero else ""
int_strategy = st.integers(min_value=1, max_value=1000)
width = draw(st.one_of(int_strategy, st.none()))
width = str(width) if width is not None else ""
comma = draw(st.sampled_from((",", ""))) if can_have_comma else ""
if can_have_precision:
precision = draw(st.one_of(int_strategy, st.none()))
precision = "." + str(precision) if precision else ""
else:
precision = ""
return "".join((fill_align, sign, pound, zero, width, comma, precision, type_))
@st.composite
def fstrings(draw):
"""
Generate a valid f-string.
See https://www.python.org/dev/peps/pep-0498/#specification
:param draw: Let hypothsis draw from other strategies.
:return: A valid f-string.
"""
character_strategy = st.characters(
blacklist_characters="\r\n'\\s{}", min_codepoint=1, max_codepoint=1000
)
is_raw = draw(st.booleans())
integer_strategy = st.integers(min_value=0, max_value=3)
expression_count = draw(integer_strategy)
content = []
for _ in range(expression_count):
expression = draw(expressions())
conversion = draw(st.sampled_from(("", "!s", "!r", "!a")))
has_specifier = draw(st.booleans())
specifier = ":" + draw(format_specifiers()) if has_specifier else ""
content.append("{{{}{}}}".format(expression, conversion, specifier))
content.append(draw(st.text(character_strategy)))
content = "".join(content)
return "f{}'{}'".format("r" if is_raw else "", content)
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason="need Python 3.6")
@hypothesis.given(format_specifiers())
def test_format_specifiers(format_specifier):
"""Verify that format_specifiers generates valid specifiers"""
try:
exec('"{:' + format_specifier + '}".format(0)')
except ValueError as e:
if "Unknown format code" not in str(e):
raise
def run_test(text):
hypothesis.assume(len(text))
hypothesis.assume("f'{" in text)
expr = text + "\n"
code = compile(expr, "<string>", "single")
deparsed = code_deparse(code, sys.stdout, PYTHON_VERSION, compile_mode="single")
recompiled = compile(deparsed.text, "<string>", "single")
if recompiled != code:
print(recompiled)
print("================")
print(code)
print("----------------")
assert (
"dis(" + deparsed.text.strip("\n") + ")"
== "dis(" + expr.strip("\n") + ")"
)
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason="need Python 3.6")
@hypothesis.given(fstrings())
def test_uncompyle_fstring(fstring):
"""Verify uncompyling fstring bytecode"""
run_test(fstring)
@pytest.mark.skipif(PYTHON_VERSION != 3.6, reason="need Python 3.6+")
@pytest.mark.parametrize("fstring", ["f'{abc}{abc!s}'", "f'{abc}0'"])
def test_uncompyle_direct(fstring):
"""useful for debugging"""
run_test(fstring)

View File

@@ -0,0 +1,185 @@
import string
from uncompyle6 import PYTHON_VERSION
import pytest
pytestmark = pytest.mark.skip(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
if PYTHON_VERSION > 2.6:
from hypothesis import given, assume, example, settings, strategies as st
from validate import validate_uncompyle
from test_fstring import expressions
alpha = st.sampled_from(string.ascii_lowercase)
numbers = st.sampled_from(string.digits)
alphanum = st.sampled_from(string.ascii_lowercase + string.digits)
@st.composite
def function_calls(draw,
min_keyword_args=0, max_keyword_args=5,
min_positional_args=0, max_positional_args=5,
min_star_args=0, max_star_args=1,
min_double_star_args=0, max_double_star_args=1):
"""
Strategy factory for generating function calls.
:param draw: Callable which draws examples from other strategies.
:return: The function call text.
"""
st_positional_args = st.lists(
alpha,
min_size=min_positional_args,
max_size=max_positional_args
)
st_keyword_args = st.lists(
alpha,
min_size=min_keyword_args,
max_size=max_keyword_args
)
st_star_args = st.lists(
alpha,
min_size=min_star_args,
max_size=max_star_args
)
st_double_star_args = st.lists(
alpha,
min_size=min_double_star_args,
max_size=max_double_star_args
)
positional_args = draw(st_positional_args)
keyword_args = draw(st_keyword_args)
st_values = st.lists(
expressions(),
min_size=len(keyword_args),
max_size=len(keyword_args)
)
keyword_args = [
x + '=' + e
for x, e in
zip(keyword_args, draw(st_values))
]
star_args = ['*' + x for x in draw(st_star_args)]
double_star_args = ['**' + x for x in draw(st_double_star_args)]
arguments = positional_args + keyword_args + star_args + double_star_args
draw(st.randoms()).shuffle(arguments)
arguments = ','.join(arguments)
function_call = 'fn({arguments})'.format(arguments=arguments)
try:
# TODO: Figure out the exact rules for ordering of positional, keyword,
# star args, double star args and in which versions the various
# types of arguments are supported so we don't need to check that the
# expression compiles like this.
compile(function_call, '<string>', 'single')
except:
assume(False)
return function_call
def test_function_no_args():
validate_uncompyle("fn()")
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
def isolated_function_calls(which):
"""
Returns a strategy for generating function calls, but isolated to
particular types of arguments, for example only positional arguments.
This can help reason about debugging errors in specific types of function
calls.
:param which: One of 'keyword', 'positional', 'star', 'double_star'
:return: Strategy for generating an function call isolated to specific
argument types.
"""
kwargs = dict(
max_keyword_args=0,
max_positional_args=0,
max_star_args=0,
max_double_star_args=0,
)
kwargs['_'.join(('min', which, 'args'))] = 1
kwargs['_'.join(('max', which, 'args'))] = 5 if 'star' not in which else 1
return function_calls(**kwargs)
with settings(max_examples=25):
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
@given(isolated_function_calls('positional'))
@example("fn(0)")
def test_function_positional_only(expr):
validate_uncompyle(expr)
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
@given(isolated_function_calls('keyword'))
@example("fn(a=0)")
def test_function_call_keyword_only(expr):
validate_uncompyle(expr)
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
@given(isolated_function_calls('star'))
@example("fn(*items)")
def test_function_call_star_only(expr):
validate_uncompyle(expr)
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
@given(isolated_function_calls('double_star'))
@example("fn(**{})")
def test_function_call_double_star_only(expr):
validate_uncompyle(expr)
@pytest.mark.xfail()
def test_BUILD_CONST_KEY_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(w=0,m=0,**v)")
@pytest.mark.xfail()
def test_BUILD_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(a=0,**g)")
@pytest.mark.xfail()
def test_CALL_FUNCTION_EX():
validate_uncompyle("fn(*g,**j)")
@pytest.mark.xfail()
def test_BUILD_MAP_CALL_FUNCTION_EX():
validate_uncompyle("fn(*z,u=0)")
@pytest.mark.xfail()
def test_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(**a)")
@pytest.mark.xfail()
def test_BUILD_MAP_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
validate_uncompyle("fn(b,b,b=0,*a)")
@pytest.mark.xfail()
def test_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
validate_uncompyle("fn(*c,v)")
@pytest.mark.xfail()
def test_BUILD_CONST_KEY_MAP_CALL_FUNCTION_EX():
validate_uncompyle("fn(i=0,y=0,*p)")
@pytest.mark.skip(reason='skipping property based test until all individual tests are passing')
@given(function_calls())
def test_function_call(function_call):
validate_uncompyle(function_call)

View File

@@ -1,69 +1,81 @@
import re
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY # , PYTHON_VERSION
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY # , PYTHON_VERSION
from uncompyle6.parser import get_python_parser, python_parser
from uncompyle6.scanner import get_scanner
def test_grammar():
def test_grammar():
def check_tokens(tokens, opcode_set):
remain_tokens = set(tokens) - opcode_set
remain_tokens = set([re.sub(r'_\d+$','', t) for t in remain_tokens])
remain_tokens = set([re.sub('_CONT$','', t) for t in remain_tokens])
remain_tokens = set([re.sub('LOAD_CODE$','', t) for t in remain_tokens])
remain_tokens = set([re.sub(r"_\d+$", "", t) for t in remain_tokens])
remain_tokens = set([re.sub("_CONT$", "", t) for t in remain_tokens])
remain_tokens = set([re.sub("LOAD_CODE$", "", t) for t in remain_tokens])
remain_tokens = set(remain_tokens) - opcode_set
assert remain_tokens == set([]), \
"Remaining tokens %s\n====\n%s" % (remain_tokens, p.dump_grammar())
assert remain_tokens == set([]), "Remaining tokens %s\n====\n%s" % (
remain_tokens,
p.dump_grammar(),
)
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
(lhs, rhs, tokens,
right_recursive, dup_rhs) = p.check_sets()
(lhs, rhs, tokens, right_recursive, dup_rhs) = p.check_sets()
# We have custom rules that create the below
expect_lhs = set(['pos_arg', 'attribute'])
expect_lhs = set(["pos_arg"])
if PYTHON_VERSION < 3.8:
expect_lhs.add('get_iter')
if PYTHON_VERSION < 3.7:
expect_lhs.add("attribute")
expect_lhs.add("get_iter")
else:
expect_lhs.add("async_with_as_stmt")
expect_lhs.add("async_with_stmt")
unused_rhs = set(['list', 'mkfunc',
'mklambda',
'unpack',])
unused_rhs = set(["list", "mkfunc", "mklambda", "unpack"])
expect_right_recursive = set([('designList',
('store', 'DUP_TOP', 'designList'))])
expect_right_recursive = set([("designList", ("store", "DUP_TOP", "designList"))])
if PYTHON_VERSION < 3.7:
unused_rhs.add('call')
if PYTHON_VERSION <= 3.7:
unused_rhs.add("call")
if PYTHON_VERSION > 2.6:
expect_lhs.add('kvlist')
expect_lhs.add('kv3')
unused_rhs.add('dict')
expect_lhs.add("kvlist")
expect_lhs.add("kv3")
unused_rhs.add("dict")
if PYTHON3:
expect_lhs.add('load_genexpr')
expect_lhs.add("load_genexpr")
unused_rhs = unused_rhs.union(set("""
unused_rhs = unused_rhs.union(
set(
"""
except_pop_except generator_exp
""".split()))
""".split()
)
)
if PYTHON_VERSION >= 3.0:
expect_lhs.add("annotate_arg")
expect_lhs.add("annotate_tuple")
unused_rhs.add("mkfunc_annotate")
if PYTHON_VERSION < 3.7:
expect_lhs.add("annotate_arg")
expect_lhs.add("annotate_tuple")
unused_rhs.add("mkfunc_annotate")
unused_rhs.add("dict_comp")
unused_rhs.add("classdefdeco1")
unused_rhs.add("tryelsestmtl")
if PYTHON_VERSION >= 3.5:
expect_right_recursive.add((('l_stmts',
('lastl_stmt', 'come_froms', 'l_stmts'))))
expect_right_recursive.add(
(("l_stmts", ("lastl_stmt", "come_froms", "l_stmts")))
)
pass
elif 3.0 < PYTHON_VERSION < 3.3:
expect_right_recursive.add((('l_stmts',
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
expect_right_recursive.add(
(("l_stmts", ("lastl_stmt", "COME_FROM", "l_stmts")))
)
pass
pass
pass
else:
expect_lhs.add('kwarg')
expect_lhs.add("kwarg")
assert expect_lhs == set(lhs)
@@ -73,9 +85,16 @@ def test_grammar():
assert expect_right_recursive == right_recursive
expect_dup_rhs = frozenset([('COME_FROM',), ('CONTINUE',), ('JUMP_ABSOLUTE',),
('LOAD_CONST',),
('JUMP_BACK',), ('JUMP_FORWARD',)])
expect_dup_rhs = frozenset(
[
("COME_FROM",),
("CONTINUE",),
("JUMP_ABSOLUTE",),
("LOAD_CONST",),
("JUMP_BACK",),
("JUMP_FORWARD",),
]
)
reduced_dup_rhs = dict((k, dup_rhs[k]) for k in dup_rhs if k not in expect_dup_rhs)
for k in reduced_dup_rhs:
print(k, reduced_dup_rhs[k])
@@ -83,7 +102,7 @@ def test_grammar():
s = get_scanner(PYTHON_VERSION, IS_PYPY)
ignore_set = set(
"""
"""
JUMP_BACK CONTINUE
COME_FROM COME_FROM_EXCEPT
COME_FROM_EXCEPT_CLAUSE
@@ -92,22 +111,33 @@ def test_grammar():
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_STR LOAD_CODE
LAMBDA_MARKER
RETURN_END_IF RETURN_END_IF_LAMBDA RETURN_VALUE_LAMBDA RETURN_LAST
""".split())
""".split()
)
if 2.6 <= PYTHON_VERSION <= 2.7:
opcode_set = set(s.opc.opname).union(ignore_set)
if PYTHON_VERSION == 2.6:
opcode_set.add("THEN")
check_tokens(tokens, opcode_set)
elif PYTHON_VERSION == 3.4:
ignore_set.add('LOAD_CLASSNAME')
ignore_set.add('STORE_LOCALS')
ignore_set.add("LOAD_CLASSNAME")
ignore_set.add("STORE_LOCALS")
opcode_set = set(s.opc.opname).union(ignore_set)
check_tokens(tokens, opcode_set)
def test_dup_rule():
import inspect
python_parser(PYTHON_VERSION, inspect.currentframe().f_code,
is_pypy=IS_PYPY,
parser_debug={
'dups': True, 'transition': False, 'reduce': False,
'rules': False, 'errorstack': None, 'context': True})
python_parser(
PYTHON_VERSION,
inspect.currentframe().f_code,
is_pypy=IS_PYPY,
parser_debug={
"dups": True,
"transition": False,
"reduce": False,
"rules": False,
"errorstack": None,
"context": True,
},
)

View File

@@ -8,8 +8,12 @@ from uncompyle6.semantics.consts import (
if PYTHON3:
from io import StringIO
def iteritems(d):
return d.items()
else:
from StringIO import StringIO
def iteritems(d):
return d.iteritems()
from uncompyle6.semantics.pysource import (SourceWalker, deparse_code2str)
@@ -26,7 +30,7 @@ def test_template_engine():
# FIXME: and so on...
from uncompyle6.semantics.consts import (
TABLE_R, TABLE_DIRECT,
TABLE_DIRECT, TABLE_R,
)
from uncompyle6.semantics.fragments import (
@@ -40,7 +44,7 @@ def test_tables():
(TABLE_DIRECT, 'TABLE_DIRECT', False),
(TABLE_R, 'TABLE_R', False),
(TABLE_DIRECT_FRAGMENT, 'TABLE_DIRECT_FRAGMENT', True)):
for k, entry in t.iteritems():
for k, entry in iteritems(t):
if k in skip_for_now:
continue
fmt = entry[0]

View File

@@ -1,4 +1,7 @@
import pytest
from uncompyle6 import PYTHON_VERSION, code_deparse
pytestmark = pytest.mark.skip(PYTHON_VERSION < 2.7,
reason="need at least Python 2.7")
if PYTHON_VERSION > 2.6:
def test_single_mode():

View File

@@ -9,4 +9,4 @@
12 JUMP_FORWARD 0 'to 15'
15_0 COME_FROM 12 '12'
15 LOAD_CONST None
18 RETURN_VALUE
18 RETURN_VALUE

View File

@@ -12,4 +12,4 @@
18 STORE_NAME 2 'd'
21_0 COME_FROM 12 '12'
21 LOAD_CONST None
24 RETURN_VALUE
24 RETURN_VALUE

View File

@@ -1,16 +1,16 @@
#!/usr/bin/env python
"""Setup script for the 'uncompyle6' distribution."""
import sys
"""Setup script for the 'uncompyle6' distribution."""
SYS_VERSION = sys.version_info[0:2]
if not ((2, 4) <= SYS_VERSION <= (2, 7)):
mess = "Python Release 2.4 .. 2.7 are supported in this code branch."
if ((3, 2) <= SYS_VERSION <= (3, 8)):
mess += ("\nFor your Python, version %s, use the master code/branch." %
if not ((2, 6) <= SYS_VERSION <= (3, 9)):
mess = "Python Release 2.6 .. 3.9 are supported in this code branch."
if ((2, 4) <= SYS_VERSION <= (2, 7)):
mess += ("\nFor your Python, version %s, use the python-2.4 code/branch." %
sys.version[0:3])
else:
mess += ("\nThis package is not supported before Python 2.4. Your Python version is %s."
elif SYS_VERSION < (2, 4):
mess += ("\nThis package is not supported for Python version %s."
% sys.version[0:3])
print(mess)
raise Exception(mess)
@@ -32,6 +32,7 @@ setup(
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,

View File

@@ -1,55 +0,0 @@
import re
import unittest
from uncompyle6 import PYTHON_VERSION, IS_PYPY # , PYTHON_VERSION
from uncompyle6.parser import get_python_parser, python_parser
class TestGrammar(unittest.TestCase):
def test_grammar(self):
def check_tokens(tokens, opcode_set):
remain_tokens = set(tokens) - opcode_set
remain_tokens = set([re.sub('_\d+$','', t) for t in remain_tokens])
remain_tokens = set([re.sub('_CONT$','', t) for t in remain_tokens])
remain_tokens = set(remain_tokens) - opcode_set
self.assertEqual(remain_tokens, set([]),
"Remaining tokens %s\n====\n%s" % (remain_tokens, p.dump_grammar()))
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
(lhs, rhs, tokens,
right_recursive, dup_rhs) = p.check_sets()
expect_lhs = set(['expr1024', 'pos_arg'])
unused_rhs = set(['list', 'call', 'mkfunc',
'mklambda',
'unpack',])
expect_right_recursive = frozenset([('designList',
('store', 'DUP_TOP', 'designList'))])
expect_lhs.add('kwarg')
self.assertEqual(expect_lhs, set(lhs))
self.assertEqual(unused_rhs, set(rhs))
self.assertEqual(expect_right_recursive, right_recursive)
expect_dup_rhs = frozenset([('COME_FROM',), ('CONTINUE',), ('JUMP_ABSOLUTE',),
('LOAD_CONST',),
('JUMP_BACK',), ('JUMP_FORWARD',)])
reduced_dup_rhs = {}
for k in dup_rhs:
if k not in expect_dup_rhs:
reduced_dup_rhs[k] = dup_rhs[k]
pass
pass
for k in reduced_dup_rhs:
print(k, reduced_dup_rhs[k])
# assert not reduced_dup_rhs, reduced_dup_rhs
def test_dup_rule(self):
import inspect
python_parser(PYTHON_VERSION, inspect.currentframe().f_code,
is_pypy=IS_PYPY,
parser_debug={
'dups': True, 'transition': False, 'reduce': False,
'rules': False, 'errorstack': None, 'context': True})
if __name__ == '__main__':
unittest.main()

View File

@@ -30,7 +30,7 @@ check:
$(MAKE) check-$(PYTHON_VERSION)
#: Run working tests from Python 2.6 or 2.7
check-2.4 check-2.5 check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-bytecode-1 check-native-short
check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-bytecode-1 check-native-short
#: Run working tests from Python 3.0
check-3.0: check-bytecode
@@ -72,10 +72,10 @@ check-3.7: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.7-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-3.7 --syntax-verify $(COMPILE)
# #: Run working tests from Python 3.8
# check-3.8: check-bytecode
# $(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
# $(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify $(COMPILE)
#: Run working tests from Python 3.8
check-3.8: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify $(COMPILE)
# FIXME
#: this is called when running under pypy3.5-5.8.0 or pypy2-5.6.0
@@ -99,8 +99,8 @@ check-bytecode-3:
$(PYTHON) test_pythonlib.py --bytecode-3.0 \
--bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6 \
--bytecode-3.7 \
--bytecode-pypy3.2
--bytecode-3.7 \
--bytecode-pypy3.2 --bytecode-pypy3.6 --bytecode-3.8
#: Check deparsing on selected bytecode 3.x
check-bytecode-3-short:
@@ -166,7 +166,6 @@ check-bytecode-2.3:
#: Check deparsing Python 2.4
check-bytecode-2.4:
$(PYTHON) test_pythonlib.py --bytecode-2.4-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-2.4
#: Check deparsing Python 2.5
@@ -295,20 +294,16 @@ check-bytecode-3.7:
$(PYTHON) test_pythonlib.py --bytecode-3.7-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-3.7 --syntax-verify
# #: Check deparsing Python 3.8
# check-bytecode-3.8:
# $(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
# $(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify
#: Check deparsing Python 3.8
check-bytecode-3.8:
$(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify
#: short tests for bytecodes only for this version of Python
check-native-short:
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --syntax-verify $(COMPILE)
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION)-run --verify-run $(COMPILE)
#: Run longer Python 2.6's lib files known to be okay
check-2.4-ok:
$(PYTHON) test_pythonlib.py --ok-2.4 --verify $(COMPILE)
#: Run longer Python 2.6's lib files known to be okay
check-2.6-ok:
$(PYTHON) test_pythonlib.py --ok-2.6 --syntax-verify $(COMPILE)
@@ -337,8 +332,16 @@ pypy-2.7 5.0 5.3 6.0:
pypy-3.2 2.4:
$(PYTHON) test_pythonlib.py --bytecode-pypy3.2 --verify
#: PyPy 5.0.x with Python 3.6 ...
#: PyPy 5.0.x with Python 3.6.1 ...
check-bytecode-pypy3.6: 7.1
7.1:
$(PYTHON) test_pythonlib.py --bytecode-pypy3.6-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-pypy3.6 --verify
#: PyPy 5.0.x with Python 3.6.9
check-bytecode-pypy3.6: 7.2
7.2:
$(PYTHON) test_pythonlib.py --bytecode-pypy3.6-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-pypy3.6 --verify

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More