Compare commits

...

582 Commits

Author SHA1 Message Date
rocky
df8c092212 Merge branch 'master' into python-2.4 2017-12-10 18:12:14 -05:00
rocky
3ac1e64c56 Administrivia 2017-12-10 18:12:02 -05:00
rocky
55d2e598db Merge branch 'master' into python-2.4 2017-12-10 18:11:13 -05:00
rocky
3c67c7b32c Administrivia 2017-12-10 18:10:51 -05:00
rocky
5264ffc0e5 Merge branch 'master' into python-2.4 2017-12-10 18:02:23 -05:00
rocky
c5b8531ef1 Fix last-minute bug due to kwargs->kwargs1 2017-12-10 18:00:44 -05:00
rocky
c787c27901 Get ready for release 2.14.1 2017-12-10 17:41:58 -05:00
rocky
83fc2bf25a Small updates to "how to report a bug" 2017-12-09 05:10:14 -05:00
rocky
27b217a4ed Merge branch 'master' into python-2.4 2017-12-09 04:53:21 -05:00
rocky
137f3d44d6 ChangeLog should not be in git 2017-12-09 04:51:19 -05:00
rocky
88fbb691d8 Fix 3.1 and 3.2 named and kwargs parsing..
Improve 3.4 coverage and note a 3.5 while bug
2017-12-07 16:47:56 -05:00
rocky
41bfa3fc01 Back off 3.5 control flow for now 2017-12-07 15:25:32 -05:00
rocky
ef08677287 Reinstate kwargs1...
was just missing the semantic action rule for it
2017-12-07 13:24:55 -05:00
rocky
08789adbb4 Reduce singletons rules and ..
fix recently introduced kwargs bug.
2017-12-07 13:20:08 -05:00
rocky
b8b9b8463c Fix grammar cover from last commit 2017-12-07 12:34:13 -05:00
rocky
7d8c17cb93 grammar isolation and reduction 2017-12-07 12:27:22 -05:00
rocky
b6413b6e6e Skirt around control-flow problems...
Tag some of the weaknesses if we can't address them now
2017-12-07 08:55:45 -05:00
rocky
41db5b8848 Fix while1/if parsing in 3.x. Reinstate some tests 2017-12-06 22:47:56 -05:00
rocky
a1b990a078 Back off pervasiveness of singleton reductions 2017-12-06 21:38:27 -05:00
rocky
3d277270a4 Partial fix for removing singleton expr reduction 2017-12-06 20:21:00 -05:00
rocky
a4e9410c07 Start to reduce singleton reductions 2017-12-06 12:14:42 -05:00
rocky
78e8b93125 Fix grammar after last change 2017-12-06 01:53:49 -05:00
rocky
7daf95fcb4 NT break_stmt, continue_stmt -> break, continue...
to match AST
2017-12-06 01:48:44 -05:00
rocky
f8d6998b22 NT continue_stmt -> continue to match AST 2017-12-06 01:45:08 -05:00
rocky
7b39002476 Sync NT joined_str and formmated_value with AST 2017-12-05 23:17:51 -05:00
rocky
e064791870 Fix 10_del.py syntax 2017-12-05 22:50:21 -05:00
rocky
d756548ac3 Correct 10_del.py syntax 2017-12-05 22:44:33 -05:00
rocky
0171e4d899 remove from exclusion those stdlib test that now work 2017-12-05 18:21:15 -05:00
rocky
a2054fb7dd Merge branch 'master' into python-2.4 2017-12-05 18:14:03 -05:00
rocky
7c58f8b41d runtest.sh: remove from exlusion stdlib test that now work 2017-12-05 18:13:22 -05:00
rocky
f07dcb1508 Remove debug schmutz 2017-12-05 14:23:05 -05:00
rocky
e3f62e4a1a unicode bug fix try #2...
this time, for sure!
2017-12-05 14:20:01 -05:00
rocky
ee3bdbc2ed logic bug: and->or 2017-12-05 14:12:03 -05:00
rocky
2599b94786 Start to handle FUTURE_UNICODE_LITERALS flag 2017-12-05 13:28:26 -05:00
rocky
f07c9c6dcf Merge branch 'master' into python-2.4 2017-12-05 08:32:31 -05:00
rocky
9d77b5a956 Bug in 2.6 tryelse rule 2017-12-05 08:31:13 -05:00
rocky
bbaa3e6602 Fix bug in single param **arg 2017-12-05 07:50:22 -05:00
rocky
c677c946ea Merge branch 'master' into python-2.4 2017-12-05 05:59:50 -05:00
rocky
03743fa9fc Python 3.x raise statement reduction 2017-12-05 05:57:11 -05:00
rocky
87063851be Merge branch 'master' into python-2.4 2017-12-05 05:44:59 -05:00
rocky
e12e278efc Narrow 3.x mkfunc rules 2017-12-05 05:43:22 -05:00
rocky
516c1a7910 Merge branch 'master' into python-2.4 2017-12-05 00:13:59 -05:00
rocky
2d628acf60 Separate rules for set, tuple, dict from list...
Sync fragments.py with pysource
2017-12-05 00:13:17 -05:00
rocky
00b95dd72e More verbiage about the comprehension mess 2017-12-04 15:16:46 -05:00
rocky
2293f77841 Make 2.4 compatible 2017-12-04 14:18:39 -05:00
rocky
212771244a Merge branch 'master' into python-2.4 2017-12-04 14:15:30 -05:00
rocky
c953701623 Slightly better 3.x list comprehension handling 2017-12-04 14:15:06 -05:00
rocky
8dd953de48 Slight picayune correction 2017-12-04 10:20:25 -05:00
rocky
9506412aba More tidiness...
Shorten/improve description of what's up with add_customize_rules
2017-12-04 10:14:13 -05:00
rocky
5fc33aeef5 Merge branch 'master' into python-2.4 2017-12-04 09:41:49 -05:00
rocky
53b195ede9 Tidy a little ...
parse32.py: Move common grammar rules from parse32.py to parse3.py
            parse32 should just have 3.2ish specific stuff.

parse3.py: favor addRule over add_unique_rule

pysource.py: make more clear what's up with comprehensions.
             more later.
2017-12-04 09:36:39 -05:00
rocky
3425851dc7 Python 3.x needs conditional_not 2017-12-04 08:40:06 -05:00
rocky
6ecaa16cd5 More weirdness testing 2017-12-03 20:29:55 -05:00
rocky
fff0d1c988 Include weird 2.6 bugs in 2.5 2017-12-03 20:22:29 -05:00
rocky
987b5a2290 Merge branch 'master' into python-2.4 2017-12-03 19:57:26 -05:00
rocky
c791a45aae Handle a wierd 2.6 conditional false expression...
from 2.6. test_grammar
2017-12-03 19:56:14 -05:00
rocky
0df29f344e Fix some really weird Python 2.6 constructs
From 2.6's test grammar.
2017-12-03 18:41:31 -05:00
rocky
910d210e52 Merge branch 'master' into python-2.4 2017-12-03 13:03:28 -05:00
rocky
344d2d92c4 NT: load_attr -> attribute to match AST 2017-12-03 13:02:22 -05:00
rocky
b719a0ee35 Merge branch 'master' into python-2.4 2017-12-03 12:29:05 -05:00
rocky
f78a3fb92e Parens around constant in method call ..
again.
Note what fails in 2.7 runtests
2017-12-03 12:25:26 -05:00
rocky
25329d2752 Update runtest failures 2017-12-03 11:20:06 -05:00
rocky
df4d80ff26 Merge branch 'master' into python-2.4 2017-12-03 11:19:48 -05:00
rocky
5fe8303184 Two bugs and a refactor ..
1. parse2.py: try except in a loop with a (virtual) continue
   treat CONTINUE like JUMP_ABSOLUTE which it is
2. in taking methods off of constants, a parenthesis needs to be added

Some refactoring of global code done
2017-12-03 10:46:22 -05:00
rocky
0724dc1c0e Merge branch 'master' of github.com:rocky/python-uncompyle6 2017-12-03 09:35:20 -05:00
rocky
5b916567fe NT try-middle -> except-handler to match AST 2017-12-03 06:30:33 -05:00
rocky
260bfd176e Fix bug in 2.6- except_cond3 2017-12-03 06:16:29 -05:00
rocky
13ab06ecb1 Fix bug in 2.6- except_cond3 2017-12-03 06:10:37 -05:00
rocky
cfce914889 One more _come_from -> _come_froms 2017-12-03 05:22:12 -05:00
rocky
72e2d1a2bf One more _come_from -> _come_froms 2017-12-03 05:19:20 -05:00
rocky
32f3d947bb Grammar "COME_FROM"_from cleanups ...
tryelse constructs in 2.x fixed up
_come_from -> _come_froms (COME_FROM*)
consolidate come_froms rule into sincle parser.py
2017-12-03 05:10:59 -05:00
rocky
c90210c063 Grammar "COME_FROM"_from cleanups ...
tryelse constructs in 2.x fixed up
_come_from -> _come_froms (COME_FROM*)
consolidate come_froms rule into sincle parser.py

sync unit/test_grammar.py
2017-12-03 05:04:06 -05:00
rocky
21a8726a47 Merge branch 'master' into python-2.4 2017-12-03 03:34:50 -05:00
rocky
710b0013c9 Update README 2017-12-02 22:55:13 -05:00
rocky
b1cdbe1656 update history 2017-12-02 22:45:07 -05:00
rocky
34736af561 Update doc 2017-12-02 22:29:33 -05:00
rocky
eafb32b9a0 NT trystmt -> try_except to match AST 2017-12-02 22:20:45 -05:00
rocky
de594ce7f2 Remove 3-arg raise in 3.x and..
add tests in 2.x
2017-12-02 22:07:44 -05:00
rocky
ca7f267103 Merge branch 'master' into python-2.4 2017-12-02 21:18:00 -05:00
rocky
e172a8f3c0 Fix docstring bug..
small sync with python 2.4 branch
2017-12-02 21:11:19 -05:00
rocky
f7abc69861 Administrivia 2017-12-02 20:51:58 -05:00
rocky
624c59cd5e Adminsitrivia 2017-12-02 20:08:38 -05:00
rocky
5ae32de709 Add global statements even for read of globals 2017-12-02 19:13:11 -05:00
rocky
7b15e54b7d Add "global" in functions that just read 2017-12-02 19:11:11 -05:00
rocky
ccd007355c Merge branch 'master' into python-2.4 2017-12-02 17:10:10 -05:00
rocky
ec9d00a34d Administrivia 2017-12-02 17:08:12 -05:00
rocky
8e2f78ceba Add Python 2.4 importmultiple rule 2017-12-02 14:19:32 -05:00
rocky
36aba02093 Correct Python 2.4 importmultiple rule 2017-12-02 14:17:59 -05:00
rocky
a5dd330218 Merge branch 'master' into python-2.4 2017-12-02 13:23:07 -05:00
rocky
f5c91d77d2 runtests.sh tweaks 2017-12-02 13:16:18 -05:00
rocky
cda15026e5 A couple more tests 2017-12-02 12:17:24 -05:00
rocky
5919be1451 Fix chained compares with -'s 2017-12-02 12:06:01 -05:00
rocky
93949e8222 Small grammar isolation bugs 2017-12-02 10:57:32 -05:00
rocky
fc0eb87620 Python 2.4 compatability 2017-12-02 10:01:33 -05:00
rocky
5872caee54 Correct hacky version number 2017-12-02 09:53:05 -05:00
rocky
0b9fca2263 Sync with master 2017-12-02 09:51:15 -05:00
rocky
a7005f6a77 2.7 exec stmt grammar rule isolation/reduction 2017-12-02 09:23:18 -05:00
rocky
28e573b73c Improve 3.x forelselast coverage 2017-12-02 08:53:11 -05:00
rocky
ac819cd1b9 whileTrue grammar reduction 2017-12-02 07:53:19 -05:00
rocky
6d0f72f13b Fix bug in 2.6 tryelse get test_grammar working...
localize grammar rules
2017-12-02 01:35:43 -05:00
rocky
fc33a4a72d Python 3.5 grammar reduction 2017-12-01 22:26:58 -05:00
rocky
8b6ae46a1d Isolate and reduce 3.x conditionals and lambda rules 2017-12-01 22:03:12 -05:00
rocky
ad822c02d8 opt_come_from_loop -> come_from_loops...
ANd remove unused rules associated with COME_FROM_FINALLY
2017-12-01 21:46:56 -05:00
rocky
03a5ad3d94 NT funcdef -> function_def to match AST 2017-12-01 21:36:23 -05:00
rocky
dad1b4780c Fix bugs in 3.6 default parameter handling
Mentioned in Issue #139
2017-12-01 20:12:06 -05:00
rocky
edfedec65c Small tweak 2017-12-01 04:54:59 -05:00
rocky
dd0fe36af0 NT importfrom -> import_from ...
to match AST better
and importstar -> import_from_star

misc administrivia
2017-12-01 04:33:04 -05:00
rocky
dfdd5c6c1c NT build_list -> list to match AST 2017-12-01 03:55:31 -05:00
rocky
0744a549dd Modify test_grammar for last change 2017-11-30 17:17:44 -05:00
rocky
01b5ed2304 NT mapexpr -> dict to match AST 2017-11-30 15:59:15 -05:00
rocky
77617a05c2 ops coverage on 3.{0,1} 2017-11-30 12:38:08 -05:00
rocky
824824b402 Typo 2017-11-30 11:27:50 -05:00
rocky
3d8eb01c4c _ifstmts_jump rule reduction in 3.x 2017-11-30 11:17:44 -05:00
rocky
41adcef8f8 Isolate unmap_dict rule in 3.5 2017-11-30 11:03:12 -05:00
rocky
6e19e922f8 Last commit introduced a bug 2017-11-30 10:41:50 -05:00
rocky
860d9b21f0 Isolate listcomp a little in Python 3 too 2017-11-30 10:36:00 -05:00
rocky
bf5a6237d8 Isolate listcomp rule in 2.7 2017-11-30 10:30:08 -05:00
rocky
ac4d4d1da9 NT dictcomp -> dict_comp to match AST 2017-11-30 08:50:00 -05:00
rocky
0b284f8230 NT setcomp -> set_comp to match AST 2017-11-30 07:14:29 -05:00
rocky
fcdea73b4f list_compr -> list_comp to match AST...
more Python 3 custom rule cleanup
2017-11-29 21:26:31 -05:00
rocky
6fee7fdfe3 Claan up 3.x custom MAKE_{FUNCTION,CLOSURE} rules 2017-11-29 21:09:50 -05:00
rocky
34117522b2 NT importstmt -> import to match AST 2017-11-29 20:20:54 -05:00
rocky
4ea1416fdd Python 3.x reduction of listcomp with closures 2017-11-29 19:14:08 -05:00
rocky
c4bfe38ee0 Reduce 3.x rules, esp. listcomp 2017-11-29 19:03:11 -05:00
rocky
acb4ffb758 Better grammar coverage; reduce 3.x mklambda rules 2017-11-29 16:39:32 -05:00
rocky
11e2637eeb NT augassign -> aug_assign to match AST 2017-11-29 10:51:38 -05:00
rocky
7775bdabd5 import_as -> alias; and reinstate rule 2017-11-29 10:38:18 -05:00
rocky
ff43403a05 More test coverage; simplify 3.2 grammar 2017-11-29 10:32:34 -05:00
rocky
278756be49 Administrivia and more coverage 2017-11-29 10:12:09 -05:00
rocky
98312c172b More coverage on 3.2 and 3.3 2017-11-29 09:36:32 -05:00
rocky
f2eaa09e96 Fix import and 3.x class bugs...
import x.y as z was failing across all Python versions
class decorators for Python 3.0..3.3 was failing
reduce 3.x while grammar rules
2017-11-29 06:59:05 -05:00
rocky
42fd38e2c0 More Wordsmithing 2017-11-29 05:27:17 -05:00
rocky
3a55faf9f3 More wordsmithing 2017-11-29 05:24:53 -05:00
rocky
1fcccb2472 Wordsmithing 2017-11-29 05:21:16 -05:00
rocky
ce20060cc8 Wordsmithing 2017-11-29 05:14:52 -05:00
rocky
a9171018d4 Sync up some 2.4-branch changes 2017-11-29 05:11:50 -05:00
rocky
0d9464bb92 Merge branch 'master' into python-2.4 2017-11-29 05:09:22 -05:00
rocky
43c3154a55 NT designatore -> store to match AST 2017-11-29 05:05:15 -05:00
rocky
c81b4df8b7 NT binary_subscr -> subscript to match AST 2017-11-29 00:08:08 -05:00
rocky
fb695616a6 NT call_function -> call to match AST 2017-11-28 22:13:23 -05:00
rocky
d03c5549a6 Add link to parser 2017-11-28 18:50:46 -05:00
rocky
f8690da7fd Typo 2017-11-28 18:47:03 -05:00
rocky
0637dd62d7 Update doc 2017-11-28 18:45:01 -05:00
rocky
3becefab1f nots tie me in knots 2017-11-28 18:29:14 -05:00
rocky
8454264cfc One more genexpr -> generator_exp 2017-11-28 18:00:42 -05:00
rocky
071207ce48 NT genexpr -> generate_exp to match AST 2017-11-28 17:53:33 -05:00
rocky
dded92b85d Narrow unused classdefdeco2 rules 2017-11-28 12:49:37 -05:00
rocky
05ab491d2e Small Python 2 grammar reduction 2017-11-28 11:18:11 -05:00
rocky
1a137780ad Python 2.4- doesn't do "with" 2017-11-28 10:10:45 -05:00
rocky
3c8f38f8a6 More tests 2017-11-28 10:07:46 -05:00
rocky
ff435227e9 2.5 test for UNARY_CONVERT 2017-11-28 10:01:24 -05:00
rocky
fcdc3f67af Python 2.4 doesn't do "with" 2017-11-28 09:55:25 -05:00
rocky
299936e554 Merge branch 'master' into python-2.4 2017-11-28 09:22:24 -05:00
rocky
b5cd160ebb Python 2.4 grammar reduction...
while increasing 2.4 increase test coverage
2017-11-28 09:17:27 -05:00
rocky
43076a2548 3.6 genexpr has changed
Fixes Issue #139
2017-11-28 06:57:15 -05:00
rocky
c0f1129a9d Sync with python-2.4 branch 2017-11-27 22:23:04 -05:00
rocky
2e192f0467 2.3- import statement fixes 2017-11-27 22:16:36 -05:00
rocky
9062f19a97 2.4 grammar reduction 2017-11-27 21:55:26 -05:00
rocky
f51e40a1de Merge branch 'master' into python-2.4 2017-11-27 21:41:01 -05:00
rocky
4b4fce01f6 Add UNARY convert; improve 2.1 imports 2017-11-27 21:38:09 -05:00
rocky
2ac8a0c0a6 Mege hell 2017-11-27 19:45:24 -05:00
rocky
e411024696 Merge hell 2017-11-27 19:44:47 -05:00
rocky
01a27e22b4 2.5 grammar reduction and increase coverage 2017-11-27 19:39:37 -05:00
rocky
d56547e830 Reinstate a 3.3 grammar rule 2017-11-27 14:28:45 -05:00
rocky
7553c4aed9 Add UNARY_INVERT_OP test 2017-11-27 12:49:39 -05:00
rocky
b8d9e1d25c Add 2.5 INVERT_OP test 2017-11-27 12:47:46 -05:00
rocky
593304bc43 Administrivia 2017-11-27 12:40:44 -05:00
rocky
bd4f2d086c Python 2.5- grammar reduction 2017-11-27 12:39:33 -05:00
rocky
a9ca30fe34 Reduce Python 2.5- grammar rules 2017-11-27 12:17:10 -05:00
rocky
4afff131f4 2.6- grammar reduction 2017-11-27 11:21:05 -05:00
rocky
d17440c96f bump min parser version 2017-11-27 11:01:14 -05:00
rocky
6030730870 Merge branch 'master' into python-2.4 2017-11-27 07:33:23 -05:00
rocky
1fcfadb9c8 Grammar reduction inch by inch 2017-11-27 07:27:50 -05:00
rocky
c66be4a858 Grammar hell 2017-11-27 07:15:28 -05:00
rocky
f1a98e94da Grammar isolation 2017-11-27 06:38:00 -05:00
rocky
169e4681c3 Grammar isolation 2017-11-27 05:26:43 -05:00
rocky
c241b12308 Grammar isolation fixes 2017-11-27 05:16:08 -05:00
rocky
fab6870710 need kvlist in 3.3+ 2017-11-27 05:00:51 -05:00
rocky
2674ec893a Grammar reduction 2017-11-27 04:56:01 -05:00
rocky
3f7b5e6db3 Small grammar sync 2017-11-26 21:12:01 -05:00
rocky
3edfc1611e Back off previous reduction a little 2017-11-26 20:33:00 -05:00
rocky
2e6f2cac27 Remove some unused grammar rules 2017-11-26 19:43:37 -05:00
rocky
b9436e4851 Merge branch 'master' into python-2.4 2017-11-26 19:24:24 -05:00
rocky
d72ee71368 localize Python2 ifelsetmtr, compare_chained: 2.7 2017-11-26 19:08:20 -05:00
rocky
17f5b35b1d More grammar isolation 2017-11-26 16:34:10 -05:00
rocky
b0a7452d48 2.7 tryfinally grammar rule removal 2017-11-26 15:34:00 -05:00
rocky
6db5c63307 More specific 2.7 dictcomp and setcomp rules 2017-11-26 15:06:45 -05:00
rocky
df2cda5b66 Another RsT typo 2017-11-26 10:32:01 -05:00
rocky
42c49945ad RsT typo 2017-11-26 10:27:53 -05:00
rocky
5e05e521d9 Merge branch 'master' into python-2.4 2017-11-26 10:08:59 -05:00
rocky
3c68ca6cde Update test version 2.7.13->2.7.14 2017-11-26 10:08:15 -05:00
rocky
5f6f78531f Get ready for release 2.14.0 2017-11-26 10:00:08 -05:00
rocky
7a052c349a Merge branch 'master' into python-2.4 2017-11-26 09:33:25 -05:00
rocky
bfac9a6260 Back of build_set/build_list separation 2017-11-26 09:25:37 -05:00
rocky
dd329f9c03 Isolate build_set from build_list in Python 2...
More work is needed. Not done in Python 3 yet
2017-11-26 09:15:35 -05:00
rocky
deb5b8bc6c stdlib/runtess.sh python version detection 2017-11-26 08:13:46 -05:00
rocky
a5e3d01dd3 Work around grammar remove rule bug...
And reinstate source to a current 3.3 bug (which we don't detect).
But at least it is noted for future work.
2017-11-26 08:07:00 -05:00
rocky
ad755b27a3 Isolaate kv, kv2 and kv3 better 2017-11-26 07:13:04 -05:00
rocky
35aca37557 Isolate kv, kv2, and kdv3 better 2017-11-26 06:53:22 -05:00
rocky
f98e29a3a3 Localize kv 2017-11-26 01:40:34 -05:00
rocky
57fe56d72e localize kv 2017-11-26 01:35:03 -05:00
rocky
218e73540a Merge branch 'master' into python-2.4 2017-11-26 01:27:56 -05:00
rocky
0965e2cc96 Localize kv 2017-11-26 01:26:57 -05:00
rocky
79d729e9f9 remove comp_ifnot 2017-11-26 00:58:20 -05:00
rocky
c9eeb681b9 Another test 2017-11-25 23:16:52 -05:00
rocky
5cf4f0a82f Merge hell 2017-11-25 23:15:07 -05:00
rocky
9b0225db60 Merge branch 'master' into python-2.4 2017-11-25 23:15:01 -05:00
rocky
8c0959de42 inf and nan tests 2017-11-25 23:11:27 -05:00
rocky
43cea023c4 2.7 control-flow bug: except/pass in loop 2017-11-25 22:18:57 -05:00
rocky
566ef37ecc back off of build_slice{2,3} ->slice{2,3}
There is another slice rule that interferes with this.
2017-11-25 21:49:03 -05:00
rocky
b7003914c9 localize 2 and 3 argument BUILD_SLICE...
Nontermninal name matches AST anme now. Add test.
2017-11-25 21:10:11 -05:00
rocky
3d7b160e30 Improve grammar-cover targets 2017-11-25 20:06:01 -05:00
rocky
af38064a1b remove unpack_list rule and ...
tidy things a bit more
2017-11-25 00:32:13 -05:00
rocky
ccd71c857f Regularze grammar coverage rules 2017-11-24 22:44:22 -05:00
rocky
b89dbb0ee7 Merge hell 2017-11-24 21:48:24 -05:00
rocky
a5bdc1acd0 Merge branch 'master' into python-2.4 2017-11-24 21:48:14 -05:00
rocky
c9f3838d04 Fix bug in 2.x with decorator of old-style class 2017-11-24 21:16:59 -05:00
rocky
f34c558d38 Handle inf, +inf, -nan, and nan constants 2017-11-24 15:30:05 -05:00
rocky
37b8e21c76 A couple more bugs found running 2.7 stdlib tests 2017-11-24 10:22:58 -05:00
rocky
f908e8dd8e One more (lambda) test 2017-11-24 08:57:18 -05:00
rocky
0c386d2c39 Fix bug where lambda has a yield in it 2017-11-24 08:55:26 -05:00
rocky
be5efe3e56 cmp -> compare ...
to better match the Python AST name Compare.
This forces us to change compare -> compare_single

Relates to Issue #29
2017-11-24 07:15:37 -05:00
rocky
85d65e25ba cmp_list -> compare_chained ...
to better match the Python AST name Compare. Relates to Issue #29
2017-11-24 06:58:07 -05:00
rocky
340ac7407f Start another kind of testing...
And fix a bug found in that with 3-way equal
2017-11-24 00:10:12 -05:00
rocky
a279784d8d Merge branch 'master' into python-2.4 2017-11-23 17:17:54 -05:00
rocky
84632bdc78 Forgot to update a call in last change 2017-11-23 16:44:07 -05:00
rocky
494bbbdadb Reduce 3.5 call_aysnc grammar rules 2017-11-23 16:23:49 -05:00
rocky
0e54c37fab Trystmt grammar from 3.3 needed in 3.2
Add test to cover this
2017-11-23 14:29:31 -05:00
rocky
a94b844988 Add triple compare from 3.3 into 3.2 2017-11-23 13:43:19 -05:00
rocky
7548364e8e Improve try else in 3.2...
Grammar from 3.3 is relevant here
2017-11-23 13:06:08 -05:00
rocky
3a9f4f2984 Merge branch 'master' into python-2.4 2017-11-23 12:37:00 -05:00
rocky
184f480bc8 Remove whileelselastsmt ...
Right now I don't know what it does and we don't have something that
needs it
2017-11-23 12:33:41 -05:00
rocky
cddb55eb33 provisional 2.7 whileelselast rule 2017-11-23 11:45:24 -05:00
rocky
e2a6c0435d grammar reduction of while loops 2017-11-23 10:51:22 -05:00
rocky
1823513841 3.x Grammar reduction of custom rules...
by looking for token patterns GET_ITER CALL_FUNCTION_1
2017-11-23 07:47:38 -05:00
rocky
d8a3c2708e Grammar coverage and pruning 2017-11-23 05:40:30 -05:00
rocky
d0644e08d7 Isotate conditionalnot 2017-11-22 19:38:02 -05:00
rocky
b8f74c23f4 2.x Grammar reduction/isolation 2017-11-22 19:13:21 -05:00
rocky
51ae8313cf Merge branch 'master' into python-2.4 2017-11-22 14:45:16 -05:00
rocky
b00c59bdd7 Grammar reduction for load_attrs 2017-11-22 14:41:23 -05:00
rocky
c0f0485754 Reduce unecessary grammar rules in 2.x 2017-11-22 13:06:05 -05:00
rocky
288516d8c2 Increase grammar coverage 2017-11-22 11:28:05 -05:00
rocky
38f04f0073 More complete grammar coverage 2017-11-22 11:15:39 -05:00
rocky
2de8718de3 Administrivia: add "git pull"s 2017-11-22 06:29:35 -05:00
rocky
f3da5d770d Merge hell 2017-11-22 06:26:20 -05:00
rocky
24fb13cf23 Merge branch 'master' into python-2.4 2017-11-22 06:25:52 -05:00
rocky
a8e235de17 3.3. grammar cleanup ...
need build_list in for BUILD_TUPLE_0
2017-11-18 11:02:54 -05:00
rocky
f7ff4c2d41 Grammar cleanup: import_as_cont -> import_as 2017-11-18 10:26:57 -05:00
rocky
0c0a534a48 Track spark_parser changes 2017-11-18 09:49:14 -05:00
rocky
e116d7280c custom rule hacking ...
Reduce extraneous 3.x "load_list" and "load_closure" rules
2017-11-17 12:06:14 -05:00
rocky
b7f8bee11f Python 3 grammar clean up and reorganization 2017-11-17 07:16:24 -05:00
rocky
58ee49159e More grammar isolation. narrow custom rules...
Specifically: _mklambda with load_closure is Python2 only
Add classdefdeco2 rule only when we have seen a LOAD_BUILD_CLASS
2017-11-17 00:51:03 -05:00
rocky
934df7b5c4 Python 3.4 while grammar cleanup 2017-11-16 12:36:49 -05:00
rocky
37108bc41c More grammar cleanups 2017-11-16 12:01:18 -05:00
rocky
d18a353381 Tag %c nonterminals in more template rules 2017-11-16 11:31:18 -05:00
rocky
f1004e6445 Bump copyright 2017-11-16 11:23:04 -05:00
rocky
2f218fe9bf More grammar isolation: assert2 in Python3 2017-11-16 11:20:35 -05:00
rocky
2a13851f55 Isolate "assert2" rule 2017-11-16 10:55:40 -05:00
rocky
e26de53332 Isolate "and2" rule to 2.3 2017-11-16 10:47:35 -05:00
rocky
53beae8ee6 Python 2.5 "with"; Isolate 2.5-2.6 grammar better 2017-11-16 09:26:23 -05:00
rocky
524e8c8410 Python 2.5 "with". isolate 2.5-2.7 grammar better 2017-11-16 09:18:26 -05:00
rocky
52d1e44560 Merge branch 'master' into python-2.4 2017-11-16 09:18:19 -05:00
rocky
953cf312db Add BINARY_TRUE_DIVIDE tests for 2.{6,7} 2017-11-16 01:30:41 -05:00
rocky
183a406bf1 More grammar cleanup 2017-11-16 00:32:34 -05:00
rocky
902941102f 2.7 continue-detection bug 2017-11-16 00:22:24 -05:00
rocky
c28f2f2e56 More 2.7/2.7- grammer separation & cleanup 2017-11-15 23:01:33 -05:00
rocky
f274ac0e3b Grammar cleanup: separate some 2.7 from 2.7- rules 2017-11-15 21:04:06 -05:00
rocky
05e1be7b61 I said, remove dict/setcomp from <= 2.6! 2017-11-15 09:58:34 -05:00
rocky
ee6db130ec grammar cleanup: dict/set comprehensions 2.7+ 2017-11-15 09:38:48 -05:00
rocky
5bcfa254c6 Grammar typo 2017-11-15 04:23:21 -05:00
rocky
95c2336a76 Grammar typo 2017-11-15 04:22:44 -05:00
rocky
039b084e4b One more pypy test 2017-11-15 04:09:52 -05:00
rocky
b60c05ea86 Keep bytecode_2.7 pypy free...
We need to add _another_ pypy directory
2017-11-15 04:00:54 -05:00
rocky
968e8465bc del stmt testing on 2.7 2017-11-15 03:35:55 -05:00
rocky
3a0f0557f7 Stronger 3.4 testing ...
parse3.py: remove unused grammar rule
2017-11-15 03:33:40 -05:00
rocky
63a43d0c93 Profiling workarounds, more coverage ...
test/Makefile: more grammar checking. Update python versions
10_del.pyc add test of DEL_GLOBAL

check_ast.py, pysource.py: Profileing workarounds
2017-11-15 03:16:54 -05:00
rocky
9a141a3144 Guard around null ast
This can happen in profiling
2017-11-14 10:58:41 -05:00
rocky
669a220762 bug report doc tweak 2017-11-13 11:39:17 -05:00
rocky
1436ba7abb add note on illegal use 2017-11-13 11:28:35 -05:00
rocky
6055c5e165 Get ready for release python-2.4- 2017-11-13 10:58:46 -05:00
rocky
69847dbeec detected old-style Python 2.4 class better 2017-11-13 10:57:50 -05:00
rocky
e0ed187ea6 2.4isms...
Need print without parens. Handle old-style classes more properly?
2017-11-13 10:52:43 -05:00
rocky
eafe048c7e Get ready for release python-2.4-2.13.3 2017-11-13 10:12:27 -05:00
rocky
c0e553dbb5 Merge branch 'master' into python-2.4 2017-11-13 10:11:00 -05:00
rocky
35e4e03468 Administrivia 2017-11-13 09:53:10 -05:00
rocky
d1917046f4 Get ready for release 2.13.3 2017-11-13 09:43:12 -05:00
rocky
55f12e36b7 Back off --verify for --weak-verify 2017-11-12 21:26:57 -05:00
rocky
81669ad7e7 Back off --verify for --weak-verify 2017-11-12 20:43:27 -05:00
rocky
5b9f9319a8 Reinstate previously failed tests
2.6, 3.5 and 3.6 decompilation has gotten better
2017-11-12 16:05:19 -05:00
rocky
4b0892bcb5 Use newer xdis 2017-11-10 22:30:03 -05:00
rocky
74731a9d42 Fix bug in return-optimized try stmt 2017-11-09 11:01:29 -05:00
rocky
b9dfba7400 More detail is needed in bug reporting...
sigh.
2017-11-09 09:57:11 -05:00
rocky
9ec43de039 bug in 3.x importlists
consts.py: add rule for importlists. imports weren't separated by ', '.
parser.py: Make importlist a list type of node.

test/* add test for importlist
2017-11-09 04:42:47 -05:00
rocky
5d42fe39bb Merge branch 'master' of github.com:rocky/python-uncompyle6 2017-11-08 23:06:23 -05:00
rocky
e9b60ddbf0 Better Python 3 ENDIF detection
If we have

COMPARE_OP exception-match
POP_JUMP_IF...
....
RETURN_VALUE

Then RETURN_VALUE can't be RETURN_END_IF
2017-11-08 23:05:01 -05:00
rocky
0e04b12ad4 more wordsmithing 2017-11-08 16:00:02 -05:00
rocky
cb2b6d9bf4 more wordsmithing 2017-11-08 15:58:27 -05:00
rocky
a28f5604ce more wordsmithing 2017-11-08 15:56:54 -05:00
rocky
55ced53ca9 Typo 2017-11-08 15:54:25 -05:00
rocky
41f5835fcf Typo 2017-11-08 15:54:08 -05:00
rocky
70b77025ac Typo 2017-11-08 15:53:48 -05:00
rocky
918d4f5808 Typo 2017-11-08 15:53:09 -05:00
rocky
024f295feb Tweak how to report a bug. 2017-11-08 15:42:51 -05:00
rocky
0bb793239b Add 3.6+ grammar for except's ending in RETURN...
Not totally out of the maze in 3.6 control flow...
There are still problems with erroneous RETURN_VALUEs becoming RETURN_END_IF,
2017-11-08 10:31:38 -05:00
R. Bernstein
f82165aaa7 Merge pull request #135 from rocky/3.6-instruction-refactor
3.6 instruction refactor
2017-11-07 12:58:07 -05:00
rocky
4c77170ddf Small fixes and tweaks:
parser.py: handle errors when no tokens have been produced.
scanner3{,0}.py: DRY custom scanner 3.0 rem_or code.
scanner3.py misc other small tweaks
2017-11-07 12:48:03 -05:00
rocky
3e4889bcd7 Small tweaks to sync up better with scanner2.py 2017-11-06 13:30:49 -05:00
rocky
7beac3f646 Remove parts of erroneous 2.7 test for now 2017-11-06 12:56:50 -05:00
rocky
6b6755d599 Fix 3.{3,4} pytest. Remove dup find_jump_targets 2017-11-06 12:27:43 -05:00
rocky
4a904951f4 Move refactored find-jump-targets from 3.6 to 3.x 2017-11-06 11:54:01 -05:00
rocky
124267849c Move refactored ingest from 3.6 to 3.x...
We are getting away from working with bytecode in favor of
working with full-fledged structured instructions

Up next: find_jump_targets()
2017-11-06 09:43:49 -05:00
rocky
6bffae91fa awith custom COME_FROMs ...
Now that jump branching has been properly fixed up for
EXTENDED_ARG instructions which are more prevalent with
wordcode encoding.
2017-11-06 09:10:42 -05:00
rocky
da6e32b08e Merge branch 'master' into 3.6-instruction-refactor 2017-11-06 00:47:17 -05:00
rocky
9379922c89 Iterate over instruction, not bytecode 2017-11-06 00:46:49 -05:00
rocky
6dbdaedf7a Revert change that should have been in a branch 2017-11-06 00:45:04 -05:00
rocky
dea17cd7f1 xdis _disassemble->disassemble 2017-11-06 00:38:22 -05:00
rocky
4f0a668b7c Add flag to tolerate deparse errors...
and keep going. The fragment parser should ignore errors
in nested function definitions
2017-11-04 12:29:27 -04:00
rocky
6746e5167d Add Python 3.6.3 scanner lookup 2017-11-04 11:13:55 -04:00
R. Bernstein
b32823bb7d Merge pull request #134 from mikemrm/master
Corrected python3 import from queue
2017-11-03 10:23:24 -04:00
Mike Mason
54332ddffb Corrected python3 import from queue 2017-11-03 09:05:52 -05:00
rocky
b83d6c64ed Python 3.6 control flow bug...
Much more is needed, but it's a start
2017-10-29 23:52:58 -04:00
rocky
95268cb14e In verify, JUMP_BACK is the same as CONTINUE...
at least for now. See FIXME in verify
2017-10-29 21:34:34 -04:00
rocky
5df09540b5 Python 3.6-inspired instruction size cleanup
Revise and generalize for Python 3.6+ instructions vs < 3.6 instuctions.
Used more of the generalized methods in xdis and remove some (but not
all) of the magic numbers.

This is a lot of changes, but not all of the refactoring needed. Much
crap still remains. Also, there are still bugs in handling 3.6 bytecodes.
2017-10-29 11:46:28 -04:00
rocky
5e7632c33e Bump uncompyle. Pypy 5.8.0-beta tolerance 2017-10-24 22:56:23 -04:00
rocky
1761ba2581 Tag more semantic actions with nonterminals 2017-10-13 15:43:41 -04:00
rocky
03d1c48088 More node checking in tables 2017-10-13 11:35:17 -04:00
rocky
9dd881fae1 Start allowing node names in template engine
These are now used to assert we have the right node type.

Simplify import_from
2017-10-13 11:16:58 -04:00
rocky
2fc3886693 Small changes 2017-10-13 07:52:56 -04:00
rocky
0dfbb27af5 Administrivia - generalize shell code 2017-10-12 20:36:24 -04:00
rocky
7e59987af7 Merge branch 'master' into python-2.4 2017-10-12 07:31:19 -04:00
rocky
e42e3cc230 Update install doc 2017-10-12 07:29:52 -04:00
rocky
0560c32093 Update instructions 2017-10-12 07:26:52 -04:00
rocky
3f309cebab Administrivia 2017-10-12 07:19:46 -04:00
rocky
1f012f7c46 Merge conflicts 2017-10-12 07:18:11 -04:00
rocky
d3a42ff992 Minor 2017-10-12 07:14:53 -04:00
rocky
d1a3d42ab8 Sync 2017-10-12 07:08:58 -04:00
rocky
05fd992c48 Update news 2017-10-12 07:06:19 -04:00
rocky
47f1d888eb Merge branch 'master' into python-2.4 2017-10-12 07:05:34 -04:00
rocky
b1e650a7bd Merge branch 'master' of github.com:rocky/python-uncompyle6 2017-10-12 06:52:24 -04:00
rocky
491572ed2d Get ready for release 2.13.2 2017-10-12 06:52:02 -04:00
rocky
717b22bd13 Get ready for release 2.13.2 2017-10-12 06:51:08 -04:00
rocky
ca9c227837 More administrivia 2017-10-11 22:17:50 -04:00
rocky
5e1d91cb94 Administrivia 2017-10-11 22:09:03 -04:00
rocky
e0def48020 Adminstrivia 2017-10-11 21:51:01 -04:00
rocky
5df384bb71 Some admin tools I use 2017-10-11 21:16:35 -04:00
rocky
9a2534556c Some admin tools I use. 2017-10-11 21:15:06 -04:00
rocky
e80b36347a Remove creaping Python 2.6ism 2017-10-11 20:43:17 -04:00
rocky
85269dc4d8 remove python_requires 2017-10-11 17:18:47 -04:00
rocky
01a39bf8ed Program name was incorrect.
uncompile -> uncompyle6
2017-10-11 14:52:42 -04:00
rocky
97999c5e67 Administrivia woes 2017-10-11 07:56:52 -04:00
rocky
9e37495493 Sync with master 2017-10-10 23:06:22 -04:00
rocky
77b93c5f21 Sync with master 2017-10-10 23:04:25 -04:00
rocky
0b198ee881 Sync with master 2017-10-10 23:02:20 -04:00
rocky
9e0c65881d Sync with master 2017-10-10 22:52:07 -04:00
rocky
c796d6a799 Merge commit '1d7a3c6444eab5a02d899f789f2a57cfdcbc5a84' into python-2.4 2017-10-10 22:50:28 -04:00
rocky
4563a547bc Merge branch 'master' of github.com:rocky/python-uncompyle6 2017-10-10 22:08:30 -04:00
rocky
9cfd7d669e Get ready for release 2.13.0 2017-10-10 22:08:10 -04:00
rocky
413f5aa5a5 Improve parse trace. lambda fixes yet again 2017-10-10 21:50:06 -04:00
rocky
b4426931ef Address dead code in lambda ifelse 2017-10-10 19:05:16 -04:00
rocky
3892fb533a Misc bugs 2017-10-10 16:12:02 -04:00
rocky
92f5981661 Misc bugs 2017-10-10 16:08:24 -04:00
R. Bernstein
54fe07e989 Merge pull request #131 from rocky/type2kind-rework
Adjust for spark-parser 2.7.0 incompatibilities
2017-10-10 15:19:03 -04:00
rocky
adc9b99106 More spark-parser 2.7.0 compatabilithy changes 2017-10-10 15:11:08 -04:00
rocky
1392b18bd7 Adjust for spark-parser 2.7.0 incompatabilities 2017-10-10 14:14:26 -04:00
rocky
2ea7487ca7 One more test 2017-10-05 11:19:36 -04:00
rocky
d4f6cec3d0 Sync with master 2017-10-05 11:17:49 -04:00
rocky
9ae84092cb One more test 2017-10-05 11:13:35 -04:00
rocky
85d68a7926 Merge branch 'master' of github.com:rocky/python-uncompyle6 2017-10-05 11:03:59 -04:00
rocky
b3359439f9 if bug in lambda with ifelse
A synergy of Python's irregular lambda, its custom ifelse syntax and its
marvelous indentation regime. Fixes #130
2017-10-05 11:00:55 -04:00
rocky
b1705e283d handle newer parser reduction behavior 2017-10-03 11:54:24 -04:00
rocky
9be9abc682 handle newer parser reduction behavior 2017-10-03 11:53:05 -04:00
rocky
c17ac696d6 Remove schumutz 2017-10-03 11:39:26 -04:00
rocky
9e2119f1a9 More table doc tweaks 2017-10-03 11:36:25 -04:00
rocky
eee751e22a Go over table-semantics description yet again 2017-10-03 05:44:55 -04:00
rocky
86305097d2 Go over table-semantics description yet again 2017-10-03 05:42:14 -04:00
rocky
2b0fefb95f Sync with master 2017-10-02 03:12:26 -04:00
rocky
c8d15e7654 spark-parser induced changes...
reduce rules can be called without token streams.
2017-10-02 03:09:28 -04:00
rocky
1d7a3c6444 Document hacky customize arg count better. 2017-09-30 18:02:35 -04:00
rocky
e7778f83f2 Word hacking 2017-09-26 10:35:00 -04:00
rocky
b51039ac1e Get ready for release 2.12.0 2017-09-26 09:59:55 -04:00
rocky
1a627ba207 Annotation field can be unicode...
When deparsing Python 3.x from Python 2.
2017-09-26 09:53:26 -04:00
rocky
f73f0ba41c No unicode in Python3.
but we need it in Python2. The bug was probably introduced
as a result of recent Python code type unteroperability canonicalization
2017-09-26 09:43:01 -04:00
rocky
114f979555 Pyton 3.1 Annotation args can be unicode? 2017-09-26 09:31:04 -04:00
rocky
ea75bcf47e Require xdis 3.6.0 or greater 2017-09-25 20:11:53 -04:00
rocky
6c6dcab857 Merge branch 'python-2.4' of github.com:rocky/python-uncompyle6 into python-2.4 2017-09-25 20:09:04 -04:00
rocky
0654aed6c8 Get ready for release 2.12.0 2017-09-25 20:08:50 -04:00
rocky
7b38d2f1f8 Adjust for xdis opcode JUMP_OPS. release 2.12.0 2017-09-25 20:01:31 -04:00
rocky
dfbd60231b Get ready for release 2.12.0 2017-09-25 19:11:25 -04:00
rocky
8b67f2ccd0 Python 3 compatibility 2017-09-21 11:47:42 -04:00
rocky
3447ca0767 Unit test for format-specifiers 2017-09-21 11:29:17 -04:00
rocky
aadea7224d Unit test for format-specifiers
And in the process we catch some small bugs
2017-09-21 11:25:51 -04:00
rocky
1e858efafd Tidy pysource and fragments 2017-09-20 19:08:41 -04:00
rocky
da7421da1c Tidy pysource and fragments a little more 2017-09-20 19:02:56 -04:00
rocky
ce88a72ea1 Tidy/regularize table entry formatting 2017-09-20 17:52:48 -04:00
rocky
96ca68a6fe Tidy/regularize table entry formatting 2017-09-20 17:47:56 -04:00
rocky
147b6e1cfe Small fixes
test_pyenvlib.py: it is sys.exit(), not exit()
pysource.py: reinstate nod type of async_func_call
2017-09-20 11:32:42 -04:00
rocky
7725b8e7de small fixes...
test_pythonlib.py: it is sys.exit not exit
pysource.py: restore node type on async_call function
2017-09-20 11:30:50 -04:00
rocky
d7b12f4da1 More small doc changes 2017-09-20 02:49:14 -04:00
rocky
62ddbe320d Start pysource unit test 2017-09-20 01:15:37 -04:00
rocky
c7b9e54e59 Update Table-driven info...
Start a pysource unit test.
2017-09-20 00:06:50 -04:00
rocky
a694601264 emgine -> template_engine 2017-09-17 12:03:49 -04:00
rocky
3003070acb engine -> template_engine 2017-09-17 11:56:51 -04:00
rocky
19d6dedcf5 Need weak-verification on 3.4 for now 2017-09-13 01:09:04 -04:00
rocky
51ad3fb36e Revert one of the changes pending a better fix 2017-09-10 03:01:19 -04:00
rocky
f017acce21 More semantic action cleanup 2017-09-10 02:56:47 -04:00
rocky
5bef5683e4 Match Python 3.4's terms a little names better 2017-09-10 00:48:54 -04:00
rocky
4e1467adc8 Revert last revert 2017-09-09 08:08:40 -04:00
rocky
7cdf0abb43 Revert last change 2017-09-09 08:03:04 -04:00
rocky
9b336251a7 New-style Python classes only, please. 2017-09-09 07:47:21 -04:00
rocky
7844456e1e Skeletal support for Python 3.7
Largely failing though.
2017-08-31 10:12:09 -04:00
rocky
e06f88043f Merge branch 'master' into python-2.4 2017-08-31 09:54:23 -04:00
rocky
356ea6c770 Remove python versions tag
I think it's messing up Pypi's very fussy formatting
2017-08-31 09:50:48 -04:00
rocky
8fc3fd146f Merge branch 'master' into python-2.4 2017-08-31 09:47:02 -04:00
rocky
4d58438515 Get ready for release 2.11.5 2017-08-31 09:42:14 -04:00
rocky
f7bfe3f7b2 3.7 support 2017-08-15 21:52:43 -04:00
rocky
ce5066bddb Merge branch 'master' into python-2.4 2017-08-15 11:12:20 -04:00
rocky
c54a47b15f Get ready for release 2.11.4 2017-08-15 10:57:14 -04:00
rocky
d1e02afb4b Misc cleanups...
remove code now in xdis
require at least xdis 3.5.4
PyPy tolerance in validate testing
2017-08-15 09:41:39 -04:00
rocky
93f18e2449 Allow version to be string...
in get_python_parser and get_scanner
2017-08-13 09:23:27 -04:00
rocky
f4ceb6304d 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  '2.7.13', accept that in looking up
either a scanner or a parser.
2017-08-13 09:17:07 -04:00
rocky
783e62f3ca Merge branch 'python-2.4' of github.com:rocky/python-uncompyle6 into python-2.4 2017-08-10 09:45:11 -04:00
rocky
503039ab51 Link typo
Name is trepan2 now not trepan
2017-08-10 09:41:48 -04:00
rocky
8393064136 Get ready for release 2.11.3
need xdis 3.5.1 for now. Adjust for xdis "is-not" which we need as "is not"
2017-08-09 22:09:31 -04:00
rocky
c38dc61021 xdis "is not" is now "is-not" 2017-08-09 22:07:32 -04:00
rocky
45782bbb39 Get ready for release 2.11.3 2017-08-09 21:46:27 -04:00
rocky
4c9cd5657e Merge branch 'master' into python-2.4 2017-08-09 21:45:50 -04:00
rocky
dc627d13b8 Get ready for release 2.11.3 2017-08-09 21:33:01 -04:00
rocky
ddc3489991 Python 2.4 comptiability and ...
exception match -> exception-match
2017-08-03 03:48:57 -04:00
rocky
5b24c20331 Bump xdis 2017-08-02 08:37:50 -04:00
rocky
8bb01143d8 Remove six from python 2.4/2.5 2017-08-02 08:28:08 -04:00
rocky
bb9b3ac9cf Revert commit to wrong branch 2017-08-02 08:25:39 -04:00
rocky
05ac60ea74 Remove six from Python-2.4/2.5 package 2017-08-02 08:18:54 -04:00
rocky
a9635da96a in xdis "exception match" is now "exception-match" 2017-08-02 06:36:40 -04:00
rocky
e790cb75fd Python 2.4 doesn't do six 2017-08-02 06:20:07 -04:00
rocky
348afeebbf Python 2.4 compatibility 2017-08-01 22:32:43 -04:00
rocky
d138a01bf1 xdis's "exception match" is now "exception-match" 2017-07-17 22:42:57 -04:00
rocky
9e8e4f54c7 xdis 3.5.1 is botched? 2017-07-15 00:24:40 -04:00
rocky
a06a5e1cd8 Use newer xdis 2017-07-14 23:45:56 -04:00
R. Bernstein
1048f6a964 Fixes issue #124 2017-07-14 23:43:40 -04:00
rocky
7fed237077 History updates 2017-07-14 08:03:06 -04:00
rocky
8b816ead0d RsT doc formatting 2017-07-09 02:06:39 -04:00
rocky
300d387349 Get ready for release 2.11.2 2017-07-09 01:44:55 -04:00
rocky
27ab6fe2f5 Use xdis 3.5.0's opcode sets 2017-07-08 20:41:46 -04:00
rocky
2e164763eb Start supporting Pypy 3.5 (5.7.1-beta) 2017-07-08 17:47:32 -04:00
rocky
d332bde104 Loops in Python 2.4-2.6 loop come_from
Looks like Python 2.4-2.6 may have a COME_FROM(_LOOP)
before the jump_back.

Fixes Issue #123
2017-07-05 06:12:14 -04:00
rocky
0893652943 Work around not having real flow-control analysis 2017-06-29 20:49:01 -04:00
rocky
6efd7afda3 continue non-detection in Python 2.7
fixes issue 122
2017-06-29 20:27:07 -04:00
rocky
ee3202779a A guard against badly formated bytecode 2017-06-28 18:39:05 -04:00
rocky
6888553773 Merge branch 'master' into python-2.4 2017-06-25 18:56:31 -04:00
rocky
9c072a6a42 3.x funciton and annotation bug fixes 2017-06-25 18:46:03 -04:00
rocky
277ad36566 Get ready for release 2.11.1 2017-06-25 13:50:46 -04:00
rocky
af3d46b35c Use xdis' instruction offset calculation fns..
next_offset, op_size, has_argument
2017-06-24 06:43:04 -04:00
rocky
e1bc0c5cd6 Python 2 sometimes need str->uncode in writing? 2017-06-19 08:02:59 -04:00
rocky
5a519ed36a Allow deparsed out to be str as well as unicode 2017-06-19 07:55:09 -04:00
rocky
0f489672b9 More merge fixups from master 2017-06-18 16:05:22 -04:00
rocky
b7d8cbfaf5 Merge branch 'master' into python-2.4 2017-06-18 15:40:40 -04:00
rocky
af10f99776 Get ready for release 2.11.0 2017-06-18 15:31:44 -04:00
rocky
0cbafa6e3a Adjust nodeInfo if it is a Token 2017-06-13 04:41:32 -04:00
rocky
4afaee2a36 Add nonterminal node in extractInfo 2017-06-13 04:17:23 -04:00
rocky
daea3c348c Fragment tag more expressions
Revise make_function3 comment wrt args and kwargs
2017-06-10 16:31:56 -04:00
rocky
bf45260588 Fragment tag array subscripts 2017-06-10 08:05:18 -04:00
R. Bernstein
34a356d237 Create README.rst 2017-06-10 06:21:36 -04:00
R. Bernstein
d9c1374a59 Create README.rst 2017-06-10 06:14:06 -04:00
rocky
2e05137f2b Set YIELD_VALUE offset in a <yield> expr 2017-06-10 02:09:58 -04:00
rocky
267ecda070 Python 3.2 MAKE_FUNCTION again..
Was handling bug32/01_named_and_kwargs.py wrong again
2017-06-10 01:42:50 -04:00
R. Bernstein
7e89839777 Merge pull request #119 from rocky/scan-longconstant
Simplify access to L65536 ...
2017-06-09 18:57:28 -04:00
rocky
c7f8edd5ef Simplify access to L65536 ...
and fix use in scanner26.py. Thanks to AnythingTechPro
2017-06-09 18:22:02 -04:00
rocky
6a991833a3 Attempt to document the MAKE_FUNCTION/MAKE_LAMBDA mess...
in Python 3.0+
2017-06-09 06:52:14 -04:00
rocky
28ee3f1257 Correct make_function3 for Pytohn 3.2 2017-06-08 21:49:13 -04:00
rocky
e9588e56e2 Disable "continue" removal in pysource.py
"continue" could be the only statement and then removing it
might lead to a dangling "else".
2017-06-08 04:35:06 -04:00
rocky
7b2217fda4 Mark "pass" offsets.
Start routine to find previous node.
2017-06-07 22:14:38 -04:00
rocky
5ca219f3d3 Remove hacky fragments try fixup...
hacky call_function code is also not needed or will be reinstated
properly. Better grammar structure for Python 3.6 call_function.
2017-06-06 21:58:47 -04:00
rocky
b733a1b036 BUILD_{MAP,TUPLE}_UNPACK & CALL_FUNCTION_EX_KW...
Bang on these in 3.6. Not totally succesfull right now.
In fact a regression on one of the test cases
2017-06-05 23:51:51 -04:00
rocky
4615cda03f Important fragments bug fix...
start, finish that had been adjusted wasn't getting reflected in final
returned deparsed.offsets dictionary. Redo keeping API compatibility,
i.e we still use namedtuple NodeInfo.
2017-06-05 21:17:17 -04:00
rocky
eb92418224 Python 3.5 *args with kwargs handling.
3.5 is a snowflake here. Thank you, Python.

Fully fixes Issue 95.

3.6 is broken on this source, but for a *different* reason. Sigh.
2017-06-04 17:53:51 -04:00
rocky
844221cd43 Small changes.
fragment tag EXEC_STMT
2017-06-03 23:29:46 -04:00
rocky
df8d253f78 2.4 doesn't do six 2017-06-03 06:00:47 -04:00
rocky
89b42e3696 Nope it (appveyor) doesn't. 2017-06-03 05:55:21 -04:00
rocky
22e5a4a283 Administrivia
See if appveyor will handle 2.5
2017-06-03 05:53:41 -04:00
rocky
61810172d1 Merge branch 'master' into python-2.4 2017-06-03 05:50:42 -04:00
rocky
7c299fbf37 Streamline .travis.yml a little bit 2017-06-03 05:38:05 -04:00
rocky
da695115b5 We need six 2017-06-03 05:36:50 -04:00
rocky
f1d9e194fe Go over administrivia 2017-06-03 05:31:46 -04:00
rocky
e727a437ea Get ready for release 2.10.1 2017-06-03 05:26:34 -04:00
rocky
9a3e11a957 Fragment bugs
fragment.py:
* deparse_code_aorund_offset: was sometimes returning the wrong type
* capture function name offset
* lint imports

pysource.py: use a clearer variable name
2017-06-03 05:18:40 -04:00
rocky
966a4bc7dc Track changes in ifelstmtr..
in fragments from pysource
2017-06-02 21:15:23 -04:00
rocky
658c8b4be7 No decorators in Python < 2.6 2017-05-30 02:30:56 -04:00
rocky
d4dab54c7b Merge branch 'master' into python-2.4 2017-05-30 02:18:57 -04:00
rocky
ad98fae3d4 Get ready for release 2.10.0 2017-05-30 01:55:36 -04:00
rocky
cbbf64ccd0 Python 3.6 makefunction handling for fragments 2017-05-30 01:25:33 -04:00
rocky
394120bb1a Fix up 3.6 unmapexpr 2017-05-23 21:10:14 -04:00
rocky
7257ba41c5 Fix up retreiving "async" property on 3.6 2017-05-23 21:02:06 -04:00
rocky
9eee4eccd7 Fix bug in a 3.6 class name. 2017-05-23 19:00:06 -04:00
rocky
cf3c07e047 Add fuzzy offset deparse lookup 2017-05-23 06:10:31 -04:00
rocky
d93b7a9eae Correct EXTENDED_ARG handling on Python 3.6...
where it can appear several times and xdis may handle it as well.
It possibly in other versions bug since EXTENDED_ARG is used so rarely
there because it has such a high value 1<<16, it's hard to test and
determine that.
2017-05-21 04:44:11 -04:00
rocky
5ebb731c04 Worse results. Revert some of the last changes 2017-05-20 07:50:41 -04:00
rocky
d3794ec9af More explicit about 3.5 UNMAP_PACK
Have to reduce 3.5 bytecode testing for now, code is more solid.
2017-05-20 07:40:59 -04:00
rocky
2ab7aa2f48 Simplify EXTENDED_ARG on 3.x
We largely remove them and fold them itno the next op.
MAKE_FUNCTION though before 3.6 is an exception as that indicates an
annotated function
2017-05-19 22:06:18 -04:00
rocky
49fd430505 EXTENDED_ARG is implemented in 2.6 2017-05-19 19:29:56 -04:00
rocky
2a47f0309f Fix EXTENDED_ARG for long lists, sets, maps 2017-05-19 15:36:53 -04:00
rocky
3084ac20e9 Another attempt at getting get_target() correct 2017-05-19 07:52:31 -04:00
rocky
9c846c309e Bug in pypy JUMP_IF_NOT_DEBUG handling 2017-05-19 07:18:25 -04:00
rocky
b4efa62fad EXTENDED_ARG handling...
get_target() wasn't taking into account EXTENDED_ARG before opcode.

This is mostly relevant in Python 3.6 where the max size before needing
EXTENDED_ARG has been reduced to 256, but theoretically possible in earlier
versions.
2017-05-19 07:13:20 -04:00
rocky
94d1c6dfd3 Enforce using xdis >=3.3.1 ..
to pick up bug fixes to 3.6 in xdis
2017-05-18 04:20:16 -04:00
rocky
6991a637a2 Small changes....
* __pkginfo__.py: Need spark parser 1.6.1 for corrected remove_rules() fn
* parser36.py: remove replaced Python3 rules
* scanner3.py: corrected comment. Thanks to moagstar here.
*
2017-05-17 23:31:56 -04:00
rocky
52b1f4d2b6 Fix broken CI on 3.6...
Another grammar rule replacing SETUP_LOOP with setup_loop
2017-05-16 20:23:24 -04:00
rocky
0ce804ae16 More EXTENDED_ARGS on 3.6 2017-05-16 06:20:41 -04:00
rocky
d2502f205e extend use of EXTENDED_ARGS in 3.6
switching to a wordcode seems to have made opcode fields smaller so we
need EXTENDED_ARG more?
2017-05-16 06:03:57 -04:00
rocky
2ad40a5648 Allow LOAD_CONST EXTENDED_ARG 2017-05-16 00:22:48 -04:00
rocky
d1a695b2bd Reinstate 3.6 listcomp rule 2017-05-15 19:28:17 -04:00
rocky
47b6a35abc Bang on 3.6 MAKE_FUNCTION some more 2017-05-15 03:07:11 -04:00
rocky
b1e32c7cc5 towards fixing a 3.5.CALL_FUNCTONI_VAR bug 2017-05-14 12:23:47 -04:00
rocky
47977b3372 Python 3.5 kw arg can be an expr
Fixes Issue #95
2017-05-14 11:46:15 -04:00
R. Bernstein
2a7a166696 Merge pull request #117 from rocky/3.6-MAKE_FUNCTION
3.6 make function
2017-05-14 03:47:05 -04:00
rocky
ea732acf49 In conjunction with MAKE_FUNCTION_FLAGS change...
Switched from tuple to string, but forgot to change the code that uses this.
2017-05-13 17:29:20 -04:00
rocky
da884487d5 MAKE_FUNCTION_FLAGS can be a simpler tuple 2017-05-13 11:47:27 -04:00
rocky
ff73efcf8e Grammar rules for Python 3.6 MAKE_FUNCTION 2017-05-13 11:39:19 -04:00
rocky
a32c0e68ef Bang on 3.6 MAKE_FUNCTION a bit more
parse3.py, parse36.py: adding return_closure rule tags what's going on
with this rule

pysource.py: start changing semantic rules to support code changed by
new make_function semantics

README.rst: typo
2017-05-13 10:06:43 -04:00
rocky
73857c831b Typo 2017-05-13 06:12:31 -04:00
rocky
4c2ca44818 Bug in 2.7 decompiling ourself!
Troublesome file was uncompyle6.semantics.pysource.engine()
2017-05-12 22:52:05 -04:00
R. Bernstein
3e7add1138 Merge pull request #113 from grkov90/patch-1
Fixed out_base bug
2017-05-11 16:39:08 -04:00
Gregory Komagurov
69fd1b3371 Fix tests 2017-05-11 19:43:14 +03:00
rocky
d540146d5a WIP: start 3.6 MAKE_FUNCTION handling 2017-05-11 07:00:46 -04:00
Daniel Bradburn
e9a17010c7 Merge pull request #116 from moagstar/function_call_keyword_only
Added support for Python 3.6 CALL_FUNCTION_KW
2017-05-11 07:56:08 +02:00
Daniel Bradburn
038692dbf9 Double star arg only test is no longer expected to fail 2017-05-10 22:57:48 +02:00
Daniel Bradburn
93437152a2 Fixed bug in compiling double star arg only function calls where the closing parenthesis would be missed 2017-05-10 22:52:49 +02:00
Daniel Bradburn
b952f56c44 Adding requirement for pytest >= 3.0 to fix strange INTERNALERROR in combination with hypothesis when using pytest 2.6.4 2017-05-10 22:36:28 +02:00
Daniel Bradburn
ca1679e636 Added support for support for Python 3.6 CALL_FUNCTION_KW 2017-05-10 21:49:42 +02:00
rocky
8d084ed358 pysource guard and another appveyor test 2017-05-08 07:03:10 -04:00
rocky
a10914a645 appveyor take 2 2017-05-08 06:44:43 -04:00
rocky
9c0ef9fa63 Try appveyor 2017-05-08 06:28:36 -04:00
rocky
449d74af51 More guarded CONTINUE deletion 2017-05-07 13:30:26 -04:00
rocky
f8a40c1949 Reduce spurious "continue" statements 2017-05-07 13:15:26 -04:00
rocky
e10e184eda --weak-verify on 3.3 with inclusion of last commit
Note that the result is sematically equivalent, so it is is correct.
2017-05-07 09:13:50 -04:00
rocky
605721c995 Python 3.x control-flow bug...
"pass" statement inside "while True"
2017-05-07 09:10:05 -04:00
rocky
50d875f6a6 Small typo 2017-05-07 08:01:48 -04:00
rocky
26e8de8532 Fix improper COME_FROM_EXCEPT in Python 3.3+ 2017-05-07 03:19:53 -04:00
rocky
89d8a70778 python 3.3 while True parsing bug 2017-05-06 10:00:33 -04:00
rocky
5566b9ba6c Get ready for release 2.9.11 2017-05-06 07:49:09 -04:00
rocky
e56ab2dcd5 Sync with master 2017-05-06 07:17:04 -04:00
rocky
d6c45979ba Merge branch 'master' into python-2.4 2017-05-06 07:16:39 -04:00
Gregory
93ec81673b Some fix 2017-05-03 18:25:55 +03:00
Gregory
0cf5f41fda Fixed out_base bug
Variable filename using in for

tags 
uncompyle6 -o haven't worked
argument -o haven't worked
2017-05-03 15:14:53 +03:00
rocky
a06e9bf32e Merge branch 'master' into python-2.4 2017-04-14 05:45:53 -04:00
rocky
7e8f7ba674 namedtuple25 -> namedtuple24 2017-04-14 05:42:44 -04:00
rocky
09eb7f7f78 Merge branch 'master' into python-2.4 2017-04-10 00:48:04 -04:00
rocky
f7a910ec66 Merge branch 'master' into python-2.4 2017-03-01 05:55:26 -05:00
rocky
6d6a73eea7 Merge branch 'master' into python-2.4 2017-02-25 21:02:12 -05:00
rocky
e4a7641927 Python <= 2.6 grammar fixes 2017-02-25 05:13:19 -05:00
rocky
b24b46d48c Merge branch 'master' into python-2.4 2017-02-25 04:48:06 -05:00
rocky
a65d7dce5b Python 2.5 was missing try else stmt 2017-02-22 05:30:07 -05:00
rocky
718a0a5d34 Merge branch 'master' into python-2.4 2017-02-22 05:29:49 -05:00
rocky
ea9e3ab3f5 Group coverage Makefile targets 2017-02-10 01:00:26 -05:00
rocky
770e988ff8 Changes based on coverage information 2017-01-29 22:54:30 -05:00
rocky
0fa0641974 Merge branch 'master' into python-2.4 2017-01-29 22:05:55 -05:00
rocky
c13e23cdae Get ready for release 2.9.9 2017-01-11 21:52:20 -05:00
rocky
fab4ebb768 Merge changes ...
* str() in Python 2.4 doesn't detect unicode.
* index() doesn't work on tuples
* ifelse change
2017-01-11 19:34:28 -05:00
rocky
89429339fa Merge branch 'master' into python-2.4 2017-01-11 19:25:44 -05:00
rocky
6ed129bd7a 2.4 verify hacks 2017-01-02 07:15:46 -05:00
rocky
c4fde6b53e Merge branch 'master' into python-2.4 2017-01-02 05:39:50 -05:00
rocky
a7d93e88b4 Merge branch 'master' into python-2.4 2017-01-02 05:39:13 -05:00
rocky
9891494142 We are version 2.9.9 2016-12-31 18:16:23 -05:00
rocky
f8544dfbbe 2.7->2.4 conversion 2016-12-31 10:56:43 -05:00
rocky
b00651d428 Merge master branche
Handle 2.2 list_if
2016-12-31 05:19:21 -05:00
rocky
da8dccbaca Merge branch 'master' into python-2.4 2016-12-29 02:08:12 -05:00
rocky
37272ae827 Merge commit '9b1dd0f' into python-2.4 2016-12-27 10:32:25 -05:00
rocky
7f2bee46b7 Bug in using python2 ast checking in python 2.5 2016-12-26 01:55:16 -05:00
rocky
c8a4dcf72b Removing NAME_MODULE, lint and bug fixes
scanner*.py: show_asm param is optional
verify.py: call correct scanners
main.py, verify.py: Use older Python print statements
2016-12-25 09:16:04 -05:00
rocky
012ff91cfb Merge branch 'master' into python-2.4 2016-12-25 07:57:17 -05:00
rocky
e690ddd50a Merge branch 'master' into python-2.4 2016-12-18 07:43:15 -05:00
rocky
45b7c1948c show-asm on python2.5 is optional
Make scanner2 a little more like scanner3.
2016-12-17 07:57:31 -05:00
rocky
e2fb7ca3d2 Python 2.6/2.7 tolerance in Python 2.4 branch 2016-12-17 06:51:47 -05:00
rocky
b3bda76582 Merge branch 'master' into python-2.4 2016-12-16 22:56:07 -05:00
rocky
ab6d322eca Get ready for release 2.9.7 2016-12-04 14:09:53 -05:00
rocky
1a8a0df107 Merge branch 'master' into python-2.4 2016-12-04 13:40:06 -05:00
rocky
0a37709b0a CircleCI build 2016-11-24 05:41:31 -05:00
rocky
98cd1417df Remove dup Python 3 grammar rule 2016-11-24 05:36:43 -05:00
rocky
460069ceaa Bug in 2.4 "if" dectection and...
Wrong language used in old-style exceptions: use "except Error,e" not
"except Error(e)""
2016-11-24 05:15:35 -05:00
rocky
316aa44f23 Python 2.6 grammary bug and..
__pkginfo.py__: Bump spark_parser version for parse_flags 'dups'
2016-11-24 04:09:32 -05:00
rocky
7133540c23 Make work on 2.4 2016-11-23 08:26:12 -05:00
rocky
590231741d Merge branch 'come-from-type' into python-2.4 2016-11-23 07:54:18 -05:00
rocky
a9349b8f3d Making it run on Python 2.4 and 2.5 2016-11-23 07:53:51 -05:00
325 changed files with 7222 additions and 9043 deletions

4
.gitignore vendored
View File

@@ -17,4 +17,6 @@
__pycache__
build
/.venv*
/.idea
/.idea
/.hypothesis
./ChangeLog

View File

@@ -3,16 +3,10 @@ language: python
sudo: false
python:
- '3.5'
- '2.7.12'
- '2.6'
- '3.3'
- '3.4'
- '3.2'
- '3.6'
- '2.7' # this is a cheat here because travis doesn't do 2.4-2.6
install:
- pip install -r requirements.txt
- pip install -e .
- pip install -r requirements-dev.txt
script:

6028
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -44,8 +44,8 @@ it appears that Hartmut did most of the work to get this code to
accept the full Python language. He added precedence to the table
specifiers, support for multiple versions of Python, the
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 says he could verify against the
entire Python library. However I have subsequently found small and relatively obscure bugs in the decompilation code.
deparsed bytecode, and used this in an extensive set of tests that he also wrote. He says he could verify against the
entire Python library. However I have subsequently found small and relatively obscure bugs in the decompilation code.
decompyle2.2 was packaged for Debian (sarge) by
[Ben Burton around 2002](https://packages.qa.debian.org/d/decompyle.html). As
@@ -64,14 +64,17 @@ success that his good work deserves.
Dan Pascu did a bit of work from late 2004 to early 2006 to get this
code to handle first Python 2.3 and then 2.4 bytecodes. Because of
jump optimization introduced in the CPython bytecode compiler at that
time, various JUMP instructions were classifed as going backwards, and
COME FROM instructions were reintroduced. See
[RELEASE-2.4-CHANGELOG.txt](https://github.com/rocky/python-uncompyle6/blob/master/DECOMPYLE-2.4-CHANGELOG.txt)
for more details here. There wasn't a public
release of RELEASE-2.4 and bytecodes other than Python 2.4 weren't
supported. Dan says the Python 2.3 version could verify the entire
Python library. But given subsequent bugs found like simply
recognizing complex-number constants in bytecode, decompilation wasn't perfect.
time, various JUMP instructions were classified to assist parsing For
example, due to the way that code generation and line number table
work, jump instructions to an earlier offset must be looping jumps,
such as those found in a "continue" statement; "COME FROM"
instructions were reintroduced. See
[RELEASE-2.4-CHANGELOG.txt](https://github.com/rocky/python-uncompyle6/blob/master/DECOMPYLE-2.4-CHANGELOG.txt)
for more details here. There wasn't a public release of RELEASE-2.4
and bytecodes other than Python 2.4 weren't supported. Dan says the
Python 2.3 version could verify the entire Python library. But given
subsequent bugs found like simply recognizing complex-number constants
in bytecode, decompilation wasn't perfect.
Next we get to ["uncompyle" and
PyPI](https://pypi.python.org/pypi/uncompyle/1.1) and the era of
@@ -98,15 +101,37 @@ so. Then hamled made a few commits earler on, while Eike Siewertsen
made a few commits later on. But mostly wibiti, and Guenther
Starnberger got the code to where uncompyle2 was around 2012.
In `uncompyle`, decompilation of python bytecode 2.5 & 2.6 is done by
transforming the byte code into a a pseudo 2.7 python bytecode and is
based on code from Eloi Vanderbeken.
While John Aycock and Hartmut Goebel were well versed in compiler
technology, those that have come afterwards don't seem to have been as
facile in it. Furthermore, documentation or guidance on how the
decompiler code worked, comparison to a conventional compiler
pipeline, how to add new constructs, or debug grammars was weak. Some
of the grammar tracing and error reporting was a bit weak as well.
Given this, perhaps it is not surprising that subsequent changes
tended to shy away from using the built-in compiler technology
mechanisms and addressed problems and extensions by some other means.
Specifically, in `uncompyle`, decompilation of python bytecode 2.5 &
2.6 is done by transforming the byte code into a pseudo-2.7 Python
bytecode and is based on code from Eloi Vanderbeken. A bit of this
could have bene easily added by modifying grammar rules.
This project, `uncompyle6`, abandons that approach for various
reasons. However the main reason is that we need offsets in fragment
deparsing to be exactly the same, and the transformation process can
remove instructions. _Adding_ instructions with psuedo offsets is
however okay.
reasons. Having a grammar per Python version is much cleaner and it
scales indefinitely. That said, we don't have entire copies of the
grammar, but work off of differences from some neighboring version.
Should there be a desire to rebase or start a new base version to work
off of, say for some future Python version, that can be done by
dumping a grammar for a specific version after it has been loaded
incrementally. You can get a full dump of the grammar by profiling the
grammar on a large body of Python source code.
Another problem with pseudo-2.7 bytecode is that that we need offsets
in fragment deparsing to be exactly the same as the bytecode; the
transformation process can remove instructions. _Adding_ instructions
with psuedo offsets is however okay.
`Uncompyle6` however owes its existence to the fork of `uncompyle2` by
Myst herie (Mysterie) whose first commit picks up at
@@ -120,10 +145,10 @@ while, handling Python bytecodes from Python versions 2.5+ and
3.2+. In doing so, it has been expedient to separate this into three
projects:
* bytecode loading and disassembly ([xdis](https://pypi.python.org/pypi/xdis)),
* marshaling/unmarshaling, bytecode loading and disassembly ([xdis](https://pypi.python.org/pypi/xdis)),
* parsing and tree building ([spark_parser](https://pypi.python.org/pypi/spark_parser)),
* this project - grammar and semantic actions for decompiling
([uncompyle6](https://pypi.python.org/pypi/spark_parser)).
([uncompyle6](https://pypi.python.org/pypi/uncompyle6)).
Over the many years, code styles and Python features have
@@ -144,23 +169,45 @@ Hartmut a decade an a half ago:
This project deparses using an Earley-algorithm parse with lots of
massaging of tokens and the grammar in the scanner
phase. Earley-algorithm parsers are context free and tend to be linear
if the grammar is LR or left recursive.
if the grammar is LR or left recursive. There is a technique for
improving LL right recursion, but our parser doesn't have that yet.
Another approach that doesn't use grammars is to do something like
simulate execution symbolically and build expression trees off of
stack results. Control flow in that apprproach still needs to be
handled somewhat ad hoc. The two important projects that work this
way are [unpyc3](https://code.google.com/p/unpyc3/) and most
especially [pycdc](https://github.com/zrax/pycdc) The latter project
is largely by Michael Hansen and Darryl Pogue. If they supported
getting source-code fragments, did a better job in supporting Python
more fully, and had a way I could call it from Python, I'd probably
would have ditched this and used that. The code runs blindingly fast
and spans all versions of Python, although more recently Python 3
support has been lagging.
Another approach to decompiling, and one that doesn't use grammars is
to do something like simulate execution symbolically and build
expression trees off of stack results. Control flow in that approach
still needs to be handled somewhat ad hoc. The two important projects
that work this way are [unpyc3](https://code.google.com/p/unpyc3/) and
most especially [pycdc](https://github.com/zrax/pycdc) The latter
project is largely by Michael Hansen and Darryl Pogue. If they
supported getting source-code fragments, did a better job in
supporting Python more fully, and had a way I could call it from
Python, I'd probably would have ditched this and used that. The code
runs blindingly fast and spans all versions of Python, although more
recently Python 3 support has been lagging. The code is impressive for
its smallness given that it covers many versions of Python. However, I
think it has reached a scalability issue, same as all the other
efforts. To handle Python versions more accurately, I think that code
base will need to have a lot more code specially which specializes for
Python versions. And then it will run into a modularity problem.
Tests for the project have been, or are being, culled from all of the
projects mentioned.
projects mentioned. Quite a few have been added to improve grammar
coverage and to address the numerous bugs that have been encountered.
If you think, as I am sure will happen in the future, "hey, I can just
write a decompiler from scratch and not have to deal with all all of
the complexity here", think again. What is likely to happen is that
you'll get at best a 90% solution working for a single Python release
that will be obsolete in about a year, and more obsolete each
subsequent year. Writing a decompiler for Python gets harder as it
Python progresses, so writing one for Python 3.7 isn't as easy as it
was for Python 2.2. That said, if you still feel you want to write a
single version decompiler, look at the test cases in this project and
talk to me. I may have some ideas.
For a little bit of the history of changes to the Earley-algorithm parser,
see the file [NEW-FEATURES.rst](https://github.com/rocky/python-spark/blob/master/NEW-FEATURES.rst) in the [python-spark github repository](https://github.com/rocky/python-spark).
NB. If you find mistakes, want corrections, or want your name added
(or removed), please contact me.

View File

@@ -2,34 +2,122 @@
## The difficulty of the problem
There is no Python decompiler yet, that I know about that will
decompyle everything. This one probably does the
best job of *any* Python decompiler. But it is a constant work in progress: Python keeps changing, and so does its code generation.
This decompiler is a constant work in progress: Python keeps
changing, and so does its code generation.
I have found bugs in *every* Python decompiler I have tried. Even
those where authors/maintainers claim that they have used it on
the entire Python standard library. And I don't mean that
the program doesn't come out with the same Python source instructions,
but that the program is *semantically* not equivalent.
There is no Python decompiler yet that I know about that will
decompile everything. Overall, I think this one probably does the best
job of *any* Python decompiler that handles such a wide range of
versions.
So it is likely you'll find a mistranslation in decompiling.
But at any given time, there are maybe dozens of valid Python bytecode
files that I know of that will cause problems. And when I get through
those and all the issues of decompiler bugs that are currently logged,
I could probably easily find dozens more bugs just by doing a
decompile of all the Python bytecode on any one of my
computers. Unless you want to help out by _fixing_ bugs, or are
willing to do work by isolating and narrowing bugs, don't feel you are
doing me a favor by doing scans on your favorite sets of bytecode
files.
In sum, it is not uncommon that you will find a mistranslation in
decompiling. Furthermore, you may be expected to do some work in order
to have your bug worthy of being considered above other bugs.
No one is getting paid to work to work on this project, let alone bugs
you may have an interest in. If you require decompiling bytecode
immediately, consider using a decompilation service.
## Is it really a bug?
### Do you have valid bytecode?
As mentioned in README.rst, this project doesn't handle obfuscated
code. See README.rst for suggestions for how to remove some kinds of
obfuscation.
Checking if bytecode is valid is pretty simple: disassemble the code.
Python comes with a disassembly module called `dis`. A prerequisite
module for this package, `xdis` has a cross-python version
disassembler called `pydisasm`.
### Semantic equivalence vs. exact source code
Almost all versions of Python can perform some sort of code
improvement that can't be undone. In earlier versions of Python it is
rare; in later Python versions, it is more common.
If the code emitted is semantically equivalent, then this isn't a bug.
For example the code might be
```
if a:
if b:
x = 1
```
and we might produce:
```
if a and b:
x = 1
```
These are equivalent. Sometimes
```
else:
if ...
```
may come out as `elif`.
As mentioned in the README, It is possible that Python changes what
you write to be more efficient. For example, for:
```
if True:
x = 5
```
Python will generate code like:
```
x = 5
```
So just because the text isn't the same, does not
necessarily mean there's a bug.
## What to send (minimum requirements)
The basic requirement is pretty simple:
* Python bytecode
* Source text
* Python source text
Please don't put files on download services that one has to register
for or can't get to by issuing a simple `curl` or `wget`. If you can't
attach it to the issue, or create a github gist, then the code you are
sending is too large.
Also try to narrow the bug. See below.
## What to send (additional helpful information)
Some kind folks also give the invocation they used and the output
which usually includes an error message produced. This is helpful. I
can figure out what OS you are running this on and what version of
*uncomplye6* was used. Therefore, if you don't provide the input
command and the output from that, please give:
which usually includes an error message produced. This is
helpful. From this, I can figure out what OS you are running this on
and what version of *uncomplye6* was used. Therefore, if you don't
provide the input command and the output from that, please give:
* _uncompile6_ version used
* _uncompyle6_ version used
* OS that you used this on
* Python interpreter version used
@@ -37,17 +125,29 @@ command and the output from that, please give:
### But I don't *have* the source code!
Sure, I get it. No problem. There is Python assembly code on parse
errors, so simply by hand decompile that. To get a full disassembly, use pydisasm from the [xdis](https://pypi.python.org/pypi/xdis) package. Opcodes are described in the documentation for the [dis](https://docs.python.org/3.6/library/dis.html) module.
errors, so simply by hand decompile that. To get a full disassembly,
use `pydisasm` from the [xdis](https://pypi.python.org/pypi/xdis)
package. Opcodes are described in the documentation for
the [dis](https://docs.python.org/3.6/library/dis.html) module.
### But I don't *have* the source code and am incapable of figuring how how to do a hand disassembly!
Well, you could learn. No one is born into this world knowing how to disassemble Python bytecode. And as Richard Feynman once said, "What one fool can learn, so can another."
Well, you could learn. No one is born into this world knowing how to
disassemble Python bytecode. And as Richard Feynman once said, "What
one fool can learn, so can another."
If this is too difficult, or too time consuming, or not of interest to
you, then perhaps what require is a decompilation service. [Crazy
Compilers](http://www.crazy-compilers.com/decompyle/) offers a
byte-code decompiler service for versions of Python up to 2.6. (If
there are others around let me know and I'll list them here.)
## Narrowing the problem
I don't need the entire source code base for which one file or module
can't be decompiled. I just need that one file or module only. If
there are several files, file a bug report for each file.
I don't need or want the entire source code base for the file(s) or
module(s) can't be decompiled. I just need those file(s) or module(s).
If there are problems in several files, file a bug report for each
file.
Python modules can get quite large, and usually decompilation problems
occur in a single function or maybe the main-line code but not any of
@@ -61,3 +161,27 @@ properly on a neighboring version of Python. That is helpful too.
In sum, the more you can isolate or narrow the problem, the more
likley the problem will be fixed and fixed sooner.
## Confidentiality of Bug Reports
When you report a bug, you are giving up confidentiality to the source
code and the byte code. However, I would imagine that if you have
narrowed the problem sufficiently, confidentiality of the little that
remains would not be an issue.
However feel free to remove any commments, and modify variable names
or constants in the source code.
## Ethics
I do not condone using this program for unethical or illegal purposes.
More detestful, at least to me, is asking for help to assist you in
something that might not legitimate.
Don't use the issue tracker for such solicitations. To try to stave
off illegitimate behavior, you should note that the issue tracker, the
code, and bugs mentioned in that are in the open: there is no
confidentiality. You may be asked about the authorship or claimed
ownership of the bytecode. If I think something is not quite right, I
may label the issue questionable which may make the it easier those
who are looking for illegal activity.

View File

@@ -11,7 +11,7 @@ RM ?= rm
LINT = flake8
#EXTRA_DIST=ipython/ipy_trepan.py trepan
PHONY=all check clean pytest check-long dist distclean lint flake8 test rmChangeLog clean_pyc
PHONY=all check clean distcheck pytest check-long dist distclean lint flake8 test rmChangeLog clean_pyc
TEST_TYPES=check-long check-short check-2.7 check-3.4
@@ -36,13 +36,15 @@ check-2.7 check-3.3 check-3.4: pytest
check-3.0 check-3.1 check-3.2 check-3.5 check-3.6:
$(MAKE) -C test $@
check-3.7: pytest
#:Tests for Python 2.6 (doesn't have pytest)
check-2.6:
check-2.4 check-2.5 check-2.6:
$(MAKE) -C test $@
#:PyPy 2.6.1 or PyPy 5.0.1
#:PyPy 2.6.1 PyPy 5.0.1, or PyPy 5.8.0-beta0
# Skip for now
2.6 5.0 5.3:
2.6 5.0 5.3 5.6 5.8:
#:PyPy pypy3-2.4.0 Python 3:
pypy-3.2 2.4:
@@ -58,9 +60,13 @@ clean: clean_pyc
(cd test && $(MAKE) clean)
#: Create source (tarball) and wheel distribution
dist:
dist: distcheck
$(PYTHON) ./setup.py sdist bdist_wheel
# perform some checks on the package via setup.py
distcheck:
$(PYTHON) ./setup.py check
#: Remove .pyc files
clean_pyc:
( cd uncompyle6 && $(RM) -f *.pyc */*.pyc )
@@ -87,7 +93,7 @@ bdist_egg:
#: Create binary wheel distribution
bdist_wheel:
wheel:
$(PYTHON) ./setup.py bdist_wheel

164
NEWS
View File

@@ -1,10 +1,150 @@
uncompyle6 2.9.11 2016-04-06
uncompyle6 2.14.0 2017-12-10 Dr. Gecko
- Many decompilation bugfixes
- Grammar rule reduction and version isolation
- Match higher-level nonterminal names more closely
with Python AST
- Start automated Python stdlib testing - full round trip
uncompyle6 2.14.0 2017-11-26 johnnybamazing
- Start to isolate grammar rules between versions
and remove used grammar rules
- Fix a number of bytecode decompile problems
(many more remain)
- Add stdlib/runtests.sh for even more rigourous testing
uncompyle6 2.13.3 2017-11-13
Overall: better 3.6 decompiling and some much needed code refactoring and cleanup
- Start noting names in for template-action names; these are
used to check/assert we have the right node type
- Simplify <import_from> rule
- Pypy 5.80-beta testing tolerance
- Start to clean up instruction mangling phase by using 3.6-style instructions
rather trying to parse the bytecode array. This largely been done in for versions 3.x;
3.0 custom mangling code has been reduced;
some 2.x conversion has been done, but more is desired. This make it possible to...
- Handle EXTENDED_ARGS better. While relevant to all Python versions it is most noticeable in
version 3.6+ where in switching to wordcodes the size of operands has been reduced from 2**16
to 2**8. JUMP instruction then often need EXTENDED_ARGS.
- Refactor find_jump_targets() with via working of of instructions rather the bytecode array.
- use --weak-verify more and additional fuzzing on verify()
- fragment parser now ignores errors in nested function definitions; an parameter was
added to assist here. Ignoring errors may be okay because the fragment parser often just needs,
well, *fragments*.
- Distinguish RETURN_VALUE from RETURN_END_IF in exception bodies better in 3.6
- bug in 3.x language changes: import queue va import Queue
- reinstate some bytecode tests since decompiling has gotten better
- Revise how to report a bug
uncompyle6 2.13.2 2017-10-12
- Re-release using a more automated approach
uncompyle6 2.13.1 2017-10-11
- Re-release because Python 2.4 source uploaded rather than 2.6-3.6
uncompyle6 2.13.0 2017-10-10
- Fixes in deparsing lambda expressions
- Improve table-semantics descriptions
- Document hacky customize arg count better (until we can remove it)
- Update to use xdis 3.7.0 or greater
uncompyle6 2.12.0 2017-09-26
- Use xdis 3.6.0 or greater now
- Small semantic table cleanups
- Python 3.4's terms a little names better
- Slightly more Python 3.7, but still failing a lot
- Cross Python 2/3 compatibility with annotation arguments
uncompyle6 2.11.5 2017-08-31
- Skeletal support for Python 3.7
uncompyle6 2.11.4 2017-08-15
* scanner and parser now allow 3-part version string lookups,
e.g. 2.7.1 We allow a float here, but if passed a string like '2.7'. or
* unpin 3.5.1. xdis 3.5.4 has been releasd and fixes the problems we had. Use that.
* some routnes here moved to xdis. Use the xdis version
* README.rst: Link typo Name is trepan2 now not trepan
* xdis-forced change adjust for COMPARE_OP "is-not" in
semanatic routines. We need "is not".
* Some PyPy tolerance in validate testing.
* Some pyston tolerance
uncompyle6 2.11.3 2017-08-09
Very minor changes
- RsT doc fixes and updates
- use newer xdis, but not too new; 3.5.2 breaks uncompyle6
- use xdis opcode sets
- xdis "exception match" is now "exception-match"
uncompyle6 2.11.2 2017-07-09
- Start supporting Pypy 3.5 (5.7.1-beta)
- use xdis 3.5.0's opcode sets and require xdis 3.5.0
- Correct some Python 2.4-2.6 loop detection
- guard against badly formatted bytecode
uncompyle6 2.11.1 2017-06-25
- Python 3.x annotation and function signature fixes
- Bump xdis version
- Small pysource bug fixes
uncompyle6 2.11.0 2017-06-18 Fleetwood
- Major improvements in fragment tracking
* Add nonterminal node in extractInfo
* tag more offsets in expressions
* tag array subscripts
* set YIELD value offset in a <yield> expr
* fix a long-standing bug in not adjusting final AST when melding other deparse ASTs
- Fixes yet again for make_function node handling; document what's up here
- Fix bug in snowflake Python 3.5 *args kwargs
uncompyle6 2.10.1 2017-06-3 Marylin Frankel
- fix some fragments parsing bugs
- was returning the wrong type sometimes in deparse_code_around_offset()
- capture function name in offsets
- track changes to ifelstrmtr node from pysource into fragments
uncompyle6 2.10.0 2017-05-30 Elaine Gordon
- Add fuzzy offset deparse look up
- 3.6 bug fixes
- fix EXTENDED_ARGS handling (and in 2.6 and others)
- semantic routine make_function fragments.py
- MAKE_FUNCTION handling
- CALL_FUNCTION_EX handling
- async property on defs
- support for CALL_FUNCTION_KW (moagstar)
- 3.5+ UNMAP_PACK and BUILD_UNMAP_PACK handling
- 3.5 FUNCTION_VAR bug
- 3.x pass statement insdie while True
- Improve 3.2 decompilation
- Fixed -o argument processing (grkov90)
- Reduce scope of LOAD_ASSERT as expr to 3.4+
- "await" statement fixes
- 2.3, 2.4 "if 1 .." fixes
- 3.x annotation fixes
uncompyle6 2.9.11 2017-04-06
- Better support for Python 3.5+ BUILD_MAP_UNPACK
- Start 3.6 CALL_FUNCTION_EX support
- Many decompilation bug fixes. (Many more remain). See ChangeLog
uncompyle6 2.9.10 2016-02-25
uncompyle6 2.9.10 2017-02-25
- Python grammar rule fixes
- Add ability to get grammar coverage on runs
@@ -71,7 +211,7 @@ uncompyle6 2.9.6 2016-11-20
uncompyle6 2.9.5 2016-11-13
- Fix Python 3 bugs:
* improprer while 1 else
* improper while 1 else
* docstring indent
* 3.3 default values in lambda expressions
* start 3.0 decompilation (needs newer xdis)
@@ -81,12 +221,12 @@ uncompyle6 2.9.5 2016-11-13
uncompyle6 2.9.4 2016-11-02
- Handle Python 3.x function annotations
- track def keywoard-parameter line-splitting in source code better
- track def keyword-parameter line-splitting in source code better
- bump min xdis version to mask previous xdis bug
uncompyle6 2.9.3 2016-10-26
Release forced by incompatiblity change in xdis 3.2.0.
Release forced by incompatibility change in xdis 3.2.0.
- Python 3.1 bugs:
* handle "with ... as"
@@ -118,7 +258,7 @@ uncompyle6 2.9.0 2016-10-09
this Forces change in requirements.txt and _pkg_info_.py
- Start Python 1.5 decompiling; another round of work is needed to
remove bugs
- Simpify python 2.1 grammar
- Simplify python 2.1 grammar
- Fix bug with -t ... Wasn't showing source text when -t option was given
- Fix 2.1-2.6 bug in list comprehension
@@ -141,7 +281,7 @@ control-flow structure detection is done.
. 3.0 .. 3.2 *args processing
. 3.0 .. 3.2 call name and kwargs bug
. 3.0 .. getting parameter of *
. 3.0 .. handling varible number of args
. 3.0 .. handling variable number of args
. 3.0 .. "if" structure bugs
* 3.5+ if/else bugs
* 2.2-2.6 bugs
@@ -192,7 +332,7 @@ uncompyle6 2.7.1 2016-07-26
uncompyle6 2.7.0 2016-07-15
- Many Syntax and verifification bugs removed
- Many Syntax and verification 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.
@@ -219,9 +359,9 @@ uncompyle6 2.6.0 2016-07-07
- Better <2.6 vs. 2.7 grammar separation
- Fix some 2.7 deparsing bugs
- Fix bug in installing uncompyle6 script
- Doc improvments
- Doc improvements
uncompyle6 2.5.0 2016-06-22 Summer Solstace
uncompyle6 2.5.0 2016-06-22 Summer Solstice
- Much better Python 3.2-3.5 coverage.
3.4.6 is probably the best;3.2 and 3.5 are weaker
@@ -233,7 +373,7 @@ uncompyle6 2.5.0 2016-06-22 Summer Solstace
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
* Python 3.2 to 3.5 libraries largely
uncompyle and most verify
- pydisassembler:
* disassembles all code objects in a file
@@ -291,7 +431,7 @@ uncompyle6 2.2.0 2016-04-30
uncompyle6 2.2.0 2016-04-02
- Support single-mode (in addtion to exec-mode) compilation
- Support single-mode (in addition to exec-mode) compilation
- Start to DRY Python 2 and Python 3 grammars
- Fix bug in if else ternary construct
- Fix bug in uncomplye6 -d and -r options (via lelicopter)

View File

@@ -1,10 +1,10 @@
|buildstatus| |Supported Python Versions|
|buildstatus|
uncompyle6
==========
A native Python cross-version Decompiler and Fragment Decompiler.
Follows in the tradition of decompyle, uncompyle, and uncompyle2.
A native Python cross-version decompiler and fragment decompiler.
The successor to decompyle, uncompyle, and uncompyle2.
Introduction
@@ -12,34 +12,53 @@ Introduction
*uncompyle6* translates Python bytecode back into equivalent Python
source code. It accepts bytecodes from Python version 1.5, and 2.1 to
3.6 or so, including PyPy bytecode and Dropbox's Python 2.5 bytecode.
3.7 or so, including PyPy bytecode and Dropbox's Python 2.5 bytecode.
Why this?
---------
There were a number of decompyle, uncompile, uncompyle2, uncompyle3
forks around. All of them came basically from the same code base, and
almost all of them no were no longer actively maintained. Only one
handled Python 3, and even there, only 3.2 or 3.3 depending on which
code is used. This code pulls these together and moves forward. This
project has the most complete support for Python 3.3 and above. It
also addresses a number of open issues in the previous forks.
Ok, I'll say it: this software is amazing. It is more than your
normal hacky decompiler. Using compiler_ technology, the program
creates a parse tree of the program from the instructions; nodes at
the upper levels that look a little like what might come from a Python
AST. So we can really classify and understand what's going on in
sections of Python bytecode.
What makes this different from other CPython bytecode decompilers?: its
ability to deparse just fragments and give source-code information
around a given bytecode offset.
Building on this, another thing that makes this different from other
CPython bytecode decompilers is the ability to deparse just
*fragments* of source code and give source-code information around a
given bytecode offset.
I use this to deparse fragments of code inside my trepan_
debuggers_. For that, I need to record text fragments for all
bytecode offsets (of interest). This purpose although largely
compatible with the original intention is yet a little bit different.
I use the tree fragments to deparse fragments of code inside my
trepan_ debuggers_. For that, bytecode offsets are recorded and
associated with fragments of the source code. This purpose, although
compatible with the original intention, is yet a little bit different.
See this_ for more information.
The idea of Python fragment deparsing given an instruction offset can
be used in showing stack traces or any program that wants to show a
location in more detail than just a line number. It can be also used
when source-code information does not exist and there is just bytecode
information.
Python fragment deparsing given an instruction offset is useful in
showing stack traces and can be encorporated into any program that
wants to show a location in more detail than just a line number at
runtime. This code can be also used when source-code information does
not exist and there is just bytecode. Again, my debuggers make use of
this.
There were (and still are) a number of decompyle, uncompyle,
uncompyle2, uncompyle3 forks around. Almost all of them come basically
from the same code base, and (almost?) all of them are no longer
actively maintained. One was really good at decompiling Python 1.5-2.3
or so, another really good at Python 2.7, but that only. Another
handles Python 3.2 only; another patched that and handled only 3.3.
You get the idea. This code pulls all of these forks together and
*moves forward*. There is some serious refactoring and cleanup in this
code base over those old forks.
This project has the most complete support for Python 3.3 and above
and the best all-around Python support.
We are serious about testing, and use automated processes to find
bugs. In the issue trackers for other decompilers, you will find a
number of bugs we've found along the way. Very few to none of them are
fixed in the other decompilers.
Requirements
------------
@@ -56,11 +75,9 @@ This uses setup.py, so it follows the standard Python routine:
::
pip install -r requirements.txt
pip install -r requirements-dev.txt
pip install -e . # set up to run from source tree
# Or if you want to install instead
python setup.py install # may need sudo
# or if you have pyenv:
python setup.py develop
A GNU makefile is also provided so :code:`make install` (possibly as root or
sudo) will do the steps above.
@@ -109,14 +126,14 @@ Known Bugs/Restrictions
-----------------------
The biggest known and possibly fixable (but hard) problem has to do
with handling control flow. All of the Python decompilers I have looked
at have the same problem. In some cases we can detect an erroneous
decompilation and report that.
with handling control flow. (Python has probably the most diverse and
screwy set of compound statements I've ever seen; a number of the
usual ones like else clauses on loops and try blocks I suspect most
programmers don't know about.)
Over 98% of the decompilation of Python standard library packages in
Python 2.7.12 verifies correctly. Over 99% of Python 2.7 and 3.3-3.5
"weakly" verify. Python 2.6 drops down to 96% weakly verifying.
Other versions drop off in quality too.
All of the Python decompilers I have looked at have the same
problem. In some cases we can detect an erroneous decompilation and
report that.
*Verification* is the process of decompiling bytecode, compiling with
a Python for that bytecode version, and then comparing the bytecode
@@ -134,6 +151,17 @@ program by running the Python interpreter. Because the Python language
has changed so much, for best results you should use the same Python
Version in checking as used in the bytecode.
Finally, we have automated running the standard Python tests after
first compiling and decompiling the test program. Results here are a
bit weak (if not better than most other Python decompilers). But over
time this will probably get better.
Python support is strongest in Python 2 for 2.7 and drops off as you
get further away from that. Support is also probably pretty good for
python 2.3-2.4 since a lot of the goodness of early the version of the
decompiler from that era has been preserved (and Python compilation in
that era was minimal)
Later distributions average about 200 files. There is some work to do
on the lower end Python versions which is more difficult for us to
handle since we don't have a Python interpreter for versions 1.5, 1.6,
@@ -144,7 +172,9 @@ In the Python 3 series, Python support is is strongest around 3.4 or
3.6 changes things drastically by using word codes rather than byte
codes. That has been addressed, but then it also changes function call
opcodes and its semantics and has more problems with control flow than
3.5 has.
3.5 has. Between Python 3.5, 3.6 and 3.7 there have been major changes
to the `MAKE_FUNCTION` and `CALL_FUNCTION` instructions. Those are
not handled yet.
Currently not all Python magic numbers are supported. Specifically in
some versions of Python, notably Python 3.6, the magic number has
@@ -168,12 +198,17 @@ 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 what is used here.
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Include some fixes like supporting function annotations
* https://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.
* `How to report a bug <https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>`_
* https://github.com/rocky/python-xdis : Cross Python version disassembler
* https://github.com/rocky/python-xasm : Cross Python version assembler
* https://github.com/rocky/python-uncompyle6/wiki : Wiki Documents which describe the code and aspects of it in more detail
.. |downloads| image:: https://img.shields.io/pypi/dd/uncompyle6.svg
.. _trepan: https://pypi.python.org/pypi/trepan
.. _trepan: https://pypi.python.org/pypi/trepan2
.. _compiler: https://pypi.python.org/pypi/spark_parser
.. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md
.. _debuggers: https://pypi.python.org/pypi/trepan3k
.. _remake: https://bashdb.sf.net/remake
@@ -181,7 +216,5 @@ See Also
.. _this: https://github.com/rocky/python-uncompyle6/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting
.. |buildstatus| image:: https://travis-ci.org/rocky/python-uncompyle6.svg
:target: https://travis-ci.org/rocky/python-uncompyle6
.. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/uncompyle6.svg
:target: https://pypi.python.org/pypi/uncompyle6/
.. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84
.. _Deobfuscator: https://github.com/extremecoders-re/PjOrion-Deobfuscator

View File

@@ -33,14 +33,14 @@ classifiers = ['Development Status :: 5 - Production/Stable',
# The rest in alphabetic order
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
author_email = "rb@dustyfeet.com"
entry_points={
entry_points = {
'console_scripts': [
'uncompyle6=uncompyle6.bin.uncompile:main_bin',
'pydisassemble=uncompyle6.bin.pydisassemble:main',
]}
ftp_url = None
install_requires = ['spark-parser >= 1.6.0, < 1.7.0',
'xdis >= 3.3.0, < 3.4.0']
install_requires = ['spark-parser >= 1.8.4, < 1.9.0',
'xdis >= 3.6.2, < 3.7.0']
license = 'MIT'
mailing_list = 'python-debugger@googlegroups.com'
modname = 'uncompyle6'

11
admin-tools/README.md Normal file
View File

@@ -0,0 +1,11 @@
Making a release is a somewhat tedious process so I've automated it a little
Here are tools that I, rocky, use to check and build a distribution.
They are customized to my environment:
- I use pyenv to various Python versions installed
- I have git repos for xdis, and spark parser at the same level as uncompyle6
There may be other rocky-specific things that need customization.
how-to-make-a-release.txt has overall how I make a release

View File

@@ -0,0 +1,26 @@
#!/bin/bash
function finish {
cd $owd
}
# FIXME put some of the below in a common routine
owd=$(pwd)
trap finish EXIT
cd $(dirname ${BASH_SOURCE[0]})
if ! source ./pyenv-newer-versions ; then
exit $?
fi
if ! source ./setup-master.sh ; then
exit $?
fi
cd ..
for version in $PYVERSIONS; do
if ! pyenv local $version ; then
exit $?
fi
make clean && pip install -e .
if ! make check; then
exit $?
fi
done

View File

@@ -0,0 +1,25 @@
#!/bin/bash
function finish {
cd $owd
}
owd=$(pwd)
trap finish EXIT
cd $(dirname ${BASH_SOURCE[0]})
if ! source ./pyenv-older-versions ; then
exit $?
fi
if ! source ./setup-python-2.4.sh ; then
exit $?
fi
cd ..
for version in $PYVERSIONS; do
if ! pyenv local $version ; then
exit $?
fi
make clean && python setup.py develop
if ! make check ; then
exit $?
fi
done

View File

@@ -0,0 +1,87 @@
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
**Table of Contents**
- [Get latest sources:](#get-latest-sources)
- [Change version in uncompyle6/version.py](#change-version-in-uncompyle6versionpy)
- [Update ChangeLog:](#update-changelog)
- [Update NEWS from ChangeLog:](#update-news-from-changelog)
- [Make sure pyenv is running and check newer versions](#make-sure-pyenv-is-running-and-check-newer-versions)
- [Switch to python-2.4, sync that up and build that first since it creates a tarball which we don't want.](#switch-to-python-24-sync-that-up-and-build-that-first-since-it-creates-a-tarball-which-we-dont-want)
- [Update NEWS from master branch](#update-news-from-master-branch)
- [Check against all versions](#check-against-all-versions)
- [Make packages and tag](#make-packages-and-tag)
- [Upload single package and look at Rst Formating](#upload-single-package-and-look-at-rst-formating)
- [Upload rest of versions](#upload-rest-of-versions)
- [Push tags:](#push-tags)
<!-- markdown-toc end -->
# Get latest sources:
$ . ./admin-tool/update-sources.sh
# Change version in uncompyle6/version.py:
$ emacs uncompyle6/version.py
$ source uncompyle6/version.py
$ echo $VERSION
$ git commit -m"Get ready for release $VERSION" .
# Update ChangeLog:
$ make ChangeLog
# Update NEWS from ChangeLog:
$ emacs NEWS
$ make check
$ git commit --amend .
$ git push # get CI testing going early
# Make sure pyenv is running and check newer versions
$ pyenv local && source admin-tools/check-newer-versions.sh
# Switch to python-2.4, sync that up and build that first since it creates a tarball which we don't want.
$ source admin-tools/setup-python-2.4.sh
$ rm ChangeLog
$ git merge master
# Update NEWS from master branch
$ git commit -m"Get ready for release $VERSION" .
# Check against all versions
$ source admin-tools/check-older-versions.sh
# Make packages and tag
$ . ./admin-tools/make-dist-older.sh
$ git tag release-python-2.4-$VERSION
$ . /admin-tools/make-dist-newer.sh
$ git tag release-$VERSION
# Upload single package and look at Rst Formating
$ twine upload dist/uncompyle6-${VERSION}-py3.3.egg
# Upload rest of versions
$ twine upload dist/uncompyle6-${VERSION}*
# Push tags:
$ git push --tags
# Check on a VM
$ cd /virtual/vagrant/virtual/vagrant/ubuntu-zesty
$ vagrant up
$ vagrant ssh
$ pyenv local 3.5.2
$ pip install --upgrade uncompyle6
$ exit
$ vagrant halt

View File

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

38
admin-tools/make-dist-newer.sh Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/bash
PACKAGE=uncompyle6
# FIXME put some of the below in a common routine
function finish {
cd $owd
}
cd $(dirname ${BASH_SOURCE[0]})
owd=$(pwd)
trap finish EXIT
if ! source ./pyenv-newer-versions ; then
exit $?
fi
if ! source ./setup-master.sh ; then
exit $?
fi
cd ..
source $PACKAGE/version.py
echo $VERSION
for pyversion in $PYVERSIONS; do
if ! pyenv local $pyversion ; then
exit $?
fi
# pip bdist_egg create too-general wheels. So
# we narrow that by moving the generated wheel.
# Pick out first two number of version, e.g. 3.5.1 -> 35
first_two=$(echo $pyversion | cut -d'.' -f 1-2 | sed -e 's/\.//')
rm -fr build
python setup.py bdist_egg bdist_wheel
mv -v dist/${PACKAGE}-$VERSION-{py2.py3,py$first_two}-none-any.whl
done
python ./setup.py sdist

39
admin-tools/make-dist-older.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/bash
PACKAGE=uncompyle6
# FIXME put some of the below in a common routine
function finish {
cd $owd
}
owd=$(pwd)
trap finish EXIT
cd $(dirname ${BASH_SOURCE[0]})
if ! source ./pyenv-older-versions ; then
exit $?
fi
if ! source ./setup-python-2.4.sh ; then
exit $?
fi
cd ..
source $PACKAGE/version.py
echo $VERSION
for pyversion in $PYVERSIONS; do
if ! pyenv local $pyversion ; then
exit $?
fi
rm -fr build
python setup.py bdist_egg
done
# Pypi can only have one source tarball.
# Tarballs can get created from the above setup, so make sure to remove them since we want
# the tarball from master.
tarball=dist/${PACKAGE}-$VERSION-tar.gz
if [[ -f $tarball ]]; then
rm -v dist/${PACKAGE}-$VERSION-tar.gz
fi

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,22 @@
#!/bin/bash
PYTHON_VERSION=3.6.3
# FIXME put some of the below in a common routine
function finish {
cd $owd
}
export PATH=$HOME/.pyenv/bin/pyenv:$PATH
owd=$(pwd)
bs=${BASH_SOURCE[0]}
if [[ $0 == $bs ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
mydir=$(dirname $bs)
fulldir=$(readlink -f $mydir)
cd $fulldir/..
(cd ../python-spark && git checkout master && pyenv local $PYTHON_VERSION) && git pull && \
(cd ../python-xdis && git checkout master && pyenv local $PYTHON_VERSION) && git pull && \
git checkout master && pyenv local $PYTHON_VERSION && git pull
cd $owd

View File

@@ -0,0 +1,16 @@
#!/bin/bash
PYTHON_VERSION=2.4.6
owd=$(pwd)
bs=${BASH_SOURCE[0]}
if [[ $0 == $bs ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
mydir=$(dirname $bs)
fulldir=$(readlink -f $mydir)
cd $fulldir/..
(cd ../python-spark && git checkout python-2.4 && pyenv local $PYTHON_VERSION) && git pull && \
(cd ../python-xdis && git checkout python-2.4 && pyenv local $PYTHON_VERSION) && git pull && \
git checkout python-2.4 && pyenv local $PYTHON_VERSION && git pull
cd $owd

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

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

78
appveyor.yml Normal file
View File

@@ -0,0 +1,78 @@
environment:
global:
# SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
# /E:ON and /V:ON options are not enabled in the batch script intepreter
# See: http://stackoverflow.com/a/13751649/163740
CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd"
matrix:
# Pre-installed Python versions, which Appveyor may upgrade to
# a later point release.
# See: http://www.appveyor.com/docs/installed-software#python
# - PYTHON: "C:\\Python27"
# PYTHON_VERSION: "2.7.x"
# PYTHON_ARCH: "32"
- PYTHON: "C:\\Python27-x64"
PYTHON_VERSION: "2.7.x"
PYTHON_ARCH: "64"
# - PYTHON: "C:\\Python26"
# PYTHON_VERSION: "2.6.x"
# PYTHON_ARCH: "32"
# - PYTHON: "C:\\Python26-x64"
# PYTHON_VERSION: "2.6.x"
# PYTHON_ARCH: "64"
install:
# We need wheel installed to build wheels
- "%PYTHON%\\python.exe -m pip install wheel"
# Install Python (from the official .msi of http://python.org) and pip when
# not already installed.
- ps: if (-not(Test-Path($env:PYTHON))) { & appveyor\install.ps1 }
# Prepend newly installed Python to the PATH of this build (this cannot be
# done from inside the powershell script as it would require to restart
# the parent CMD process).
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- "SET HOME=."
# Check that we have the expected version and architecture for Python
- "python --version"
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
# 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"
# Install the build dependencies of the project. If some dependencies contain
# compiled extensions and are not provided as pre-built wheel packages,
# pip will build them from source using the MSVC compiler matching the
# target Python version and architecture
- "%CMD_IN_ENV% pip install -r requirements.txt"
build_script:
# Build the compiled extension
- "%CMD_IN_ENV% python setup.py build"
test_script:
# Run the project tests
- "%CMD_IN_ENV% python test/test_pyenvlib.py --native --weak-verify"
after_test:
# If tests are successful, create binary packages for the project.
- "%CMD_IN_ENV% python setup.py bdist_wininst"
- "%CMD_IN_ENV% python setup.py bdist_msi"
- ps: "ls dist"
artifacts:
# Archive the generated packages in the ci.appveyor.com build report.
- path: dist\*
#on_success:
# - TODO: upload the content of dist/*.whl to a public wheelhouse
#

229
appveyor/install.ps1 Normal file
View File

@@ -0,0 +1,229 @@
# Sample script to install Python and pip under Windows
# Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer
# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
$MINICONDA_URL = "http://repo.continuum.io/miniconda/"
$BASE_URL = "https://www.python.org/ftp/python/"
$GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
$GET_PIP_PATH = "C:\get-pip.py"
$PYTHON_PRERELEASE_REGEX = @"
(?x)
(?<major>\d+)
\.
(?<minor>\d+)
\.
(?<micro>\d+)
(?<prerelease>[a-z]{1,2}\d+)
"@
function Download ($filename, $url) {
$webclient = New-Object System.Net.WebClient
$basedir = $pwd.Path + "\"
$filepath = $basedir + $filename
if (Test-Path $filename) {
Write-Host "Reusing" $filepath
return $filepath
}
# Download and retry up to 3 times in case of network transient errors.
Write-Host "Downloading" $filename "from" $url
$retry_attempts = 2
for ($i = 0; $i -lt $retry_attempts; $i++) {
try {
$webclient.DownloadFile($url, $filepath)
break
}
Catch [Exception]{
Start-Sleep 1
}
}
if (Test-Path $filepath) {
Write-Host "File saved at" $filepath
} else {
# Retry once to get the error message if any at the last try
$webclient.DownloadFile($url, $filepath)
}
return $filepath
}
function ParsePythonVersion ($python_version) {
if ($python_version -match $PYTHON_PRERELEASE_REGEX) {
return ([int]$matches.major, [int]$matches.minor, [int]$matches.micro,
$matches.prerelease)
}
$version_obj = [version]$python_version
return ($version_obj.major, $version_obj.minor, $version_obj.build, "")
}
function DownloadPython ($python_version, $platform_suffix) {
$major, $minor, $micro, $prerelease = ParsePythonVersion $python_version
if (($major -le 2 -and $micro -eq 0) `
-or ($major -eq 3 -and $minor -le 2 -and $micro -eq 0) `
) {
$dir = "$major.$minor"
$python_version = "$major.$minor$prerelease"
} else {
$dir = "$major.$minor.$micro"
}
if ($prerelease) {
if (($major -le 2) `
-or ($major -eq 3 -and $minor -eq 1) `
-or ($major -eq 3 -and $minor -eq 2) `
-or ($major -eq 3 -and $minor -eq 3) `
) {
$dir = "$dir/prev"
}
}
if (($major -le 2) -or ($major -le 3 -and $minor -le 4)) {
$ext = "msi"
if ($platform_suffix) {
$platform_suffix = ".$platform_suffix"
}
} else {
$ext = "exe"
if ($platform_suffix) {
$platform_suffix = "-$platform_suffix"
}
}
$filename = "python-$python_version$platform_suffix.$ext"
$url = "$BASE_URL$dir/$filename"
$filepath = Download $filename $url
return $filepath
}
function InstallPython ($python_version, $architecture, $python_home) {
Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home
if (Test-Path $python_home) {
Write-Host $python_home "already exists, skipping."
return $false
}
if ($architecture -eq "32") {
$platform_suffix = ""
} else {
$platform_suffix = "amd64"
}
$installer_path = DownloadPython $python_version $platform_suffix
$installer_ext = [System.IO.Path]::GetExtension($installer_path)
Write-Host "Installing $installer_path to $python_home"
$install_log = $python_home + ".log"
if ($installer_ext -eq '.msi') {
InstallPythonMSI $installer_path $python_home $install_log
} else {
InstallPythonEXE $installer_path $python_home $install_log
}
if (Test-Path $python_home) {
Write-Host "Python $python_version ($architecture) installation complete"
} else {
Write-Host "Failed to install Python in $python_home"
Get-Content -Path $install_log
Exit 1
}
}
function InstallPythonEXE ($exepath, $python_home, $install_log) {
$install_args = "/quiet InstallAllUsers=1 TargetDir=$python_home"
RunCommand $exepath $install_args
}
function InstallPythonMSI ($msipath, $python_home, $install_log) {
$install_args = "/qn /log $install_log /i $msipath TARGETDIR=$python_home"
$uninstall_args = "/qn /x $msipath"
RunCommand "msiexec.exe" $install_args
if (-not(Test-Path $python_home)) {
Write-Host "Python seems to be installed else-where, reinstalling."
RunCommand "msiexec.exe" $uninstall_args
RunCommand "msiexec.exe" $install_args
}
}
function RunCommand ($command, $command_args) {
Write-Host $command $command_args
Start-Process -FilePath $command -ArgumentList $command_args -Wait -Passthru
}
function InstallPip ($python_home) {
$pip_path = $python_home + "\Scripts\pip.exe"
$python_path = $python_home + "\python.exe"
if (-not(Test-Path $pip_path)) {
Write-Host "Installing pip..."
$webclient = New-Object System.Net.WebClient
$webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH)
Write-Host "Executing:" $python_path $GET_PIP_PATH
& $python_path $GET_PIP_PATH
} else {
Write-Host "pip already installed."
}
}
function DownloadMiniconda ($python_version, $platform_suffix) {
if ($python_version -eq "3.4") {
$filename = "Miniconda3-3.5.5-Windows-" + $platform_suffix + ".exe"
} else {
$filename = "Miniconda-3.5.5-Windows-" + $platform_suffix + ".exe"
}
$url = $MINICONDA_URL + $filename
$filepath = Download $filename $url
return $filepath
}
function InstallMiniconda ($python_version, $architecture, $python_home) {
Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home
if (Test-Path $python_home) {
Write-Host $python_home "already exists, skipping."
return $false
}
if ($architecture -eq "32") {
$platform_suffix = "x86"
} else {
$platform_suffix = "x86_64"
}
$filepath = DownloadMiniconda $python_version $platform_suffix
Write-Host "Installing" $filepath "to" $python_home
$install_log = $python_home + ".log"
$args = "/S /D=$python_home"
Write-Host $filepath $args
Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru
if (Test-Path $python_home) {
Write-Host "Python $python_version ($architecture) installation complete"
} else {
Write-Host "Failed to install Python in $python_home"
Get-Content -Path $install_log
Exit 1
}
}
function InstallMinicondaPip ($python_home) {
$pip_path = $python_home + "\Scripts\pip.exe"
$conda_path = $python_home + "\Scripts\conda.exe"
if (-not(Test-Path $pip_path)) {
Write-Host "Installing pip..."
$args = "install --yes pip"
Write-Host $conda_path $args
Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru
} else {
Write-Host "pip already installed."
}
}
function main () {
InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON
InstallPip $env:PYTHON
}
main

87
appveyor/run_with_env.cmd Normal file
View File

@@ -0,0 +1,87 @@
:: To build extensions for 64 bit Python 3, we need to configure environment
:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1)
::
:: To build extensions for 64 bit Python 2, we need to configure environment
:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of:
:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0)
::
:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific
:: environment configurations.
::
:: Note: this script needs to be run with the /E:ON and /V:ON flags for the
:: cmd interpreter, at least for (SDK v7.0)
::
:: More details at:
:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
:: http://stackoverflow.com/a/13751649/163740
::
:: Author: Olivier Grisel
:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
::
:: Notes about batch files for Python people:
::
:: Quotes in values are literally part of the values:
:: SET FOO="bar"
:: FOO is now five characters long: " b a r "
:: If you don't want quotes, don't include them on the right-hand side.
::
:: The CALL lines at the end of this file look redundant, but if you move them
:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y
:: case, I don't know why.
@ECHO OFF
SET COMMAND_TO_RUN=%*
SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
SET WIN_WDK=c:\Program Files (x86)\Windows Kits\10\Include\wdf
:: Extract the major and minor versions, and allow for the minor version to be
:: more than 9. This requires the version number to have two dots in it.
SET MAJOR_PYTHON_VERSION=%PYTHON_VERSION:~0,1%
IF "%PYTHON_VERSION:~3,1%" == "." (
SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1%
) ELSE (
SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,2%
)
:: Based on the Python version, determine what SDK version to use, and whether
:: to set the SDK for 64-bit.
IF %MAJOR_PYTHON_VERSION% == 2 (
SET WINDOWS_SDK_VERSION="v7.0"
SET SET_SDK_64=Y
) ELSE (
IF %MAJOR_PYTHON_VERSION% == 3 (
SET WINDOWS_SDK_VERSION="v7.1"
IF %MINOR_PYTHON_VERSION% LEQ 4 (
SET SET_SDK_64=Y
) ELSE (
SET SET_SDK_64=N
IF EXIST "%WIN_WDK%" (
:: See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/
REN "%WIN_WDK%" 0wdf
)
)
) ELSE (
ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%"
EXIT 1
)
)
IF %PYTHON_ARCH% == 64 (
IF %SET_SDK_64% == Y (
ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture
SET DISTUTILS_USE_SDK=1
SET MSSdk=1
"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
ECHO Executing: %COMMAND_TO_RUN%
call %COMMAND_TO_RUN% || EXIT 1
) ELSE (
ECHO Using default MSVC build environment for 64 bit architecture
ECHO Executing: %COMMAND_TO_RUN%
call %COMMAND_TO_RUN% || EXIT 1
)
) ELSE (
ECHO Using default MSVC build environment for 32 bit architecture
ECHO Executing: %COMMAND_TO_RUN%
call %COMMAND_TO_RUN% || EXIT 1
)

View File

@@ -6,8 +6,8 @@ machine:
dependencies:
override:
- pip install -r requirements.txt
- pip install -e .
- pip install -r requirements-dev.txt
test:
override:
- python ./setup.py develop && make check-2.7
- python ./setup.py develop && make check-2.6

View File

@@ -0,0 +1,6 @@
source ../.venv.3.6/bin/activate
py.test -k test_CALL_FUNCTION_KW
source ../.venv.3.5/bin/activate
py.test -k test_CALL_FUNCTION_KW
source ../.venv.2.7/bin/activate
py.test -k test_CALL_FUNCTION_KW

11
pytest/test_basic.py Normal file
View File

@@ -0,0 +1,11 @@
from uncompyle6.scanner import get_scanner
from uncompyle6.parser import get_python_parser
def test_get_scanner():
# See that we can retrieve a scanner using a full version number
assert get_scanner('2.7.13')
def test_get_parser():
# See that we can retrieve a sparser using a full version number
assert get_python_parser('2.7.13')

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python
from uncompyle6 import PYTHON_VERSION, IS_PYPY
from uncompyle6.scanner import get_scanner
from xdis.bytecode import Bytecode
from array import array
def bug(state, slotstate):
if state:
@@ -21,20 +22,24 @@ def bug_loop(disassemble, tb=None):
disassemble(tb)
def test_if_in_for():
code = bug.__code__
code = bug.func_code
scan = get_scanner(PYTHON_VERSION)
print(PYTHON_VERSION)
if 2.7 <= PYTHON_VERSION <= 3.0 and not IS_PYPY:
n = scan.setup_code(code)
scan.build_lines_data(code, n)
scan.build_prev_op(n)
fjt = scan.find_jump_targets(False)
assert {15: [3], 69: [66], 63: [18]} == fjt
assert scan.structs == \
[{'start': 0, 'end': 72, 'type': 'root'},
{'start': 15, 'end': 66, 'type': 'if-then'},
{'start': 31, 'end': 59, 'type': 'for-loop'},
{'start': 62, 'end': 63, 'type': 'for-else'}]
## FIXME: the data below is wrong.
## we get different results currenty as well.
## We need to probably fix both the code
## and the test below
# assert {15: [3], 69: [66], 63: [18]} == fjt
# assert scan.structs == \
# [{'start': 0, 'end': 72, 'type': 'root'},
# {'start': 15, 'end': 66, 'type': 'if-then'},
# {'start': 31, 'end': 59, 'type': 'for-loop'},
# {'start': 62, 'end': 63, 'type': 'for-else'}]
code = bug_loop.__code__
n = scan.setup_code(code)
@@ -53,9 +58,11 @@ def test_if_in_for():
{'start': 48, 'end': 67, 'type': 'while-loop'}]
elif 3.2 < PYTHON_VERSION <= 3.4:
bytecode = Bytecode(code, scan.opc)
scan.code = array('B', code.co_code)
scan.build_lines_data(code)
scan.build_prev_op()
scan.insts = list(bytecode)
fjt = scan.find_jump_targets(False)
assert {69: [66], 63: [18]} == fjt
assert scan.structs == \

View File

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

View File

@@ -1,128 +0,0 @@
# std
import string
# 3rd party
from hypothesis import given, assume, strategies as st
import pytest
# uncompyle
from validate import validate_uncompyle
alpha = st.sampled_from(string.ascii_lowercase)
numbers = st.sampled_from(string.digits)
alphanum = st.sampled_from(string.ascii_lowercase + string.digits)
expressions = st.sampled_from([x for x in string.ascii_lowercase + string.digits] + ['x+1'])
@st.composite
def function_calls(draw):
"""
Strategy factory for generating function calls.
:param draw: Callable which draws examples from other strategies.
:return: The function call text.
"""
list1 = st.lists(alpha, min_size=0, max_size=1)
list3 = st.lists(alpha, min_size=0, max_size=3)
positional_args = draw(list3)
named_args = [x + '=0' for x in draw(list3)]
star_args = ['*' + x for x in draw(list1)]
double_star_args = ['**' + x for x in draw(list1)]
arguments = positional_args + named_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, named,
# 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
@pytest.mark.xfail()
def test_CALL_FUNCTION():
validate_uncompyle("fn(w,m,f)")
@pytest.mark.xfail()
def test_BUILD_CONST_KEY_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(w=0,m=0,**v)")
@pytest.mark.xfail()
def test_BUILD_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(a=0,**g)")
@pytest.mark.xfail()
def test_CALL_FUNCTION_KW():
validate_uncompyle("fn(j=0)")
@pytest.mark.xfail()
def test_CALL_FUNCTION_EX():
validate_uncompyle("fn(*g,**j)")
@pytest.mark.xfail()
def test_BUILD_MAP_CALL_FUNCTION_EX():
validate_uncompyle("fn(*z,u=0)")
@pytest.mark.xfail()
def test_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(**a)")
@pytest.mark.xfail()
def test_BUILD_MAP_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
validate_uncompyle("fn(b,b,b=0,*a)")
@pytest.mark.xfail()
def test_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
validate_uncompyle("fn(*c,v)")
@pytest.mark.xfail()
def test_BUILD_CONST_KEY_MAP_CALL_FUNCTION_EX():
validate_uncompyle("fn(i=0,y=0,*p)")
@pytest.mark.skip(reason='skipping property based test until all individual tests are passing')
@given(function_calls())
def test_function_call(function_call):
validate_uncompyle(function_call)
examples = set()
generate_examples = False
@pytest.mark.skipif(not generate_examples, reason='not generating examples')
@given(function_calls())
def test_generate_hypothesis(function_call):
examples.add(function_call)
@pytest.mark.skipif(not generate_examples, reason='not generating examples')
def test_generate_examples():
import dis
example_opcodes = {}
for example in examples:
opcodes = tuple(sorted(set(
instruction.opname
for instruction in dis.Bytecode(example)
if instruction.opname not in ('LOAD_CONST', 'LOAD_NAME', 'RETURN_VALUE')
)))
example_opcodes[opcodes] = example
for k, v in example_opcodes.items():
print('def test_' + '_'.join(k) + '():\n validate_uncompyle("' + v + '")\n\n')
return

View File

@@ -11,41 +11,75 @@ def test_grammar():
remain_tokens = set([re.sub('_CONT$','', t) for t in remain_tokens])
remain_tokens = set(remain_tokens) - opcode_set
assert remain_tokens == set([]), \
"Remaining tokens %s\n====\n%s" % (remain_tokens, p.dumpGrammar())
"Remaining tokens %s\n====\n%s" % (remain_tokens, p.dump_grammar())
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
lhs, rhs, tokens, right_recursive = p.checkSets()
(lhs, rhs, tokens,
right_recursive, dup_rhs) = p.check_sets()
expect_lhs = set(['expr1024', 'pos_arg'])
unused_rhs = set(['build_list', 'call_function', 'mkfunc',
unused_rhs = set(['list', 'mkfunc',
'mklambda',
'unpack', 'unpack_list'])
expect_right_recursive = [['designList', ('designator', 'DUP_TOP', 'designList')]]
'unpack',])
expect_right_recursive = set([('designList',
('store', 'DUP_TOP', 'designList'))])
if PYTHON3:
expect_lhs.add('load_genexpr')
expect_lhs.add('kvlist')
expect_lhs.add('kv3')
unused_rhs = unused_rhs.union(set("""
except_pop_except genexpr classdefdeco2 listcomp
except_pop_except generator_exp classdefdeco2
dict
""".split()))
if 3.0 <= PYTHON_VERSION:
if PYTHON_VERSION >= 3.0:
expect_lhs.add("annotate_arg")
expect_lhs.add("annotate_tuple")
unused_rhs.add("mkfunc_annotate")
if PYTHON_VERSION < 3.6:
# 3.6 has at least one non-custom call rule
# the others don't
unused_rhs.add('call')
if PYTHON_VERSION == 3.5:
expect_right_recursive.add((('l_stmts',
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
pass
pass
else:
expect_right_recursive.add((('l_stmts',
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
unused_rhs.add('build_map_unpack_with_call')
unused_rhs.add('unmapexpr')
# expect_lhs.add('kwargs1')
pass
pass
pass
else:
expect_lhs.add('kwarg')
unused_rhs.add('call')
assert expect_lhs == set(lhs)
assert unused_rhs == set(rhs)
assert expect_right_recursive == right_recursive
expect_dup_rhs = frozenset([('COME_FROM',), ('CONTINUE',), ('JUMP_ABSOLUTE',),
('LOAD_CONST',),
('JUMP_BACK',), ('JUMP_FORWARD',)])
# reduced_dup_rhs = {k: dup_rhs[k] for k in dup_rhs if k not in expect_dup_rhs}
# for k in reduced_dup_rhs:
# print(k, reduced_dup_rhs[k])
# assert not reduced_dup_rhs, reduced_dup_rhs
s = get_scanner(PYTHON_VERSION, IS_PYPY)
ignore_set = set(
"""
JUMP_BACK CONTINUE RETURN_END_IF
JUMP_BACK CONTINUE
COME_FROM COME_FROM_EXCEPT
COME_FROM_EXCEPT_CLAUSE
COME_FROM_LOOP COME_FROM_WITH
COME_FROM_FINALLY ELSE
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP
LAMBDA_MARKER RETURN_LAST
LAMBDA_MARKER
RETURN_END_IF RETURN_END_IF_LAMBDA RETURN_VALUE_LAMBDA RETURN_LAST
""".split())
if 2.6 <= PYTHON_VERSION <= 2.7:
opcode_set = set(s.opc.opname).union(ignore_set)

172
pytest/test_pysource.py Normal file
View File

@@ -0,0 +1,172 @@
from uncompyle6 import PYTHON3
from uncompyle6.semantics.consts import (
escape, NONE,
# RETURN_NONE, PASS, RETURN_LOCALS
)
if PYTHON3:
from io import StringIO
else:
from StringIO import StringIO
from uncompyle6.semantics.pysource import SourceWalker as SourceWalker
def test_template_engine():
s = StringIO()
sw = SourceWalker(2.7, s, None)
sw.ast = NONE
sw.template_engine(('--%c--', 0), NONE)
print(sw.f.getvalue())
assert sw.f.getvalue() == '--None--'
# FIXME: and so on...
from uncompyle6.semantics.consts import (
TABLE_R, TABLE_DIRECT,
)
from uncompyle6.semantics.fragments import (
TABLE_DIRECT_FRAGMENT,
)
skip_for_now = "DELETE_DEREF".split()
def test_tables():
for t, name, fragment in (
(TABLE_DIRECT, 'TABLE_DIRECT', False),
(TABLE_R, 'TABLE_R', False),
(TABLE_DIRECT_FRAGMENT, 'TABLE_DIRECT_FRAGMENT', True)):
for k, entry in t.iteritems():
if k in skip_for_now:
continue
fmt = entry[0]
arg = 1
i = 0
m = escape.search(fmt)
print("%s[%s]" % (name, k))
while m:
i = m.end()
typ = m.group('type') or '{'
if typ in frozenset(['%', '+', '-', '|', ',', '{']):
# No args
pass
elif typ in frozenset(['c', 'p', 'P', 'C', 'D']):
# One arg - should be int or tuple of int
if typ == 'c':
item = entry[arg]
if isinstance(item, tuple):
assert isinstance(item[1], str), (
"%s[%s][%d] kind %s is '%s' should be str but is %s. "
"Full entry: %s" %
(name, k, arg, typ, item[1], type(item[1]), entry)
)
item = item[0]
assert isinstance(item, int), (
"%s[%s][%d] kind %s is '%s' should be an int but is %s. "
"Full entry: %s" %
(name, k, arg, typ, item, type(item), entry)
)
elif typ in frozenset(['C', 'D']):
tup = entry[arg]
assert isinstance(tup, tuple), (
"%s[%s][%d] type %s is %s should be an tuple but is %s. "
"Full entry: %s" %
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
)
assert len(tup) == 3
for j, x in enumerate(tup[:-1]):
assert isinstance(x, int), (
"%s[%s][%d][%d] type %s is %s should be an tuple but is %s. "
"Full entry: %s" %
(name, k, arg, j, typ, x, type(x), entry)
)
assert isinstance(tup[-1], str) or tup[-1] is None, (
"%s[%s][%d][%d] sep type %s is %s should be an string but is %s. "
"Full entry: %s" %
(name, k, arg, j, typ, tup[-1], type(x), entry)
)
elif typ == 'P':
tup = entry[arg]
assert isinstance(tup, tuple), (
"%s[%s][%d] type %s is %s should be an tuple but is %s. "
"Full entry: %s" %
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
)
assert len(tup) == 4
for j, x in enumerate(tup[:-2]):
assert isinstance(x, int), (
"%s[%s][%d][%d] type %s is '%s' should be an tuple but is %s. "
"Full entry: %s" %
(name, k, arg, j, typ, x, type(x), entry)
)
assert isinstance(tup[-2], str), (
"%s[%s][%d][%d] sep type %s is '%s' should be an string but is %s. "
"Full entry: %s" %
(name, k, arg, j, typ, x, type(x), entry)
)
assert isinstance(tup[1], int), (
"%s[%s][%d][%d] prec type %s is '%s' should be an int but is %s. "
"Full entry: %s" %
(name, k, arg, j, typ, x, type(x), entry)
)
else:
# Should be a tuple which contains only ints
tup = entry[arg]
assert isinstance(tup, tuple), (
"%s[%s][%d] type %s is '%s' should be an tuple but is %s. "
"Full entry: %s" %
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
)
assert len(tup) == 2
for j, x in enumerate(tup):
assert isinstance(x, int), (
"%s[%s][%d][%d] type '%s' is '%s should be an int but is %s. Full entry: %s" %
(name, k, arg, j, typ, x, type(x), entry)
)
pass
arg += 1
elif typ in frozenset(['r']) and fragment:
pass
elif typ == 'b' and fragment:
assert isinstance(entry[arg], int), (
"%s[%s][%d] type %s is '%s' should be an int but is %s. "
"Full entry: %s" %
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
)
arg += 1
elif typ == 'x' and fragment:
tup = entry[arg]
assert isinstance(tup, tuple), (
"%s[%s][%d] type %s is '%s' should be an tuple but is %s. "
"Full entry: %s" %
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
)
assert len(tup) == 2
assert isinstance(tup[0], int), (
"%s[%s][%d] source type %s is '%s' should be an int but is %s. "
"Full entry: %s" %
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
)
assert isinstance(tup[1], tuple), (
"%s[%s][%d] dest type %s is '%s' should be an tuple but is %s. "
"Full entry: %s" %
(name, k, arg, typ, entry[arg], type(entry[arg]), entry)
)
for j, x in enumerate(tup[1]):
assert isinstance(x, int), (
"%s[%s][%d][%d] type %s is %s should be an int but is %s. Full entry: %s" %
(name, k, arg, j, typ, x, type(x), entry)
)
arg += 1
pass
else:
assert False, (
"%s[%s][%d] type %s is not known. Full entry: %s" %
(name, k, arg, typ, entry)
)
m = escape.search(fmt, i)
pass
assert arg == len(entry), (
"%s[%s] arg %d should be length of entry %d. Full entry: %s" %
(name, k, arg, len(entry), entry))

View File

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

View File

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

View File

@@ -1,4 +1,3 @@
pytest
pytest>=3.0.0
flake8
hypothesis
six

View File

@@ -24,6 +24,6 @@ setup(
py_modules = py_modules,
test_suite = 'nose.collector',
url = web,
tests_require = ['nose>=1.0'],
tests_require = ['nose>=1.0'],
version = VERSION,
zip_safe = zip_safe)

55
test-unit/test_grammar.py Normal file
View File

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

View File

@@ -1,4 +1,12 @@
PHONY=check clean dist distclean test test-unit test-functional rmChangeLog clean_pyc nosetests
PHONY=check clean dist distclean test test-unit test-functional rmChangeLog clean_pyc nosetests \
check-bytecode-1.5 check-bytecode-1 check-bytecode-2 check-bytecode-3 \
check-bytecode-2.2 check-byteocde-2.3 check-bytecode-2.4 \
check-short check-2.6 check-2.7 check-3.0 check-3.1 check-3.2 check-3.3 \
check-3.4 check-3.5 check-5.6 5.6 5.8 \
grammar-coverage-2.5 grammar-coverage-2.6 grammarcoverage-2.7 \
grammar-coverage-3.1 grammar-coverage-3.2 grammarcoverage-3.3 \
grammar-coverage-3.4 grammar-coverage-3.5 grammarcoverage-3.6
GIT2CL ?= git2cl
PYTHON ?= python
@@ -8,6 +16,7 @@ NATIVE_CHECK = check-$(PYTHON_VERSION)
# Set COMPILE='--compile' to force compilation before check
COMPILE ?=
COVER_DIR=../tmp/grammar-cover
# Run short tests
check-short:
@@ -19,7 +28,7 @@ check:
$(MAKE) check-$(PYTHON_VERSION)
#: Run working tests from Python 2.6 or 2.7
check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-bytecode-1 check-native-short
check-2.4 check-2.5 check-2.6 check-2.7: check-bytecode-2 check-bytecode-3 check-bytecode-1 check-native-short
#: Run working tests from Python 3.0
check-3.0: check-bytecode
@@ -35,27 +44,30 @@ check-3.2: check-bytecode
#: Run working tests from Python 3.3
check-3.3: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.3 --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --bytecode-3.3 --weak-verify $(COMPILE)
#: Run working tests from Python 3.4
check-3.4: check-bytecode check-3.4-ok check-2.7-ok
$(PYTHON) test_pythonlib.py --bytecode-3.4 --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --bytecode-3.4 --weak-verify $(COMPILE)
#: Run working tests from Python 3.5
check-3.5: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.5 --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --bytecode-3.5 --weak-verify $(COMPILE)
#: Run working tests from Python 3.6
check-3.6: check-bytecode
$(PYTHON) test_pythonlib.py --bytecode-3.6 --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify $(COMPILE)
# FIXME
#: this is called when running under pypy3.5-5.8.0 or pypy2-5.6.0
5.8 5.6:
#: Check deparsing only, but from a different Python version
check-disasm:
$(PYTHON) dis-compare.py
#: Check deparsing bytecode 1.x only
check-bytecode-1:
$(PYTHON) test_pythonlib.py --bytecode-1.5
check-bytecode-1: check-bytecode-1.5
#: Check deparsing bytecode 2.x only
check-bytecode-2:
@@ -67,7 +79,7 @@ check-bytecode-2:
check-bytecode-3:
$(PYTHON) test_pythonlib.py --bytecode-3.0 \
--bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \
--bytecode-3.4 --bytecode-3.5 --bytecode-pypy3.2
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6 --bytecode-pypy3.2
#: Check deparsing bytecode that works running Python 2 and Python 3
check-bytecode: check-bytecode-3
@@ -77,6 +89,10 @@ check-bytecode: check-bytecode-3
--bytecode-pypy2.7 --bytecode-1
#: Check deparsing bytecode 1.5 only
check-bytecode-1.5:
$(PYTHON) test_pythonlib.py --bytecode-1.5
#: Check deparsing Python 2.1
check-bytecode-2.1:
$(PYTHON) test_pythonlib.py --bytecode-2.1
@@ -97,20 +113,66 @@ check-bytecode-2.4:
check-bytecode-2.5:
$(PYTHON) test_pythonlib.py --bytecode-2.5
#: Get grammar coverage for Python 2.4
grammar-coverage-2.4:
-rm $(COVER_DIR)/spark-grammar-24.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-24.cover $(PYTHON) test_pythonlib.py --bytecode-2.4
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-24.cover $(PYTHON) test_pyenvlib.py --2.4.6
#: Get grammar coverage for Python 2.5
grammar-coverage-2.5:
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-25.cover $(PYTHON) test_pythonlib.py --bytecode-2.5
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-25.cover $(PYTHON) test_pyenvlib.py --2.5.6
-rm $(COVER_DIR)/spark-grammar-25.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-25.cover $(PYTHON) test_pythonlib.py --bytecode-2.5
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-25.cover $(PYTHON) test_pyenvlib.py --2.5.6
#: Get grammar coverage for Python 2.6
grammar-coverage-2.6:
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-26.cover $(PYTHON) test_pythonlib.py --bytecode-2.6
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-26.cover $(PYTHON) test_pyenvlib.py --2.6.9
-rm $(COVER_DIR)/spark-grammar-26.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-26.cover $(PYTHON) test_pythonlib.py --bytecode-2.6
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-26.cover $(PYTHON) test_pyenvlib.py --2.6.9
#: Get grammar coverage for Python 2.7
grammar-coverage-2.7:
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-27.cover $(PYTHON) test_pythonlib.py --bytecode-2.7
SPARK_PARSER_COVERAGE=/tmp/spark-grammar-27.cover $(PYTHON) test_pyenvlib.py --2.7.13
-rm $(COVER_DIR)/spark-grammar-27.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-27.cover $(PYTHON) test_pythonlib.py --bytecode-2.7
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-27.cover $(PYTHON) test_pyenvlib.py --2.7.13
#: Get grammar coverage for Python 3.0
grammar-coverage-3.0:
-rm $(COVER_DIR)/spark-grammar-30.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-30.cover $(PYTHON) test_pythonlib.py --bytecode-3.1
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-30.cover $(PYTHON) test_pyenvlib.py --3.0.1
#: Get grammar coverage for Python 3.1
grammar-coverage-3.1:
-rm $(COVER_DIR)/spark-grammar-31.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-31.cover $(PYTHON) test_pythonlib.py --bytecode-3.1
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-31.cover $(PYTHON) test_pyenvlib.py --3.1.5
#: Get grammar coverage for Python 3.2
grammar-coverage-3.2:
-rm $(COVER_DIR)/spark-grammar-32.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-32.cover $(PYTHON) test_pythonlib.py --bytecode-3.2
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-32.cover $(PYTHON) test_pyenvlib.py --3.2.6
#: Get grammar coverage for Python 3.3
grammar-coverage-3.3:
-rm $(COVER_DIR)/spark-grammar-33.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-33.cover $(PYTHON) test_pythonlib.py --bytecode-3.3
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-33.cover $(PYTHON) test_pyenvlib.py --3.3.6
##: Get grammar coverage for Python 3.4
grammar-coverage-3.4:
-rm $(COVER_DIR)/spark-grammar-34.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-34.cover $(PYTHON) test_pythonlib.py --bytecode-3.4
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-34.cover $(PYTHON) test_pyenvlib.py --3.4.2
##: Get grammar coverage for Python 3.5
grammar-coverage-3.5:
rm $(COVER_DIR)/spark-grammar-35.cover || /bin/true
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-35.cover $(PYTHON) test_pythonlib.py --bytecode-3.5
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-35.cover $(PYTHON) test_pyenvlib.py --3.5.3
#: Check deparsing Python 2.6
check-bytecode-2.6:
@@ -118,55 +180,59 @@ check-bytecode-2.6:
#: Check deparsing Python 2.7
check-bytecode-2.7:
$(PYTHON) test_pythonlib.py --bytecode-2.7 --verify
$(PYTHON) test_pythonlib.py --bytecode-2.7 --weak-verify
#: Check deparsing Python 3.0
check-bytecode-3.0:
$(PYTHON) test_pythonlib.py --bytecode-3.0
$(PYTHON) test_pythonlib.py --bytecode-3.0 --weak-verify
#: Check deparsing Python 3.1
check-bytecode-3.1:
$(PYTHON) test_pythonlib.py --bytecode-3.1
$(PYTHON) test_pythonlib.py --bytecode-3.1 --weak-verify
#: Check deparsing Python 3.2
check-bytecode-3.2:
$(PYTHON) test_pythonlib.py --bytecode-3.2
$(PYTHON) test_pythonlib.py --bytecode-3.2 --weak-verify
#: Check deparsing Python 3.3
check-bytecode-3.3:
$(PYTHON) test_pythonlib.py --bytecode-3.3
$(PYTHON) test_pythonlib.py --bytecode-3.3 --weak-verify
#: Check deparsing Python 3.4
check-bytecode-3.4:
$(PYTHON) test_pythonlib.py --bytecode-3.4
$(PYTHON) test_pythonlib.py --bytecode-3.4 --weak-verify
#: Check deparsing Python 3.5
check-bytecode-3.5:
$(PYTHON) test_pythonlib.py --bytecode-3.5
$(PYTHON) test_pythonlib.py --bytecode-3.5 --weak-verify
#: Check deparsing Python 3.6
check-bytecode-3.6:
$(PYTHON) test_pythonlib.py --bytecode-3.6
$(PYTHON) test_pythonlib.py --bytecode-3.6 --weak-verify
#: short tests for bytecodes only for this version of Python
check-native-short:
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --weak-verify $(COMPILE)
#: Run longer Python 2.6's lib files known to be okay
check-2.4-ok:
$(PYTHON) test_pythonlib.py --ok-2.4 --verify $(COMPILE)
#: Run longer Python 2.6's lib files known to be okay
check-2.6-ok:
$(PYTHON) test_pythonlib.py --ok-2.6 --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --ok-2.6 --weak-verify $(COMPILE)
#: Run longer Python 2.7's lib files known to be okay
check-2.7-ok:
$(PYTHON) test_pythonlib.py --ok-2.7 --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --ok-2.7 --weak-verify $(COMPILE)
#: Run longer Python 3.2's lib files known to be okay
check-3.2-ok:
$(PYTHON) test_pythonlib.py --ok-3.2 --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --ok-3.2 --weak-verify $(COMPILE)
#: Run longer Python 3.4's lib files known to be okay
check-3.4-ok:
$(PYTHON) test_pythonlib.py --ok-3.4 --verify $(COMPILE)
$(PYTHON) test_pythonlib.py --ok-3.4 --weak-verify $(COMPILE)
#: PyPy of some sort. E.g. [PyPy 5.0.1 with GCC 4.8.4]
# Skip for now

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test/bytecode_2.2/01_kv.pyc Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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