Compare commits

..

119 Commits

Author SHA1 Message Date
rocky
5e05e521d9 Merge branch 'master' into python-2.4 2017-11-26 10:08:59 -05:00
rocky
7a052c349a Merge branch 'master' into python-2.4 2017-11-26 09:33:25 -05:00
rocky
35aca37557 Isolate kv, kv2, and kdv3 better 2017-11-26 06:53:22 -05:00
rocky
57fe56d72e localize kv 2017-11-26 01:35:03 -05:00
rocky
218e73540a Merge branch 'master' into python-2.4 2017-11-26 01:27:56 -05:00
rocky
0965e2cc96 Localize kv 2017-11-26 01:26:57 -05:00
rocky
5cf4f0a82f Merge hell 2017-11-25 23:15:07 -05:00
rocky
9b0225db60 Merge branch 'master' into python-2.4 2017-11-25 23:15:01 -05:00
rocky
8c0959de42 inf and nan tests 2017-11-25 23:11:27 -05:00
rocky
ccd71c857f Regularze grammar coverage rules 2017-11-24 22:44:22 -05:00
rocky
b89dbb0ee7 Merge hell 2017-11-24 21:48:24 -05:00
rocky
a5bdc1acd0 Merge branch 'master' into python-2.4 2017-11-24 21:48:14 -05:00
rocky
a279784d8d Merge branch 'master' into python-2.4 2017-11-23 17:17:54 -05:00
rocky
3a9f4f2984 Merge branch 'master' into python-2.4 2017-11-23 12:37:00 -05:00
rocky
51ae8313cf Merge branch 'master' into python-2.4 2017-11-22 14:45:16 -05:00
rocky
38f04f0073 More complete grammar coverage 2017-11-22 11:15:39 -05:00
rocky
f3da5d770d Merge hell 2017-11-22 06:26:20 -05:00
rocky
24fb13cf23 Merge branch 'master' into python-2.4 2017-11-22 06:25:52 -05:00
rocky
524e8c8410 Python 2.5 "with". isolate 2.5-2.7 grammar better 2017-11-16 09:18:26 -05:00
rocky
52d1e44560 Merge branch 'master' into python-2.4 2017-11-16 09:18:19 -05:00
rocky
6055c5e165 Get ready for release python-2.4- 2017-11-13 10:58:46 -05:00
rocky
e0ed187ea6 2.4isms...
Need print without parens. Handle old-style classes more properly?
2017-11-13 10:52:43 -05:00
rocky
eafe048c7e Get ready for release python-2.4-2.13.3 2017-11-13 10:12:27 -05:00
rocky
c0e553dbb5 Merge branch 'master' into python-2.4 2017-11-13 10:11:00 -05:00
rocky
7e59987af7 Merge branch 'master' into python-2.4 2017-10-12 07:31:19 -04:00
rocky
1f012f7c46 Merge conflicts 2017-10-12 07:18:11 -04:00
rocky
d1a3d42ab8 Sync 2017-10-12 07:08:58 -04:00
rocky
05fd992c48 Update news 2017-10-12 07:06:19 -04:00
rocky
47f1d888eb Merge branch 'master' into python-2.4 2017-10-12 07:05:34 -04:00
rocky
ca9c227837 More administrivia 2017-10-11 22:17:50 -04:00
rocky
5df384bb71 Some admin tools I use 2017-10-11 21:16:35 -04:00
rocky
e80b36347a Remove creaping Python 2.6ism 2017-10-11 20:43:17 -04:00
rocky
9e37495493 Sync with master 2017-10-10 23:06:22 -04:00
rocky
77b93c5f21 Sync with master 2017-10-10 23:04:25 -04:00
rocky
0b198ee881 Sync with master 2017-10-10 23:02:20 -04:00
rocky
9e0c65881d Sync with master 2017-10-10 22:52:07 -04:00
rocky
c796d6a799 Merge commit '1d7a3c6444eab5a02d899f789f2a57cfdcbc5a84' into python-2.4 2017-10-10 22:50:28 -04:00
rocky
3892fb533a Misc bugs 2017-10-10 16:12:02 -04:00
rocky
2ea7487ca7 One more test 2017-10-05 11:19:36 -04:00
rocky
d4f6cec3d0 Sync with master 2017-10-05 11:17:49 -04:00
rocky
b1705e283d handle newer parser reduction behavior 2017-10-03 11:54:24 -04:00
rocky
eee751e22a Go over table-semantics description yet again 2017-10-03 05:44:55 -04:00
rocky
2b0fefb95f Sync with master 2017-10-02 03:12:26 -04:00
rocky
1a627ba207 Annotation field can be unicode...
When deparsing Python 3.x from Python 2.
2017-09-26 09:53:26 -04:00
rocky
ea75bcf47e Require xdis 3.6.0 or greater 2017-09-25 20:11:53 -04:00
rocky
6c6dcab857 Merge branch 'python-2.4' of github.com:rocky/python-uncompyle6 into python-2.4 2017-09-25 20:09:04 -04:00
rocky
0654aed6c8 Get ready for release 2.12.0 2017-09-25 20:08:50 -04:00
rocky
3447ca0767 Unit test for format-specifiers 2017-09-21 11:29:17 -04:00
rocky
1e858efafd Tidy pysource and fragments 2017-09-20 19:08:41 -04:00
rocky
ce88a72ea1 Tidy/regularize table entry formatting 2017-09-20 17:52:48 -04:00
rocky
7725b8e7de small fixes...
test_pythonlib.py: it is sys.exit not exit
pysource.py: restore node type on async_call function
2017-09-20 11:30:50 -04:00
rocky
62ddbe320d Start pysource unit test 2017-09-20 01:15:37 -04:00
rocky
a694601264 emgine -> template_engine 2017-09-17 12:03:49 -04:00
rocky
e06f88043f Merge branch 'master' into python-2.4 2017-08-31 09:54:23 -04:00
rocky
8fc3fd146f Merge branch 'master' into python-2.4 2017-08-31 09:47:02 -04:00
rocky
ce5066bddb Merge branch 'master' into python-2.4 2017-08-15 11:12:20 -04:00
rocky
93f18e2449 Allow version to be string...
in get_python_parser and get_scanner
2017-08-13 09:23:27 -04:00
rocky
783e62f3ca Merge branch 'python-2.4' of github.com:rocky/python-uncompyle6 into python-2.4 2017-08-10 09:45:11 -04:00
rocky
c38dc61021 xdis "is not" is now "is-not" 2017-08-09 22:07:32 -04:00
rocky
45782bbb39 Get ready for release 2.11.3 2017-08-09 21:46:27 -04:00
rocky
4c9cd5657e Merge branch 'master' into python-2.4 2017-08-09 21:45:50 -04:00
rocky
dc627d13b8 Get ready for release 2.11.3 2017-08-09 21:33:01 -04:00
rocky
ddc3489991 Python 2.4 comptiability and ...
exception match -> exception-match
2017-08-03 03:48:57 -04:00
rocky
5b24c20331 Bump xdis 2017-08-02 08:37:50 -04:00
rocky
8bb01143d8 Remove six from python 2.4/2.5 2017-08-02 08:28:08 -04:00
rocky
a9635da96a in xdis "exception match" is now "exception-match" 2017-08-02 06:36:40 -04:00
rocky
e790cb75fd Python 2.4 doesn't do six 2017-08-02 06:20:07 -04:00
rocky
348afeebbf Python 2.4 compatibility 2017-08-01 22:32:43 -04:00
rocky
6888553773 Merge branch 'master' into python-2.4 2017-06-25 18:56:31 -04:00
rocky
0f489672b9 More merge fixups from master 2017-06-18 16:05:22 -04:00
rocky
b7d8cbfaf5 Merge branch 'master' into python-2.4 2017-06-18 15:40:40 -04:00
rocky
df8d253f78 2.4 doesn't do six 2017-06-03 06:00:47 -04:00
rocky
89b42e3696 Nope it (appveyor) doesn't. 2017-06-03 05:55:21 -04:00
rocky
22e5a4a283 Administrivia
See if appveyor will handle 2.5
2017-06-03 05:53:41 -04:00
rocky
61810172d1 Merge branch 'master' into python-2.4 2017-06-03 05:50:42 -04:00
rocky
658c8b4be7 No decorators in Python < 2.6 2017-05-30 02:30:56 -04:00
rocky
d4dab54c7b Merge branch 'master' into python-2.4 2017-05-30 02:18:57 -04:00
rocky
5566b9ba6c Get ready for release 2.9.11 2017-05-06 07:49:09 -04:00
rocky
e56ab2dcd5 Sync with master 2017-05-06 07:17:04 -04:00
rocky
d6c45979ba Merge branch 'master' into python-2.4 2017-05-06 07:16:39 -04:00
rocky
a06e9bf32e Merge branch 'master' into python-2.4 2017-04-14 05:45:53 -04:00
rocky
7e8f7ba674 namedtuple25 -> namedtuple24 2017-04-14 05:42:44 -04:00
rocky
09eb7f7f78 Merge branch 'master' into python-2.4 2017-04-10 00:48:04 -04:00
rocky
f7a910ec66 Merge branch 'master' into python-2.4 2017-03-01 05:55:26 -05:00
rocky
6d6a73eea7 Merge branch 'master' into python-2.4 2017-02-25 21:02:12 -05:00
rocky
e4a7641927 Python <= 2.6 grammar fixes 2017-02-25 05:13:19 -05:00
rocky
b24b46d48c Merge branch 'master' into python-2.4 2017-02-25 04:48:06 -05:00
rocky
a65d7dce5b Python 2.5 was missing try else stmt 2017-02-22 05:30:07 -05:00
rocky
718a0a5d34 Merge branch 'master' into python-2.4 2017-02-22 05:29:49 -05:00
rocky
ea9e3ab3f5 Group coverage Makefile targets 2017-02-10 01:00:26 -05:00
rocky
770e988ff8 Changes based on coverage information 2017-01-29 22:54:30 -05:00
rocky
0fa0641974 Merge branch 'master' into python-2.4 2017-01-29 22:05:55 -05:00
rocky
c13e23cdae Get ready for release 2.9.9 2017-01-11 21:52:20 -05:00
rocky
fab4ebb768 Merge changes ...
* str() in Python 2.4 doesn't detect unicode.
* index() doesn't work on tuples
* ifelse change
2017-01-11 19:34:28 -05:00
rocky
89429339fa Merge branch 'master' into python-2.4 2017-01-11 19:25:44 -05:00
rocky
6ed129bd7a 2.4 verify hacks 2017-01-02 07:15:46 -05:00
rocky
c4fde6b53e Merge branch 'master' into python-2.4 2017-01-02 05:39:50 -05:00
rocky
a7d93e88b4 Merge branch 'master' into python-2.4 2017-01-02 05:39:13 -05:00
rocky
9891494142 We are version 2.9.9 2016-12-31 18:16:23 -05:00
rocky
f8544dfbbe 2.7->2.4 conversion 2016-12-31 10:56:43 -05:00
rocky
b00651d428 Merge master branche
Handle 2.2 list_if
2016-12-31 05:19:21 -05:00
rocky
da8dccbaca Merge branch 'master' into python-2.4 2016-12-29 02:08:12 -05:00
rocky
37272ae827 Merge commit '9b1dd0f' into python-2.4 2016-12-27 10:32:25 -05:00
rocky
7f2bee46b7 Bug in using python2 ast checking in python 2.5 2016-12-26 01:55:16 -05:00
rocky
c8a4dcf72b Removing NAME_MODULE, lint and bug fixes
scanner*.py: show_asm param is optional
verify.py: call correct scanners
main.py, verify.py: Use older Python print statements
2016-12-25 09:16:04 -05:00
rocky
012ff91cfb Merge branch 'master' into python-2.4 2016-12-25 07:57:17 -05:00
rocky
e690ddd50a Merge branch 'master' into python-2.4 2016-12-18 07:43:15 -05:00
rocky
45b7c1948c show-asm on python2.5 is optional
Make scanner2 a little more like scanner3.
2016-12-17 07:57:31 -05:00
rocky
e2fb7ca3d2 Python 2.6/2.7 tolerance in Python 2.4 branch 2016-12-17 06:51:47 -05:00
rocky
b3bda76582 Merge branch 'master' into python-2.4 2016-12-16 22:56:07 -05:00
rocky
ab6d322eca Get ready for release 2.9.7 2016-12-04 14:09:53 -05:00
rocky
1a8a0df107 Merge branch 'master' into python-2.4 2016-12-04 13:40:06 -05:00
rocky
0a37709b0a CircleCI build 2016-11-24 05:41:31 -05:00
rocky
98cd1417df Remove dup Python 3 grammar rule 2016-11-24 05:36:43 -05:00
rocky
460069ceaa Bug in 2.4 "if" dectection and...
Wrong language used in old-style exceptions: use "except Error,e" not
"except Error(e)""
2016-11-24 05:15:35 -05:00
rocky
316aa44f23 Python 2.6 grammary bug and..
__pkginfo.py__: Bump spark_parser version for parse_flags 'dups'
2016-11-24 04:09:32 -05:00
rocky
7133540c23 Make work on 2.4 2016-11-23 08:26:12 -05:00
rocky
590231741d Merge branch 'come-from-type' into python-2.4 2016-11-23 07:54:18 -05:00
rocky
a9349b8f3d Making it run on Python 2.4 and 2.5 2016-11-23 07:53:51 -05:00
324 changed files with 10180 additions and 5248 deletions

1
.gitignore vendored
View File

@@ -19,4 +19,3 @@ build
/.venv*
/.idea
/.hypothesis
ChangeLog

View File

@@ -3,13 +3,7 @@ language: python
sudo: false
python:
- '3.5'
- '2.7.12'
- '2.6'
- '3.3'
- '3.4'
- '3.2'
- '3.6'
- '2.7' # this is a cheat here because travis doesn't do 2.4-2.6
install:
- pip install -e .

7794
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -64,17 +64,14 @@ success that his good work deserves.
Dan Pascu did a bit of work from late 2004 to early 2006 to get this
code to handle first Python 2.3 and then 2.4 bytecodes. Because of
jump optimization introduced in the CPython bytecode compiler at that
time, various JUMP instructions were classified to assist parsing For
example, due to the way that code generation and line number table
work, jump instructions to an earlier offset must be looping jumps,
such as those found in a "continue" statement; "COME FROM"
instructions were reintroduced. See
time, various JUMP instructions were classifed as going backwards, and
COME FROM instructions were reintroduced. See
[RELEASE-2.4-CHANGELOG.txt](https://github.com/rocky/python-uncompyle6/blob/master/DECOMPYLE-2.4-CHANGELOG.txt)
for more details here. There wasn't a public release of RELEASE-2.4
and bytecodes other than Python 2.4 weren't supported. Dan says the
Python 2.3 version could verify the entire Python library. But given
subsequent bugs found like simply recognizing complex-number constants
in bytecode, decompilation wasn't perfect.
for more details here. There wasn't a public
release of RELEASE-2.4 and bytecodes other than Python 2.4 weren't
supported. Dan says the Python 2.3 version could verify the entire
Python library. But given subsequent bugs found like simply
recognizing complex-number constants in bytecode, decompilation wasn't perfect.
Next we get to ["uncompyle" and
PyPI](https://pypi.python.org/pypi/uncompyle/1.1) and the era of
@@ -112,26 +109,15 @@ Given this, perhaps it is not surprising that subsequent changes
tended to shy away from using the built-in compiler technology
mechanisms and addressed problems and extensions by some other means.
Specifically, in `uncompyle`, decompilation of python bytecode 2.5 &
2.6 is done by transforming the byte code into a pseudo-2.7 Python
bytecode and is based on code from Eloi Vanderbeken. A bit of this
could have bene easily added by modifying grammar rules.
Specifically, in `uncompyle`, decompilation of python bytecode 2.5 & 2.6
is done by transforming the byte code into a pseudo-2.7 Python
bytecode and is based on code from Eloi Vanderbeken.
This project, `uncompyle6`, abandons that approach for various
reasons. Having a grammar per Python version is much cleaner and it
scales indefinitely. That said, we don't have entire copies of the
grammar, but work off of differences from some neighboring version.
Should there be a desire to rebase or start a new base version to work
off of, say for some future Python version, that can be done by
dumping a grammar for a specific version after it has been loaded
incrementally. You can get a full dump of the grammar by profiling the
grammar on a large body of Python source code.
Another problem with pseudo-2.7 bytecode is that that we need offsets
in fragment deparsing to be exactly the same as the bytecode; the
transformation process can remove instructions. _Adding_ instructions
with psuedo offsets is however okay.
reasons. However the main reason is that we need offsets in fragment
deparsing to be exactly the same, and the transformation process can
remove instructions. _Adding_ instructions with psuedo offsets is
however okay.
`Uncompyle6` however owes its existence to the fork of `uncompyle2` by
Myst herie (Mysterie) whose first commit picks up at
@@ -169,44 +155,25 @@ Hartmut a decade an a half ago:
This project deparses using an Earley-algorithm parse with lots of
massaging of tokens and the grammar in the scanner
phase. Earley-algorithm parsers are context free and tend to be linear
if the grammar is LR or left recursive. There is a technique for
improving LL right recursion, but our parser doesn't have that yet.
if the grammar is LR or left recursive.
Another approach to decompiling, and one that doesn't use grammars is
to do something like simulate execution symbolically and build
expression trees off of stack results. Control flow in that approach
still needs to be handled somewhat ad hoc. The two important projects
that work this way are [unpyc3](https://code.google.com/p/unpyc3/) and
most especially [pycdc](https://github.com/zrax/pycdc) The latter
project is largely by Michael Hansen and Darryl Pogue. If they
supported getting source-code fragments, did a better job in
supporting Python more fully, and had a way I could call it from
Python, I'd probably would have ditched this and used that. The code
runs blindingly fast and spans all versions of Python, although more
recently Python 3 support has been lagging. The code is impressive for
its smallness given that it covers many versions of Python. However, I
think it has reached a scalability issue, same as all the other
efforts. To handle Python versions more accurately, I think that code
base will need to have a lot more code specially which specializes for
Python versions. And then it will run into a modularity problem.
Another approach that doesn't use grammars is to do something like
simulate execution symbolically and build expression trees off of
stack results. Control flow in that apprproach still needs to be
handled somewhat ad hoc. The two important projects that work this
way are [unpyc3](https://code.google.com/p/unpyc3/) and most
especially [pycdc](https://github.com/zrax/pycdc) The latter project
is largely by Michael Hansen and Darryl Pogue. If they supported
getting source-code fragments, did a better job in supporting Python
more fully, and had a way I could call it from Python, I'd probably
would have ditched this and used that. The code runs blindingly fast
and spans all versions of Python, although more recently Python 3
support has been lagging.
Tests for the project have been, or are being, culled from all of the
projects mentioned. Quite a few have been added to improve grammar
coverage and to address the numerous bugs that have been encountered.
projects mentioned.
If you think, as I am sure will happen in the future, "hey, I can just
write a decompiler from scratch and not have to deal with all all of
the complexity here", think again. What is likely to happen is that
you'll get at best a 90% solution working for a single Python release
that will be obsolete in about a year, and more obsolete each
subsequent year. Writing a decompiler for Python gets harder as it
Python progresses, so writing one for Python 3.7 isn't as easy as it
was for Python 2.2. That said, if you still feel you want to write a
single version decompiler, look at the test cases in this project and
talk to me. I may have some ideas.
For a little bit of the history of changes to the Earley-algorithm parser,
For a little bit of the history of changes to the Early-algorithm parser,
see the file [NEW-FEATURES.rst](https://github.com/rocky/python-spark/blob/master/NEW-FEATURES.rst) in the [python-spark github repository](https://github.com/rocky/python-spark).
NB. If you find mistakes, want corrections, or want your name added

View File

@@ -10,36 +10,23 @@ decompile everything. Overall, I think this one probably does the best
job of *any* Python decompiler that handles such a wide range of
versions.
But at any given time, there are a number of valid Python bytecode
files that I know of that will cause problems. See, for example, the
list in
[`test/stdlib/runtests.sh`](https://github.com/rocky/python-uncompyle6/blob/master/test/stdlib/runtests.sh).
But at any given time, there are maybe dozens of valid Python bytecode
files that I know of that will cause problems. And when I get through
those and all the issues of decompiler bugs that are currently logged,
I could probably easily find dozens more bugs just by doing a
decompile of all the Python bytecode on any one of my
computers. Unless you want to help out by _fixing_ bugs, or are
willing to do work by isolating and narrowing bugs, don't feel you are
doing me a favor by doing scans on your favorite sets of bytecode
files.
But I understand: you would the bugs _you_ encounter addressed before
all the other known bugs.
In sum, it is not uncommon that you will find a mistranslation in
decompiling. Furthermore, you may be expected to do some work in order
to have your bug worthy of being considered above other bugs.
From my standpoint, the good thing about the bugs listed in
`runtests.sh` is that each test case is small and isolated to a single
kind of problem. And I'll tend to fix easier, more isolated cases than
generic "something's wrong" kinds of bugs where I'd have to do a bit
of work to figure out what's up, if not use some sort of mind reading,
make some guesses, and perform some experiments to see if the guesses
are correct. I can't read minds, nor am I into guessing games; I'd
rather devote the effort spent instead towards fixing bugs that are
precisely defined.
And it often turns out that by just fixing the well-defined and
prescribed cases, the ill-defined amorphous cases as well will get
handled as well.
In sum, you may need to do some work to have the bug you have found
handled before the hundreds of other bugs, and things I could be
doing.
No one is getting paid to work to work on this project, let alone the
bugs you may have an interest in. If you require decompiling bytecode
immediately, consider using a decompilation service, listed further
down in this document.
No one is getting paid to work to work on this project, let alone bugs
you may have an interest in. If you require decompiling bytecode
immediately, consider using a decompilation service.
## Is it really a bug?
@@ -53,7 +40,7 @@ obfuscation.
Checking if bytecode is valid is pretty simple: disassemble the code.
Python comes with a disassembly module called `dis`. A prerequisite
module for this package, `xdis` has a cross-python version
disassembler called `pydisasm`.
disassembler.
### Semantic equivalence vs. exact source code
@@ -127,7 +114,7 @@ Also try to narrow the bug. See below.
Some kind folks also give the invocation they used and the output
which usually includes an error message produced. This is
helpful. From this, I can figure out what OS you are running this on
and what version of *uncomplye6* was used. Therefore, if you _don't_
and what version of *uncomplye6* was used. Therefore, if you don't
provide the input command and the output from that, please give:
* _uncompyle6_ version used
@@ -139,7 +126,7 @@ provide the input command and the output from that, please give:
Sure, I get it. No problem. There is Python assembly code on parse
errors, so simply by hand decompile that. To get a full disassembly,
use `pydisasm` from the [xdis](https://pypi.python.org/pypi/xdis)
use pydisasm from the [xdis](https://pypi.python.org/pypi/xdis)
package. Opcodes are described in the documentation for
the [dis](https://docs.python.org/3.6/library/dis.html) module.

View File

@@ -39,7 +39,7 @@ check-3.0 check-3.1 check-3.2 check-3.5 check-3.6:
check-3.7: pytest
#:Tests for Python 2.6 (doesn't have pytest)
check-2.6:
check-2.4 check-2.5 check-2.6:
$(MAKE) -C test $@
#:PyPy 2.6.1 PyPy 5.0.1, or PyPy 5.8.0-beta0

57
NEWS
View File

@@ -1,60 +1,3 @@
uncompyle6 2.15.0 2018-02-05 pycon2018.co
- Bug fixes
- Code fragment improvements
- Code cleanups
- Expand testing
uncompyle6 2.15.1 2018-01-27
- Add --linemap option to give line correspondences
between original source lines and reconstructed line sources.
It is far from perfect, but it is a start
- Add a new class of tests: tests which when decompiled check themselves
- Split off Python version semantic action customizations into its own file
- Fix 2.7 bug in ifelse loop statement
- Handle 3.6+ EXTENDED_ARGs for POP_JUMP_IF... instructions
- Correct 3.6+ calls with kwargs
- Describe the difficulty of 3.6 in README
uncompyle6 2.14.3 2018-01-19
- Fix bug in 3.5+ await stmt
- Better version to magic handling; handle 3.5.2 .. 3.5.4 versions
- Improve/correct test_pyenvlib.py status messages
- Fix some 2.7 and 2.6 parser bugs
- Fix whilelse parsing bugs
- Correct 2.5- decorator parsing
- grammar for decorators matches AST a little more
- better tests in setup.py for running the right version of Python
- Fix 2.6- parsing of "for .. try/else" ... with "continue" inside
uncompyle6 2.14.2 2018-01-09 Samish
Decompilation bug fixes, mostly 3.6 and pre 2.7
- 3.6 FUNCTION_EX (somewhat)
- 3.6 FUNCTION_EX_KW fixes
- 3.6 MAKE_FUNCTION fixes
- correct 3.5 CALL_FUNCTION_VAR
- stronger 3.x "while 1" testing
- Fix bug in if's with "pass" bodies. Fixes #104
- try/else and try/finally fixes on 2.6-
- limit pypy customization to pypy
- Add addr fields in COME_FROMS
- Allow use of full instructions in parser reduction routines
- Reduce grammar in Pythion 3 by specialization more to specific
Python versions
- Match Python AST names more closely when possible
uncompyle6 2.14.1 2017-12-10 Dr. Gecko
- Many decompilation bugfixes
- Grammar rule reduction and version isolation
- Match higher-level nonterminal names more closely
with Python AST
- Start automated Python stdlib testing - full round trip
uncompyle6 2.14.0 2017-11-26 johnnybamazing
- Start to isolate grammar rules between versions

View File

@@ -3,7 +3,7 @@
uncompyle6
==========
A native Python cross-version decompiler and fragment decompiler.
A native Python cross-version Decompiler and Fragment Decompiler.
The successor to decompyle, uncompyle, and uncompyle2.
@@ -17,57 +17,43 @@ source code. It accepts bytecodes from Python version 1.5, and 2.1 to
Why this?
---------
Ok, I'll say it: this software is amazing. It is more than your
normal hacky decompiler. Using compiler_ technology, the program
creates a parse tree of the program from the instructions; nodes at
the upper levels that look a little like what might come from a Python
AST. So we can really classify and understand what's going on in
sections of Python bytecode.
Building on this, another thing that makes this different from other
CPython bytecode decompilers is the ability to deparse just
*fragments* of source code and give source-code information around a
given bytecode offset.
I use the tree fragments to deparse fragments of code inside my
trepan_ debuggers_. For that, bytecode offsets are recorded and
associated with fragments of the source code. This purpose, although
compatible with the original intention, is yet a little bit different.
See this_ for more information.
Python fragment deparsing given an instruction offset is useful in
showing stack traces and can be encorporated into any program that
wants to show a location in more detail than just a line number at
runtime. This code can be also used when source-code information does
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.
There were a number of decompyle, uncompyle, uncompyle2, uncompyle3
forks around. All of them came basically from the same code base, and
almost all of them no were no longer actively maintained. Only one
handled Python 3, and even there, only 3.2 or 3.3 depending on which
code is used. This code pulls these together and moves forward.
This project has the most complete support for Python 3.3 and above
and the best all-around Python support.
and the best all-around Pythoin support.
We are serious about testing, and use automated processes to find
bugs. In the issue trackers for other decompilers, you will find a
number of bugs we've found along the way. Very few to none of them are
fixed in the other decompilers.
not fixed in the other decompilers.
Another thing that makes this different from other CPython bytecode
decompilers is the ability to deparse just fragments and give
source-code information around a given bytecode offset.
I use this to deparse fragments of code inside my trepan_
debuggers_. For that, I need to record text fragments for all
bytecode offsets (of interest). This purpose although largely
compatible with the original intention is yet a little bit different.
See this_ for more information.
The idea of Python fragment deparsing given an instruction offset can
be used in showing stack traces or any program that wants to show a
location in more detail than just a line number. It can be also used
when source-code information does not exist and there is just bytecode
information.
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.5, 2.1-2.7, and 3.0-3.6 and the
above-mentioned PyPy versions.
This project requires Python 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 has been tested on Python bytecodes from
versions 1.5, 2.1-2.7, and 3.0-3.6 and the above-mentioned PyPy versions.
Installation
------------
@@ -76,9 +62,11 @@ This uses setup.py, so it follows the standard Python routine:
::
pip install -e . # set up to run from source tree
# Or if you want to install instead
pip install -e .
pip install -r requirements-dev.txt
python setup.py install # may need sudo
# or if you have pyenv:
python setup.py develop
A GNU makefile is also provided so :code:`make install` (possibly as root or
sudo) will do the steps above.
@@ -128,13 +116,13 @@ Known Bugs/Restrictions
The biggest known and possibly fixable (but hard) problem has to do
with handling control flow. (Python has probably the most diverse and
screwy set of compound statements I've ever seen; there
are "else" clauses on loops and try blocks that I suspect many
programmers don't know about.)
screwy set of compound statements I've ever seen; a number of the
usual ones like else clauses on loops and try blocks I suspect most
programmers don't know aobut.)
All of the Python decompilers that I have looked at have problems
decompiling Python's control flow. In some cases we can detect an
erroneous decompilation and report that.
All of the Python decompilers I have looked at have the same
problem. In some cases we can detect an erroneous decompilation and
report that.
*Verification* is the process of decompiling bytecode, compiling with
a Python for that bytecode version, and then comparing the bytecode
@@ -163,22 +151,19 @@ python 2.3-2.4 since a lot of the goodness of early the version of the
decompiler from that era has been preserved (and Python compilation in
that era was minimal)
There is some work to do on the lower end Python versions which is
more difficult for us to handle since we don't have a Python
interpreter for versions 1.5, 1.6, and 2.0.
Later distributions average about 200 files. There is some work to do
on the lower end Python versions which is more difficult for us to
handle since we don't have a Python interpreter for versions 1.5, 1.6,
and 2.0.
In the Python 3 series, Python support is is strongest around 3.4 or
3.3 and drops off as you move further away from those versions. Python
3.6 changes things drastically by using word codes rather than byte
codes. As a result, the jump offset field in a jump instruction
argument has been reduced. This makes the `EXTENDED_ARG` instructions
are now more prevalent in jump instruction; previously they had been
rare. Perhaps to compensate for the additional `EXTENDED_ARG`
instructions, additional jump optimization has been added. So in sum
handling control flow by ad hoc means as is currently done is worse.
Also, between Python 3.5, 3.6 and 3.7 there have been major changes to the
`MAKE_FUNCTION` and `CALL_FUNCTION` instructions.
codes. That has been addressed, but then it also changes function call
opcodes and its semantics and has more problems with control flow than
3.5 has. Between Python 3.5, 3.6 and 3.7 there have been major changes
to the `MAKE_FUNCTION` and `CALL_FUNCTION` instructions. Those are
not handled yet.
Currently not all Python magic numbers are supported. Specifically in
some versions of Python, notably Python 3.6, the magic number has
@@ -190,12 +175,10 @@ handled.
We also don't handle PJOrion_ obfuscated code. For that try: PJOrion
Deobfuscator_ to unscramble the bytecode to get valid bytecode before
trying this tool. This program can't decompile Microsoft Windows EXE
files created by Py2EXE_, although we can probably decompile the code
after you extract the bytecode properly. For situations like this, you
might want to consider a decompilation service like `Crazy Compilers
<http://www.crazy-compilers.com/decompyle/>`_. Handling
pathologically long lists of expressions or statements is slow.
trying this tool.
Handling pathologically long lists of expressions or statements is
slow.
There is lots to do, so please dig in and help.
@@ -205,16 +188,14 @@ See Also
* https://github.com/zrax/pycdc : supports all versions of Python and is written in C++. Support for later Python 3 versions is a bit lacking though.
* 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.
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Includes some fixes like supporting function annotations
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Include some fixes like supporting function annotations
* The HISTORY_ file.
* `How to report a bug <https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>`_
* 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
.. _trepan: https://pypi.python.org/pypi/trepan2
.. _compiler: https://pypi.python.org/pypi/spark_parser
.. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md
.. _debuggers: https://pypi.python.org/pypi/trepan3k
.. _remake: https://bashdb.sf.net/remake
@@ -224,4 +205,3 @@ See Also
:target: https://travis-ci.org/rocky/python-uncompyle6
.. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84
.. _Deobfuscator: https://github.com/extremecoders-re/PjOrion-Deobfuscator
.. _Py2EXE: https://en.wikipedia.org/wiki/Py2exe

View File

@@ -9,7 +9,7 @@
# Things that change more often go here.
copyright = """
Copyright (C) 2015-2018 Rocky Bernstein <rb@dustyfeet.com>.
Copyright (C) 2015-2017 Rocky Bernstein <rb@dustyfeet.com>.
"""
classifiers = ['Development Status :: 5 - Production/Stable',
@@ -26,7 +26,6 @@ classifiers = ['Development Status :: 5 - Production/Stable',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Software Development :: Debuggers',
'Topic :: Software Development :: Libraries :: Python Modules',
]
@@ -40,14 +39,13 @@ entry_points = {
'pydisassemble=uncompyle6.bin.pydisassemble:main',
]}
ftp_url = None
install_requires = ['spark-parser >= 1.8.5, < 1.9.0',
'xdis >= 3.6.9, < 3.7.0', 'six']
install_requires = ['spark-parser >= 1.8.0, < 1.9.0',
'xdis >= 3.6.1, < 3.7.0']
license = 'MIT'
mailing_list = 'python-debugger@googlegroups.com'
modname = 'uncompyle6'
py_modules = None
short_desc = 'Python cross-version byte-code decompiler'
short_desc = 'Python cross-version byte-code deparser'
web = 'https://github.com/rocky/python-uncompyle6/'
# tracebacks in zip files are funky and not debuggable

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

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

@@ -13,6 +13,8 @@ if ! source ./setup-python-2.4.sh ; then
exit $?
fi
PYVERSIONS='2.7.14 2.6.9 3.3.6 3.4.2 3.5.4 3.6.3'
cd ..
for version in $PYVERSIONS; do
if ! pyenv local $version ; then

View File

@@ -2,9 +2,9 @@
**Table of Contents**
- [Get latest sources:](#get-latest-sources)
- [Change version in uncompyle6/version.py](#change-version-in-uncompyle6versionpy)
- [Change version in uncompyle6/version.py. Then:](#change-version-in-uncompyle6versionpy-then)
- [Update ChangeLog:](#update-changelog)
- [Update NEWS from ChangeLog:](#update-news-from-changelog)
- [Update NEWS from ChangeLog. Then:](#update-news-from-changelog-then)
- [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)
- [Update NEWS from master branch](#update-news-from-master-branch)
@@ -17,11 +17,11 @@
<!-- markdown-toc end -->
# Get latest sources:
git pull
$ . ./admin-tool/update-sources.sh
# Change version in uncompyle6/version.py:
# Change version in uncompyle6/version.py. Then:
$ emacs uncompyle6/version.py
$ emacs uncompyle6/version.py
$ source uncompyle6/version.py
$ echo $VERSION
$ git commit -m"Get ready for release $VERSION" .
@@ -30,9 +30,9 @@
$ make ChangeLog
# Update NEWS from ChangeLog:
# Update NEWS from ChangeLog. Then:
$ emacs NEWS
$ emacs NEWS
$ make check
$ git commit --amend .
$ git push # get CI testing going early
@@ -44,18 +44,25 @@
# Switch to python-2.4, sync that up and build that first since it creates a tarball which we don't want.
$ source admin-tools/setup-python-2.4.sh
$ git merge master
$ rm ChangeLog
# Check against older versions
# $ git merge master ?
# Update NEWS from master branch
$ git commit -m"Get ready for release $VERSION" .
# Check against all versions
$ source admin-tools/check-older-versions.sh
$ source admin-tools/check-newer-versions.sh
# Make packages and tag
$ . ./admin-tools/make-dist-older.sh
$ admin-tools/make-dist-older.sh
$ git tag release-python-2.4-$VERSION
$ . ./admin-tools/make-dist-newer.sh
$ admin-tools/make-dist-newer.sh
$ git tag release-$VERSION
# Upload single package and look at Rst Formating

View File

@@ -0,0 +1,46 @@
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

@@ -1,19 +0,0 @@
# -*- shell-script -*-
# Sets PYVERSIONS to be all pyenv versions we have
if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
olddir=$(pwd)
mydir=$(dirname ${BASH_SOURCE[0]})
cd $mydir
all=""
for file in pyenv-{olde{st,r},newer}-versions ; do
. $mydir/$file
all="$all $PYVERSIONS"
done
PYVERSIONS="$all"
cd $olddir

View File

@@ -1,8 +1,6 @@
# -*- shell-script -*-
# Sets PYVERSIONS to be pyenv versions that
# we can use in the master branch.
if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
export PYVERSIONS='3.5.3 3.6.3 2.6.9 3.3.6 2.7.14 3.4.2'
export PYVERSIONS='3.5.2 3.6.2 2.6.9 3.3.6 2.7.14 3.4.2'

View File

@@ -1,7 +1,4 @@
# -*- shell-script -*-
# Sets PYVERSIONS to be pyenv versions that
# we can use in the python-2.4 branch.
if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1

View File

@@ -1,9 +0,0 @@
# -*- shell-script -*-
# Sets PYVERSIONS to be all pyenv the oldest versions we have.
# These are not covered (yet) by uncompyle6, although
# some programs do work here.
if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
export PYVERSIONS='2.1.3 2.2.3 2.3.7'

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

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

3
admin-tools/update-sources.sh Executable file
View File

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

View File

@@ -7,8 +7,7 @@ machine:
dependencies:
override:
- pip install -e .
- pip install pytest==3.2.5 hypothesis
- pip install -r requirements-dev.txt
test:
override:
- python ./setup.py develop && make check-2.7
- cd ./test/stdlib && pyenv local 2.7.10 && bash ./runtests.sh 'test_[p-z]*.py'
- python ./setup.py develop && make check-2.6

View File

@@ -1,4 +1,3 @@
import pytest
from uncompyle6.semantics.fragments import deparse_code as deparse
from uncompyle6 import PYTHON_VERSION, PYTHON3
@@ -30,23 +29,22 @@ def list_comp():
[y for y in range(3)]
def get_parsed_for_fn(fn):
code = fn.__code__ if PYTHON3 else fn.func_code
code = fn.func_code
return deparse(PYTHON_VERSION, code)
def check_expect(expect, parsed, fn_name):
def check_expect(expect, parsed):
debug = False
i = 2
max_expect = len(expect)
for name, offset in sorted(parsed.offsets.keys()):
assert i+1 <= max_expect, (
"%s: ran out if items in testing node" % fn_name)
assert i+1 <= max_expect, "ran out if items in testing node"
nodeInfo = parsed.offsets[name, offset]
node = nodeInfo.node
extractInfo = parsed.extract_node_info(node)
assert expect[i] == extractInfo.selectedLine, \
('%s: line %s expect:\n%s\ngot:\n%s' %
(fn_name, i, expect[i], extractInfo.selectedLine))
('line %s expect:\n%s\ngot:\n%s' %
(i, expect[i], extractInfo.selectedLine))
assert expect[i+1] == extractInfo.markerLine, \
('line %s expect:\n%s\ngot:\n%s' %
(i+1, expect[i+1], extractInfo.markerLine))
@@ -75,7 +73,6 @@ def check_expect(expect, parsed, fn_name):
def test_stuff():
return
parsed = get_parsed_for_fn(map_stmts)
expect = """
-1
@@ -86,10 +83,10 @@ return (x, y)
-------------
0
x = []
-
--
Contained in...
x = []
--
------
3
x = []
-
@@ -98,10 +95,10 @@ x = []
------
6
y = {}
-
--
Contained in...
y = {}
--
------
9
y = {}
-
@@ -133,7 +130,7 @@ Contained in...
x = [] ...
------ ...
""".split("\n")
check_expect(expect, parsed, 'map_stmts')
check_expect(expect, parsed)
########################################################
# return
@@ -170,7 +167,7 @@ Contained in...
return (x, y)
-------------
""".split("\n")
check_expect(expect, parsed, 'return_stmt')
check_expect(expect, parsed)
########################################################
# # try
@@ -318,4 +315,4 @@ for i in range(2): ...
""".split("\n")
parsed = get_parsed_for_fn(for_range_stmt)
if not PYTHON3:
check_expect(expect, parsed, 'range_stmt')
check_expect(expect, parsed)

View File

@@ -11,14 +11,20 @@ src_dir = get_srcdir()
os.chdir(src_dir)
@pytest.mark.parametrize(("test_tuple"), [
('../test/bytecode_2.7/05_if.pyc', 'testdata/if-2.7.right',),
('../test/bytecode_2.7/05_ifelse.pyc', 'testdata/ifelse-2.7.right',),
@pytest.mark.parametrize(("test_tuple", "function_to_test"), [
(
('../test/bytecode_2.7/05_if.pyc', 'testdata/if-2.7.right',),
disassemble_file
),
(
('../test/bytecode_2.7/05_ifelse.pyc', 'testdata/ifelse-2.7.right',),
disassemble_file
),
])
def test_funcoutput(capfd, test_tuple):
def test_funcoutput(capfd, test_tuple, function_to_test):
in_file, filename_expected = test_tuple
disassemble_file(in_file)
in_file , filename_expected = test_tuple
function_to_test(in_file, native=False)
resout, reserr = capfd.readouterr()
expected = open(filename_expected, "r").read()
if resout != expected:

View File

@@ -10,7 +10,7 @@ else:
maxint = sys.maxint
from uncompyle6.semantics.helper import print_docstring
class PrintFake():
class PrintFake:
def __init__(self):
self.pending_newlines = 0
self.f = StringIO()

View File

@@ -22,17 +22,11 @@ def bug_loop(disassemble, tb=None):
disassemble(tb)
def test_if_in_for():
code = bug.__code__
code = bug.func_code
scan = get_scanner(PYTHON_VERSION)
print(PYTHON_VERSION)
if 2.7 <= PYTHON_VERSION <= 3.0 and not IS_PYPY:
n = scan.setup_code(code)
bytecode = Bytecode(code, scan.opc)
scan.build_lines_data(code, n)
scan.insts = list(bytecode)
scan.offset2inst_index = {}
for i, inst in enumerate(scan.insts):
scan.offset2inst_index[inst.offset] = i
scan.build_prev_op(n)
fjt = scan.find_jump_targets(False)
@@ -49,13 +43,8 @@ def test_if_in_for():
code = bug_loop.__code__
n = scan.setup_code(code)
bytecode = Bytecode(code, scan.opc)
scan.build_lines_data(code, n)
scan.insts = list(bytecode)
scan.build_prev_op(n)
scan.offset2inst_index = {}
for i, inst in enumerate(scan.insts):
scan.offset2inst_index[inst.offset] = i
fjt = scan.find_jump_targets(False)
assert{64: [42], 67: [42, 42], 42: [16, 41], 19: [6]} == fjt
assert scan.structs == [
@@ -74,9 +63,6 @@ def test_if_in_for():
scan.build_lines_data(code)
scan.build_prev_op()
scan.insts = list(bytecode)
scan.offset2inst_index = {}
for i, inst in enumerate(scan.insts):
scan.offset2inst_index[inst.offset] = i
fjt = scan.find_jump_targets(False)
assert {69: [66], 63: [18]} == fjt
assert scan.structs == \

View File

@@ -1,150 +0,0 @@
# std
import os
# test
import pytest
import hypothesis
from hypothesis import strategies as st
# uncompyle6
from uncompyle6 import PYTHON_VERSION, deparse_code
@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 at least 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 = deparse_code(PYTHON_VERSION, code, compile_mode='single')
recompiled = compile(deparsed.text, '<string>', 'single')
if recompiled != code:
assert 'dis(' + deparsed.text.strip('\n') + ')' == 'dis(' + expr.strip('\n') + ')'
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need at least 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 at least 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

@@ -1,175 +0,0 @@
# std
import string
# 3rd party
from hypothesis import given, assume, example, settings, strategies as st
import pytest
# uncompyle
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()")
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):
@given(isolated_function_calls('positional'))
@example("fn(0)")
def test_function_positional_only(expr):
validate_uncompyle(expr)
@given(isolated_function_calls('keyword'))
@example("fn(a=0)")
def test_function_call_keyword_only(expr):
validate_uncompyle(expr)
@given(isolated_function_calls('star'))
@example("fn(*items)")
def test_function_call_star_only(expr):
validate_uncompyle(expr)
@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

@@ -16,48 +16,32 @@ def test_grammar():
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
(lhs, rhs, tokens,
right_recursive, dup_rhs) = p.check_sets()
# We have custom rules that create the below
expect_lhs = set(['expr1024', 'pos_arg', 'get_iter', 'attribute'])
unused_rhs = set(['list', 'mkfunc',
expect_lhs = set(['expr1024', 'pos_arg'])
unused_rhs = set(['build_list', 'call_function', 'mkfunc',
'mklambda',
'unpack',])
expect_right_recursive = set([('designList',
('store', 'DUP_TOP', 'designList'))])
expect_right_recursive = frozenset([('designList',
('designator', 'DUP_TOP', 'designList'))])
if PYTHON3:
expect_lhs.add('load_genexpr')
expect_lhs.add('kvlist')
expect_lhs.add('kv3')
unused_rhs = unused_rhs.union(set("""
except_pop_except generator_exp classdefdeco2
dict
except_pop_except genexpr classdefdeco2 listcomp
""".split()))
if PYTHON_VERSION >= 3.0:
if 3.0 <= PYTHON_VERSION:
expect_lhs.add("annotate_arg")
expect_lhs.add("annotate_tuple")
unused_rhs.add("mkfunc_annotate")
unused_rhs.add('call')
if PYTHON_VERSION < 3.6:
# 3.6 has at least one non-custom call rule
# the others don't
unused_rhs.add('call')
if PYTHON_VERSION == 3.5:
expect_right_recursive.add((('l_stmts',
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
pass
pass
else:
expect_right_recursive.add((('l_stmts',
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
# expect_lhs.add('kwargs1')
pass
pass
pass
else:
expect_lhs.add('kwarg')
unused_rhs.add('call')
# FIXME: grammar remove_rule on
# kv3 ::= expr expr STORE_MAP
# doesn't currently work in grammar, so we have this extraneous kv3 around.
if 3.3 <= PYTHON_VERSION <= 3.4:
expect_lhs.add('kv3')
assert expect_lhs == set(lhs)
assert unused_rhs == set(rhs)

View File

@@ -1,6 +1,4 @@
import sys
from uncompyle6 import PYTHON3
from uncompyle6.scanner import get_scanner
from uncompyle6.semantics.consts import (
escape, NONE,
# RETURN_NONE, PASS, RETURN_LOCALS
@@ -8,21 +6,14 @@ 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 as SourceWalker
def test_template_engine():
s = StringIO()
sys_version = float(sys.version[0:3])
scanner = get_scanner(sys_version, is_pypy=False)
scanner.insts = []
sw = SourceWalker(2.7, s, scanner)
sw = SourceWalker(2.7, s, None)
sw.ast = NONE
sw.template_engine(('--%c--', 0), NONE)
print(sw.f.getvalue())
@@ -30,7 +21,7 @@ def test_template_engine():
# FIXME: and so on...
from uncompyle6.semantics.consts import (
TABLE_DIRECT, TABLE_R,
TABLE_R, TABLE_DIRECT,
)
from uncompyle6.semantics.fragments import (
@@ -44,7 +35,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 iteritems(t):
for k, entry in t.iteritems():
if k in skip_for_now:
continue
fmt = entry[0]

View File

@@ -1,19 +1,19 @@
import pytest
from uncompyle6 import PYTHON_VERSION, PYTHON3, deparse_code
from uncompyle6 import PYTHON_VERSION, deparse_code
def test_single_mode():
single_expressions = (
'i = 1',
'i and (j or k)',
'i += 1',
'i = j % 4',
'i = {}',
'i = []',
'for i in range(10):\n i\n',
'for i in range(10):\n for j in range(10):\n i + j\n',
'try:\n i\nexcept Exception:\n j\nelse:\n k\n'
)
if PYTHON_VERSION >= 2.5:
def test_single_mode():
single_expressions = (
'i = 1',
'i and (j or k)',
'i += 1',
'i = j % 4',
'i = {}',
'i = []',
'for i in range(10):\n i\n',
'for i in range(10):\n for j in range(10):\n i + j\n',
'try:\n i\nexcept Exception:\n j\nelse:\n k\n'
)
for expr in single_expressions:
code = compile(expr + '\n', '<string>', 'single')
assert deparse_code(PYTHON_VERSION, code, compile_mode='single').text == expr + '\n'
for expr in single_expressions:
code = compile(expr + '\n', '<string>', 'single')
assert deparse_code(PYTHON_VERSION, code, compile_mode='single').text == expr + '\n'

View File

@@ -7,6 +7,6 @@
7 6 LOAD_NAME 1 'False'
9 STORE_NAME 2 'b'
12 JUMP_FORWARD 0 'to 15'
15_0 COME_FROM 12 '12'
15_0 COME_FROM '12'
15 LOAD_CONST 0 ''
18 RETURN_VALUE

View File

@@ -10,6 +10,6 @@
6 15 LOAD_CONST 1 2
18 STORE_NAME 2 'd'
21_0 COME_FROM 12 '12'
21_0 COME_FROM '12'
21 LOAD_CONST 2 ''
24 RETURN_VALUE

View File

@@ -1,24 +1,25 @@
# future
from __future__ import print_function
# std
import os
import difflib
import subprocess
import tempfile
import functools
# compatability
import six
from StringIO import StringIO
# uncompyle6 / xdis
from uncompyle6 import PYTHON_VERSION, IS_PYPY, deparse_code
# TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there
from xdis.bytecode import Bytecode
from xdis.main import get_opcode
opc = get_opcode(PYTHON_VERSION, IS_PYPY)
Bytecode = functools.partial(Bytecode, opc=opc)
try:
import functools
Bytecode = functools.partial(Bytecode, opc=opc)
def _dis_to_text(co):
return Bytecode(co).dis()
except:
pass
def _dis_to_text(co):
return Bytecode(co).dis()
def print_diff(original, uncompyled):
@@ -42,8 +43,11 @@ def print_diff(original, uncompyled):
print('\nTo display diff highlighting run:\n pip install BeautifulSoup4')
diff = difflib.HtmlDiff().make_table(*args)
with tempfile.NamedTemporaryFile(delete=False) as f:
f = tempfile.NamedTemporaryFile(delete=False)
try:
f.write(str(diff).encode('utf-8'))
finally:
f.close()
try:
print()
@@ -60,8 +64,7 @@ def print_diff(original, uncompyled):
print('\nFor side by side diff install elinks')
diff = difflib.Differ().compare(original_lines, uncompyled_lines)
print('\n'.join(diff))
finally:
os.unlink(f.name)
os.unlink(f.name)
def are_instructions_equal(i1, i2):
@@ -123,8 +126,9 @@ def validate_uncompyle(text, mode='exec'):
original_text = text
deparsed = deparse_code(PYTHON_VERSION, original_code,
compile_mode=mode,
out=six.StringIO(),
out=StringIO(),
is_pypy=IS_PYPY)
uncompyled_text = deparsed.text
uncompyled_code = compile(uncompyled_text, '<string>', 'exec')

View File

@@ -1,3 +1,3 @@
pytest>=3.0.0
flake8
hypothesis<=3.8.3
hypothesis

View File

@@ -1,20 +1,7 @@
#!/usr/bin/env python
import sys
"""Setup script for the 'uncompyle6' distribution."""
SYS_VERSION = sys.version_info[0:2]
if not ((2, 6) <= SYS_VERSION <= (3, 7)) or ((3, 0) <= SYS_VERSION <= (3, 1)):
mess = "Python Release 2.6 .. 3.7 excluding 3.0 and 3.1 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])
elif SYS_VERSION < (2, 4) or ((3, 0) <= SYS_VERSION <= (3, 1)):
mess += ("\nThis package is not supported for Python version %s."
% sys.version[0:3])
print(mess)
raise Exception(mess)
from __pkginfo__ import \
author, author_email, install_requires, \
license, long_description, classifiers, \

View File

@@ -1,12 +1,4 @@
PHONY=check clean dist distclean test test-unit test-functional rmChangeLog clean_pyc nosetests \
check-bytecode-1.5 check-bytecode-1 check-bytecode-2 check-bytecode-3 \
check-bytecode-2.2 check-byteocde-2.3 check-bytecode-2.4 \
check-short check-2.6 check-2.7 check-3.0 check-3.1 check-3.2 check-3.3 \
check-3.4 check-3.5 check-5.6 5.6 5.8 \
grammar-coverage-2.5 grammar-coverage-2.6 grammarcoverage-2.7 \
grammar-coverage-3.1 grammar-coverage-3.2 grammarcoverage-3.3 \
grammar-coverage-3.4 grammar-coverage-3.5 grammarcoverage-3.6
PHONY=check clean dist distclean test test-unit test-functional rmChangeLog clean_pyc nosetests
GIT2CL ?= git2cl
PYTHON ?= python
@@ -28,7 +20,7 @@ check:
$(MAKE) check-$(PYTHON_VERSION)
#: Run working tests from Python 2.6 or 2.7
check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-bytecode-1 check-native-short
check-2.4 check-2.5 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
@@ -52,7 +44,7 @@ check-3.4: check-bytecode check-3.4-ok check-2.7-ok
#: Run working tests from Python 3.5
check-3.5: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.5 --weak-verify $(COMPILE)
$(PYTHON) test_pythonlib.py --bytecode-3.5 --verify $(COMPILE)
#: Run working tests from Python 3.6
check-3.6: check-bytecode
@@ -67,7 +59,8 @@ check-disasm:
$(PYTHON) dis-compare.py
#: Check deparsing bytecode 1.x only
check-bytecode-1: check-bytecode-1.5
check-bytecode-1:
$(PYTHON) test_pythonlib.py --bytecode-1.5
#: Check deparsing bytecode 2.x only
check-bytecode-2:
@@ -86,13 +79,9 @@ check-bytecode: check-bytecode-3
$(PYTHON) test_pythonlib.py \
--bytecode-2.1 --bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
--bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \
--bytecode-pypy2.7
--bytecode-pypy2.7 --bytecode-1
#: Check deparsing bytecode 1.5 only
check-bytecode-1.5:
$(PYTHON) test_pythonlib.py --bytecode-1.5
#: Check deparsing Python 2.1
check-bytecode-2.1:
$(PYTHON) test_pythonlib.py --bytecode-2.1
@@ -113,6 +102,12 @@ check-bytecode-2.4:
check-bytecode-2.5:
$(PYTHON) test_pythonlib.py --bytecode-2.5
#: Get grammar coverage for Python 2.4
grammar-coverage-2.4:
-rm $(COVER_DIR)/spark-grammar-24.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-24.cover $(PYTHON) test_pythonlib.py --bytecode-2.4
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-24.cover $(PYTHON) test_pyenvlib.py --2.4.6
#: Get grammar coverage for Python 2.5
grammar-coverage-2.5:
-rm $(COVER_DIR)/spark-grammar-25.cover
@@ -131,19 +126,6 @@ grammar-coverage-2.7:
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-27.cover $(PYTHON) test_pythonlib.py --bytecode-2.7
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-27.cover $(PYTHON) test_pyenvlib.py --2.7.13
#: Get grammar coverage for Python 3.0
grammar-coverage-3.0:
-rm $(COVER_DIR)/spark-grammar-30.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-30.cover $(PYTHON) test_pythonlib.py --bytecode-3.1
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-30.cover $(PYTHON) test_pyenvlib.py --3.0.1
#: Get grammar coverage for Python 3.1
grammar-coverage-3.1:
-rm $(COVER_DIR)/spark-grammar-31.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-31.cover $(PYTHON) test_pythonlib.py --bytecode-3.1
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-31.cover $(PYTHON) test_pyenvlib.py --3.1.5
#: Get grammar coverage for Python 3.2
grammar-coverage-3.2:
-rm $(COVER_DIR)/spark-grammar-32.cover
@@ -156,64 +138,57 @@ grammar-coverage-3.3:
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-33.cover $(PYTHON) test_pythonlib.py --bytecode-3.3
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-33.cover $(PYTHON) test_pyenvlib.py --3.3.6
#: Get grammar coverage for Python 3.4
##: Get grammar coverage for Python 3.4
grammar-coverage-3.4:
-rm $(COVER_DIR)/spark-grammar-34.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-34.cover $(PYTHON) test_pythonlib.py --bytecode-3.4
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-34.cover $(PYTHON) test_pyenvlib.py --3.4.2
#: Get grammar coverage for Python 3.5
##: Get grammar coverage for Python 3.5
grammar-coverage-3.5:
rm $(COVER_DIR)/spark-grammar-35.cover || /bin/true
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-35.cover $(PYTHON) test_pythonlib.py --bytecode-3.5
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-35.cover $(PYTHON) test_pyenvlib.py --3.5.3
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-35.cover $(PYTHON) test_pyenvlib.py --3.5.2
#: Check deparsing Python 2.6
check-bytecode-2.6:
pcheck-bytecode-2.6:
$(PYTHON) test_pythonlib.py --bytecode-2.6 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-2.6-run --verify-run
#: Check deparsing Python 2.7
check-bytecode-2.7:
$(PYTHON) test_pythonlib.py --bytecode-2.7 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-2.7-run --verify-run
#: Check deparsing Python 3.0
check-bytecode-3.0:
$(PYTHON) test_pythonlib.py --bytecode-3.0 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-3.0
#: Check deparsing Python 3.1
check-bytecode-3.1:
$(PYTHON) test_pythonlib.py --bytecode-3.1 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-3.1
#: Check deparsing Python 3.2
check-bytecode-3.2:
$(PYTHON) test_pythonlib.py --bytecode-3.2 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-3.2
#: Check deparsing Python 3.3
check-bytecode-3.3:
$(PYTHON) test_pythonlib.py --bytecode-3.3 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-3.3-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-3.3
#: Check deparsing Python 3.4
check-bytecode-3.4:
$(PYTHON) test_pythonlib.py --bytecode-3.4 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-3.4-run --verify-run
#: Check deparsing Python 3.5
check-bytecode-3.5:
$(PYTHON) test_pythonlib.py --bytecode-3.5 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-3.5-run --verify-run
#: Check deparsing Python 3.6
check-bytecode-3.6:
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify
$(PYTHON) test_pythonlib.py --bytecode-3.6-run --verify-run
$(PYTHON) test_pythonlib.py --bytecode-3.5
#: short tests for bytecodes only for this version of Python
check-native-short:
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --weak-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:
@@ -221,15 +196,15 @@ check-2.6-ok:
#: Run longer Python 2.7's lib files known to be okay
check-2.7-ok:
$(PYTHON) test_pythonlib.py --ok-2.7 --weak-verify $(COMPILE)
$(PYTHON) test_pythonlib.py --ok-2.7 --verify $(COMPILE)
#: Run longer Python 3.2's lib files known to be okay
check-3.2-ok:
$(PYTHON) test_pythonlib.py --ok-3.2 --weak-verify $(COMPILE)
$(PYTHON) test_pythonlib.py --ok-3.2 --verify $(COMPILE)
#: Run longer Python 3.4's lib files known to be okay
check-3.4-ok:
$(PYTHON) test_pythonlib.py --ok-3.4 --weak-verify $(COMPILE)
$(PYTHON) test_pythonlib.py --ok-3.4 --verify $(COMPILE)
#: PyPy of some sort. E.g. [PyPy 5.0.1 with GCC 4.8.4]
# Skip for now

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.

View File

@@ -1,5 +0,0 @@
These are byte-compiled programs compiled by Python 2.4
Furthrmore the programs here are self-checking: when decompiled and
then run again in a 2.4 interpreter, they will give an error if they
are miscompiled.

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.

View File

@@ -1,5 +0,0 @@
These are byte-compiled programs compiled by Python 2.5.
Furthrmore the programs here are self-checking: when decompiled and
then run again in a 2.5 interpreter, they will give an error if they
are miscompiled.

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.

View File

@@ -1,5 +0,0 @@
These are byte-compiled programs compiled by Python 2.6.
Furthrmore the programs here are self-checking: when decompiled and
then run again in a 2.6 interpreter, they will give an error if they
are miscompiled.

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