You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 16:59:52 +08:00
Compare commits
425 Commits
release-py
...
release-py
Author | SHA1 | Date | |
---|---|---|---|
|
df8c092212 | ||
|
3ac1e64c56 | ||
|
55d2e598db | ||
|
3c67c7b32c | ||
|
5264ffc0e5 | ||
|
c5b8531ef1 | ||
|
c787c27901 | ||
|
83fc2bf25a | ||
|
27b217a4ed | ||
|
137f3d44d6 | ||
|
88fbb691d8 | ||
|
41bfa3fc01 | ||
|
ef08677287 | ||
|
08789adbb4 | ||
|
b8b9b8463c | ||
|
7d8c17cb93 | ||
|
b6413b6e6e | ||
|
41db5b8848 | ||
|
a1b990a078 | ||
|
3d277270a4 | ||
|
a4e9410c07 | ||
|
78e8b93125 | ||
|
7daf95fcb4 | ||
|
f8d6998b22 | ||
|
7b39002476 | ||
|
e064791870 | ||
|
d756548ac3 | ||
|
0171e4d899 | ||
|
a2054fb7dd | ||
|
7c58f8b41d | ||
|
f07dcb1508 | ||
|
e3f62e4a1a | ||
|
ee3bdbc2ed | ||
|
2599b94786 | ||
|
f07c9c6dcf | ||
|
9d77b5a956 | ||
|
bbaa3e6602 | ||
|
c677c946ea | ||
|
03743fa9fc | ||
|
87063851be | ||
|
e12e278efc | ||
|
516c1a7910 | ||
|
2d628acf60 | ||
|
00b95dd72e | ||
|
2293f77841 | ||
|
212771244a | ||
|
c953701623 | ||
|
8dd953de48 | ||
|
9506412aba | ||
|
5fc33aeef5 | ||
|
53b195ede9 | ||
|
3425851dc7 | ||
|
6ecaa16cd5 | ||
|
fff0d1c988 | ||
|
987b5a2290 | ||
|
c791a45aae | ||
|
0df29f344e | ||
|
910d210e52 | ||
|
344d2d92c4 | ||
|
b719a0ee35 | ||
|
f78a3fb92e | ||
|
25329d2752 | ||
|
df4d80ff26 | ||
|
5fe8303184 | ||
|
0724dc1c0e | ||
|
5b916567fe | ||
|
260bfd176e | ||
|
13ab06ecb1 | ||
|
cfce914889 | ||
|
72e2d1a2bf | ||
|
32f3d947bb | ||
|
c90210c063 | ||
|
21a8726a47 | ||
|
710b0013c9 | ||
|
b1cdbe1656 | ||
|
34736af561 | ||
|
eafb32b9a0 | ||
|
de594ce7f2 | ||
|
ca7f267103 | ||
|
e172a8f3c0 | ||
|
f7abc69861 | ||
|
624c59cd5e | ||
|
5ae32de709 | ||
|
7b15e54b7d | ||
|
ccd007355c | ||
|
ec9d00a34d | ||
|
8e2f78ceba | ||
|
36aba02093 | ||
|
a5dd330218 | ||
|
f5c91d77d2 | ||
|
cda15026e5 | ||
|
5919be1451 | ||
|
93949e8222 | ||
|
fc0eb87620 | ||
|
5872caee54 | ||
|
0b9fca2263 | ||
|
a7005f6a77 | ||
|
28e573b73c | ||
|
ac819cd1b9 | ||
|
6d0f72f13b | ||
|
fc33a4a72d | ||
|
8b6ae46a1d | ||
|
ad822c02d8 | ||
|
03a5ad3d94 | ||
|
dad1b4780c | ||
|
edfedec65c | ||
|
dd0fe36af0 | ||
|
dfdd5c6c1c | ||
|
0744a549dd | ||
|
01b5ed2304 | ||
|
77617a05c2 | ||
|
824824b402 | ||
|
3d8eb01c4c | ||
|
41adcef8f8 | ||
|
6e19e922f8 | ||
|
860d9b21f0 | ||
|
bf5a6237d8 | ||
|
ac4d4d1da9 | ||
|
0b284f8230 | ||
|
fcdea73b4f | ||
|
6fee7fdfe3 | ||
|
34117522b2 | ||
|
4ea1416fdd | ||
|
c4bfe38ee0 | ||
|
acb4ffb758 | ||
|
11e2637eeb | ||
|
7775bdabd5 | ||
|
ff43403a05 | ||
|
278756be49 | ||
|
98312c172b | ||
|
f2eaa09e96 | ||
|
42fd38e2c0 | ||
|
3a55faf9f3 | ||
|
1fcccb2472 | ||
|
ce20060cc8 | ||
|
a9171018d4 | ||
|
0d9464bb92 | ||
|
43c3154a55 | ||
|
c81b4df8b7 | ||
|
fb695616a6 | ||
|
d03c5549a6 | ||
|
f8690da7fd | ||
|
0637dd62d7 | ||
|
3becefab1f | ||
|
8454264cfc | ||
|
071207ce48 | ||
|
dded92b85d | ||
|
05ab491d2e | ||
|
1a137780ad | ||
|
3c8f38f8a6 | ||
|
ff435227e9 | ||
|
fcdc3f67af | ||
|
299936e554 | ||
|
b5cd160ebb | ||
|
43076a2548 | ||
|
c0f1129a9d | ||
|
2e192f0467 | ||
|
9062f19a97 | ||
|
f51e40a1de | ||
|
4b4fce01f6 | ||
|
2ac8a0c0a6 | ||
|
e411024696 | ||
|
01a27e22b4 | ||
|
d56547e830 | ||
|
7553c4aed9 | ||
|
b8d9e1d25c | ||
|
593304bc43 | ||
|
bd4f2d086c | ||
|
a9ca30fe34 | ||
|
4afff131f4 | ||
|
d17440c96f | ||
|
6030730870 | ||
|
1fcfadb9c8 | ||
|
c66be4a858 | ||
|
f1a98e94da | ||
|
169e4681c3 | ||
|
c241b12308 | ||
|
fab6870710 | ||
|
2674ec893a | ||
|
3f7b5e6db3 | ||
|
3edfc1611e | ||
|
2e6f2cac27 | ||
|
b9436e4851 | ||
|
d72ee71368 | ||
|
17f5b35b1d | ||
|
b0a7452d48 | ||
|
6db5c63307 | ||
|
df2cda5b66 | ||
|
42c49945ad | ||
|
5e05e521d9 | ||
|
3c68ca6cde | ||
|
5f6f78531f | ||
|
7a052c349a | ||
|
bfac9a6260 | ||
|
dd329f9c03 | ||
|
deb5b8bc6c | ||
|
a5e3d01dd3 | ||
|
ad755b27a3 | ||
|
35aca37557 | ||
|
f98e29a3a3 | ||
|
57fe56d72e | ||
|
218e73540a | ||
|
0965e2cc96 | ||
|
79d729e9f9 | ||
|
c9eeb681b9 | ||
|
5cf4f0a82f | ||
|
9b0225db60 | ||
|
8c0959de42 | ||
|
43cea023c4 | ||
|
566ef37ecc | ||
|
b7003914c9 | ||
|
3d7b160e30 | ||
|
af38064a1b | ||
|
ccd71c857f | ||
|
b89dbb0ee7 | ||
|
a5bdc1acd0 | ||
|
c9f3838d04 | ||
|
f34c558d38 | ||
|
37b8e21c76 | ||
|
f908e8dd8e | ||
|
0c386d2c39 | ||
|
be5efe3e56 | ||
|
85d65e25ba | ||
|
340ac7407f | ||
|
a279784d8d | ||
|
84632bdc78 | ||
|
494bbbdadb | ||
|
0e54c37fab | ||
|
a94b844988 | ||
|
7548364e8e | ||
|
3a9f4f2984 | ||
|
184f480bc8 | ||
|
cddb55eb33 | ||
|
e2a6c0435d | ||
|
1823513841 | ||
|
d8a3c2708e | ||
|
d0644e08d7 | ||
|
b8f74c23f4 | ||
|
51ae8313cf | ||
|
b00c59bdd7 | ||
|
c0f0485754 | ||
|
288516d8c2 | ||
|
38f04f0073 | ||
|
2de8718de3 | ||
|
f3da5d770d | ||
|
24fb13cf23 | ||
|
a8e235de17 | ||
|
f7ff4c2d41 | ||
|
0c0a534a48 | ||
|
e116d7280c | ||
|
b7f8bee11f | ||
|
58ee49159e | ||
|
934df7b5c4 | ||
|
37108bc41c | ||
|
d18a353381 | ||
|
f1004e6445 | ||
|
2f218fe9bf | ||
|
2a13851f55 | ||
|
e26de53332 | ||
|
53beae8ee6 | ||
|
524e8c8410 | ||
|
52d1e44560 | ||
|
953cf312db | ||
|
183a406bf1 | ||
|
902941102f | ||
|
c28f2f2e56 | ||
|
f274ac0e3b | ||
|
05e1be7b61 | ||
|
ee6db130ec | ||
|
5bcfa254c6 | ||
|
95c2336a76 | ||
|
039b084e4b | ||
|
b60c05ea86 | ||
|
968e8465bc | ||
|
3a0f0557f7 | ||
|
63a43d0c93 | ||
|
9a141a3144 | ||
|
669a220762 | ||
|
1436ba7abb | ||
|
6055c5e165 | ||
|
69847dbeec | ||
|
e0ed187ea6 | ||
|
eafe048c7e | ||
|
c0e553dbb5 | ||
|
35e4e03468 | ||
|
d1917046f4 | ||
|
55f12e36b7 | ||
|
81669ad7e7 | ||
|
5b9f9319a8 | ||
|
4b0892bcb5 | ||
|
74731a9d42 | ||
|
b9dfba7400 | ||
|
9ec43de039 | ||
|
5d42fe39bb | ||
|
e9b60ddbf0 | ||
|
0e04b12ad4 | ||
|
cb2b6d9bf4 | ||
|
a28f5604ce | ||
|
55ced53ca9 | ||
|
41f5835fcf | ||
|
70b77025ac | ||
|
918d4f5808 | ||
|
024f295feb | ||
|
0bb793239b | ||
|
f82165aaa7 | ||
|
4c77170ddf | ||
|
3e4889bcd7 | ||
|
7beac3f646 | ||
|
6b6755d599 | ||
|
4a904951f4 | ||
|
124267849c | ||
|
6bffae91fa | ||
|
da6e32b08e | ||
|
9379922c89 | ||
|
6dbdaedf7a | ||
|
dea17cd7f1 | ||
|
4f0a668b7c | ||
|
6746e5167d | ||
|
b32823bb7d | ||
|
54332ddffb | ||
|
b83d6c64ed | ||
|
95268cb14e | ||
|
5df09540b5 | ||
|
5e7632c33e | ||
|
1761ba2581 | ||
|
03d1c48088 | ||
|
9dd881fae1 | ||
|
2fc3886693 | ||
|
0dfbb27af5 | ||
|
7e59987af7 | ||
|
e42e3cc230 | ||
|
0560c32093 | ||
|
3f309cebab | ||
|
1f012f7c46 | ||
|
d3a42ff992 | ||
|
d1a3d42ab8 | ||
|
05fd992c48 | ||
|
47f1d888eb | ||
|
b1e650a7bd | ||
|
491572ed2d | ||
|
717b22bd13 | ||
|
ca9c227837 | ||
|
5e1d91cb94 | ||
|
e0def48020 | ||
|
5df384bb71 | ||
|
9a2534556c | ||
|
e80b36347a | ||
|
85269dc4d8 | ||
|
01a39bf8ed | ||
|
97999c5e67 | ||
|
9e37495493 | ||
|
77b93c5f21 | ||
|
0b198ee881 | ||
|
9e0c65881d | ||
|
c796d6a799 | ||
|
4563a547bc | ||
|
9cfd7d669e | ||
|
413f5aa5a5 | ||
|
b4426931ef | ||
|
3892fb533a | ||
|
92f5981661 | ||
|
54fe07e989 | ||
|
adc9b99106 | ||
|
1392b18bd7 | ||
|
2ea7487ca7 | ||
|
d4f6cec3d0 | ||
|
9ae84092cb | ||
|
85d68a7926 | ||
|
b3359439f9 | ||
|
b1705e283d | ||
|
9be9abc682 | ||
|
c17ac696d6 | ||
|
9e2119f1a9 | ||
|
eee751e22a | ||
|
86305097d2 | ||
|
2b0fefb95f | ||
|
c8d15e7654 | ||
|
1d7a3c6444 | ||
|
e7778f83f2 | ||
|
b51039ac1e | ||
|
1a627ba207 | ||
|
f73f0ba41c | ||
|
114f979555 | ||
|
ea75bcf47e | ||
|
6c6dcab857 | ||
|
0654aed6c8 | ||
|
7b38d2f1f8 | ||
|
dfbd60231b | ||
|
8b67f2ccd0 | ||
|
3447ca0767 | ||
|
aadea7224d | ||
|
1e858efafd | ||
|
da7421da1c | ||
|
ce88a72ea1 | ||
|
96ca68a6fe | ||
|
147b6e1cfe | ||
|
7725b8e7de | ||
|
d7b12f4da1 | ||
|
62ddbe320d | ||
|
c7b9e54e59 | ||
|
a694601264 | ||
|
3003070acb | ||
|
19d6dedcf5 | ||
|
51ad3fb36e | ||
|
f017acce21 | ||
|
5bef5683e4 | ||
|
4e1467adc8 | ||
|
7cdf0abb43 | ||
|
9b336251a7 | ||
|
7844456e1e | ||
|
e06f88043f | ||
|
356ea6c770 | ||
|
8fc3fd146f | ||
|
4d58438515 | ||
|
f7bfe3f7b2 | ||
|
ce5066bddb | ||
|
c54a47b15f | ||
|
d1e02afb4b | ||
|
93f18e2449 | ||
|
f4ceb6304d | ||
|
783e62f3ca | ||
|
503039ab51 | ||
|
8393064136 | ||
|
a9635da96a | ||
|
e790cb75fd |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -18,3 +18,5 @@ __pycache__
|
||||
build
|
||||
/.venv*
|
||||
/.idea
|
||||
/.hypothesis
|
||||
./ChangeLog
|
||||
|
102
HISTORY.md
102
HISTORY.md
@@ -64,14 +64,17 @@ 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 classifed as going backwards, and
|
||||
COME FROM instructions were reintroduced. See
|
||||
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
|
||||
[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
|
||||
@@ -98,15 +101,37 @@ so. Then hamled made a few commits earler on, while Eike Siewertsen
|
||||
made a few commits later on. But mostly wibiti, and Guenther
|
||||
Starnberger got the code to where uncompyle2 was around 2012.
|
||||
|
||||
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.
|
||||
While John Aycock and Hartmut Goebel were well versed in compiler
|
||||
technology, those that have come afterwards don't seem to have been as
|
||||
facile in it. Furthermore, documentation or guidance on how the
|
||||
decompiler code worked, comparison to a conventional compiler
|
||||
pipeline, how to add new constructs, or debug grammars was weak. Some
|
||||
of the grammar tracing and error reporting was a bit weak as well.
|
||||
|
||||
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.
|
||||
|
||||
This project, `uncompyle6`, abandons that approach for various
|
||||
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.
|
||||
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.
|
||||
|
||||
`Uncompyle6` however owes its existence to the fork of `uncompyle2` by
|
||||
Myst herie (Mysterie) whose first commit picks up at
|
||||
@@ -144,25 +169,44 @@ 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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Tests for the project have been, or are being, culled from all of the
|
||||
projects mentioned.
|
||||
projects mentioned. Quite a few have been added to improve grammar
|
||||
coverage and to address the numerous bugs that have been encountered.
|
||||
|
||||
For a little bit of the history of changes to the Early-algorithm parser,
|
||||
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,
|
||||
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
|
||||
|
@@ -2,17 +2,98 @@
|
||||
|
||||
## The difficulty of the problem
|
||||
|
||||
There is no Python decompiler yet, that I know about that will
|
||||
decompyle everything. This one probably does the
|
||||
best job of *any* Python decompiler. But it is a constant work in progress: Python keeps changing, and so does its code generation.
|
||||
This decompiler is a constant work in progress: Python keeps
|
||||
changing, and so does its code generation.
|
||||
|
||||
I have found bugs in *every* Python decompiler I have tried. Even
|
||||
those where authors/maintainers claim that they have used it on
|
||||
the entire Python standard library. And I don't mean that
|
||||
the program doesn't come out with the same Python source instructions,
|
||||
but that the program is *semantically* not equivalent.
|
||||
There is no Python decompiler yet that I know about that will
|
||||
decompile everything. Overall, I think this one probably does the best
|
||||
job of *any* Python decompiler that handles such a wide range of
|
||||
versions.
|
||||
|
||||
So it is likely you'll find a mistranslation in decompiling.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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?
|
||||
|
||||
|
||||
### Do you have valid bytecode?
|
||||
|
||||
As mentioned in README.rst, this project doesn't handle obfuscated
|
||||
code. See README.rst for suggestions for how to remove some kinds of
|
||||
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`.
|
||||
|
||||
### Semantic equivalence vs. exact source code
|
||||
|
||||
Almost all versions of Python can perform some sort of code
|
||||
improvement that can't be undone. In earlier versions of Python it is
|
||||
rare; in later Python versions, it is more common.
|
||||
|
||||
If the code emitted is semantically equivalent, then this isn't a bug.
|
||||
|
||||
|
||||
For example the code might be
|
||||
|
||||
```
|
||||
if a:
|
||||
if b:
|
||||
x = 1
|
||||
```
|
||||
|
||||
and we might produce:
|
||||
|
||||
```
|
||||
if a and b:
|
||||
x = 1
|
||||
```
|
||||
|
||||
These are equivalent. Sometimes
|
||||
|
||||
```
|
||||
else:
|
||||
if ...
|
||||
|
||||
```
|
||||
|
||||
may come out as `elif`.
|
||||
|
||||
|
||||
As mentioned in the README, It is possible that Python changes what
|
||||
you write to be more efficient. For example, for:
|
||||
|
||||
|
||||
```
|
||||
if True:
|
||||
x = 5
|
||||
```
|
||||
|
||||
Python will generate code like:
|
||||
|
||||
```
|
||||
x = 5
|
||||
```
|
||||
|
||||
So just because the text isn't the same, does not
|
||||
necessarily mean there's a bug.
|
||||
|
||||
## What to send (minimum requirements)
|
||||
|
||||
@@ -21,13 +102,20 @@ The basic requirement is pretty simple:
|
||||
* Python bytecode
|
||||
* Python source text
|
||||
|
||||
Please don't put files on download services that one has to register
|
||||
for or can't get to by issuing a simple `curl` or `wget`. If you can't
|
||||
attach it to the issue, or create a github gist, then the code you are
|
||||
sending is too large.
|
||||
|
||||
Also try to narrow the bug. See below.
|
||||
|
||||
## What to send (additional helpful information)
|
||||
|
||||
Some kind folks also give the invocation they used and the output
|
||||
which usually includes an error message produced. This is helpful. I
|
||||
can figure out what OS you are running this on and what version of
|
||||
*uncomplye6* was used. Therefore, if you don't provide the input
|
||||
command and the output from that, please give:
|
||||
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
|
||||
provide the input command and the output from that, please give:
|
||||
|
||||
* _uncompyle6_ version used
|
||||
* OS that you used this on
|
||||
@@ -38,7 +126,7 @@ 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.
|
||||
|
||||
@@ -48,11 +136,18 @@ Well, you could learn. No one is born into this world knowing how to
|
||||
disassemble Python bytecode. And as Richard Feynman once said, "What
|
||||
one fool can learn, so can another."
|
||||
|
||||
If this is too difficult, or too time consuming, or not of interest to
|
||||
you, then perhaps what require is a decompilation service. [Crazy
|
||||
Compilers](http://www.crazy-compilers.com/decompyle/) offers a
|
||||
byte-code decompiler service for versions of Python up to 2.6. (If
|
||||
there are others around let me know and I'll list them here.)
|
||||
|
||||
## Narrowing the problem
|
||||
|
||||
I don't need or want the entire source code base for which one file or module
|
||||
can't be decompiled. I just need that one file or module only. If
|
||||
there are several files, file a bug report for each file.
|
||||
I don't need or want the entire source code base for the file(s) or
|
||||
module(s) can't be decompiled. I just need those file(s) or module(s).
|
||||
If there are problems in several files, file a bug report for each
|
||||
file.
|
||||
|
||||
Python modules can get quite large, and usually decompilation problems
|
||||
occur in a single function or maybe the main-line code but not any of
|
||||
@@ -66,3 +161,27 @@ properly on a neighboring version of Python. That is helpful too.
|
||||
|
||||
In sum, the more you can isolate or narrow the problem, the more
|
||||
likley the problem will be fixed and fixed sooner.
|
||||
|
||||
## Confidentiality of Bug Reports
|
||||
|
||||
When you report a bug, you are giving up confidentiality to the source
|
||||
code and the byte code. However, I would imagine that if you have
|
||||
narrowed the problem sufficiently, confidentiality of the little that
|
||||
remains would not be an issue.
|
||||
|
||||
However feel free to remove any commments, and modify variable names
|
||||
or constants in the source code.
|
||||
|
||||
## Ethics
|
||||
|
||||
I do not condone using this program for unethical or illegal purposes.
|
||||
More detestful, at least to me, is asking for help to assist you in
|
||||
something that might not legitimate.
|
||||
|
||||
Don't use the issue tracker for such solicitations. To try to stave
|
||||
off illegitimate behavior, you should note that the issue tracker, the
|
||||
code, and bugs mentioned in that are in the open: there is no
|
||||
confidentiality. You may be asked about the authorship or claimed
|
||||
ownership of the bytecode. If I think something is not quite right, I
|
||||
may label the issue questionable which may make the it easier those
|
||||
who are looking for illegal activity.
|
||||
|
18
Makefile
18
Makefile
@@ -11,7 +11,7 @@ RM ?= rm
|
||||
LINT = flake8
|
||||
|
||||
#EXTRA_DIST=ipython/ipy_trepan.py trepan
|
||||
PHONY=all check clean pytest check-long dist distclean lint flake8 test rmChangeLog clean_pyc
|
||||
PHONY=all check clean distcheck pytest check-long dist distclean lint flake8 test rmChangeLog clean_pyc
|
||||
|
||||
TEST_TYPES=check-long check-short check-2.7 check-3.4
|
||||
|
||||
@@ -36,13 +36,15 @@ check-2.7 check-3.3 check-3.4: pytest
|
||||
check-3.0 check-3.1 check-3.2 check-3.5 check-3.6:
|
||||
$(MAKE) -C test $@
|
||||
|
||||
check-3.7: pytest
|
||||
|
||||
#:Tests for Python 2.6 (doesn't have pytest)
|
||||
check-2.4 check-2.5 check-2.6:
|
||||
$(MAKE) -C test $@
|
||||
|
||||
#:PyPy 2.6.1 or PyPy 5.0.1
|
||||
#:PyPy 2.6.1 PyPy 5.0.1, or PyPy 5.8.0-beta0
|
||||
# Skip for now
|
||||
2.6 5.0 5.3:
|
||||
2.6 5.0 5.3 5.6 5.8:
|
||||
|
||||
#:PyPy pypy3-2.4.0 Python 3:
|
||||
pypy-3.2 2.4:
|
||||
@@ -58,8 +60,12 @@ clean: clean_pyc
|
||||
(cd test && $(MAKE) clean)
|
||||
|
||||
#: Create source (tarball) and wheel distribution
|
||||
dist:
|
||||
$(PYTHON) ./setup.py sdist bdist_egg
|
||||
dist: distcheck
|
||||
$(PYTHON) ./setup.py sdist bdist_wheel
|
||||
|
||||
# perform some checks on the package via setup.py
|
||||
distcheck:
|
||||
$(PYTHON) ./setup.py check
|
||||
|
||||
#: Remove .pyc files
|
||||
clean_pyc:
|
||||
@@ -87,7 +93,7 @@ bdist_egg:
|
||||
|
||||
|
||||
#: Create binary wheel distribution
|
||||
bdist_wheel:
|
||||
wheel:
|
||||
$(PYTHON) ./setup.py bdist_wheel
|
||||
|
||||
|
||||
|
83
NEWS
83
NEWS
@@ -1,4 +1,85 @@
|
||||
uncompyle6 2.11.2 2017-08-09
|
||||
uncompyle6 2.14.0 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
|
||||
and remove used grammar rules
|
||||
- Fix a number of bytecode decompile problems
|
||||
(many more remain)
|
||||
- Add stdlib/runtests.sh for even more rigourous testing
|
||||
|
||||
uncompyle6 2.13.3 2017-11-13
|
||||
|
||||
Overall: better 3.6 decompiling and some much needed code refactoring and cleanup
|
||||
|
||||
|
||||
- Start noting names in for template-action names; these are
|
||||
used to check/assert we have the right node type
|
||||
- Simplify <import_from> rule
|
||||
- Pypy 5.80-beta testing tolerance
|
||||
- Start to clean up instruction mangling phase by using 3.6-style instructions
|
||||
rather trying to parse the bytecode array. This largely been done in for versions 3.x;
|
||||
3.0 custom mangling code has been reduced;
|
||||
some 2.x conversion has been done, but more is desired. This make it possible to...
|
||||
- Handle EXTENDED_ARGS better. While relevant to all Python versions it is most noticeable in
|
||||
version 3.6+ where in switching to wordcodes the size of operands has been reduced from 2**16
|
||||
to 2**8. JUMP instruction then often need EXTENDED_ARGS.
|
||||
- Refactor find_jump_targets() with via working of of instructions rather the bytecode array.
|
||||
- use --weak-verify more and additional fuzzing on verify()
|
||||
- fragment parser now ignores errors in nested function definitions; an parameter was
|
||||
added to assist here. Ignoring errors may be okay because the fragment parser often just needs,
|
||||
well, *fragments*.
|
||||
- Distinguish RETURN_VALUE from RETURN_END_IF in exception bodies better in 3.6
|
||||
- bug in 3.x language changes: import queue va import Queue
|
||||
- reinstate some bytecode tests since decompiling has gotten better
|
||||
- Revise how to report a bug
|
||||
|
||||
uncompyle6 2.13.2 2017-10-12
|
||||
|
||||
- Re-release using a more automated approach
|
||||
|
||||
uncompyle6 2.13.1 2017-10-11
|
||||
|
||||
- Re-release because Python 2.4 source uploaded rather than 2.6-3.6
|
||||
|
||||
uncompyle6 2.13.0 2017-10-10
|
||||
|
||||
- Fixes in deparsing lambda expressions
|
||||
- Improve table-semantics descriptions
|
||||
- Document hacky customize arg count better (until we can remove it)
|
||||
- Update to use xdis 3.7.0 or greater
|
||||
|
||||
uncompyle6 2.12.0 2017-09-26
|
||||
|
||||
- Use xdis 3.6.0 or greater now
|
||||
- Small semantic table cleanups
|
||||
- Python 3.4's terms a little names better
|
||||
- Slightly more Python 3.7, but still failing a lot
|
||||
- Cross Python 2/3 compatibility with annotation arguments
|
||||
|
||||
uncompyle6 2.11.5 2017-08-31
|
||||
|
||||
- Skeletal support for Python 3.7
|
||||
|
||||
uncompyle6 2.11.4 2017-08-15
|
||||
|
||||
* scanner and parser now allow 3-part version string lookups,
|
||||
e.g. 2.7.1 We allow a float here, but if passed a string like '2.7'. or
|
||||
* unpin 3.5.1. xdis 3.5.4 has been releasd and fixes the problems we had. Use that.
|
||||
* some routnes here moved to xdis. Use the xdis version
|
||||
* README.rst: Link typo Name is trepan2 now not trepan
|
||||
* xdis-forced change adjust for COMPARE_OP "is-not" in
|
||||
semanatic routines. We need "is not".
|
||||
* Some PyPy tolerance in validate testing.
|
||||
* Some pyston tolerance
|
||||
|
||||
uncompyle6 2.11.3 2017-08-09
|
||||
|
||||
Very minor changes
|
||||
|
||||
|
108
README.rst
108
README.rst
@@ -1,10 +1,10 @@
|
||||
|buildstatus| |Supported Python Versions|
|
||||
|buildstatus|
|
||||
|
||||
uncompyle6
|
||||
==========
|
||||
|
||||
A native Python cross-version Decompiler and Fragment Decompiler.
|
||||
Follows in the tradition of decompyle, uncompyle, and uncompyle2.
|
||||
A native Python cross-version decompiler and fragment decompiler.
|
||||
The successor to decompyle, uncompyle, and uncompyle2.
|
||||
|
||||
|
||||
Introduction
|
||||
@@ -12,34 +12,53 @@ Introduction
|
||||
|
||||
*uncompyle6* translates Python bytecode back into equivalent Python
|
||||
source code. It accepts bytecodes from Python version 1.5, and 2.1 to
|
||||
3.6 or so, including PyPy bytecode and Dropbox's Python 2.5 bytecode.
|
||||
3.7 or so, including PyPy bytecode and Dropbox's Python 2.5 bytecode.
|
||||
|
||||
Why this?
|
||||
---------
|
||||
|
||||
There were a number of decompyle, uncompile, 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. It
|
||||
also addresses a number of open issues in the previous forks.
|
||||
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.
|
||||
|
||||
What makes this different from other CPython bytecode decompilers?: its
|
||||
ability to deparse just fragments and give source-code information
|
||||
around a given bytecode offset.
|
||||
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 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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
This project has the most complete support for Python 3.3 and above
|
||||
and the best all-around Python 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.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
@@ -56,11 +75,9 @@ This uses setup.py, so it follows the standard Python routine:
|
||||
|
||||
::
|
||||
|
||||
pip install -e .
|
||||
pip install -r requirements-dev.txt
|
||||
pip install -e . # set up to run from source tree
|
||||
# Or if you want to install instead
|
||||
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.
|
||||
@@ -109,14 +126,14 @@ Known Bugs/Restrictions
|
||||
-----------------------
|
||||
|
||||
The biggest known and possibly fixable (but hard) problem has to do
|
||||
with handling control flow. 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.
|
||||
with handling control flow. (Python has probably the most diverse and
|
||||
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 about.)
|
||||
|
||||
Over 98% of the decompilation of Python standard library packages in
|
||||
Python 2.7.12 verifies correctly. Over 99% of Python 2.7 and 3.3-3.5
|
||||
"weakly" verify. Python 2.6 drops down to 96% weakly verifying.
|
||||
Other versions drop off in quality too.
|
||||
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
|
||||
@@ -134,6 +151,17 @@ program by running the Python interpreter. Because the Python language
|
||||
has changed so much, for best results you should use the same Python
|
||||
Version in checking as used in the bytecode.
|
||||
|
||||
Finally, we have automated running the standard Python tests after
|
||||
first compiling and decompiling the test program. Results here are a
|
||||
bit weak (if not better than most other Python decompilers). But over
|
||||
time this will probably get better.
|
||||
|
||||
Python support is strongest in Python 2 for 2.7 and drops off as you
|
||||
get further away from that. Support is also probably pretty good for
|
||||
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)
|
||||
|
||||
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,
|
||||
@@ -144,7 +172,9 @@ In the Python 3 series, Python support is is strongest around 3.4 or
|
||||
3.6 changes things drastically by using word codes rather than byte
|
||||
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.
|
||||
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
|
||||
@@ -169,14 +199,16 @@ 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. Include some fixes like supporting function annotations
|
||||
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Includes 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/trepan
|
||||
.. _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
|
||||
@@ -184,7 +216,5 @@ See Also
|
||||
.. _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
|
||||
.. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/uncompyle6.svg
|
||||
:target: https://pypi.python.org/pypi/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
|
||||
|
@@ -39,8 +39,8 @@ entry_points = {
|
||||
'pydisassemble=uncompyle6.bin.pydisassemble:main',
|
||||
]}
|
||||
ftp_url = None
|
||||
install_requires = ['spark-parser >= 1.6.1, < 1.7.0',
|
||||
'xdis == 3.5.1, < 3.6.0']
|
||||
install_requires = ['spark-parser >= 1.8.4, < 1.9.0',
|
||||
'xdis >= 3.6.2, < 3.7.0']
|
||||
license = 'MIT'
|
||||
mailing_list = 'python-debugger@googlegroups.com'
|
||||
modname = 'uncompyle6'
|
||||
|
11
admin-tools/README.md
Normal file
11
admin-tools/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Making a release is a somewhat tedious process so I've automated it a little
|
||||
|
||||
|
||||
Here are tools that I, rocky, use to check and build a distribution.
|
||||
|
||||
They are customized to my environment:
|
||||
- I use pyenv to various Python versions installed
|
||||
- I have git repos for xdis, and spark parser at the same level as uncompyle6
|
||||
|
||||
There may be other rocky-specific things that need customization.
|
||||
how-to-make-a-release.txt has overall how I make a release
|
26
admin-tools/check-newer-versions.sh
Normal file
26
admin-tools/check-newer-versions.sh
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
function finish {
|
||||
cd $owd
|
||||
}
|
||||
|
||||
# FIXME put some of the below in a common routine
|
||||
owd=$(pwd)
|
||||
trap finish EXIT
|
||||
|
||||
cd $(dirname ${BASH_SOURCE[0]})
|
||||
if ! source ./pyenv-newer-versions ; then
|
||||
exit $?
|
||||
fi
|
||||
if ! source ./setup-master.sh ; then
|
||||
exit $?
|
||||
fi
|
||||
cd ..
|
||||
for version in $PYVERSIONS; do
|
||||
if ! pyenv local $version ; then
|
||||
exit $?
|
||||
fi
|
||||
make clean && pip install -e .
|
||||
if ! make check; then
|
||||
exit $?
|
||||
fi
|
||||
done
|
25
admin-tools/check-older-versions.sh
Normal file
25
admin-tools/check-older-versions.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
function finish {
|
||||
cd $owd
|
||||
}
|
||||
owd=$(pwd)
|
||||
trap finish EXIT
|
||||
|
||||
cd $(dirname ${BASH_SOURCE[0]})
|
||||
if ! source ./pyenv-older-versions ; then
|
||||
exit $?
|
||||
fi
|
||||
if ! source ./setup-python-2.4.sh ; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
cd ..
|
||||
for version in $PYVERSIONS; do
|
||||
if ! pyenv local $version ; then
|
||||
exit $?
|
||||
fi
|
||||
make clean && python setup.py develop
|
||||
if ! make check ; then
|
||||
exit $?
|
||||
fi
|
||||
done
|
87
admin-tools/how-to-make-a-release.md
Normal file
87
admin-tools/how-to-make-a-release.md
Normal file
@@ -0,0 +1,87 @@
|
||||
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
|
||||
**Table of Contents**
|
||||
|
||||
- [Get latest sources:](#get-latest-sources)
|
||||
- [Change version in uncompyle6/version.py](#change-version-in-uncompyle6versionpy)
|
||||
- [Update ChangeLog:](#update-changelog)
|
||||
- [Update NEWS from ChangeLog:](#update-news-from-changelog)
|
||||
- [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)
|
||||
- [Check against all versions](#check-against-all-versions)
|
||||
- [Make packages and tag](#make-packages-and-tag)
|
||||
- [Upload single package and look at Rst Formating](#upload-single-package-and-look-at-rst-formating)
|
||||
- [Upload rest of versions](#upload-rest-of-versions)
|
||||
- [Push tags:](#push-tags)
|
||||
|
||||
<!-- markdown-toc end -->
|
||||
# Get latest sources:
|
||||
|
||||
$ . ./admin-tool/update-sources.sh
|
||||
|
||||
# Change version in uncompyle6/version.py:
|
||||
|
||||
$ emacs 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:
|
||||
|
||||
$ emacs NEWS
|
||||
$ make check
|
||||
$ git commit --amend .
|
||||
$ git push # get CI testing going early
|
||||
|
||||
# Make sure pyenv is running and check newer versions
|
||||
|
||||
$ pyenv local && source admin-tools/check-newer-versions.sh
|
||||
|
||||
# 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
|
||||
$ rm ChangeLog
|
||||
|
||||
$ 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
|
||||
|
||||
# Make packages and tag
|
||||
|
||||
$ . ./admin-tools/make-dist-older.sh
|
||||
$ git tag release-python-2.4-$VERSION
|
||||
|
||||
$ . /admin-tools/make-dist-newer.sh
|
||||
$ git tag release-$VERSION
|
||||
|
||||
# Upload single package and look at Rst Formating
|
||||
|
||||
$ twine upload dist/uncompyle6-${VERSION}-py3.3.egg
|
||||
|
||||
# Upload rest of versions
|
||||
|
||||
$ twine upload dist/uncompyle6-${VERSION}*
|
||||
|
||||
# Push tags:
|
||||
|
||||
$ git push --tags
|
||||
|
||||
# Check on a VM
|
||||
|
||||
$ cd /virtual/vagrant/virtual/vagrant/ubuntu-zesty
|
||||
$ vagrant up
|
||||
$ vagrant ssh
|
||||
$ pyenv local 3.5.2
|
||||
$ pip install --upgrade uncompyle6
|
||||
$ exit
|
||||
$ vagrant halt
|
46
admin-tools/how-to-make-a-release.txt
Normal file
46
admin-tools/how-to-make-a-release.txt
Normal 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}*
|
38
admin-tools/make-dist-newer.sh
Executable file
38
admin-tools/make-dist-newer.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
PACKAGE=uncompyle6
|
||||
|
||||
# FIXME put some of the below in a common routine
|
||||
function finish {
|
||||
cd $owd
|
||||
}
|
||||
|
||||
cd $(dirname ${BASH_SOURCE[0]})
|
||||
owd=$(pwd)
|
||||
trap finish EXIT
|
||||
|
||||
if ! source ./pyenv-newer-versions ; then
|
||||
exit $?
|
||||
fi
|
||||
if ! source ./setup-master.sh ; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
cd ..
|
||||
source $PACKAGE/version.py
|
||||
echo $VERSION
|
||||
|
||||
for pyversion in $PYVERSIONS; do
|
||||
if ! pyenv local $pyversion ; then
|
||||
exit $?
|
||||
fi
|
||||
# pip bdist_egg create too-general wheels. So
|
||||
# we narrow that by moving the generated wheel.
|
||||
|
||||
# Pick out first two number of version, e.g. 3.5.1 -> 35
|
||||
first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//')
|
||||
rm -fr build
|
||||
python setup.py bdist_egg bdist_wheel
|
||||
mv -v dist/${PACKAGE}-$VERSION-{py2.py3,py$first_two}-none-any.whl
|
||||
done
|
||||
|
||||
python ./setup.py sdist
|
39
admin-tools/make-dist-older.sh
Executable file
39
admin-tools/make-dist-older.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
PACKAGE=uncompyle6
|
||||
|
||||
# FIXME put some of the below in a common routine
|
||||
function finish {
|
||||
cd $owd
|
||||
}
|
||||
owd=$(pwd)
|
||||
trap finish EXIT
|
||||
|
||||
cd $(dirname ${BASH_SOURCE[0]})
|
||||
if ! source ./pyenv-older-versions ; then
|
||||
exit $?
|
||||
fi
|
||||
if ! source ./setup-python-2.4.sh ; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
cd ..
|
||||
source $PACKAGE/version.py
|
||||
echo $VERSION
|
||||
|
||||
for pyversion in $PYVERSIONS; do
|
||||
if ! pyenv local $pyversion ; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
rm -fr build
|
||||
python setup.py bdist_egg
|
||||
done
|
||||
|
||||
# Pypi can only have one source tarball.
|
||||
# Tarballs can get created from the above setup, so make sure to remove them since we want
|
||||
# the tarball from master.
|
||||
|
||||
tarball=dist/${PACKAGE}-$VERSION-tar.gz
|
||||
if [[ -f $tarball ]]; then
|
||||
rm -v dist/${PACKAGE}-$VERSION-tar.gz
|
||||
fi
|
19
admin-tools/pyenv-all-versions
Normal file
19
admin-tools/pyenv-all-versions
Normal file
@@ -0,0 +1,19 @@
|
||||
# -*- 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
|
8
admin-tools/pyenv-newer-versions
Normal file
8
admin-tools/pyenv-newer-versions
Normal file
@@ -0,0 +1,8 @@
|
||||
# -*- 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'
|
9
admin-tools/pyenv-older-versions
Normal file
9
admin-tools/pyenv-older-versions
Normal file
@@ -0,0 +1,9 @@
|
||||
# -*- 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
|
||||
fi
|
||||
export PYVERSIONS='2.4.6 2.5.6'
|
9
admin-tools/pyenv-oldest-versions
Normal file
9
admin-tools/pyenv-oldest-versions
Normal file
@@ -0,0 +1,9 @@
|
||||
# -*- 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'
|
22
admin-tools/setup-master.sh
Normal file
22
admin-tools/setup-master.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
PYTHON_VERSION=3.6.3
|
||||
|
||||
# FIXME put some of the below in a common routine
|
||||
function finish {
|
||||
cd $owd
|
||||
}
|
||||
|
||||
export PATH=$HOME/.pyenv/bin/pyenv:$PATH
|
||||
owd=$(pwd)
|
||||
bs=${BASH_SOURCE[0]}
|
||||
if [[ $0 == $bs ]] ; then
|
||||
echo "This script should be *sourced* rather than run directly through bash"
|
||||
exit 1
|
||||
fi
|
||||
mydir=$(dirname $bs)
|
||||
fulldir=$(readlink -f $mydir)
|
||||
cd $fulldir/..
|
||||
(cd ../python-spark && git checkout master && pyenv local $PYTHON_VERSION) && git pull && \
|
||||
(cd ../python-xdis && git checkout master && pyenv local $PYTHON_VERSION) && git pull && \
|
||||
git checkout master && pyenv local $PYTHON_VERSION && git pull
|
||||
cd $owd
|
16
admin-tools/setup-python-2.4.sh
Normal file
16
admin-tools/setup-python-2.4.sh
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
PYTHON_VERSION=2.4.6
|
||||
|
||||
owd=$(pwd)
|
||||
bs=${BASH_SOURCE[0]}
|
||||
if [[ $0 == $bs ]] ; then
|
||||
echo "This script should be *sourced* rather than run directly through bash"
|
||||
exit 1
|
||||
fi
|
||||
mydir=$(dirname $bs)
|
||||
fulldir=$(readlink -f $mydir)
|
||||
cd $fulldir/..
|
||||
(cd ../python-spark && git checkout python-2.4 && pyenv local $PYTHON_VERSION) && git pull && \
|
||||
(cd ../python-xdis && git checkout python-2.4 && pyenv local $PYTHON_VERSION) && git pull && \
|
||||
git checkout python-2.4 && pyenv local $PYTHON_VERSION && git pull
|
||||
cd $owd
|
3
admin-tools/update-sources.sh
Executable file
3
admin-tools/update-sources.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd $(dirname ${BASH_SOURCE[0]})/..
|
||||
git pull
|
11
pytest/test_basic.py
Normal file
11
pytest/test_basic.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from uncompyle6.scanner import get_scanner
|
||||
from uncompyle6.parser import get_python_parser
|
||||
|
||||
def test_get_scanner():
|
||||
# See that we can retrieve a scanner using a full version number
|
||||
assert get_scanner('2.7.13')
|
||||
|
||||
|
||||
def test_get_parser():
|
||||
# See that we can retrieve a sparser using a full version number
|
||||
assert get_python_parser('2.7.13')
|
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
from uncompyle6 import PYTHON_VERSION, IS_PYPY
|
||||
from uncompyle6.scanner import get_scanner
|
||||
from xdis.bytecode import Bytecode
|
||||
from array import array
|
||||
def bug(state, slotstate):
|
||||
if state:
|
||||
@@ -28,12 +29,17 @@ def test_if_in_for():
|
||||
scan.build_lines_data(code, n)
|
||||
scan.build_prev_op(n)
|
||||
fjt = scan.find_jump_targets(False)
|
||||
assert {15: [3], 69: [66], 63: [18]} == fjt
|
||||
assert scan.structs == \
|
||||
[{'start': 0, 'end': 72, 'type': 'root'},
|
||||
{'start': 15, 'end': 66, 'type': 'if-then'},
|
||||
{'start': 31, 'end': 59, 'type': 'for-loop'},
|
||||
{'start': 62, 'end': 63, 'type': 'for-else'}]
|
||||
|
||||
## FIXME: the data below is wrong.
|
||||
## we get different results currenty as well.
|
||||
## We need to probably fix both the code
|
||||
## and the test below
|
||||
# assert {15: [3], 69: [66], 63: [18]} == fjt
|
||||
# assert scan.structs == \
|
||||
# [{'start': 0, 'end': 72, 'type': 'root'},
|
||||
# {'start': 15, 'end': 66, 'type': 'if-then'},
|
||||
# {'start': 31, 'end': 59, 'type': 'for-loop'},
|
||||
# {'start': 62, 'end': 63, 'type': 'for-else'}]
|
||||
|
||||
code = bug_loop.__code__
|
||||
n = scan.setup_code(code)
|
||||
@@ -52,9 +58,11 @@ def test_if_in_for():
|
||||
{'start': 48, 'end': 67, 'type': 'while-loop'}]
|
||||
|
||||
elif 3.2 < PYTHON_VERSION <= 3.4:
|
||||
bytecode = Bytecode(code, scan.opc)
|
||||
scan.code = array('B', code.co_code)
|
||||
scan.build_lines_data(code)
|
||||
scan.build_prev_op()
|
||||
scan.insts = list(bytecode)
|
||||
fjt = scan.find_jump_targets(False)
|
||||
assert {69: [66], 63: [18]} == fjt
|
||||
assert scan.structs == \
|
||||
|
@@ -11,41 +11,75 @@ def test_grammar():
|
||||
remain_tokens = set([re.sub('_CONT$','', 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.dumpGrammar())
|
||||
"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 = p.checkSets()
|
||||
(lhs, rhs, tokens,
|
||||
right_recursive, dup_rhs) = p.check_sets()
|
||||
expect_lhs = set(['expr1024', 'pos_arg'])
|
||||
unused_rhs = set(['build_list', 'call_function', 'mkfunc',
|
||||
unused_rhs = set(['list', 'mkfunc',
|
||||
'mklambda',
|
||||
'unpack', 'unpack_list'])
|
||||
expect_right_recursive = [['designList', ('designator', 'DUP_TOP', 'designList')]]
|
||||
'unpack',])
|
||||
expect_right_recursive = set([('designList',
|
||||
('store', '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 genexpr classdefdeco2 listcomp
|
||||
except_pop_except generator_exp classdefdeco2
|
||||
dict
|
||||
""".split()))
|
||||
if 3.0 <= PYTHON_VERSION:
|
||||
if PYTHON_VERSION >= 3.0:
|
||||
expect_lhs.add("annotate_arg")
|
||||
expect_lhs.add("annotate_tuple")
|
||||
unused_rhs.add("mkfunc_annotate")
|
||||
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'))))
|
||||
unused_rhs.add('build_map_unpack_with_call')
|
||||
unused_rhs.add('unmapexpr')
|
||||
# expect_lhs.add('kwargs1')
|
||||
pass
|
||||
pass
|
||||
pass
|
||||
else:
|
||||
expect_lhs.add('kwarg')
|
||||
unused_rhs.add('call')
|
||||
|
||||
assert expect_lhs == set(lhs)
|
||||
assert unused_rhs == set(rhs)
|
||||
assert expect_right_recursive == right_recursive
|
||||
|
||||
expect_dup_rhs = frozenset([('COME_FROM',), ('CONTINUE',), ('JUMP_ABSOLUTE',),
|
||||
('LOAD_CONST',),
|
||||
('JUMP_BACK',), ('JUMP_FORWARD',)])
|
||||
# reduced_dup_rhs = {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])
|
||||
# assert not reduced_dup_rhs, reduced_dup_rhs
|
||||
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
ignore_set = set(
|
||||
"""
|
||||
JUMP_BACK CONTINUE RETURN_END_IF
|
||||
JUMP_BACK CONTINUE
|
||||
COME_FROM COME_FROM_EXCEPT
|
||||
COME_FROM_EXCEPT_CLAUSE
|
||||
COME_FROM_LOOP COME_FROM_WITH
|
||||
COME_FROM_FINALLY ELSE
|
||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP
|
||||
LAMBDA_MARKER RETURN_LAST
|
||||
LAMBDA_MARKER
|
||||
RETURN_END_IF RETURN_END_IF_LAMBDA RETURN_VALUE_LAMBDA RETURN_LAST
|
||||
""".split())
|
||||
if 2.6 <= PYTHON_VERSION <= 2.7:
|
||||
opcode_set = set(s.opc.opname).union(ignore_set)
|
||||
|
172
pytest/test_pysource.py
Normal file
172
pytest/test_pysource.py
Normal file
@@ -0,0 +1,172 @@
|
||||
from uncompyle6 import PYTHON3
|
||||
from uncompyle6.semantics.consts import (
|
||||
escape, NONE,
|
||||
# RETURN_NONE, PASS, RETURN_LOCALS
|
||||
)
|
||||
|
||||
if PYTHON3:
|
||||
from io import StringIO
|
||||
else:
|
||||
from StringIO import StringIO
|
||||
|
||||
from uncompyle6.semantics.pysource import SourceWalker as SourceWalker
|
||||
|
||||
def test_template_engine():
|
||||
s = StringIO()
|
||||
sw = SourceWalker(2.7, s, None)
|
||||
sw.ast = NONE
|
||||
sw.template_engine(('--%c--', 0), NONE)
|
||||
print(sw.f.getvalue())
|
||||
assert sw.f.getvalue() == '--None--'
|
||||
# FIXME: and so on...
|
||||
|
||||
from uncompyle6.semantics.consts import (
|
||||
TABLE_R, TABLE_DIRECT,
|
||||
)
|
||||
|
||||
from uncompyle6.semantics.fragments import (
|
||||
TABLE_DIRECT_FRAGMENT,
|
||||
)
|
||||
|
||||
skip_for_now = "DELETE_DEREF".split()
|
||||
|
||||
def test_tables():
|
||||
for t, name, fragment in (
|
||||
(TABLE_DIRECT, 'TABLE_DIRECT', False),
|
||||
(TABLE_R, 'TABLE_R', False),
|
||||
(TABLE_DIRECT_FRAGMENT, 'TABLE_DIRECT_FRAGMENT', True)):
|
||||
for k, entry in t.iteritems():
|
||||
if k in skip_for_now:
|
||||
continue
|
||||
fmt = entry[0]
|
||||
arg = 1
|
||||
i = 0
|
||||
m = escape.search(fmt)
|
||||
print("%s[%s]" % (name, k))
|
||||
while m:
|
||||
i = m.end()
|
||||
typ = m.group('type') or '{'
|
||||
if typ in frozenset(['%', '+', '-', '|', ',', '{']):
|
||||
# No args
|
||||
pass
|
||||
elif typ in frozenset(['c', 'p', 'P', 'C', 'D']):
|
||||
# One arg - should be int or tuple of int
|
||||
if typ == 'c':
|
||||
item = entry[arg]
|
||||
if isinstance(item, tuple):
|
||||
assert isinstance(item[1], str), (
|
||||
"%s[%s][%d] kind %s is '%s' should be str but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, item[1], type(item[1]), entry)
|
||||
)
|
||||
item = item[0]
|
||||
assert isinstance(item, int), (
|
||||
"%s[%s][%d] kind %s is '%s' should be an int but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, item, type(item), entry)
|
||||
)
|
||||
elif typ in frozenset(['C', 'D']):
|
||||
tup = entry[arg]
|
||||
assert isinstance(tup, tuple), (
|
||||
"%s[%s][%d] type %s is %s should be an tuple but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
||||
)
|
||||
assert len(tup) == 3
|
||||
for j, x in enumerate(tup[:-1]):
|
||||
assert isinstance(x, int), (
|
||||
"%s[%s][%d][%d] type %s is %s should be an tuple but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, j, typ, x, type(x), entry)
|
||||
)
|
||||
assert isinstance(tup[-1], str) or tup[-1] is None, (
|
||||
"%s[%s][%d][%d] sep type %s is %s should be an string but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, j, typ, tup[-1], type(x), entry)
|
||||
)
|
||||
|
||||
elif typ == 'P':
|
||||
tup = entry[arg]
|
||||
assert isinstance(tup, tuple), (
|
||||
"%s[%s][%d] type %s is %s should be an tuple but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
||||
)
|
||||
assert len(tup) == 4
|
||||
for j, x in enumerate(tup[:-2]):
|
||||
assert isinstance(x, int), (
|
||||
"%s[%s][%d][%d] type %s is '%s' should be an tuple but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, j, typ, x, type(x), entry)
|
||||
)
|
||||
assert isinstance(tup[-2], str), (
|
||||
"%s[%s][%d][%d] sep type %s is '%s' should be an string but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, j, typ, x, type(x), entry)
|
||||
)
|
||||
assert isinstance(tup[1], int), (
|
||||
"%s[%s][%d][%d] prec type %s is '%s' should be an int but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, j, typ, x, type(x), entry)
|
||||
)
|
||||
|
||||
else:
|
||||
# Should be a tuple which contains only ints
|
||||
tup = entry[arg]
|
||||
assert isinstance(tup, tuple), (
|
||||
"%s[%s][%d] type %s is '%s' should be an tuple but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
||||
)
|
||||
assert len(tup) == 2
|
||||
for j, x in enumerate(tup):
|
||||
assert isinstance(x, int), (
|
||||
"%s[%s][%d][%d] type '%s' is '%s should be an int but is %s. Full entry: %s" %
|
||||
(name, k, arg, j, typ, x, type(x), entry)
|
||||
)
|
||||
pass
|
||||
arg += 1
|
||||
elif typ in frozenset(['r']) and fragment:
|
||||
pass
|
||||
elif typ == 'b' and fragment:
|
||||
assert isinstance(entry[arg], int), (
|
||||
"%s[%s][%d] type %s is '%s' should be an int but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
||||
)
|
||||
arg += 1
|
||||
elif typ == 'x' and fragment:
|
||||
tup = entry[arg]
|
||||
assert isinstance(tup, tuple), (
|
||||
"%s[%s][%d] type %s is '%s' should be an tuple but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
||||
)
|
||||
assert len(tup) == 2
|
||||
assert isinstance(tup[0], int), (
|
||||
"%s[%s][%d] source type %s is '%s' should be an int but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
||||
)
|
||||
assert isinstance(tup[1], tuple), (
|
||||
"%s[%s][%d] dest type %s is '%s' should be an tuple but is %s. "
|
||||
"Full entry: %s" %
|
||||
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
|
||||
)
|
||||
for j, x in enumerate(tup[1]):
|
||||
assert isinstance(x, int), (
|
||||
"%s[%s][%d][%d] type %s is %s should be an int but is %s. Full entry: %s" %
|
||||
(name, k, arg, j, typ, x, type(x), entry)
|
||||
)
|
||||
arg += 1
|
||||
pass
|
||||
else:
|
||||
assert False, (
|
||||
"%s[%s][%d] type %s is not known. Full entry: %s" %
|
||||
(name, k, arg, typ, entry)
|
||||
)
|
||||
m = escape.search(fmt, i)
|
||||
pass
|
||||
assert arg == len(entry), (
|
||||
"%s[%s] arg %d should be length of entry %d. Full entry: %s" %
|
||||
(name, k, arg, len(entry), entry))
|
@@ -126,7 +126,10 @@ def validate_uncompyle(text, mode='exec'):
|
||||
original_text = text
|
||||
|
||||
deparsed = deparse_code(PYTHON_VERSION, original_code,
|
||||
compile_mode=mode, out=StringIO())
|
||||
|
||||
compile_mode=mode,
|
||||
out=StringIO(),
|
||||
is_pypy=IS_PYPY)
|
||||
uncompyled_text = deparsed.text
|
||||
uncompyled_code = compile(uncompyled_text, '<string>', 'exec')
|
||||
|
||||
|
2
setup.py
2
setup.py
@@ -24,6 +24,6 @@ setup(
|
||||
py_modules = py_modules,
|
||||
test_suite = 'nose.collector',
|
||||
url = web,
|
||||
tests_require = ['nose>=1.0'],
|
||||
tests_require = ['nose>=1.0'],
|
||||
version = VERSION,
|
||||
zip_safe = zip_safe)
|
||||
|
55
test-unit/test_grammar.py
Normal file
55
test-unit/test_grammar.py
Normal file
@@ -0,0 +1,55 @@
|
||||
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()
|
157
test/Makefile
157
test/Makefile
@@ -1,4 +1,12 @@
|
||||
PHONY=check clean dist distclean test test-unit test-functional rmChangeLog clean_pyc nosetests
|
||||
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
|
||||
|
||||
|
||||
GIT2CL ?= git2cl
|
||||
PYTHON ?= python
|
||||
@@ -8,6 +16,7 @@ NATIVE_CHECK = check-$(PYTHON_VERSION)
|
||||
|
||||
# Set COMPILE='--compile' to force compilation before check
|
||||
COMPILE ?=
|
||||
COVER_DIR=../tmp/grammar-cover
|
||||
|
||||
# Run short tests
|
||||
check-short:
|
||||
@@ -39,23 +48,26 @@ check-3.3: check-bytecode
|
||||
|
||||
#: Run working tests from Python 3.4
|
||||
check-3.4: check-bytecode check-3.4-ok check-2.7-ok
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.4 --verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.4 --weak-verify $(COMPILE)
|
||||
|
||||
#: Run working tests from Python 3.5
|
||||
check-3.5: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.5 --verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.5 --weak-verify $(COMPILE)
|
||||
|
||||
#: Run working tests from Python 3.6
|
||||
check-3.6: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.6 --verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify $(COMPILE)
|
||||
|
||||
# FIXME
|
||||
#: this is called when running under pypy3.5-5.8.0 or pypy2-5.6.0
|
||||
5.8 5.6:
|
||||
|
||||
#: Check deparsing only, but from a different Python version
|
||||
check-disasm:
|
||||
$(PYTHON) dis-compare.py
|
||||
|
||||
#: Check deparsing bytecode 1.x only
|
||||
check-bytecode-1:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-1.5
|
||||
check-bytecode-1: check-bytecode-1.5
|
||||
|
||||
#: Check deparsing bytecode 2.x only
|
||||
check-bytecode-2:
|
||||
@@ -77,6 +89,10 @@ check-bytecode: check-bytecode-3
|
||||
--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
|
||||
@@ -97,53 +113,102 @@ check-bytecode-2.4:
|
||||
check-bytecode-2.5:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-2.5
|
||||
|
||||
#: Check deparsing Python 3.0
|
||||
check-bytecode-3.0:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.0
|
||||
|
||||
#: Check deparsing Python 3.1
|
||||
check-bytecode-3.1:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.1
|
||||
|
||||
#: Check deparsing Python 3.2
|
||||
check-bytecode-3.2:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.2
|
||||
|
||||
#: Check deparsing Python 3.3
|
||||
check-bytecode-3.3:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.3
|
||||
|
||||
#: Check deparsing Python 3.4
|
||||
check-bytecode-3.4:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.4
|
||||
|
||||
#: Check deparsing Python 3.5
|
||||
check-bytecode-3.5:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.5
|
||||
|
||||
#: Check deparsing Python 3.6
|
||||
check-bytecode-3.6:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.6
|
||||
|
||||
#: Get grammar coverage for Python 2.4
|
||||
grammar-coverage-2.4:
|
||||
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-24.cover $(PYTHON) test_pythonlib.py --bytecode-2.4
|
||||
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-24.cover $(PYTHON) test_pyenvlib.py --2.4.6
|
||||
-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:
|
||||
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-25.cover $(PYTHON) test_pythonlib.py --bytecode-2.5
|
||||
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-25.cover $(PYTHON) test_pyenvlib.py --2.5.6
|
||||
-rm $(COVER_DIR)/spark-grammar-25.cover
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-25.cover $(PYTHON) test_pythonlib.py --bytecode-2.5
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-25.cover $(PYTHON) test_pyenvlib.py --2.5.6
|
||||
|
||||
#: Get grammar coverage for Python 2.6
|
||||
grammar-coverage-2.6:
|
||||
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-26.cover $(PYTHON) test_pythonlib.py --bytecode-2.6
|
||||
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-26.cover $(PYTHON) test_pyenvlib.py --2.6.9
|
||||
-rm $(COVER_DIR)/spark-grammar-26.cover
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-26.cover $(PYTHON) test_pythonlib.py --bytecode-2.6
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-26.cover $(PYTHON) test_pyenvlib.py --2.6.9
|
||||
|
||||
#: Get grammar coverage for Python 2.7
|
||||
grammar-coverage-2.7:
|
||||
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-27.cover $(PYTHON) test_pythonlib.py --bytecode-2.7
|
||||
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-27.cover $(PYTHON) test_pyenvlib.py --2.7.13
|
||||
-rm $(COVER_DIR)/spark-grammar-27.cover
|
||||
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
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-32.cover $(PYTHON) test_pythonlib.py --bytecode-3.2
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-32.cover $(PYTHON) test_pyenvlib.py --3.2.6
|
||||
|
||||
#: Get grammar coverage for Python 3.3
|
||||
grammar-coverage-3.3:
|
||||
-rm $(COVER_DIR)/spark-grammar-33.cover
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
#: Check deparsing Python 2.6
|
||||
check-bytecode-2.6:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-2.6 --weak-verify
|
||||
|
||||
#: Check deparsing Python 2.7
|
||||
check-bytecode-2.7:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-2.7 --weak-verify
|
||||
|
||||
#: Check deparsing Python 3.0
|
||||
check-bytecode-3.0:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.0 --weak-verify
|
||||
|
||||
#: Check deparsing Python 3.1
|
||||
check-bytecode-3.1:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.1 --weak-verify
|
||||
|
||||
#: Check deparsing Python 3.2
|
||||
check-bytecode-3.2:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.2 --weak-verify
|
||||
|
||||
#: Check deparsing Python 3.3
|
||||
check-bytecode-3.3:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.3 --weak-verify
|
||||
|
||||
#: Check deparsing Python 3.4
|
||||
check-bytecode-3.4:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.4 --weak-verify
|
||||
|
||||
#: Check deparsing Python 3.5
|
||||
check-bytecode-3.5:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.5 --weak-verify
|
||||
|
||||
#: Check deparsing Python 3.6
|
||||
check-bytecode-3.6:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify
|
||||
|
||||
#: short tests for bytecodes only for this version of Python
|
||||
check-native-short:
|
||||
@@ -155,19 +220,19 @@ check-2.4-ok:
|
||||
|
||||
#: Run longer Python 2.6's lib files known to be okay
|
||||
check-2.6-ok:
|
||||
$(PYTHON) test_pythonlib.py --ok-2.6 --verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --ok-2.6 --weak-verify $(COMPILE)
|
||||
|
||||
#: Run longer Python 2.7's lib files known to be okay
|
||||
check-2.7-ok:
|
||||
$(PYTHON) test_pythonlib.py --ok-2.7 --verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --ok-2.7 --weak-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 --verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --ok-3.2 --weak-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 --verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --ok-3.4 --weak-verify $(COMPILE)
|
||||
|
||||
#: PyPy of some sort. E.g. [PyPy 5.0.1 with GCC 4.8.4]
|
||||
# Skip for now
|
||||
|
BIN
test/bytecode_2.1/00_import.pyc
Normal file
BIN
test/bytecode_2.1/00_import.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.1/02_def.pyc
Normal file
BIN
test/bytecode_2.1/02_def.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.1/10_del.pyc
Normal file
BIN
test/bytecode_2.1/10_del.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.2/01_augmented_assign.pyc
Normal file
BIN
test/bytecode_2.2/01_augmented_assign.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/01_kv.pyc
Normal file
BIN
test/bytecode_2.2/01_kv.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/02_def.pyc
Normal file
BIN
test/bytecode_2.2/02_def.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/10_del.pyc
Normal file
BIN
test/bytecode_2.2/10_del.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.4/01_augmented_assign.pyc
Normal file
BIN
test/bytecode_2.4/01_augmented_assign.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.4/02_except_as.pyc
Normal file
BIN
test/bytecode_2.4/02_except_as.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/02_unary_convert.pyc
Normal file
BIN
test/bytecode_2.4/02_unary_convert.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/03_if1.pyc
Normal file
BIN
test/bytecode_2.4/03_if1.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.5/01_augmented_assign.pyc
Normal file
BIN
test/bytecode_2.5/01_augmented_assign.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.5/01_float.pyc
Normal file
BIN
test/bytecode_2.5/01_float.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.5/01_inplace_true_divide.pyc
Normal file
BIN
test/bytecode_2.5/01_inplace_true_divide.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.5/02_true_divide.pyc
Normal file
BIN
test/bytecode_2.5/02_true_divide.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.5/02_unary_convert.pyc
Normal file
BIN
test/bytecode_2.5/02_unary_convert.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.5/03_weird26.pyc
Normal file
BIN
test/bytecode_2.5/03_weird26.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.5/05_dup_top_two.pyc
Normal file
BIN
test/bytecode_2.5/05_dup_top_two.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.5/06_setif_comprehension.pyc
Normal file
BIN
test/bytecode_2.5/06_setif_comprehension.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.5/10_del.pyc
Normal file
BIN
test/bytecode_2.5/10_del.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.6/01_augmented_assign.pyc
Normal file
BIN
test/bytecode_2.6/01_augmented_assign.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.6/02_test_exec.pyc
Normal file
BIN
test/bytecode_2.6/02_test_exec.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6/02_true_divide.pyc
Normal file
BIN
test/bytecode_2.6/02_true_divide.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6/02_while1else.pyc
Normal file
BIN
test/bytecode_2.6/02_while1else.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6/03_weird26.pyc
Normal file
BIN
test/bytecode_2.6/03_weird26.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.6/05_unicode_literals.pyc
Normal file
BIN
test/bytecode_2.6/05_unicode_literals.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7/01_augmented_assign.pyc
Normal file
BIN
test/bytecode_2.7/01_augmented_assign.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/01_float.pyc
Normal file
BIN
test/bytecode_2.7/01_float.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7/01_triple_compare.pyc
Normal file
BIN
test/bytecode_2.7/01_triple_compare.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/02_def.pyc
Normal file
BIN
test/bytecode_2.7/02_def.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/02_except_as.pyc
Normal file
BIN
test/bytecode_2.7/02_except_as.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/02_ifelse_lambda.pyc
Normal file
BIN
test/bytecode_2.7/02_ifelse_lambda.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/02_true_divide.pyc
Normal file
BIN
test/bytecode_2.7/02_true_divide.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/02_unary_convert.pyc
Normal file
BIN
test/bytecode_2.7/02_unary_convert.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7/03_weird26.pyc
Normal file
BIN
test/bytecode_2.7/03_weird26.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7/05_unicode_literals.pyc
Normal file
BIN
test/bytecode_2.7/05_unicode_literals.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7/10_del.pyc
Normal file
BIN
test/bytecode_2.7/10_del.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/10_lambda.pyc
Normal file
BIN
test/bytecode_2.7/10_lambda.pyc
Normal file
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
Reference in New Issue
Block a user