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
272 Commits
release-3.
...
release-3.
Author | SHA1 | Date | |
---|---|---|---|
|
9415ad34ff | ||
|
476db9ad1d | ||
|
9ba0b1bad2 | ||
|
b7942bc5f2 | ||
|
3ac4f1ee61 | ||
|
55d2df04f7 | ||
|
6d529d3cee | ||
|
201e5b18b1 | ||
|
ac2bbfc65a | ||
|
3b8e6635e2 | ||
|
7e172b63d1 | ||
|
c01eb554ed | ||
|
d32e67891b | ||
|
78b8d1cd06 | ||
|
600e56b1d7 | ||
|
170504c518 | ||
|
e3d918df3d | ||
|
e7b62a722f | ||
|
92d63ac598 | ||
|
79bed3419f | ||
|
0353b74a7a | ||
|
67910e7d8e | ||
|
61fa4fe391 | ||
|
a8cdcc4d85 | ||
|
f0176add7a | ||
|
45c8d62e68 | ||
|
096563cf91 | ||
|
7fd21aa227 | ||
|
82bc294995 | ||
|
9d3e4a6660 | ||
|
7dfade1195 | ||
|
1df5aa0ef9 | ||
|
c06ba45991 | ||
|
7fab91eb4e | ||
|
c2181e3235 | ||
|
3695921364 | ||
|
d14193f219 | ||
|
94251cd294 | ||
|
a9515c7aab | ||
|
e5f3d803a8 | ||
|
e5ae70bea8 | ||
|
189605ea2c | ||
|
4c74bf1d9d | ||
|
c087bd785e | ||
|
80b68af2d3 | ||
|
24ccc16701 | ||
|
69714fb65a | ||
|
b94f98f8f7 | ||
|
f05b092983 | ||
|
76a66c3460 | ||
|
91224b2382 | ||
|
e76f1f107f | ||
|
2f8e063a99 | ||
|
15533c5e38 | ||
|
6511cc4dd4 | ||
|
fdf97a1cc0 | ||
|
24011bb0da | ||
|
4f61321c91 | ||
|
269f4f2e1b | ||
|
aab951280b | ||
|
f1e48fb60a | ||
|
c0022ed5b7 | ||
|
41a50b5e46 | ||
|
0154c87d63 | ||
|
c9c70103aa | ||
|
a18dc340ce | ||
|
037648577f | ||
|
cd62e54c88 | ||
|
ef9ccc3a8c | ||
|
c397bf6bda | ||
|
0aa41058a6 | ||
|
27f67e6fca | ||
|
6fcf49b214 | ||
|
49661b222e | ||
|
c481d97866 | ||
|
ab5303f504 | ||
|
6c6d62edb8 | ||
|
245deb0931 | ||
|
87b70cfd13 | ||
|
bbc7616e24 | ||
|
d5b7be59c5 | ||
|
7a4c11c3f4 | ||
|
9ef38285f4 | ||
|
5de8a33286 | ||
|
9e652f3fc6 | ||
|
9fa7b9ea53 | ||
|
1890aad660 | ||
|
7237658f1f | ||
|
fa6408d53b | ||
|
da57e2d416 | ||
|
9545541be7 | ||
|
98f969592c | ||
|
edbab038ca | ||
|
08cbf56eea | ||
|
8734608929 | ||
|
ab414d3d9c | ||
|
ede6eabc40 | ||
|
61e2b3b635 | ||
|
23fb07b1c9 | ||
|
1bbb72a6ce | ||
|
17361a9baa | ||
|
68821efdb0 | ||
|
e9ee671874 | ||
|
9593043432 | ||
|
1c95eb7b4e | ||
|
ff9ae4e792 | ||
|
d9eb5c5b09 | ||
|
e7b7de8842 | ||
|
3f26589bf1 | ||
|
30ce3a8bea | ||
|
341e17f62c | ||
|
b561b0090c | ||
|
ca41ea99f2 | ||
|
e3040c78a9 | ||
|
a556e96c22 | ||
|
e9c0d03b8b | ||
|
155fd06372 | ||
|
acff1b6ee0 | ||
|
1cd2d1e915 | ||
|
e2dec73a62 | ||
|
fad43feb3d | ||
|
96d8daeae9 | ||
|
8f6a1cb10b | ||
|
fc98bc972e | ||
|
007ba4a8f3 | ||
|
6b78677a74 | ||
|
ab1dba1536 | ||
|
254d0519bb | ||
|
120412f5a8 | ||
|
b54be24e14 | ||
|
535df1592e | ||
|
64ffa5f6ab | ||
|
9be4908c9c | ||
|
f18ce71e91 | ||
|
362a353e03 | ||
|
7d110f17bc | ||
|
04f4f3c25f | ||
|
1d5f4b0a05 | ||
|
dc3e6b31ca | ||
|
94a81a36b7 | ||
|
e568d68baa | ||
|
8c22d57979 | ||
|
bf0f5715a3 | ||
|
d90c44b454 | ||
|
9d807501af | ||
|
aa4416571b | ||
|
d38395334c | ||
|
516c7a0e9a | ||
|
681588f12d | ||
|
3500c49daf | ||
|
3d218c84b0 | ||
|
1afe1fd943 | ||
|
c5f8bbf32d | ||
|
6b36d14859 | ||
|
ccbe8a8e2b | ||
|
46c02bd352 | ||
|
30ba043000 | ||
|
1f0e5f27d5 | ||
|
75245ba38c | ||
|
4889916304 | ||
|
d1806edaad | ||
|
c968e31be8 | ||
|
c8870c6ed8 | ||
|
23180806b4 | ||
|
1f835d6237 | ||
|
3d072e29a6 | ||
|
74f01fbe33 | ||
|
710c950965 | ||
|
7aa6ff1d9b | ||
|
421c358f9d | ||
|
cfb4ad625f | ||
|
0b622a0ad8 | ||
|
8b7d5d3270 | ||
|
5c7fdf6e8f | ||
|
d2c8e4e12c | ||
|
626f690a5a | ||
|
39cef6a41b | ||
|
116fbb33e0 | ||
|
631940887f | ||
|
47beff57b2 | ||
|
7fb94176b1 | ||
|
2ae9cd7d08 | ||
|
1f663013ab | ||
|
e3c7afb94d | ||
|
0d327ab0ce | ||
|
35a60e0274 | ||
|
1b2b45642b | ||
|
28bfb453f5 | ||
|
df55ce3212 | ||
|
fcb4409e50 | ||
|
155031a7c4 | ||
|
c81b40b43b | ||
|
7fc7e083c3 | ||
|
d41a858f80 | ||
|
6dd0ad0810 | ||
|
9368b63a2f | ||
|
da06d83a87 | ||
|
6fb5808ff0 | ||
|
0c3db340fa | ||
|
925b6667d7 | ||
|
b8547346b7 | ||
|
0aa7a7c223 | ||
|
cf5445c202 | ||
|
bc8c38ee58 | ||
|
4cd81dab61 | ||
|
4f4b628842 | ||
|
ff50a7f37b | ||
|
85a49aec2f | ||
|
9f2c7352e7 | ||
|
e9cf370e11 | ||
|
90ac8a463d | ||
|
0e64111195 | ||
|
fd84325e4f | ||
|
ddc00edd42 | ||
|
4259963859 | ||
|
4905cc6bb0 | ||
|
f008b8f411 | ||
|
2e81ee5d2e | ||
|
50e59a37c1 | ||
|
5c8f93b735 | ||
|
88ef4baca8 | ||
|
6ab711baab | ||
|
9e05750537 | ||
|
5c662b334e | ||
|
56b2e17e30 | ||
|
94038151f4 | ||
|
b9281c79be | ||
|
51dec051df | ||
|
f5ac06013f | ||
|
06bbacef45 | ||
|
bfdc6529a0 | ||
|
1ed389ce61 | ||
|
19f2e1277b | ||
|
6290311143 | ||
|
947d619c77 | ||
|
908d313204 | ||
|
38dffa3290 | ||
|
c8747cc899 | ||
|
8a705a70f5 | ||
|
92d562e600 | ||
|
30756c52b2 | ||
|
74e280171b | ||
|
df0207eb90 | ||
|
07a8ae9541 | ||
|
5d6872bcd1 | ||
|
c03cdf1a49 | ||
|
01ad91b519 | ||
|
ccd42077c1 | ||
|
ca3f822c81 | ||
|
1896c40202 | ||
|
8278c72a6f | ||
|
3b0a5aab16 | ||
|
a74890d388 | ||
|
5d24367ef6 | ||
|
cad1325a90 | ||
|
61534ceed5 | ||
|
9f66694056 | ||
|
2bdfd76635 | ||
|
01f2f6578b | ||
|
02b1554da3 | ||
|
fac5d31f34 | ||
|
d42858cae4 | ||
|
9e815d8d79 | ||
|
def9e1676b | ||
|
35fcb1edf1 | ||
|
ffbce9cb77 | ||
|
dc1971f559 | ||
|
cef61904c7 | ||
|
778f92b6f4 | ||
|
a8260edded | ||
|
c662cb1df2 | ||
|
e809ade6e1 |
12
.gitignore
vendored
12
.gitignore
vendored
@@ -1,11 +1,15 @@
|
||||
*.pyo
|
||||
*.pyc
|
||||
*.pyo
|
||||
*_dis
|
||||
*~
|
||||
/.cache
|
||||
/.eggs
|
||||
/.hypothesis
|
||||
/.idea
|
||||
/.pytest_cache
|
||||
/.python-version
|
||||
/.tox
|
||||
/.venv*
|
||||
/README
|
||||
/__pkginfo__.pyc
|
||||
/dist
|
||||
@@ -14,9 +18,7 @@
|
||||
/tmp
|
||||
/uncompyle6.egg-info
|
||||
/unpyc
|
||||
ChangeLog
|
||||
__pycache__
|
||||
build
|
||||
/.venv*
|
||||
/.idea
|
||||
/.hypothesis
|
||||
ChangeLog
|
||||
nohup.out
|
||||
|
@@ -4,7 +4,7 @@ sudo: false
|
||||
|
||||
python:
|
||||
- '3.5'
|
||||
- '2.7.12'
|
||||
- '2.7'
|
||||
- '2.6'
|
||||
- '3.3'
|
||||
- '3.4'
|
||||
|
@@ -57,6 +57,19 @@ disassembler called `pydisasm`.
|
||||
|
||||
### Semantic equivalence vs. exact source code
|
||||
|
||||
Consider how Python compiles something like "(x*y) + 5". Early on
|
||||
Python creates an "abstract syntax tree" (AST) for this. And this is
|
||||
"abstract" in the sense that unimportant, redundant or unnecceary
|
||||
items have been removed. Here, this means that any notion that you
|
||||
wrote "x+y" in parenthesis is lost, since in this context they are
|
||||
unneeded. Also lost is the fact that the multiplication didn't have
|
||||
spaces around it while the addition did. It should not come as a
|
||||
surprise then that the bytecode which is derived from the AST also has
|
||||
no notion of such possible variation. Generally this kind of thing
|
||||
isn't noticed since the Python community has laid out a very rigid set
|
||||
of formatting guidelines; and it has largely beaten the community into
|
||||
compliance.
|
||||
|
||||
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.
|
||||
@@ -66,7 +79,7 @@ If the code emitted is semantically equivalent, then this isn't a bug.
|
||||
|
||||
For example the code might be
|
||||
|
||||
```
|
||||
```python
|
||||
if a:
|
||||
if b:
|
||||
x = 1
|
||||
@@ -74,7 +87,7 @@ if a:
|
||||
|
||||
and we might produce:
|
||||
|
||||
```
|
||||
```python
|
||||
if a and b:
|
||||
x = 1
|
||||
```
|
||||
@@ -87,24 +100,35 @@ else:
|
||||
|
||||
```
|
||||
|
||||
may come out as `elif`.
|
||||
may come out as `elif` or vice versa.
|
||||
|
||||
|
||||
As mentioned in the README, It is possible that Python changes what
|
||||
you write to be more efficient. For example, for:
|
||||
|
||||
|
||||
```
|
||||
```python
|
||||
if True:
|
||||
x = 5
|
||||
```
|
||||
|
||||
Python will generate code like:
|
||||
|
||||
```
|
||||
```python
|
||||
x = 5
|
||||
```
|
||||
|
||||
Even more extreme, if your code is:
|
||||
|
||||
```python
|
||||
if False:
|
||||
x = 1
|
||||
y = 2
|
||||
# ...
|
||||
```
|
||||
|
||||
Python will eliminate the entire "if" statement.
|
||||
|
||||
So just because the text isn't the same, does not
|
||||
necessarily mean there's a bug.
|
||||
|
||||
|
10
Makefile
10
Makefile
@@ -27,20 +27,18 @@ check:
|
||||
check-short: pytest
|
||||
$(MAKE) -C test check-short
|
||||
|
||||
# Note for 2.6 use <=3.0.1 see requirements-dev.txt
|
||||
#: Tests for Python 2.7, 3.3 and 3.4
|
||||
check-2.7 check-3.3 check-3.4: pytest
|
||||
check-2.6 check-2.7 check-3.3 check-3.4 check-3.5: pytest
|
||||
$(MAKE) -C test $@
|
||||
|
||||
#: Tests for Python 3.2 and 3.5 - pytest doesn't work here
|
||||
# Or rather 3.5 doesn't work not on Travis
|
||||
check-3.0 check-3.1 check-3.2 check-3.5 check-3.6:
|
||||
check-3.0 check-3.1 check-3.2 check-3.6:
|
||||
$(MAKE) -C test $@
|
||||
|
||||
check-3.7: pytest
|
||||
|
||||
#:Tests for Python 2.6 (doesn't have pytest)
|
||||
check-2.6:
|
||||
$(MAKE) -C test $@
|
||||
$(MAKE) -C test check
|
||||
|
||||
#:PyPy 2.6.1 PyPy 5.0.1, or PyPy 5.8.0-beta0
|
||||
# Skip for now
|
||||
|
85
NEWS
85
NEWS
@@ -1,3 +1,68 @@
|
||||
uncompyle6 3.2.3 2018-06-04 Michael Cohen flips and Fleetwood Redux
|
||||
|
||||
- Python 1.3 support 3.0 bug and
|
||||
- fix botched parameter ordering of 3.x in last release
|
||||
|
||||
uncompyle6 3.2.2 2018-06-04 When I'm 64
|
||||
|
||||
- Python 3.0 support and bug fixes
|
||||
|
||||
uncompyle6 3.2.1 2018-06-04 MF
|
||||
|
||||
- Python 1.4 and 1.5 bug fixes
|
||||
|
||||
uncompyle6 3.2.0 2018-05-19 Rocket Scientist
|
||||
|
||||
- Add rudimentary 1.4 support (still a bit buggy)
|
||||
- add --tree+ option to show formatting rule, when it is constant
|
||||
- Python 2.7.15candidate1 support (via xdis)
|
||||
- bug fixes, especially for 3.7 (but 2.7 and 3.6 and others as well)
|
||||
|
||||
uncompyle6 3.1.3 2018-04-16
|
||||
|
||||
- Add some Python 3.7 rules, such as for handling LOAD_METHOD (not complete)
|
||||
- Fix some fragment bugs
|
||||
- small doc changes
|
||||
|
||||
uncompyle6 3.1.2 2018-04-08 Eastern Orthodox Easter
|
||||
|
||||
- Python 3.x subclass and call parsing fixes
|
||||
- Allow/note running on Python 3.1
|
||||
- improve 3.5+ BUILD_MAP_UNPACK
|
||||
- DRY instruction building code between 2.x and 3.x
|
||||
- expand testing
|
||||
|
||||
uncompyle6 3.1.1 2018-04-01 Easter April Fool's
|
||||
|
||||
Jesus on Friday's New York Times puzzle: "I'm stuck on 2A"
|
||||
|
||||
- fill out 3.5+ BUILD_MAP_UNPACK (more work is needed)
|
||||
- fill out 3.4+ CALL_FUNCTION_... (more work is needed)
|
||||
- fill out 3.5 MAKE_FUNCTION (more work is needed)
|
||||
- reduce 3.5, 3.6 control-flow bugs
|
||||
- reduce ambiguity in rules that lead to long (exponential?) parses
|
||||
- limit/isolate some 2.6/2.7,3.x grammar rules
|
||||
- more runtime testing of decompiled code
|
||||
- more removal of parenthesis around calls via setting precidence
|
||||
|
||||
uncompyle6 3.1.0 2018-03-21 Equinox
|
||||
|
||||
- Add code_deparse_with_offset() fragment function.
|
||||
- Correct paramenter call fragment deparse_code()
|
||||
- Lots of 3.6, 3.x, and 2.7 bug fixes
|
||||
About 5% of 3.6 fail parsing now. But
|
||||
semantics still needs much to be desired.
|
||||
|
||||
uncompyle6 3.0.1 2018-02-17
|
||||
|
||||
- All Python 2.6.9 standard library files weakly verify
|
||||
- Many 3.6 fixes. 84% of the first 200 standard library files weakly compile.
|
||||
One more big push is needed to get the remaining to compile
|
||||
- Many decompilation fixes for other Python versions
|
||||
- Add more to the test framework
|
||||
- And more add tests target previous existing bugs more completely
|
||||
- sync recent license changes in metadata
|
||||
|
||||
uncompyle6 3.0.0 2018-02-17
|
||||
|
||||
- deparse_code() and lookalikes from the various semantic actions are
|
||||
@@ -10,7 +75,7 @@ uncompyle6 3.0.0 2018-02-17
|
||||
of jumps, and messes up the peephole-like analysis that is
|
||||
done for control flow since we don't have something better in place.
|
||||
- Code has been reorganized to be more instruction nametuple based where it
|
||||
has been more byecode array based. There was and still is code that had
|
||||
has been more bytecode array based. There was and still is code that had
|
||||
had magic numbers to advance instructions or to pick out operands.
|
||||
- Bug fixes in numerous other Python versions
|
||||
- Instruction display improved
|
||||
@@ -28,7 +93,7 @@ uncompyle6 2.16.0 2018-02-17
|
||||
- Better 2.7 end_if and COME_FROM determination
|
||||
- Fix up 3.6+ CALL_FUNCTION_EX
|
||||
- Misc pydisasm fixes
|
||||
- Wierd comprehension bug seen via new loctraceback
|
||||
- Weird comprehension bug seen via new loctraceback
|
||||
- Fix Python 3.5+ CALL_FUNCTION_VAR and BUILD_LIST_UNPACK in call; with this
|
||||
we can can handle 3.5+ f(a, b, *c, *d, *e) now
|
||||
|
||||
@@ -81,7 +146,7 @@ Decompilation bug fixes, mostly 3.6 and pre 2.7
|
||||
- limit pypy customization to pypy
|
||||
- Add addr fields in COME_FROMS
|
||||
- Allow use of full instructions in parser reduction routines
|
||||
- Reduce grammar in Pythion 3 by specialization more to specific
|
||||
- Reduce grammar in Python 3 by specialization more to specific
|
||||
Python versions
|
||||
- Match Python AST names more closely when possible
|
||||
|
||||
@@ -99,7 +164,7 @@ uncompyle6 2.14.0 2017-11-26 johnnybamazing
|
||||
and remove used grammar rules
|
||||
- Fix a number of bytecode decompile problems
|
||||
(many more remain)
|
||||
- Add stdlib/runtests.sh for even more rigourous testing
|
||||
- Add stdlib/runtests.sh for even more rigorous testing
|
||||
|
||||
uncompyle6 2.13.3 2017-11-13
|
||||
|
||||
@@ -123,7 +188,7 @@ Overall: better 3.6 decompiling and some much needed code refactoring and cleanu
|
||||
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
|
||||
- bug in 3.x language changes: import queue via import Queue
|
||||
- reinstate some bytecode tests since decompiling has gotten better
|
||||
- Revise how to report a bug
|
||||
|
||||
@@ -158,8 +223,8 @@ 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
|
||||
* unpin 3.5.1. xdis 3.5.4 has been release and fixes the problems we had. Use that.
|
||||
* some routines 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".
|
||||
@@ -255,9 +320,9 @@ uncompyle6 2.9.8 2016-12-16
|
||||
- fix bug in --verify option
|
||||
- DRY (a little) control-flow detection
|
||||
- fix syntax in tuples with one element
|
||||
- if AST rule inheritence in Python 2.5
|
||||
- if AST rule inheritance in Python 2.5
|
||||
- NAME_MODULE removal for Python <= 2.4
|
||||
- verifycall fixes for Python <= 2.4
|
||||
- verify call fixes for Python <= 2.4
|
||||
- more Python lint
|
||||
|
||||
uncompyle6 2.9.7 2016-12-16
|
||||
@@ -293,7 +358,7 @@ uncompyle6 2.9.6 2016-11-20
|
||||
in the results.
|
||||
- better control flow debugging output
|
||||
- Python 2 and 3 detect structure code is more similar
|
||||
- Handle Docstrings with embedded tiple quotes (""")
|
||||
- Handle Docstrings with embedded triple quotes (""")
|
||||
|
||||
uncompyle6 2.9.5 2016-11-13
|
||||
|
||||
|
100
README.rst
100
README.rst
@@ -1,4 +1,4 @@
|
||||
|buildstatus|
|
||||
|buildstatus| |Latest Version| |Supported Python Versions|
|
||||
|
||||
uncompyle6
|
||||
==========
|
||||
@@ -11,8 +11,9 @@ Introduction
|
||||
------------
|
||||
|
||||
*uncompyle6* translates Python bytecode back into equivalent Python
|
||||
source code. It accepts bytecodes from Python version 1.5, and 2.1 to
|
||||
3.7 or so, including PyPy bytecode and Dropbox's Python 2.5 bytecode.
|
||||
source code. It accepts bytecodes from Python version 1.3 to version
|
||||
3.7, spanning over 22 years of Python releases. We include Dropbox's
|
||||
Python 2.5 bytecode and some PyPy bytecode.
|
||||
|
||||
Why this?
|
||||
---------
|
||||
@@ -29,11 +30,11 @@ CPython bytecode decompilers is the ability to deparse just
|
||||
*fragments* of source code and give source-code information around a
|
||||
given bytecode offset.
|
||||
|
||||
I use the tree fragments to deparse fragments of code inside my
|
||||
trepan_ debuggers_. For that, bytecode offsets are recorded and
|
||||
associated with fragments of the source code. This purpose, although
|
||||
compatible with the original intention, is yet a little bit different.
|
||||
See this_ for more information.
|
||||
I use the tree fragments to deparse fragments of code *at run time*
|
||||
inside my trepan_ debuggers_. For that, bytecode offsets are recorded
|
||||
and associated with fragments of the source code. This purpose,
|
||||
although compatible with the original intention, is yet a little bit
|
||||
different. See this_ for more information.
|
||||
|
||||
Python fragment deparsing given an instruction offset is useful in
|
||||
showing stack traces and can be encorporated into any program that
|
||||
@@ -52,8 +53,17 @@ 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.
|
||||
This demonstrably does the best in decompiling Python across all
|
||||
Python versions. And even when there is another project that only
|
||||
provides decompilation for subset of Python versions, we generally do
|
||||
demonstrably better for those as well.
|
||||
|
||||
How can we tell? By taking Python bytecode that comes distributed with
|
||||
that version of Python and decompiling these. Among those that
|
||||
successfully decompile, we can then make sure the resulting programs
|
||||
are syntactically correct by running the Python interpreter for that
|
||||
bytecode version. Finally, in cases where the program has a test for
|
||||
itself, we can run the check on the decompiled code.
|
||||
|
||||
We are serious about testing, and use automated processes to find
|
||||
bugs. In the issue trackers for other decompilers, you will find a
|
||||
@@ -66,7 +76,7 @@ Requirements
|
||||
The code here can be run on Python versions 2.6 or later, PyPy 3-2.4,
|
||||
or PyPy-5.0.1. Python versions 2.4-2.7 are supported in the
|
||||
python-2.4 branch. The bytecode files it can read have been tested on
|
||||
Python bytecodes from versions 1.5, 2.1-2.7, and 3.0-3.6 and the
|
||||
Python bytecodes from versions 1.4, 2.1-2.7, and 3.0-3.6 and the
|
||||
above-mentioned PyPy versions.
|
||||
|
||||
Installation
|
||||
@@ -136,26 +146,26 @@ All of the Python decompilers that I have looked at have problems
|
||||
decompiling Python's control flow. In some cases we can detect an
|
||||
erroneous decompilation and report that.
|
||||
|
||||
*Verification* is the process of decompiling bytecode, compiling with
|
||||
a Python for that bytecode version, and then comparing the bytecode
|
||||
produced by the decompiled/compiled program. Some allowance is made
|
||||
for inessential differences. But other semantically equivalent
|
||||
differences are not caught. For example ``1 and 0`` is decompiled to
|
||||
the equivalent ``0``; remnants of the first true evaluation (1) is
|
||||
lost when Python compiles this. When Python next compiles ``0`` the
|
||||
resulting code is simpler.
|
||||
In older versions of Python it was possible to verify bytecode by
|
||||
decompiling bytecode, and then compiling using the Python interpreter
|
||||
for that bytecode version. Having done this the bytecode produced
|
||||
could be compared with the original bytecode. However as Python's code
|
||||
generation got better, this is no longer feasible.
|
||||
|
||||
*Weak Verification*
|
||||
on the other hand doesn't check bytecode for equivalence but does
|
||||
check to see if the resulting decompiled source is a valid Python
|
||||
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.
|
||||
There verification that we use that doesn't check bytecode for
|
||||
equivalence but does check to see if the resulting decompiled source
|
||||
is a valid Python 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 was used in creating 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.
|
||||
There are however an interesting class of these programs that is
|
||||
readily available give stronger verification: those programs that
|
||||
when run check some computation, or even better themselves.
|
||||
|
||||
And already Python has a set of programs like this: the test suite
|
||||
for the standard library that comes with Python. We have some
|
||||
code in `test/stdlib` to facilitate this kind of checking.
|
||||
|
||||
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
|
||||
@@ -165,19 +175,21 @@ that era was minimal)
|
||||
|
||||
There is some work to do on the lower end Python versions which is
|
||||
more difficult for us to handle since we don't have a Python
|
||||
interpreter for versions 1.5, 1.6, and 2.0.
|
||||
interpreter for versions 1.6, and 2.0.
|
||||
|
||||
In the Python 3 series, Python support is is strongest around 3.4 or
|
||||
3.3 and drops off as you move further away from those versions. Python
|
||||
3.6 changes things drastically by using word codes rather than byte
|
||||
codes. As a result, the jump offset field in a jump instruction
|
||||
argument has been reduced. This makes the `EXTENDED_ARG` instructions
|
||||
are now more prevalent in jump instruction; previously they had been
|
||||
rare. Perhaps to compensate for the additional `EXTENDED_ARG`
|
||||
instructions, additional jump optimization has been added. So in sum
|
||||
handling control flow by ad hoc means as is currently done is worse.
|
||||
3.0 is weird in that it in some ways resembles 2.6 more than it does
|
||||
3.1 or 2.7. Python 3.6 changes things drastically by using word codes
|
||||
rather than byte codes. As a result, the jump offset field in a jump
|
||||
instruction argument has been reduced. This makes the `EXTENDED_ARG`
|
||||
instructions are now more prevalent in jump instruction; previously
|
||||
they had been rare. Perhaps to compensate for the additional
|
||||
`EXTENDED_ARG` instructions, additional jump optimization has been
|
||||
added. So in sum handling control flow by ad hoc means as is currently
|
||||
done is worse.
|
||||
|
||||
Also, between Python 3.5, 3.6 and 3.7 there have been major changes to the
|
||||
Between Python 3.5, 3.6 and 3.7 there have been major changes to the
|
||||
`MAKE_FUNCTION` and `CALL_FUNCTION` instructions.
|
||||
|
||||
Currently not all Python magic numbers are supported. Specifically in
|
||||
@@ -203,11 +215,12 @@ There is lots to do, so please dig in and help.
|
||||
See Also
|
||||
--------
|
||||
|
||||
* https://github.com/zrax/pycdc : supports all versions of Python and is written in C++. Support for later Python 3 versions is a bit lacking though.
|
||||
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique than what is used here.
|
||||
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Includes some fixes like supporting function annotations
|
||||
* The HISTORY_ file.
|
||||
* https://github.com/zrax/pycdc : purports to support all versions of Python. It is written in C++ and is most accurate for Python versions around 2.7 and 3.3 when the code was more actively developed. Accuracy for more recent versions of Python 3 and early versions of Python are especially lacking. See its `issue tracker <https://github.com/zrax/pycdc/issues>`_ for details. Currently lightly maintained.
|
||||
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique than what is used here. Currently unmaintained.
|
||||
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Includes some fixes like supporting function annotations. Currently unmaintained.
|
||||
* https://github.com/wibiti/uncompyle2 : supports Python 2.7 only, but does that fairly well. There are situtations where `uncompyle6` results are incorrect while `uncompyle2` results are not, but more often uncompyle6 is correct when uncompyle2 is not. Because `uncompyle6` adheres to accuracy over idiomatic Python, `uncompyle2` can produce more natural-looking code when it is correct. Currently `uncompyle2` is lightly maintained. See its issue `tracker <https://github.com/wibiti/uncompyle2/issues>`_ for more details
|
||||
* `How to report a bug <https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>`_
|
||||
* The HISTORY_ file.
|
||||
* 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
|
||||
@@ -225,3 +238,6 @@ See Also
|
||||
.. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84
|
||||
.. _Deobfuscator: https://github.com/extremecoders-re/PjOrion-Deobfuscator
|
||||
.. _Py2EXE: https://en.wikipedia.org/wiki/Py2exe
|
||||
.. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/uncompyle6.svg
|
||||
.. |Latest Version| image:: https://badge.fury.io/py/uncompyle6.svg
|
||||
:target: https://badge.fury.io/py/uncompyle6
|
||||
|
@@ -35,6 +35,7 @@ classifiers = ['Development Status :: 5 - Production/Stable',
|
||||
'Programming Language :: Python :: 2.5',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3.0',
|
||||
'Programming Language :: Python :: 3.1',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
@@ -56,9 +57,9 @@ entry_points = {
|
||||
]}
|
||||
ftp_url = None
|
||||
install_requires = ['spark-parser >= 1.8.5, < 1.9.0',
|
||||
'xdis >= 3.6.9, < 3.7.0', 'six']
|
||||
'xdis >= 3.8.4, < 3.9.0']
|
||||
|
||||
license = 'MIT'
|
||||
license = 'GPL3'
|
||||
mailing_list = 'python-debugger@googlegroups.com'
|
||||
modname = 'uncompyle6'
|
||||
py_modules = None
|
||||
|
@@ -16,6 +16,7 @@ if ! source ./setup-master.sh ; then
|
||||
fi
|
||||
cd ..
|
||||
for version in $PYVERSIONS; do
|
||||
echo --- $version ---
|
||||
if ! pyenv local $version ; then
|
||||
exit $?
|
||||
fi
|
||||
@@ -23,4 +24,5 @@ for version in $PYVERSIONS; do
|
||||
if ! make check; then
|
||||
exit $?
|
||||
fi
|
||||
echo === $version ===
|
||||
done
|
||||
|
@@ -15,6 +15,7 @@ fi
|
||||
|
||||
cd ..
|
||||
for version in $PYVERSIONS; do
|
||||
echo --- $version ---
|
||||
if ! pyenv local $version ; then
|
||||
exit $?
|
||||
fi
|
||||
@@ -22,4 +23,5 @@ for version in $PYVERSIONS; do
|
||||
if ! make check ; then
|
||||
exit $?
|
||||
fi
|
||||
echo === $version ===
|
||||
done
|
||||
|
15
admin-tools/pycdc-runtests.sh
Executable file
15
admin-tools/pycdc-runtests.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
# Use pycdc to run our test/bytecode* test suite
|
||||
bs=${BASH_SOURCE[0]}
|
||||
testdir=$(dirname $bs)/../test
|
||||
fulldir=$(readlink -f $testdir)
|
||||
cd $fulldir
|
||||
for dir in bytecode_* ; do
|
||||
echo ========= $dir ================
|
||||
cd $fulldir/$dir
|
||||
for file in *.pyc; do
|
||||
if ! pycdc $file > /dev/null ; then
|
||||
echo ----- $dir/$file ------
|
||||
fi
|
||||
done
|
||||
done
|
@@ -5,4 +5,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
|
||||
echo "This script should be *sourced* rather than run directly through bash"
|
||||
exit 1
|
||||
fi
|
||||
export PYVERSIONS='3.5.3 3.6.3 2.6.9 3.3.6 2.7.14 3.4.2'
|
||||
export PYVERSIONS='3.5.5 3.6.5 2.6.9 3.3.7 2.7.14 3.2.6 3.1.5 3.4.8'
|
||||
|
28
admin-tools/run-pyenvlib-test-all.sh
Executable file
28
admin-tools/run-pyenvlib-test-all.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
# Runs test_pyenvlib.test on all versions of Python master.
|
||||
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 ../test
|
||||
for version in $PYVERSIONS; do
|
||||
if ! pyenv local $version ; then
|
||||
exit $?
|
||||
fi
|
||||
echo "====== Running test_pyenvlib.py on $version ====="
|
||||
if ! python ./test_pyenvlib.py --weak-verify --max 800 --${version} ; then
|
||||
exit $?
|
||||
fi
|
||||
echo "------ Done test_pyenvlib.py on $version -----"
|
||||
done
|
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
PYTHON_VERSION=3.6.3
|
||||
PYTHON_VERSION=3.6.5
|
||||
|
||||
# FIXME put some of the below in a common routine
|
||||
function finish {
|
||||
|
32
admin-tools/uncompyle2-runtests.sh
Executable file
32
admin-tools/uncompyle2-runtests.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
# Use pycdc to run our test/bytecode_2.7* test suite
|
||||
bs=${BASH_SOURCE[0]}
|
||||
topdir=$(dirname $bs)/..
|
||||
(cd $topdir && pyenv local 2.7.14)
|
||||
testdir=$topdir/test
|
||||
fulldir=$(readlink -f $testdir)
|
||||
cd $fulldir
|
||||
|
||||
for bytecode in bytecode_2.7/*.pyc ; do
|
||||
echo $bytecode
|
||||
uncompyle2 $bytecode > /dev/null
|
||||
echo ================ $bytecode rc: $? ==============
|
||||
done
|
||||
|
||||
tmpdir=/tmp/test-2.7
|
||||
( cd bytecode_2.7_run &&
|
||||
mkdir $tmpdir || true
|
||||
for bytecode in *.pyc ; do
|
||||
shortname=$(basename $bytecode .pyc)
|
||||
echo $bytecode
|
||||
py_file=${tmpdir}/${shortname}.py
|
||||
typeset -i rc=0
|
||||
uncompyle2 $bytecode > $py_file
|
||||
rc=$?
|
||||
if (( rc == 0 )); then
|
||||
python $py_file
|
||||
rc=$?
|
||||
fi
|
||||
echo ================ $bytecode rc: $rc ==============
|
||||
done
|
||||
)
|
@@ -47,7 +47,7 @@ install:
|
||||
|
||||
# Upgrade to the latest version of pip to avoid it displaying warnings
|
||||
# about it being out of date.
|
||||
- "pip install --disable-pip-version-check --user --upgrade pip"
|
||||
- "%PYTHON%\\python.exe -m pip install --disable-pip-version-check --user --upgrade pip"
|
||||
|
||||
# Install the build dependencies of the project. If some dependencies contain
|
||||
# compiled extensions and are not provided as pre-built wheel packages,
|
||||
|
@@ -6,6 +6,7 @@ machine:
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
- pip install --upgrade setuptools
|
||||
- pip install -e .
|
||||
- pip install pytest==3.2.5 hypothesis
|
||||
test:
|
||||
|
@@ -1,8 +1,6 @@
|
||||
#!/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:
|
||||
if slotstate is not None:
|
||||
@@ -24,16 +22,8 @@ def bug_loop(disassemble, tb=None):
|
||||
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)
|
||||
bytecode = Bytecode(code, scan.opc)
|
||||
scan.build_lines_data(code, n)
|
||||
scan.insts = list(bytecode)
|
||||
scan.offset2inst_index = {}
|
||||
for i, inst in enumerate(scan.insts):
|
||||
scan.offset2inst_index[inst.offset] = i
|
||||
scan.build_prev_op(n)
|
||||
scan.build_instructions(code)
|
||||
fjt = scan.find_jump_targets(False)
|
||||
|
||||
## FIXME: the data below is wrong.
|
||||
@@ -48,14 +38,7 @@ def test_if_in_for():
|
||||
# {'start': 62, 'end': 63, 'type': 'for-else'}]
|
||||
|
||||
code = bug_loop.__code__
|
||||
n = scan.setup_code(code)
|
||||
bytecode = Bytecode(code, scan.opc)
|
||||
scan.build_lines_data(code, n)
|
||||
scan.insts = list(bytecode)
|
||||
scan.build_prev_op(n)
|
||||
scan.offset2inst_index = {}
|
||||
for i, inst in enumerate(scan.insts):
|
||||
scan.offset2inst_index[inst.offset] = i
|
||||
scan.build_instructions(code)
|
||||
fjt = scan.find_jump_targets(False)
|
||||
assert{64: [42], 67: [42, 42], 42: [16, 41], 19: [6]} == fjt
|
||||
assert scan.structs == [
|
||||
@@ -69,14 +52,7 @@ 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.lines = scan.build_lines_data(code)
|
||||
scan.build_prev_op()
|
||||
scan.insts = list(bytecode)
|
||||
scan.offset2inst_index = {}
|
||||
for i, inst in enumerate(scan.insts):
|
||||
scan.offset2inst_index[inst.offset] = i
|
||||
scan.build_instructions(code)
|
||||
fjt = scan.find_jump_targets(False)
|
||||
assert {69: [66], 63: [18]} == fjt
|
||||
assert scan.structs == \
|
||||
@@ -86,5 +62,6 @@ def test_if_in_for():
|
||||
{'end': 59, 'type': 'for-loop', 'start': 31},
|
||||
{'end': 63, 'type': 'for-else', 'start': 62}]
|
||||
else:
|
||||
assert True, "FIXME: should note fixed"
|
||||
print("FIXME: should fix for %s" % PYTHON_VERSION)
|
||||
assert True
|
||||
return
|
||||
|
@@ -1,150 +1,154 @@
|
||||
# std
|
||||
import os
|
||||
# test
|
||||
import pytest
|
||||
import hypothesis
|
||||
from hypothesis import strategies as st
|
||||
# uncompyle6
|
||||
from uncompyle6 import PYTHON_VERSION, deparse_code
|
||||
import pytest
|
||||
pytestmark = pytest.mark.skipif(PYTHON_VERSION <= 2.6,
|
||||
reason='hypothesis needs 2.7 or later')
|
||||
if PYTHON_VERSION > 2.6:
|
||||
|
||||
import hypothesis
|
||||
from hypothesis import strategies as st
|
||||
|
||||
# uncompyle6
|
||||
|
||||
|
||||
@st.composite
|
||||
def expressions(draw):
|
||||
# todo : would be nice to generate expressions using hypothesis however
|
||||
# this is pretty involved so for now just use a corpus of expressions
|
||||
# from which to select.
|
||||
return draw(st.sampled_from((
|
||||
'abc',
|
||||
'len(items)',
|
||||
'x + 1',
|
||||
'lineno',
|
||||
'container',
|
||||
'self.attribute',
|
||||
'self.method()',
|
||||
# These expressions are failing, I think these are control
|
||||
# flow problems rather than problems with FORMAT_VALUE,
|
||||
# however I need to confirm this...
|
||||
#'sorted(items, key=lambda x: x.name)',
|
||||
#'func(*args, **kwargs)',
|
||||
#'text or default',
|
||||
#'43 if life_the_universe and everything else None'
|
||||
)))
|
||||
@st.composite
|
||||
def expressions(draw):
|
||||
# todo : would be nice to generate expressions using hypothesis however
|
||||
# this is pretty involved so for now just use a corpus of expressions
|
||||
# from which to select.
|
||||
return draw(st.sampled_from((
|
||||
'abc',
|
||||
'len(items)',
|
||||
'x + 1',
|
||||
'lineno',
|
||||
'container',
|
||||
'self.attribute',
|
||||
'self.method()',
|
||||
# These expressions are failing, I think these are control
|
||||
# flow problems rather than problems with FORMAT_VALUE,
|
||||
# however I need to confirm this...
|
||||
#'sorted(items, key=lambda x: x.name)',
|
||||
#'func(*args, **kwargs)',
|
||||
#'text or default',
|
||||
#'43 if life_the_universe and everything else None'
|
||||
)))
|
||||
|
||||
|
||||
@st.composite
|
||||
def format_specifiers(draw):
|
||||
"""
|
||||
Generate a valid format specifier using the rules:
|
||||
@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" | "%"
|
||||
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
|
||||
See https://docs.python.org/2/library/string.html
|
||||
|
||||
:param draw: Let hypothesis draw from other strategies.
|
||||
: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 ''
|
||||
: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'
|
||||
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 ''
|
||||
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)
|
||||
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 ''
|
||||
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 = ''
|
||||
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_,))
|
||||
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
|
||||
@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.
|
||||
:param draw: Let hypothsis draw from other strategies.
|
||||
|
||||
:return: A valid f-string.
|
||||
"""
|
||||
character_strategy = st.characters(
|
||||
blacklist_characters='\r\n\'\\s{}',
|
||||
min_codepoint=1,
|
||||
max_codepoint=1000,
|
||||
)
|
||||
is_raw = draw(st.booleans())
|
||||
integer_strategy = st.integers(min_value=0, max_value=3)
|
||||
expression_count = draw(integer_strategy)
|
||||
content = []
|
||||
for _ in range(expression_count):
|
||||
expression = draw(expressions())
|
||||
conversion = draw(st.sampled_from(('', '!s', '!r', '!a',)))
|
||||
has_specifier = draw(st.booleans())
|
||||
specifier = ':' + draw(format_specifiers()) if has_specifier else ''
|
||||
content.append('{{{}{}}}'.format(expression, conversion, specifier))
|
||||
content.append(draw(st.text(character_strategy)))
|
||||
content = ''.join(content)
|
||||
return "f{}'{}'".format('r' if is_raw else '', content)
|
||||
:return: A valid f-string.
|
||||
"""
|
||||
character_strategy = st.characters(
|
||||
blacklist_characters='\r\n\'\\s{}',
|
||||
min_codepoint=1,
|
||||
max_codepoint=1000,
|
||||
)
|
||||
is_raw = draw(st.booleans())
|
||||
integer_strategy = st.integers(min_value=0, max_value=3)
|
||||
expression_count = draw(integer_strategy)
|
||||
content = []
|
||||
for _ in range(expression_count):
|
||||
expression = draw(expressions())
|
||||
conversion = draw(st.sampled_from(('', '!s', '!r', '!a',)))
|
||||
has_specifier = draw(st.booleans())
|
||||
specifier = ':' + draw(format_specifiers()) if has_specifier else ''
|
||||
content.append('{{{}{}}}'.format(expression, conversion, specifier))
|
||||
content.append(draw(st.text(character_strategy)))
|
||||
content = ''.join(content)
|
||||
return "f{}'{}'".format('r' if is_raw else '', content)
|
||||
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need at least python 3.6')
|
||||
@hypothesis.given(format_specifiers())
|
||||
def test_format_specifiers(format_specifier):
|
||||
"""Verify that format_specifiers generates valid specifiers"""
|
||||
try:
|
||||
exec('"{:' + format_specifier + '}".format(0)')
|
||||
except ValueError as e:
|
||||
if 'Unknown format code' not in str(e):
|
||||
raise
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need at least python 3.6')
|
||||
@hypothesis.given(format_specifiers())
|
||||
def test_format_specifiers(format_specifier):
|
||||
"""Verify that format_specifiers generates valid specifiers"""
|
||||
try:
|
||||
exec('"{:' + format_specifier + '}".format(0)')
|
||||
except ValueError as e:
|
||||
if 'Unknown format code' not in str(e):
|
||||
raise
|
||||
|
||||
|
||||
def run_test(text):
|
||||
hypothesis.assume(len(text))
|
||||
hypothesis.assume("f'{" in text)
|
||||
expr = text + '\n'
|
||||
code = compile(expr, '<string>', 'single')
|
||||
deparsed = deparse_code(PYTHON_VERSION, code, compile_mode='single')
|
||||
recompiled = compile(deparsed.text, '<string>', 'single')
|
||||
if recompiled != code:
|
||||
assert 'dis(' + deparsed.text.strip('\n') + ')' == 'dis(' + expr.strip('\n') + ')'
|
||||
def run_test(text):
|
||||
hypothesis.assume(len(text))
|
||||
hypothesis.assume("f'{" in text)
|
||||
expr = text + '\n'
|
||||
code = compile(expr, '<string>', 'single')
|
||||
deparsed = deparse_code(PYTHON_VERSION, code, compile_mode='single')
|
||||
recompiled = compile(deparsed.text, '<string>', 'single')
|
||||
if recompiled != code:
|
||||
assert 'dis(' + deparsed.text.strip('\n') + ')' == 'dis(' + expr.strip('\n') + ')'
|
||||
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need at least python 3.6')
|
||||
@hypothesis.given(fstrings())
|
||||
def test_uncompyle_fstring(fstring):
|
||||
"""Verify uncompyling fstring bytecode"""
|
||||
run_test(fstring)
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need at least python 3.6')
|
||||
@hypothesis.given(fstrings())
|
||||
def test_uncompyle_fstring(fstring):
|
||||
"""Verify uncompyling fstring bytecode"""
|
||||
run_test(fstring)
|
||||
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need at least python 3.6')
|
||||
@pytest.mark.parametrize('fstring', [
|
||||
"f'{abc}{abc!s}'",
|
||||
"f'{abc}0'",
|
||||
])
|
||||
def test_uncompyle_direct(fstring):
|
||||
"""useful for debugging"""
|
||||
run_test(fstring)
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 3.6, reason='need at least python 3.6')
|
||||
@pytest.mark.parametrize('fstring', [
|
||||
"f'{abc}{abc!s}'",
|
||||
"f'{abc}0'",
|
||||
])
|
||||
def test_uncompyle_direct(fstring):
|
||||
"""useful for debugging"""
|
||||
run_test(fstring)
|
||||
|
@@ -1,175 +1,185 @@
|
||||
# std
|
||||
import string
|
||||
# 3rd party
|
||||
from hypothesis import given, assume, example, settings, strategies as st
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
import pytest
|
||||
# uncompyle
|
||||
from validate import validate_uncompyle
|
||||
from test_fstring import expressions
|
||||
pytestmark = pytest.mark.skip(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
|
||||
if PYTHON_VERSION > 2.6:
|
||||
from hypothesis import given, assume, example, settings, strategies as st
|
||||
from validate import validate_uncompyle
|
||||
from test_fstring import expressions
|
||||
|
||||
alpha = st.sampled_from(string.ascii_lowercase)
|
||||
numbers = st.sampled_from(string.digits)
|
||||
alphanum = st.sampled_from(string.ascii_lowercase + string.digits)
|
||||
|
||||
|
||||
alpha = st.sampled_from(string.ascii_lowercase)
|
||||
numbers = st.sampled_from(string.digits)
|
||||
alphanum = st.sampled_from(string.ascii_lowercase + string.digits)
|
||||
@st.composite
|
||||
def function_calls(draw,
|
||||
min_keyword_args=0, max_keyword_args=5,
|
||||
min_positional_args=0, max_positional_args=5,
|
||||
min_star_args=0, max_star_args=1,
|
||||
min_double_star_args=0, max_double_star_args=1):
|
||||
"""
|
||||
Strategy factory for generating function calls.
|
||||
|
||||
:param draw: Callable which draws examples from other strategies.
|
||||
|
||||
:return: The function call text.
|
||||
"""
|
||||
st_positional_args = st.lists(
|
||||
alpha,
|
||||
min_size=min_positional_args,
|
||||
max_size=max_positional_args
|
||||
)
|
||||
st_keyword_args = st.lists(
|
||||
alpha,
|
||||
min_size=min_keyword_args,
|
||||
max_size=max_keyword_args
|
||||
)
|
||||
st_star_args = st.lists(
|
||||
alpha,
|
||||
min_size=min_star_args,
|
||||
max_size=max_star_args
|
||||
)
|
||||
st_double_star_args = st.lists(
|
||||
alpha,
|
||||
min_size=min_double_star_args,
|
||||
max_size=max_double_star_args
|
||||
)
|
||||
|
||||
positional_args = draw(st_positional_args)
|
||||
keyword_args = draw(st_keyword_args)
|
||||
st_values = st.lists(
|
||||
expressions(),
|
||||
min_size=len(keyword_args),
|
||||
max_size=len(keyword_args)
|
||||
)
|
||||
keyword_args = [
|
||||
x + '=' + e
|
||||
for x, e in
|
||||
zip(keyword_args, draw(st_values))
|
||||
]
|
||||
star_args = ['*' + x for x in draw(st_star_args)]
|
||||
double_star_args = ['**' + x for x in draw(st_double_star_args)]
|
||||
|
||||
arguments = positional_args + keyword_args + star_args + double_star_args
|
||||
draw(st.randoms()).shuffle(arguments)
|
||||
arguments = ','.join(arguments)
|
||||
|
||||
function_call = 'fn({arguments})'.format(arguments=arguments)
|
||||
try:
|
||||
# TODO: Figure out the exact rules for ordering of positional, keyword,
|
||||
# star args, double star args and in which versions the various
|
||||
# types of arguments are supported so we don't need to check that the
|
||||
# expression compiles like this.
|
||||
compile(function_call, '<string>', 'single')
|
||||
except:
|
||||
assume(False)
|
||||
return function_call
|
||||
|
||||
|
||||
@st.composite
|
||||
def function_calls(draw,
|
||||
min_keyword_args=0, max_keyword_args=5,
|
||||
min_positional_args=0, max_positional_args=5,
|
||||
min_star_args=0, max_star_args=1,
|
||||
min_double_star_args=0, max_double_star_args=1):
|
||||
"""
|
||||
Strategy factory for generating function calls.
|
||||
def test_function_no_args():
|
||||
validate_uncompyle("fn()")
|
||||
|
||||
:param draw: Callable which draws examples from other strategies.
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
def isolated_function_calls(which):
|
||||
"""
|
||||
Returns a strategy for generating function calls, but isolated to
|
||||
particular types of arguments, for example only positional arguments.
|
||||
|
||||
:return: The function call text.
|
||||
"""
|
||||
st_positional_args = st.lists(
|
||||
alpha,
|
||||
min_size=min_positional_args,
|
||||
max_size=max_positional_args
|
||||
)
|
||||
st_keyword_args = st.lists(
|
||||
alpha,
|
||||
min_size=min_keyword_args,
|
||||
max_size=max_keyword_args
|
||||
)
|
||||
st_star_args = st.lists(
|
||||
alpha,
|
||||
min_size=min_star_args,
|
||||
max_size=max_star_args
|
||||
)
|
||||
st_double_star_args = st.lists(
|
||||
alpha,
|
||||
min_size=min_double_star_args,
|
||||
max_size=max_double_star_args
|
||||
)
|
||||
This can help reason about debugging errors in specific types of function
|
||||
calls.
|
||||
|
||||
positional_args = draw(st_positional_args)
|
||||
keyword_args = draw(st_keyword_args)
|
||||
st_values = st.lists(
|
||||
expressions(),
|
||||
min_size=len(keyword_args),
|
||||
max_size=len(keyword_args)
|
||||
)
|
||||
keyword_args = [
|
||||
x + '=' + e
|
||||
for x, e in
|
||||
zip(keyword_args, draw(st_values))
|
||||
]
|
||||
star_args = ['*' + x for x in draw(st_star_args)]
|
||||
double_star_args = ['**' + x for x in draw(st_double_star_args)]
|
||||
:param which: One of 'keyword', 'positional', 'star', 'double_star'
|
||||
|
||||
arguments = positional_args + keyword_args + star_args + double_star_args
|
||||
draw(st.randoms()).shuffle(arguments)
|
||||
arguments = ','.join(arguments)
|
||||
|
||||
function_call = 'fn({arguments})'.format(arguments=arguments)
|
||||
try:
|
||||
# TODO: Figure out the exact rules for ordering of positional, keyword,
|
||||
# star args, double star args and in which versions the various
|
||||
# types of arguments are supported so we don't need to check that the
|
||||
# expression compiles like this.
|
||||
compile(function_call, '<string>', 'single')
|
||||
except:
|
||||
assume(False)
|
||||
return function_call
|
||||
:return: Strategy for generating an function call isolated to specific
|
||||
argument types.
|
||||
"""
|
||||
kwargs = dict(
|
||||
max_keyword_args=0,
|
||||
max_positional_args=0,
|
||||
max_star_args=0,
|
||||
max_double_star_args=0,
|
||||
)
|
||||
kwargs['_'.join(('min', which, 'args'))] = 1
|
||||
kwargs['_'.join(('max', which, 'args'))] = 5 if 'star' not in which else 1
|
||||
return function_calls(**kwargs)
|
||||
|
||||
|
||||
def test_function_no_args():
|
||||
validate_uncompyle("fn()")
|
||||
with settings(max_examples=25):
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
@given(isolated_function_calls('positional'))
|
||||
@example("fn(0)")
|
||||
def test_function_positional_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
@given(isolated_function_calls('keyword'))
|
||||
@example("fn(a=0)")
|
||||
def test_function_call_keyword_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
@given(isolated_function_calls('star'))
|
||||
@example("fn(*items)")
|
||||
def test_function_call_star_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
@given(isolated_function_calls('double_star'))
|
||||
@example("fn(**{})")
|
||||
def test_function_call_double_star_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
|
||||
def isolated_function_calls(which):
|
||||
"""
|
||||
Returns a strategy for generating function calls, but isolated to
|
||||
particular types of arguments, for example only positional arguments.
|
||||
|
||||
This can help reason about debugging errors in specific types of function
|
||||
calls.
|
||||
|
||||
:param which: One of 'keyword', 'positional', 'star', 'double_star'
|
||||
|
||||
:return: Strategy for generating an function call isolated to specific
|
||||
argument types.
|
||||
"""
|
||||
kwargs = dict(
|
||||
max_keyword_args=0,
|
||||
max_positional_args=0,
|
||||
max_star_args=0,
|
||||
max_double_star_args=0,
|
||||
)
|
||||
kwargs['_'.join(('min', which, 'args'))] = 1
|
||||
kwargs['_'.join(('max', which, 'args'))] = 5 if 'star' not in which else 1
|
||||
return function_calls(**kwargs)
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_CONST_KEY_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(w=0,m=0,**v)")
|
||||
|
||||
|
||||
with settings(max_examples=25):
|
||||
|
||||
@given(isolated_function_calls('positional'))
|
||||
@example("fn(0)")
|
||||
def test_function_positional_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@given(isolated_function_calls('keyword'))
|
||||
@example("fn(a=0)")
|
||||
def test_function_call_keyword_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@given(isolated_function_calls('star'))
|
||||
@example("fn(*items)")
|
||||
def test_function_call_star_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@given(isolated_function_calls('double_star'))
|
||||
@example("fn(**{})")
|
||||
def test_function_call_double_star_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(a=0,**g)")
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_CONST_KEY_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(w=0,m=0,**v)")
|
||||
@pytest.mark.xfail()
|
||||
def test_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(*g,**j)")
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(a=0,**g)")
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_MAP_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(*z,u=0)")
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
def test_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(*g,**j)")
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_TUPLE_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(**a)")
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_MAP_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(*z,u=0)")
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_MAP_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(b,b,b=0,*a)")
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_TUPLE_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(**a)")
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(*c,v)")
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_MAP_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(b,b,b=0,*a)")
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_CONST_KEY_MAP_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(i=0,y=0,*p)")
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(*c,v)")
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
def test_BUILD_CONST_KEY_MAP_CALL_FUNCTION_EX():
|
||||
validate_uncompyle("fn(i=0,y=0,*p)")
|
||||
|
||||
|
||||
@pytest.mark.skip(reason='skipping property based test until all individual tests are passing')
|
||||
@given(function_calls())
|
||||
def test_function_call(function_call):
|
||||
validate_uncompyle(function_call)
|
||||
@pytest.mark.skip(reason='skipping property based test until all individual tests are passing')
|
||||
@given(function_calls())
|
||||
def test_function_call(function_call):
|
||||
validate_uncompyle(function_call)
|
||||
|
@@ -18,46 +18,48 @@ def test_grammar():
|
||||
right_recursive, dup_rhs) = p.check_sets()
|
||||
|
||||
# We have custom rules that create the below
|
||||
expect_lhs = set(['expr1024', 'pos_arg', 'get_iter', 'attribute'])
|
||||
expect_lhs = set(['pos_arg', 'get_iter', 'attribute'])
|
||||
|
||||
unused_rhs = set(['list', 'mkfunc',
|
||||
'mklambda',
|
||||
'unpack',])
|
||||
expect_right_recursive = set([('designList',
|
||||
('store', 'DUP_TOP', 'designList'))])
|
||||
if PYTHON3:
|
||||
expect_lhs.add('load_genexpr')
|
||||
|
||||
if PYTHON_VERSION != 3.7:
|
||||
unused_rhs.add('call')
|
||||
|
||||
if PYTHON_VERSION > 2.6:
|
||||
expect_lhs.add('kvlist')
|
||||
expect_lhs.add('kv3')
|
||||
unused_rhs.add('dict')
|
||||
|
||||
if PYTHON3:
|
||||
expect_lhs.add('load_genexpr')
|
||||
|
||||
unused_rhs = unused_rhs.union(set("""
|
||||
except_pop_except generator_exp classdefdeco2
|
||||
dict
|
||||
except_pop_except generator_exp
|
||||
""".split()))
|
||||
if PYTHON_VERSION >= 3.0:
|
||||
expect_lhs.add("annotate_arg")
|
||||
expect_lhs.add("annotate_tuple")
|
||||
unused_rhs.add("mkfunc_annotate")
|
||||
unused_rhs.add('call')
|
||||
if PYTHON_VERSION < 3.6:
|
||||
# 3.6 has at least one non-custom call rule
|
||||
# the others don't
|
||||
unused_rhs.add('call')
|
||||
if PYTHON_VERSION == 3.5:
|
||||
unused_rhs.add("dict_comp")
|
||||
unused_rhs.add("classdefdeco1")
|
||||
if PYTHON_VERSION != 3.6:
|
||||
if PYTHON_VERSION in (3.5, 3.7):
|
||||
expect_right_recursive.add((('l_stmts',
|
||||
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
|
||||
('lastl_stmt', 'come_froms', 'l_stmts'))))
|
||||
pass
|
||||
pass
|
||||
else:
|
||||
expect_right_recursive.add((('l_stmts',
|
||||
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
|
||||
# expect_lhs.add('kwargs1')
|
||||
pass
|
||||
pass
|
||||
pass
|
||||
else:
|
||||
expect_lhs.add('kwarg')
|
||||
unused_rhs.add('call')
|
||||
|
||||
assert expect_lhs == set(lhs)
|
||||
assert unused_rhs == set(rhs)
|
||||
@@ -85,6 +87,8 @@ def test_grammar():
|
||||
""".split())
|
||||
if 2.6 <= PYTHON_VERSION <= 2.7:
|
||||
opcode_set = set(s.opc.opname).union(ignore_set)
|
||||
if PYTHON_VERSION == 2.6:
|
||||
opcode_set.add("THEN")
|
||||
check_tokens(tokens, opcode_set)
|
||||
elif PYTHON_VERSION == 3.4:
|
||||
ignore_set.add('LOAD_CLASSNAME')
|
||||
|
@@ -1,19 +1,22 @@
|
||||
import pytest
|
||||
from uncompyle6 import PYTHON_VERSION, PYTHON3, deparse_code
|
||||
from uncompyle6 import PYTHON_VERSION, deparse_code
|
||||
pytestmark = pytest.mark.skip(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
|
||||
def test_single_mode():
|
||||
single_expressions = (
|
||||
'i = 1',
|
||||
'i and (j or k)',
|
||||
'i += 1',
|
||||
'i = j % 4',
|
||||
'i = {}',
|
||||
'i = []',
|
||||
'for i in range(10):\n i\n',
|
||||
'for i in range(10):\n for j in range(10):\n i + j\n',
|
||||
'try:\n i\nexcept Exception:\n j\nelse:\n k\n'
|
||||
)
|
||||
if PYTHON_VERSION > 2.6:
|
||||
def test_single_mode():
|
||||
single_expressions = (
|
||||
'i = 1',
|
||||
'i and (j or k)',
|
||||
'i += 1',
|
||||
'i = j % 4',
|
||||
'i = {}',
|
||||
'i = []',
|
||||
'for i in range(10):\n i\n',
|
||||
'for i in range(10):\n for j in range(10):\n i + j\n',
|
||||
'try:\n i\nexcept Exception:\n j\nelse:\n k\n'
|
||||
)
|
||||
|
||||
for expr in single_expressions:
|
||||
code = compile(expr + '\n', '<string>', 'single')
|
||||
assert deparse_code(PYTHON_VERSION, code, compile_mode='single').text == expr + '\n'
|
||||
for expr in single_expressions:
|
||||
code = compile(expr + '\n', '<string>', 'single')
|
||||
assert deparse_code(PYTHON_VERSION, code, compile_mode='single').text == expr + '\n'
|
||||
|
@@ -6,16 +6,18 @@ import difflib
|
||||
import subprocess
|
||||
import tempfile
|
||||
import functools
|
||||
# compatability
|
||||
import six
|
||||
# uncompyle6 / xdis
|
||||
from uncompyle6 import PYTHON_VERSION, IS_PYPY, deparse_code
|
||||
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY, deparse_code
|
||||
# TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there
|
||||
from xdis.bytecode import Bytecode
|
||||
from xdis.main import get_opcode
|
||||
opc = get_opcode(PYTHON_VERSION, IS_PYPY)
|
||||
Bytecode = functools.partial(Bytecode, opc=opc)
|
||||
|
||||
if PYTHON3:
|
||||
from io import StringIO
|
||||
else:
|
||||
from StringIO import StringIO
|
||||
|
||||
def _dis_to_text(co):
|
||||
return Bytecode(co).dis()
|
||||
|
@@ -1,3 +1,3 @@
|
||||
pytest>=3.0.0
|
||||
pytest>=3.0.0,<=3.0.1
|
||||
flake8
|
||||
hypothesis<=3.8.3
|
||||
hypothesis<=3.0.0
|
||||
|
@@ -1,2 +1,4 @@
|
||||
# Pick up stuff from setup.py
|
||||
hypothesis==2.0.0
|
||||
pytest
|
||||
-e .
|
||||
|
6
setup.py
6
setup.py
@@ -4,12 +4,12 @@ import sys
|
||||
"""Setup script for the 'uncompyle6' distribution."""
|
||||
|
||||
SYS_VERSION = sys.version_info[0:2]
|
||||
if not ((2, 6) <= SYS_VERSION <= (3, 7)) or ((3, 0) <= SYS_VERSION <= (3, 1)):
|
||||
mess = "Python Release 2.6 .. 3.7 excluding 3.0 and 3.1 are supported in this code branch."
|
||||
if not ((2, 6) <= SYS_VERSION <= (3, 7)):
|
||||
mess = "Python Release 2.6 .. 3.7 are supported in this code branch."
|
||||
if ((2, 4) <= SYS_VERSION <= (2, 7)):
|
||||
mess += ("\nFor your Python, version %s, use the python-2.4 code/branch." %
|
||||
sys.version[0:3])
|
||||
elif SYS_VERSION < (2, 4) or ((3, 0) <= SYS_VERSION <= (3, 1)):
|
||||
elif SYS_VERSION < (2, 4):
|
||||
mess += ("\nThis package is not supported for Python version %s."
|
||||
% sys.version[0:3])
|
||||
print(mess)
|
||||
|
1
test/.gitignore
vendored
Normal file
1
test/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/nohup.out
|
122
test/Makefile
122
test/Makefile
@@ -1,12 +1,13 @@
|
||||
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-1 check-bytecode-1.4 check-bytecode-1.5 \
|
||||
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
|
||||
|
||||
check-3.4 check-3.5 check-3.6 check-3.7 check-5.6 5.6 5.8 \
|
||||
grammar-coverage-2.5 grammar-coverage-2.6 grammar-coverage-2.7 \
|
||||
grammar-coverage-3.1 grammar-coverage-3.2 grammar-coverage-3.3 \
|
||||
grammar-coverage-3.4 grammar-coverage-3.5 grammar-coverage-3.6 \
|
||||
grammar-coverage-3.7
|
||||
|
||||
GIT2CL ?= git2cl
|
||||
PYTHON ?= python
|
||||
@@ -21,7 +22,7 @@ COVER_DIR=../tmp/grammar-cover
|
||||
# Run short tests
|
||||
check-short:
|
||||
@$(PYTHON) -V && PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2`; \
|
||||
$(MAKE) check-bytecode
|
||||
$(MAKE) check-bytecode-short
|
||||
|
||||
# Run all tests
|
||||
check:
|
||||
@@ -37,27 +38,36 @@ check-3.0: check-bytecode
|
||||
#: Run working tests from Python 3.1
|
||||
check-3.1: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.1 --weak-verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.1-run --verify-run
|
||||
|
||||
#: Run working tests from Python 3.2
|
||||
check-3.2: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.2 --weak-verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.2-run --verify-run
|
||||
|
||||
#: Run working tests from Python 3.3
|
||||
check-3.3: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.3 --weak-verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.3-run --verify-run
|
||||
|
||||
#: 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 --weak-verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.4-run --verify-run
|
||||
|
||||
#: Run working tests from Python 3.5
|
||||
check-3.5: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.5 --weak-verify $(COMPILE)
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.5-run --verify-run
|
||||
|
||||
#: Run working tests from Python 3.6
|
||||
check-3.6: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify $(COMPILE)
|
||||
|
||||
#: Run working tests from Python 3.7
|
||||
check-3.7: check-bytecode
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.7 --weak-verify $(COMPILE)
|
||||
|
||||
# FIXME
|
||||
#: this is called when running under pypy3.5-5.8.0 or pypy2-5.6.0
|
||||
5.8 5.6:
|
||||
@@ -67,7 +77,7 @@ check-disasm:
|
||||
$(PYTHON) dis-compare.py
|
||||
|
||||
#: Check deparsing bytecode 1.x only
|
||||
check-bytecode-1: check-bytecode-1.5
|
||||
check-bytecode-1: check-bytecode-1.4 check-bytecode-1.5
|
||||
|
||||
#: Check deparsing bytecode 2.x only
|
||||
check-bytecode-2:
|
||||
@@ -81,14 +91,35 @@ check-bytecode-3:
|
||||
--bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \
|
||||
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6 --bytecode-pypy3.2
|
||||
|
||||
#: Check deparsing bytecode that works running Python 2 and Python 3
|
||||
#: Check deparsing on selected bytecode 3.x
|
||||
check-bytecode-3-short:
|
||||
$(PYTHON) test_pythonlib.py \
|
||||
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6
|
||||
|
||||
#: Check deparsing bytecode on all Python 2 and Python 3 versions
|
||||
check-bytecode: check-bytecode-3
|
||||
$(PYTHON) test_pythonlib.py \
|
||||
--bytecode-1.3 --bytecode-1.4 --bytecode-1.5 \
|
||||
--bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
|
||||
--bytecode-2.1 --bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
|
||||
--bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \
|
||||
--bytecode-pypy2.7
|
||||
|
||||
|
||||
#: Check deparsing bytecode on selected Python 2 and Python 3 versions
|
||||
check-bytecode-short: check-bytecode-3-short
|
||||
$(PYTHON) test_pythonlib.py \
|
||||
--bytecode-2.6 --bytecode-2.7 --bytecode-pypy2.7
|
||||
|
||||
|
||||
#: Check deparsing bytecode 1.3 only
|
||||
check-bytecode-1.3:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-1.3
|
||||
|
||||
#: Check deparsing bytecode 1.4 only
|
||||
check-bytecode-1.4:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-1.4
|
||||
|
||||
#: Check deparsing bytecode 1.5 only
|
||||
check-bytecode-1.5:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-1.5
|
||||
@@ -113,23 +144,29 @@ check-bytecode-2.4:
|
||||
check-bytecode-2.5:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-2.5
|
||||
|
||||
#: Get grammar coverage for Python 2.4
|
||||
grammar-coverage-2.4:
|
||||
-rm $(COVER_DIR)/spark-grammar-24.cover
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-2.4.cover $(PYTHON) test_pythonlib.py --bytecode-2.4
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-2.4.cover $(PYTHON) test_pyenvlib.py --2.4.6 --max= 800
|
||||
|
||||
#: Get grammar coverage for Python 2.5
|
||||
grammar-coverage-2.5:
|
||||
-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
|
||||
-rm $(COVER_DIR)/spark-grammar-2.5.cover || true
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-2.5.cover $(PYTHON) test_pythonlib.py --bytecode-2.5
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-2.5.cover $(PYTHON) test_pyenvlib.py --2.5.6 --max=800
|
||||
|
||||
#: Get grammar coverage for Python 2.6
|
||||
grammar-coverage-2.6:
|
||||
-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
|
||||
-rm $(COVER_DIR)/spark-grammar-2.6.cover || true
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-2.6.cover $(PYTHON) test_pythonlib.py --bytecode-2.6
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-2.6.cover $(PYTHON) test_pyenvlib.py --2.6.9 --max=800
|
||||
|
||||
#: Get grammar coverage for Python 2.7
|
||||
grammar-coverage-2.7:
|
||||
-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
|
||||
-rm $(COVER_DIR)/spark-grammar-2.7.cover || true
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-2.7.cover $(PYTHON) test_pythonlib.py --bytecode-2.7
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-2.7.cover $(PYTHON) test_pyenvlib.py --2.7.14 --max=600
|
||||
|
||||
#: Get grammar coverage for Python 3.0
|
||||
grammar-coverage-3.0:
|
||||
@@ -140,33 +177,39 @@ SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-30.cover $(PYTHON) test_pythonl
|
||||
|
||||
#: 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
|
||||
-rm $(COVER_DIR)/spark-grammar-3.1.cover
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.1.cover $(PYTHON) test_pythonlib.py --bytecode-3.1
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.1.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
|
||||
-rm $(COVER_DIR)/spark-grammar-3.2.cover || true
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.2.cover $(PYTHON) test_pythonlib.py --bytecode-3.2
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.2.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
|
||||
-rm $(COVER_DIR)/spark-grammar-3.3.cover || true
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.3.cover $(PYTHON) test_pythonlib.py --bytecode-3.3
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.3.cover $(PYTHON) test_pyenvlib.py --3.3.7 --max=800
|
||||
|
||||
#: 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
|
||||
-rm $(COVER_DIR)/spark-grammar-3.4.cover || true
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.4.cover $(PYTHON) test_pythonlib.py --bytecode-3.4
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.4.cover $(PYTHON) test_pyenvlib.py --3.4.8 --max=800
|
||||
|
||||
#: 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
|
||||
rm $(COVER_DIR)/spark-grammar-3.5.cover || /bin/true
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.5.cover $(PYTHON) test_pythonlib.py --bytecode-3.5
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.5.cover $(PYTHON) test_pyenvlib.py --3.5.5 --max=450
|
||||
|
||||
#: Get grammar coverage for Python 3.6
|
||||
grammar-coverage-3.6:
|
||||
rm $(COVER_DIR)/spark-grammar-3.6.cover || /bin/true
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.6.cover $(PYTHON) test_pythonlib.py --bytecode-3.6
|
||||
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-3.6.cover $(PYTHON) test_pyenvlib.py --3.6.4 --max=280
|
||||
|
||||
#: Check deparsing Python 2.6
|
||||
check-bytecode-2.6:
|
||||
@@ -182,13 +225,20 @@ check-bytecode-2.7:
|
||||
check-bytecode-3.0:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.0 --weak-verify
|
||||
|
||||
#: Check deparsing Python 3.0
|
||||
check-bytecode-3.0:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.0 --weak-verify
|
||||
# $(PYTHON) test_pythonlib.py --bytecode-3.0-run --verify-run
|
||||
|
||||
#: Check deparsing Python 3.1
|
||||
check-bytecode-3.1:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.1 --weak-verify
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.1-run --verify-run
|
||||
|
||||
#: Check deparsing Python 3.2
|
||||
check-bytecode-3.2:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.2 --weak-verify
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.2-run --verify-run
|
||||
|
||||
#: Check deparsing Python 3.3
|
||||
check-bytecode-3.3:
|
||||
@@ -210,6 +260,10 @@ check-bytecode-3.6:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.6-run --verify-run
|
||||
|
||||
#: Check deparsing Python 3.7
|
||||
check-bytecode-3.7:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.7 --weak-verify
|
||||
|
||||
#: short tests for bytecodes only for this version of Python
|
||||
check-native-short:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --weak-verify $(COMPILE)
|
||||
@@ -236,7 +290,7 @@ check-3.4-ok:
|
||||
2.6:
|
||||
|
||||
#: PyPy 5.0.x with Python 2.7 ...
|
||||
pypy-2.7 5.0 5.3:
|
||||
pypy-2.7 5.0 5.3 6.0:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-pypy2.7 --verify
|
||||
|
||||
#: PyPy 2.4.x with Python 3.2 ...
|
||||
|
BIN
test/bytecode_1.3/test_builtin.pyc
Normal file
BIN
test/bytecode_1.3/test_builtin.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.3/test_exceptions.pyc
Normal file
BIN
test/bytecode_1.3/test_exceptions.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.3/test_grammar.pyc
Normal file
BIN
test/bytecode_1.3/test_grammar.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.3/test_operations.pyc
Normal file
BIN
test/bytecode_1.3/test_operations.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.3/testall.pyc
Normal file
BIN
test/bytecode_1.3/testall.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/01_print-1.4.pyc
Normal file
BIN
test/bytecode_1.4/01_print-1.4.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/02_continue.pyc
Normal file
BIN
test/bytecode_1.4/02_continue.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/addpack.pyc
Normal file
BIN
test/bytecode_1.4/addpack.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/anydbm.pyc
Normal file
BIN
test/bytecode_1.4/anydbm.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/bisect.pyc
Normal file
BIN
test/bytecode_1.4/bisect.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/cmp.pyc
Normal file
BIN
test/bytecode_1.4/cmp.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/cmpcache.pyc
Normal file
BIN
test/bytecode_1.4/cmpcache.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/dbhash.pyc
Normal file
BIN
test/bytecode_1.4/dbhash.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/emacs.pyc
Normal file
BIN
test/bytecode_1.4/emacs.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/glob.pyc
Normal file
BIN
test/bytecode_1.4/glob.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/test_class.pyc
Normal file
BIN
test/bytecode_1.4/test_class.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/test_del.pyc
Normal file
BIN
test/bytecode_1.4/test_del.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/test_docstring.pyc
Normal file
BIN
test/bytecode_1.4/test_docstring.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/test_empty.pyc
Normal file
BIN
test/bytecode_1.4/test_empty.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/test_exec.pyc
Normal file
BIN
test/bytecode_1.4/test_exec.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/test_global.pyc
Normal file
BIN
test/bytecode_1.4/test_global.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/test_globals.pyc
Normal file
BIN
test/bytecode_1.4/test_globals.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.4/test_single_stmt.pyc
Normal file
BIN
test/bytecode_1.4/test_single_stmt.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.5/00_unpack_list.pyc
Normal file
BIN
test/bytecode_1.5/00_unpack_list.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.4_run/04_try_except_else.pyc
Normal file
BIN
test/bytecode_2.4_run/04_try_except_else.pyc
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
These are byte-compiled programs compiled by Python 2.4
|
||||
|
||||
Furthrmore the programs here are self-checking: when decompiled and
|
||||
then run again in a 2.4 interpreter, they will give an error if they
|
||||
Furthermore, the programs here are self-checking: when decompiled and
|
||||
then run again in a 2.4 interpreter, they are likely to give an error when they
|
||||
are miscompiled.
|
||||
|
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.
BIN
test/bytecode_2.5/01_ops.pyc
Normal file
BIN
test/bytecode_2.5/01_ops.pyc
Normal file
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/08_if_while_else.pyc
Normal file
BIN
test/bytecode_2.5/08_if_while_else.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.
@@ -1,5 +1,5 @@
|
||||
These are byte-compiled programs compiled by Python 2.5.
|
||||
|
||||
Furthrmore the programs here are self-checking: when decompiled and
|
||||
then run again in a 2.5 interpreter, they will give an error if they
|
||||
are miscompiled.
|
||||
Furthermore the programs here are self-checking: when decompiled and
|
||||
then run again in a 2.5 interpreter, they are likely to give an error
|
||||
when they are miscompiled.
|
||||
|
Binary file not shown.
BIN
test/bytecode_2.6/02_while1_if_and.pyc
Normal file
BIN
test/bytecode_2.6/02_while1_if_and.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6/08_distbug.pyc
Normal file
BIN
test/bytecode_2.6/08_distbug.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6_run/01_ifelse_listcomp.pyc
Normal file
BIN
test/bytecode_2.6_run/01_ifelse_listcomp.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6_run/02_ifelse_lambda.pyc
Normal file
BIN
test/bytecode_2.6_run/02_ifelse_lambda.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6_run/03_complex_and.pyc-notyet
Normal file
BIN
test/bytecode_2.6_run/03_complex_and.pyc-notyet
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
These are byte-compiled programs compiled by Python 2.6.
|
||||
|
||||
Furthrmore the programs here are self-checking: when decompiled and
|
||||
then run again in a 2.6 interpreter, they will give an error if they
|
||||
are miscompiled.
|
||||
Furthermore the programs here are self-checking: when decompiled and
|
||||
then run again in a 2.6 interpreter, they are likely to give an error
|
||||
when they are miscompiled.
|
||||
|
BIN
test/bytecode_2.7.5/01_while1.pyc
Normal file
BIN
test/bytecode_2.7.5/01_while1.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/01_rel_import.pyc
Normal file
BIN
test/bytecode_2.7/01_rel_import.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7/03_for_try_raise.pyc
Normal file
BIN
test/bytecode_2.7/03_for_try_raise.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7/04_while1_while1.pyc
Normal file
BIN
test/bytecode_2.7/04_while1_while1.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/05_try_else.pyc-notyet
Normal file
BIN
test/bytecode_2.7/05_try_else.pyc-notyet
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_2.7_run/01_ifelse_listcomp.pyc
Normal file
BIN
test/bytecode_2.7_run/01_ifelse_listcomp.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7_run/02_assert.pyc
Normal file
BIN
test/bytecode_2.7_run/02_assert.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7_run/02_ifelse_lambda.pyc
Normal file
BIN
test/bytecode_2.7_run/02_ifelse_lambda.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7_run/04_assert_continue.pyc
Normal file
BIN
test/bytecode_2.7_run/04_assert_continue.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7_run/05_dict_comp.pyc
Normal file
BIN
test/bytecode_2.7_run/05_dict_comp.pyc
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
These are byte-compiled programs compiled by Python 2.7.
|
||||
|
||||
Furthrmore the programs here are self-checking: when decompiled and
|
||||
then run again in a 2.7 interpreter, they will give an error if they
|
||||
are miscompiled.
|
||||
Furthermore, the programs here are self-checking: when decompiled and
|
||||
then run again in a 2.7 interpreter, they are likely to give an error
|
||||
when they are miscompiled.
|
||||
|
BIN
test/bytecode_3.0/01_comprehension.pyc
Normal file
BIN
test/bytecode_3.0/01_comprehension.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.0/02_ifelse_lambda.pyc
Normal file
BIN
test/bytecode_3.0/02_ifelse_lambda.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.0/03_pop_top.pyc
Normal file
BIN
test/bytecode_3.0/03_pop_top.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.0/10_classdec.pyc
Normal file
BIN
test/bytecode_3.0/10_classdec.pyc
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
These are byte-compiled programs compiled by Python 3.0.
|
||||
|
||||
Furthrmore the programs here are self-checking: when decompiled and
|
||||
then run again in a 3.0 interpreter, they will give an error if they
|
||||
are miscompiled.
|
||||
Furthermore, the programs here are self-checking: when decompiled and
|
||||
then run again in a 3.0 interpreter, they are likely to give an error
|
||||
when they are miscompiled.
|
||||
|
Binary file not shown.
BIN
test/bytecode_3.1/04_call_function.pyc
Normal file
BIN
test/bytecode_3.1/04_call_function.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.1_run/05_abc_test.pyc
Normal file
BIN
test/bytecode_3.1_run/05_abc_test.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.1_run/05_dict_comp.pyc
Normal file
BIN
test/bytecode_3.1_run/05_dict_comp.pyc
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
These are byte-compiled programs compiled by Python 3.1.
|
||||
|
||||
Furthrmore the programs here are self-checking: when decompiled and
|
||||
then run again in a 3.1 interpreter, they will give an error if they
|
||||
are miscompiled.
|
||||
Furthrmore, the programs here are self-checking: when decompiled and
|
||||
then run again in a 3.1 interpreter, they are likely to give an error
|
||||
when they are miscompiled.
|
||||
|
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.2_run/04_call_function.pyc
Normal file
BIN
test/bytecode_3.2_run/04_call_function.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.2_run/05_abc_test.pyc
Normal file
BIN
test/bytecode_3.2_run/05_abc_test.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.2_run/15_assert.pyc
Normal file
BIN
test/bytecode_3.2_run/15_assert.pyc
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
These are byte-compiled programs compiled by Python 3.2.
|
||||
|
||||
Furthrmore the programs here are self-checking: when decompiled and
|
||||
then run again in a 3.2 interpreter, they will give an error if they
|
||||
are miscompiled.
|
||||
Furthermore, the programs here are self-checking: when decompiled and
|
||||
then run again in a 3.2 interpreter, they are likely to give an error
|
||||
when they are miscompiled.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user