Compare commits

..

211 Commits

Author SHA1 Message Date
rocky
4fb379afb4 Get ready for release 2.15.0 2018-01-27 12:26:22 -05:00
rocky
eb7484c671 Merge branch 'master' into python-2.4 2018-01-27 11:47:57 -05:00
rocky
79470ffff7 Merge branch 'master' into python-2.4 2018-01-20 15:30:45 -05:00
rocky
44af6c42a2 Merge branch 'master' into python-2.4 2018-01-19 03:33:29 -05:00
rocky
d7380dc549 Merge branch 'master' into python-2.4 2018-01-19 03:18:23 -05:00
rocky
b2f6e1cf1a Merge branch 'master' into python-2.4 2018-01-18 19:05:19 -05:00
rocky
7c9437f0a9 Merge branch 'master' into python-2.4 2018-01-18 01:27:52 -05:00
rocky
162bb0a85f Merge branch 'master' into python-2.4 2018-01-13 01:05:38 -05:00
rocky
e44ccd5787 Merge branch 'master' into python-2.4 2018-01-12 20:57:10 -05:00
rocky
c4612b7484 Fix ok status on --weak-verify 2018-01-12 09:57:32 -05:00
rocky
731c5a2092 Merge branch 'master' into python-2.4 2018-01-12 09:57:17 -05:00
rocky
7efbd55b69 Merge branch 'master' into python-2.4 2018-01-11 21:55:43 -05:00
rocky
5dbec5b383 Merge branch 'master' into python-2.4 2018-01-11 10:35:49 -05:00
rocky
f28ad69c38 Merge branch 'master' into python-2.4 2018-01-11 01:48:28 -05:00
rocky
49a71819a1 Correct Python 2.5- decorator parsing 2018-01-10 11:02:54 -05:00
rocky
ed7d11525a Check Python version in setup.py ...
to make the code is compatible. Fixes #146
2018-01-10 09:49:39 -05:00
rocky
5b1dcccddc Merge branch 'master' into python-2.4 2018-01-10 09:39:39 -05:00
rocky
992a08f5ce Check Python version in setup.py ...
to make sure we are running a compatible version.
2018-01-10 09:38:55 -05:00
rocky
49ef408699 Reinstates run tests that now work 2018-01-09 08:48:57 -05:00
rocky
0487f2fb7a Merge branch 'master' into python-2.4 2018-01-09 08:40:31 -05:00
rocky
e43c8acd30 Merge branch 'master' into python-2.4 2018-01-09 03:19:48 -05:00
rocky
97604a93dd Small typo 2018-01-09 00:28:04 -05:00
rocky
d266e9e123 Merge branch 'master' into python-2.4 2018-01-09 00:23:33 -05:00
rocky
7ac8bf91df Merge branch 'master' into python-2.4 2018-01-08 23:21:24 -05:00
rocky
772d36015c 2.4-compatiblity for next iteration 2018-01-08 22:18:59 -05:00
rocky
f381211291 Merge branch 'master' into python-2.4 2018-01-08 22:13:05 -05:00
rocky
aca4cb233d Merge branch 'master' into python-2.4 2018-01-08 12:24:59 -05:00
rocky
01ef3b774f Merge branch 'master' into python-2.4 2018-01-08 11:44:11 -05:00
rocky
9041dead7f Merge branch 'master' into python-2.4 2018-01-07 21:36:19 -05:00
rocky
4ea308f75a Fix another 2.5- try/else bug (in a loop) 2018-01-07 08:36:17 -05:00
rocky
e5f06eb551 Fix bug 2.5- in try/else inside ifelsestmt 2018-01-06 22:10:05 -05:00
rocky
c68030e9fa Merge branch 'master' into python-2.4 2017-12-15 19:21:59 -05:00
rocky
fd95839701 Merge branch 'master' into python-2.4 2017-12-15 08:26:03 -05:00
rocky
6305023219 Handl 2.4- try/finally properly 2017-12-14 19:20:57 -05:00
rocky
c7dda72a84 Merge branch 'master' into python-2.4 2017-12-14 17:58:03 -05:00
rocky
7caedcb50d Merge branch 'master' into python-2.4 2017-12-14 09:51:50 -05:00
rocky
1856e09a0c 2.4 tolerance 2017-12-14 08:45:13 -05:00
rocky
e47568e147 Merge branch 'master' into python-2.4 2017-12-14 08:40:43 -05:00
rocky
c702ce3802 runtests for 2.4 and 2.5 2017-12-13 18:06:56 -05:00
rocky
a37f403410 Fix runtests.sh 2017-12-13 17:44:19 -05:00
rocky
9248a954bd Merge branch 'master' into python-2.4 2017-12-13 17:43:44 -05:00
rocky
89a7ad6f81 Update docs and failed decompiles (for 2.5) 2017-12-13 10:02:30 -05:00
rocky
f432f4f698 Update runtest failures 2017-12-13 09:24:59 -05:00
rocky
5ef2d5cd9f Merge branch 'master' into python-2.4 2017-12-13 08:58:18 -05:00
rocky
204612ca85 Merge branch 'master' into python-2.4 2017-12-12 11:05:20 -05:00
rocky
df8c092212 Merge branch 'master' into python-2.4 2017-12-10 18:12:14 -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
27b217a4ed Merge branch 'master' into python-2.4 2017-12-09 04:53: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
f07c9c6dcf Merge branch 'master' into python-2.4 2017-12-05 08:32:31 -05:00
rocky
c677c946ea Merge branch 'master' into python-2.4 2017-12-05 05:59:50 -05:00
rocky
87063851be Merge branch 'master' into python-2.4 2017-12-05 05:44:59 -05:00
rocky
516c1a7910 Merge branch 'master' into python-2.4 2017-12-05 00:13:59 -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
5fc33aeef5 Merge branch 'master' into python-2.4 2017-12-04 09:41:49 -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
910d210e52 Merge branch 'master' into python-2.4 2017-12-03 13:03:28 -05:00
rocky
b719a0ee35 Merge branch 'master' into python-2.4 2017-12-03 12:29:05 -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
13ab06ecb1 Fix bug in 2.6- except_cond3 2017-12-03 06:10:37 -05:00
rocky
72e2d1a2bf One more _come_from -> _come_froms 2017-12-03 05:19:20 -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
ca7f267103 Merge branch 'master' into python-2.4 2017-12-02 21:18:00 -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
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
fc0eb87620 Python 2.4 compatability 2017-12-02 10:01:33 -05:00
rocky
0b9fca2263 Sync with master 2017-12-02 09:51:15 -05:00
rocky
0d9464bb92 Merge branch 'master' into python-2.4 2017-11-29 05:09:22 -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
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
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
7553c4aed9 Add UNARY_INVERT_OP test 2017-11-27 12:49:39 -05:00
rocky
593304bc43 Administrivia 2017-11-27 12:40:44 -05:00
rocky
a9ca30fe34 Reduce Python 2.5- grammar rules 2017-11-27 12:17:10 -05:00
rocky
6030730870 Merge branch 'master' into python-2.4 2017-11-27 07:33:23 -05:00
rocky
b9436e4851 Merge branch 'master' into python-2.4 2017-11-26 19:24:24 -05:00
rocky
b0a7452d48 2.7 tryfinally grammar rule removal 2017-11-26 15:34:00 -05:00
rocky
5e05e521d9 Merge branch 'master' into python-2.4 2017-11-26 10:08:59 -05:00
rocky
7a052c349a Merge branch 'master' into python-2.4 2017-11-26 09:33:25 -05:00
rocky
35aca37557 Isolate kv, kv2, and kdv3 better 2017-11-26 06:53:22 -05:00
rocky
57fe56d72e localize kv 2017-11-26 01:35:03 -05:00
rocky
218e73540a Merge branch 'master' into python-2.4 2017-11-26 01:27:56 -05:00
rocky
0965e2cc96 Localize kv 2017-11-26 01:26:57 -05:00
rocky
5cf4f0a82f Merge hell 2017-11-25 23:15:07 -05:00
rocky
9b0225db60 Merge branch 'master' into python-2.4 2017-11-25 23:15:01 -05:00
rocky
8c0959de42 inf and nan tests 2017-11-25 23:11:27 -05:00
rocky
ccd71c857f Regularze grammar coverage rules 2017-11-24 22:44:22 -05:00
rocky
b89dbb0ee7 Merge hell 2017-11-24 21:48:24 -05:00
rocky
a5bdc1acd0 Merge branch 'master' into python-2.4 2017-11-24 21:48:14 -05:00
rocky
a279784d8d Merge branch 'master' into python-2.4 2017-11-23 17:17:54 -05:00
rocky
3a9f4f2984 Merge branch 'master' into python-2.4 2017-11-23 12:37:00 -05:00
rocky
51ae8313cf Merge branch 'master' into python-2.4 2017-11-22 14:45:16 -05:00
rocky
38f04f0073 More complete grammar coverage 2017-11-22 11:15:39 -05:00
rocky
f3da5d770d Merge hell 2017-11-22 06:26:20 -05:00
rocky
24fb13cf23 Merge branch 'master' into python-2.4 2017-11-22 06:25:52 -05:00
rocky
524e8c8410 Python 2.5 "with". isolate 2.5-2.7 grammar better 2017-11-16 09:18:26 -05:00
rocky
52d1e44560 Merge branch 'master' into python-2.4 2017-11-16 09:18:19 -05:00
rocky
6055c5e165 Get ready for release python-2.4- 2017-11-13 10:58:46 -05:00
rocky
e0ed187ea6 2.4isms...
Need print without parens. Handle old-style classes more properly?
2017-11-13 10:52:43 -05:00
rocky
eafe048c7e Get ready for release python-2.4-2.13.3 2017-11-13 10:12:27 -05:00
rocky
c0e553dbb5 Merge branch 'master' into python-2.4 2017-11-13 10:11:00 -05:00
rocky
7e59987af7 Merge branch 'master' into python-2.4 2017-10-12 07:31:19 -04:00
rocky
1f012f7c46 Merge conflicts 2017-10-12 07:18:11 -04:00
rocky
d1a3d42ab8 Sync 2017-10-12 07:08:58 -04:00
rocky
05fd992c48 Update news 2017-10-12 07:06:19 -04:00
rocky
47f1d888eb Merge branch 'master' into python-2.4 2017-10-12 07:05:34 -04:00
rocky
ca9c227837 More administrivia 2017-10-11 22:17:50 -04:00
rocky
5df384bb71 Some admin tools I use 2017-10-11 21:16:35 -04:00
rocky
e80b36347a Remove creaping Python 2.6ism 2017-10-11 20:43:17 -04:00
rocky
9e37495493 Sync with master 2017-10-10 23:06:22 -04:00
rocky
77b93c5f21 Sync with master 2017-10-10 23:04:25 -04:00
rocky
0b198ee881 Sync with master 2017-10-10 23:02:20 -04:00
rocky
9e0c65881d Sync with master 2017-10-10 22:52:07 -04:00
rocky
c796d6a799 Merge commit '1d7a3c6444eab5a02d899f789f2a57cfdcbc5a84' into python-2.4 2017-10-10 22:50:28 -04:00
rocky
3892fb533a Misc bugs 2017-10-10 16:12:02 -04:00
rocky
2ea7487ca7 One more test 2017-10-05 11:19:36 -04:00
rocky
d4f6cec3d0 Sync with master 2017-10-05 11:17:49 -04:00
rocky
b1705e283d handle newer parser reduction behavior 2017-10-03 11:54:24 -04:00
rocky
eee751e22a Go over table-semantics description yet again 2017-10-03 05:44:55 -04:00
rocky
2b0fefb95f Sync with master 2017-10-02 03:12:26 -04:00
rocky
1a627ba207 Annotation field can be unicode...
When deparsing Python 3.x from Python 2.
2017-09-26 09:53:26 -04:00
rocky
ea75bcf47e Require xdis 3.6.0 or greater 2017-09-25 20:11:53 -04:00
rocky
6c6dcab857 Merge branch 'python-2.4' of github.com:rocky/python-uncompyle6 into python-2.4 2017-09-25 20:09:04 -04:00
rocky
0654aed6c8 Get ready for release 2.12.0 2017-09-25 20:08:50 -04:00
rocky
3447ca0767 Unit test for format-specifiers 2017-09-21 11:29:17 -04:00
rocky
1e858efafd Tidy pysource and fragments 2017-09-20 19:08:41 -04:00
rocky
ce88a72ea1 Tidy/regularize table entry formatting 2017-09-20 17:52:48 -04:00
rocky
7725b8e7de small fixes...
test_pythonlib.py: it is sys.exit not exit
pysource.py: restore node type on async_call function
2017-09-20 11:30:50 -04:00
rocky
62ddbe320d Start pysource unit test 2017-09-20 01:15:37 -04:00
rocky
a694601264 emgine -> template_engine 2017-09-17 12:03:49 -04:00
rocky
e06f88043f Merge branch 'master' into python-2.4 2017-08-31 09:54:23 -04:00
rocky
8fc3fd146f Merge branch 'master' into python-2.4 2017-08-31 09:47:02 -04:00
rocky
ce5066bddb Merge branch 'master' into python-2.4 2017-08-15 11:12:20 -04:00
rocky
93f18e2449 Allow version to be string...
in get_python_parser and get_scanner
2017-08-13 09:23:27 -04:00
rocky
783e62f3ca Merge branch 'python-2.4' of github.com:rocky/python-uncompyle6 into python-2.4 2017-08-10 09:45:11 -04:00
rocky
c38dc61021 xdis "is not" is now "is-not" 2017-08-09 22:07:32 -04:00
rocky
45782bbb39 Get ready for release 2.11.3 2017-08-09 21:46:27 -04:00
rocky
4c9cd5657e Merge branch 'master' into python-2.4 2017-08-09 21:45:50 -04:00
rocky
dc627d13b8 Get ready for release 2.11.3 2017-08-09 21:33:01 -04:00
rocky
ddc3489991 Python 2.4 comptiability and ...
exception match -> exception-match
2017-08-03 03:48:57 -04:00
rocky
5b24c20331 Bump xdis 2017-08-02 08:37:50 -04:00
rocky
8bb01143d8 Remove six from python 2.4/2.5 2017-08-02 08:28:08 -04:00
rocky
a9635da96a in xdis "exception match" is now "exception-match" 2017-08-02 06:36:40 -04:00
rocky
e790cb75fd Python 2.4 doesn't do six 2017-08-02 06:20:07 -04:00
rocky
348afeebbf Python 2.4 compatibility 2017-08-01 22:32:43 -04:00
rocky
6888553773 Merge branch 'master' into python-2.4 2017-06-25 18:56:31 -04:00
rocky
0f489672b9 More merge fixups from master 2017-06-18 16:05:22 -04:00
rocky
b7d8cbfaf5 Merge branch 'master' into python-2.4 2017-06-18 15:40:40 -04:00
rocky
df8d253f78 2.4 doesn't do six 2017-06-03 06:00:47 -04:00
rocky
89b42e3696 Nope it (appveyor) doesn't. 2017-06-03 05:55:21 -04:00
rocky
22e5a4a283 Administrivia
See if appveyor will handle 2.5
2017-06-03 05:53:41 -04:00
rocky
61810172d1 Merge branch 'master' into python-2.4 2017-06-03 05:50:42 -04:00
rocky
658c8b4be7 No decorators in Python < 2.6 2017-05-30 02:30:56 -04:00
rocky
d4dab54c7b Merge branch 'master' into python-2.4 2017-05-30 02:18:57 -04:00
rocky
5566b9ba6c Get ready for release 2.9.11 2017-05-06 07:49:09 -04:00
rocky
e56ab2dcd5 Sync with master 2017-05-06 07:17:04 -04:00
rocky
d6c45979ba Merge branch 'master' into python-2.4 2017-05-06 07:16:39 -04:00
rocky
a06e9bf32e Merge branch 'master' into python-2.4 2017-04-14 05:45:53 -04:00
rocky
7e8f7ba674 namedtuple25 -> namedtuple24 2017-04-14 05:42:44 -04:00
rocky
09eb7f7f78 Merge branch 'master' into python-2.4 2017-04-10 00:48:04 -04:00
rocky
f7a910ec66 Merge branch 'master' into python-2.4 2017-03-01 05:55:26 -05:00
rocky
6d6a73eea7 Merge branch 'master' into python-2.4 2017-02-25 21:02:12 -05:00
rocky
e4a7641927 Python <= 2.6 grammar fixes 2017-02-25 05:13:19 -05:00
rocky
b24b46d48c Merge branch 'master' into python-2.4 2017-02-25 04:48:06 -05:00
rocky
a65d7dce5b Python 2.5 was missing try else stmt 2017-02-22 05:30:07 -05:00
rocky
718a0a5d34 Merge branch 'master' into python-2.4 2017-02-22 05:29:49 -05:00
rocky
ea9e3ab3f5 Group coverage Makefile targets 2017-02-10 01:00:26 -05:00
rocky
770e988ff8 Changes based on coverage information 2017-01-29 22:54:30 -05:00
rocky
0fa0641974 Merge branch 'master' into python-2.4 2017-01-29 22:05:55 -05:00
rocky
c13e23cdae Get ready for release 2.9.9 2017-01-11 21:52:20 -05:00
rocky
fab4ebb768 Merge changes ...
* str() in Python 2.4 doesn't detect unicode.
* index() doesn't work on tuples
* ifelse change
2017-01-11 19:34:28 -05:00
rocky
89429339fa Merge branch 'master' into python-2.4 2017-01-11 19:25:44 -05:00
rocky
6ed129bd7a 2.4 verify hacks 2017-01-02 07:15:46 -05:00
rocky
c4fde6b53e Merge branch 'master' into python-2.4 2017-01-02 05:39:50 -05:00
rocky
a7d93e88b4 Merge branch 'master' into python-2.4 2017-01-02 05:39:13 -05:00
rocky
9891494142 We are version 2.9.9 2016-12-31 18:16:23 -05:00
rocky
f8544dfbbe 2.7->2.4 conversion 2016-12-31 10:56:43 -05:00
rocky
b00651d428 Merge master branche
Handle 2.2 list_if
2016-12-31 05:19:21 -05:00
rocky
da8dccbaca Merge branch 'master' into python-2.4 2016-12-29 02:08:12 -05:00
rocky
37272ae827 Merge commit '9b1dd0f' into python-2.4 2016-12-27 10:32:25 -05:00
rocky
7f2bee46b7 Bug in using python2 ast checking in python 2.5 2016-12-26 01:55:16 -05:00
rocky
c8a4dcf72b Removing NAME_MODULE, lint and bug fixes
scanner*.py: show_asm param is optional
verify.py: call correct scanners
main.py, verify.py: Use older Python print statements
2016-12-25 09:16:04 -05:00
rocky
012ff91cfb Merge branch 'master' into python-2.4 2016-12-25 07:57:17 -05:00
rocky
e690ddd50a Merge branch 'master' into python-2.4 2016-12-18 07:43:15 -05:00
rocky
45b7c1948c show-asm on python2.5 is optional
Make scanner2 a little more like scanner3.
2016-12-17 07:57:31 -05:00
rocky
e2fb7ca3d2 Python 2.6/2.7 tolerance in Python 2.4 branch 2016-12-17 06:51:47 -05:00
rocky
b3bda76582 Merge branch 'master' into python-2.4 2016-12-16 22:56:07 -05:00
rocky
ab6d322eca Get ready for release 2.9.7 2016-12-04 14:09:53 -05:00
rocky
1a8a0df107 Merge branch 'master' into python-2.4 2016-12-04 13:40:06 -05:00
rocky
0a37709b0a CircleCI build 2016-11-24 05:41:31 -05:00
rocky
98cd1417df Remove dup Python 3 grammar rule 2016-11-24 05:36:43 -05:00
rocky
460069ceaa Bug in 2.4 "if" dectection and...
Wrong language used in old-style exceptions: use "except Error,e" not
"except Error(e)""
2016-11-24 05:15:35 -05:00
rocky
316aa44f23 Python 2.6 grammary bug and..
__pkginfo.py__: Bump spark_parser version for parse_flags 'dups'
2016-11-24 04:09:32 -05:00
rocky
7133540c23 Make work on 2.4 2016-11-23 08:26:12 -05:00
rocky
590231741d Merge branch 'come-from-type' into python-2.4 2016-11-23 07:54:18 -05:00
rocky
a9349b8f3d Making it run on Python 2.4 and 2.5 2016-11-23 07:53:51 -05:00
112 changed files with 710 additions and 1124 deletions

View File

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

View File

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

23
NEWS
View File

@@ -1,23 +1,4 @@
uncompyle6 2.15.0 2018-02-05 pycon2018.co
- Bug fixes
- Code fragment improvements
- Code cleanups
- Expand testing
uncompyle6 2.15.1 2018-01-27
- Add --linemap option to give line correspondences
between original source lines and reconstructed line sources.
It is far from perfect, but it is a start
- Add a new class of tests: tests which when decompiled check themselves
- Split off Python version semantic action customizations into its own file
- Fix 2.7 bug in ifelse loop statement
- Handle 3.6+ EXTENDED_ARGs for POP_JUMP_IF... instructions
- Correct 3.6+ calls with kwargs
- Describe the difficulty of 3.6 in README
uncompyle6 2.14.3 2018-01-19
uncompyle6 2.14.3 2017-01-19
- Fix bug in 3.5+ await stmt
- Better version to magic handling; handle 3.5.2 .. 3.5.4 versions
@@ -29,7 +10,7 @@ uncompyle6 2.14.3 2018-01-19
- better tests in setup.py for running the right version of Python
- Fix 2.6- parsing of "for .. try/else" ... with "continue" inside
uncompyle6 2.14.2 2018-01-09 Samish
uncompyle6 2.14.2 2017-01-09 Samish
Decompilation bug fixes, mostly 3.6 and pre 2.7

View File

@@ -41,8 +41,7 @@ entry_points = {
]}
ftp_url = None
install_requires = ['spark-parser >= 1.8.5, < 1.9.0',
'xdis >= 3.6.9, < 3.7.0', 'six']
'xdis >= 3.6.6, < 3.7.0']
license = 'MIT'
mailing_list = 'python-debugger@googlegroups.com'
modname = 'uncompyle6'

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

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

View File

@@ -17,7 +17,7 @@
<!-- markdown-toc end -->
# Get latest sources:
git pull
$ . ./admin-tool/update-sources.sh
# Change version in uncompyle6/version.py:

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}*

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

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

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

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

View File

@@ -10,5 +10,4 @@ dependencies:
- pip install pytest==3.2.5 hypothesis
test:
override:
- python ./setup.py develop && make check-2.7
- cd ./test/stdlib && pyenv local 2.7.10 && bash ./runtests.sh 'test_[p-z]*.py'
- python ./setup.py develop && make check-2.6

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,175 +0,0 @@
# std
import string
# 3rd party
from hypothesis import given, assume, example, settings, strategies as st
import pytest
# uncompyle
from validate import validate_uncompyle
from test_fstring import expressions
alpha = st.sampled_from(string.ascii_lowercase)
numbers = st.sampled_from(string.digits)
alphanum = st.sampled_from(string.ascii_lowercase + string.digits)
@st.composite
def function_calls(draw,
min_keyword_args=0, max_keyword_args=5,
min_positional_args=0, max_positional_args=5,
min_star_args=0, max_star_args=1,
min_double_star_args=0, max_double_star_args=1):
"""
Strategy factory for generating function calls.
:param draw: Callable which draws examples from other strategies.
:return: The function call text.
"""
st_positional_args = st.lists(
alpha,
min_size=min_positional_args,
max_size=max_positional_args
)
st_keyword_args = st.lists(
alpha,
min_size=min_keyword_args,
max_size=max_keyword_args
)
st_star_args = st.lists(
alpha,
min_size=min_star_args,
max_size=max_star_args
)
st_double_star_args = st.lists(
alpha,
min_size=min_double_star_args,
max_size=max_double_star_args
)
positional_args = draw(st_positional_args)
keyword_args = draw(st_keyword_args)
st_values = st.lists(
expressions(),
min_size=len(keyword_args),
max_size=len(keyword_args)
)
keyword_args = [
x + '=' + e
for x, e in
zip(keyword_args, draw(st_values))
]
star_args = ['*' + x for x in draw(st_star_args)]
double_star_args = ['**' + x for x in draw(st_double_star_args)]
arguments = positional_args + keyword_args + star_args + double_star_args
draw(st.randoms()).shuffle(arguments)
arguments = ','.join(arguments)
function_call = 'fn({arguments})'.format(arguments=arguments)
try:
# TODO: Figure out the exact rules for ordering of positional, keyword,
# star args, double star args and in which versions the various
# types of arguments are supported so we don't need to check that the
# expression compiles like this.
compile(function_call, '<string>', 'single')
except:
assume(False)
return function_call
def test_function_no_args():
validate_uncompyle("fn()")
def isolated_function_calls(which):
"""
Returns a strategy for generating function calls, but isolated to
particular types of arguments, for example only positional arguments.
This can help reason about debugging errors in specific types of function
calls.
:param which: One of 'keyword', 'positional', 'star', 'double_star'
:return: Strategy for generating an function call isolated to specific
argument types.
"""
kwargs = dict(
max_keyword_args=0,
max_positional_args=0,
max_star_args=0,
max_double_star_args=0,
)
kwargs['_'.join(('min', which, 'args'))] = 1
kwargs['_'.join(('max', which, 'args'))] = 5 if 'star' not in which else 1
return function_calls(**kwargs)
with settings(max_examples=25):
@given(isolated_function_calls('positional'))
@example("fn(0)")
def test_function_positional_only(expr):
validate_uncompyle(expr)
@given(isolated_function_calls('keyword'))
@example("fn(a=0)")
def test_function_call_keyword_only(expr):
validate_uncompyle(expr)
@given(isolated_function_calls('star'))
@example("fn(*items)")
def test_function_call_star_only(expr):
validate_uncompyle(expr)
@given(isolated_function_calls('double_star'))
@example("fn(**{})")
def test_function_call_double_star_only(expr):
validate_uncompyle(expr)
@pytest.mark.xfail()
def test_BUILD_CONST_KEY_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(w=0,m=0,**v)")
@pytest.mark.xfail()
def test_BUILD_MAP_BUILD_MAP_UNPACK_WITH_CALL_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(a=0,**g)")
@pytest.mark.xfail()
def test_CALL_FUNCTION_EX():
validate_uncompyle("fn(*g,**j)")
@pytest.mark.xfail()
def test_BUILD_MAP_CALL_FUNCTION_EX():
validate_uncompyle("fn(*z,u=0)")
@pytest.mark.xfail()
def test_BUILD_TUPLE_CALL_FUNCTION_EX():
validate_uncompyle("fn(**a)")
@pytest.mark.xfail()
def test_BUILD_MAP_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
validate_uncompyle("fn(b,b,b=0,*a)")
@pytest.mark.xfail()
def test_BUILD_TUPLE_BUILD_TUPLE_UNPACK_WITH_CALL_CALL_FUNCTION_EX():
validate_uncompyle("fn(*c,v)")
@pytest.mark.xfail()
def test_BUILD_CONST_KEY_MAP_CALL_FUNCTION_EX():
validate_uncompyle("fn(i=0,y=0,*p)")
@pytest.mark.skip(reason='skipping property based test until all individual tests are passing')
@given(function_calls())
def test_function_call(function_call):
validate_uncompyle(function_call)

View File

@@ -66,9 +66,9 @@ def test_grammar():
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])
# 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)

View File

@@ -8,12 +8,8 @@ from uncompyle6.semantics.consts import (
if PYTHON3:
from io import StringIO
def iteritems(d):
return d.items()
else:
from StringIO import StringIO
def iteritems(d):
return d.iteritems()
from uncompyle6.semantics.pysource import SourceWalker as SourceWalker
@@ -30,7 +26,7 @@ def test_template_engine():
# FIXME: and so on...
from uncompyle6.semantics.consts import (
TABLE_DIRECT, TABLE_R,
TABLE_R, TABLE_DIRECT,
)
from uncompyle6.semantics.fragments import (
@@ -44,7 +40,7 @@ def test_tables():
(TABLE_DIRECT, 'TABLE_DIRECT', False),
(TABLE_R, 'TABLE_R', False),
(TABLE_DIRECT_FRAGMENT, 'TABLE_DIRECT_FRAGMENT', True)):
for k, entry in iteritems(t):
for k, entry in t.iteritems():
if k in skip_for_now:
continue
fmt = entry[0]

View File

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

View File

@@ -9,4 +9,4 @@
12 JUMP_FORWARD 0 'to 15'
15_0 COME_FROM 12 '12'
15 LOAD_CONST 0 ''
18 RETURN_VALUE
18 RETURN_VALUE

View File

@@ -12,4 +12,4 @@
18 STORE_NAME 2 'd'
21_0 COME_FROM 12 '12'
21 LOAD_CONST 2 ''
24 RETURN_VALUE
24 RETURN_VALUE

View File

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

View File

@@ -1,16 +1,16 @@
#!/usr/bin/env python
import sys
"""Setup script for the 'uncompyle6' distribution."""
import sys
SYS_VERSION = sys.version_info[0:2]
if not ((2, 6) <= SYS_VERSION <= (3, 7)) or ((3, 0) <= SYS_VERSION <= (3, 1)):
mess = "Python Release 2.6 .. 3.7 excluding 3.0 and 3.1 are supported in this code branch."
if ((2, 4) <= SYS_VERSION <= (2, 7)):
mess += ("\nFor your Python, version %s, use the python-2.4 code/branch." %
if not ((2, 4) <= SYS_VERSION <= (2, 7)):
mess = "Python Release 2.4 .. 2.7 are supported in this code branch."
if ((3, 2) <= SYS_VERSION <= (3, 7)):
mess += ("\nFor your Python, version %s, use the master code/branch." %
sys.version[0:3])
elif SYS_VERSION < (2, 4) or ((3, 0) <= SYS_VERSION <= (3, 1)):
mess += ("\nThis package is not supported for Python version %s."
else:
mess += ("\nThis package is not supported before Python 2.4. Your Python version is %s."
% sys.version[0:3])
print(mess)
raise Exception(mess)

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

@@ -28,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
@@ -113,6 +113,12 @@ check-bytecode-2.4:
check-bytecode-2.5:
$(PYTHON) test_pythonlib.py --bytecode-2.5
#: Get grammar coverage for Python 2.4
grammar-coverage-2.4:
-rm $(COVER_DIR)/spark-grammar-24.cover
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-24.cover $(PYTHON) test_pythonlib.py --bytecode-2.4
SPARK_PARSER_COVERAGE=$(COVER_DIR)/spark-grammar-24.cover $(PYTHON) test_pyenvlib.py --2.4.6
#: Get grammar coverage for Python 2.5
grammar-coverage-2.5:
-rm $(COVER_DIR)/spark-grammar-25.cover
@@ -215,6 +221,10 @@ check-native-short:
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION) --weak-verify $(COMPILE)
$(PYTHON) test_pythonlib.py --bytecode-$(PYTHON_VERSION)-run --verify-run $(COMPILE)
#: Run longer Python 2.6's lib files known to be okay
check-2.4-ok:
$(PYTHON) test_pythonlib.py --ok-2.4 --verify $(COMPILE)
#: Run longer Python 2.6's lib files known to be okay
check-2.6-ok:
$(PYTHON) test_pythonlib.py --ok-2.6 --weak-verify $(COMPILE)

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.

View File

@@ -1,9 +1,8 @@
#!/usr/bin/env python
# Mode: -*- python -*-
#
# Copyright (c) 2015 by Rocky Bernstein <rb@dustyfeet.com>
# Copyright (c) 2015, 2017 by Rocky Bernstein <rb@dustyfeet.com>
#
from __future__ import print_function
import dis, os.path

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env python
from __future__ import print_function
from uncompyle6 import uncompyle
import sys, inspect

View File

@@ -1,21 +0,0 @@
# From 2.7 test_normalize.py
# Bug has to to with finding the end of the tryelse block. I think thrown
# off by the "continue". In instructions the COME_FROM for END_FINALLY
# was at the wrong offset because some sort of "rtarget" was adjust.
# When control flow is in place this logic in the code will be simplified
def test_main(self, c1):
for line in self:
try:
c1 = 6
except:
if c1:
try:
c1 = 5
except:
pass
else:
c1 = 1
continue
pass

View File

@@ -1,6 +0,0 @@
# Test to see we can a program that has dead code in it.
# This was issue #150
def func(a):
if a:
return True
something_never_run()

View File

@@ -1,11 +0,0 @@
# Issue 151 for Python 2.7
# Bug was two-fold. Not having a rile for a while loop with an ending return statement
# and allowing iflastsmtl to have an optional c_stmt which allowed the "if" to get
# comined into the "while". A separate analysis for control flow should make this
# simpiler.
def func(a, b, c):
while a:
if b:
continue
return False
return True

View File

@@ -1,10 +0,0 @@
# Issue #149. Bug in Python 2.7 was handling a return stmt at the end
# of a while with so no jump back, confusing which block the
# return should be part of
def test(a):
while True:
if a:
pass
else:
continue
return

View File

@@ -1,19 +1,6 @@
#!/bin/bash
me=${BASH_SOURCE[0]}
function displaytime {
local T=$1
local D=$((T/60/60/24))
local H=$((T/60/60%24))
local M=$((T/60%60))
local S=$((T%60))
(( $D > 0 )) && printf '%d days ' $D
(( $H > 0 )) && printf '%d hours ' $H
(( $M > 0 )) && printf '%d minutes ' $M
(( $D > 0 || $H > 0 || $M > 0 )) && printf 'and '
printf '%d seconds\n' $S
}
# Python version setup
FULLVERSION=$(pyenv local)
PYVERSION=${FULLVERSION%.*}
@@ -48,7 +35,9 @@ case $PYVERSION in
[test_pwd.py]=1 # Long test - might work? Control flow?
[test_queue.py]=1 # Control flow?
[test_re.py]=1 # Probably Control flow?
[test_sax.py]=1 # Control flow?
[test_trace.py]=1 # Line numbers are expected to be different
[test_types.py]=1 # Control flow?
[test_zipfile64.py]=1 # Runs ok but takes 204 seconds
)
;;
@@ -73,23 +62,25 @@ case $PYVERSION in
SKIP_TESTS=(
[test_curses.py]=1 # Possibly fails on its own but not detected
[test_dis.py]=1 # We change line numbers - duh!
[test_doctest.py]=1 # Fails on its own
[test_doctest.py]=1
[test_grammar.py]=1 # Too many stmts. Handle large stmts
[test_io.py]=1 # Test takes too long to run
[test_ioctl.py]=1 # Test takes too long to run
[test_itertools.py]=1 # Syntax error - look at!
[test_memoryio.py]=1 # FIX
[test_multiprocessing.py]=1 # On uncompyle2, taks 24 secs
[test_memoryio.py]=1 # ?
[test_multiprocessing.py]=1 # ?
[test_pep352.py]=1 # ?
[test_select.py]=1 # Runs okay but takes 11 seconds
[test_socket.py]=1 # Runs ok but takes 22 seconds
[test_subprocess.py]=1 # Runs ok but takes 22 seconds
[test_re.py]=1 # ?
[test_sys_settrace.py]=1 # Line numbers are expected to be different
[test_strtod.py]=1 # FIX
[test_traceback.py]=1 # Line numbers change - duh.
[test_unicode.py]=1 # Too long to run 11 seconds
[test_xpickle.py]=1 # Runs ok but takes 72 seconds
[test_strtod.py]=1
[test_traceback.py]=1
[test_unicode.py]=1
[test_zipfile64.py]=1 # Runs ok but takes 204 seconds
# Syntax errors:
# .pyenv/versions/2.7.14/lib/python2.7/mimify.pyc
# .pyenv/versions/2.7.14/lib/python2.7/netrc.pyc
# .pyenv/versions/2.7.14/lib/python2.7/pyclbr.pyc
# .pyenv/versions/2.7.14/lib/python2.7/sre_compile.pyc
)
;;
*)
@@ -105,7 +96,7 @@ cd $srcdir
fulldir=$(pwd)
# DECOMPILER=uncompyle2
DECOMPILER=${DECOMPILER:-"$fulldir/../../bin/uncompyle6"}
DECOMPILER="$fulldir/../../bin/uncompyle6"
TESTDIR=/tmp/test${PYVERSION}
if [[ -e $TESTDIR ]] ; then
rm -fr $TESTDIR
@@ -120,16 +111,10 @@ typeset -i i=0
typeset -i allerrs=0
if [[ -n $1 ]] ; then
files=$1
typeset -a files_ary=( $(echo $1) )
if (( ${#files_ary[@]} == 1 )) ; then
SKIP_TESTS=()
fi
SKIP_TESTS=()
else
files=test_*.py
fi
typeset -i ALL_FILES_STARTTIME=$(date +%s)
for file in $files; do
# AIX bash doesn't grok [[ -v SKIP... ]]
[[ ${SKIP_TESTS[$file]} == 1 ]] && continue
@@ -170,11 +155,5 @@ for file in $files; do
exit $allerrs
fi
done
typeset -i ALL_FILES_ENDTIME=$(date +%s)
(( time_diff = ALL_FILES_ENDTIME - ALL_FILES_STARTTIME))
printf "Ran $i tests in "
displaytime $time_diff
echo "Ran $i tests"
exit $allerrs

View File

@@ -19,8 +19,7 @@ Step 2: Run the test:
test_pyenvlib --mylib --verify # decompile verify 'mylib'
"""
from __future__ import print_function
from uncompyle6 import main, PYTHON3
import os, time, re, shutil, sys
from fnmatch import fnmatch

View File

@@ -27,8 +27,6 @@ Step 2: Run the test:
test_pythonlib.py --mylib --verify # decompile verify 'mylib'
"""
from __future__ import print_function
import getopt, os, py_compile, sys, shutil, tempfile, time
from uncompyle6 import PYTHON_VERSION
@@ -130,8 +128,10 @@ def do_tests(src_dir, obj_patterns, target_dir, opts):
if opts['do_compile']:
compiled_version = opts['compiled_version']
if compiled_version and PYTHON_VERSION != compiled_version:
print("Not compiling: desired Python version is %s but we are running %s" %
(compiled_version, PYTHON_VERSION), file=sys.stderr)
sys.stderr.write("Not compiling: "
"desired Python version is %s "
"but we are running %s" %
(compiled_version, PYTHON_VERSION))
else:
for root, dirs, basenames in os.walk(src_dir):
file_matches(files, root, basenames, PY)
@@ -149,8 +149,8 @@ def do_tests(src_dir, obj_patterns, target_dir, opts):
file_matches(files, dirname, basenames, obj_patterns)
if not files:
print("Didn't come up with any files to test! Try with --compile?",
file=sys.stderr)
sys.stderr.write("Didn't come up with any files to test! "
"Try with --compile?")
exit(1)
os.chdir(cwd)
@@ -164,9 +164,9 @@ def do_tests(src_dir, obj_patterns, target_dir, opts):
except ValueError:
pass
print(time.ctime())
print('Source directory: ', src_dir)
print('Output directory: ', target_dir)
print time.ctime()
print 'Source directory: ', src_dir
print 'Output directory: ', target_dir
try:
_, _, failed_files, failed_verify = \
main(src_dir, target_dir, files, [],
@@ -242,14 +242,13 @@ if __name__ == '__main__':
if os.path.isdir(src_dir):
checked_dirs.append([src_dir, pattern, target_dir])
else:
print("Can't find directory %s. Skipping" % src_dir,
file=sys.stderr)
sys.stderr.write("Can't find directory %s. Skipping" % src_dir)
continue
last_compile_version = compiled_version
pass
if not checked_dirs:
print("No directories found to check", file=sys.stderr)
sys.stderr.write("No directories found to check\n")
sys.exit(1)
test_opts['compiled_version'] = last_compile_version

View File

@@ -3,7 +3,6 @@
#
# Copyright (c) 2015-2016 by Rocky Bernstein <rb@dustyfeet.com>
#
from __future__ import print_function
import sys, os, getopt
from uncompyle6.disas import disassemble_file
@@ -26,7 +25,7 @@ Options:
-V | --version show version and stop
-h | --help show this message
""".format(program)
""" % (program, program)
PATTERNS = ('*.pyc', '*.pyo')
@@ -37,15 +36,15 @@ Type -h for for full help.""" % program
native = True
if len(sys.argv) == 1:
print("No file(s) given", file=sys.stderr)
print(Usage_short, file=sys.stderr)
sys.stderr.write("No file(s) given\n")
sys.stderr.write(Usage_short)
sys.exit(1)
try:
opts, files = getopt.getopt(sys.argv[1:], 'hVU',
['help', 'version', 'uncompyle6'])
except getopt.GetoptError as e:
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
except getopt.GetoptError(e):
sys.stderr.write('%s: %s' % (os.path.basename(sys.argv[0]), e))
sys.exit(-1)
for opt, val in opts:
@@ -59,15 +58,14 @@ Type -h for for full help.""" % program
native = False
else:
print(opt)
print(Usage_short, file=sys.stderr)
sys.stderr.write(Usage_short)
sys.exit(1)
for file in files:
if os.path.exists(files[0]):
disassemble_file(file, sys.stdout, native)
else:
print("Can't read %s - skipping" % files[0],
file=sys.stderr)
sys.stderr.write("Can't read %s - skipping\n" % files[0])
pass
pass
return

View File

@@ -4,7 +4,6 @@
# Copyright (c) 2015-2017 by Rocky Bernstein
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
#
from __future__ import print_function
import sys, os, getopt, time
program = 'uncompyle6'
@@ -34,7 +33,6 @@ Options:
-d print timestamps
-p <integer> use <integer> number of processes
-r recurse directories looking for .pyc and .pyo files
--fragments use fragments deparser
--verify compare generated source with input byte-code
--verify-run compile generated source, run it and check exit code
--weak-verify compile generated source
@@ -68,11 +66,11 @@ def usage():
def main_bin():
if not (sys.version_info[0:2] in ((2, 6), (2, 7),
(3, 1), (3, 2), (3, 3),
if not (sys.version_info[0:2] in ((2, 4), (2, 5), (2, 6), (2, 7),
(3, 2), (3, 3),
(3, 4), (3, 5), (3, 6))):
print('Error: %s requires Python 2.6-2.7, or 3.1-3.6' % program,
file=sys.stderr)
sys.stderr.write('Error: %s requires Python 2.4 2.5 2.6, 2.7, '
'3.2, 3.3, 3.4, 3.5, or 3.6' % program)
sys.exit(-1)
do_verify = recurse_dirs = False
@@ -86,10 +84,9 @@ def main_bin():
try:
opts, files = getopt.getopt(sys.argv[1:], 'hagtdrVo:c:p:',
'help asm grammar linemaps recurse timestamp tree '
'fragments verify verify-run version weak-verify '
'showgrammar'.split(' '))
except getopt.GetoptError as e:
print('%s: %s' % (os.path.basename(sys.argv[0]), e), file=sys.stderr)
'verify verify-run version showgrammar'.split(' '))
except getopt.GetoptError, e:
sys.stderr.write('%s: %s\n' % (os.path.basename(sys.argv[0]), e))
sys.exit(-1)
options = {}
@@ -104,8 +101,6 @@ def main_bin():
options['do_verify'] = 'strong'
elif opt == '--weak-verify':
options['do_verify'] = 'weak'
elif opt == '--fragments':
options['do_fragments'] = True
elif opt == '--verify-run':
options['do_verify'] = 'verify-run'
elif opt == '--linemaps':
@@ -129,7 +124,7 @@ def main_bin():
elif opt in ('--recurse', '-r'):
recurse_dirs = True
else:
print(opt, file=sys.stderr)
sys.stderr.write(opt)
usage()
# expand directory if specified
@@ -154,7 +149,7 @@ def main_bin():
files = [f[sb_len:] for f in files]
if not files:
print("No files given", file=sys.stderr)
sys.stderr.write("No files given\n")
usage()
if outfile == '-':
@@ -171,9 +166,8 @@ def main_bin():
try:
result = main(src_base, out_base, files, codes, outfile,
**options)
result = list(result) + [options.get('do_verify', None)]
if len(files) > 1:
mess = status_msg(do_verify, *result)
mess = status_msg(do_verify, result, do_verify)
print('# ' + mess)
pass
except (KeyboardInterrupt):

View File

@@ -16,8 +16,6 @@ Second, we need structured instruction information for the
want to run on earlier Python versions.
"""
from __future__ import print_function
import sys
from collections import deque
@@ -36,10 +34,9 @@ def disco(version, co, out=None, is_pypy=False):
# store final output stream for case of error
real_out = out or sys.stdout
print('# Python %s' % version, file=real_out)
real_out.write('# Python %s\n' % version)
if co.co_filename:
print('# Embedded file name: %s' % co.co_filename,
file=real_out)
real_out.write('# Embedded file name: %s\n' % co.co_filename)
scanner = get_scanner(version, is_pypy=is_pypy)
@@ -51,16 +48,15 @@ def disco_loop(disasm, queue, real_out):
while len(queue) > 0:
co = queue.popleft()
if co.co_name != '<module>':
print('\n# %s line %d of %s' %
(co.co_name, co.co_firstlineno, co.co_filename),
file=real_out)
real_out.write('\n# %s line %d of %s\n' %
(co.co_name, co.co_firstlineno, co.co_filename))
tokens, customize = disasm(co)
for t in tokens:
if iscode(t.pattr):
queue.append(t.pattr)
elif iscode(t.attr):
queue.append(t.attr)
print(t, file=real_out)
real_out.write(t)
pass
pass

View File

@@ -10,7 +10,7 @@ def line_number_mapping(pyc_filename, src_filename):
source_size) = load_module(pyc_filename)
try:
code2 = load_file(src_filename)
except SyntaxError as e:
except SyntaxError, e:
return str(e)
queue = deque([code1, code2])

View File

@@ -1,4 +1,3 @@
from __future__ import print_function
import datetime, os, subprocess, sys, tempfile
from uncompyle6 import verify, IS_PYPY, PYTHON_VERSION
@@ -7,10 +6,9 @@ from uncompyle6.disas import check_object_path
from uncompyle6.semantics import pysource
from uncompyle6.parser import ParserError
from uncompyle6.version import VERSION
# from uncompyle6.linenumbers import line_number_mapping
from uncompyle6.linenumbers import line_number_mapping
from uncompyle6.semantics.pysource import deparse_code
from uncompyle6.semantics.fragments import deparse_code as deparse_code_fragments
from uncompyle6.semantics.linemap import deparse_code_with_map
from xdis.load import load_module
@@ -30,7 +28,7 @@ def decompile(
bytecode_version, co, out=None, showasm=None, showast=False,
timestamp=None, showgrammar=False, code_objects={},
source_size=None, is_pypy=False, magic_int=None,
mapstream=None, do_fragments=False):
mapstream=None):
"""
ingests and deparses a given code block 'co'
@@ -45,20 +43,35 @@ def decompile(
assert iscode(co)
co_pypy_str = 'PyPy ' if is_pypy else ''
run_pypy_str = 'PyPy ' if IS_PYPY else ''
if is_pypy:
co_pypy_str = 'PyPy '
else:
co_pypy_str = ''
if IS_PYPY:
run_pypy_str = 'PyPy '
else:
run_pypy_str = ''
if magic_int:
m = str(magic_int)
else:
m = ""
sys_version_lines = sys.version.split('\n')
write('# uncompyle6 version %s\n'
'# %sPython bytecode %s%s\n# Decompiled from: %sPython %s' %
(VERSION, co_pypy_str, bytecode_version,
" (%s)" % str(magic_int) if magic_int else "",
run_pypy_str, '\n# '.join(sys_version_lines)))
" (%s)" % m, run_pypy_str,
'\n# '.join(sys_version_lines)))
if co.co_filename:
write('# Embedded file name: %s' % co.co_filename,)
if timestamp:
write('# Compiled at: %s' % datetime.datetime.fromtimestamp(timestamp))
write('# Compiled at: %s' %
datetime.datetime.fromtimestamp(timestamp))
if source_size:
write('# Size of source mod 2**32: %d bytes' % source_size)
real_out.write('# Size of source mod 2**32: %d bytes\n' %
source_size)
try:
if mapstream:
@@ -76,21 +89,17 @@ def decompile(
sorted(deparsed.source_linemap.keys())]
mapstream.write("\n\n# %s\n" % linemap)
else:
if do_fragments:
deparse_fn = deparse_code_fragments
else:
deparse_fn = deparse_code
deparsed = deparse_fn(bytecode_version, co, out, showasm, showast,
showgrammar, code_objects=code_objects,
is_pypy=is_pypy)
deparsed = deparse_code(bytecode_version, co, out, showasm, showast,
showgrammar, code_objects=code_objects,
is_pypy=is_pypy)
pass
return deparsed
except pysource.SourceWalkerError as e:
except pysource.SourceWalkerError, e:
# deparsing failed
raise pysource.SourceWalkerError(str(e))
def decompile_file(filename, outstream=None, showasm=None, showast=False,
showgrammar=False, mapstream=None, do_fragments=False):
showgrammar=False, mapstream=None):
"""
decompile Python byte-code file (.pyc). Return objects to
all of the deparsed objects found in `filename`.
@@ -114,7 +123,7 @@ def decompile_file(filename, outstream=None, showasm=None, showast=False,
timestamp, showgrammar,
code_objects=code_objects, source_size=source_size,
is_pypy=is_pypy, magic_int=magic_int,
mapstream=mapstream, do_fragments=do_fragments)]
mapstream=mapstream)]
co = None
return deparsed
@@ -123,7 +132,7 @@ def decompile_file(filename, outstream=None, showasm=None, showast=False,
def main(in_base, out_base, files, codes, outfile=None,
showasm=None, showast=False, do_verify=False,
showgrammar=False, raise_on_error=False,
do_linemaps=False, do_fragments=False):
do_linemaps=False):
"""
in_base base directory for input files
out_base base directory for output files (ignored when
@@ -164,17 +173,10 @@ def main(in_base, out_base, files, codes, outfile=None,
prefix = prefix[:-len('.py')]
# Unbuffer output if possible
buffering = -1 if sys.stdout.isatty() else 0
if PYTHON_VERSION >= 3.5:
t = tempfile.NamedTemporaryFile(mode='w+b',
buffering=buffering,
suffix='.py',
prefix=prefix)
if sys.stdout.isatty():
buffering = -1
else:
t = tempfile.NamedTemporaryFile(mode='w+b',
suffix='.py',
prefix=prefix)
current_outfile = t.name
buffering = 0
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering)
tee = subprocess.Popen(["tee", current_outfile],
stdin=subprocess.PIPE)
@@ -194,28 +196,11 @@ def main(in_base, out_base, files, codes, outfile=None,
# Try to uncompile the input file
try:
deparsed = decompile_file(infile, outstream, showasm, showast, showgrammar,
linemap_stream, do_fragments)
if do_fragments:
for d in deparsed:
last_mod = None
offsets = d.offsets
for e in sorted([k for k in offsets.keys() if isinstance(k[1], int)]):
if e[0] != last_mod:
line = '=' * len(e[0])
outstream.write("%s\n%s\n%s\n" % (line, e[0], line))
last_mod = e[0]
info = offsets[e]
extractInfo = d.extract_node_info(info)
outstream.write("%s" % info.node.format().strip() + "\n")
outstream.write(extractInfo.selectedLine + "\n")
outstream.write(extractInfo.markerLine + "\n\n")
pass
pass
decompile_file(infile, outstream, showasm, showast, showgrammar, linemap_stream)
tot_files += 1
except (ValueError, SyntaxError, ParserError, pysource.SourceWalkerError) as e:
except (ValueError, SyntaxError, ParserError, pysource.SourceWalkerError):
sys.stdout.write("\n")
sys.stderr.write("\n# file %s\n# %s\n" % (infile, e))
sys.stderr.write("# file %s\n" % (infile))
failed_files += 1
except KeyboardInterrupt:
if outfile:
@@ -243,7 +228,7 @@ def main(in_base, out_base, files, codes, outfile=None,
do_verify)
if not current_outfile:
if not msg:
print('\n# okay decompiling %s' % infile)
print '\n# okay decompiling %s' % infile
okay_files += 1
else:
verify_failed_files += 1
@@ -252,13 +237,16 @@ def main(in_base, out_base, files, codes, outfile=None,
else:
okay_files += 1
pass
except verify.VerifyCmpError as e:
except verify.VerifyCmpError, e:
print(e)
verify_failed_files += 1
os.rename(current_outfile, current_outfile + '_unverified')
sys.stderr.write("### Error Verifying %s\n" % filename)
sys.stderr.write(str(e) + "\n")
if not outfile:
sys.stderr.write("### Error Verifiying %s" %
filename)
sys.stderr.write(e)
if raise_on_error:
raise
pass
@@ -268,14 +256,15 @@ def main(in_base, out_base, files, codes, outfile=None,
okay_files += 1
pass
elif do_verify:
sys.stderr.write("\n### uncompile successful, but no file to compare against\n")
sys.stderr.write("\n### uncompile successful, "
"but no file to compare against")
pass
else:
okay_files += 1
if not current_outfile:
mess = '\n# okay decompiling'
# mem_usage = __memUsage()
print(mess, infile)
print mess, infile
if current_outfile:
sys.stdout.write("%s\r" %
status_msg(do_verify, tot_files, okay_files, failed_files,

View File

@@ -6,8 +6,6 @@
Common uncompyle6 parser routines.
"""
from __future__ import print_function
import sys
from xdis.code import iscode
@@ -168,7 +166,7 @@ class PythonParser(GenericASTBuilder):
indent = ' '
else:
indent = '-> '
print("%s%s" % (indent, instructions[i]))
print "%s%s" % (indent, instructions[i])
raise ParserError(err_token, err_token.offset)
else:
raise ParserError(None, -1)
@@ -323,7 +321,7 @@ class PythonParser(GenericASTBuilder):
stmt ::= return
return ::= ret_expr RETURN_VALUE
# "returns" nonterminal is a sequence of statements that ends in a RETURN statement.
# returns are a sequence of statements that ends in a RETURN statement.
# In later Python versions with jump optimization, this can cause JUMPs
# that would normally appear to be omitted.
@@ -768,4 +766,4 @@ if __name__ == '__main__':
ast = python_parser(PYTHON_VERSION, co, showasm=True, is_pypy=IS_PYPY)
print(ast)
return
parse_test(parse_test.__code__)
# parse_test(parse_test.__code__)

View File

@@ -12,8 +12,6 @@ If we succeed in creating a parse tree, then we have a Python program
that a later phase can turn into a sequence of ASCII text.
"""
from __future__ import print_function
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
from uncompyle6.parsers.astnode import AST
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
@@ -505,7 +503,7 @@ class Python2Parser(PythonParser):
self.check_reduce['aug_assign1'] = 'AST'
self.check_reduce['aug_assign2'] = 'AST'
# self.check_reduce['_stmts'] = 'AST'
self.check_reduce['_stmts'] = 'AST'
# Dead code testing...
# self.check_reduce['while1elsestmt'] = 'tokens'
@@ -522,6 +520,15 @@ class Python2Parser(PythonParser):
if lhs in ('aug_assign1', 'aug_assign2') and ast[0] and ast[0][0] == 'and':
return True
elif lhs == '_stmts':
for i, stmt in enumerate(ast):
if stmt == '_stmts':
stmt = stmt[0]
assert stmt == 'stmt'
if stmt[0] == 'return':
return i+1 != len(ast)
pass
return False
return False
class Python2ParserSingle(Python2Parser, PythonParserSingle):

View File

@@ -69,6 +69,7 @@ class Python24Parser(Python25Parser):
super(Python24Parser, self).customize_grammar_rules(tokens, customize)
if self.version == 2.4:
self.check_reduce['nop_stmt'] = 'tokens'
self.check_reduce['try_except'] = 'tokens'
def reduce_is_invalid(self, rule, ast, tokens, first, last):
invalid = super(Python24Parser,

View File

@@ -19,6 +19,9 @@ class Python25Parser(Python26Parser):
return_if_stmt ::= ret_expr RETURN_END_IF JUMP_BACK
# We have no jumps to jumps, so no "come_froms" but a single "COME_FROM"
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite COME_FROM
# Python 2.6 uses ROT_TWO instead of the STORE_xxx
# withas is allowed as a "from future" in 2.5
# 2.6 and 2.7 do something slightly different
@@ -36,6 +39,8 @@ class Python25Parser(Python26Parser):
# loop. FIXME: should "come_froms" below be a single COME_FROM?
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
except_handler else_suite come_froms
tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
except_handler else_suitel
# Python 2.6 omits the LOAD_FAST DELETE_FAST below
# withas is allowed as a "from future" in 2.5
@@ -54,6 +59,9 @@ class Python25Parser(Python26Parser):
def customize_grammar_rules(self, tokens, customize):
# Remove grammar rules inherited from Python 2.6 or Python 2
self.remove_rules("""
# No jump to jumps in 2.4 so we have a single "COME_FROM", not "come_froms"
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite come_froms
setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
withstmt ::= expr setupwith SETUP_FINALLY suite_stmts_opt
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY

View File

@@ -64,9 +64,9 @@ class Python27Parser(Python2Parser):
def p_jump27(self, args):
"""
iflaststmtl ::= testexpr c_stmts
iflaststmtl ::= testexpr c_stmts_opt
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD come_froms
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD come_froms
bp_come_from ::= POP_BLOCK COME_FROM
# FIXME: Common with 3.0+
@@ -119,9 +119,6 @@ class Python27Parser(Python2Parser):
POP_BLOCK LOAD_CONST COME_FROM_WITH
WITH_CLEANUP END_FINALLY
whilestmt ::= SETUP_LOOP testexpr returns
_come_froms POP_BLOCK COME_FROM
while1stmt ::= SETUP_LOOP returns bp_come_from
while1stmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK COME_FROM
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK _come_froms
@@ -197,4 +194,5 @@ if __name__ == '__main__':
for t in remain_tokens])
remain_tokens = set(remain_tokens) - opcode_set
print(remain_tokens)
# p.dump_grammar()
p.check_grammar()
p.dump_grammar()

View File

@@ -19,6 +19,7 @@ from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
from uncompyle6.parsers.astnode import AST
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from xdis import PYTHON3
from itertools import islice,chain,repeat
class Python3Parser(PythonParser):
@@ -1092,7 +1093,7 @@ class Python3Parser(PythonParser):
if tokens[cfl-1] != 'JUMP_BACK':
cfl_offset = tokens[cfl-1].offset
insn = next(i for i in self.insts if cfl_offset == i.offset)
insn = chain((i for i in self.insts if cfl_offset == i.offset), repeat(None)).next()
if insn and insn.is_jump_target:
return True

View File

@@ -2,7 +2,6 @@
"""
spark grammar differences over Python 3.1 for Python 3.0.
"""
from __future__ import print_function
from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse31 import Python31Parser

View File

@@ -2,7 +2,6 @@
"""
spark grammar differences over Python 3.2 for Python 3.1.
"""
from __future__ import print_function
from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse32 import Python32Parser

View File

@@ -2,8 +2,6 @@
"""
spark grammar differences over Python 3 for Python 3.2.
"""
from __future__ import print_function
from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse3 import Python3Parser

View File

@@ -2,7 +2,6 @@
"""
spark grammar differences over Python 3.2 for Python 3.3.
"""
from __future__ import print_function
from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse32 import Python32Parser

View File

@@ -2,7 +2,6 @@
"""
spark grammar differences over Python 3.4 for Python 3.5.
"""
from __future__ import print_function
from uncompyle6.parser import PythonParserSingle, nop_func
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG

View File

@@ -2,7 +2,6 @@
"""
spark grammar differences over Python 3.5 for Python 3.6.
"""
from __future__ import print_function
from uncompyle6.parser import PythonParserSingle, nop_func
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
@@ -135,9 +134,9 @@ class Python36Parser(Python35Parser):
if opname.startswith('CALL_FUNCTION_KW'):
self.addRule("expr ::= call_kw", nop_func)
values = 'expr ' * token.attr
rule = 'call_kw ::= expr kwargs_36 {token.kind}'.format(**locals())
rule = 'call_kw ::= expr kwargs_36 %s' % token.kind
self.addRule(rule, nop_func)
rule = 'kwargs_36 ::= {values} LOAD_CONST'.format(**locals())
rule = 'kwargs_36 ::= %s LOAD_CONST' % values
self.add_unique_rule(rule, token.kind, token.attr, customize)
elif opname == 'CALL_FUNCTION_EX_KW':
self.addRule("""expr ::= call_ex_kw

View File

@@ -2,7 +2,6 @@
"""
spark grammar differences over Python 3.6 for Python 3.7
"""
from __future__ import print_function
from uncompyle6.parser import PythonParserSingle
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016, 2018 by Rocky Bernstein
# Copyright (c) 2016-2017 by Rocky Bernstein
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
# Copyright (c) 1999 John Aycock
@@ -10,14 +10,11 @@ scanner/ingestion module. From here we call various version-specific
scanners, e.g. for Python 2.7 or 3.4.
"""
from __future__ import print_function
import sys
from uncompyle6 import PYTHON3, IS_PYPY
from uncompyle6.scanners.tok import Token
import xdis
from xdis.bytecode import op_size, extended_arg_val
from xdis.bytecode import op_size
from xdis.magics import py_str2float, canonic_python_version
from xdis.util import code2num
@@ -106,13 +103,14 @@ class Scanner(object):
target += pos + 3
return target
# FIXME: the below can be removed after xdis version 3.6.1 has been released
def extended_arg_val(self, val):
return val << self.opc.EXTENDED_ARG_SHIFT
def get_argument(self, pos):
arg = self.code[pos+1] + self.code[pos+2] * 256
return arg
def next_offset(self, op, offset):
return xdis.next_offset(op, self.opc, offset)
def print_bytecode(self):
for i in self.op_range(0, len(self.code)):
op = self.code[i]
@@ -190,7 +188,7 @@ class Scanner(object):
if op == self.opc.EXTENDED_ARG:
arg = code2num(code, offset+1) | extended_arg
extended_arg = extended_arg_val(self.opc, arg)
extended_arg = self.extended_arg_val(arg)
continue
if op in instr:
@@ -242,7 +240,7 @@ class Scanner(object):
if op == self.opc.EXTENDED_ARG:
arg = code2num(code, offset+1) | extended_arg
extended_arg = extended_arg_val(self.opc, arg)
extended_arg = self.extended_arg_val(arg)
continue
if op in instr:

View File

@@ -13,13 +13,13 @@ import uncompyle6.scanners.scanner21 as scan
from xdis.opcodes import opcode_15
JUMP_OPS = opcode_15.JUMP_OPS
# We base this off of 2.2 instead of the other way around
# We base this off of 2.1 instead of the other way around
# because we cleaned things up this way.
# The history is that 2.7 support is the cleanest,
# then from that we got 2.6 and so on.
class Scanner15(scan.Scanner21):
def __init__(self, show_asm=False):
scan.Scanner21.__init__(self, show_asm)
scan.Scanner21.__init__(self, show_asm=False)
self.opc = opcode_15
self.opname = opcode_15.opname
self.version = 1.5

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2015-2018 by Rocky Bernstein
# Copyright (c) 2015-2017 by Rocky Bernstein
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
"""
@@ -20,9 +20,13 @@ For example:
Finally we save token information.
"""
from __future__ import print_function
from uncompyle6 import PYTHON_VERSION
if PYTHON_VERSION < 2.6:
from xdis.namedtuple24 import namedtuple
else:
from collections import namedtuple
from collections import namedtuple
from array import array
from xdis.code import iscode
@@ -109,11 +113,7 @@ class Scanner2(Scanner):
self.build_lines_data(co, codelen)
self.build_prev_op(codelen)
self.insts = list(bytecode)
self.offset2inst_index = {}
for i, inst in enumerate(self.insts):
self.offset2inst_index[inst.offset] = i
free, names, varnames = self.unmangle_code_names(co, classname)
self.names = names
@@ -510,55 +510,50 @@ class Scanner2(Scanner):
# Try to find the jump_back instruction of the loop.
# It could be a return instruction.
inst = self.insts[self.offset2inst_index[offset]]
start += instruction_size(op, self.opc)
setup_target = inst.argval
loop_end_offset = self.restrict_to_parent(setup_target, parent)
self.setup_loop_targets[offset] = setup_target
self.setup_loops[setup_target] = offset
target = self.get_target(offset) + extended_arg
end = self.restrict_to_parent(target, parent)
self.setup_loop_targets[offset] = target
self.setup_loops[target] = offset
if setup_target != loop_end_offset:
self.fixed_jumps[offset] = loop_end_offset
if target != end:
self.fixed_jumps[offset] = end
(line_no, next_line_byte) = self.lines[offset]
# jump_back_offset is the instruction after the SETUP_LOOP
# where we iterate back to.
jump_back_offset = self.last_instr(start, loop_end_offset, self.opc.JUMP_ABSOLUTE,
jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE,
next_line_byte, False)
if jump_back_offset:
if jump_back:
# Account for the fact that < 2.7 has an explicit
# POP_TOP instruction in the equivalate POP_JUMP_IF
# construct
if self.version < 2.7:
jump_forward_offset = jump_back_offset+4
return_val_offset1 = self.prev[self.prev[self.prev[loop_end_offset]]]
jump_forward_offset = jump_back+4
return_val_offset1 = self.prev[self.prev[self.prev[end]]]
# Is jump back really "back"?
jump_target = self.get_target(jump_back_offset, code[jump_back_offset])
if (jump_target > jump_back_offset or
code[jump_back_offset+3] in [self.opc.JUMP_FORWARD, self.opc.JUMP_ABSOLUTE]):
jump_back_offset = None
jump_target = self.get_target(jump_back, code[jump_back])
if (jump_target > jump_back or
code[jump_back+3] in [self.opc.JUMP_FORWARD, self.opc.JUMP_ABSOLUTE]):
jump_back = None
pass
else:
jump_forward_offset = jump_back_offset+3
return_val_offset1 = self.prev[self.prev[loop_end_offset]]
jump_forward_offset = jump_back+3
return_val_offset1 = self.prev[self.prev[end]]
if (jump_back_offset and jump_back_offset != self.prev[loop_end_offset]
if (jump_back and jump_back != self.prev[end]
and code[jump_forward_offset] in self.jump_forward):
if (code[self.prev[loop_end_offset]] == self.opc.RETURN_VALUE or
(code[self.prev[loop_end_offset]] == self.opc.POP_BLOCK
if (code[self.prev[end]] == self.opc.RETURN_VALUE or
(code[self.prev[end]] == self.opc.POP_BLOCK
and code[return_val_offset1] == self.opc.RETURN_VALUE)):
jump_back_offset = None
if not jump_back_offset:
jump_back = None
if not jump_back:
# loop suite ends in return
# scanner26 of wbiti had:
# jump_back_offset = self.last_instr(start, loop_end_offset, self.opc.JUMP_ABSOLUTE, start, False)
jump_back_offset = self.last_instr(start, loop_end_offset, self.opc.RETURN_VALUE)
if not jump_back_offset:
# jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE, start, False)
jump_back = self.last_instr(start, end, self.opc.RETURN_VALUE)
if not jump_back:
return
jump_back_offset += 1
jump_back += 1
if_offset = None
if self.version < 2.7:
@@ -574,76 +569,71 @@ class Scanner2(Scanner):
loop_type = 'while'
self.ignore_if.add(if_offset)
if self.version < 2.7 and (
code[self.prev[jump_back_offset]] == self.opc.RETURN_VALUE):
self.ignore_if.add(self.prev[jump_back_offset])
code[self.prev[jump_back]] == self.opc.RETURN_VALUE):
self.ignore_if.add(self.prev[jump_back])
pass
pass
else:
loop_type = 'for'
setup_target = next_line_byte
loop_end_offset = jump_back_offset + 3
target = next_line_byte
end = jump_back + 3
else:
# We have a loop with a jump-back instruction
if self.get_target(jump_back_offset) >= next_line_byte:
jump_back_offset = self.last_instr(start, loop_end_offset, self.opc.JUMP_ABSOLUTE, start, False)
if loop_end_offset > jump_back_offset+4 and code[loop_end_offset] in self.jump_forward:
if code[jump_back_offset+4] in self.jump_forward:
if self.get_target(jump_back_offset+4) == self.get_target(loop_end_offset):
self.fixed_jumps[offset] = jump_back_offset+4
loop_end_offset = jump_back_offset+4
elif setup_target < offset:
self.fixed_jumps[offset] = jump_back_offset+4
loop_end_offset = jump_back_offset+4
if self.get_target(jump_back) >= next_line_byte:
jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE, start, False)
if end > jump_back+4 and code[end] in self.jump_forward:
if code[jump_back+4] in self.jump_forward:
if self.get_target(jump_back+4) == self.get_target(end):
self.fixed_jumps[offset] = jump_back+4
end = jump_back+4
elif target < offset:
self.fixed_jumps[offset] = jump_back+4
end = jump_back+4
setup_target = self.get_target(jump_back_offset, self.opc.JUMP_ABSOLUTE)
target = self.get_target(jump_back, self.opc.JUMP_ABSOLUTE)
if (self.version > 2.1 and
code[setup_target] in (self.opc.FOR_ITER, self.opc.GET_ITER)):
code[target] in (self.opc.FOR_ITER, self.opc.GET_ITER)):
loop_type = 'for'
else:
loop_type = 'while'
# Look for a test condition immediately after the
# SETUP_LOOP while
if (self.version < 2.7
and self.code[self.prev[next_line_byte]] == self.opc.POP_TOP):
test_op_offset = self.prev[self.prev[next_line_byte]]
test = self.prev[self.prev[next_line_byte]]
else:
test_op_offset = self.prev[next_line_byte]
test = self.prev[next_line_byte]
if test_op_offset == offset:
if test == offset:
loop_type = 'while 1'
elif self.code[test_op_offset] in self.opc.JUMP_OPs:
test_target = self.get_target(test_op_offset)
self.ignore_if.add(test_op_offset)
if test_target > (jump_back_offset+3):
jump_back_offset = test_target
self.not_continue.add(jump_back_offset)
self.loops.append(setup_target)
elif self.code[test] in self.opc.JUMP_OPs:
self.ignore_if.add(test)
test_target = self.get_target(test)
if test_target > (jump_back+3):
jump_back = test_target
self.not_continue.add(jump_back)
self.loops.append(target)
self.structs.append({'type': loop_type + '-loop',
'start': setup_target,
'end': jump_back_offset})
if jump_back_offset+3 != loop_end_offset:
'start': target,
'end': jump_back})
if jump_back+3 != end:
self.structs.append({'type': loop_type + '-else',
'start': jump_back_offset+3,
'end': loop_end_offset})
'start': jump_back+3,
'end': end})
elif op == self.opc.SETUP_EXCEPT:
start = offset + op_size(op, self.opc)
target = self.get_target(offset, op)
end_offset = self.restrict_to_parent(target, parent)
if target != end_offset:
self.fixed_jumps[offset] = end_offset
end = self.restrict_to_parent(target, parent)
if target != end:
self.fixed_jumps[offset] = end
# print target, end, parent
# Add the try block
self.structs.append({'type': 'try',
'start': start-3,
'end': end_offset-4})
'end': end-4})
# Now isolate the except and else blocks
end_else = start_else = self.get_target(self.prev[end_offset])
end_else = start_else = self.get_target(self.prev[end])
end_finally_offset = end_offset
end_finally_offset = end
setup_except_nest = 0
while end_finally_offset < len(self.code):
if self.code[end_finally_offset] == self.opc.END_FINALLY:
@@ -657,7 +647,7 @@ class Scanner2(Scanner):
pass
# Add the except blocks
i = end_offset
i = end
while i < len(self.code) and i < end_finally_offset:
jmp = self.next_except_jump(i)
if jmp is None: # check
@@ -715,7 +705,7 @@ class Scanner2(Scanner):
test_target = target
if self.version < 2.7:
# Before 2.7 we have to deal with the fact that there is an extra
# Before 2.6 we have to deal with the fact that there is an extra
# POP_TOP that is logically associated with the JUMP_IF's (even though
# the instance set is called "self.pop_jump_if")
if code[pre[test_target]] == self.opc.POP_TOP:
@@ -725,29 +715,22 @@ class Scanner2(Scanner):
test_set = self.pop_jump_if_or_pop | self.pop_jump_if
if ( code[pre[test_target]] in test_set and target > offset ):
# We have POP_JUMP_IF... target
# ...
# pre: POP_JUMP_IF ...
# target: ...
#
# We will take that as either as "and" or "or".
self.fixed_jumps[offset] = pre[target]
self.structs.append({'type': 'and/or',
'start': start,
'end': pre[target]})
return
# The instruction offset just before the target jump offset is important
# The op offset just before the target jump offset is important
# in making a determination of what we have. Save that.
pre_rtarget = pre[rtarget]
# Is it an "and" inside an "if" or "while" block
if op == self.opc.PJIF:
# Search for other POP_JUMP_IF_...'s targetting the
# same target, of the current POP_JUMP_... instruction,
# starting from current offset, and filter everything inside inner 'or'
# jumps and mid-line ifs
# Search for other POP_JUMP_IF_FALSE targetting the same op,
# in current statement, starting from current offset, and filter
# everything inside inner 'or' jumps and midline ifs
match = self.rem_or(start, self.next_stmt[offset], self.opc.PJIF, target)
# If we still have any offsets in set, start working on it
@@ -837,7 +820,6 @@ class Scanner2(Scanner):
rtarget = pre_rtarget
else:
rtarget = pre_rtarget
pre_rtarget = pre[rtarget]
# Does the "jump if" jump beyond a jump op?
# That is, we have something like:
@@ -846,7 +828,7 @@ class Scanner2(Scanner):
# JUMP_FORWARD
# HERE:
#
# If so, this can be a block inside an "if" statement
# If so, this can be block inside an "if" statement
# or a conditional assignment like:
# x = 1 if x else 2
#
@@ -877,7 +859,7 @@ class Scanner2(Scanner):
self.fixed_jumps[jump_if_offset] = jump_target
return
end_offset = self.restrict_to_parent(if_end, parent)
end = self.restrict_to_parent(if_end, parent)
if_then_maybe = None
@@ -916,7 +898,7 @@ class Scanner2(Scanner):
self.structs.append({'type': 'if-then',
'start': start-3,
'end': pre_rtarget})
self.thens[start] = end_offset
self.thens[start] = end
elif jump_op == 'JUMP_ABSOLUTE':
if_then_maybe = {'type': 'if-then',
'start': start-3,
@@ -931,7 +913,7 @@ class Scanner2(Scanner):
if pre_rtarget not in self.linestartoffsets or self.version < 2.7:
self.not_continue.add(pre_rtarget)
if rtarget < end_offset:
if rtarget < end:
# We have an "else" block of some kind.
# Is it associated with "if_then_maybe" seen above?
# These will be linked in this funny way:
@@ -947,15 +929,15 @@ class Scanner2(Scanner):
# 256
if if_then_maybe and jump_op == 'JUMP_ABSOLUTE':
jump_target = self.get_target(jump_inst, code[jump_inst])
if self.opname_for_offset(end_offset) == 'JUMP_FORWARD':
end_target = self.get_target(end_offset, code[end_offset])
if self.opname_for_offset(end) == 'JUMP_FORWARD':
end_target = self.get_target(end, code[end])
if jump_target == end_target:
self.structs.append(if_then_maybe)
self.thens[start] = end_offset
self.thens[start] = end
self.structs.append({'type': 'else',
'start': rtarget,
'end': end_offset})
'end': end})
elif code_pre_rtarget == self.opc.RETURN_VALUE:
if self.version == 2.7 or pre_rtarget not in self.ignore_if:
# 10 is exception-match. If there is an exception match in the

View File

@@ -19,7 +19,7 @@ JUMP_OPS = opcode_21.JUMP_OPS
# then from that we got 2.6 and so on.
class Scanner21(scan.Scanner22):
def __init__(self, show_asm=False):
scan.Scanner22.__init__(self, show_asm)
scan.Scanner22.__init__(self, show_asm=False)
self.opc = opcode_21
self.opname = opcode_21.opname
self.version = 2.1

View File

@@ -19,7 +19,7 @@ JUMP_OPS = opcode_22.JUMP_OPS
# then from that we got 2.6 and so on.
class Scanner22(scan.Scanner23):
def __init__(self, show_asm=False):
scan.Scanner23.__init__(self, show_asm)
scan.Scanner23.__init__(self, show_asm=False)
self.opc = opcode_22
self.opname = opcode_22.opname
self.version = 2.2

View File

@@ -110,11 +110,7 @@ class Scanner26(scan.Scanner2):
self.build_lines_data(co, codelen)
self.build_prev_op(codelen)
self.insts = list(bytecode)
self.offset2inst_index = {}
for i, inst in enumerate(self.insts):
self.offset2inst_index[inst.offset] = i
free, names, varnames = self.unmangle_code_names(co, classname)
self.names = names

View File

@@ -7,8 +7,6 @@ grammar parsing.
"""
from __future__ import print_function
from uncompyle6.scanners.scanner2 import Scanner2
from uncompyle6 import PYTHON3

View File

@@ -20,9 +20,13 @@ For example:
Finally we save token information.
"""
from __future__ import print_function
from uncompyle6 import PYTHON_VERSION
if PYTHON_VERSION < 2.6:
from xdis.namedtuple24 import namedtuple
else:
from collections import namedtuple
from collections import namedtuple
from array import array
from uncompyle6.scanner import Scanner
@@ -162,7 +166,9 @@ class Scanner3(Scanner):
self.code = array('B', co.co_code)
bytecode = Bytecode(co, self.opc)
show_asm = self.show_asm if not show_asm else show_asm
if not show_asm:
show_asm = self.show_asm
# show_asm = 'both'
if show_asm in ('both', 'before'):
for instr in bytecode.get_instructions(co):

View File

@@ -6,8 +6,6 @@ This sets up opcodes Python's 3.0 and calls a generalized
scanner routine for Python 3.
"""
from __future__ import print_function
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_30 as opc
from xdis.bytecode import instruction_size, next_offset

View File

@@ -6,8 +6,6 @@ This sets up opcodes Python's 3.1 and calls a generalized
scanner routine for Python 3.
"""
from __future__ import print_function
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_31 as opc
JUMP_OPS = opc.JUMP_OPS

View File

@@ -9,8 +9,6 @@ This sets up opcodes Python's 3.2 and calls a generalized
scanner routine for Python 3.
"""
from __future__ import print_function
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_32 as opc
JUMP_OPS = opc.JUMP_OPS

View File

@@ -6,8 +6,6 @@ This sets up opcodes Python's 3.3 and calls a generalized
scanner routine for Python 3.
"""
from __future__ import print_function
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_33 as opc
JUMP_OPS = opc.JUMP_OPS

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