Compare commits

...

182 Commits

Author SHA1 Message Date
rocky
1358d40aef Merge branch 'python-3.3-to-3.5' into python-2.4 2021-10-29 22:32:01 -04:00
rocky
c8c6f1a63d Merge hell 2021-10-29 22:29:15 -04:00
rocky
850500c7ad Merge branch 'master' into python-3.3-to-3.5 2021-10-29 22:25:36 -04:00
rocky
470d203b40 Merge branch 'master' of github.com:rocky/python-uncompyle6 2021-10-29 22:19:47 -04:00
rocky
4911d85237 Get ready for release 3.8.0 2021-10-29 22:17:17 -04:00
rocky
93a218a8b1 Get ready for release 3.8.0 2021-10-29 22:16:20 -04:00
rocky
9ec8918c1f Merge branch 'python-3.3-to-3.5' into python-2.4 2021-10-28 18:54:42 -04:00
rocky
08ed185608 Merge branch 'master' into python-3.3-to-3.5 2021-10-28 18:46:08 -04:00
rocky
32c4b84458 Better handling of bytecode errors 2021-10-28 18:37:54 -04:00
rocky
9cf345d446 Allow running test from 3.9 and 3.10
this does not mean we decompile either of those bytecode though.
2021-10-26 19:05:32 -04:00
rocky
c164df2795 Redo packaging. 2021-10-26 18:52:55 -04:00
rocky
3ad63071ac Admnistrivia: package info 2021-10-26 18:39:36 -04:00
rocky
25cd759dbe Packaging adminstrivia 2021-10-26 18:39:07 -04:00
rocky
000c060093 One more PYTHON_VERSION_TRIPLE conversion 2021-10-26 06:49:49 -04:00
rocky
39d79217ca Merge hell 2021-10-26 06:47:35 -04:00
rocky
5390e3b838 Merge hell 2021-10-26 06:42:23 -04:00
rocky
8aeb0aad8c Merge branch 'python-3.3-to-3.5' into python-2.4 2021-10-26 06:41:20 -04:00
rocky
d0ca7b0363 Loosen check to allow running from 2.4-3.10
We still only can *decompile* 2.4-3.8
2021-10-26 06:21:51 -04:00
rocky
a2e34ab75c Merge branch 'master' into python-3.3-to-3.5 2021-10-26 06:19:01 -04:00
rocky
5c2af69925 Loosen check to allow running from 2.4-3.10
We still only can *decompile* 2.4-3.8
2021-10-26 06:08:17 -04:00
rocky
8076c60eee Remove float2str 2021-10-26 04:43:08 -04:00
rocky
ea26084e6d Modernize and sync with decompyle3 better 2021-10-25 09:13:47 -04:00
rocky
1b4b6b334e Merge branch 'master' into python-3.3-to-3.5 2021-10-25 09:09:51 -04:00
rocky
482dbb5c82 Modernize and sync with decompyle3 better 2021-10-25 09:04:12 -04:00
rocky
fa203af665 Better messages when xdis not handling Python x.y 2021-10-24 23:22:41 -04:00
rocky
08e27a8b0f Merge branch 'python-3.3-to-3.5' into python-2.4 2021-10-24 01:54:39 -04:00
rocky
55ffaa1aff Merge branch 'master' into python-3.3-to-3.5 2021-10-24 01:52:52 -04:00
rocky
51ac72ba1f Sync with decompile3 2021-10-24 01:52:23 -04:00
rocky
d5bf7626af Fix bug in fragment parser 2021-10-24 01:32:41 -04:00
rocky
91fa73bf01 Try CI on 2.4 branch 2021-10-24 00:58:36 -04:00
rocky
9a1b77aff4 Merge branch 'python-3.3-to-3.5' into python-2.4 2021-10-24 00:49:32 -04:00
rocky
79d5790e3f Workflows CI adjusment 2021-10-23 16:06:02 -04:00
rocky
381a470d90 Merge branch 'python-3.3-to-3.5' into python-2.4 2021-10-23 16:02:28 -04:00
rocky
64b75625a9 Merge branch 'master' into python-3.3-to-3.5 2021-10-23 15:56:19 -04:00
rocky
7387e5094b More version tuple conversions 2021-10-23 15:54:14 -04:00
rocky
1bcd21a6f4 More version conversion bugs 2021-10-23 10:04:58 -04:00
rocky
536d45deb1 Another version bug 2021-10-23 10:01:53 -04:00
rocky
dce7e809e2 Merge branch 'python-3.3-to-3.5' into python-2.4 2021-10-23 09:52:40 -04:00
rocky
5ddbea73f4 Merge branch 'master' into python-3.3-to-3.5 2021-10-23 09:50:29 -04:00
rocky
71fe1e6c2c Fragment and other bugs
Part of the upgrade process
2021-10-23 09:47:30 -04:00
rocky
8a9a4ca6cc CircleCI testing 2021-10-23 09:12:45 -04:00
rocky
b8e9ce8a7a CircleCI testing 2021-10-23 09:08:11 -04:00
rocky
40a40b0bad Administrivia 2021-10-23 09:03:29 -04:00
rocky
528a2b0c22 Administrivia 2021-10-23 08:57:19 -04:00
rocky
d75bf1c32a Admnistrivia 2021-10-23 08:56:33 -04:00
rocky
cef3203601 merge hell 2021-10-23 08:46:05 -04:00
rocky
5b657ac7d8 Merge branch 'python-3.3-to-3.5' into python-2.4 2021-10-23 08:42:32 -04:00
rocky
1509bc4828 Administrivia 2021-10-23 08:35:00 -04:00
rocky
fad5089175 Administrivia 2021-10-23 08:33:39 -04:00
rocky
52262dc38a Merge hell 2021-10-23 08:27:47 -04:00
rocky
b61255535e Merge branch 'master' into python-3.3-to-3.5 2021-10-23 08:26:39 -04:00
rocky
e3369edaed DRY using version_info_to_str 2021-10-23 08:24:35 -04:00
rocky
ce58ed7434 CircleCI testing 2021-10-23 08:10:21 -04:00
rocky
01859ce820 Don not upgrade pip on older pythons 2021-10-23 07:53:50 -04:00
rocky
0a9dc57cc9 Try 3.6 CI testing 2021-10-21 18:53:44 -04:00
rocky
ada786e08c Administrivia 2021-10-21 16:38:12 -04:00
rocky
48bd832e7c Adminsitrivia 2021-10-21 16:36:46 -04:00
rocky
cfb5c442e2 Version twiddling 2021-10-21 16:33:42 -04:00
rocky
29a91fc015 Version twiddling 2021-10-21 16:33:09 -04:00
rocky
37f953c353 More version twiddling 2021-10-21 16:28:41 -04:00
rocky
4d84a723f4 Use right xdis branch 2021-10-21 16:22:57 -04:00
rocky
ddbfc168c5 CI testing 3.5, 3.6
Workflows doesn't go back before 3.5.
It is okay to use 3.6 in testing the 3.3-3.5 branch
2021-10-21 16:14:26 -04:00
rocky
a463220df2 Break out code for 3.3-3.5 versions 2021-10-21 16:12:39 -04:00
rocky
3e5f963c64 Merge branch 'master' of github.com:rocky/python-uncompyle6 2021-10-21 15:54:08 -04:00
R. Bernstein
c7ebdb344b Merge pull request #360 from rocky/3.10-adjust
Try Travis with new xdis
2021-10-21 15:52:40 -04:00
rocky
438c3b8d1d Add Windows and OSX CI 2021-10-21 15:47:15 -04:00
rocky
aa1d7abfdc Worflows CI testing 2021-10-21 15:42:22 -04:00
rocky
d3e30cf0e0 Update Python version in appveyor 2021-10-21 14:23:14 -04:00
rocky
36efc1fc8a Try 1st workflows CI 2021-10-21 14:18:56 -04:00
rocky
f00080317b Add pyston-2.3 in testing 2021-10-21 14:15:26 -04:00
rocky
162423895e Administrivia 2021-10-21 02:31:59 -04:00
rocky
f2750cff50 Correct pytest/test_grammar.py for new regime 2021-10-21 02:28:48 -04:00
R. Bernstein
256aaf0ef9 Update HOW-TO-REPORT-A-BUG.md 2021-10-21 02:23:03 -04:00
rocky
41314f95bb More Python version comparison adjustments 2021-10-19 16:30:56 -04:00
rocky
0645738775 Revise Python version comparisions
And set scanner.show_asm for 3.6
2021-10-19 05:54:54 -04:00
rocky
ceb7c659bd Python version comparison adjustments 2021-10-18 12:23:53 -04:00
rocky
8ac7a75372 Use tuples not floats in Python release comparison 2021-10-18 11:59:02 -04:00
rocky
15efaffe8d More Python version tuple comparison conversion 2021-10-16 11:41:22 -04:00
rocky
e8e006bb8c More Python version comparison conversions 2021-10-16 11:33:03 -04:00
rocky
c68b74a9c6 new dis - Python compisons involving tuples 2021-10-15 23:39:59 -04:00
rocky
f4bb0c44fe Try Travis with new xdis 2021-10-12 17:24:19 -04:00
R. Bernstein
8d81f4ab27 Update HOW-TO-REPORT-A-BUG.md 2021-09-16 06:23:25 -04:00
R. Bernstein
e0a56d4739 Update HOW-TO-REPORT-A-BUG.md 2021-09-03 07:41:38 -04:00
R. Bernstein
054364cb22 Update HOW-TO-REPORT-A-BUG.md 2021-09-03 07:32:53 -04:00
R. Bernstein
83c8313a8e Update HOW-TO-REPORT-A-BUG.md 2021-09-03 07:31:03 -04:00
rocky
184bda1b03 Work around broken modularity in python_parser 2021-08-27 02:13:09 -04:00
rocky
f374485e93 Another fragment fix for 3.8 2021-07-29 14:23:17 -04:00
rocky
fe7df87288 Sync 3.8 and Makefile changes with decompyle3
Makefile: pyston 2.3 tolerance
fragments: 3.8 comprehension adjustments
2021-07-29 13:16:03 -04:00
rocky
cfbb25df3d Fix some small bugs 2021-07-08 05:40:43 -04:00
rocky
d4174832a1 Black shouldn't format version.py 2021-06-23 11:46:31 -04:00
rocky
345de81d06 Administriva: add some config files
.editoryconfig: tell editors how to format this
setup.cfg: general project setup outside of Python-specific stuff
2021-06-23 02:09:32 -04:00
rocky
3684b38310 One more test 2021-06-15 22:50:36 -04:00
rocky
f472275196 Merge branch 'master' into python-2.4 2021-06-15 22:47:45 -04:00
rocky
2bca6753d3 Merge branch 'python-2.4' of github.com:rocky/python-uncompyle6 into python-2.4 2021-06-15 22:47:36 -04:00
R. Bernstein
dd8f22e698 Merge pull request #352 from rocky/lambda-bug
Fixes #360
2021-06-15 22:46:46 -04:00
rocky
96b1e435c2 Fixes #360 2021-06-15 22:42:55 -04:00
R. Bernstein
971757e997 Merge pull request #348 from IzeBerg/patch-1
'NoneType' object is not iterable with numproc > 1
2021-06-14 13:44:49 -04:00
Renat Iliev
2b154e0b88 'NoneType' object is not iterable with numproc > 1
main calls with source_paths=None, but it needs to be iterable
2021-06-14 19:50:18 +03:00
R. Bernstein
5d35a75743 Merge pull request #340 from timgates42/bugfix_typo_unnecessary
docs: fix simple typo, unecessary -> unnecessary
2020-12-31 03:22:09 -05:00
Tim Gates
fc38e23d8f docs: fix simple typo, unecessary -> unnecessary
There is a small typo in test/simple_source/looping/12_if_while_true_pass.py.

Should read `unnecessary` rather than `unecessary`.
2020-12-31 18:11:41 +11:00
rocky
5c16c73a6c Fix annotation transform for 3.7+
We were producing:

```
z: z: int = 5 on bytecode_3.7_run/02_var_annotate.pyc
```

because grammar went

     5. sstmt
        ann_assign (4) transformed by n_stmts: ('%|%[2]{attr}: %c\n', 0)
             0. ann_assign_init (3): ('%|%[2]{attr}: %c = %c\n', 0, 1)

The "ann_assign" added "z:". Instead we have now:

```
     5. sstmt
        ann_assign_init (3) transformed by n_stmts: ('%|%[2]{attr}: %c = %c\n', 0, 1)
```

Also, in the previous statement which appears in the listing (but is not
actually in the finaly tree) we had:

     4. sstmt
        assign (2): ('%|%c = %p\n', -1, (0, 200))
             0. expr
                L. L.   7        26  LOAD_CONST               5
             1. store

So we now preface the node type with "deleted", e.g.:

     4. deleted sstmt
        assign (2): ('%|%c = %p\n', -1, (0, 200))
             0. expr
                L. L.   7        26  LOAD_CONST               5
             1. store

to reduce confusion
2020-12-27 22:50:46 -05:00
R. Bernstein
3f665b939d Merge pull request #339 from bloerwald/parsers-fix_expr32_emitted_when_used_by_expr1024
parsers: parse2: fix: also emit expr32 if count perfectly divisible by 1024
2020-12-27 20:46:10 -05:00
Bernd Lörwald
f2f49104ea parsers: parse2: fix: also emit expr32 if count perfectly divisible by 1024
expr1024 requires expr32, but a build_count of 1024 would emit only the
expr1024 rule and rely on luck of it being emitted somewhere else.

Emit expr32 rule either if there is a expr32 use or a expr1024 use to avoid.
2020-12-28 01:42:42 +01:00
R. Bernstein
c2ee564e11 Update README.rst 2020-11-20 08:52:55 -05:00
rocky
f95db091bc Merge branch 'master' of github.com:rocky/python-uncompyle6 2020-11-03 18:09:40 -05:00
rocky
78dbc8ae0f Adjust ann_assign_init rule...
We've reduced spurious `sstmt` reductions. The `ann_assign_init` rule needs
to adjust accordingly.
2020-11-03 18:07:42 -05:00
rocky
a0cb9c5d6a merge hell 2020-10-31 11:37:58 -04:00
rocky
3ca66d0184 Merge branch 'master' into python-2.4 2020-10-31 11:37:53 -04:00
rocky
70b7e51df6 VERSION -> version 2020-10-31 11:25:06 -04:00
rocky
1164cd90dc Merge branch 'master' of github.com:rocky/python-uncompyle6 2020-09-10 17:19:36 -04:00
rocky
4bbdbe3894 Remove bogus async_with rule 2020-09-10 17:19:13 -04:00
rocky
28855767fb Get ready for release 3.7.4 2020-09-05 06:06:40 -04:00
rocky
316adff2d4 Merge branch 'python-2.4' of github.com:rocky/python-uncompyle6 into python-2.4 2020-09-05 06:02:58 -04:00
rocky
1a3bd3cabe Merge branch 'master' into python-2.4 2020-09-05 06:02:41 -04:00
rocky
9bc9532c24 Merge branch 'master' into python-2.4 2020-09-05 05:58:41 -04:00
rocky
732e3331b8 Get ready for release 3.7.4 2020-09-05 05:51:09 -04:00
rocky
8eb4d6a576 Fix bit rot in fragments.py
build_ast() added a code argument
n_dict(): was out of sync with corresponding pysource routine
pysource.py: small doc typo
2020-09-04 19:30:48 -04:00
rocky
b4db22d525 Narrow precedence for call statement 2020-09-03 04:35:59 -04:00
rocky
8879708da7 del_stmt -> delete to match Python AST better 2020-09-02 07:14:56 -04:00
rocky
67c45467c3 little sync with decompyle3
Add another forelsestmt (found only in a loop)
Add precidence on walrus operator
2020-09-01 17:10:33 -04:00
rocky
33bff4dc47 Small int thing and sync with decompyle3 2020-09-01 16:18:10 -04:00
rocky
71c17c4e53 Fragment api changed...
sync with pysource.
Simplify pysource a little
2020-08-23 19:27:52 -04:00
rocky
a5cfd81805 Include 3.8 excludes from decompyle3 2020-07-28 07:59:39 -04:00
rocky
64f19bf188 Use newest versions for 3.6-3.8 2020-07-26 10:53:17 -04:00
rocky
ff08f8a977 Administrivia 2020-07-25 15:42:54 -04:00
rocky
fae5525514 Administrivia 2020-07-25 15:42:31 -04:00
rocky
3ae4fda292 Administrivia 2020-07-25 15:40:27 -04:00
rocky
6cb6e45789 Get ready for release 3.7.3 2020-07-25 15:34:37 -04:00
rocky
730b739907 Merge branch 'master' into python-2.4 2020-07-25 13:38:24 -04:00
rocky
844144f90a Get ready for release 3.7.3 2020-07-25 13:21:37 -04:00
rocky
024a81c053 Fix condition sense in except_handler.py reduction 2020-07-23 11:03:43 -04:00
rocky
a0f93f7ad9 Comment last change 2020-07-22 06:44:34 -04:00
rocky
d3d67441d1 Add VERSION in a pydoc-friendly way 2020-07-22 06:38:47 -04:00
rocky
c105edff47 Merge branch 'master' into python-2.4 2020-07-21 18:52:31 -04:00
rocky
a215ee2f00 Use "co_consts" in docstring detection.
Note: this is an upheaval because we need to pass "code" or at least
"code.co_consts" to the docstring detection routine
2020-07-21 10:31:07 -04:00
rocky
f62512dd65 Clarify a warning message 2020-07-19 20:36:18 -04:00
rocky
0f80c38530 Better doc string detection
A bug in 2.7 test_descr.py revealed a problem with the way we were
detecting docstrings.

        __doc__ = DocDescr()

was getting confused with a docstring.

This program also reveals other bugs in 3.2+ but we'll deal with that
in another commit.
2020-07-19 20:31:50 -04:00
rocky
bd07de5172 Issue template tweaking again 2020-07-16 07:21:24 -04:00
rocky
f65aac7b97 Merge branch 'master' into python-2.4 2020-07-16 07:11:55 -04:00
rocky
e36945e2d9 Another tweak 2020-07-16 07:09:48 -04:00
rocky
25df0bdb76 Spelling typo 2020-07-16 07:04:25 -04:00
rocky
29ceb3fe05 Tweak again 2020-07-16 07:03:01 -04:00
rocky
fd7e04fa5d Small tweaks 2020-07-16 07:00:13 -04:00
rocky
5079164db2 Add reduce check for aug_assign1 2020-07-07 09:54:57 -04:00
rocky
68a145d050 Merge branch 'master' into python-2.4 2020-07-06 18:47:55 -04:00
rocky
815ae2c5cd for/else detection for older 2.x Pythons 2020-07-06 18:38:14 -04:00
rocky
54932d36fa Small tweaks...
add-test.py: wasn't handling optimize correctly. Handle python version better
parse27.py: dyslexia
01_for_else_try_else.py: bug in found in 1.4 anydbm.py which we will
address soon
2020-07-06 18:19:06 -04:00
rocky
fa1d7e4af4 Tweak. 2020-07-06 14:44:25 -04:00
rocky
bfd4b4cd68 Update bug-fixing expectations 2020-07-06 14:35:24 -04:00
rocky
c2e3ff0f43 Set bug-report expectations. 2020-07-06 14:34:16 -04:00
rocky
430fd2fa85 Update README.rst status on early Pythons 2020-07-06 12:02:59 -04:00
rocky
b49033d584 test_pwd.py now works 2020-07-06 10:26:35 -04:00
rocky
ef59b9c304 Forelse reduction checks on 2.6 2020-07-06 10:09:42 -04:00
rocky
d822017520 Add try/else reduction rule 2020-07-06 10:04:08 -04:00
rocky
084e183577 Add reduce check for 2.7 except_handler range 2020-07-05 22:18:07 -04:00
rocky
3dc6c31ae5 Fix bug in detecting 2.7 except-handler ranges 2020-07-05 22:11:37 -04:00
rocky
8de663ff52 A test unexplicably got fixed somewhere previously 2020-07-05 21:20:47 -04:00
rocky
7c14cf2d66 Add missing ref URLs 2020-07-05 09:55:43 -04:00
rocky
1d3fdbb4cd Update status 2020-07-05 00:59:16 -04:00
rocky
6e0b010cd3 Merge branch 'master' into python-2.4 2020-06-27 23:13:43 -04:00
rocky
b21e8b8b57 Get ready for release 3.7.2 2020-06-27 23:08:46 -04:00
rocky
4b2f26ca70 Merge branch 'master' into python-2.4 2020-06-27 11:45:16 -04:00
rocky
4007b8b702 Back off "or" check using instructions vs opcodes 2020-06-27 11:44:23 -04:00
rocky
e91fe14612 Merge branch 'master' into python-2.4 2020-06-27 11:34:20 -04:00
rocky
598b58796d Back off buggy "or" check 2020-06-27 11:33:46 -04:00
rocky
f7bad891a4 Last commit fixed test_pep352.py 2020-06-27 11:22:53 -04:00
rocky
8ce921c5b7 Last commit fixed test_pep352 test 2020-06-27 11:21:34 -04:00
rocky
5d609ae1aa Merge branch 'master' into python-2.4 2020-06-27 11:17:21 -04:00
rocky
357f28dd89 Add "comp_if_not" for 2.6- 2020-06-27 11:16:47 -04:00
rocky
7042d00203 Merge branch 'master' into python-2.4 2020-06-27 09:17:39 -04:00
rocky
5cc572147a Handle more ifelse reduction rules patterns 2020-06-27 09:10:48 -04:00
rocky
6c8b3bfbe9 Merge branch 'master' into python-2.4 2020-06-26 08:47:02 -04:00
rocky
11be90758f Workaround bug detecting MAKE_FUNCTION docstrings 2020-06-26 07:17:31 -04:00
rocky
e3720515ae Adjust for newer xdis 2020-06-21 20:20:25 -04:00
rocky
38cd854b81 Merge branch 'master' into python-2.4 2020-06-17 10:16:34 -04:00
rocky
7dec354a47 Merge branch 'master' of github.com:rocky/python-uncompyle6 2020-06-17 10:15:07 -04:00
rocky
2a8daca25d Fix broken __doc__ transform yet again...
Hopefully by using first_child() we have something more robust now.
2020-06-17 10:12:56 -04:00
rocky
33be603e3d Merge branch 'master' into python-2.4 2020-06-17 05:42:50 -04:00
rocky
7799819cad Add another 3.7 stdlib exclusion test 2020-06-17 05:42:10 -04:00
rocky
c6c50b5dfb Disable compile-farm 3.8.3 checking 2020-06-17 05:29:04 -04:00
rocky
d357898bbf Towards fixing a 3.8 try except-as bug 2020-06-15 06:03:28 -04:00
rocky
c4e7ddf90a Administrivia 2020-06-12 21:29:32 -04:00
144 changed files with 1673 additions and 948 deletions

View File

@@ -1,4 +1,7 @@
version: 2
filters:
branches:
only: python-2.4
jobs:
build:
parallelism: 1
@@ -32,7 +35,12 @@ jobs:
- v2-dependencies-
- run:
command: sudo easy_install xdis spark-parser && sudo pip install -e . && sudo pip install -r requirements-dev.txt
command: | # Use pip to install dependengcies
sudo easy_install click==7.1.2
# Until next release use github xdis
sudo pip install git+git://github.com/rocky/python-xdis.git@python-2.4-to-2.7#egg=xdis
sudo pip install -e .
sudo pip install -r requirements-dev.txt
# Save dependency cache
- save_cache:

28
.editorconfig Normal file
View File

@@ -0,0 +1,28 @@
# THis is an EditorConfig file
# https://EditorConfig.org
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
indent_size = 4
insert_final_newline = true
[*.yml]
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
[*.py]
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
# Tab indentation (no size specified)
[Makefile]
indent_style = tab

View File

@@ -4,28 +4,40 @@ about: Tell us about uncompyle6 bugs
---
<!-- __Note:__ Have you read https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md ?
<!-- __Note:__ Bugs are not for asking questions about a problem you
are trying to solve that involve the use of uncompyle6 along the way,
although I may be more tolerent of this if you sponsor the project.
Also, the unless you are a sponsor of the project, it may take a
while, maybe a week or so, before the bug report is noticed, let alone
acted upon.
To set expectations, some legitimate bugs can take years
to fix, but they eventually do get fixed. Funding the project was
added to address the problem that there are lots of people seeking
help and reporting bugs, but few people who are willing or capable of
providing help or fixing bugs.
Finally, have you read https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md
?
Please remove any of the optional sections if they are not applicable.
Prerequisites
Prerequisites/Caveats
* Make sure the bytecode you have can be disassembled with a
disassembler and produces valid results.
* Don't put bytecode and corresponding source code on any service that
requires registration to download.
* When you open a bug report there is no privacy. If the legitimacy of
the activity is deemed suspicous, I may flag it as suspicious,
* When you open a bug report there is no privacy. If you need privacy, then
contact me by email and explain who you are and the need for privacy.
But be mindful that you may be asked to sponsor the project for the
personal and private help that you are requesting.
* If the legitimacy of the activity is deemed suspicous, I may flag it as suspicious,
making the issue even more easy to detect.
Bug reports that violate a prerequisite may be discarded.
Note that there are way more bug-fix requestors than there are bug
fixers. If you want you need more immediate, confidential or urgent
assistance
http://www.crazy-compilers.com/decompyle/ offers a byte-code
decompiler service for versions of Python up to 2.6.
Bug reports that violate the above may be discarded.
-->

30
.github/workflows/osx.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: uncompyle6 (osx)
on:
push:
branches: [ python-2.4 ]
pull_request:
branches: [ python-2.4 ]
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
os: [macOS]
python-version: [2.7]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
# Until the next xdis release
pip install git+git://github.com/rocky/python-xdis.git@python-2.4-to-2.7#egg=xdis
pip install -e .
pip install -r requirements-dev.txt
- name: Test uncompyle6
run: |
make check

30
.github/workflows/ubuntu.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: uncompyle6 (ubuntu)
on:
push:
branches: [ python-2.4 ]
pull_request:
branches: [ python-2.4 ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [2.7]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
# Until the next xdis release
pip install git+git://github.com/rocky/python-xdis.git@python-2.4-to-2.7#egg=xdis
pip install -e .
pip install -r requirements-dev.txt
- name: Test uncompyle6
run: |
make check

30
.github/workflows/windows.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: uncompyle6 (windows)
on:
push:
branches: [ python-2.4 ]
pull_request:
branches: [ python-2.4 ]
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
os: [windows]
python-version: [2.7]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
# Until the next xdis release
pip install git+git://github.com/rocky/python-xdis.git@python-2.4-to-2.7#egg=xdis
pip install -e .
pip install -r requirements-dev.txt
- name: Test uncompyle6
run: |
make check

View File

@@ -4,6 +4,8 @@ python:
- 2.7 # this is a cheat here because travis doesn't do 2.4-2.6
install:
# Remove the next line when xdis 6.0.0 is released
# - pip install git://github.com/rocky/python-xdis.git#egg=xdis
- pip install -e .
- pip install -r requirements-dev.txt

View File

@@ -20,41 +20,14 @@
This decompiler is a constant work in progress: Python keeps
changing, and so does its code generation.
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.
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.
But at any given time, there are a number of valid Python bytecode
files that I know of that will cause problems. See, for example, the
list in
But at any given time, there are a number of valid Python bytecode files that I know of that will cause problems. See, for example, the list in
[`test/stdlib/runtests.sh`](https://github.com/rocky/python-uncompyle6/blob/master/test/stdlib/runtests.sh).
But I understand: you would the bugs _you_ encounter addressed before
all the other known bugs.
There are far more bug reporters than there are bug fixers.
From my standpoint, the good thing about the bugs listed in
`runtests.sh` is that each test case is small and isolated to a single
kind of problem. And I'll tend to fix easier, more isolated cases than
generic "something's wrong" kinds of bugs where I'd have to do a bit
of work to figure out what's up, if not use some sort of mind reading,
make some guesses, and perform some experiments to see if the guesses
are correct. I can't read minds, nor am I into guessing games; I'd
rather devote the effort spent instead towards fixing bugs that are
precisely defined.
And it often turns out that by just fixing the well-defined and
prescribed cases, the ill-defined amorphous cases as well will get
handled as well.
In sum, you may need to do some work to have the bug you have found
handled before the hundreds of other bugs, and other things I could be
doing.
No one is getting paid to work to work on this project, let alone the
bugs you may have an interest in. If you require decompiling bytecode
immediately, consider using a decompilation service, listed further
down in this document.
Unless you are a sponsor of this project, it may take a while, maybe a week or so, before the bug report is noticed, let alone acted upon. Things eventually get fixed, but it may take years.
# Is it really a bug?
@@ -62,7 +35,7 @@ down in this document.
## 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
code or release candidates. See README.rst for suggestions for how to remove some kinds of
obfuscation.
Checking if bytecode is valid is pretty simple: disassemble the code.
@@ -144,8 +117,7 @@ if False:
Python will eliminate the entire "if" statement.
So just because the text isn't the same, does not
necessarily mean there's a bug.
So just because the text isn't the same, this does not necessarily mean there's a bug.
# What to send (minimum requirements)
@@ -176,30 +148,18 @@ provide the input 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.
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.
### But I don't *have* the source code and am incapable of figuring 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.)
If this is too difficult, or too time consuming, or not of interest to you, then you might consider [sponsoring](https://github.com/sponsors/rocky) the project. [Crazy
Compilers](http://www.crazy-compilers.com/decompyle/) offers a byte-code decompiler service for versions of Python up to 2.6. (If there are others around let me know and I'll list them here.)
# Narrowing the problem
I don't need or want the entire source code base for 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.
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
@@ -217,10 +177,7 @@ likely the problem will be fixed and fixed sooner.
# Karma
I realize that following the instructions given herein puts a bit of
burden on the bug reporter. In my opinion, this is justified as
attempts to balance somewhat the burden and effort needed to fix the
bug and the attempts to balance number of would-be bug reporters with
the number of bug fixers. Better bug reporters are more likely to move
burden on the bug reporter. This is justified as attempts to balance somewhat the burden and effort needed to fix the bug and the attempts to balance number of would-be bug reporters with the number of bug fixers. Better bug reporters are more likely to move
in the category of bug fixers.
The barrier to reporting a big is pretty small: all you really need is
@@ -228,22 +185,14 @@ a github account, and the ability to type something after clicking
some buttons. So the reality is that many people just don't bother to
read these instructions, let alone follow it to any simulacrum.
And the reality is also that bugs sometimes get fixed even though
these instructions are not followed.
That said, bugs sometimes get fixed even though these instructions are not followed.
So one factors I may take into consideration is the bug reporter's karma.
I may take into consideration is the bug reporter's karma.
* Have you demonstrably contributed to open source? I may look at your github profile to see what contributions you have made, how popular those contributions are, or how popular you are.
* How appreciative are you? Have you starred this project that you are seeking help from? Have you starred _any_ github project? And the above two kind of feed into ...
* Attitude. Some people feel that they are doing me and the world a great favor by just pointing out that there is a problem whose solution would greatly benefit them. (This might account partially those that have this attitude often don't read or follow instructions such as those given here.)
* Have you demonstrably contributed to open source? I may look at your
github profile to see what contributions you have made, how popular
those contributions are, or how popular you are.
* How appreciative are you? Have you starred this project that you are
seeking help from? Have you starred _any_ github project? And the above
two kind of feed into ...
* Attitude. Some people feel that they are doing me and the world a
great favor by just pointing out that there is a problem whose solution
would greatly benefit them. Perhaps this is why they feel that
instructions are not to be followed by them, nor any need for
showing evidence gratitude when help is offered them.
# Confidentiality of Bug Reports
@@ -255,6 +204,8 @@ remains would not be an issue.
However feel free to remove any comments, and modify variable names
or constants in the source code.
If there is some legitimate reason to keep confidentiality, you can contact me by email to explain the extenuating circumstances. However I tend to discard without reading anonymous email.
# Ethics
I do not condone using this program for unethical or illegal purposes.

43
NEWS.md
View File

@@ -1,3 +1,46 @@
3.8.0: 2020-10-29
=================
* Better handling of invalid bytecode magic
* Support running from 3.9 and 3.10 although we do not support those bytecodes
* Redo version comparisons using tuples instead of floats. This is needed for Python 3.10
* Split out into 3 branches so that the master branch can assume Python 3.6+ conventions, especially type annotations
* Source Fragment fixes
* Lambda-bug fixes #360
* Bug fixes
3.7.4: 2020-8-05
================
* Fragment parsing was borked. This means deparsing in trepan2/trepan3k was broken
* 3.7+: narrow precedence for call tatement
* del_stmt -> delete to better match Python AST
* 3.8+ Add another `forelsestmt` (found only in a loop)
* 3.8+ Add precedence on walrus operator
* More files blackened
* bump min xdis version
3.7.3: 2020-7-25
================
Mostly small miscellaneous bug fixes
* `__doc__ = DocDescr()` from `test_descr.py` was getting confused as a docstring.
* detect 2.7 exchandler range better
* Add for .. else reduction checks on 2.6 and before
* Add reduce check for 2.7 augmented assign
* Add VERSION in a pydoc-friendly way
3.7.2: 2020-6-27
================
* Use newer xdis
* Docstrings (again) which were broken again on earlier Python
* Fix 2.6 and 2.7 decompilation bug in handling "list if" comprehensions
3.7.1: 2020-6-12 Fleetwood66
====================================================

View File

@@ -68,10 +68,9 @@ are syntactically correct by running the Python interpreter for that
bytecode version. Finally, in cases where the program has a test for
itself, we can run the check on the decompiled code.
We are serious about testing, and use automated processes to find
bugs. In the issue trackers for other decompilers, you will find a
number of bugs we've found along the way. Very few to none of them are
fixed in the other decompilers.
We use an 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
------------
@@ -171,15 +170,11 @@ All of the Python decompilers that I have looked at have problems
decompiling Python's control flow. In some cases we can detect an
erroneous decompilation and report that.
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)
Python support is pretty good for Python 2
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.6, and 2.0.
On the lower end of Python versions, decompilation seems pretty good although
we don't have any automated testing in place for Python's distributed tests.
Also, we don't have a Python interpreter for versions 1.6, and 2.0.
In the Python 3 series, Python support is is strongest around 3.4 or
3.3 and drops off as you move further away from those versions. Python
@@ -194,7 +189,7 @@ added. So in sum handling control flow by ad hoc means as is currently
done is worse.
Between Python 3.5, 3.6, 3.7 there have been major changes to the
:code:`MAKE_FUNCTION` and :code:`CALL_FUNCTION` instructions. Python
:code:`MAKE_FUNCTION` and :code:`CALL_FUNCTION` instructions.
Python 3.8 removes :code:`SETUP_LOOP`, :code:`SETUP_EXCEPT`,
:code:`BREAK_LOOP`, and :code:`CONTINUE_LOOP`, instructions which may
@@ -214,17 +209,43 @@ which use their own magic and encrypt bytecode. With the exception of
the Dropbox's old Python 2.5 interpreter this kind of thing is not
handled.
We also don't handle PJOrion_ obfuscated code. For that try: PJOrion
Deobfuscator_ to unscramble the bytecode to get valid bytecode before
trying this tool. This program can't decompile Microsoft Windows EXE
files created by Py2EXE_, although we can probably decompile the code
after you extract the bytecode properly. For situations like this, you
might want to consider a decompilation service like `Crazy Compilers
<http://www.crazy-compilers.com/decompyle/>`_. Handling
pathologically long lists of expressions or statements is slow.
We also don't handle PJOrion_ or otherwise obfuscated code. For
PJOrion try: PJOrion Deobfuscator_ to unscramble the bytecode to get
valid bytecode before trying this tool. This program can't decompile
Microsoft Windows EXE files created by Py2EXE_, although we can
probably decompile the code after you extract the bytecode
properly. Handling pathologically long lists of expressions or
statements is slow. We don't handle Cython_ or MicroPython which don't
use bytecode.
There are numerous bugs in decompilation. And that's true for every
other CPython decompiler I have encountered, even the ones that
claimed to be "perfect" on some particular version like 2.4.
There is lots to do, so please dig in and help.
As Python progresses decompilation also gets harder because the
compilation is more sophisticated and the language itself is more
sophisticated. I suspect that attempts there will be fewer ad-hoc
attempts like unpyc37_ (which is based on a 3.3 decompiler) simply
because it is harder to do so. The good news, at least from my
standpoint, is that I think I understand what's needed to address the
problems in a more robust way. But right now until such time as
project is better funded, I do not intend to make any serious effort
to support Python versions 3.8 or 3.9, including bugs that might come
in. I imagine at some point I may be interested in it.
You can easily find bugs by running the tests against the standard
test suite that Python uses to check itself. At any given time, there are
dozens of known problems that are pretty well isolated and that could
be solved if one were to put in the time to do so. The problem is that
there aren't that many people who have been working on bug fixing.
Some of the bugs in 3.7 and 3.8 are simply a matter of back-porting
the fixes in decompyle3.
You may run across a bug, that you want to report. Please do so. But
be aware that it might not get my attention for a while. If you
sponsor or support the project in some way, I'll prioritize your
issues above the queue of other things I might be doing instead.
See Also
--------
@@ -241,6 +262,7 @@ See Also
* https://github.com/zrax/pycdc : The README for this C++ code says it aims to support all versions of Python. It is best for Python versions around 2.7 and 3.3 when the code was initially developed. Accuracy for current versions of Python3 and early versions of Python is lacking. Without major effort, it is unlikely it can be made to support current Python 3. See its `issue tracker <https://github.com/zrax/pycdc/issues>`_ for details. Currently lightly maintained.
.. _Cython: https://en.wikipedia.org/wiki/Cython
.. _trepan: https://pypi.python.org/pypi/trepan2g
.. _compiler: https://pypi.python.org/pypi/spark_parser
.. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2018, 2020 Rocky Bernstein <rocky@gnu.org>
# Copyright (C) 2018, 2020-2021 Rocky Bernstein <rocky@gnu.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -33,65 +33,76 @@
# 3.4 | pip | 19.1.1 |
# Things that change more often go here.
copyright = """
Copyright (C) 2015-2020 Rocky Bernstein <rb@dustyfeet.com>.
copyright = """
Copyright (C) 2015-2021 Rocky Bernstein <rb@dustyfeet.com>.
"""
classifiers = ["Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2.4",
"Programming Language :: Python :: 2.5",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.0",
"Programming Language :: Python :: 3.1",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Topic :: Software Development :: Debuggers",
"Topic :: Software Development :: Libraries :: Python Modules",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.4",
"Programming Language :: Python :: 2.5",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.0",
"Programming Language :: Python :: 3.1",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Software Development :: Debuggers",
"Topic :: Software Development :: Libraries :: Python Modules",
]
# The rest in alphabetic order
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
author_email = "rb@dustyfeet.com"
entry_points = {
author = "Rocky Bernstein, Hartmut Goebel, John Aycock, and others"
author_email = "rb@dustyfeet.com"
entry_points = {
"console_scripts": [
"uncompyle6=uncompyle6.bin.uncompile:main_bin",
"pydisassemble=uncompyle6.bin.pydisassemble:main",
]}
ftp_url = None
install_requires = ["spark-parser >= 1.8.9, < 1.9.0",
"xdis >= 4.6.1, < 4.8.0"]
]
}
ftp_url = None
install_requires = ["spark-parser >= 1.8.9, < 1.9.0", "xdis >= 6.0.2, < 6.1.0"]
license = "GPL3"
mailing_list = "python-debugger@googlegroups.com"
modname = "uncompyle6"
py_modules = None
short_desc = "Python cross-version byte-code decompiler"
web = "https://github.com/rocky/python-uncompyle6/"
license = "GPL3"
mailing_list = "python-debugger@googlegroups.com"
modname = "uncompyle6"
py_modules = None
short_desc = "Python cross-version byte-code decompiler"
web = "https://github.com/rocky/python-uncompyle6/"
# tracebacks in zip files are funky and not debuggable
zip_safe = True
import os.path
def get_srcdir():
filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__)))
return os.path.realpath(filename)
srcdir = get_srcdir()
def read(*rnames):
return open(os.path.join(srcdir, *rnames)).read()
# Get info from files; set: long_description and VERSION
long_description = ( read("README.rst") + "\n" )
# Get info from files; set: long_description and __version__
long_description = read("README.rst") + "\n"
exec(read("uncompyle6/version.py"))

View File

@@ -6,7 +6,7 @@ owd=$(pwd)
trap finish EXIT
cd $(dirname ${BASH_SOURCE[0]})
if ! source ./pyenv-older-versions ; then
if ! source ./pyenv-2.4-2.7-versions ; then
exit $?
fi
if ! source ./setup-python-2.4.sh ; then

View File

@@ -8,7 +8,7 @@ owd=$(pwd)
trap finish EXIT
cd $(dirname ${BASH_SOURCE[0]})
if ! source ./pyenv-newer-versions ; then
if ! source ./pyenv-newest-versions ; then
exit $?
fi
if ! source ./setup-master.sh ; then

View File

@@ -2,17 +2,17 @@
**Table of Contents**
- [Get latest sources:](#get-latest-sources)
- [Change version in uncompyle6/version.py](#change-version-in-uncompyle6versionpy)
- [Change version in uncompyle6/version.py:](#change-version-in-uncompyle6versionpy)
- [Update ChangeLog:](#update-changelog)
- [Update NEWS from ChangeLog:](#update-news-from-changelog)
- [Update NEWS.md from ChangeLog:](#update-newsmd-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)
- [Check against older versions](#check-against-older-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)
- [Check package on github](#check-package-on-github)
- [Release on Github](#release-on-github)
- [Get onto PyPI](#get-onto-pypi)
- [Update tags:](#update-tags)
<!-- markdown-toc end -->
# Get latest sources:
@@ -39,7 +39,7 @@
# Make sure pyenv is running and check newer versions
$ pyenv local && source admin-tools/check-newer-versions.sh
$ 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.
@@ -50,37 +50,51 @@
# Check against older versions
$ source admin-tools/check-older-versions.sh
$ admin-tools/check-older-versions.sh
# Make packages and tag
$ . ./admin-tools/make-dist-older.sh
$ pyenv local 3.8.3
$ pyenv local 3.8.5
$ twine check dist/uncompyle6-$VERSION*
$ git tag release-python-2.4-$VERSION
$ . ./admin-tools/make-dist-newer.sh
$ ./admin-tools/make-dist-newer.sh
$ twine check dist/uncompyle6-$VERSION*
# Upload single package and look at Rst Formating
# Check package on github
$ twine check dist/uncompyle6-${VERSION}*
$ twine upload dist/uncompyle6-${VERSION}-py3.3.egg
$ [[ ! -d /tmp/gittest ]] && mkdir /tmp/gittest; pushd /tmp/gittest
$ pyenv local 3.8.3
$ pip install -e git://github.com/rocky/python-uncompyle6.git#egg=uncompyle6
$ uncompyle6 --help
$ pip uninstall uncompyle6
$ popd
# Upload rest of versions
$ twine upload dist/uncompyle6-${VERSION}*
# Release on Github
Goto https://github.com/rocky/python-uncompyle6/releases
# Push tags:
Now check the *tagged* release. (Checking the untagged release was previously done).
Todo: turn this into a script in `admin-tools`
$ pushd /tmp/gittest
$ pip install -e git://github.com/rocky/python-uncompyle6.git@$VERSION#egg=uncompyle6
$ uncompyle6 --help
$ pip uninstall uncompyle6
$ popd
# Get onto PyPI
$ twine upload dist/uncompyle6-${VERSION}*
# Update tags:
$ git push --tags
$ git pull --tags
# Check on a VM
# Move dist files to uploaded
$ cd /virtual/vagrant/virtual/vagrant/ubuntu-zesty
$ vagrant up
$ vagrant ssh
$ pyenv local 3.5.2
$ pip install --upgrade uncompyle6
$ exit
$ vagrant halt
$ mv -v dist/uncompyle6-${VERSION}* dist/uploaded

View File

@@ -9,7 +9,7 @@ owd=$(pwd)
trap finish EXIT
cd $(dirname ${BASH_SOURCE[0]})
if ! source ./pyenv-older-versions ; then
if ! source ./pyenv-2.4-2.7-versions ; then
exit $?
fi
if ! source ./setup-python-2.4.sh ; then
@@ -18,7 +18,7 @@ fi
cd ..
source $PACKAGE/version.py
echo $VERSION
echo $__version__
for pyversion in $PYVERSIONS; do
if ! pyenv local $pyversion ; then
@@ -29,11 +29,15 @@ for pyversion in $PYVERSIONS; do
python setup.py bdist_egg
done
pyenv local 2.7.18
python setup.py bdist_wheel
mv -v dist/${PACKAGE}-$__version__-py2{.py3,}-none-any.whl
# 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
tarball=dist/${PACKAGE}-${__version_}_-tar.gz
if [[ -f $tarball ]]; then
rm -v dist/${PACKAGE}-$VERSION-tar.gz
rm -v dist/${PACKAGE}-${__version__}-tar.gz
fi

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-3.3-3.5-versions ; then
exit $?
fi
if ! source ./setup-python-3.3.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

View File

@@ -10,7 +10,7 @@ cd $(dirname ${BASH_SOURCE[0]})
owd=$(pwd)
trap finish EXIT
if ! source ./pyenv-newer-versions ; then
if ! source ./pyenv-newest-versions ; then
exit $?
fi
if ! source ./setup-master.sh ; then
@@ -19,7 +19,7 @@ fi
cd ..
source $PACKAGE/version.py
echo $VERSION
echo $__version__
for pyversion in $PYVERSIONS; do
if ! pyenv local $pyversion ; then
@@ -32,7 +32,7 @@ for pyversion in $PYVERSIONS; do
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
mv -v dist/${PACKAGE}-$__version__-{py2.py3,py$first_two}-none-any.whl
done
python ./setup.py sdist

View File

@@ -0,0 +1,9 @@
# -*- shell-script -*-
# Sets PYVERSIONS to be pyenv versions that
# we can use in the python-2.4-to-2.7 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 2.6.9 2.7.18'

View File

@@ -6,4 +6,4 @@ 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'
export PYVERSIONS='3.1.5 3.2.6'

View File

@@ -0,0 +1,8 @@
# -*- shell-script -*-
# Sets PYVERSIONS to be pyenv versions that
# we can use in the python-3.3-to-3.5 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.3.7 3.4.10 3.5.10 '

View File

@@ -5,4 +5,4 @@ if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
echo "This script should be *sourced* rather than run directly through bash"
exit 1
fi
export PYVERSIONS='3.5.9 3.6.10 2.6.9 3.3.7 2.7.18 3.2.6 3.1.5 3.4.10 3.7.7 3.8.3'
export PYVERSIONS='3.6.15 3.7.12 pyston-2.3 3.8.11 3.9.7 3.10.0'

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.7.11 3.8.12 3.9.7 3.10.0'

View File

@@ -1,5 +1,5 @@
#!/bin/bash
PYTHON_VERSION=3.7.7
PYTHON_VERSION=3.7.12
# FIXME put some of the below in a common routine
function finish {
@@ -20,4 +20,4 @@ cd $fulldir/..
(cd ../python-xdis && git checkout master && pyenv local $PYTHON_VERSION) && git pull && \
git checkout master && pyenv local $PYTHON_VERSION && git pull
cd $owd
rm -v */.python-version || true
rm -v */.python-version >/dev/null 2>&1 || true

View File

@@ -11,7 +11,7 @@ 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 && \
(cd ../python-xdis && . ./admin-tools/setup-python-2.4.sh) && \
git checkout python-2.4 && pyenv local $PYTHON_VERSION && git pull
cd $owd
rm -v */.python-version || true

View File

@@ -0,0 +1,15 @@
#!/bin/bash
PYTHON_VERSION=3.3.7
pyenv local $PYTHON_VERSION
owd=$(pwd)
bs=${BASH_SOURCE[0]}
mydir=$(dirname $bs)
fulldir=$(readlink -f $mydir)
cd $fulldir/..
(cd ../python-xdis && ./admin-tools/setup-python-3.3.sh)
cd $owd
rm -v */.python-version || true
git checkout python-3.3-to-3.5 && git pull && pyenv local $PYTHON_VERSION

View File

@@ -1,79 +0,0 @@
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.
- "%PYTHON%\\python.exe -m pip install --disable-pip-version-check --user --upgrade pip"
# Install the build dependencies of the project. If some dependencies contain
# compiled extensions and are not provided as pre-built wheel packages,
# pip will build them from source using the MSVC compiler matching the
# target Python version and architecture
- "%CMD_IN_ENV% pip install git+git://github.com/rocky/python-uncompyle6.git#egg=uncompyle6-3.6.6"
- "%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 --syntax-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
#

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python
from uncompyle6 import PYTHON_VERSION, IS_PYPY
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY, version_tuple_to_str
from uncompyle6.scanner import get_scanner
def bug(state, slotstate):
if state:
@@ -21,8 +21,8 @@ def bug_loop(disassemble, tb=None):
def test_if_in_for():
code = bug.func_code
scan = get_scanner(PYTHON_VERSION)
if 2.7 <= PYTHON_VERSION <= 3.0 and not IS_PYPY:
scan = get_scanner(PYTHON_VERSION_TRIPLE)
if (2, 7) <= PYTHON_VERSION_TRIPLE < (3, 1) and not IS_PYPY:
scan.build_instructions(code)
fjt = scan.find_jump_targets(False)
@@ -51,7 +51,7 @@ def test_if_in_for():
# previous bug was not mistaking while-loop for if-then
{'start': 48, 'end': 67, 'type': 'while-loop'}]
elif 3.2 < PYTHON_VERSION <= 3.4:
elif (3, 2) < PYTHON_VERSION_TRIPLE <= (3, 4):
scan.build_instructions(code)
fjt = scan.find_jump_targets(False)
assert {69: [66], 63: [18]} == fjt
@@ -62,6 +62,6 @@ def test_if_in_for():
{'end': 59, 'type': 'for-loop', 'start': 31},
{'end': 63, 'type': 'for-else', 'start': 62}]
else:
print("FIXME: should fix for %s" % PYTHON_VERSION)
print("FIXME: should fix for %s" % version_tuple_to_str())
assert True
return

View File

@@ -1,7 +1,7 @@
import re
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY # , PYTHON_VERSION
from uncompyle6.parser import get_python_parser, python_parser
from uncompyle6.scanner import get_scanner
from xdis.version_info import PYTHON_VERSION_TRIPLE, PYTHON3, IS_PYPY
def test_grammar():
@@ -16,19 +16,19 @@ def test_grammar():
p.dump_grammar(),
)
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
p = get_python_parser(PYTHON_VERSION_TRIPLE, is_pypy=IS_PYPY)
(lhs, rhs, tokens, right_recursive, dup_rhs) = p.check_sets()
# We have custom rules that create the below
expect_lhs = set(["pos_arg"])
if PYTHON_VERSION < 3.8:
if PYTHON_VERSION < 3.7:
if PYTHON_VERSION_TRIPLE < (3, 8):
if PYTHON_VERSION_TRIPLE < (3, 7):
expect_lhs.add("attribute")
expect_lhs.add("get_iter")
if PYTHON_VERSION > 3.7 or PYTHON_VERSION < 3.0:
if PYTHON_VERSION_TRIPLE >= (3, 8) or PYTHON_VERSION_TRIPLE < (3, 0):
expect_lhs.add("stmts_opt")
else:
expect_lhs.add("async_with_as_stmt")
@@ -38,10 +38,10 @@ def test_grammar():
expect_right_recursive = set([("designList", ("store", "DUP_TOP", "designList"))])
if PYTHON_VERSION <= 3.6:
if PYTHON_VERSION_TRIPLE[:2] <= (3, 6):
unused_rhs.add("call")
if PYTHON_VERSION > 2.6:
if PYTHON_VERSION_TRIPLE >= (2, 7):
expect_lhs.add("kvlist")
expect_lhs.add("kv3")
unused_rhs.add("dict")
@@ -49,7 +49,7 @@ def test_grammar():
# NOTE: this may disappear
expect_lhs.add("except_handler_else")
if PYTHON_VERSION < 3.7 and PYTHON_VERSION != 2.7:
if PYTHON_VERSION_TRIPLE < (3, 7) and PYTHON_VERSION_TRIPLE[:2] != (2, 7):
# NOTE: this may disappear
expect_lhs.add("except_handler_else")
@@ -63,8 +63,8 @@ def test_grammar():
""".split()
)
)
if PYTHON_VERSION >= 3.0:
if PYTHON_VERSION < 3.7:
if PYTHON_VERSION_TRIPLE >= (3, 0):
if PYTHON_VERSION_TRIPLE < (3, 7):
expect_lhs.add("annotate_arg")
expect_lhs.add("annotate_tuple")
unused_rhs.add("mkfunc_annotate")
@@ -72,7 +72,7 @@ def test_grammar():
unused_rhs.add("dict_comp")
unused_rhs.add("classdefdeco1")
unused_rhs.add("tryelsestmtl")
if PYTHON_VERSION >= 3.5:
if PYTHON_VERSION_TRIPLE >= (3, 5):
expect_right_recursive.add(
(("l_stmts", ("lastl_stmt", "come_froms", "l_stmts")))
)
@@ -83,7 +83,7 @@ def test_grammar():
expect_lhs.add("kwarg")
# FIXME
if PYTHON_VERSION < 3.8:
if PYTHON_VERSION_TRIPLE < (3, 8):
assert expect_lhs == set(lhs)
assert unused_rhs == set(rhs)
@@ -106,7 +106,7 @@ def test_grammar():
print(k, reduced_dup_rhs[k])
# assert not reduced_dup_rhs, reduced_dup_rhs
s = get_scanner(PYTHON_VERSION, IS_PYPY)
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
ignore_set = set(
"""
JUMP_BACK CONTINUE
@@ -119,12 +119,13 @@ def test_grammar():
RETURN_END_IF RETURN_END_IF_LAMBDA RETURN_VALUE_LAMBDA RETURN_LAST
""".split()
)
if 2.6 <= PYTHON_VERSION <= 2.7:
if (2, 6) <= PYTHON_VERSION_TRIPLE <= (2, 7):
opcode_set = set(s.opc.opname).union(ignore_set)
if PYTHON_VERSION == 2.6:
if PYTHON_VERSION_TRIPLE[:2] == (2, 6):
opcode_set.add("THEN")
check_tokens(tokens, opcode_set)
elif PYTHON_VERSION == 3.4:
elif PYTHON_VERSION_TRIPLE[:2] == (3, 4):
ignore_set.add("LOAD_CLASSNAME")
ignore_set.add("STORE_LOCALS")
opcode_set = set(s.opc.opname).union(ignore_set)
@@ -135,7 +136,7 @@ def test_dup_rule():
import inspect
python_parser(
PYTHON_VERSION,
PYTHON_VERSION_TRIPLE,
inspect.currentframe().f_code,
is_pypy=IS_PYPY,
parser_debug={

View File

@@ -1,6 +1,7 @@
from uncompyle6 import PYTHON_VERSION, code_deparse
from uncompyle6 import code_deparse
from xdis.version_info import PYTHON_VERSION_TRIPLE
if PYTHON_VERSION > 2.6:
if PYTHON_VERSION_TRIPLE >= (2, 7):
def test_single_mode():
single_expressions = (
'i = 1',

View File

@@ -9,12 +9,13 @@ import tempfile
import functools
# uncompyle6 / xdis
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY, code_deparse
from uncompyle6 import code_deparse
from xdis.version_info import PYTHON_VERSION_TRIPLE, PYTHON3, IS_PYPY
# TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there
from xdis import Bytecode, get_opcode
opc = get_opcode(PYTHON_VERSION, IS_PYPY)
opc = get_opcode(PYTHON_VERSION_TRIPLE, IS_PYPY)
Bytecode = functools.partial(Bytecode, opc=opc)
import six
@@ -127,7 +128,7 @@ def validate_uncompyle(text, mode="exec"):
original_text = text
deparsed = code_deparse(
original_code, out=six.StringIO(), version=PYTHON_VERSION, compile_mode=mode
original_code, out=six.StringIO(), version=PYTHON_VERSION_TRIPLE, compile_mode=mode
)
uncompyled_text = deparsed.text
uncompyled_code = compile(uncompyled_text, "<string>", "exec")

View File

@@ -1,11 +1,57 @@
[bdist_rpm]
release = 1
packager = rocky <rb@dustyfeet.com>
doc_files = README
release = 0
packager = rocky <rb@dustyfeet.com
doc_files = README.rst
ChangeLog
COPYING
DECOMPYLE-2.4-CHANGELOG.txt
HISTORY.md
HOW-TO_REPORT-A-BUG.md
NEWS.md
# doc/
# examples/
[bdist_wheel]
universal=1
[egg_info]
tag_build =
tag_date = 0
[metadata]
description_file = README.rst
[flake8]
# max-line-length setting: NO we do not want everyone writing 120-character lines!
# We are setting the maximum line length big here because there are longer
# lines allowed by black in some cases that are forbidden by flake8. Since
# black has the final say about code formatting issues, this setting is here to
# make sure that flake8 doesn't fail the build on longer lines allowed by
# black.
max-line-length = 120
max-complexity = 12
select = E,F,W,C,B,B9
ignore =
# E123 closing bracket does not match indentation of opening bracket's line
E123
# E203 whitespace before ':' (Not PEP8 compliant, Python Black)
E203
# E501 line too long (82 > 79 characters) (replaced by B950 from flake8-bugbear,
# https://github.com/PyCQA/flake8-bugbear)
E501
# W503 line break before binary operator (Not PEP8 compliant, Python Black)
W503
# W504 line break after binary operator (Not PEP8 compliant, Python Black)
W504
# C901 function too complex - since many of zz9 functions are too complex with a lot
# of if branching
C901
# module level import not at top of file. This is too restrictive. Can't even have a
# docstring higher.
E402
per-file-ignores =
# These are config files. The `c` variable them is injected not defined.
pow/ansible/roles/jupyterhub/templates/jupyterhub_config*.py:F821
# Ignore some errors in files that are stolen from other projects to avoid lots
# of merge problems later .
pow/ansible/roles/webtier/files/supervisor_httpgroupok.py:E126,E128,E222,E225,E226,E261,E301,E302,E305,F841,E201,E202
silhouette/src/silhouette/gprof2dot.py:E711,E713,E741,F401
# Ignore undefined name errors in "expectation" test Python code.
# These files get exec'd in an environment that defines the variables.
server/tests/files/expectations/*.py:F821

View File

@@ -6,12 +6,18 @@ import sys
SYS_VERSION = sys.version_info[0:2]
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, 8)):
if ((3, 6) <= SYS_VERSION < (3, 9)):
mess += ("\nFor your Python, version %s, use the master code/branch." %
sys.version[0:3])
else:
mess += ("\nThis package is not supported before Python 2.4. Your Python version is %s."
% sys.version[0:3])
elif (3, 3) <= SYS_VERSION <= (3, 6):
mess += (
"\nFor your Python, version %s, use the python-3.3-3.5 code/branch."
% sys.version[0:3]
)
elif SYS_VERSION < (2, 4):
mess += (
"\nThis package is not supported for Python before Python 2.4 version %s." % sys.version[0:3]
)
print(mess)
raise Exception(mess)
@@ -26,7 +32,7 @@ from __pkginfo__ import (
modname,
py_modules,
short_desc,
VERSION,
__version__,
web,
zip_safe,
)
@@ -49,6 +55,6 @@ setup(
test_suite="nose.collector",
url=web,
tests_require=["nose>=1.0"],
version=VERSION,
version=__version__,
zip_safe=zip_safe,
)

View File

@@ -44,7 +44,8 @@ class TestGrammar(unittest.TestCase):
print(k, reduced_dup_rhs[k])
# assert not reduced_dup_rhs, reduced_dup_rhs
def test_dup_rule(self):
# FIXME: Something got borked here
def no_test_dup_rule(self):
import inspect
python_parser(PYTHON_VERSION, inspect.currentframe().f_code,
is_pypy=IS_PYPY,

View File

@@ -13,7 +13,7 @@ PHONY=check clean dist distclean test test-unit test-functional rmChangeLog clea
GIT2CL ?= git2cl
PYTHON ?= python
PYTHON_VERSION = $(shell $(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2)
PYTHON_VERSION = $(shell $(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2 | head -1)
NATIVE_CHECK = check-$(PYTHON_VERSION)
# Set COMPILE='--compile' to force compilation before check
@@ -22,8 +22,8 @@ COVER_DIR=../tmp/grammar-cover
# Run short tests
check-short:
@$(PYTHON) -V && PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2`; \
$(MAKE) check-bytecode-$${PYTHON_VERSION}
@$(PYTHON) -V && PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2` | head -1; \
$(MAKE) check-bytecode-${PYTHON_VERSION}
# Run all tests
check:
@@ -77,6 +77,12 @@ check-3.7: check-bytecode
# $(PYTHON) test_pythonlib.py --bytecode-3.8-run --verify-run
# $(PYTHON) test_pythonlib.py --bytecode-3.8 --syntax-verify $(COMPILE)
check-3.9: check-bytecode
@echo "Note that we do not support decompiling Python 3.9 bytecode - no 3.9 tests run"
check-3.10: check-bytecode
@echo "Note that we do not support decompiling Python 3.10 bytecode - no 3.10 tests run"
# FIXME
#: this is called when running under pypy3.5-5.8.0, pypy2-5.6.0, or pypy3.6-7.3.0
5.8 5.6:

View File

@@ -3,14 +3,22 @@
"""
import os, sys, py_compile
assert len(sys.argv) >= 2
assert (2 <= len(sys.argv) <= 4)
version = sys.version[0:3]
vers = sys.version_info[:2]
if sys.argv[1] in ("--run", "-r"):
suffix = "_run"
py_source = sys.argv[2:]
i = 2
else:
suffix = ""
py_source = sys.argv[1:]
i = 1
try:
optimize = int(sys.argv[-1])
py_source = sys.argv[i:-1]
except:
optimize = 2
for path in py_source:
short = os.path.basename(path)
@@ -19,7 +27,10 @@ for path in py_source:
else:
cfile = "bytecode_%s%s/%s" % (version, suffix, short) + "c"
print("byte-compiling %s to %s" % (path, cfile))
optimize = 2
py_compile.compile(path, cfile, optimize=optimize)
if isinstance(version, str) or version >= (2, 6, 0):
optimize = optimize
if vers > (3, 1):
py_compile.compile(path, cfile, optimize=optimize)
else:
py_compile.compile(path, cfile)
if vers >= (2, 6):
os.system("../bin/uncompyle6 -a -T %s" % cfile)

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

@@ -50,7 +50,7 @@ for VERSION in $PYVERSIONS ; do
LOGFILE=/tmp/${MAIN}-$VERSION-$$.log
case "$VERSION" in
3.7.7 | 3.8.2 | 3.1.5 | 3.0.1 )
3.7.8 | 3.8.5 | 3.1.5 | 3.0.1 )
continue
;;
3.5.9 )
@@ -65,7 +65,7 @@ for VERSION in $PYVERSIONS ; do
3.4.10 )
MAX_TESTS=800
;;
3.6.10 )
3.6.11 )
# MAX_TESTS=1300 # about 2139 exist
# fails on _pyio.cpython-36.opt-1.pyc
MAX_TESTS=34

View File

@@ -0,0 +1,17 @@
# Adapted from 1.4 anydbm
"""This program is self-checking!"""
def scan(items):
for i in items:
try:
5 / i
except:
continue
else:
break
else:
return 2
return i
assert scan((0, 1)) == 1
assert scan((0, 0)) == 2
assert scan((3, 2, 1)) == 3

View File

@@ -0,0 +1,4 @@
# From https://github.com/rocky/python-uncompyle6/issues/350
# This is RUNNABLE!
a = (lambda x: x)(abs)
assert a(-3) == 3

View File

@@ -0,0 +1,9 @@
# From 2.7.17 test_bdb.py
# The problem was detecting a docstring at the begining of the module
# It must be detected and change'd or else the "from __future__" below
# is invalid.
# Note that this has to be compiled with optimation < 2 or else optimization
# will remove the docstring
"""Rational, infinite-precision, real numbers."""
from __future__ import division

View File

@@ -0,0 +1,27 @@
# From 2.7 test_descr.py
# Testing __doc__ descriptor...
# The bug in decompilation was erroneously matching
# __doc__ = as a docstring
"""This program is self-checking!"""
def test_doc_descriptor():
# Testing __doc__ descriptor...
# Python SF bug 542984
class DocDescr(object):
def __get__(self, object, otype):
if object:
object = object.__class__.__name__ + ' instance'
if otype:
otype = otype.__name__
return 'object=%s; type=%s' % (object, otype)
class OldClass:
__doc__ = DocDescr()
class NewClass(object):
__doc__ = DocDescr()
assert OldClass.__doc__ == 'object=None; type=OldClass'
assert OldClass().__doc__ == 'object=OldClass instance; type=OldClass'
assert NewClass.__doc__ == 'object=None; type=NewClass'
assert NewClass().__doc__ == 'object=NewClass instance; type=NewClass'
test_doc_descriptor()

View File

@@ -1,5 +1,5 @@
# Python 3.3 pyclbr.py
# Note that Python 3 adds a lot of unecessary "continues"
# Note that Python 3 adds a lot of unnecessary "continues"
# and puts that in for "pass"
def _readmodule(g, token, path):
for tokentype in g:

View File

@@ -8,7 +8,7 @@ b = [4, 5, 6]
del b[1]
del b[:]
# del_stmt ::= expr expr DELETE_SLICE+1
# delete ::= expr expr DELETE_SLICE+1
l = [None] * 10
del l[-2:]

View File

@@ -45,7 +45,6 @@ SKIP_TESTS=(
[test_grammar.py]=1 # Too many stmts. Handle large stmts
[test_grp.py]=1 # Long test - might work Control flow?
[test_pep247.py]=1 # Long test - might work? Control flow?
[test_pwd.py]=1 # Long test - might work? Control flow?
[test_socketserver.py]=1 # -- test takes too long to run: 40 seconds
[test_threading.py]=1 # test takes too long to run: 11 seconds
[test_thread.py]=1 # test takes too long to run: 36 seconds

View File

@@ -55,12 +55,9 @@ SKIP_TESTS=(
[test_ossaudiodev.py]=1 # it fails on its own
[test_pdb.py]=1 # Line-number specific
[test_pep277.py]=1 # it fails on its own
[test_pep352.py]=1 # Investigate
[test_plistlib.py]=1 # it fails on its own
[test_pwd.py]=1 # Long test - might work? Control flow?
[test_pyclbr.py]=1 # Investigate
[test_rgbimg.py]=1 # it fails on its own
[test_queue.py]=1 # Control flow?
[test_scriptpackages.py]=1 # it fails on its own
[test_socketserver.py]=1 # Too long to run - 42 seconds
[test_sqlite.py]=1 # it fails on its own

View File

@@ -7,7 +7,6 @@ SKIP_TESTS=(
# assert 0 # shouldn't reach here.
[test_shutil.py]=1
[test___all__.py]=1 # it fails on its own
[test___all__.py]=1 # it fails on its own
[test_aepack.py]=1 # Fails on its own
@@ -60,9 +59,7 @@ SKIP_TESTS=(
[test_ossaudiodev.py]=1 # it fails on its own
[test_pep277.py]=1 # it fails on its own
[test_pep352.py]=1 # Investigate
[test_pyclbr.py]=1 # Investigate
[test_pwd.py]=1 # Long test - might work? Control flow?
[test_py3kwarn.py]=1 # it fails on its own
[test_scriptpackages.py]=1 # it fails on its own

View File

@@ -19,7 +19,6 @@ SKIP_TESTS=(
[test_modulefinder.py]=1 # FIX
[test_multiprocessing.py]=1 # On uncompyle2, takes 24 secs
[test_poll.py]=1 # test takes too long to run: 11 seconds
[test_pwd.py]=1 # Takes too long
[test_regrtest.py]=1 #
[test_runpy.py]=1 # Long and fails on its own
[test_select.py]=1 # Runs okay but takes 11 seconds

View File

@@ -63,6 +63,7 @@ SKIP_TESTS=(
[test_faulthandler.py]=1 # test takes too long before decompiling
[test_fileinput.py]=1 # Test assertion failures
[test_finalization.py]=1 # if/else logic
[test_frame.py]=1 # test assertion errors
[test_ftplib.py]=1 # parse error
[test_fstring.py]=1 # need to disambiguate leading fstrings from docstrings

View File

@@ -8,6 +8,37 @@ SKIP_TESTS=(
[test_urllib2.py]=1 # FIXME: works on uncompyle6?
[test_zipimport.py]=1 # FIXME: works on uncompyle6
# From decompyle3 excludes
# Very Simple example. Compare with 3.7 Need 3.8 parse rules for exception handling return
# for proto in p:
# try:
# drop = 5
# except StopIteration:
# continue
[test_dict.py]=1 #
# Simple example. Compare with 3.7 Need 3.8 parse rules for exception handling return
# try:
# return 5
# except KeyError:
# return res
# except TypeError:
# return 10
# These and the above may be due to new code generation or tests
# between 3.8.3 and 3.8.5 ?
[test_decorators.py]=1 #
[test_dtrace.py]=1 #
[test_exceptions.py]=1 #
[test_ftplib.py]=1 #
[test_gc.py]=1 #
[test_gzip.py]=1 #
[test_hashlib.py]=1 #
[test_iter.py]=1 #
[test_itertools.py]=1 #
[test___all__.py]=1 # it fails on its own
[test_argparse.py]=1 #- it fails on its own
[test_array.py]=1 #- parse error

View File

@@ -52,7 +52,7 @@ for VERSION in $PYVERSIONS ; do
LOGFILE=/tmp/runtests-$VERSION-$$.log
case "$VERSION" in
3.0.1 | 3.1.5 | 3.2.6 | 3.8.1 )
3.0.1 | 3.1.5 | 3.2.6 | 3.8.5 )
continue
;;
esac

View File

@@ -30,6 +30,8 @@ import xdis.magics as magics
# ----- configure this for your needs
python_versions = [v for v in magics.python_versions if re.match("^[0-9.]+$", v)]
print(python_versions)
sys.exit(0)
# FIXME: we should remove Python versions that we don't support.
# These include Jython, and Python bytecode changes pre release.

View File

@@ -3,7 +3,7 @@
[flake8]
exclude = .tox,./build,./trepan/processor/command/tmp
filename = *.py
ignore = C901,E113,E121,E122,E123,E124,E125,E126,E127,E128,E129,E201,E202,E203,E221,E222,E225,E226,E241,E242,E251,E261,E271,E272,E302,E401,E402,E501,F401,E701,E702
ignore = C901,E113,E121,E122,E123,E124,E125,E126,E127,E128,E129,E201,E202,E203,E221,E222,E225,E226,E241,E242,E251,E261,E271,E272,E302,E401,E402,E501,F401,E701,E702,W503
[tox]
envlist = py27, py34, pypy

View File

@@ -28,20 +28,22 @@
import sys
__docformat__ = 'restructuredtext'
__docformat__ = "restructuredtext"
PYTHON3 = (sys.version_info >= (3, 0))
from uncompyle6.version import __version__
PYTHON3 = sys.version_info >= (3, 0)
# We do this crazy way to support Python 2.6 which
# doesn't support version_major, and has a bug in
# floating point so we can't divide 26 by 10 and get
# 2.6
PYTHON_VERSION = sys.version_info[0] + (sys.version_info[1] / 10.0)
PYTHON_VERSION_STR = "%s.%s" % (sys.version_info[0], sys.version_info[1])
PYTHON_VERSION_STR = "%s.%s" % (sys.version_info[0], sys.version_info[1])
IS_PYPY = '__pypy__' in sys.builtin_module_names
IS_PYPY = "__pypy__" in sys.builtin_module_names
if hasattr(sys, 'setrecursionlimit'):
if hasattr(sys, "setrecursionlimit"):
# pyston doesn't have setrecursionlimit
sys.setrecursionlimit(5000)

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env python
# Mode: -*- python -*-
#
# Copyright (c) 2015-2016, 2018 by Rocky Bernstein <rb@dustyfeet.com>
# Copyright (c) 2015-2016, 2018, 2020 by Rocky Bernstein <rb@dustyfeet.com>
#
import sys, os, getopt
from uncompyle6.disas import disassemble_file
from uncompyle6.version import VERSION
from uncompyle6.version import __version__
program, ext = os.path.splitext(os.path.basename(__file__))
@@ -57,7 +57,7 @@ Type -h for for full help.""" % program
print(__doc__)
sys.exit(1)
elif opt in ('-V', '--version'):
print("%s %s" % (program, VERSION))
print("%s %s" % (program, __version__))
sys.exit(0)
else:
print(opt)

View File

@@ -1,10 +1,11 @@
#!/usr/bin/env python
# Mode: -*- python -*-
#
# Copyright (c) 2015-2017, 2019 by Rocky Bernstein
# Copyright (c) 2015-2017, 2019-2020 by Rocky Bernstein
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
#
import sys, os, getopt, time
from xdis.version_info import version_tuple_to_str
program = 'uncompyle6'
@@ -62,7 +63,7 @@ program = 'uncompyle6'
from uncompyle6 import verify
from uncompyle6.main import main, status_msg
from uncompyle6.version import VERSION
from uncompyle6.version import __version__
def usage():
print(__doc__)
@@ -70,9 +71,12 @@ def usage():
def main_bin():
if not (sys.version_info[0:2] in ((2, 4), (2, 5), (2, 6), (2, 7))):
sys.stderr.write('Error: this branch of %s requires Python 2.4, 2.5, 2.6 or 2.7'
% program)
if not (sys.version_info[0:2] in ((2, 4), (2, 5), (2, 6), (2, 7), (3, 0),
(3, 1), (3, 2), (3, 3),
(3, 4), (3, 5), (3, 6),
(3, 7), (3, 8), (3, 9), (3, 10)
)):
print('Error: %s requires Python 2.4-3.10' % program)
sys.exit(-1)
do_verify = recurse_dirs = False
@@ -101,7 +105,7 @@ def main_bin():
print(__doc__)
sys.exit(0)
elif opt in ('-V', '--version'):
print("%s %s" % (program, VERSION))
print("%s %s" % (program, __version__))
sys.exit(0)
elif opt == '--verify':
options['do_verify'] = 'strong'
@@ -193,6 +197,9 @@ def main_bin():
mess = status_msg(do_verify, *result)
print('# ' + mess)
pass
except ImportError:
print(str(sys.exc_info()[1]))
sys.exit(2)
except (KeyboardInterrupt):
pass
except verify.VerifyCmpError:
@@ -221,7 +228,7 @@ def main_bin():
if f is None:
break
(t, o, f, v) = \
main(src_base, out_base, [f], None, outfile, **options)
main(src_base, out_base, [f], [], outfile, **options)
tot_files += t
okay_files += o
failed_files += f

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2015-2016, 2818-2020 by Rocky Bernstein
# Copyright (c) 2015-2016, 2818-2021 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
@@ -33,6 +33,7 @@ import sys
from collections import deque
from xdis import check_object_path, iscode, load_module
from xdis.version_info import version_tuple_to_str
from uncompyle6.scanner import get_scanner
@@ -45,7 +46,7 @@ def disco(version, co, out=None, is_pypy=False):
# store final output stream for case of error
real_out = out or sys.stdout
real_out.write("# Python %s\n" % version)
real_out.write("# Python %s\n" % version_tuple_to_str(version))
if co.co_filename:
real_out.write("# Embedded file name: %s\n" % co.co_filename)

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2018-2020 Rocky Bernstein <rocky@gnu.org>
# Copyright (C) 2018-2021 Rocky Bernstein <rocky@gnu.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,12 +14,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime, os, subprocess, sys
from uncompyle6 import verify, IS_PYPY, PYTHON_VERSION
from xdis import iscode, sysinfo2float
from uncompyle6 import verify
from xdis import iscode
from xdis.version_info import IS_PYPY, PYTHON_VERSION_TRIPLE, version_tuple_to_str
from uncompyle6.disas import check_object_path
from uncompyle6.semantics import pysource
from uncompyle6.parser import ParserError
from uncompyle6.version import VERSION
from uncompyle6.version import __version__
# from uncompyle6.linenumbers import line_number_mapping
@@ -29,7 +30,6 @@ from uncompyle6.semantics.linemap import deparse_code_with_map
from xdis.load import load_module
def _get_outstream(outfile):
dir = os.path.dirname(outfile)
failed_file = outfile + "_failed"
@@ -66,7 +66,7 @@ def decompile(
Caller is responsible for closing `out` and `mapstream`
"""
if bytecode_version is None:
bytecode_version = sysinfo2float()
bytecode_version = PYTHON_VERSION_TRIPLE
# store final output stream for case of error
real_out = out or sys.stdout
@@ -75,7 +75,7 @@ def decompile(
s += "\n"
real_out.write(s)
assert iscode(co)
assert iscode(co), ("%s does not smell like code" % co)
if is_pypy:
co_pypy_str = "PyPy "
@@ -97,18 +97,21 @@ def decompile(
write("# -*- coding: %s -*-" % source_encoding)
write(
"# uncompyle6 version %s\n"
"# %sPython bytecode %s%s\n# Decompiled from: %sPython %s" %
(VERSION,
co_pypy_str,
bytecode_version,
"# %sPython bytecode %s%s\n# Decompiled from: %sPython %s"
% (
__version__,
co_pypy_str,
version_tuple_to_str(bytecode_version),
" (%s)" % m, run_pypy_str,
"\n# ".join(sys_version_lines),
)
"\n# ".join(sys_version_lines),
)
)
if bytecode_version >= 3.0:
write("# Warning: this version has problems handling the Python 3 byte type in constants properly.\n")
write(
"# Warning: this version of Python has problems handling the Python 3 byte type in constants properly.\n"
)
if co.co_filename:
write("# Embedded file name: %s" % co.co_filename,)
write("# Embedded file name: %s" % co.co_filename)
if timestamp:
write("# Compiled at: %s" %
datetime.datetime.fromtimestamp(timestamp))
@@ -124,12 +127,10 @@ def decompile(
mapstream = _get_outstream(mapstream)
deparsed = deparse_code_with_map(
bytecode_version,
co,
out,
showasm,
showast,
showgrammar,
bytecode_version,
debug_opts,
code_objects=code_objects,
is_pypy=is_pypy,
)
@@ -161,9 +162,9 @@ def compile_file(source_path):
basename = source_path
if hasattr(sys, "pypy_version_info"):
bytecode_path = "%s-pypy%s.pyc" % (basename, PYTHON_VERSION)
bytecode_path = "%s-pypy%s.pyc" % (basename, version_tuple_to_str())
else:
bytecode_path = "%s-%s.pyc" % (basename, PYTHON_VERSION)
bytecode_path = "%s-%s.pyc" % (basename, version_tuple_to_str())
print("compiling %s to %s" % (source_path, bytecode_path))
py_compile.compile(source_path, bytecode_path, "exec")
@@ -297,7 +298,7 @@ def main(
else:
buffering = 0
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering)
if PYTHON_VERSION > 2.6:
if PYTHON_VERSION_TRIPLE > (2, 6):
tee = subprocess.Popen(["tee", current_outfile],
stdin=subprocess.PIPE)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2015-2020 Rocky Bernstein
# Copyright (c) 2015-2021 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
@@ -21,9 +21,9 @@ Common uncompyle6 parser routines.
import sys
from xdis import iscode, py_str2float
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6.show import maybe_show_asm
from xdis import iscode
class ParserError(Exception):
@@ -352,10 +352,10 @@ class PythonParser(GenericASTBuilder):
stmt ::= with
stmt ::= withasstmt
stmt ::= del_stmt
del_stmt ::= DELETE_FAST
del_stmt ::= DELETE_NAME
del_stmt ::= DELETE_GLOBAL
stmt ::= delete
delete ::= DELETE_FAST
delete ::= DELETE_NAME
delete ::= DELETE_GLOBAL
stmt ::= return
@@ -621,7 +621,7 @@ class PythonParser(GenericASTBuilder):
"""
def parse(p, tokens, customize):
def parse(p, tokens, customize, code):
p.customize_grammar_rules(tokens, customize)
ast = p.parse(tokens)
# p.cleanup()
@@ -640,107 +640,109 @@ def get_python_parser(
# If version is a string, turn that into the corresponding float.
if isinstance(version, str):
version = py_str2float(version)
version = tuple([int(v) for v in version.split(".")[:2]])
version = version[:2]
# FIXME: there has to be a better way...
# We could do this as a table lookup, but that would force us
# in import all of the parsers all of the time. Perhaps there is
# a lazy way of doing the import?
if version < 3.0:
if version < 2.2:
if version == 1.0:
if version < (3, 0):
if version < (2, 2):
if version == (1, 0):
import uncompyle6.parsers.parse10 as parse10
if compile_mode == "exec":
p = parse10.Python10Parser(debug_parser)
else:
p = parse10.Python01ParserSingle(debug_parser)
elif version == 1.1:
elif version == (1, 1):
import uncompyle6.parsers.parse11 as parse11
if compile_mode == "exec":
p = parse11.Python11Parser(debug_parser)
else:
p = parse11.Python11ParserSingle(debug_parser)
if version == 1.2:
if version == (1, 2):
import uncompyle6.parsers.parse12 as parse12
if compile_mode == "exec":
p = parse12.Python12Parser(debug_parser)
else:
p = parse12.Python12ParserSingle(debug_parser)
if version == 1.3:
if version == (1, 3):
import uncompyle6.parsers.parse13 as parse13
if compile_mode == "exec":
p = parse13.Python13Parser(debug_parser)
else:
p = parse13.Python13ParserSingle(debug_parser)
elif version == 1.4:
elif version == (1, 4):
import uncompyle6.parsers.parse14 as parse14
if compile_mode == "exec":
p = parse14.Python14Parser(debug_parser)
else:
p = parse14.Python14ParserSingle(debug_parser)
elif version == 1.5:
elif version == (1, 5):
import uncompyle6.parsers.parse15 as parse15
if compile_mode == "exec":
p = parse15.Python15Parser(debug_parser)
else:
p = parse15.Python15ParserSingle(debug_parser)
elif version == 1.6:
elif version == (1, 6):
import uncompyle6.parsers.parse16 as parse16
if compile_mode == "exec":
p = parse16.Python16Parser(debug_parser)
else:
p = parse16.Python16ParserSingle(debug_parser)
elif version == 2.1:
elif version == (2, 1):
import uncompyle6.parsers.parse21 as parse21
if compile_mode == "exec":
p = parse21.Python21Parser(debug_parser)
else:
p = parse21.Python21ParserSingle(debug_parser)
elif version == 2.2:
elif version == (2, 2):
import uncompyle6.parsers.parse22 as parse22
if compile_mode == "exec":
p = parse22.Python22Parser(debug_parser)
else:
p = parse22.Python22ParserSingle(debug_parser)
elif version == 2.3:
elif version == (2, 3):
import uncompyle6.parsers.parse23 as parse23
if compile_mode == "exec":
p = parse23.Python23Parser(debug_parser)
else:
p = parse23.Python23ParserSingle(debug_parser)
elif version == 2.4:
elif version == (2, 4):
import uncompyle6.parsers.parse24 as parse24
if compile_mode == "exec":
p = parse24.Python24Parser(debug_parser)
else:
p = parse24.Python24ParserSingle(debug_parser)
elif version == 2.5:
elif version == (2, 5):
import uncompyle6.parsers.parse25 as parse25
if compile_mode == "exec":
p = parse25.Python25Parser(debug_parser)
else:
p = parse25.Python25ParserSingle(debug_parser)
elif version == 2.6:
elif version == (2, 6):
import uncompyle6.parsers.parse26 as parse26
if compile_mode == "exec":
p = parse26.Python26Parser(debug_parser)
else:
p = parse26.Python26ParserSingle(debug_parser)
elif version == 2.7:
elif version == (2, 7):
import uncompyle6.parsers.parse27 as parse27
if compile_mode == "exec":
@@ -760,63 +762,63 @@ def get_python_parser(
else:
import uncompyle6.parsers.parse3 as parse3
if version == 3.0:
if version == (3, 0):
import uncompyle6.parsers.parse30 as parse30
if compile_mode == "exec":
p = parse30.Python30Parser(debug_parser)
else:
p = parse30.Python30ParserSingle(debug_parser)
elif version == 3.1:
elif version == (3, 1):
import uncompyle6.parsers.parse31 as parse31
if compile_mode == "exec":
p = parse31.Python31Parser(debug_parser)
else:
p = parse31.Python31ParserSingle(debug_parser)
elif version == 3.2:
elif version == (3, 2):
import uncompyle6.parsers.parse32 as parse32
if compile_mode == "exec":
p = parse32.Python32Parser(debug_parser)
else:
p = parse32.Python32ParserSingle(debug_parser)
elif version == 3.3:
elif version == (3, 3):
import uncompyle6.parsers.parse33 as parse33
if compile_mode == "exec":
p = parse33.Python33Parser(debug_parser)
else:
p = parse33.Python33ParserSingle(debug_parser)
elif version == 3.4:
elif version == (3, 4):
import uncompyle6.parsers.parse34 as parse34
if compile_mode == "exec":
p = parse34.Python34Parser(debug_parser)
else:
p = parse34.Python34ParserSingle(debug_parser)
elif version == 3.5:
elif version == (3, 5):
import uncompyle6.parsers.parse35 as parse35
if compile_mode == "exec":
p = parse35.Python35Parser(debug_parser)
else:
p = parse35.Python35ParserSingle(debug_parser)
elif version == 3.6:
elif version == (3, 6):
import uncompyle6.parsers.parse36 as parse36
if compile_mode == "exec":
p = parse36.Python36Parser(debug_parser)
else:
p = parse36.Python36ParserSingle(debug_parser)
elif version == 3.7:
elif version == (3, 7):
import uncompyle6.parsers.parse37 as parse37
if compile_mode == "exec":
p = parse37.Python37Parser(debug_parser)
else:
p = parse37.Python37ParserSingle(debug_parser)
elif version == 3.8:
elif version == (3, 8):
import uncompyle6.parsers.parse38 as parse38
if compile_mode == "exec":
@@ -875,16 +877,23 @@ def python_parser(
# For heavy grammar debugging
# parser_debug = {'rules': True, 'transition': True, 'reduce' : True,
# 'showstack': 'full'}
p = get_python_parser(version, parser_debug)
return parse(p, tokens, customize)
# FIXME: have p.insts update in a better way
# modularity is broken here
p.insts = scanner.insts
p.offset2inst_index = scanner.offset2inst_index
return parse(p, tokens, customize, co)
if __name__ == "__main__":
def parse_test(co):
from uncompyle6 import PYTHON_VERSION, IS_PYPY
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
ast = python_parser(PYTHON_VERSION, co, showasm=True, is_pypy=IS_PYPY)
ast = python_parser(PYTHON_VERSION_TRIPLE[:2], co, showasm=True, is_pypy=IS_PYPY)
print(ast)
return
parse_test(parse_test.func_code)

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2015-2020 Rocky Bernstein
# Copyright (c) 2015-2021 Rocky Bernstein
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
#
# Copyright (c) 1999 John Aycock
@@ -97,9 +97,9 @@ class Python2Parser(PythonParser):
for ::= SETUP_LOOP expr for_iter store
for_block POP_BLOCK _come_froms
del_stmt ::= delete_subscript
delete ::= delete_subscript
delete_subscript ::= expr expr DELETE_SUBSCR
del_stmt ::= expr DELETE_ATTR
delete ::= expr DELETE_ATTR
_mklambda ::= load_closure mklambda
kwarg ::= LOAD_CONST expr
@@ -317,7 +317,7 @@ class Python2Parser(PythonParser):
build_count = token.attr
thousands = build_count // 1024
thirty32s = (build_count // 32) % 32
if thirty32s > 0:
if thirty32s > 0 or thousands > 0:
rule = "expr32 ::=%s" % (" expr" * 32)
self.add_unique_rule(rule, opname_base, build_count, customize)
if thousands > 0:
@@ -348,7 +348,7 @@ class Python2Parser(PythonParser):
],
customize,
)
if self.version >= 2.7:
if self.version >= (2, 7):
self.add_unique_rule(
"dict_comp_func ::= BUILD_MAP_n LOAD_FAST FOR_ITER store "
"comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST",
@@ -421,17 +421,17 @@ class Python2Parser(PythonParser):
custom_seen_ops.add(opname)
continue
elif opname == "DELETE_ATTR":
self.addRule("del_stmt ::= expr DELETE_ATTR", nop_func)
self.addRule("delete ::= expr DELETE_ATTR", nop_func)
custom_seen_ops.add(opname)
continue
elif opname.startswith("DELETE_SLICE"):
self.addRule(
"""
del_expr ::= expr
del_stmt ::= del_expr DELETE_SLICE+0
del_stmt ::= del_expr del_expr DELETE_SLICE+1
del_stmt ::= del_expr del_expr DELETE_SLICE+2
del_stmt ::= del_expr del_expr del_expr DELETE_SLICE+3
delete ::= del_expr DELETE_SLICE+0
delete ::= del_expr del_expr DELETE_SLICE+1
delete ::= del_expr del_expr DELETE_SLICE+2
delete ::= del_expr del_expr del_expr DELETE_SLICE+3
""",
nop_func,
)
@@ -451,7 +451,7 @@ class Python2Parser(PythonParser):
elif opname == "DELETE_SUBSCR":
self.addRule(
"""
del_stmt ::= delete_subscript
delete ::= delete_subscript
delete_subscript ::= expr expr DELETE_SUBSCR
""",
nop_func,
@@ -575,7 +575,7 @@ class Python2Parser(PythonParser):
customize,
)
if self.version >= 2.7:
if self.version >= (2, 7):
if i > 0:
prev_tok = tokens[i - 1]
if prev_tok == "LOAD_DICTCOMP":
@@ -713,7 +713,7 @@ class Python2Parser(PythonParser):
elif lhs in ("raise_stmt1",):
# We will assume 'LOAD_ASSERT' will be handled by an assert grammar rule
return tokens[first] == "LOAD_ASSERT" and (last >= len(tokens))
elif rule == ("or", ("expr_jit", "expr", "\\e_come_from_opt")):
elif rule == ("or", ("expr", "jmp_true", "expr", "\\e_come_from_opt")):
expr2 = ast[2]
return expr2 == "expr" and expr2[0] == "LOAD_ASSERT"
elif lhs in ("delete_subscript", "del_expr"):

View File

@@ -48,7 +48,7 @@ class Python23Parser(Python24Parser):
while1stmt ::= _while1test l_stmts JUMP_BACK
POP_TOP POP_BLOCK
list_comp ::= BUILD_LIST_0 DUP_TOP LOAD_ATTR store list_iter del_stmt
list_comp ::= BUILD_LIST_0 DUP_TOP LOAD_ATTR store list_iter delete
list_for ::= expr for_iter store list_iter JUMP_BACK come_froms POP_TOP JUMP_BACK
lc_body ::= LOAD_NAME expr CALL_FUNCTION_1 POP_TOP

View File

@@ -91,7 +91,7 @@ class Python24Parser(Python25Parser):
""")
super(Python24Parser, self).customize_grammar_rules(tokens, customize)
self.remove_rules_24()
if self.version == 2.4:
if self.version[:2] == (2, 4):
self.check_reduce['nop_stmt'] = 'tokens'
def reduce_is_invalid(self, rule, ast, tokens, first, last):

View File

@@ -97,7 +97,7 @@ class Python25Parser(Python26Parser):
return_stmt_lambda LAMBDA_MARKER
""")
super(Python25Parser, self).customize_grammar_rules(tokens, customize)
if self.version == 2.5:
if self.version[:2] == (2, 5):
self.check_reduce["try_except"] = "tokens"
self.check_reduce["aug_assign1"] = "AST"
self.check_reduce["ifelsestmt"] = "AST"

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2017-2019 Rocky Bernstein
# Copyright (c) 2017-2021 Rocky Bernstein
"""
spark grammar differences over Python2 for Python 2.6.
"""
@@ -6,6 +6,7 @@ spark grammar differences over Python2 for Python 2.6.
from uncompyle6.parser import PythonParserSingle
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6.parsers.parse2 import Python2Parser
from uncompyle6.parsers.reducecheck import (except_handler, tryelsestmt)
class Python26Parser(Python2Parser):
@@ -24,7 +25,11 @@ class Python26Parser(Python2Parser):
except_handler ::= JUMP_FORWARD COME_FROM except_stmts
come_froms_pop END_FINALLY come_froms
except_handler ::= JUMP_FORWARD COME_FROM except_stmts END_FINALLY
except_handler ::= JUMP_FORWARD COME_FROM except_stmts
END_FINALLY
except_handler ::= JUMP_FORWARD COME_FROM except_stmts
POP_TOP END_FINALLY
come_froms
except_handler ::= jmp_abs COME_FROM except_stmts
@@ -33,6 +38,7 @@ class Python26Parser(Python2Parser):
except_handler ::= jmp_abs COME_FROM except_stmts
END_FINALLY JUMP_FORWARD
# Sometimes we don't put in COME_FROM to the next statement
# like we do in 2.7. Perhaps we should?
try_except ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
@@ -87,8 +93,8 @@ class Python26Parser(Python2Parser):
cf_jb_cf_pop ::= _come_froms JUMP_BACK come_froms POP_TOP
bp_come_from ::= POP_BLOCK COME_FROM
jb_pb_come_from ::= JUMP_BACK bp_come_from
pb_come_from ::= POP_BLOCK COME_FROM
jb_pb_come_from ::= JUMP_BACK pb_come_from
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM POP_TOP
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD come_froms POP_TOP COME_FROM
@@ -142,7 +148,7 @@ class Python26Parser(Python2Parser):
while1stmt ::= SETUP_LOOP l_stmts_opt CONTINUE _come_froms
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_pop POP_BLOCK _come_froms
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cf_pop bp_come_from
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cf_pop pb_come_from
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cf_pop POP_BLOCK
whilestmt ::= SETUP_LOOP testexpr returns POP_BLOCK COME_FROM
@@ -224,15 +230,18 @@ class Python26Parser(Python2Parser):
list_iter ::= list_if JUMP_BACK
list_iter ::= list_if JUMP_BACK COME_FROM POP_TOP
list_comp ::= BUILD_LIST_0 DUP_TOP
store list_iter del_stmt
store list_iter delete
list_comp ::= BUILD_LIST_0 DUP_TOP
store list_iter JUMP_BACK del_stmt
store list_iter JUMP_BACK delete
lc_body ::= LOAD_NAME expr LIST_APPEND
lc_body ::= LOAD_FAST expr LIST_APPEND
comp_for ::= SETUP_LOOP expr for_iter store comp_iter jb_pb_come_from
comp_body ::= gen_comp_body
comp_iter ::= comp_if_not
comp_if_not ::= expr jmp_true comp_iter
comp_body ::= gen_comp_body
for_block ::= l_stmts_opt _come_froms POP_TOP JUMP_BACK
@@ -342,18 +351,30 @@ class Python26Parser(Python2Parser):
WITH_CLEANUP END_FINALLY
""")
super(Python26Parser, self).customize_grammar_rules(tokens, customize)
self.reduce_check_table = {
"except_handler": except_handler,
"tryelsestmt": tryelsestmt,
"tryelsestmtl": tryelsestmt,
}
self.check_reduce['and'] = 'AST'
self.check_reduce['assert_expr_and'] = 'AST'
self.check_reduce["except_handler"] = "tokens"
self.check_reduce["ifstmt"] = "tokens"
self.check_reduce["ifelsestmt"] = "AST"
self.check_reduce["forelselaststmtl"] = "tokens"
self.check_reduce["forelsestmt"] = "tokens"
self.check_reduce['list_for'] = 'AST'
self.check_reduce['try_except'] = 'tokens'
self.check_reduce['tryelsestmt'] = 'AST'
self.check_reduce['tryelsestmtl'] = 'AST'
def reduce_is_invalid(self, rule, ast, tokens, first, last):
invalid = super(Python26Parser,
self).reduce_is_invalid(rule, ast,
tokens, first, last)
lhs = rule[0]
if invalid or tokens is None:
return invalid
if rule in (
@@ -369,7 +390,7 @@ class Python26Parser(Python2Parser):
# For now, we won't let the 2nd 'expr' be a "if_exp_not"
# However in < 2.6 where we don't have if/else expression it *can*
# be.
if self.version >= 2.6 and ast[2][0] == "if_exp_not":
if self.version >= (2, 6) and ast[2][0] == "if_exp_not":
return True
test_index = last
@@ -386,6 +407,26 @@ class Python26Parser(Python2Parser):
return not (jmp_target == tokens[test_index].offset or
tokens[last].pattr == jmp_false.pattr)
elif lhs in ("forelselaststmtl", "forelsestmt"):
# print("XXX", first, last)
# for t in range(first, last):
# print(tokens[t])
# print("=" * 30)
# If the SETUP_LOOP jumps to the tokens[last] then
# this is a "for" not a "for else".
# However, in Python 2.2 and before there is a SET_LINENO
# instruction which might have gotten removed. So we need
# to account for that. bytecode-1.4/anydbm.pyc exhibits
# this behavior.
# Also we need to use the setup_loop instruction (not opcode)
# since the operand can be a relative offset rather than
# an absolute offset.
setup_inst = self.insts[self.offset2inst_index[tokens[first].offset]]
if self.version <= (2, 2) and tokens[last] == "COME_FROM":
last += 1
return tokens[last-1].off2int() > setup_inst.argval
elif rule == ("ifstmt", ("testexpr", "_ifstmts_jump")):
for i in range(last-1, last-4, -1):
t = tokens[i]
@@ -402,7 +443,7 @@ class Python26Parser(Python2Parser):
# The JUMP_ABSOLUTE has to be to the last POP_TOP or this is invalid
ja_attr = ast[4].attr
return tokens[last].offset != ja_attr
elif rule[0] == 'try_except':
elif lhs == 'try_except':
# We need to distingush try_except from tryelsestmt and we do that
# by checking the jump before the END_FINALLY
# If we have:
@@ -419,12 +460,12 @@ class Python26Parser(Python2Parser):
last -= 1
if (tokens[last] == 'COME_FROM'
and tokens[last-1] == 'END_FINALLY'
and tokens[last-2] == 'POP_TOP'):
and tokens[last-2] == 'POP_TOP'):
# A jump of 2 is a jump around POP_TOP, END_FINALLY which
# would indicate try/else rather than try
return (tokens[last-3].kind not in frozenset(('JUMP_FORWARD', 'RETURN_VALUE'))
or (tokens[last-3] == 'JUMP_FORWARD' and tokens[last-3].attr != 2))
elif rule[0] == 'tryelsestmt':
elif lhs == 'tryelsestmt':
# We need to distingush try_except from tryelsestmt and we do that
# by making sure that the jump before the except handler jumps to

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016-2019 Rocky Bernstein
# Copyright (c) 2016-2020 Rocky Bernstein
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
# Copyright (c) 2000-2002 by hartmut Goebel <hartmut@goebel.noris.de>
@@ -7,9 +7,10 @@ from xdis import next_offset
from uncompyle6.parser import PythonParserSingle, nop_func
from uncompyle6.parsers.parse2 import Python2Parser
from uncompyle6.parsers.reducecheck import (
aug_assign1_check,
or_check,
ifelsestmt,
tryelsestmt,
except_handler,
)
class Python27Parser(Python2Parser):
@@ -92,7 +93,7 @@ class Python27Parser(Python2Parser):
iflaststmtl ::= testexpr c_stmts
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD come_froms
bp_come_from ::= POP_BLOCK COME_FROM
pb_come_from ::= POP_BLOCK COME_FROM
# FIXME: Common with 3.0+
jmp_false ::= POP_JUMP_IF_FALSE
@@ -164,7 +165,7 @@ class Python27Parser(Python2Parser):
while1elsestmt ::= SETUP_LOOP l_stmts JUMP_BACK
else_suitel COME_FROM
while1stmt ::= SETUP_LOOP returns bp_come_from
while1stmt ::= SETUP_LOOP returns pb_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
@@ -231,12 +232,15 @@ class Python27Parser(Python2Parser):
# FIXME: Put more in this table
self.reduce_check_table = {
# "ifelsestmt": ifelsestmt,
"aug_assign1": aug_assign1_check,
"except_handler": except_handler,
"or": or_check,
"tryelsestmt": tryelsestmt,
"tryelsestmtl": tryelsestmt,
}
self.check_reduce["and"] = "AST"
self.check_reduce["aug_assign1"] = "AST"
self.check_reduce["if_exp"] = "AST"
self.check_reduce["except_handler"] = "tokens"

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2015-2020 Rocky Bernstein
# Copyright (c) 2015-2021 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
@@ -254,7 +254,7 @@ class Python3Parser(PythonParser):
END_FINALLY _jump
except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM_FINALLY
LOAD_CONST store del_stmt
LOAD_CONST store delete
except_suite ::= returns
@@ -538,7 +538,7 @@ class Python3Parser(PythonParser):
# FIXME: What's the deal with the two rules? Different Python versions?
# Different situations? Note that the above rule is based on the CALL_FUNCTION
# token found, while this one doesn't.
if self.version < 3.6:
if self.version < (3, 6):
call_function = self.call_fn_name(call_fn_tok)
args_pos, args_kw = self.get_pos_kw(call_fn_tok)
rule = "build_class ::= LOAD_BUILD_CLASS mkfunc %s" "%s" % (
@@ -593,7 +593,7 @@ class Python3Parser(PythonParser):
# Note: 3.5+ have subclassed this method; so we don't handle
# 'CALL_FUNCTION_VAR' or 'CALL_FUNCTION_EX' here.
if is_pypy and self.version >= 3.6:
if is_pypy and self.version >= (3, 6):
if token == "CALL_FUNCTION":
token.kind = self.call_fn_name(token)
rule = (
@@ -627,7 +627,7 @@ class Python3Parser(PythonParser):
"""Python 3.3 added a an addtional LOAD_STR before MAKE_FUNCTION and
this has an effect on many rules.
"""
if self.version >= 3.3:
if self.version >= (3, 3):
if PYTHON3 or not self.is_pypy:
load_op = "LOAD_STR "
else:
@@ -776,7 +776,7 @@ class Python3Parser(PythonParser):
rule = "kvlist_n ::="
self.add_unique_rule(rule, "kvlist_n", 1, customize)
rule = "dict ::= BUILD_MAP_n kvlist_n"
elif self.version >= 3.5:
elif self.version >= (3, 5):
if not opname.startswith("BUILD_MAP_WITH_CALL"):
# FIXME: Use the attr
# so this doesn't run into exponential parsing time.
@@ -846,7 +846,7 @@ class Python3Parser(PythonParser):
build_count = token.attr
thousands = build_count // 1024
thirty32s = (build_count // 32) % 32
if thirty32s > 0:
if thirty32s > 0 or thousands > 0:
rule = "expr32 ::=%s" % (" expr" * 32)
self.add_unique_rule(rule, opname_base, build_count, customize)
pass
@@ -935,7 +935,7 @@ class Python3Parser(PythonParser):
self.addRule("continue ::= CONTINUE_LOOP", nop_func)
custom_ops_processed.add(opname)
elif opname == "DELETE_ATTR":
self.addRule("del_stmt ::= expr DELETE_ATTR", nop_func)
self.addRule("delete ::= expr DELETE_ATTR", nop_func)
custom_ops_processed.add(opname)
elif opname == "DELETE_DEREF":
self.addRule(
@@ -949,7 +949,7 @@ class Python3Parser(PythonParser):
elif opname == "DELETE_SUBSCR":
self.addRule(
"""
del_stmt ::= delete_subscript
delete ::= delete_subscript
delete_subscript ::= expr expr DELETE_SUBSCR
""",
nop_func,
@@ -1061,7 +1061,7 @@ class Python3Parser(PythonParser):
args_pos, args_kw, annotate_args = token.attr
# FIXME: Fold test into add_make_function_rule
if self.version < 3.3:
if self.version < (3, 3):
j = 1
else:
j = 2
@@ -1123,7 +1123,7 @@ class Python3Parser(PythonParser):
kwargs_str = ""
# Note order of kwargs and pos args changed between 3.3-3.4
if self.version <= 3.2:
if self.version <= (3, 2):
if annotate_args > 0:
rule = (
"mkfunc_annotate ::= %s%s%sannotate_tuple load_closure LOAD_CODE %s"
@@ -1140,7 +1140,7 @@ class Python3Parser(PythonParser):
"pos_arg " * args_pos,
opname,
)
elif self.version == 3.3:
elif self.version == (3, 3):
if annotate_args > 0:
rule = (
"mkfunc_annotate ::= %s%s%sannotate_tuple load_closure LOAD_CODE LOAD_STR %s"
@@ -1158,7 +1158,7 @@ class Python3Parser(PythonParser):
opname,
)
elif self.version >= 3.4:
elif self.version >= (3, 4):
if PYTHON3 or not self.is_pypy:
load_op = "LOAD_STR"
else:
@@ -1192,7 +1192,7 @@ class Python3Parser(PythonParser):
)
self.add_unique_rule(rule, opname, token.attr, customize)
if self.version < 3.4:
if self.version < (3, 4):
rule = "mkfunc ::= %sload_closure LOAD_CODE %s" % (
"expr " * args_pos,
opname,
@@ -1202,7 +1202,7 @@ class Python3Parser(PythonParser):
pass
elif opname_base.startswith("MAKE_FUNCTION"):
# DRY with MAKE_CLOSURE
if self.version >= 3.6:
if self.version >= (3, 6):
# The semantics of MAKE_FUNCTION in 3.6 are totally different from
# before.
args_pos, args_kw, annotate_args, closure = token.attr
@@ -1264,7 +1264,7 @@ class Python3Parser(PythonParser):
if self.is_pypy or (
i >= 2 and tokens[i - 2] == "LOAD_LISTCOMP"
):
if self.version >= 3.6:
if self.version >= (3, 6):
# 3.6+ sometimes bundles all of the
# 'exprs' in the rule above into a
# tuple.
@@ -1295,12 +1295,12 @@ class Python3Parser(PythonParser):
)
continue
if self.version < 3.6:
if self.version < (3, 6):
args_pos, args_kw, annotate_args = token.attr
else:
args_pos, args_kw, annotate_args, closure = token.attr
if self.version < 3.3:
if self.version < (3, 3):
j = 1
else:
j = 2
@@ -1341,7 +1341,7 @@ class Python3Parser(PythonParser):
else:
kwargs = "kwargs"
if self.version < 3.3:
if self.version < (3, 3):
# positional args after keyword args
rule = "mkfunc ::= %s %s%s%s" % (
kwargs,
@@ -1355,7 +1355,7 @@ class Python3Parser(PythonParser):
"LOAD_CODE ",
opname,
)
elif self.version == 3.3:
elif self.version == (3, 3):
# positional args after keyword args
rule = "mkfunc ::= %s %s%s%s" % (
kwargs,
@@ -1363,7 +1363,7 @@ class Python3Parser(PythonParser):
"LOAD_CODE LOAD_STR ",
opname,
)
elif self.version > 3.5:
elif self.version >= (3, 6):
# positional args before keyword args
rule = "mkfunc ::= %s%s %s%s" % (
"pos_arg " * args_pos,
@@ -1371,7 +1371,7 @@ class Python3Parser(PythonParser):
"LOAD_CODE LOAD_STR ",
opname,
)
elif self.version > 3.3:
elif self.version >= (3, 4):
# positional args before keyword args
rule = "mkfunc ::= %s%s %s%s" % (
"pos_arg " * args_pos,
@@ -1388,7 +1388,7 @@ class Python3Parser(PythonParser):
self.add_unique_rule(rule, opname, token.attr, customize)
if re.search("^MAKE_FUNCTION.*_A", opname):
if self.version >= 3.6:
if self.version >= (3, 6):
rule = (
"mkfunc_annotate ::= %s%sannotate_tuple LOAD_CODE LOAD_STR %s"
% (
@@ -1406,11 +1406,11 @@ class Python3Parser(PythonParser):
opname,
)
)
if self.version >= 3.3:
if self.version >= (3, 3):
# Normally we remove EXTENDED_ARG from the opcodes, but in the case of
# annotated functions can use the EXTENDED_ARG tuple to signal we have an annotated function.
# Yes this is a little hacky
if self.version == 3.3:
if self.version == (3, 3):
# 3.3 puts kwargs before pos_arg
pos_kw_tuple = (
("kwargs " * args_kw),
@@ -1550,7 +1550,7 @@ class Python3Parser(PythonParser):
"try_except": tryexcept,
}
if self.version == 3.6:
if self.version == (3, 6):
self.reduce_check_table["and"] = and_check
self.check_reduce["and"] = "AST"
@@ -1562,7 +1562,7 @@ class Python3Parser(PythonParser):
self.check_reduce["ifelsestmtc"] = "AST"
self.check_reduce["ifstmt"] = "AST"
self.check_reduce["ifstmtl"] = "AST"
if self.version == 3.6:
if self.version == (3, 6):
self.reduce_check_table["iflaststmtl"] = iflaststmt
self.check_reduce["iflaststmt"] = "AST"
self.check_reduce["iflaststmtl"] = "AST"
@@ -1570,7 +1570,7 @@ class Python3Parser(PythonParser):
self.check_reduce["testtrue"] = "tokens"
if not PYTHON3:
self.check_reduce["kwarg"] = "noAST"
if self.version < 3.6 and not self.is_pypy:
if self.version < (3, 6) and not self.is_pypy:
# 3.6+ can remove a JUMP_FORWARD which messes up our testing here
# Pypy we need to go over in better detail
self.check_reduce["try_except"] = "AST"
@@ -1597,11 +1597,11 @@ class Python3Parser(PythonParser):
elif lhs == "kwarg":
arg = tokens[first].attr
return not (isinstance(arg, str) or isinstance(arg, unicode))
elif lhs in ("iflaststmt", "iflaststmtl") and self.version == 3.6:
elif lhs in ("iflaststmt", "iflaststmtl") and self.version[:2] == (3, 6):
return ifstmt(self, lhs, n, rule, ast, tokens, first, last)
elif rule == ("ifstmt", ("testexpr", "_ifstmts_jump")):
# FIXME: go over what's up with 3.0. Evetually I'd like to remove RETURN_END_IF
if self.version <= 3.0 or tokens[last] == "RETURN_END_IF":
if self.version <= (3, 0) or tokens[last] == "RETURN_END_IF":
return False
if ifstmt(self, lhs, n, rule, ast, tokens, first, last):
return True
@@ -1643,7 +1643,7 @@ class Python3Parser(PythonParser):
if while1stmt(self, lhs, n, rule, ast, tokens, first, last):
return True
if self.version == 3.0:
if self.version == (3, 0):
return False
if 0 <= last < len(tokens) and tokens[last] in (
@@ -1685,7 +1685,7 @@ class Python3Parser(PythonParser):
if last == n:
return False
# 3.8+ Doesn't have SETUP_LOOP
return self.version < 3.8 and tokens[first].attr > tokens[last].offset
return self.version < (3, 8) and tokens[first].attr > tokens[last].offset
elif rule == (
"ifelsestmt",
(

View File

@@ -17,15 +17,15 @@ class Python31Parser(Python32Parser):
with ::= expr setupwith SETUP_FINALLY
suite_stmts_opt
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
load del_stmt WITH_CLEANUP END_FINALLY
load delete WITH_CLEANUP END_FINALLY
# Keeps Python 3.1 withas desigator in the same position as it is in other version
setupwithas31 ::= setupwithas SETUP_FINALLY load del_stmt
setupwithas31 ::= setupwithas SETUP_FINALLY load delete
withasstmt ::= expr setupwithas31 store
suite_stmts_opt
POP_BLOCK LOAD_CONST COME_FROM_FINALLY
load del_stmt WITH_CLEANUP END_FINALLY
load delete WITH_CLEANUP END_FINALLY
store ::= STORE_NAME
load ::= LOAD_FAST

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016-2017, 2019 Rocky Bernstein
# Copyright (c) 2016-2017, 2019, 2021 Rocky Bernstein
"""
spark grammar differences over Python 3.4 for Python 3.5.
"""
@@ -156,7 +156,7 @@ class Python35Parser(Python34Parser):
# FIXME: I suspect this is wrong for 3.6 and 3.5, but
# I haven't verified what the 3.7ish fix is
elif opname == 'BUILD_MAP_UNPACK_WITH_CALL':
if self.version < 3.7:
if self.version < (3, 7):
self.addRule("expr ::= unmapexpr", nop_func)
nargs = token.attr % 256
map_unpack_n = "map_unpack_%s" % nargs
@@ -167,10 +167,9 @@ class Python35Parser(Python34Parser):
call_token = tokens[i+1]
rule = 'call ::= expr unmapexpr ' + call_token.kind
self.addRule(rule, nop_func)
elif opname == 'BEFORE_ASYNC_WITH' and self.version < 3.8:
elif opname == 'BEFORE_ASYNC_WITH' and self.version < (3, 8):
# Some Python 3.5+ async additions
rules_str = """
async_with_stmt ::= expr
stmt ::= async_with_stmt
async_with_pre ::= BEFORE_ASYNC_WITH GET_AWAITABLE LOAD_CONST YIELD_FROM SETUP_ASYNC_WITH
async_with_post ::= COME_FROM_ASYNC_WITH

View File

@@ -395,7 +395,7 @@ class Python36Parser(Python35Parser):
starred ::= expr
call_ex ::= expr starred CALL_FUNCTION_EX
""", nop_func)
if self.version >= 3.6:
if self.version >= (3, 6):
if 'BUILD_MAP_UNPACK_WITH_CALL' in self.seen_ops:
self.addRule("""
expr ::= call_ex_kw

View File

@@ -112,10 +112,10 @@ class Python37Parser(Python37BaseParser):
stmt ::= tryelsestmt
stmt ::= tryfinallystmt
stmt ::= del_stmt
del_stmt ::= DELETE_FAST
del_stmt ::= DELETE_NAME
del_stmt ::= DELETE_GLOBAL
stmt ::= delete
delete ::= DELETE_FAST
delete ::= DELETE_NAME
delete ::= DELETE_GLOBAL
stmt ::= return
return ::= ret_expr RETURN_VALUE
@@ -888,7 +888,7 @@ class Python37Parser(Python37BaseParser):
END_FINALLY _jump
except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM_FINALLY
LOAD_CONST store del_stmt
LOAD_CONST store delete
except_suite ::= returns
@@ -1291,7 +1291,7 @@ class Python37Parser(Python37BaseParser):
withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
"""
if self.version < 3.8:
if self.version < (3, 8):
rules_str += """
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
LOAD_CONST

View File

@@ -209,7 +209,7 @@ class Python37BaseParser(PythonParser):
stmt ::= async_with_as_stmt
"""
if self.version < 3.8:
if self.version < (3, 8):
rules_str += """
stmt ::= async_with_stmt SETUP_ASYNC_WITH
c_stmt ::= c_async_with_stmt SETUP_ASYNC_WITH
@@ -541,7 +541,7 @@ class Python37BaseParser(PythonParser):
self.addRule("continue ::= CONTINUE_LOOP", nop_func)
custom_ops_processed.add(opname)
elif opname == "DELETE_ATTR":
self.addRule("del_stmt ::= expr DELETE_ATTR", nop_func)
self.addRule("delete ::= expr DELETE_ATTR", nop_func)
custom_ops_processed.add(opname)
elif opname == "DELETE_DEREF":
self.addRule(
@@ -555,7 +555,7 @@ class Python37BaseParser(PythonParser):
elif opname == "DELETE_SUBSCR":
self.addRule(
"""
del_stmt ::= delete_subscript
delete ::= delete_subscript
delete_subscript ::= expr expr DELETE_SUBSCR
""",
nop_func,
@@ -1034,7 +1034,7 @@ class Python37BaseParser(PythonParser):
POP_BLOCK LOAD_CONST COME_FROM_WITH
with_suffix
"""
if self.version < 3.8:
if self.version < (3, 8):
rules_str += """
with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
LOAD_CONST

View File

@@ -44,6 +44,7 @@ class Python38Parser(Python37Parser):
stmt ::= try_elsestmtl38
stmt ::= try_except_ret38
stmt ::= try_except38
stmt ::= try_except_as
stmt ::= whilestmt38
stmt ::= whileTruestmt38
stmt ::= call_stmt
@@ -110,6 +111,8 @@ class Python38Parser(Python37Parser):
for38 ::= expr get_for_iter store for_block
forelsestmt38 ::= expr get_for_iter store for_block POP_BLOCK else_suite
forelsestmt38 ::= expr get_for_iter store for_block JUMP_BACK _come_froms else_suite
forelselaststmt38 ::= expr get_for_iter store for_block POP_BLOCK else_suitec
forelselaststmtl38 ::= expr get_for_iter store for_block POP_BLOCK else_suitel
@@ -132,6 +135,8 @@ class Python38Parser(Python37Parser):
except_cond1 ::= DUP_TOP expr COMPARE_OP jmp_false
POP_TOP POP_TOP POP_TOP
POP_EXCEPT
except_cond_as ::= DUP_TOP expr COMPARE_OP POP_JUMP_IF_FALSE
POP_TOP STORE_FAST POP_TOP
try_elsestmtl38 ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
except_handler38 COME_FROM
@@ -144,6 +149,10 @@ class Python38Parser(Python37Parser):
# suite_stmts has a return
try_except38 ::= SETUP_FINALLY POP_BLOCK suite_stmts
except_handler38b
try_except_as ::= SETUP_FINALLY POP_BLOCK suite_stmts
except_handler_as END_FINALLY COME_FROM
try_except_as ::= SETUP_FINALLY suite_stmts
except_handler_as END_FINALLY COME_FROM
try_except_ret38 ::= SETUP_FINALLY returns except_ret38a
try_except_ret38a ::= SETUP_FINALLY returns except_handler38c
@@ -164,6 +173,11 @@ class Python38Parser(Python37Parser):
except_handler38a ::= COME_FROM_FINALLY POP_TOP POP_TOP POP_TOP
POP_EXCEPT POP_TOP stmts END_FINALLY
except_handler38c ::= COME_FROM_FINALLY except_cond1a except_stmts
POP_EXCEPT JUMP_FORWARD COME_FROM
except_handler_as ::= COME_FROM_FINALLY except_cond_as tryfinallystmt
POP_EXCEPT JUMP_FORWARD COME_FROM
tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK
BEGIN_FINALLY COME_FROM_FINALLY suite_stmts_opt
END_FINALLY

View File

@@ -1,4 +1,6 @@
from uncompyle6.parsers.reducecheck.and_check import *
from uncompyle6.parsers.reducecheck.aug_assign import *
from uncompyle6.parsers.reducecheck.except_handler import *
from uncompyle6.parsers.reducecheck.except_handler_else import *
from uncompyle6.parsers.reducecheck.ifelsestmt import *
from uncompyle6.parsers.reducecheck.iflaststmt import *

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2020 Rocky Bernstein
def aug_assign1_check(self, lhs, n, rule, ast, tokens, first, last):
# print("XXX", first, last, rule)
# for t in range(first, last): print(tokens[t])
# print("="*40)
expr = ast[0]
return expr == "expr" and expr[0] == "or"
return False

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2020 Rocky Bernstein
def except_handler(self, lhs, n, rule, ast, tokens, first, last):
end_token = tokens[last-1]
# print("XXX", first, last)
# for t in range(first, last):
# print(tokens[t])
# print("=" * 30)
# FIXME: Figure out why this doesn't work on
# bytecode-1.4/anydbm.pyc
if self.version[:2] == (1, 4):
return False
# Make sure come froms all come from within "except_handler".
if end_token != "COME_FROM":
return False
return end_token.attr < tokens[first].offset

View File

@@ -1,8 +1,8 @@
# Copyright (c) 2020 Rocky Bernstein
# Copyright (c) 2020-2021 Rocky Bernstein
def except_handler_else(self, lhs, n, rule, ast, tokens, first, last):
# FIXME: expand this to other versions
if self.version not in (2.7, 3.5):
if self.version[:2] not in ((2, 7), (3, 5)):
return False
if tokens[first] in ("JUMP_FORWARD", "JUMP_ABSOLUTE"):

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2020 Rocky Bernstein
# Copyright (c) 2020-2021 Rocky Bernstein
from uncompyle6.scanners.tok import Token
@@ -105,6 +105,24 @@ IFELSE_STMT_RULES = frozenset(
"opt_come_from_except",
),
),
(
"ifelsestmt",
(
"testexpr",
"stmts",
"jf_cfs",
"\\e_else_suite_opt",
"\\e_opt_come_from_except")
),
(
"ifelsestmt",
(
"testexpr",
"stmts",
"jf_cfs",
"\\e_else_suite_opt",
"opt_come_from_except")
),
])
def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
@@ -113,6 +131,11 @@ def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
# ifelsestmt jumped outside of loop. No good.
return True
# print("XXX", first, last)
# for t in range(first, last):
# print(tokens[t])
# print("=" * 30)
if rule not in IFELSE_STMT_RULES:
# print("XXX", rule)
return False
@@ -135,7 +158,7 @@ def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
# just the last one.
if len(ast) == 5:
end_come_froms = ast[-1]
if end_come_froms.kind != "else_suite" and self.version >= 3.0:
if end_come_froms.kind != "else_suite" and self.version >= (3, 0):
if end_come_froms == "opt_come_from_except" and len(end_come_froms) > 0:
end_come_froms = end_come_froms[0]
if not isinstance(end_come_froms, Token):
@@ -146,12 +169,12 @@ def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
# FIXME: There is weirdness in the grammar we need to work around.
# we need to clean up the grammar.
if self.version < 3.0:
if self.version < (3, 0):
last_token = ast[-1]
else:
last_token = tokens[last]
if last_token == "COME_FROM" and tokens[first].offset > last_token.attr:
if self.version < 3.0 and self.insts[self.offset2inst_index[last_token.attr]].opname != "SETUP_LOOP":
if self.version < (3, 0) and self.insts[self.offset2inst_index[last_token.attr]].opname != "SETUP_LOOP":
return True
testexpr = ast[0]
@@ -168,7 +191,7 @@ def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
if last == n:
last -= 1
jmp = if_condition[1]
if self.version > 2.6:
if self.version >= (2, 7):
jmp_target = jmp[0].attr
else:
jmp_target = int(jmp[0].pattr)
@@ -186,9 +209,7 @@ def ifelsestmt(self, lhs, n, rule, ast, tokens, first, last):
if jump_else_end == "jf_cf_pop":
jump_else_end = jump_else_end[0]
jump_to_jump = False
if jump_else_end == "JUMP_FORWARD":
jump_to_jump = True
endif_target = int(jump_else_end.pattr)
last_offset = tokens[last].off2int()
if endif_target != last_offset:

View File

@@ -44,7 +44,7 @@ def or_check(self, lhs, n, rule, ast, tokens, first, last):
return True
# If the jmp is backwards
if last_token == "POP_JUMP_IF_FALSE" and not self.version in (2.7, 3.5, 3.6):
if last_token == "POP_JUMP_IF_FALSE" and not self.version[:2] in ((2, 7), (3, 5), (3, 6)):
if last_token.attr < last_token_offset:
# For a backwards loop, well compare to the instruction *after*
# then POP_JUMP...

View File

@@ -1,9 +1,9 @@
# Copyright (c) 2020 Rocky Bernstein
# Copyright (c) 2020-2021 Rocky Bernstein
def testtrue(self, lhs, n, rule, ast, tokens, first, last):
# FIXME: make this work for all versions
if self.version != 3.7:
if self.version[:2] != (3, 7):
return False
if rule == ("testtrue", ("expr", "jmp_true")):
pjit = tokens[min(last - 1, n - 2)]

View File

@@ -6,7 +6,13 @@ def tryelsestmt(self, lhs, n, rule, ast, tokens, first, last):
# Check the end of the except handler that there isn't a jump from
# inside the except handler to the end. If that happens
# then this is a "try" with no "else".
# for t in range(first, last):
# print(tokens[t])
# print("=" * 30)
except_handler = ast[3]
if except_handler == "except_handler_else":
except_handler = except_handler[0]
if except_handler == "except_handler":
@@ -32,5 +38,8 @@ def tryelsestmt(self, lhs, n, rule, ast, tokens, first, last):
except_handler_first_offset = leading_jump.first_child().off2int()
else:
except_handler_first_offset = leading_jump.off2int()
if first_come_from.attr < tokens[first].offset:
return True
return first_come_from.attr > except_handler_first_offset
return False

View File

@@ -20,4 +20,4 @@ def while1elsestmt(self, lhs, n, rule, ast, tokens, first, last):
# not while1else. Also do for whileTrue?
last += 1
# 3.8+ Doesn't have SETUP_LOOP
return self.version < 3.8 and tokens[first].attr > tokens[last].off2int()
return self.version < (3, 8) and tokens[first].attr > tokens[last].off2int()

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016, 2018-2020 by Rocky Bernstein
# Copyright (c) 2016, 2018-2021 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
@@ -24,47 +24,56 @@ scanners, e.g. for Python 2.7 or 3.4.
from array import array
import sys
from uncompyle6 import PYTHON3, IS_PYPY, PYTHON_VERSION
from uncompyle6.scanners.tok import Token
from xdis.version_info import IS_PYPY, PYTHON_VERSION_TRIPLE, PYTHON3, version_tuple_to_str
import xdis
from xdis import Bytecode, canonic_python_version, code2num, instruction_size, extended_arg_val, next_offset
from xdis import (
Bytecode,
canonic_python_version,
code2num,
instruction_size,
extended_arg_val,
next_offset,
)
if PYTHON_VERSION < 2.6:
if PYTHON_VERSION_TRIPLE < (2, 6):
from xdis.namedtuple24 import namedtuple
else:
from collections import namedtuple
# The byte code versions we support.
# Note: these all have to be floats
# Note: these all have to be tuples of 2 ints
PYTHON_VERSIONS = frozenset(
(
1.0,
1.1,
1.3,
1.4,
1.5,
1.6,
2.1,
2.2,
2.3,
2.4,
2.5,
2.6,
2.7,
3.0,
3.1,
3.2,
3.3,
3.4,
3.5,
3.6,
3.7,
3.8,
3.9,
(1, 0),
(1, 1),
(1, 3),
(1, 4),
(1, 5),
(1, 6),
(2, 1),
(2, 2),
(2, 3),
(2, 4),
(2, 5),
(2, 6),
(2, 7),
(3, 0),
(3, 1),
(3, 2),
(3, 3),
(3, 4),
(3, 5),
(3, 6),
(3, 7),
(3, 8),
)
)
CANONIC2VERSION = dict((canonic_python_version[str(v)], v) for v in PYTHON_VERSIONS)
CANONIC2VERSION = dict(
(canonic_python_version[version_tuple_to_str(python_version)], python_version)
for python_version in PYTHON_VERSIONS
)
# Magic changed mid version for Python 3.5.2. Compatibility was added for
# the older 3.5 interpreter magic.
@@ -76,8 +85,8 @@ if PYTHON3:
intern = sys.intern
L65536 = 65536
def long(l):
return l
def long(num):
return num
else:
@@ -105,15 +114,19 @@ class Scanner(object):
self.show_asm = show_asm
self.is_pypy = is_pypy
if version in PYTHON_VERSIONS:
if version[:2] in PYTHON_VERSIONS:
v_str = "opcode_%s" % version_tuple_to_str(
version, start=0, end=2, delimiter=""
)
if is_pypy:
v_str = "opcode_%spypy" % (int(version * 10))
else:
v_str = "opcode_%s" % (int(version * 10))
v_str += "pypy"
exec("from xdis.opcodes import %s" % v_str)
exec("self.opc = %s" % v_str)
else:
raise TypeError("%s is not a Python version I know about" % version)
raise TypeError(
"%s is not a Python version I know about"
% version_tuple_to_str(version)
)
self.opname = self.opc.opname
@@ -146,7 +159,7 @@ class Scanner(object):
# Offset: lineno pairs, only for offsets which start line.
# Locally we use list for more convenient iteration using indices
if self.version > 1.4:
if self.version > (1, 4):
linestarts = list(self.opc.findlinestarts(code_obj))
else:
linestarts = [[0, 1]]
@@ -535,8 +548,8 @@ def get_scanner(version, is_pypy=False, show_asm=None):
version = CANONIC2VERSION[canonic_version]
# Pick up appropriate scanner
if version in PYTHON_VERSIONS:
v_str = "%s" % (int(version * 10))
if version[:2] in PYTHON_VERSIONS:
v_str = version_tuple_to_str(version, start=0, end=2, delimiter="")
try:
import importlib
@@ -568,7 +581,10 @@ def get_scanner(version, is_pypy=False, show_asm=None):
"scan.Scanner%s(show_asm=show_asm)" % v_str, locals(), globals()
)
else:
raise RuntimeError("Unsupported Python version %s" % version)
raise RuntimeError(
"Unsupported Python version, %s, for decompilation"
% version_tuple_to_str(version)
)
return scanner
@@ -578,5 +594,5 @@ if __name__ == "__main__":
co = inspect.currentframe().f_code
# scanner = get_scanner('2.7.13', True)
# scanner = get_scanner(sys.version[:5], False)
scanner = get_scanner(uncompyle6.PYTHON_VERSION, IS_PYPY, True)
scanner = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY, True)
tokens, customize = scanner.ingest(co, {}, show_asm="after")

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2016-2017 by Rocky Bernstein
# Copyright (c) 2016-2017, 2021 by Rocky Bernstein
"""
Python PyPy 2.7 bytecode scanner/deparser
@@ -22,5 +22,5 @@ class ScannerPyPy27(scan.Scanner27):
# There are no differences in initialization between
# pypy 2.7 and 2.7
scan.Scanner27.__init__(self, show_asm, is_pypy=True)
self.version = 2.7
self.version = (2, 7)
return

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2017 by Rocky Bernstein
# Copyright (c) 2017, 2021 by Rocky Bernstein
"""
Python PyPy 3.2 decompiler scanner.
@@ -18,6 +18,6 @@ class ScannerPyPy32(scan.Scanner32):
# There are no differences in initialization between
# pypy 3.2 and 3.2
scan.Scanner32.__init__(self, show_asm, is_pypy=True)
self.version = 3.2
self.version = (3, 2)
self.opc = opc
return

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2019-2020 by Rocky Bernstein
# Copyright (c) 2019-2021 by Rocky Bernstein
"""
Python PyPy 3.3 decompiler scanner.
@@ -19,6 +19,6 @@ class ScannerPyPy33(scan.Scanner33):
# There are no differences in initialization between
# pypy 3.3 and 3.3
scan.Scanner33.__init__(self, show_asm, is_pypy=True)
self.version = 3.3
self.version = (3, 3)
self.opc = opc
return

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2017, 2019 by Rocky Bernstein
# Copyright (c) 2017, 2019, 2021 by Rocky Bernstein
"""
Python PyPy 3.5 decompiler scanner.
@@ -18,5 +18,5 @@ class ScannerPyPy35(scan.Scanner35):
# There are no differences in initialization between
# pypy 3.5 and 3.5
scan.Scanner35.__init__(self, show_asm, is_pypy=True)
self.version = 3.5
self.version = (3, 5)
return

View File

@@ -18,5 +18,5 @@ class ScannerPyPy36(scan.Scanner36):
# There are no differences in initialization between
# pypy 3.6 and 3.6
scan.Scanner36.__init__(self, show_asm, is_pypy=True)
self.version = 3.6
self.version = (3, 6)
return

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2019 by Rocky Bernstein
# Copyright (c) 2019, 2021 by Rocky Bernstein
"""
Python 1.0 bytecode decompiler massaging.
@@ -22,7 +22,7 @@ class Scanner10(scan.Scanner11):
scan.Scanner11.__init__(self, show_asm)
self.opc = opcode_10
self.opname = opcode_10.opname
self.version = 1.0
self.version = (1, 0)
return
# def ingest(self, co, classname=None, code_objects={}, show_asm=None):

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