You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
Compare commits
408 Commits
release-2.
...
release-2.
Author | SHA1 | Date | |
---|---|---|---|
|
e4cc126b38 | ||
|
da458bdce7 | ||
|
f47aecae9f | ||
|
ddc5460030 | ||
|
835c4151c3 | ||
|
1087613a27 | ||
|
a67891c563 | ||
|
31413be7a1 | ||
|
98a6f47ad6 | ||
|
2e3e6658ee | ||
|
85c562cb36 | ||
|
5ab3e52c9c | ||
|
004ce5c491 | ||
|
599ceddd08 | ||
|
6547d0230f | ||
|
a65443ee02 | ||
|
2bd850f297 | ||
|
90477edf04 | ||
|
c912d16b50 | ||
|
8dd405a5ee | ||
|
116a22a425 | ||
|
7d771b9a8c | ||
|
a1972bbc08 | ||
|
8a91081535 | ||
|
0958dc889d | ||
|
33a0c75b69 | ||
|
7ccbd419c6 | ||
|
a45ee15cf2 | ||
|
fb5ad76c4e | ||
|
d8598f61e4 | ||
|
5f52cce24d | ||
|
70463e036a | ||
|
7fba24198f | ||
|
e06a90ed27 | ||
|
d030a04c1a | ||
|
37d5a05241 | ||
|
5d27832d6f | ||
|
6b98432082 | ||
|
109e813058 | ||
|
4b8cb11d77 | ||
|
c77e9cdaf8 | ||
|
4c2f0df3dc | ||
|
b49d30266f | ||
|
65a16327ce | ||
|
fff09db66e | ||
|
3ef0325cb8 | ||
|
3a6f9d8f24 | ||
|
d14865c1be | ||
|
152935ab26 | ||
|
5c9c0228ee | ||
|
ac121076e6 | ||
|
04ae94ee9e | ||
|
e8ed17967c | ||
|
3f7c4209d9 | ||
|
f33f425692 | ||
|
5ffd9b2be7 | ||
|
87dc5ad80c | ||
|
177a422b87 | ||
|
3a78332d59 | ||
|
5e801b5d74 | ||
|
2523b340cd | ||
|
c3f6fa32db | ||
|
6dc9d3ab2f | ||
|
74f440bd0b | ||
|
affc504418 | ||
|
ecbbc7dfea | ||
|
6c5bd6289f | ||
|
9f0b0809b1 | ||
|
f0a8505887 | ||
|
04cc80b0d6 | ||
|
281f429223 | ||
|
8cfecff9c4 | ||
|
116b6eb468 | ||
|
2509d212e5 | ||
|
96b83c3d85 | ||
|
a3e10db8dc | ||
|
7e1aa6a34d | ||
|
476eb50868 | ||
|
285444e19a | ||
|
aed4d23c34 | ||
|
1c50e34c30 | ||
|
1be53ca729 | ||
|
808e468e5e | ||
|
936b213cec | ||
|
21683719e1 | ||
|
9754d27597 | ||
|
7e8173b076 | ||
|
ca9888ace4 | ||
|
070b7dab7b | ||
|
44d95e40e6 | ||
|
f6f3ad362b | ||
|
21377f3b43 | ||
|
a5f45f232d | ||
|
7c4316d4fb | ||
|
d1ef0bf21b | ||
|
063e517a7c | ||
|
4a3a62d01b | ||
|
ea733c31d7 | ||
|
63ec3f934a | ||
|
7c261d8495 | ||
|
942b15e3c6 | ||
|
69e65463b7 | ||
|
cd8cbf9200 | ||
|
accc959b71 | ||
|
0ee52aeeef | ||
|
c9d1f72424 | ||
|
29990c8da0 | ||
|
4e6e38358d | ||
|
fb870ccd8d | ||
|
7b7a9fa4cf | ||
|
1e25ffa879 | ||
|
7cc55f0c5f | ||
|
723ba1365f | ||
|
6a125d49d8 | ||
|
fd0d8d2567 | ||
|
772c67fcd7 | ||
|
bc86b73cf0 | ||
|
b99f196d18 | ||
|
78f24f9c66 | ||
|
55b269f744 | ||
|
8e0413273b | ||
|
c10b9babbe | ||
|
9fdf70f68d | ||
|
f571f6dfce | ||
|
59ba8a65cd | ||
|
9c2f48ca4a | ||
|
44dba42a40 | ||
|
af62286357 | ||
|
3cd3f7ccdf | ||
|
52b71bb01a | ||
|
c098b834fa | ||
|
15bb9e3823 | ||
|
21da5e787e | ||
|
b44c566a9f | ||
|
65b9ecee31 | ||
|
047c95a1e5 | ||
|
5f9f8f4d79 | ||
|
ac45e5757c | ||
|
e40d5d3897 | ||
|
ae78e9f930 | ||
|
0075c8a5f7 | ||
|
d6b35d57e4 | ||
|
11eddb7940 | ||
|
ec66dc0639 | ||
|
e31f829a56 | ||
|
61535a010d | ||
|
62e60817f6 | ||
|
7fdb4d3e68 | ||
|
e020f8f9a9 | ||
|
b640d42113 | ||
|
1a2aa41f7d | ||
|
170244181f | ||
|
6f5dce342f | ||
|
f3696cc3f1 | ||
|
13ae869267 | ||
|
663e724788 | ||
|
06023c247d | ||
|
21314c1dad | ||
|
0b6108801d | ||
|
42f26c3ffd | ||
|
8b305f78f4 | ||
|
72c781258f | ||
|
f865ecaa58 | ||
|
14b4f8e2da | ||
|
aa65b098a4 | ||
|
a1dab0fa3a | ||
|
0adf70b4d9 | ||
|
694e1edd00 | ||
|
a34f1fcd7a | ||
|
04698f45cc | ||
|
974b11ff55 | ||
|
4d9d659cfa | ||
|
bec1524c5a | ||
|
12d22c055f | ||
|
4dff02b19c | ||
|
71822bf9b3 | ||
|
fa6ae76a64 | ||
|
44c03ff7c7 | ||
|
261c60efd9 | ||
|
d87b5fe34c | ||
|
bd5b2be8fa | ||
|
73a043830c | ||
|
da9aeecc60 | ||
|
7772243ac7 | ||
|
f573013501 | ||
|
4b0b7f76dc | ||
|
d7f7748000 | ||
|
5b2198a4a6 | ||
|
1ce1cf87a4 | ||
|
32ca0c4482 | ||
|
0af3dd28bc | ||
|
36432c7488 | ||
|
74c6b38fd8 | ||
|
ae980e4f64 | ||
|
21216b4eb1 | ||
|
40d4348757 | ||
|
622f83970b | ||
|
460ad129cc | ||
|
fa84f4277a | ||
|
fa7d8f955a | ||
|
fe8000e02a | ||
|
4fa68b8894 | ||
|
36b7521597 | ||
|
f474ea648b | ||
|
7a4e3a05ff | ||
|
982a6010a1 | ||
|
c9fd86e38e | ||
|
9a251b239e | ||
|
1563e16f9f | ||
|
e2917590fc | ||
|
493ffa62fe | ||
|
9a2369830d | ||
|
f999e6a33a | ||
|
126af429fb | ||
|
480e6a125f | ||
|
faa630902d | ||
|
f576853f19 | ||
|
dc88bcf69f | ||
|
c77e4a9dc9 | ||
|
75592795b3 | ||
|
649da8fbc0 | ||
|
cdb02fa591 | ||
|
051ed90185 | ||
|
1a83c849dc | ||
|
a6fbe4c636 | ||
|
f215888374 | ||
|
24d4cfb150 | ||
|
59780483a8 | ||
|
80cfe62f36 | ||
|
8c374904f5 | ||
|
078f15013e | ||
|
efb4012087 | ||
|
8b50dda9ef | ||
|
bd809dc08b | ||
|
109d99bc62 | ||
|
5c268ee2a6 | ||
|
520290898b | ||
|
f8ccb8065e | ||
|
5d86a4e536 | ||
|
ff014a8393 | ||
|
2c22e86562 | ||
|
305002e910 | ||
|
8943167e96 | ||
|
90e504e806 | ||
|
10b95cd9a8 | ||
|
a0834890fa | ||
|
d7b79c2b59 | ||
|
73df5f3737 | ||
|
724faf9a3a | ||
|
c4912be570 | ||
|
fe56ca96c2 | ||
|
e9c8c11071 | ||
|
bdfe14069c | ||
|
70d4841a6a | ||
|
8b1250dcc8 | ||
|
4f8714ff4c | ||
|
cf4fb3c252 | ||
|
d4006abf15 | ||
|
bdd8a9f2a0 | ||
|
ebcb1d08f4 | ||
|
eefbc40eef | ||
|
6bdddb6a58 | ||
|
3da4c9ce77 | ||
|
167f5af5e6 | ||
|
3bd41b68ec | ||
|
92f20f489f | ||
|
e368ab282c | ||
|
5f6314d757 | ||
|
a9809e332b | ||
|
b3182e804d | ||
|
52731bb5cd | ||
|
e3ef9c1724 | ||
|
70c6ee946c | ||
|
20768266b4 | ||
|
3e5876dd03 | ||
|
07d49d0f5b | ||
|
08790ab0ab | ||
|
69bb74c86e | ||
|
ead41d7a96 | ||
|
bb2e9c0d31 | ||
|
58fd0f7fe5 | ||
|
cd7ccdc872 | ||
|
b60f62d529 | ||
|
e70e7bfc16 | ||
|
90741148ad | ||
|
a984ae4f6a | ||
|
fca233419f | ||
|
bebd85f5e1 | ||
|
0a64c478c3 | ||
|
949b9b504e | ||
|
b18b3e5d47 | ||
|
64191aa2d3 | ||
|
8e2c6aaa96 | ||
|
4398b5b2e0 | ||
|
eebe8249a8 | ||
|
b6a0c5a704 | ||
|
450d103760 | ||
|
ebee84228b | ||
|
79593d6ef1 | ||
|
79f4893cd9 | ||
|
544cb334e8 | ||
|
fd9ecdecc7 | ||
|
bec66bfb44 | ||
|
913decaaec | ||
|
b6e7f365c5 | ||
|
09f6286bec | ||
|
95bc1a76cb | ||
|
207edbd53d | ||
|
68ff878b3e | ||
|
f834b46b84 | ||
|
6956e88e0e | ||
|
1121ff2456 | ||
|
fbcdc7a181 | ||
|
06edeeeb46 | ||
|
b629a0c5df | ||
|
a08ece371e | ||
|
d42f84a59c | ||
|
a3dd61c981 | ||
|
9462e33f48 | ||
|
f69c76c351 | ||
|
09bf364d89 | ||
|
3d261a38c7 | ||
|
bb384bc0b3 | ||
|
09a01dc783 | ||
|
73d784510a | ||
|
bdd7df6040 | ||
|
134b67d952 | ||
|
ebfe5e3ba8 | ||
|
b5eaa9445d | ||
|
007328b353 | ||
|
6be6632e96 | ||
|
2c121545f0 | ||
|
bb31629c35 | ||
|
56dc270145 | ||
|
4cba5a28ef | ||
|
e79cecbb71 | ||
|
38a5180e02 | ||
|
2fdcdcb154 | ||
|
b9692c9b1f | ||
|
b16a166d84 | ||
|
4da2b8e2ed | ||
|
1d9ab4e1d1 | ||
|
51df8d8cbe | ||
|
b69001ccbf | ||
|
8c560a4791 | ||
|
931eb4a7e5 | ||
|
2db380a77f | ||
|
de0ec195b7 | ||
|
e0eba6998f | ||
|
e1a2860013 | ||
|
cce40bef21 | ||
|
ca10f5652f | ||
|
05898dc7cb | ||
|
37406557bc | ||
|
7929e4b57d | ||
|
5babde61c4 | ||
|
6f6f1db576 | ||
|
8d51456f59 | ||
|
a6320359c8 | ||
|
631d7be921 | ||
|
1e22734b6b | ||
|
b134d08e91 | ||
|
8a66fd0be3 | ||
|
9ae45b363f | ||
|
b287a305ea | ||
|
d823dfb5d3 | ||
|
378cca27da | ||
|
f9dc797aa0 | ||
|
8b9e0eca42 | ||
|
41f9e9e53e | ||
|
1179dc72da | ||
|
e63bcd54e9 | ||
|
73461d323e | ||
|
e37b197db9 | ||
|
196495c40e | ||
|
dddb486d78 | ||
|
ce2ae463c4 | ||
|
739ce7b1fd | ||
|
b11f6d94f7 | ||
|
debb46b0fe | ||
|
400153ea53 | ||
|
a65a8bb68e | ||
|
4a79082872 | ||
|
61c4a711a2 | ||
|
406df297df | ||
|
36ffd4c31f | ||
|
039c115679 | ||
|
15b2a742e9 | ||
|
163dfd888d | ||
|
408ba8c564 | ||
|
c58481a9eb | ||
|
845a4a2003 | ||
|
469cadd5c9 | ||
|
4377354cf9 | ||
|
6caa2c12fa | ||
|
3153a955d4 | ||
|
6f3a88d7e2 | ||
|
109737cbef | ||
|
05733c6171 | ||
|
6765a2ea97 | ||
|
c85496a92d | ||
|
e4ba73adfb | ||
|
7bf93980ce | ||
|
8241a5e3a8 | ||
|
faac11ad8c | ||
|
fe04b97c6b | ||
|
62f6220082 | ||
|
11e6eff427 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,7 @@
|
|||||||
|
*.pyc
|
||||||
*_dis
|
*_dis
|
||||||
*~
|
*~
|
||||||
|
*.pyc
|
||||||
/.cache
|
/.cache
|
||||||
/.eggs
|
/.eggs
|
||||||
/.python-version
|
/.python-version
|
||||||
@@ -8,6 +10,7 @@
|
|||||||
/__pkginfo__.pyc
|
/__pkginfo__.pyc
|
||||||
/dist
|
/dist
|
||||||
/how-to-make-a-release.txt
|
/how-to-make-a-release.txt
|
||||||
|
/nose-*.egg
|
||||||
/tmp
|
/tmp
|
||||||
/uncompyle6.egg-info
|
/uncompyle6.egg-info
|
||||||
__pycache__
|
__pycache__
|
||||||
|
11
.travis.yml
11
.travis.yml
@@ -3,10 +3,10 @@ language: python
|
|||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
python:
|
python:
|
||||||
- '2.6'
|
|
||||||
- '2.7'
|
|
||||||
- '3.4'
|
|
||||||
- '3.5'
|
- '3.5'
|
||||||
|
- '2.7.11'
|
||||||
|
- '2.6'
|
||||||
|
- '3.4'
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install -r requirements.txt
|
- pip install -r requirements.txt
|
||||||
@@ -14,3 +14,8 @@ install:
|
|||||||
|
|
||||||
script:
|
script:
|
||||||
- python ./setup.py develop && COMPILE='--compile' make check
|
- python ./setup.py develop && COMPILE='--compile' make check
|
||||||
|
|
||||||
|
# blacklist
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- data-driven-pytest
|
||||||
|
76
DECOMPYLE-2.4-CHANGELOG.txt
Normal file
76
DECOMPYLE-2.4-CHANGELOG.txt
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
This is the changelog from *decompyle*'s release 2.4 passed on by Dan Pascu
|
||||||
|
|
||||||
|
|
||||||
|
release 2.4 (Dan Pascu)
|
||||||
|
- Replaced the way code structures are identified by the parser.
|
||||||
|
Previously, the scanner introduced some COME_FROM entries in the
|
||||||
|
dissasembly output to mark all the destinations of jump instructions.
|
||||||
|
Using these COME_FROM labels the parser was then able to identify the
|
||||||
|
code structures (if tests, while loops, etc). Up to python-2.3 this was
|
||||||
|
possible because the code structures were clearly defined and jump
|
||||||
|
targets were always to the same points in a given strcuture making it
|
||||||
|
easy to identify the structure. Python 2.3 however introduced optimized
|
||||||
|
jumps to increase code performance. In the previous version of decompyle
|
||||||
|
(2.3) we used a technique to identify the code structures and then used
|
||||||
|
these structures to determine where the jump targets would have been if
|
||||||
|
not optimized. Using this information we then added COME_FROM labels at
|
||||||
|
the points where they would have been if not optimized, thus emulating
|
||||||
|
the way decompyle worked with versions before python 2.3. However with
|
||||||
|
the introduction of even more optimizations in python 2.4 this technique
|
||||||
|
no longer works. Not only the jump targets are no longer an effective
|
||||||
|
mean for the parser to identify the code structures, but also trying to
|
||||||
|
emulate the old way things were solved when it clearly no longer works
|
||||||
|
is not the right solution. To solve this issue, the code to identify the
|
||||||
|
structures that we had developed in version 2.3, was used to add real
|
||||||
|
start/end points for strcuture identification, instead of the COME_FROM
|
||||||
|
labels. Now these new start/end labels are used by the parser to more
|
||||||
|
precisely identify the structures and the COME_FROM labels were removed
|
||||||
|
completely. The scanner is responsible to identify these code structures
|
||||||
|
and use any knowledge of optimizations that python applies to determine
|
||||||
|
the start/end points of any structure and then mark them with certain
|
||||||
|
keywords that are understood by the parser.
|
||||||
|
- Correctly identify certain `while 1' structures that were not
|
||||||
|
recognized in the previous version.
|
||||||
|
- Added support for new byte code constructs used by python 2.4
|
||||||
|
|
||||||
|
release 2.3.2
|
||||||
|
- tidied up copyright and changelog information for releases 2.3 and later
|
||||||
|
|
||||||
|
release 2.3.1 (Dan Pascu)
|
||||||
|
- implemented a structure detection technique that fixes problems with
|
||||||
|
optimised jumps in Python >= 2.3. In the previous release (decompyle 2.3),
|
||||||
|
these problems meant that some files were incorrectly decompiled and
|
||||||
|
others could not be decompiled at all. With this new structure detection
|
||||||
|
technique, thorough testing over the standard python libraries suggests
|
||||||
|
that decompyle 2.3.1 can handle everything that decompyle 2.2beta1 could,
|
||||||
|
plus new Python 2.3 bytecodes and constructs.
|
||||||
|
|
||||||
|
release 2.3 (Dan Pascu)
|
||||||
|
- support for Python 2.3 added
|
||||||
|
- use the marshal and disassembly code from their respective python
|
||||||
|
versions, so that decompyle can manipulate bytecode independently
|
||||||
|
of the interpreter that runs decompyle itself (for example it can
|
||||||
|
decompile python2.3 bytecode even when running under python2.2)
|
||||||
|
|
||||||
|
——————————————————
|
||||||
|
|
||||||
|
release 2.2beta1 (hartmut Goebel)
|
||||||
|
- support for Python 1.5 up to Python 2.2
|
||||||
|
- no longer requires to be run with the Python interpreter version
|
||||||
|
which generated the byte-code.
|
||||||
|
- requires Python 2.2
|
||||||
|
- pretty-prints docstrings, hashes, lists and tuples
|
||||||
|
- decompyle is now a script and a package
|
||||||
|
- added emacs mode-hint and tab-width for each file output
|
||||||
|
- enhanced test suite: more test patterns, .pyc/.pyo included
|
||||||
|
- avoids unnecessary 'global' statements
|
||||||
|
- still untested: EXTENDED_ARG
|
||||||
|
|
||||||
|
internal changes:
|
||||||
|
- major code overhoul: splitted into several modules, clean-ups
|
||||||
|
- use a list of valid magics instead of the single one from imp.py
|
||||||
|
- uses copies of 'dis.py' for every supported version. This ensures
|
||||||
|
correct disassemling of the byte-code.
|
||||||
|
- use a single Walker and a single Parser, thus saving time and memory
|
||||||
|
- use augmented assign and 'print >>' internally
|
||||||
|
- optimized 'Walker.engine', the main part of code generation
|
93
HISTORY.md
93
HISTORY.md
@@ -4,7 +4,8 @@ There have been a number of people who have worked on this. I am awed
|
|||||||
by the amount of work, number of people who have contributed to this,
|
by the amount of work, number of people who have contributed to this,
|
||||||
and the cleverness in the code.
|
and the cleverness in the code.
|
||||||
|
|
||||||
The below is an annotated history from my reading of the sources cited.
|
The below is an annotated history from talking to participants
|
||||||
|
involved and my reading of the code and sources cited.
|
||||||
|
|
||||||
In 1998, John Aycock first wrote a grammar parser in Python,
|
In 1998, John Aycock first wrote a grammar parser in Python,
|
||||||
eventually called SPARK, that was usable inside a Python program. This
|
eventually called SPARK, that was usable inside a Python program. This
|
||||||
@@ -23,8 +24,10 @@ working on his thesis, John realized SPARK could be used to deparse
|
|||||||
Python bytecode. In the fall of 1999, he started writing the Python
|
Python bytecode. In the fall of 1999, he started writing the Python
|
||||||
program, "decompyle", to do this.
|
program, "decompyle", to do this.
|
||||||
|
|
||||||
This code introduced another clever idea: using table-driven
|
To help with control structure deparsing the instruction sequence was
|
||||||
semantics routines, using format specifiers.
|
augmented with pseudo instruction COME_FROM. This code introduced
|
||||||
|
another clever idea: using table-driven semantics routines, using
|
||||||
|
format specifiers.
|
||||||
|
|
||||||
The last mention of a release of SPARK from John is around 2002.
|
The last mention of a release of SPARK from John is around 2002.
|
||||||
|
|
||||||
@@ -36,7 +39,7 @@ first subsequent public release announcement that I can find is
|
|||||||
From the CHANGES file found in
|
From the CHANGES file found in
|
||||||
[the tarball for that release](http://old-releases.ubuntu.com/ubuntu/pool/universe/d/decompyle2.2/decompyle2.2_2.2beta1.orig.tar.gz),
|
[the tarball for that release](http://old-releases.ubuntu.com/ubuntu/pool/universe/d/decompyle2.2/decompyle2.2_2.2beta1.orig.tar.gz),
|
||||||
it appears that Hartmut did most of the work to get this code to
|
it appears that Hartmut did most of the work to get this code to
|
||||||
accept the full Python language. He added precidence to the table
|
accept the full Python language. He added precedence to the table
|
||||||
specifiers, support for multiple versions of Python, the
|
specifiers, support for multiple versions of Python, the
|
||||||
pretty-printing of docstrings, lists, and hashes. He also wrote test and verification routines of
|
pretty-printing of docstrings, lists, and hashes. He also wrote test and verification routines of
|
||||||
deparsed bytecode, and used this in an extensive set of tests that he also wrote. He could verify against the entire Python library.
|
deparsed bytecode, and used this in an extensive set of tests that he also wrote. He could verify against the entire Python library.
|
||||||
@@ -55,27 +58,61 @@ it doesn't look like he's done anything compiler-wise since SPARK). So
|
|||||||
I hope people will use the crazy-compilers service. I wish them the
|
I hope people will use the crazy-compilers service. I wish them the
|
||||||
success that his good work deserves.
|
success that his good work deserves.
|
||||||
|
|
||||||
Next we get to
|
Dan Pascu did a bit of work from late 2004 to early 2006 to get this
|
||||||
["uncompyle" and PyPI](https://pypi.python.org/pypi/uncompyle/1.1) and
|
code to handle first Python 2.3 and then 2.4 bytecodes. Because of
|
||||||
the era of git repositories. In contrast to decompyle, this now runs
|
jump optimization introduced in the CPython bytecode compiler at that
|
||||||
only on Python 2.7 although it accepts bytecode back to Python
|
time, various JUMP instructions were classifed as going backwards, and
|
||||||
|
COME FROM instructions were reintroduced. See
|
||||||
|
RELEASE-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.
|
||||||
|
|
||||||
|
Next we get to ["uncompyle" and
|
||||||
|
PyPI](https://pypi.python.org/pypi/uncompyle/1.1) and the era of
|
||||||
|
public version control. (Dan's code although not public used
|
||||||
|
[darcs](http://darcs.net/) for version control.)
|
||||||
|
|
||||||
|
In contrast to _decompyle_, _uncompyle_ at least in its final versions,
|
||||||
|
runs only on Python 2.7. However it accepts bytecode back to Python
|
||||||
2.5. Thomas Grainger is the package owner of this, although Hartmut is
|
2.5. Thomas Grainger is the package owner of this, although Hartmut is
|
||||||
listed as the author.
|
still listed as the author.
|
||||||
|
|
||||||
The project exists not only on
|
The project exists not only on
|
||||||
[github](https://github.com/gstarnberger/uncompyle) but also on
|
[github](https://github.com/gstarnberger/uncompyle) but also on
|
||||||
[bitbucket](https://bitbucket.org/gstarnberger/uncompyle) where the
|
[bitbucket](https://bitbucket.org/gstarnberger/uncompyle) and later
|
||||||
git history goes back to 2009. Somewhere in there the name was changed
|
the defunct [google
|
||||||
from "decompyle" to "uncompyle".
|
code](https://code.google.com/archive/p/unpyc/). The git/svn history
|
||||||
|
goes back to 2009. Somewhere in there the name was changed from
|
||||||
|
"decompyle" to "unpyc" by Keknehv, and then to "uncompyle" by Guenther Starnberger.
|
||||||
|
|
||||||
The name Thomas Grainger isn't found in (m)any of the commits in the
|
The name Thomas Grainger isn't found in (m)any of the commits in the
|
||||||
several years of active development. Guenther Starnberger, Keknehv,
|
several years of active development. First Keknehv worked on this up
|
||||||
hamled, and Eike Siewertsen are principle committers here.
|
to Python 2.5 or so while acceping Python bytecode back to 2.0 or
|
||||||
|
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.
|
||||||
|
|
||||||
This project, uncompyle6, however owes its existence to uncompyle2 by
|
In uncompyle2 decompilation of python bytecode 2.5 & 2.6 is done by
|
||||||
Myst herie (Mysterie) whose first commit seems to goes back to 2012;
|
transforming the byte code into a a pseudo 2.7 python bytecode and is
|
||||||
it is also based on Hartmut's code. I chose this as it seems had been
|
based on code from Eloi Vanderbeken.
|
||||||
the most actively worked on most recently.
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Uncompyle6, however owes its existence to the fork of uncompyle2 by
|
||||||
|
Myst herie (Mysterie) whose first commit picks up at
|
||||||
|
2012. I chose this since it seemed to have been at that time the most
|
||||||
|
actively, if briefly, worked on. Also starting around 2012 is Dark
|
||||||
|
Fenx's uncompyle3 which I used for inspiration for Python3 support.
|
||||||
|
|
||||||
|
I started working on this late 2015, mostly to add fragment support.
|
||||||
|
In that, I decided to make this runnable on Python 3.2+ and Python 2.6+
|
||||||
|
while, handling Python bytecodes from Python versions 2.5+ and
|
||||||
|
3.2+.
|
||||||
|
|
||||||
Over the many years, code styles and Python features have
|
Over the many years, code styles and Python features have
|
||||||
changed. However brilliant the code was and still is, it hasn't really
|
changed. However brilliant the code was and still is, it hasn't really
|
||||||
@@ -90,12 +127,20 @@ Hartmut a decade an a half ago:
|
|||||||
NB. This is not a masterpiece of software, but became more like a hack.
|
NB. This is not a masterpiece of software, but became more like a hack.
|
||||||
Probably a complete rewrite would be sensefull. hG/2000-12-27
|
Probably a complete rewrite would be sensefull. hG/2000-12-27
|
||||||
|
|
||||||
Lastly, I should mention [unpyc](https://code.google.com/p/unpyc3/)
|
This project deparses using an Early-algorithm parse with lots of
|
||||||
and most especially [pycdc](https://github.com/zrax/pycdc), largely by
|
massaging of tokens and the grammar in the scanner
|
||||||
Michael Hansen and Darryl Pogue. If they supported getting source-code
|
phase. Early-algorithm parsers are context free and tend to be linear
|
||||||
fragments and I could call it from Python, I'd probably ditch this and
|
if the grammar is LR or left recursive.
|
||||||
use that. From what I've seen, the code runs blindingly fast and spans
|
|
||||||
all versions of Python.
|
Another approach that doesn't use grammars is to do something like
|
||||||
|
simulate execution symbolically and build expression trees off of
|
||||||
|
stack results. 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 and I could call it from Python, I'd probably
|
||||||
|
ditch this and use that. From what I've seen, the code runs blindingly
|
||||||
|
fast and spans all versions of Python.
|
||||||
|
|
||||||
Tests for the project have been, or are being, culled from all of the
|
Tests for the project have been, or are being, culled from all of the
|
||||||
projects mentioned.
|
projects mentioned.
|
||||||
|
4
LICENSE
4
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
Copyright (c) 1998-2002 John Aycock
|
|
||||||
Copyright (c) 2000 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
Copyright (c) 2015 by Rocky Bernstein
|
Copyright (c) 2015 by Rocky Bernstein
|
||||||
|
Copyright (c) 2000 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
Copyright (c) 1998-2002 John Aycock
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
include README.rst
|
include README.rst
|
||||||
include HISTORY.md
|
|
||||||
include ChangeLog
|
include ChangeLog
|
||||||
|
include HISTORY.md
|
||||||
|
include LICENSE
|
||||||
|
include DECOMPYLE-2.4-CHANGELOG.txt
|
||||||
include __pkginfo__.py
|
include __pkginfo__.py
|
||||||
recursive-include uncompyle6 *.py
|
recursive-include uncompyle6 *.py
|
||||||
include bin/uncompyle6
|
include bin/uncompyle6
|
||||||
include bin/pydisassemble
|
include bin/pydisassemble
|
||||||
recursive-include test *.py
|
recursive-include test *.py *.pyc
|
||||||
recursive-include pytest *.py
|
recursive-include pytest *.py
|
||||||
|
26
Makefile
26
Makefile
@@ -23,18 +23,31 @@ check:
|
|||||||
@PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2`; \
|
@PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2`; \
|
||||||
$(MAKE) check-$$PYTHON_VERSION
|
$(MAKE) check-$$PYTHON_VERSION
|
||||||
|
|
||||||
|
# Run all quick tests
|
||||||
|
check-short: pytest
|
||||||
|
$(MAKE) -C test check-short
|
||||||
|
|
||||||
#: Tests for Python 2.7, 3.3 and 3.4
|
#: Tests for Python 2.7, 3.3 and 3.4
|
||||||
check-2.7 check-3.3 check-3.4: pytest
|
check-2.7 check-3.3 check-3.4: pytest
|
||||||
$(MAKE) -C test $@
|
$(MAKE) -C test $@
|
||||||
|
|
||||||
#: Tests for Python 3.5 - pytest doesn't work here
|
#: Tests for Python 3.2 and 3.5 - pytest doesn't work here
|
||||||
check-3.5:
|
# Or rather 3.5 doesn't work not on Travis
|
||||||
|
check-3.1 check-3.2 check-3.5 check-3.6:
|
||||||
$(MAKE) -C test $@
|
$(MAKE) -C test $@
|
||||||
|
|
||||||
#:Tests for Python 2.6 (doesn't have pytest)
|
#:Tests for Python 2.6 (doesn't have pytest)
|
||||||
check-2.6:
|
check-2.6:
|
||||||
$(MAKE) -C test $@
|
$(MAKE) -C test $@
|
||||||
|
|
||||||
|
#:PyPy 2.6.1 or PyPy 5.0.1
|
||||||
|
# Skip for now
|
||||||
|
2.6 5.0:
|
||||||
|
|
||||||
|
#:PyPy pypy3-2.4.0 Python 3:
|
||||||
|
pypy-3.2 2.4:
|
||||||
|
$(MAKE) -C test $@
|
||||||
|
|
||||||
#: Run py.test tests
|
#: Run py.test tests
|
||||||
pytest:
|
pytest:
|
||||||
$(MAKE) -C pytest check
|
$(MAKE) -C pytest check
|
||||||
@@ -44,9 +57,9 @@ clean: clean_pyc
|
|||||||
$(PYTHON) ./setup.py $@
|
$(PYTHON) ./setup.py $@
|
||||||
(cd test && $(MAKE) clean)
|
(cd test && $(MAKE) clean)
|
||||||
|
|
||||||
#: Create source (tarball) and binary (egg) distribution
|
#: Create source (tarball) and wheel distribution
|
||||||
dist:
|
dist:
|
||||||
$(PYTHON) ./setup.py sdist bdist_egg
|
$(PYTHON) ./setup.py sdist bdist_wheel
|
||||||
|
|
||||||
#: Remove .pyc files
|
#: Remove .pyc files
|
||||||
clean_pyc:
|
clean_pyc:
|
||||||
@@ -73,6 +86,11 @@ bdist_egg:
|
|||||||
$(PYTHON) ./setup.py bdist_egg
|
$(PYTHON) ./setup.py bdist_egg
|
||||||
|
|
||||||
|
|
||||||
|
#: Create binary wheel distribution
|
||||||
|
bdist_wheel:
|
||||||
|
$(PYTHON) ./setup.py bdist_wheel
|
||||||
|
|
||||||
|
|
||||||
# It is too much work to figure out how to add a new command to distutils
|
# It is too much work to figure out how to add a new command to distutils
|
||||||
# to do the following. I'm sure distutils will someday get there.
|
# to do the following. I'm sure distutils will someday get there.
|
||||||
DISTCLEAN_FILES = build dist *.pyc
|
DISTCLEAN_FILES = build dist *.pyc
|
||||||
|
99
NEWS
99
NEWS
@@ -1,3 +1,102 @@
|
|||||||
|
uncompyle6 2.8.1 2016-08-20
|
||||||
|
|
||||||
|
- Add Python 2.2 decompilation
|
||||||
|
|
||||||
|
- Fix bugs
|
||||||
|
* PyPy LOOKUP_METHOD bug
|
||||||
|
* Python 3.6 FORMAT_VALUE handles expressions now
|
||||||
|
|
||||||
|
uncompyle6 2.8.0 2016-08-03
|
||||||
|
|
||||||
|
- Start Python 3.6 support (moagstar)
|
||||||
|
more work on PEP 498 needed
|
||||||
|
- tidy bytecode/word output
|
||||||
|
- numerous decompiling bugs fixed
|
||||||
|
- grammar testing started
|
||||||
|
- show magic number in deparsed output
|
||||||
|
- better grammar and semantic action segregation based
|
||||||
|
on python bytecode version
|
||||||
|
|
||||||
|
uncompyle6 2.7.1 2016-07-26
|
||||||
|
|
||||||
|
- PyPy bytecodes for 2.7 and 3.2 added
|
||||||
|
- Instruction formatting improved slightly
|
||||||
|
- 2.7 bytecode "continue" bug fixed
|
||||||
|
|
||||||
|
uncompyle6 2.7.0 2016-07-15
|
||||||
|
|
||||||
|
- Many Syntax and verifification bugs removed
|
||||||
|
tested on standard libraries from 2.3.7 to 3.5.1
|
||||||
|
and they all decompile and verify fine.
|
||||||
|
I'm sure there are more bugs though.
|
||||||
|
|
||||||
|
uncompyle6 2.6.2 2016-07-11 Manhattenhenge
|
||||||
|
|
||||||
|
- Extend bytecodes back to 2.3
|
||||||
|
- Fix bugs:
|
||||||
|
* 3.x and 2.7 set comprehensions,
|
||||||
|
* while1 loops
|
||||||
|
* continue statements
|
||||||
|
- DRY and segregate grammar more
|
||||||
|
|
||||||
|
uncompyle6 2.6.1 2016-07-08
|
||||||
|
|
||||||
|
- Go over Python 2.5 bytecode deparsing
|
||||||
|
all library programs now deparse
|
||||||
|
- Fix a couple bugs in 2.6 deparsing
|
||||||
|
|
||||||
|
uncompyle6 2.6.0 2016-07-07
|
||||||
|
|
||||||
|
- Improve Python 2.6 bytecode deparsing:
|
||||||
|
stdlib now will deparse something
|
||||||
|
- Better <2.6 vs. 2.7 grammar separation
|
||||||
|
- Fix some 2.7 deparsing bugs
|
||||||
|
- Fix bug in installing uncompyle6 script
|
||||||
|
- Doc improvments
|
||||||
|
|
||||||
|
uncompyle6 2.5.0 2016-06-22 Summer Solstace
|
||||||
|
|
||||||
|
- Much better Python 3.2-3.5 coverage.
|
||||||
|
3.4.6 is probably the best;3.2 and 3.5 are weaker
|
||||||
|
- Better AST printing with -t
|
||||||
|
- Better error reporting
|
||||||
|
- Better fragment offset tracking
|
||||||
|
- Some (much-needed) code refactoring
|
||||||
|
|
||||||
|
uncompyle6 2.4.0 2016-05-18 (in memory of Lewis Bernstein)
|
||||||
|
|
||||||
|
- Many Python 3 bugs fixed:
|
||||||
|
* Python 3.2 to 3.5 libaries largely
|
||||||
|
uncompyle and most verify
|
||||||
|
- pydisassembler:
|
||||||
|
* disassembles all code objects in a file
|
||||||
|
* can select showing bytecode before
|
||||||
|
or after uncompyle mangling, option -U
|
||||||
|
- DRY scanner code (but more is desired)
|
||||||
|
- Some code cleanup (but more is desired)
|
||||||
|
- Misc Bugs fixed:
|
||||||
|
* handle complex number unmarshaling
|
||||||
|
* Running on Python 2 to works on Python 3.5 bytecodes now
|
||||||
|
|
||||||
|
uncompyle6 2.3.5 and 2.3.6 2016-05-14
|
||||||
|
|
||||||
|
- Python 2 class decorator fix (thanks to Tey)
|
||||||
|
- Fix fragment parsing bugs
|
||||||
|
- Fix some Python 3 parsing bugs:
|
||||||
|
* Handling single in * parameter
|
||||||
|
* "while True"
|
||||||
|
* escape from for inside if
|
||||||
|
* yield expressions
|
||||||
|
- Correct history based on info from Dan Pascu
|
||||||
|
- Fix up pip packaging, ugh.
|
||||||
|
|
||||||
|
uncompyle6 2.3.4 2016-05-5
|
||||||
|
|
||||||
|
- More Python 3.5 parsing bugs addressed
|
||||||
|
- decompiling Python 3.5 from other Python versions works
|
||||||
|
- test from Python 3.2
|
||||||
|
- remove "__module__ = __name__" in 3.0 <= Python 3.2
|
||||||
|
|
||||||
uncompyle6 2.3.3 2016-05-3
|
uncompyle6 2.3.3 2016-05-3
|
||||||
|
|
||||||
- Fix bug in running uncompyle6 script on Python 3
|
- Fix bug in running uncompyle6 script on Python 3
|
||||||
|
2
PKG-INFO
2
PKG-INFO
@@ -5,6 +5,6 @@ Summary: Python byte-code to source-code converter
|
|||||||
Home-page: http://github.com/rocky/python-uncompyle6
|
Home-page: http://github.com/rocky/python-uncompyle6
|
||||||
Author: Rocky
|
Author: Rocky
|
||||||
Author-email: rb@dustyfeet.com
|
Author-email: rb@dustyfeet.com
|
||||||
License: GPLv3
|
License: MIT
|
||||||
Description: UNKNOWN
|
Description: UNKNOWN
|
||||||
Platform: UNKNOWN
|
Platform: UNKNOWN
|
||||||
|
69
README.rst
69
README.rst
@@ -3,27 +3,28 @@
|
|||||||
uncompyle6
|
uncompyle6
|
||||||
==========
|
==========
|
||||||
|
|
||||||
A native Python bytecode Disassembler, Decompiler, Fragment Decompiler
|
A native Python cross-version Decompiler and Fragment Decompiler.
|
||||||
and bytecode library. Follows in the tradition of decompyle, uncompyle, and uncompyle2.
|
Follows in the tradition of decompyle, uncompyle, and uncompyle2.
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
*uncompyle6* translates Python bytecode back into equivalent Python
|
*uncompyle6* translates Python bytecode back into equivalent Python
|
||||||
source code. It accepts bytecodes from Python version 2.5 to 3.4 or
|
source code. It accepts bytecodes from Python version 2.2 to 3.6 or
|
||||||
so. The code requires Python 2.6 or later and has been tested on Python
|
so, including PyPy bytecode.
|
||||||
running versions 2.6, 2.7, 3.3, 3.4 and 3.5.
|
|
||||||
|
|
||||||
Why this?
|
Why this?
|
||||||
---------
|
---------
|
||||||
|
|
||||||
There were a number of decompyle, uncompile, uncompyle2, uncompyle3
|
There were a number of decompyle, uncompile, uncompyle2, uncompyle3
|
||||||
forks around. All of them come basically from the same code base, and
|
forks around. All of them came basically from the same code base, and
|
||||||
almost all of them not maintained very well. This code pulls these together
|
almost all of them no were no longer actively maintained. Only one
|
||||||
and addresses a number of open issues in those.
|
handled Python 3, and even there, only 3.2. This code pulls these
|
||||||
|
together and moves forward. It also addresses a number of open issues
|
||||||
|
in the previous forks.
|
||||||
|
|
||||||
What makes this different from other CPython bytecode decompilers? Its
|
What makes this different from other CPython bytecode decompilers?: its
|
||||||
ability to deparse just fragments and give source-code information
|
ability to deparse just fragments and give source-code information
|
||||||
around a given bytecode offset.
|
around a given bytecode offset.
|
||||||
|
|
||||||
@@ -39,12 +40,12 @@ 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
|
when source-code information does not exist and there is just bytecode
|
||||||
information.
|
information.
|
||||||
|
|
||||||
Other parts of the library can be used inside Python for various
|
Requirements
|
||||||
bytecode-related tasks. For example you can read in bytecode,
|
------------
|
||||||
i.e. perform a version-independent `marshal.loads()`, and disassemble
|
|
||||||
the bytecode using a version of Python different from the one used to
|
|
||||||
compile the bytecode.
|
|
||||||
|
|
||||||
|
This project requires Python 2.6 or later, PyPy 3-2.4, or PyPy-5.0.1.
|
||||||
|
The bytecode files it can read has been tested on Python bytecodes from
|
||||||
|
versions 2.2-2.7, and 3.2-3.6 and the above-mentioned PyPy versions.
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
@@ -59,7 +60,7 @@ This uses setup.py, so it follows the standard Python routine:
|
|||||||
# or if you have pyenv:
|
# or if you have pyenv:
|
||||||
python setup.py develop
|
python setup.py develop
|
||||||
|
|
||||||
A GNU makefile is also provided so `make install` (possibly as root or
|
A GNU makefile is also provided so :code:`make install` (possibly as root or
|
||||||
sudo) will do the steps above.
|
sudo) will do the steps above.
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
@@ -73,7 +74,7 @@ A GNU makefile has been added to smooth over setting running the right
|
|||||||
command, and running tests from fastest to slowest.
|
command, and running tests from fastest to slowest.
|
||||||
|
|
||||||
If you have remake_ installed, you can see the list of all tasks
|
If you have remake_ installed, you can see the list of all tasks
|
||||||
including tests via `remake --tasks`
|
including tests via :code:`remake --tasks`
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
@@ -83,30 +84,46 @@ Run
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
./bin/uncompyle6 -h
|
$ uncompyle6 *compiled-python-file-pyc-or-pyo*
|
||||||
./bin/pydisassemble -h
|
|
||||||
|
|
||||||
for usage help.
|
For usage help:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
$ uncompyle6 -h
|
||||||
|
|
||||||
|
|
||||||
Known Bugs/Restrictions
|
Known Bugs/Restrictions
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Python 2 deparsing is probably as solid as the various versions of
|
Python 2 deparsing decompiles and about 90% verifies from Python 2.3.7 to Python
|
||||||
uncompyle2. Python 3 deparsing is okay but not as solid. Python 3.5 is missing some of new opcodes added, but still often works.
|
3.4.2 on the standard library packages I have on my system.
|
||||||
|
|
||||||
|
(Verification is the process of decompiling bytecode, compiling with a
|
||||||
|
Python for that byecode version, and then comparing the byetcode
|
||||||
|
produced by the decompiled/compiled program. Some allowance is made
|
||||||
|
for inessential differences.)
|
||||||
|
|
||||||
|
Later distributions average about 200 files. At this point, 2.7
|
||||||
|
decompilation is better than uncompyle2. A number of bugs have been
|
||||||
|
fixed.
|
||||||
|
|
||||||
|
Python 3.5 largely works, but still has some bugs in it.
|
||||||
|
Python 3.6 changes things drastically by using word codes rather than
|
||||||
|
byte codes, and that needs to be addressed.
|
||||||
|
|
||||||
|
There is lots to do, so please dig in and help.
|
||||||
|
|
||||||
See Also
|
See Also
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* https://github.com/zrax/pycdc : supports all versions of Python and is written in C++
|
* https://github.com/zrax/pycdc : supports all versions of Python and is written in C++
|
||||||
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only
|
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique what is used here.
|
||||||
|
* The HISTORY_ file.
|
||||||
The above projects use a different decompiling technique what is used here.
|
|
||||||
|
|
||||||
The HISTORY file.
|
|
||||||
|
|
||||||
.. |downloads| image:: https://img.shields.io/pypi/dd/uncompyle6.svg
|
.. |downloads| image:: https://img.shields.io/pypi/dd/uncompyle6.svg
|
||||||
.. _trepan: https://pypi.python.org/pypi/trepan
|
.. _trepan: https://pypi.python.org/pypi/trepan
|
||||||
|
.. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md
|
||||||
.. _debuggers: https://pypi.python.org/pypi/trepan3k
|
.. _debuggers: https://pypi.python.org/pypi/trepan3k
|
||||||
.. _remake: https://bashdb.sf.net/remake
|
.. _remake: https://bashdb.sf.net/remake
|
||||||
.. _pycdc: https://github.com/zrax/pycdc
|
.. _pycdc: https://github.com/zrax/pycdc
|
||||||
|
@@ -12,7 +12,7 @@ copyright = """
|
|||||||
Copyright (C) 2015, 2016 Rocky Bernstein <rb@dustyfeet.com>.
|
Copyright (C) 2015, 2016 Rocky Bernstein <rb@dustyfeet.com>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
classifiers = ['Development Status :: 3 - Alpha',
|
classifiers = ['Development Status :: 4 - Beta',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
@@ -23,6 +23,7 @@ classifiers = ['Development Status :: 3 - Alpha',
|
|||||||
'Programming Language :: Python :: 3.3',
|
'Programming Language :: Python :: 3.3',
|
||||||
'Programming Language :: Python :: 3.4',
|
'Programming Language :: Python :: 3.4',
|
||||||
'Programming Language :: Python :: 3.5',
|
'Programming Language :: Python :: 3.5',
|
||||||
|
'Programming Language :: Python :: 3.6',
|
||||||
'Topic :: Software Development :: Debuggers',
|
'Topic :: Software Development :: Debuggers',
|
||||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||||
]
|
]
|
||||||
@@ -30,33 +31,35 @@ classifiers = ['Development Status :: 3 - Alpha',
|
|||||||
# The rest in alphabetic order
|
# The rest in alphabetic order
|
||||||
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
|
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
|
||||||
author_email = "rb@dustyfeet.com"
|
author_email = "rb@dustyfeet.com"
|
||||||
|
entry_points={
|
||||||
|
'console_scripts': [
|
||||||
|
'uncompyle6=uncompyle6.bin.uncompile:main_bin',
|
||||||
|
'pydisassemble=uncompyle6.bin.pydisassemble:main',
|
||||||
|
]}
|
||||||
ftp_url = None
|
ftp_url = None
|
||||||
install_requires = ['python-spark >= 1.1.0']
|
install_requires = ['spark-parser >= 1.4.0',
|
||||||
license = 'GPL'
|
'xdis >= 2.2.3']
|
||||||
|
|
||||||
license = 'MIT'
|
license = 'MIT'
|
||||||
mailing_list = 'python-debugger@googlegroups.com'
|
mailing_list = 'python-debugger@googlegroups.com'
|
||||||
modname = 'uncompyle6'
|
modname = 'uncompyle6'
|
||||||
packages = ['uncompyle6', 'uncompyle6.opcodes', 'uncompyle6.semantics', 'uncompyle6.scanners', 'uncompyle6.parsers']
|
|
||||||
py_modules = None
|
py_modules = None
|
||||||
short_desc = 'Python byte-code disassembler and source-code converter'
|
short_desc = 'Python cross-version byte-code deparser'
|
||||||
scripts = ['bin/uncompyle6', 'bin/pydisassemble']
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
|
|
||||||
def get_srcdir():
|
|
||||||
filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
return os.path.realpath(filename)
|
|
||||||
|
|
||||||
ns = {}
|
|
||||||
web = 'https://github.com/rocky/python-uncompyle6/'
|
web = 'https://github.com/rocky/python-uncompyle6/'
|
||||||
|
|
||||||
# tracebacks in zip files are funky and not debuggable
|
# tracebacks in zip files are funky and not debuggable
|
||||||
zip_safe = True
|
zip_safe = True
|
||||||
|
|
||||||
|
|
||||||
def read(*rnames):
|
import os.path
|
||||||
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
|
def get_srcdir():
|
||||||
|
filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
return os.path.realpath(filename)
|
||||||
|
|
||||||
|
srcdir = get_srcdir()
|
||||||
|
|
||||||
|
def read(*rnames):
|
||||||
|
return open(os.path.join(srcdir, *rnames)).read()
|
||||||
|
|
||||||
|
# Get info from files; set: long_description and VERSION
|
||||||
long_description = ( read("README.rst") + '\n' )
|
long_description = ( read("README.rst") + '\n' )
|
||||||
|
exec(read('uncompyle6/version.py'))
|
||||||
|
@@ -1,83 +1,3 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# Mode: -*- python -*-
|
from uncompyle6.bin.pydisassemble import main
|
||||||
#
|
main()
|
||||||
# Copyright (c) 2015-2016 by Rocky Bernstein <rb@dustyfeet.com>
|
|
||||||
#
|
|
||||||
from __future__ import print_function
|
|
||||||
import sys, os, getopt
|
|
||||||
|
|
||||||
program = os.path.basename(__file__)
|
|
||||||
|
|
||||||
__doc__ = """
|
|
||||||
Usage:
|
|
||||||
%s [OPTIONS]... FILE
|
|
||||||
%s [--help | -h | -V | --version]
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
%s foo.pyc
|
|
||||||
%s foo.py
|
|
||||||
%s -o foo.pydis foo.pyc
|
|
||||||
%s -o /tmp foo.pyc
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-o <path> output decompiled files to this path:
|
|
||||||
if multiple input files are decompiled, the common prefix
|
|
||||||
is stripped from these names and the remainder appended to
|
|
||||||
<path>
|
|
||||||
--help show this message
|
|
||||||
|
|
||||||
""" % ((program,) * 6)
|
|
||||||
|
|
||||||
|
|
||||||
Usage_short = \
|
|
||||||
"%s [--help] [--verify] [--showasm] [--showast] [-o <path>] FILE|DIR..." % program
|
|
||||||
|
|
||||||
from uncompyle6 import check_python_version
|
|
||||||
from uncompyle6.disas import disassemble_files
|
|
||||||
from uncompyle6.version import VERSION
|
|
||||||
|
|
||||||
check_python_version(program)
|
|
||||||
|
|
||||||
outfile = '-'
|
|
||||||
out_base = None
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
opts, files = getopt.getopt(sys.argv[1:], 'hVo:', ['help', 'version'])
|
|
||||||
except getopt.GetoptError as e:
|
|
||||||
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
for opt, val in opts:
|
|
||||||
if opt in ('-h', '--help'):
|
|
||||||
print(__doc__)
|
|
||||||
sys.exit(1)
|
|
||||||
elif opt in ('-V', '--version'):
|
|
||||||
print("%s %s" % (program, VERSION))
|
|
||||||
sys.exit(0)
|
|
||||||
elif opt == '-o':
|
|
||||||
outfile = val
|
|
||||||
else:
|
|
||||||
print(opt)
|
|
||||||
print(Usage_short)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# argl, commonprefix works on strings, not on path parts,
|
|
||||||
# thus we must handle the case with files in 'some/classes'
|
|
||||||
# and 'some/cmds'
|
|
||||||
src_base = os.path.commonprefix(files)
|
|
||||||
if src_base[-1:] != os.sep:
|
|
||||||
src_base = os.path.dirname(src_base)
|
|
||||||
if src_base:
|
|
||||||
sb_len = len( os.path.join(src_base, '') )
|
|
||||||
files = [f[sb_len:] for f in files]
|
|
||||||
del sb_len
|
|
||||||
|
|
||||||
if outfile == '-':
|
|
||||||
outfile = None # use stdout
|
|
||||||
elif outfile and os.path.isdir(outfile):
|
|
||||||
out_base = outfile; outfile = None
|
|
||||||
elif outfile and len(files) > 1:
|
|
||||||
out_base = outfile; outfile = None
|
|
||||||
|
|
||||||
disassemble_files(src_base, out_base, files, outfile)
|
|
||||||
|
223
bin/uncompyle6
223
bin/uncompyle6
@@ -1,222 +1,3 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# Mode: -*- python -*-
|
from uncompyle6.bin.uncompile import main_bin
|
||||||
#
|
main_bin()
|
||||||
# Copyright (c) 2015-2016 by Rocky Bernstein
|
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
#
|
|
||||||
from __future__ import print_function
|
|
||||||
import sys, os, getopt, time
|
|
||||||
|
|
||||||
program = os.path.basename(__file__)
|
|
||||||
|
|
||||||
__doc__ = """
|
|
||||||
Usage:
|
|
||||||
%s [OPTIONS]... [ FILE | DIR]...
|
|
||||||
%s [--help | -h | --V | --version]
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
%s foo.pyc bar.pyc # decompile foo.pyc, bar.pyc to stdout
|
|
||||||
%s -o . foo.pyc bar.pyc # decompile to ./foo.pyc_dis and ./bar.pyc_dis
|
|
||||||
%s -o /tmp /usr/lib/python1.5 # decompile whole library
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-o <path> output decompiled files to this path:
|
|
||||||
if multiple input files are decompiled, the common prefix
|
|
||||||
is stripped from these names and the remainder appended to
|
|
||||||
<path>
|
|
||||||
uncompyle6 -o /tmp bla/fasel.pyc bla/foo.pyc
|
|
||||||
-> /tmp/fasel.pyc_dis, /tmp/foo.pyc_dis
|
|
||||||
uncompyle6 -o /tmp bla/fasel.pyc bar/foo.pyc
|
|
||||||
-> /tmp/bla/fasel.pyc_dis, /tmp/bar/foo.pyc_dis
|
|
||||||
uncompyle6 -o /tmp /usr/lib/python1.5
|
|
||||||
-> /tmp/smtplib.pyc_dis ... /tmp/lib-tk/FixTk.pyc_dis
|
|
||||||
-c <file> attempts a disassembly after compiling <file>
|
|
||||||
-d print timestamps
|
|
||||||
-p <integer> use <integer> number of processes
|
|
||||||
-r recurse directories looking for .pyc and .pyo files
|
|
||||||
--verify compare generated source with input byte-code
|
|
||||||
(requires -o)
|
|
||||||
--help show this message
|
|
||||||
|
|
||||||
Debugging Options:
|
|
||||||
--asm -a include byte-code (disables --verify)
|
|
||||||
--grammar -g show matching grammar
|
|
||||||
--tree -t include syntax tree (disables --verify)
|
|
||||||
|
|
||||||
Extensions of generated files:
|
|
||||||
'.pyc_dis' '.pyo_dis' successfully decompiled (and verified if --verify)
|
|
||||||
+ '_unverified' successfully decompile but --verify failed
|
|
||||||
+ '_failed' decompile failed (contact author for enhancement)
|
|
||||||
""" % ((program,) * 5)
|
|
||||||
|
|
||||||
program = os.path.basename(__file__)
|
|
||||||
|
|
||||||
from uncompyle6 import verify, check_python_version
|
|
||||||
from uncompyle6.main import main, status_msg
|
|
||||||
from uncompyle6.version import VERSION
|
|
||||||
|
|
||||||
def usage():
|
|
||||||
print("""usage:
|
|
||||||
%s [--verify] [--asm] [--tree] [--grammar] [-o <path>] FILE|DIR...
|
|
||||||
%s [--help | -h | --version | -V]
|
|
||||||
""" % (program, program))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
check_python_version(program)
|
|
||||||
|
|
||||||
showasm = showast = do_verify = recurse_dirs = False
|
|
||||||
numproc = 0
|
|
||||||
outfile = '-'
|
|
||||||
out_base = None
|
|
||||||
codes = []
|
|
||||||
timestamp = False
|
|
||||||
timestampfmt = "# %Y.%m.%d %H:%M:%S %Z"
|
|
||||||
|
|
||||||
try:
|
|
||||||
opts, files = getopt.getopt(sys.argv[1:], 'hagtdrVo:c:p:',
|
|
||||||
'help asm grammar recurse timestamp tree verify version '
|
|
||||||
'showgrammar'.split(' '))
|
|
||||||
except getopt.GetoptError as e:
|
|
||||||
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
options = {}
|
|
||||||
for opt, val in opts:
|
|
||||||
if opt in ('-h', '--help'):
|
|
||||||
print(__doc__)
|
|
||||||
sys.exit(0)
|
|
||||||
elif opt in ('-V', '--version'):
|
|
||||||
print("%s %s" % (program, VERSION))
|
|
||||||
sys.exit(0)
|
|
||||||
elif opt == '--verify':
|
|
||||||
options['do_verify'] = True
|
|
||||||
elif opt in ('--asm', '-a'):
|
|
||||||
options['showasm'] = True
|
|
||||||
options['do_verify'] = False
|
|
||||||
elif opt in ('--tree', '-t'):
|
|
||||||
options['showast'] = True
|
|
||||||
options['do_verify'] = False
|
|
||||||
elif opt in ('--grammar', '-g'):
|
|
||||||
options['showgrammar'] = True
|
|
||||||
elif opt == '-o':
|
|
||||||
outfile = val
|
|
||||||
elif opt in ('--timestamp', '-d'):
|
|
||||||
timestamp = True
|
|
||||||
elif opt == '-c':
|
|
||||||
codes.append(val)
|
|
||||||
elif opt == '-p':
|
|
||||||
numproc = int(val)
|
|
||||||
elif opt in ('--recurse', '-r'):
|
|
||||||
recurse_dirs = True
|
|
||||||
else:
|
|
||||||
print(opt, file=sys.stderr)
|
|
||||||
usage()
|
|
||||||
|
|
||||||
# expand directory if specified
|
|
||||||
if recurse_dirs:
|
|
||||||
expanded_files = []
|
|
||||||
for f in files:
|
|
||||||
if os.path.isdir(f):
|
|
||||||
for root, _, dir_files in os.walk(f):
|
|
||||||
for df in dir_files:
|
|
||||||
if df.endswith('.pyc') or df.endswith('.pyo'):
|
|
||||||
expanded_files.append(os.path.join(root, df))
|
|
||||||
files = expanded_files
|
|
||||||
|
|
||||||
# argl, commonprefix works on strings, not on path parts,
|
|
||||||
# thus we must handle the case with files in 'some/classes'
|
|
||||||
# and 'some/cmds'
|
|
||||||
src_base = os.path.commonprefix(files)
|
|
||||||
if src_base[-1:] != os.sep:
|
|
||||||
src_base = os.path.dirname(src_base)
|
|
||||||
if src_base:
|
|
||||||
sb_len = len( os.path.join(src_base, '') )
|
|
||||||
files = [f[sb_len:] for f in files]
|
|
||||||
del sb_len
|
|
||||||
|
|
||||||
if not files:
|
|
||||||
print("No files given", file=sys.stderr)
|
|
||||||
usage()
|
|
||||||
|
|
||||||
|
|
||||||
if outfile == '-':
|
|
||||||
outfile = None # use stdout
|
|
||||||
elif outfile and os.path.isdir(outfile):
|
|
||||||
out_base = outfile; outfile = None
|
|
||||||
elif outfile and len(files) > 1:
|
|
||||||
out_base = outfile; outfile = None
|
|
||||||
|
|
||||||
if timestamp:
|
|
||||||
print(time.strftime(timestampfmt))
|
|
||||||
|
|
||||||
if numproc <= 1:
|
|
||||||
try:
|
|
||||||
result = main(src_base, out_base, files, codes, outfile,
|
|
||||||
**options)
|
|
||||||
if len(files) > 1:
|
|
||||||
mess = status_msg(do_verify, *result)
|
|
||||||
print('# ' + mess)
|
|
||||||
pass
|
|
||||||
except (KeyboardInterrupt):
|
|
||||||
pass
|
|
||||||
except verify.VerifyCmpError:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
from multiprocessing import Process, Queue
|
|
||||||
|
|
||||||
try:
|
|
||||||
from Queue import Empty
|
|
||||||
except ImportError:
|
|
||||||
from Queue import Empty
|
|
||||||
|
|
||||||
fqueue = Queue(len(files)+numproc)
|
|
||||||
for f in files:
|
|
||||||
fqueue.put(f)
|
|
||||||
for i in range(numproc):
|
|
||||||
fqueue.put(None)
|
|
||||||
|
|
||||||
rqueue = Queue(numproc)
|
|
||||||
|
|
||||||
def process_func():
|
|
||||||
try:
|
|
||||||
(tot_files, okay_files, failed_files, verify_failed_files) = (0, 0, 0, 0)
|
|
||||||
while 1:
|
|
||||||
f = fqueue.get()
|
|
||||||
if f is None:
|
|
||||||
break
|
|
||||||
(t, o, f, v) = \
|
|
||||||
main(src_base, out_base, [f], codes, outfile, **options)
|
|
||||||
tot_files += t
|
|
||||||
okay_files += o
|
|
||||||
failed_files += f
|
|
||||||
verify_failed_files += v
|
|
||||||
except (Empty, KeyboardInterrupt):
|
|
||||||
pass
|
|
||||||
rqueue.put((tot_files, okay_files, failed_files, verify_failed_files))
|
|
||||||
rqueue.close()
|
|
||||||
|
|
||||||
try:
|
|
||||||
procs = [Process(target=process_func) for i in range(numproc)]
|
|
||||||
for p in procs:
|
|
||||||
p.start()
|
|
||||||
for p in procs:
|
|
||||||
p.join()
|
|
||||||
try:
|
|
||||||
(tot_files, okay_files, failed_files, verify_failed_files) = (0, 0, 0, 0)
|
|
||||||
while True:
|
|
||||||
(t, o, f, v) = rqueue.get(False)
|
|
||||||
tot_files += t
|
|
||||||
okay_files += o
|
|
||||||
failed_files += f
|
|
||||||
verify_failed_files += v
|
|
||||||
except Empty:
|
|
||||||
pass
|
|
||||||
print('# decompiled %i files: %i okay, %i failed, %i verify failed' %
|
|
||||||
(tot_files, okay_files, failed_files, verify_failed_files))
|
|
||||||
except (KeyboardInterrupt, OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
if timestamp:
|
|
||||||
print(time.strftime(timestampfmt))
|
|
||||||
|
@@ -20,12 +20,20 @@ def for_range_stmt():
|
|||||||
for i in range(2):
|
for i in range(2):
|
||||||
i+1
|
i+1
|
||||||
|
|
||||||
|
# # FIXME: add this test - but for Python 2.7+ only
|
||||||
|
# def set_comp():
|
||||||
|
# {y for y in range(3)}
|
||||||
|
|
||||||
|
# FIXME: add this test
|
||||||
|
def list_comp():
|
||||||
|
[y for y in range(3)]
|
||||||
|
|
||||||
def get_parsed_for_fn(fn):
|
def get_parsed_for_fn(fn):
|
||||||
code = fn.__code__ if PYTHON3 else fn.func_code
|
code = fn.__code__ if PYTHON3 else fn.func_code
|
||||||
return deparse(PYTHON_VERSION, code)
|
return deparse(PYTHON_VERSION, code)
|
||||||
|
|
||||||
def check_expect(expect, parsed):
|
def check_expect(expect, parsed):
|
||||||
debug = True
|
debug = False
|
||||||
i = 2
|
i = 2
|
||||||
max_expect = len(expect)
|
max_expect = len(expect)
|
||||||
for name, offset in sorted(parsed.offsets.keys()):
|
for name, offset in sorted(parsed.offsets.keys()):
|
||||||
@@ -160,7 +168,7 @@ return (x, y)
|
|||||||
-------------
|
-------------
|
||||||
""".split("\n")
|
""".split("\n")
|
||||||
check_expect(expect, parsed)
|
check_expect(expect, parsed)
|
||||||
# ########################################################
|
########################################################
|
||||||
# # try
|
# # try
|
||||||
|
|
||||||
# expect = """
|
# expect = """
|
||||||
@@ -291,6 +299,12 @@ return
|
|||||||
Contained in...
|
Contained in...
|
||||||
i + 1
|
i + 1
|
||||||
-----
|
-----
|
||||||
|
31
|
||||||
|
return
|
||||||
|
------
|
||||||
|
Contained in...
|
||||||
|
for i in range(2): ...
|
||||||
|
------------------ ...
|
||||||
34
|
34
|
||||||
return
|
return
|
||||||
------
|
------
|
||||||
|
@@ -24,7 +24,7 @@ os.chdir(src_dir)
|
|||||||
def test_funcoutput(capfd, test_tuple, function_to_test):
|
def test_funcoutput(capfd, test_tuple, function_to_test):
|
||||||
|
|
||||||
in_file , filename_expected = test_tuple
|
in_file , filename_expected = test_tuple
|
||||||
function_to_test(in_file)
|
function_to_test(in_file, native=False)
|
||||||
resout, reserr = capfd.readouterr()
|
resout, reserr = capfd.readouterr()
|
||||||
expected = open(filename_expected, "r").read()
|
expected = open(filename_expected, "r").read()
|
||||||
if resout != expected:
|
if resout != expected:
|
||||||
|
40
pytest/test_fjt.py
Normal file
40
pytest/test_fjt.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
from uncompyle6 import PYTHON_VERSION, IS_PYPY
|
||||||
|
from uncompyle6.scanner import get_scanner
|
||||||
|
from array import array
|
||||||
|
def bug(state, slotstate):
|
||||||
|
if state:
|
||||||
|
if slotstate is not None:
|
||||||
|
for key, value in slotstate.items():
|
||||||
|
setattr(state, key, 2)
|
||||||
|
|
||||||
|
def test_if_in_for():
|
||||||
|
code = bug.__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)
|
||||||
|
scan.build_lines_data(code, n)
|
||||||
|
scan.build_prev_op(n)
|
||||||
|
fjt = scan.find_jump_targets()
|
||||||
|
assert {15: [3], 69: [66], 63: [18]} == fjt
|
||||||
|
assert scan.structs == \
|
||||||
|
[{'start': 0, 'end': 72, 'type': 'root'},
|
||||||
|
{'start': 18, 'end': 66, 'type': 'if-then'},
|
||||||
|
{'start': 31, 'end': 59, 'type': 'for-loop'},
|
||||||
|
{'start': 62, 'end': 63, 'type': 'for-else'}]
|
||||||
|
elif 3.2 < PYTHON_VERSION <= 3.4:
|
||||||
|
scan.code = array('B', code.co_code)
|
||||||
|
scan.build_lines_data(code)
|
||||||
|
scan.build_prev_op()
|
||||||
|
fjt = scan.find_jump_targets()
|
||||||
|
assert {69: [66], 63: [18]} == fjt
|
||||||
|
assert scan.structs == \
|
||||||
|
[{'end': 72, 'type': 'root', 'start': 0},
|
||||||
|
{'end': 66, 'type': 'if-then', 'start': 6},
|
||||||
|
{'end': 63, 'type': 'if-then', 'start': 18},
|
||||||
|
{'end': 59, 'type': 'for-loop', 'start': 31},
|
||||||
|
{'end': 63, 'type': 'for-else', 'start': 62}]
|
||||||
|
else:
|
||||||
|
assert True, "FIXME: should note fixed"
|
||||||
|
return
|
136
pytest/test_fstring.py
Normal file
136
pytest/test_fstring.py
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# 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()',
|
||||||
|
'sorted(items, key=lambda x: x.name)',
|
||||||
|
'func(*args, **kwargs)',
|
||||||
|
'text or default',
|
||||||
|
)))
|
||||||
|
|
||||||
|
|
||||||
|
@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.
|
||||||
|
"""
|
||||||
|
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())
|
||||||
|
# not yet : conversion not supported
|
||||||
|
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 = ''.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
|
||||||
|
|
||||||
|
|
||||||
|
@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"""
|
||||||
|
|
||||||
|
# ignore fstring with no expressions an fsring with
|
||||||
|
# no expressions just gets compiled to a normal string.
|
||||||
|
hypothesis.assume('{' in fstring)
|
||||||
|
|
||||||
|
# BUG : At the moment a single expression is not supported
|
||||||
|
# for example f'{abc}'.
|
||||||
|
hypothesis.assume(fstring.count('{') > 1)
|
||||||
|
|
||||||
|
expr = fstring + '\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 deparsed.text == expr
|
44
pytest/test_grammar.py
Normal file
44
pytest/test_grammar.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import pytest, re
|
||||||
|
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY # , PYTHON_VERSION
|
||||||
|
from uncompyle6.parser import get_python_parser
|
||||||
|
from uncompyle6.scanner import get_scanner
|
||||||
|
|
||||||
|
def test_grammar():
|
||||||
|
|
||||||
|
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
|
||||||
|
assert remain_tokens == set([]), \
|
||||||
|
"Remaining tokens %s\n====\n%s" % (remain_tokens, p.dumpGrammar())
|
||||||
|
|
||||||
|
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
|
||||||
|
lhs, rhs, tokens, right_recursive = p.checkSets()
|
||||||
|
expect_lhs = set(['expr1024', 'pos_arg'])
|
||||||
|
unused_rhs = set(['build_list', 'call_function', 'mkfunc', 'mklambda',
|
||||||
|
'unpack', 'unpack_list'])
|
||||||
|
expect_right_recursive = [['designList', ('designator', 'DUP_TOP', 'designList')]]
|
||||||
|
if PYTHON3:
|
||||||
|
expect_lhs.add('load_genexpr')
|
||||||
|
unused_rhs = unused_rhs.union(set("""
|
||||||
|
except_pop_except genexpr classdefdeco2 listcomp
|
||||||
|
""".split()))
|
||||||
|
else:
|
||||||
|
expect_lhs.add('kwarg')
|
||||||
|
assert expect_lhs == set(lhs)
|
||||||
|
assert unused_rhs == set(rhs)
|
||||||
|
assert expect_right_recursive == right_recursive
|
||||||
|
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||||
|
ignore_set = set(
|
||||||
|
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||||
|
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP
|
||||||
|
LAMBDA_MARKER RETURN_LAST
|
||||||
|
""".split())
|
||||||
|
if 2.6 <= PYTHON_VERSION <= 2.7:
|
||||||
|
opcode_set = set(s.opc.opname).union(ignore_set)
|
||||||
|
check_tokens(tokens, opcode_set)
|
||||||
|
elif PYTHON_VERSION == 3.4:
|
||||||
|
ignore_set.add('LOAD_CLASSNAME')
|
||||||
|
opcode_set = set(s.opc.opname).union(ignore_set)
|
||||||
|
check_tokens(tokens, opcode_set)
|
@@ -1,10 +0,0 @@
|
|||||||
import sys
|
|
||||||
from uncompyle6.load import load_file, check_object_path, load_module
|
|
||||||
|
|
||||||
def test_load():
|
|
||||||
"""Basic test of load_file, check_object_path and load_module"""
|
|
||||||
co = load_file(__file__)
|
|
||||||
obj_path = check_object_path(__file__)
|
|
||||||
version, timestamp, magic_int, co2 = load_module(obj_path)
|
|
||||||
assert sys.version[0:3] == str(version)
|
|
||||||
assert co == co2
|
|
17
pytest/testdata/if-2.7.right
vendored
17
pytest/testdata/if-2.7.right
vendored
@@ -1,13 +1,12 @@
|
|||||||
# Python 2.7
|
# Python 2.7
|
||||||
# Embedded file name: simple_source/branching/05_if.py
|
# Embedded file name: simple_source/branching/05_if.py
|
||||||
|
|
||||||
6 0 LOAD_NAME 'True'
|
6 0 LOAD_NAME 0 'True'
|
||||||
3 POP_JUMP_IF_FALSE '15'
|
3 POP_JUMP_IF_FALSE 15 'to 15'
|
||||||
|
|
||||||
7 6 LOAD_NAME 'False'
|
|
||||||
9 STORE_NAME 'b'
|
|
||||||
12 JUMP_FORWARD '15'
|
|
||||||
15_0 COME_FROM '12'
|
|
||||||
15 LOAD_CONST ''
|
|
||||||
18 RETURN_VALUE ''
|
|
||||||
|
|
||||||
|
7 6 LOAD_NAME 1 'False'
|
||||||
|
9 STORE_NAME 2 'b'
|
||||||
|
12 JUMP_FORWARD 0 'to 15'
|
||||||
|
15_0 COME_FROM '12'
|
||||||
|
15 LOAD_CONST 0 ''
|
||||||
|
18 RETURN_VALUE
|
||||||
|
21
pytest/testdata/ifelse-2.7.right
vendored
21
pytest/testdata/ifelse-2.7.right
vendored
@@ -1,16 +1,15 @@
|
|||||||
# Python 2.7
|
# Python 2.7
|
||||||
# Embedded file name: simple_source/branching/05_ifelse.py
|
# Embedded file name: simple_source/branching/05_ifelse.py
|
||||||
|
|
||||||
3 0 LOAD_NAME 'True'
|
3 0 LOAD_NAME 0 'True'
|
||||||
3 POP_JUMP_IF_FALSE '15'
|
3 POP_JUMP_IF_FALSE 15 'to 15'
|
||||||
|
|
||||||
4 6 LOAD_CONST 1
|
4 6 LOAD_CONST 0 1
|
||||||
9 STORE_NAME 'b'
|
9 STORE_NAME 1 'b'
|
||||||
12 JUMP_FORWARD '21'
|
12 JUMP_FORWARD 6 'to 21'
|
||||||
|
|
||||||
6 15 LOAD_CONST 2
|
|
||||||
18 STORE_NAME 'd'
|
|
||||||
21_0 COME_FROM '12'
|
|
||||||
21 LOAD_CONST ''
|
|
||||||
24 RETURN_VALUE ''
|
|
||||||
|
|
||||||
|
6 15 LOAD_CONST 1 2
|
||||||
|
18 STORE_NAME 2 'd'
|
||||||
|
21_0 COME_FROM '12'
|
||||||
|
21 LOAD_CONST 2 ''
|
||||||
|
24 RETURN_VALUE
|
||||||
|
@@ -1,2 +1,3 @@
|
|||||||
pytest
|
pytest
|
||||||
flake8
|
flake8
|
||||||
|
hypothesis
|
@@ -1 +1,2 @@
|
|||||||
spark_parser >= 1.1.0
|
spark-parser >= 1.4.0
|
||||||
|
xdis >= 2.2.2
|
||||||
|
25
setup.py
25
setup.py
@@ -3,30 +3,27 @@
|
|||||||
"""Setup script for the 'uncompyle6' distribution."""
|
"""Setup script for the 'uncompyle6' distribution."""
|
||||||
|
|
||||||
from __pkginfo__ import \
|
from __pkginfo__ import \
|
||||||
author, author_email, \
|
author, author_email, install_requires, \
|
||||||
license, long_description, \
|
license, long_description, classifiers, \
|
||||||
modname, packages, py_modules, scripts, \
|
entry_points, modname, py_modules, \
|
||||||
short_desc, web, zip_safe
|
short_desc, VERSION, web, \
|
||||||
|
zip_safe
|
||||||
__import__('pkg_resources')
|
|
||||||
from setuptools import setup
|
|
||||||
|
|
||||||
exec(open('uncompyle6/version.py').read())
|
|
||||||
|
|
||||||
|
from setuptools import setup, find_packages
|
||||||
setup(
|
setup(
|
||||||
author = author,
|
author = author,
|
||||||
author_email = author_email,
|
author_email = author_email,
|
||||||
# classifiers = classifiers,
|
classifiers = classifiers,
|
||||||
description = short_desc,
|
description = short_desc,
|
||||||
# install_requires = install_requires,
|
entry_points = entry_points,
|
||||||
|
install_requires = install_requires,
|
||||||
license = license,
|
license = license,
|
||||||
long_description = long_description,
|
long_description = long_description,
|
||||||
py_modules = py_modules,
|
|
||||||
name = modname,
|
name = modname,
|
||||||
packages = packages,
|
packages = find_packages(),
|
||||||
|
py_modules = py_modules,
|
||||||
test_suite = 'nose.collector',
|
test_suite = 'nose.collector',
|
||||||
url = web,
|
url = web,
|
||||||
setup_requires = ['nose>=1.0'],
|
setup_requires = ['nose>=1.0'],
|
||||||
scripts = scripts,
|
|
||||||
version = VERSION,
|
version = VERSION,
|
||||||
zip_safe = zip_safe)
|
zip_safe = zip_safe)
|
||||||
|
@@ -20,36 +20,64 @@ check:
|
|||||||
$(MAKE) check-$$PYTHON_VERSION
|
$(MAKE) check-$$PYTHON_VERSION
|
||||||
|
|
||||||
#: Run working tests from Python 2.6 or 2.7
|
#: Run working tests from Python 2.6 or 2.7
|
||||||
check-2.6 check-2.7: check-bytecode-sans-3.5 check-2.7-ok
|
check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-2.7-ok
|
||||||
|
|
||||||
|
#: Run working tests from Python 3.1
|
||||||
|
check-3.2: check-bytecode
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-3.1 --verify $(COMPILE)
|
||||||
|
|
||||||
|
#: Run working tests from Python 3.2
|
||||||
|
check-3.2: check-bytecode
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-3.2 --verify $(COMPILE)
|
||||||
|
|
||||||
#: Run working tests from Python 3.3
|
#: Run working tests from Python 3.3
|
||||||
check-3.3: check-bytecode
|
check-3.3: check-bytecode
|
||||||
$(PYTHON) test_pythonlib.py --bytecode-3.3 --verify $(COMPILE)
|
$(PYTHON) test_pythonlib.py --bytecode-3.3 --verify $(COMPILE)
|
||||||
|
|
||||||
#: Run working tests from Python 3.5
|
|
||||||
check-3.5: check-bytecode
|
|
||||||
|
|
||||||
#: Run working tests from Python 3.4
|
#: Run working tests from Python 3.4
|
||||||
check-3.4: check-bytecode check-3.4-ok check-2.7-ok
|
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 --verify $(COMPILE)
|
||||||
|
|
||||||
|
#: Run working tests from Python 3.5
|
||||||
|
check-3.5: check-bytecode
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-3.5 --verify $(COMPILE)
|
||||||
|
|
||||||
|
#: Run working tests from Python 3.6
|
||||||
|
check-3.6: check-bytecode
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-3.6 --verify $(COMPILE)
|
||||||
|
|
||||||
#: Check deparsing only, but from a different Python version
|
#: Check deparsing only, but from a different Python version
|
||||||
check-disasm:
|
check-disasm:
|
||||||
$(PYTHON) dis-compare.py
|
$(PYTHON) dis-compare.py
|
||||||
|
|
||||||
#: Check deparsing bytecode only
|
#: Check deparsing bytecode 2.x only
|
||||||
check-bytecode-2:
|
check-bytecode-2:
|
||||||
$(PYTHON) test_pythonlib.py --bytecode-2.5 --bytecode-2.6 --bytecode-2.7
|
$(PYTHON) test_pythonlib.py \
|
||||||
|
--bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
|
||||||
|
--bytecode-2.5 --bytecode-2.6 --bytecode-2.7 --bytecode-pypy2.7
|
||||||
|
|
||||||
#: Check deparsing bytecode only
|
#: Check deparsing bytecode 3.x only
|
||||||
check-bytecode:
|
check-bytecode-3:
|
||||||
$(PYTHON) test_pythonlib.py --bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \
|
$(PYTHON) test_pythonlib.py --bytecode-3.2 --bytecode-3.3 \
|
||||||
--bytecode-3.2 --bytecode-3.3 --bytecode-3.4 --bytecode-3.5
|
--bytecode-3.4 --bytecode-3.5 --bytecode-pypy3.2
|
||||||
|
|
||||||
#: Check deparsing bytecode only
|
#: Check deparsing bytecode that works running Python 2 and Python 3
|
||||||
check-bytecode-sans-3.5:
|
check-bytecode: check-bytecode-3
|
||||||
$(PYTHON) test_pythonlib.py --bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \
|
$(PYTHON) test_pythonlib.py \
|
||||||
--bytecode-3.2 --bytecode-3.3 --bytecode-3.4
|
--bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
|
||||||
|
--bytecode-2.5 --bytecode-2.6 --bytecode-2.7 --bytecode-pypy2.7
|
||||||
|
|
||||||
|
#: Check deparsing Python 2.2
|
||||||
|
check-bytecode-2.3:
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-2.2
|
||||||
|
|
||||||
|
#: Check deparsing Python 2.3
|
||||||
|
check-bytecode-2.3:
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-2.3
|
||||||
|
|
||||||
|
#: Check deparsing Python 2.4
|
||||||
|
check-bytecode-2.4:
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-2.4
|
||||||
|
|
||||||
#: Check deparsing Python 2.5
|
#: Check deparsing Python 2.5
|
||||||
check-bytecode-2.5:
|
check-bytecode-2.5:
|
||||||
@@ -79,10 +107,18 @@ check-bytecode-3.4:
|
|||||||
check-bytecode-3.5:
|
check-bytecode-3.5:
|
||||||
$(PYTHON) test_pythonlib.py --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
|
||||||
|
|
||||||
#: short tests for bytecodes only for this version of Python
|
#: short tests for bytecodes only for this version of Python
|
||||||
check-native-short:
|
check-native-short:
|
||||||
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --verify $(COMPILE)
|
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --verify $(COMPILE)
|
||||||
|
|
||||||
|
#: Run longer Python 2.6's lib files known to be okay
|
||||||
|
check-2.6-ok:
|
||||||
|
$(PYTHON) test_pythonlib.py --ok-2.6 --verify $(COMPILE)
|
||||||
|
|
||||||
#: Run longer Python 2.7's lib files known to be okay
|
#: Run longer Python 2.7's lib files known to be okay
|
||||||
check-2.7-ok:
|
check-2.7-ok:
|
||||||
$(PYTHON) test_pythonlib.py --ok-2.7 --verify $(COMPILE)
|
$(PYTHON) test_pythonlib.py --ok-2.7 --verify $(COMPILE)
|
||||||
@@ -95,6 +131,18 @@ check-3.2-ok:
|
|||||||
check-3.4-ok:
|
check-3.4-ok:
|
||||||
$(PYTHON) test_pythonlib.py --ok-3.4 --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
|
||||||
|
2.6:
|
||||||
|
|
||||||
|
#: PyPy 5.0.x with Python 2.7 ...
|
||||||
|
pypy-2.7 5.0 5.3:
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-pypy2.7 --verify
|
||||||
|
|
||||||
|
#: PyPy 2.4.x with Python 3.2 ...
|
||||||
|
pypy-3.2 2.4:
|
||||||
|
$(PYTHON) test_pythonlib.py --bytecode-pypy3.2 --verify
|
||||||
|
|
||||||
clean: clean-py-dis clean-dis clean-unverified
|
clean: clean-py-dis clean-dis clean-unverified
|
||||||
|
|
||||||
clean-dis:
|
clean-dis:
|
||||||
@@ -103,6 +151,6 @@ clean-dis:
|
|||||||
clean-unverified:
|
clean-unverified:
|
||||||
find . -name '*_unverified' -exec rm -v '{}' ';'
|
find . -name '*_unverified' -exec rm -v '{}' ';'
|
||||||
|
|
||||||
#: Clean temporary compile/decompile/verify direcotries in /tmp
|
#: Clean temporary compile/decompile/verify directories in /tmp
|
||||||
clean-py-dis:
|
clean-py-dis:
|
||||||
rm -fr /tmp/py-dis-* || true
|
rm -fr /tmp/py-dis-* || true
|
||||||
|
@@ -2,11 +2,15 @@
|
|||||||
""" Trivial helper program to bytecompile and run an uncompile
|
""" Trivial helper program to bytecompile and run an uncompile
|
||||||
"""
|
"""
|
||||||
import os, sys, py_compile
|
import os, sys, py_compile
|
||||||
assert len(sys.argv) == 2
|
assert len(sys.argv) >= 2
|
||||||
path = sys.argv[1]
|
|
||||||
short = os.path.basename(path)
|
|
||||||
version = sys.version[0:3]
|
version = sys.version[0:3]
|
||||||
cfile = "bytecode_%s/%s" % (version, short) + 'c'
|
for path in sys.argv[1:]:
|
||||||
print("byte-compiling %s to %s" % (path, cfile))
|
short = os.path.basename(path)
|
||||||
py_compile.compile(path, cfile)
|
if hasattr(sys, 'pypy_version_info'):
|
||||||
os.system("../bin/uncompyle6 -a -t %s" % cfile)
|
cfile = "bytecode_pypy%s/%s" % (version, short) + 'c'
|
||||||
|
else:
|
||||||
|
cfile = "bytecode_%s/%s" % (version, short) + 'c'
|
||||||
|
print("byte-compiling %s to %s" % (path, cfile))
|
||||||
|
py_compile.compile(path, cfile)
|
||||||
|
if isinstance(version, str) or version >= (2, 6, 0):
|
||||||
|
os.system("../bin/uncompyle6 -a -t %s" % cfile)
|
||||||
|
BIN
test/bytecode_2.2/00_assign.pyc
Normal file
BIN
test/bytecode_2.2/00_assign.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/00_import.pyc
Normal file
BIN
test/bytecode_2.2/00_import.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/00_pass.pyc
Normal file
BIN
test/bytecode_2.2/00_pass.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/02_apply_equiv.pyc
Normal file
BIN
test/bytecode_2.2/02_apply_equiv.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/03_class_method.pyc
Normal file
BIN
test/bytecode_2.2/03_class_method.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/03_if_elif.pyc
Normal file
BIN
test/bytecode_2.2/03_if_elif.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.2/05_test_yield.pyc
Normal file
BIN
test/bytecode_2.2/05_test_yield.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/00_assign.pyc
Normal file
BIN
test/bytecode_2.3/00_assign.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/00_import.pyc
Normal file
BIN
test/bytecode_2.3/00_import.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/00_pass.pyc
Normal file
BIN
test/bytecode_2.3/00_pass.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/01_boolean.pyc
Normal file
BIN
test/bytecode_2.3/01_boolean.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/01_class.pyc
Normal file
BIN
test/bytecode_2.3/01_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/01_fns.pyc
Normal file
BIN
test/bytecode_2.3/01_fns.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/01_list_comprehension.pyc
Normal file
BIN
test/bytecode_2.3/01_list_comprehension.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/01_positional.pyc
Normal file
BIN
test/bytecode_2.3/01_positional.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/02_closure.pyc
Normal file
BIN
test/bytecode_2.3/02_closure.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/02_def.pyc
Normal file
BIN
test/bytecode_2.3/02_def.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/02_slice.pyc
Normal file
BIN
test/bytecode_2.3/02_slice.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/03_if_elif.pyc
Normal file
BIN
test/bytecode_2.3/03_if_elif.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/04_raise.pyc
Normal file
BIN
test/bytecode_2.3/04_raise.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/05-ret-or.pyc
Normal file
BIN
test/bytecode_2.3/05-ret-or.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/05_abc_class.pyc
Normal file
BIN
test/bytecode_2.3/05_abc_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/05_dup_top_two.pyc
Normal file
BIN
test/bytecode_2.3/05_dup_top_two.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/05_if.pyc
Normal file
BIN
test/bytecode_2.3/05_if.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/05_ifelse.pyc
Normal file
BIN
test/bytecode_2.3/05_ifelse.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/05_try_finally_pass.pyc
Normal file
BIN
test/bytecode_2.3/05_try_finally_pass.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/06_classbug.pyc
Normal file
BIN
test/bytecode_2.3/06_classbug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/06_for_break.pyc
Normal file
BIN
test/bytecode_2.3/06_for_break.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/06_list_ifnot.pyc
Normal file
BIN
test/bytecode_2.3/06_list_ifnot.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/06_list_ifnot_and.pyc
Normal file
BIN
test/bytecode_2.3/06_list_ifnot_and.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/06_return_bug.pyc
Normal file
BIN
test/bytecode_2.3/06_return_bug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/06_return_if.pyc
Normal file
BIN
test/bytecode_2.3/06_return_if.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/07_classderef.pyc
Normal file
BIN
test/bytecode_2.3/07_classderef.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/07_classparam.pyc
Normal file
BIN
test/bytecode_2.3/07_classparam.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/07_for_if_continue.pyc
Normal file
BIN
test/bytecode_2.3/07_for_if_continue.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/07_if_return_bug.pyc
Normal file
BIN
test/bytecode_2.3/07_if_return_bug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/07_try_pass.pyc
Normal file
BIN
test/bytecode_2.3/07_try_pass.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/09_class_closure.pyc
Normal file
BIN
test/bytecode_2.3/09_class_closure.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/09_whiletrue_bug.pyc
Normal file
BIN
test/bytecode_2.3/09_whiletrue_bug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/10_class.pyc
Normal file
BIN
test/bytecode_2.3/10_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/10_del.pyc
Normal file
BIN
test/bytecode_2.3/10_del.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/10_if_break_finally.pyc
Normal file
BIN
test/bytecode_2.3/10_if_break_finally.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/10_if_pass.pyc
Normal file
BIN
test/bytecode_2.3/10_if_pass.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/10_keyword.pyc
Normal file
BIN
test/bytecode_2.3/10_keyword.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/10_mixed_boolean.pyc
Normal file
BIN
test/bytecode_2.3/10_mixed_boolean.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/11-list-if.pyc
Normal file
BIN
test/bytecode_2.3/11-list-if.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/11_classbug.pyc
Normal file
BIN
test/bytecode_2.3/11_classbug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/11_classbug_subclass_fn.pyc
Normal file
BIN
test/bytecode_2.3/11_classbug_subclass_fn.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/11_return_val.pyc
Normal file
BIN
test/bytecode_2.3/11_return_val.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/15_assert.pyc
Normal file
BIN
test/bytecode_2.3/15_assert.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/15_for_if.pyc
Normal file
BIN
test/bytecode_2.3/15_for_if.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.3/20_try_except.pyc
Normal file
BIN
test/bytecode_2.3/20_try_except.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/00_assign.pyc
Normal file
BIN
test/bytecode_2.4/00_assign.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/00_import.pyc
Normal file
BIN
test/bytecode_2.4/00_import.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/00_pass.pyc
Normal file
BIN
test/bytecode_2.4/00_pass.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/01_boolean.pyc
Normal file
BIN
test/bytecode_2.4/01_boolean.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/01_class.pyc
Normal file
BIN
test/bytecode_2.4/01_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/01_fns.pyc
Normal file
BIN
test/bytecode_2.4/01_fns.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/01_list_comprehension.pyc
Normal file
BIN
test/bytecode_2.4/01_list_comprehension.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/01_positional.pyc
Normal file
BIN
test/bytecode_2.4/01_positional.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/02_closure.pyc
Normal file
BIN
test/bytecode_2.4/02_closure.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/02_complex.pyc
Normal file
BIN
test/bytecode_2.4/02_complex.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/02_def.pyc
Normal file
BIN
test/bytecode_2.4/02_def.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/02_slice.pyc
Normal file
BIN
test/bytecode_2.4/02_slice.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/03_if_elif.pyc
Normal file
BIN
test/bytecode_2.4/03_if_elif.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/03_map.pyc
Normal file
BIN
test/bytecode_2.4/03_map.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/04_raise.pyc
Normal file
BIN
test/bytecode_2.4/04_raise.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/05-ret-or.pyc
Normal file
BIN
test/bytecode_2.4/05-ret-or.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/05_abc_class.pyc
Normal file
BIN
test/bytecode_2.4/05_abc_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/05_closure_bug.pyc
Normal file
BIN
test/bytecode_2.4/05_closure_bug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/05_const_map.pyc
Normal file
BIN
test/bytecode_2.4/05_const_map.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/05_dup_top_two.pyc
Normal file
BIN
test/bytecode_2.4/05_dup_top_two.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.4/05_for_for.pyc
Normal file
BIN
test/bytecode_2.4/05_for_for.pyc
Normal file
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